** Programmer: Kevin Rosenberg
**
** This is part of the CTSim program
-** Copyright (C) 1983-2000 Kevin Rosenberg
+** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: sgp.cpp,v 1.7 2000/07/29 19:50:08 kevin Exp $
+** $Id: sgp.cpp,v 1.32 2001/03/11 18:52:03 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
int SGP::s_iRGBColorCount = sizeof(s_aRGBColor) / sizeof(class RGBColor);
#ifdef HAVE_WXWINDOWS
-SGPDriver::SGPDriver (wxDC* pDC, const char* szWinTitle = "", int xsize = 640, int ysize = 480)
- : m_iPhysicalXSize(xsize), m_iPhysicalYSize(ysize), m_sWindowTitle(szWinTitle), m_idDriver(0)
+SGPDriver::SGPDriver (wxDC* pDC, int xsize, int ysize)
+ : m_iPhysicalXSize(xsize), m_iPhysicalYSize(ysize), m_idDriver(0), m_pDC(pDC)
{
- m_pDC = pDC;
m_idDriver |= SGPDRIVER_WXWINDOWS;
}
#endif
-SGPDriver::SGPDriver (const char* szWinTitle = "", int xsize = 640, int ysize = 480)
+SGPDriver::SGPDriver (const char* szWinTitle, int xsize, int ysize)
: m_iPhysicalXSize(xsize), m_iPhysicalYSize(ysize), m_sWindowTitle(szWinTitle), m_idDriver(0)
{
#ifdef HAVE_G2_H
SGPDriver::~SGPDriver ()
{
+#if HAVE_G2_H
if (isG2())
g2_close (m_idG2);
+#endif
}
// SGP::SGP Constructor for Simple Graphics Package
SGP::SGP (const SGPDriver& driver)
- : m_driver (driver)
+ : m_driver (driver)
{
m_iPhysicalXSize = m_driver.getPhysicalXSize();
m_iPhysicalYSize = m_driver.getPhysicalYSize();
ndc_to_mc.setIdentity();
m_ctm.setIdentity();
+#ifdef HAVE_WXWINDOWS
+ initFromDC (driver.idWX());
+#endif
+
setWindow (0., 0., 1., 1.);
setViewport (0., 0., 1., 1.);
moveAbs (0., 0.);
stylusNDC (0., 0., false);
-
+
setTextAngle (0.);
- setTextSize (1. / 25.);
+ setTextPointSize (12);
setColor (C_BLACK);
+ setLineStyle (LS_SOLID);
+ setMarker (MARKER_POINT);
}
+#ifdef HAVE_WXWINDOWS
+void
+SGP::initFromDC (wxDC* pDC)
+{
+ m_pen.SetWidth (1);
+
+ if (m_driver.isWX()) {
+ static const double dScreenDPI = 82;
+ static const double dPointsPerInch = 72.;
+ m_dPointsPerPixel = dPointsPerInch / dScreenDPI;
+ const int iTestPointSize = 12;
+ m_pFont = new wxFont (wxROMAN, wxNORMAL, wxNORMAL, wxNORMAL);
+ m_pFont->SetPointSize (iTestPointSize);
+ m_pFont->SetWeight (wxNORMAL);
+ m_pFont->SetStyle (wxNORMAL);
+ m_pFont->SetFamily (wxROMAN);
+#ifdef MSVC
+ m_pFont->SetFaceName(wxString("times new roman"));
+#endif
+ m_driver.idWX()->SetFont (*m_pFont);
+ double dTestCharHeight = m_driver.idWX()->GetCharHeight();
+ m_dPointsPerPixel = iTestPointSize / dTestCharHeight;
+ m_driver.idWX()->SetBackground (*wxWHITE_BRUSH);
+ }
+}
+#endif
+
+
+SGP::~SGP()
+{
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ // m_driver.idWX()->SetFont (wxNullFont);
+ delete m_pFont;
+ }
+#endif
+}
+
void
SGP::stylusNDC (double x, double y, bool beam)
{
if (beam) {
#if HAVE_WXWINDOWS
- if (m_driver.isWX())
- m_driver.idWX()->DrawLine (m_iCurrentPhysicalX, m_iCurrentPhysicalY, xp, yp);
+ if (m_driver.isWX())
+ m_driver.idWX()->DrawLine (m_iCurrentPhysicalX, m_iCurrentPhysicalY, xp, yp);
#endif
#if HAVE_G2_H
- if (m_driver.isG2())
- g2_line (m_driver.idG2(), m_iCurrentPhysicalX, m_iCurrentPhysicalY, xp, yp);
+ if (m_driver.isG2())
+ g2_line (m_driver.idG2(), m_iCurrentPhysicalX, m_iCurrentPhysicalY, xp, yp);
#endif
}
m_iCurrentPhysicalX = xp;
void
SGP::markerNDC (double x, double y)
{
+ int xp = static_cast<int>(x * (m_iPhysicalXSize - 1) + 0.5);
+ int yp = static_cast<int>(y * (m_iPhysicalYSize - 1) + 0.5);
+ if (m_driver.isWX())
+ yp = m_iPhysicalYSize - yp;
+
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ m_driver.idWX()->DrawPoint (xp, yp);
+ m_driver.idWX()->DrawPoint (xp-1, yp-1);
+ m_driver.idWX()->DrawPoint (xp+1, yp+1);
+ m_driver.idWX()->DrawPoint (xp+1, yp-1);
+ m_driver.idWX()->DrawPoint (xp-1, yp+1);
+ }
+#endif
+ m_iCurrentPhysicalX = xp;
+ m_iCurrentPhysicalY = yp;
}
void
SGP::pointNDC (double x, double y)
{
+ int xp = static_cast<int>(x * (m_iPhysicalXSize - 1) + 0.5);
+ int yp = static_cast<int>(y * (m_iPhysicalYSize - 1) + 0.5);
+ if (m_driver.isWX())
+ yp = m_iPhysicalYSize - yp;
+
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX())
+ m_driver.idWX()->DrawPoint (xp, yp);
+#endif
+ m_iCurrentPhysicalX = xp;
+ m_iCurrentPhysicalY = yp;
}
g2_clear (m_driver.idG2());
#endif
#if HAVE_WXWINDOWS
- if (m_driver.isWX())
- m_driver.idWX()->Clear();
+ if (m_driver.isWX()) {
+ wxBrush brushWhite;
+ brushWhite.SetColour(255,255,255);
+ m_driver.idWX()->SetBackground(brushWhite);
+ m_driver.idWX()->Clear();
+ m_driver.idWX()->SetBackground(wxNullBrush);
+#if 1
+ wxPen pen;
+ pen.SetColour(255,255,255);
+ m_driver.idWX()->SetBrush (brushWhite);
+ m_driver.idWX()->DrawRectangle (0, 0, m_iPhysicalXSize, m_iPhysicalYSize);
+ m_driver.idWX()->SetBrush (wxNullBrush);
+#endif
+ }
#endif
}
viewNDC[3] = ymax;
}
+void
+SGP::getViewport (double& xmin, double& ymin, double& xmax, double& ymax)
+{
+ xmin = xv_min;
+ ymin = yv_min;
+ xmax = xv_max;
+ ymax = yv_max;
+}
+
+void
+SGP::getWindow (double& xmin, double& ymin, double& xmax, double& ymax)
+{
+ xmin = xw_min;
+ ymin = yw_min;
+ xmax = xw_max;
+ ymax = yw_max;
+}
+
// NAME
// frameViewport draw box around viewport
void
SGP::frameViewport (void)
{
- stylusNDC (xv_min, yv_min, 0);
- stylusNDC (xv_max, yv_min, 1);
- stylusNDC (xv_max, yv_max, 1);
- stylusNDC (xv_min, yv_max, 1);
- stylusNDC (xv_min, yv_min, 1);
+ stylusNDC (xv_min, yv_min, false);
+ stylusNDC (xv_max, yv_min, true);
+ stylusNDC (xv_max, yv_max, true);
+ stylusNDC (xv_min, yv_max, true);
+ stylusNDC (xv_min, yv_min, true);
}
void
SGP::setTextColor (int iFGcolor, int iBGcolor)
{
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ if (iFGcolor >= 0) {
+ wxColor colour (s_aRGBColor[iFGcolor].getRed(), s_aRGBColor[iFGcolor].getGreen(), s_aRGBColor[iFGcolor].getBlue());
+ m_driver.idWX()->SetTextForeground (colour);
+ }
+ if (iBGcolor >= 0) {
+ wxColor colour (s_aRGBColor[iBGcolor].getRed(), s_aRGBColor[iBGcolor].getGreen(), s_aRGBColor[iBGcolor].getBlue());
+ m_driver.idWX()->SetTextBackground (colour);
+ }
+ }
+#endif
}
void
#if HAVE_WXWINDOWS
if (m_driver.isWX()) {
wxColor colour (s_aRGBColor[icol].getRed(), s_aRGBColor[icol].getGreen(), s_aRGBColor[icol].getBlue());
- wxPen pen (colour, 1, wxSOLID);
- m_driver.idWX()->SetPen (pen);
+ m_pen.SetColour (colour);
+ m_driver.idWX()->SetPen (m_pen);
+ }
+#endif
+ }
+}
+
+void
+SGP::setPenWidth (int iWidth)
+{
+ if (iWidth >= 0) {
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ m_pen.SetWidth (iWidth);
+ m_driver.idWX()->SetPen (m_pen);
}
#endif
}
}
void
-SGP::setMarker (int idMarke, int iColor)
+SGP::setRasterOp (int ro)
{
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ int wxFxn = -1;
+ switch (ro) {
+ case RO_AND:
+ wxFxn = wxAND;
+ break;
+ case RO_AND_INVERT:
+ wxFxn = wxAND_INVERT;
+ break;
+ case RO_AND_REVERSE:
+ wxFxn = wxAND_REVERSE;
+ break;
+ case RO_CLEAR:
+ wxFxn = wxCLEAR;
+ break;
+ case RO_COPY:
+ wxFxn = wxCOPY;
+ break;
+ case RO_EQUIV:
+ wxFxn = wxEQUIV;
+ break;
+ case RO_INVERT:
+ wxFxn = wxINVERT;
+ break;
+ case RO_NAND:
+ wxFxn = wxNAND;
+ break;
+ case RO_NOR:
+ wxFxn = wxNOR;
+ break;
+ case RO_NO_OP:
+ wxFxn = wxNO_OP;
+ break;
+ case RO_OR:
+ wxFxn = wxOR;
+ break;
+ case RO_OR_INVERT:
+ wxFxn = wxOR_INVERT;
+ break;
+ case RO_OR_REVERSE:
+ wxFxn = wxOR_REVERSE;
+ break;
+ case RO_SET:
+ wxFxn = wxSET;
+ break;
+ case RO_SRC_INVERT:
+ wxFxn = wxSRC_INVERT;
+ break;
+ case RO_XOR:
+ wxFxn = wxXOR;
+ break;
+ }
+ if (wxFxn >= 0)
+ m_driver.idWX()->SetLogicalFunction (wxFxn);
+ }
+#endif
+}
+
+
+void
+SGP::setMarker (int idMarker)
+{
+ m_iMarker = idMarker;
}
//==============================================================
void
SGP::setLineStyle (int style)
{
+ m_iLinestyle = style;
+
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ switch (m_iLinestyle) {
+ case LS_SOLID:
+ m_pen.SetStyle (wxSOLID);
+ break;
+ case LS_DASH1:
+ m_pen.SetStyle (wxLONG_DASH);
+ break;
+ case LS_DASH2:
+ m_pen.SetStyle (wxSHORT_DASH);
+ break;
+ case LS_DASH3:
+ m_pen.SetStyle (wxDOT_DASH);
+ break;
+ case LS_DASH4:
+ m_pen.SetStyle (wxCROSS_HATCH);
+ break;
+ case LS_DOTTED:
+ m_pen.SetStyle (wxDOT);
+ break;
+ default:
+ m_pen.SetStyle (wxSOLID);
+ break;
+ }
+ m_driver.idWX()->SetPen (m_pen);
+ }
+#endif
}
//==============================================================
double x2 = x;
double y2 = y;
- mc_to_ndc.transformPoint (&x1, &y2);
+ mc_to_ndc.transformPoint (&x2, &y2);
if (clip_rect (x1, y1, x2, y2, viewNDC) == true) { // clip to viewport
- stylusNDC (x1, y1, 0); // move to first point
- stylusNDC (x2, y2, 1); // draw to second point
+ stylusNDC (x1, y1, false); // move to first point
+ stylusNDC (x2, y2, true); // draw to second point
}
m_dCurrentWorldX = x;
moveAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY);
}
+
+// Height is in master coordinates
void
SGP::setTextSize (double height)
{
+ height /= (yw_max - yw_min); // convert to NDC
+#if HAVE_G2_H
if (m_driver.isG2())
g2_set_font_size(m_driver.idG2(), (height * m_iPhysicalYSize));
+#endif
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ double dHeightPixels = height * m_iPhysicalYSize;
+ double dHeightPoints = dHeightPixels * m_dPointsPerPixel;
+ m_pFont->SetPointSize (nearest<int>(dHeightPoints));
+ m_driver.idWX()->SetFont (*m_pFont);
+ }
+#endif
+}
+
+void
+SGP::setTextNDCSize (double height)
+{
+ double dHeightPixels = height * m_iPhysicalYSize;
+#if HAVE_G2_H
+ if (m_driver.isG2())
+ g2_set_font_size(m_driver.idG2(), nearest<int>(dHeightPixels));
+#endif
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ double dHeightPoints = dHeightPixels * m_dPointsPerPixel;
+ m_pFont->SetPointSize (nearest<int>(dHeightPoints));
+ m_driver.idWX()->SetFont (*m_pFont);
+ }
+#endif
+}
+
+void
+SGP::setTextPointSize (double height)
+{
+#if HAVE_G2_H
+ // if (m_driver.isG2())
+ // g2_set_font_size(m_driver.idG2(), (height * m_iPhysicalYSize));
+#endif
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ m_iTextPointSize = static_cast<int>(height+0.5);
+ m_pFont->SetPointSize (m_iTextPointSize);
+ m_driver.idWX()->SetFont (*m_pFont);
+ }
+#endif
+}
+
+void
+SGP::getTextExtent (const char* szText, double* worldW, double* worldH)
+{
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ wxString sText (szText);
+ wxCoord deviceW, deviceH;
+ m_driver.idWX()->GetTextExtent (sText, &deviceW, &deviceH);
+ if (m_dTextAngle == 90 || m_dTextAngle == -90) {
+ wxCoord temp = deviceW;
+ deviceW = deviceH;
+ deviceH = temp;
+ }
+ *worldW = (xw_max - xw_min) * deviceW / static_cast<double>(m_iPhysicalXSize);;
+ *worldH = (yw_max - yw_min) * deviceH / static_cast<double>(m_iPhysicalYSize);
+ }
+#endif
+}
+
+double
+SGP::getCharHeight ()
+{
+ double dHeight = (1. / 25.);
+
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ dHeight = m_driver.idWX()->GetCharHeight();
+ dHeight /= static_cast<double>(m_iPhysicalYSize);
+ dHeight /= (yv_max - yv_min); // scale to viewport;
+ }
+#endif
+ dHeight *= (yw_max - yw_min); // scale to world coordinates
+ return dHeight;
+}
+
+double
+SGP::getCharWidth ()
+{
+ double dWidth = (1. / 80.);
+
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ dWidth = m_driver.idWX()->GetCharWidth();
+ dWidth /= static_cast<double>(m_iPhysicalXSize);
+ dWidth /= (xv_max - xv_min); // scale to viewport
+ }
+#endif
+ dWidth *= (xw_max - xw_min); //scale to world coordinates
+ return dWidth;
}
void
SGP::setTextAngle (double angle)
{
- m_dTextAngle = angle;
+ m_dTextAngle = convertRadiansToDegrees(angle);
}
void
double yt = y2; // as the beginning point of the next line
if (clip_rect (x1, y1, xt, yt, viewNDC)) {
- stylusNDC (x1, y1, 0);
- stylusNDC (xt, yt, 1);
+ stylusNDC (x1, y1, false);
+ stylusNDC (xt, yt, true);
}
for (int i = 2; i < n; i++) {
xt = x2;
yt = y2;
if (clip_rect (x1, y1, xt, yt, viewNDC)) {
- stylusNDC (x1, y1, 0);
- stylusNDC (xt, yt, 1);
+ stylusNDC (x1, y1, false);
+ stylusNDC (xt, yt, true);
}
}
}
double yndc = y;
mc_to_ndc.transformPoint (&xndc, &yndc);
markerNDC (xndc, yndc);
- stylusNDC (xndc, yndc, false); // move to location
m_dCurrentWorldX = x;
m_dCurrentWorldY = y;
}
double xndc = x, yndc = y;
mc_to_ndc.transformPoint (&xndc, &yndc);
pointNDC (xndc, yndc);
- stylusNDC (xndc, yndc, false); // move to location
m_dCurrentWorldX = x;
m_dCurrentWorldY = y;
}
void
-SGP::drawText (const string& rsMessage)
+SGP::drawText (const std::string& rsMessage)
{
drawText (rsMessage.c_str());
}
void
SGP::drawCircle (const double r)
{
- drawArc (0.0, 7.0, r);
+ drawArc (r, 0.0, TWOPI);
}
-// =============================================================
-// draw arc around current center. pass angles and radius
+//==============================================================
+// draw arc around current center. angles in radius
//==============================================================
void
-SGP::drawArc (double start, double stop, const double r)
-{
- if ((stop-start) > 2 * PI)
- stop = start + 2 * PI;
- if ((start-stop) > 2 * PI)
- stop = start + 2 * PI;
- while (start >= stop)
- stop += 2*PI;
-
- double x = r * cos ((double) start);
- double y = r * sin ((double) start);
- moveRel (x, y); // move from center to start of arc
-
- double theta = 5 * PI / 180;
- double c = cos(theta);
- double s = sin(theta);
-
- double angle, xp, yp;
- for (angle = start; angle < stop - theta; angle += theta) {
- xp = c * x - s * y;
- yp = s * x + c * y;
- lineRel (xp - x, yp - y);
+SGP::drawArc (const double r, double start, double stop)
+{
+ if (start > stop) {
+ double temp = start;
+ start = stop;
+ stop = temp;
+ }
+
+ double xCent = m_dCurrentWorldX;
+ double yCent = m_dCurrentWorldY;
+
+ double x = r * cos (start);
+ double y = r * sin (start);
+ moveAbs (xCent + x, yCent + y); // move from center to start of arc
+
+ const double thetaIncrement = (5 * (TWOPI / 360)); // 5 degree increments
+ double cosTheta = cos (thetaIncrement);
+ double sinTheta = sin (thetaIncrement);
+
+ double angle;
+ for (angle = start; angle < stop; angle += thetaIncrement) {
+ double xp = cosTheta * x - sinTheta * y; // translate point by thetaIncrement
+ double yp = sinTheta * x + cosTheta * y;
+ lineAbs (xCent + xp, yCent + yp);
x = xp; y = yp;
}
- c = cos (stop - angle);
- s = sin (stop - angle);
- xp = c * x - s * y;
- yp = s * x + c * y;
- lineRel (xp - x, yp - y);
+ double c = cos (stop - angle);
+ double s = sin (stop - angle);
+ double xp = c * x - s * y;
+ double yp = s * x + c * y;
+ lineAbs (xCent + xp, yCent + yp);
- x = r * cos ((double) stop);
- y = r * sin ((double) stop);
- moveRel (-x, -y); // move back to center of circle
+ moveAbs (xCent, yCent); // move back to center of circle
}
{'\076', '\042', '\042', '\042', '\076'}, // big open square
{'\010', '\024', '\042', '\024', '\010'}, // big open diamond
};
+
+
+#if HAVE_WXWINDOWS
+void
+SGP::setDC (wxDC* pDC)
+{
+ if (m_driver.isWX()) {
+ m_driver.setDC(pDC);
+ initFromDC (pDC);
+ setTextPointSize (m_iTextPointSize);
+ }
+}
+#endif