/*****************************************************************************
** FILE IDENTIFICATION
**
-** Name: sgp.cpp Simple Graphics Package
-** Programmer: Kevin Rosenberg
+** Name: sgp.cpp Simple Graphics Package
+** Programmer: Kevin Rosenberg
**
** This is part of the CTSim program
-** Copyright (C) 1983-2001 Kevin Rosenberg
-**
-** $Id: sgp.cpp,v 1.28 2001/01/27 21:02:20 kevin Exp $
+** Copyright (c) 1983-2009 Kevin Rosenberg
**
** 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
#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),
+SGP_RGBColor SGP::s_aRGBColor[] =
+{
+ SGP_RGBColor (0, 0, 0),
+ SGP_RGBColor (0, 0, 128),
+ SGP_RGBColor (0, 128, 0),
+ SGP_RGBColor (0, 128, 128),
+ SGP_RGBColor (128, 0, 0),
+ SGP_RGBColor (128, 0, 128),
+ SGP_RGBColor (128, 128, 0),
+ SGP_RGBColor (80, 80, 80),
+ SGP_RGBColor (160, 160, 160),
+ SGP_RGBColor (0, 0, 255),
+ SGP_RGBColor (0, 255, 0),
+ SGP_RGBColor (0, 255, 255),
+ SGP_RGBColor (255, 0, 0),
+ SGP_RGBColor (255, 0, 255),
+ SGP_RGBColor (255, 255, 0),
+ SGP_RGBColor (255, 255, 255),
};
-int SGP::s_iRGBColorCount = sizeof(s_aRGBColor) / sizeof(class RGBColor);
+int SGP::s_iRGBColorCount = sizeof(s_aRGBColor) / sizeof(class SGP_RGBColor);
#ifdef HAVE_WXWINDOWS
SGPDriver::SGPDriver (wxDC* pDC, int xsize, int ysize)
SGPDriver::~SGPDriver ()
{
#if HAVE_G2_H
- if (isG2())
+ if (isG2())
g2_close (m_idG2);
#endif
}
setViewport (0., 0., 1., 1.);
moveAbs (0., 0.);
stylusNDC (0., 0., false);
-
+
setTextAngle (0.);
- setTextPointSize (12);
+ setTextPointSize (8);
setColor (C_BLACK);
setLineStyle (LS_SOLID);
+ setMarker (MARKER_POINT);
}
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);
+ m_pFont = new wxFont (iTestPointSize, wxFONTFAMILY_ROMAN,
+ wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
#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);
+ m_driver.idWX()->SetBackground (*wxWHITE_BRUSH);
}
}
#endif
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;
}
// NAME
// clear Clear Window
-void
+void
SGP::eraseWindow ()
{
#if HAVE_G2_H
#endif
#if HAVE_WXWINDOWS
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);
+ 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);
+ 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
}
// NAME
-// sgp2_window Set window in world coordinates
-
+// sgp2_window Set window in world coordinates
+
void
SGP::setWindow (double xmin, double ymin, double xmax, double ymax)
sys_error (ERR_WARNING, "Minimum > Maximum [sgp2_window]");
return;
}
-
+
xw_min = xmin;
yw_min = ymin;
xw_max = xmax;
// NAME
-// sgp2_viewport Set viewport in NDC
+// sgp2_viewport Set viewport in NDC
void
SGP::setViewport (double xmin, double ymin, double xmax, double ymax)
sys_error (ERR_WARNING, "Minimum > Maximum [sgp2_viewport]");
return;
}
-
+
xv_min = xmin;
yv_min = ymin;
xv_max = xmax;
yv_max = ymax;
m_bRecalcTransform = true;
-
- viewNDC[0] = xmin; // Array for clip_rect()
+
+ viewNDC[0] = xmin; // Array for clip_rect()
viewNDC[1] = ymin;
viewNDC[2] = xmax;
viewNDC[3] = ymax;
// NAME
-// frameViewport draw box around viewport
+// frameViewport draw box around viewport
void
SGP::frameViewport (void)
#endif
}
-void
+void
SGP::setColor (int icol)
{
if (icol >= 0 && icol < s_iRGBColorCount) {
}
}
-void
+void
SGP::setPenWidth (int iWidth)
{
if (iWidth >= 0) {
void
-SGP::setMarker (int idMarke, int iColor)
+SGP::setMarker (int idMarker)
{
+ m_iMarker = idMarker;
}
//==============================================================
-// set line style. Pass 16 bit repeating pattern
+// set line style. Pass 16 bit repeating pattern
//==============================================================
-void
+void
SGP::setLineStyle (int style)
{
m_iLinestyle = style;
}
//==============================================================
-// absolute draw to
+// absolute draw to
//*==============================================================
-void
+void
SGP::lineAbs (double x, double y)
{
if (m_bRecalcTransform)
double x2 = x;
double y2 = y;
mc_to_ndc.transformPoint (&x2, &y2);
-
- if (clip_rect (x1, y1, x2, y2, viewNDC) == true) { // clip to viewport
+
+ if (clip_rect (x1, y1, x2, y2, viewNDC) == true) { // clip to viewport
stylusNDC (x1, y1, false); // move to first point
- stylusNDC (x2, y2, true); // draw to second point
+ stylusNDC (x2, y2, true); // draw to second point
}
m_dCurrentWorldX = x;
m_dCurrentWorldY = y;
}
-void
+void
SGP::moveAbs (double x, double y)
{
m_dCurrentWorldX = x;
- m_dCurrentWorldY = y; /* moves are not clipped */
+ m_dCurrentWorldY = y; /* moves are not clipped */
}
-void
+void
SGP::lineRel (double x, double y)
{
lineAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY);
}
-void
+void
SGP::moveRel (double x, double y)
{
moveAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY);
double dHeightPixels = height * m_iPhysicalYSize;
double dHeightPoints = dHeightPixels * m_dPointsPerPixel;
m_pFont->SetPointSize (nearest<int>(dHeightPoints));
+#if DEBUG
+ sys_error (ERR_TRACE, "Setting text size to %d points",
+ nearest<int>(dHeightPoints));
+#endif
+
m_driver.idWX()->SetFont (*m_pFont);
}
#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);
+ m_pFont->SetPointSize (m_iTextPointSize);
+#if DEBUG
+ sys_error (ERR_TRACE, "Setting point size to %d", m_iTextPointSize);
+#endif
+ m_driver.idWX()->SetFont (*m_pFont);
}
#endif
}
{
#if HAVE_WXWINDOWS
if (m_driver.isWX()) {
- wxString sText (szText);
wxCoord deviceW, deviceH;
- m_driver.idWX()->GetTextExtent (sText, &deviceW, &deviceH);
+ wxString str (wxConvCurrent->cMB2WC(szText));
+ m_driver.idWX()->GetTextExtent (str, &deviceW, &deviceH);
if (m_dTextAngle == 90 || m_dTextAngle == -90) {
wxCoord temp = deviceW;
deviceW = deviceH;
double
SGP::getCharHeight ()
{
- double dHeight = (1. / 25.);
+ double dHeight = (1. / 50.);
#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;
+ dHeight /= (yv_max - yv_min); // scale to viewport;
}
#endif
dHeight *= (yw_max - yw_min); // scale to world coordinates
if (m_driver.isWX()) {
dWidth = m_driver.idWX()->GetCharWidth();
dWidth /= static_cast<double>(m_iPhysicalXSize);
- dWidth /= (xv_max - xv_min); // scale to viewport
+ dWidth /= (xv_max - xv_min); // scale to viewport
}
#endif
dWidth *= (xw_max - xw_min); //scale to world coordinates
m_dTextAngle = convertRadiansToDegrees(angle);
}
-void
+void
SGP::polylineAbs (double x[], double y[], int n)
{
if (m_bRecalcTransform)
double x2 = x[1], y2 = y[1];
mc_to_ndc.transformPoint (&x2, &y2);
- double xt = x2; // don't pass (x2,y2) to clip, we need them
- double yt = y2; // as the beginning point of the next line
+ double xt = x2; // don't pass (x2,y2) to clip, we need them
+ double yt = y2; // as the beginning point of the next line
if (clip_rect (x1, y1, xt, yt, viewNDC)) {
stylusNDC (x1, y1, false);
stylusNDC (xt, yt, true);
}
-
+
for (int i = 2; i < n; i++) {
- x1 = x2; y1 = y2; // NDC endpoint of last line
+ x1 = x2; y1 = y2; // NDC endpoint of last line
x2 = x[i]; y2 = y[i];
mc_to_ndc.transformPoint (&x2, &y2);
xt = x2;
}
-void
+void
SGP::markerAbs (double x, double y)
{
if (m_bRecalcTransform)
double xndc = x;
double yndc = y;
mc_to_ndc.transformPoint (&xndc, &yndc);
- markerNDC (xndc, yndc);
- stylusNDC (xndc, yndc, false); // move to location
+ markerNDC (xndc, yndc);
m_dCurrentWorldX = x;
m_dCurrentWorldY = y;
}
-void
+void
SGP::markerRel (double x, double y)
{
markerAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY);
}
-void
+void
SGP::pointAbs (double x, double y)
{
if (m_bRecalcTransform)
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
+void
SGP::pointRel (double x, double y)
{
pointAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY);
drawText (rsMessage.c_str());
}
-void
+void
SGP::drawText (const char *pszMessage)
{
if (m_bRecalcTransform)
double yndc = m_dCurrentWorldY;
mc_to_ndc.transformPoint (&xndc, &yndc);
- stylusNDC (xndc, yndc, false); // move to location
+ stylusNDC (xndc, yndc, false); // move to location
#if HAVE_G2_H
if (m_driver.isG2()) {
#endif
#if HAVE_WXWINDOWS
if (m_driver.isWX()) {
- wxString str (pszMessage);
+ wxString str(wxConvCurrent->cMB2WC(pszMessage));
m_driver.idWX()->DrawRotatedText (str, m_iCurrentPhysicalX, m_iCurrentPhysicalY, m_dTextAngle);
}
#endif
// NAME
-// drawRect Draw box in graphics mode
+// drawRect Draw box in graphics mode
//
// SYNOPSIS
// drawbox (xmin, ymin, xmax, ymax)
-// double xmin, ymin Lower left corner of box
-// double xmax, ymax Upper left corner of box
+// double xmin, ymin Lower left corner of box
+// double xmax, ymax Upper left corner of box
//
// NOTES
// This routine leaves the current position of graphic cursor at lower
void
SGP::drawRect (double xmin, double ymin, double xmax, double ymax)
{
- moveAbs (xmin, ymin);
- lineAbs (xmax, ymin);
- lineAbs (xmax, ymax);
- lineAbs (xmin, ymax);
- lineAbs (xmin, ymin);
+ moveAbs (xmin, ymin);
+ lineAbs (xmax, ymin);
+ lineAbs (xmax, ymax);
+ lineAbs (xmin, ymax);
+ lineAbs (xmin, ymin);
}
// FUNCTION
-// sgp2_circle - draw circle of radius r at current center
-
-void
+// sgp2_circle - draw circle of radius r at current center
+
+void
SGP::drawCircle (const double r)
{
- drawArc (r, 0.0, TWOPI);
+ drawArc (r, 0.0, TWOPI);
}
//==============================================================
-// draw arc around current center. angles in radius
+// draw arc around current center. angles in radius
//==============================================================
-void
+void
SGP::drawArc (const double r, double start, double stop)
{
if (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 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));
- double cosTheta = cos(thetaIncrement);
- double sinTheta = sin(thetaIncrement);
+ const double thetaIncrement = (5 * (TWOPI / 360)); // 5 degree increments
+ double cosTheta = cos (thetaIncrement);
+ double sinTheta = sin (thetaIncrement);
- double angle, xp, yp;
- 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);
+ 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;
}
double c = cos (stop - angle);
double s = sin (stop - angle);
- xp = c * x - s * y;
- yp = s * x + c * y;
- lineAbs (xp, yp);
+ double xp = c * x - s * y;
+ double yp = s * x + c * y;
+ lineAbs (xCent + xp, yCent + yp);
- x = r * cos (stop);
- y = r * sin (stop);
- moveRel (-x, -y); // move back to center of circle
+ moveAbs (xCent, yCent); // move back to center of circle
}
// NAME
-// calc_transform Calculate transform matrices
+// calc_transform Calculate transform matrices
void
SGP::calc_transform ()
{
double scaleX = (xv_max - xv_min) / (xw_max - xw_min);
double scaleY = (yv_max - yv_min) / (yw_max - yw_min);
-
+
wc_to_ndc.setIdentity();
wc_to_ndc.mtx[0][0] = scaleX;
wc_to_ndc.mtx[2][0] = xv_min - scaleX * xw_min;
calc_transform();
}
-void
+void
SGP::ctmSet (const TransformationMatrix2D& m)
{
m_ctm = m;
}
-void
+void
SGP::postTranslate (double x, double y)
{
TransformationMatrix2D m;
}
-void
+void
SGP::preScale (double sx, double sy)
{
TransformationMatrix2D m;
}
-void
+void
SGP::postScale (double sx, double sy)
{
TransformationMatrix2D m;
}
-void
+void
SGP::preRotate (double theta)
{
TransformationMatrix2D m;
}
-void
+void
SGP::postRotate (double theta)
{
TransformationMatrix2D m;
}
-void
+void
SGP::preShear (double shrx, double shry)
{
TransformationMatrix2D m;
}
-void
+void
SGP::postShear (double shrx, double shry)
{
TransformationMatrix2D m;
////////////////////////////////////////////////////////////////////////
// Pixel patterns of marker symbols (1x1 to 5x5 matrix)
-const unsigned char SGP::MARKER_BITMAP[MARK_COUNT][5] =
-{
- {'\000', '\000', '\010', '\000', '\000'}, // small dot
- {'\000', '\034', '\024', '\034', '\000'}, // empty square
- {'\000', '\034', '\034', '\034', '\000'}, // filled square
- {'\000', '\010', '\024', '\010', '\000'}, // empty diamond
- {'\000', '\010', '\034', '\010', '\000'}, // filled diamond
- {'\010', '\010', '\076', '\010', '\010'}, // cross
- {'\000', '\024', '\010', '\024', '\000'}, // X
- {'\034', '\042', '\042', '\042', '\034'}, // open circle
- {'\034', '\076', '\076', '\076', '\034'}, // filled circle
- {'\076', '\042', '\042', '\042', '\076'}, // big open square
- {'\010', '\024', '\042', '\024', '\010'}, // big open diamond
+const unsigned char SGP::MARKER_BITMAP[MARK_COUNT][5] =
+{
+ {'\000', '\000', '\010', '\000', '\000'}, // small dot
+ {'\000', '\034', '\024', '\034', '\000'}, // empty square
+ {'\000', '\034', '\034', '\034', '\000'}, // filled square
+ {'\000', '\010', '\024', '\010', '\000'}, // empty diamond
+ {'\000', '\010', '\034', '\010', '\000'}, // filled diamond
+ {'\010', '\010', '\076', '\010', '\010'}, // cross
+ {'\000', '\024', '\010', '\024', '\000'}, // X
+ {'\034', '\042', '\042', '\042', '\034'}, // open circle
+ {'\034', '\076', '\076', '\076', '\034'}, // filled circle
+ {'\076', '\042', '\042', '\042', '\076'}, // big open square
+ {'\010', '\024', '\042', '\024', '\010'}, // big open diamond
};