X-Git-Url: http://git.kpe.io/?p=ctsim.git;a=blobdiff_plain;f=libctgraphics%2Fsgp.cpp;h=3626555c86f0e67d0fc0aad46a503a8326324fae;hp=4d70f8cfe965f265f99f06d723542bd7d8603883;hb=ee0105d74fec9d6bfd236e22e9e1d315e46c568e;hpb=c85a5b31119b4e0903144c55441717a7ad1e0b8b diff --git a/libctgraphics/sgp.cpp b/libctgraphics/sgp.cpp index 4d70f8c..3626555 100644 --- a/libctgraphics/sgp.cpp +++ b/libctgraphics/sgp.cpp @@ -7,7 +7,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: sgp.cpp,v 1.6 2000/07/28 10:51:31 kevin Exp $ +** $Id: sgp.cpp,v 1.17 2000/12/06 01:46:43 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 @@ -29,17 +29,37 @@ #include "sgp.h" +RGBColor SGP::s_aRGBColor[] = +{ + RGBColor (0, 0, 0), + RGBColor (0, 0, 128), + RGBColor (0, 128, 0), + RGBColor (0, 128, 128), + RGBColor (128, 0, 0), + RGBColor (128, 0, 128), + RGBColor (128, 128, 0), + RGBColor (80, 80, 80), + RGBColor (160, 160, 160), + RGBColor (0, 0, 255), + RGBColor (0, 255, 0), + RGBColor (0, 255, 255), + RGBColor (255, 0, 0), + RGBColor (255, 0, 255), + RGBColor (255, 255, 0), + RGBColor (255, 255, 255), +}; + +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 @@ -50,8 +70,10 @@ SGPDriver::SGPDriver (const char* szWinTitle = "", int xsize = 640, int ysize = SGPDriver::~SGPDriver () { +#if HAVE_G2_H if (isG2()) g2_close (m_idG2); +#endif } @@ -59,7 +81,7 @@ SGPDriver::~SGPDriver () // 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(); @@ -69,14 +91,30 @@ SGP::SGP (const SGPDriver& driver) ndc_to_mc.setIdentity(); m_ctm.setIdentity(); +#if HAVE_WXWINDOWS + m_pen.SetWidth(1); + m_pen.SetStyle(wxSOLID); + + if (m_driver.isWX()) { + static const double dScreenDPI = 82; + static const double dPointsPerInch = 72.; + m_dPointsPerPixel = dPointsPerInch / dScreenDPI; + const int iTestPointSize = 72; + m_font.SetPointSize (iTestPointSize); + m_driver.idWX()->SetFont(m_font); + double dTestCharHeight = m_driver.idWX()->GetCharHeight(); + m_dPointsPerPixel = iTestPointSize / dTestCharHeight; + } +#endif + setWindow (0., 0., 1., 1.); setViewport (0., 0., 1., 1.); moveAbs (0., 0.); - m_iCurrentPhysicalX = 0; - m_iCurrentPhysicalY = 0; - + stylusNDC (0., 0., false); + setTextAngle (0.); - setTextSize (1. / 25.); + setTextPointSize (12); + setColor (C_BLACK); } @@ -89,10 +127,14 @@ SGP::stylusNDC (double x, double y, bool beam) yp = m_iPhysicalYSize - yp; if (beam) { - if (m_driver.isWX()) - m_driver.idWX()->DrawLine (m_iCurrentPhysicalX, m_iCurrentPhysicalY, xp, yp); - if (m_driver.isG2()) - g2_line (m_driver.idG2(), m_iCurrentPhysicalX, m_iCurrentPhysicalY, xp, yp); +#if HAVE_WXWINDOWS + 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); +#endif } m_iCurrentPhysicalX = xp; m_iCurrentPhysicalY = yp; @@ -115,10 +157,14 @@ SGP::pointNDC (double x, double y) void SGP::eraseWindow () { +#if HAVE_G2_H if (m_driver.isG2()) g2_clear (m_driver.idG2()); +#endif +#if HAVE_WXWINDOWS if (m_driver.isWX()) m_driver.idWX()->Clear(); +#endif } // NAME @@ -164,6 +210,24 @@ SGP::setViewport (double xmin, double ymin, double xmax, double ymax) 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 @@ -171,23 +235,126 @@ SGP::setViewport (double xmin, double ymin, double xmax, double ymax) 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 SGP::setColor (int icol) { + if (icol >= 0 && icol < s_iRGBColorCount) { +#if HAVE_G2_H + if (m_driver.isG2()) { + int iInk = g2_ink (m_driver.idG2(), s_aRGBColor[icol].getRed() / 255., s_aRGBColor[icol].getGreen() / 255., s_aRGBColor[icol].getBlue() / 255.); + g2_pen (m_driver.idG2(), iInk); + } +#endif +#if HAVE_WXWINDOWS + if (m_driver.isWX()) { + wxColor colour (s_aRGBColor[icol].getRed(), s_aRGBColor[icol].getGreen(), s_aRGBColor[icol].getBlue()); + 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::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 idMarke, int iColor) { @@ -217,11 +384,11 @@ SGP::lineAbs (double x, double y) 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; @@ -247,17 +414,108 @@ SGP::moveRel (double x, double y) moveAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY); } + +// Height is in master coordinates void SGP::setTextSize (double height) { + height /= (xw_max - xw_min); +#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_font.SetPointSize (nearest(dHeightPoints)); + m_driver.idWX()->SetFont (m_font); + } +#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(dHeightPixels)); +#endif +#if HAVE_WXWINDOWS + if (m_driver.isWX()) { + double dHeightPoints = dHeightPixels * m_dPointsPerPixel; + m_font.SetPointSize (nearest(dHeightPoints)); + m_driver.idWX()->SetFont (m_font); + } +#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_font.SetPointSize (static_cast(height+0.5)); + m_driver.idWX()->SetFont (m_font); + } +#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); + *worldW = static_cast(deviceW) / static_cast(m_iPhysicalXSize);; + *worldH = static_cast(deviceH) / static_cast(m_iPhysicalYSize); + *worldW *= (xw_max - xw_min); + *worldH *= (yw_max - yw_min); + } +#endif +} + +double +SGP::getCharHeight () +{ + double dHeight = (1. / 25.); + +#if HAVE_WXWINDOWS + if (m_driver.isWX()) { + dHeight = m_driver.idWX()->GetCharHeight(); + dHeight /= static_cast(m_iPhysicalYSize); + } +#endif + dHeight *= (yw_max - yw_min); + return dHeight; +} + +double +SGP::getCharWidth () +{ + double dWidth = (1. / 80.); + +#if HAVE_WXWINDOWS + if (m_driver.isWX()) { + dWidth = m_driver.idWX()->GetCharWidth(); + dWidth /= static_cast(m_iPhysicalXSize); + } +#endif + dWidth *= (xw_max - xw_min); + return dWidth; } void SGP::setTextAngle (double angle) { - m_dTextAngle = angle; + m_dTextAngle = convertRadiansToDegrees(angle); } void @@ -275,8 +533,8 @@ SGP::polylineAbs (double x[], double y[], int n) 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++) { @@ -286,8 +544,8 @@ SGP::polylineAbs (double x[], double y[], int n) 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); } } } @@ -355,12 +613,17 @@ SGP::drawText (const char *pszMessage) stylusNDC (xndc, yndc, false); // move to location +#if HAVE_G2_H if (m_driver.isG2()) { - if (m_dTextAngle == 0.) - g2_string (m_driver.idG2(), m_iCurrentPhysicalX, m_iCurrentPhysicalY, const_cast(pszMessage)); + g2_string (m_driver.idG2(), m_iCurrentPhysicalX, m_iCurrentPhysicalY, const_cast(pszMessage)); } +#endif +#if HAVE_WXWINDOWS if (m_driver.isWX()) { + wxString str (pszMessage); + m_driver.idWX()->DrawRotatedText (str, m_iCurrentPhysicalX, m_iCurrentPhysicalY, m_dTextAngle); } +#endif } @@ -392,47 +655,46 @@ SGP::drawRect (double xmin, double ymin, double xmax, double ymax) 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) +SGP::drawArc (const double r, double start, double stop) { - if ((stop-start) > 2 * PI) - stop = start + 2 * PI; - if ((start-stop) > 2 * PI) - stop = start + 2 * PI; - while (start >= stop) - stop += 2*PI; + if (start > stop) { + double temp = start; + start = stop; + stop = temp; + } 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); + const double thetaIncrement = (5 * (TWOPI / 360)); + double cosTheta = cos(thetaIncrement); + double sinTheta = sin(thetaIncrement); 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); + for (angle = start; angle < stop - thetaIncrement; angle += thetaIncrement) { + xp = cosTheta * x - sinTheta * y; // translate point by thetaIncrement + yp = sinTheta * x + cosTheta * y; + lineAbs (xp, yp); x = xp; y = yp; } - c = cos (stop - angle); - s = sin (stop - angle); + double c = cos (stop - angle); + double s = sin (stop - angle); xp = c * x - s * y; yp = s * x + c * y; - lineRel (xp - x, yp - y); + lineAbs (xp, yp); - x = r * cos ((double) stop); - y = r * sin ((double) stop); + x = r * cos (stop); + y = r * sin (stop); moveRel (-x, -y); // move back to center of circle } @@ -609,3 +871,13 @@ const unsigned char SGP::MARKER_BITMAP[MARK_COUNT][5] = {'\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); +} +#endif