/*****************************************************************************
-** This is part of the CTSim program
-** Copyright (C) 1983-2000 Kevin Rosenberg
-**
-** $Id: sgp.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
-** $Log: sgp.cpp,v $
-** Revision 1.1 2000/06/19 18:05:03 kevin
-** initial cvs import
-**
-** Revision 1.1 2000/06/13 16:20:31 kevin
-** finished c++ conversions
-**
-** Revision 1.4 2000/05/24 22:49:01 kevin
-** Updated SGP: first function X-windows version
+** FILE IDENTIFICATION
**
-** Revision 1.3 2000/05/11 14:07:23 kevin
-** Fixed compilation warnings
-**
-** Revision 1.2 2000/05/08 20:08:15 kevin
-** *** empty log message ***
-**
-** Revision 1.1.1.1 2000/04/28 13:02:44 kevin
-** Initial CVS import for first public release
+** Name: sgp.cpp Simple Graphics Package
+** Programmer: Kevin Rosenberg
**
+** This is part of the CTSim program
+** Copyright (C) 1983-2000 Kevin Rosenberg
**
+** $Id: sgp.cpp,v 1.12 2000/08/31 08:38:58 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
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
******************************************************************************/
-/*-----------------------------------------------------------------------------
- * FILE IDENTIFICATION
- *
- * Name: sgp.c Simple Graphics Package
- * Programmer: Kevin Rosenberg
- *
- *---------------------------------------------------------------------------*/
-
-#include "stdio.h"
-#include "kstddef.h"
-#include "math.h"
-#include "kmath.h"
+#include <stdio.h>
+#include <math.h>
+#include "ctsupport.h"
#include "sgp.h"
-static SGP_ID _sgp2_cwin = NULL;
-extern CHARSPEC cspec;
+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, int xsize = 640, int ysize = 480)
+ : m_iPhysicalXSize(xsize), m_iPhysicalYSize(ysize), m_idDriver(0), m_pDC(pDC)
+{
+ m_idDriver |= SGPDRIVER_WXWINDOWS;
+}
+#endif
-/* NAME
- * sgp2_init Initialize 2 graphics system
- *
- * SYNOPSIS
- * sgp2_init()
- */
+SGPDriver::SGPDriver (const char* szWinTitle = "", int xsize = 640, int ysize = 480)
+ : m_iPhysicalXSize(xsize), m_iPhysicalYSize(ysize), m_sWindowTitle(szWinTitle), m_idDriver(0)
+{
+#ifdef HAVE_G2_H
+ m_idG2 = g2_open_X11X (m_iPhysicalXSize, m_iPhysicalYSize, 10, 10, const_cast<char*>(szWinTitle), const_cast<char*>(szWinTitle), NULL, -1, -1);
+ m_idDriver |= SGPDRIVER_G2;
+#endif
+}
-SGP_ID
-sgp2_init (int xsize, int ysize, const char *win_title )
+SGPDriver::~SGPDriver ()
{
- SGP_ID gid;
+ if (isG2())
+ g2_close (m_idG2);
+}
- gid = new SGP_WINDOW;
- _sgp2_cwin = gid;
-
- if (xsize <= 0)
- xsize = 640;
- if (ysize <= 0)
- ysize = 480;
-
- gid->pw_xsize = xsize;
- gid->pw_ysize = ysize;
- strncpy(gid->title, win_title, sizeof(gid->title));
-
- gid->recalc_mc_to_ndc = TRUE;
- gid->recalc_ndc_to_mc = TRUE;
- ident_gmtx_2 (gid->wc_to_ndc_x);
- ident_gmtx_2 (gid->mc_to_ndc_x);
- ident_gmtx_2 (gid->ndc_to_mc_x);
- ident_gmtx_2 (gid->ctm_2_x);
-
- sgp2_window (0., 0., 1., 1.);
- sgp2_viewport (0., 0., 1., 1.);
- ctm_clr_2 ();
- sgp2_move_abs (0., 0.);
-#if HAVE_G2_H
- gid->g2_id = g2_open_X11X (gid->pw_xsize, gid->pw_ysize, 10, 10, gid->title, gid->title, NULL, -1, -1);
+// NAME
+// SGP::SGP Constructor for Simple Graphics Package
+
+SGP::SGP (const SGPDriver& driver)
+ : m_driver (driver)
+{
+ m_iPhysicalXSize = m_driver.getPhysicalXSize();
+ m_iPhysicalYSize = m_driver.getPhysicalYSize();
+
+ wc_to_ndc.setIdentity ();
+ mc_to_ndc.setIdentity();
+ ndc_to_mc.setIdentity();
+ m_ctm.setIdentity();
+
+#if HAVE_WXWINDOWS
+ m_pen.SetWidth(1);
+ m_pen.SetStyle(wxSOLID);
#endif
- _sgp2_init_dev (_sgp2_cwin);
-
- return (gid);
+ setWindow (0., 0., 1., 1.);
+ setViewport (0., 0., 1., 1.);
+ moveAbs (0., 0.);
+ stylusNDC (0., 0., false);
+
+ setTextAngle (0.);
+ setTextSize (1. / 25.);
+ setColor (C_BLACK);
}
void
-sgp2_close (SGP_ID gid)
+SGP::stylusNDC (double x, double y, bool beam)
{
-#if HAVE_G2_H
- g2_close (gid->g2_id);
+ 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 (beam) {
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX())
+ m_driver.idWX()->DrawLine (m_iCurrentPhysicalX, m_iCurrentPhysicalY, xp, yp);
#endif
- if (gid == _sgp2_cwin)
- _sgp2_cwin = NULL;
-
- delete gid;
+#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;
}
void
-sgp2_set_active_win (SGP_ID gid)
+SGP::markerNDC (double x, double y)
{
- _sgp2_cwin = gid;
}
-SGP_ID
-sgp2_get_active_win (void)
+void
+SGP::pointNDC (double x, double y)
{
- return (_sgp2_cwin);
}
-/* NAME
- * sgp2_clear Clear window
- */
+// NAME
+// clear Clear Window
void
-sgp2_clear ()
+SGP::eraseWindow ()
{
-#if HAVE_G2
- if (_sgp_cwin != NULL)
- g2_clear (gid->g2_id);
+#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
- * sgp2_window Set window in world coordinates
- */
+// NAME
+// sgp2_window Set window in world coordinates
+
void
-sgp2_window (double xmin, double ymin, double xmax, double ymax)
+SGP::setWindow (double xmin, double ymin, double xmax, double ymax)
{
- if (_sgp2_cwin == NULL)
- return;
+ if (xmin >= xmax || ymin >= ymax) {
+ sys_error (ERR_WARNING, "Minimum > Maximum [sgp2_window]");
+ return;
+ }
+
+ xw_min = xmin;
+ yw_min = ymin;
+ xw_max = xmax;
+ yw_max = ymax;
+ m_bRecalcTransform = true;
+}
- if (xmin >= xmax || ymin >= ymax) {
- sys_error (ERR_WARNING, "Minimum > Maximum [sgp2_window]");
- return;
- }
- _sgp2_cwin->xw_min = xmin;
- _sgp2_cwin->yw_min = ymin;
- _sgp2_cwin->xw_max = xmax;
- _sgp2_cwin->yw_max = ymax;
- calc_wc_to_ndc();
+// NAME
+// sgp2_viewport Set viewport in NDC
+
+void
+SGP::setViewport (double xmin, double ymin, double xmax, double ymax)
+{
+ if (xmin >= xmax || ymin >= 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[1] = ymin;
+ viewNDC[2] = xmax;
+ 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;
}
-/* NAME
- * sgp2_viewport Set viewport in NDC
- */
+// NAME
+// frameViewport draw box around viewport
void
-sgp2_viewport (double xmin, double ymin, double xmax, double ymax)
+SGP::frameViewport (void)
{
- if (_sgp2_cwin == NULL)
- return;
+ 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);
+}
- if (xmin >= xmax || ymin >= ymax) {
- sys_error (ERR_WARNING, "Minimum > Maximum [sgp2_viewport]");
- return;
+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);
}
-
- _sgp2_cwin->xv_min = xmin;
- _sgp2_cwin->yv_min = ymin;
- _sgp2_cwin->xv_max = xmax;
- _sgp2_cwin->yv_max = ymax;
- calc_wc_to_ndc();
-
- _sgp2_cwin->view[0] = xmin; /* Array for clip_rect() */
- _sgp2_cwin->view[1] = ymin;
- _sgp2_cwin->view[2] = xmax;
- _sgp2_cwin->view[3] = ymax;
+ 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
+ }
+}
-/* NAME
- * sgp2_frame_vpt draw box around viewport
- */
+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
-sgp2_frame_vpt (void)
+SGP::setRasterOp (int ro)
{
- if (_sgp2_cwin == NULL)
- return;
-
- _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_min, _sgp2_cwin->yv_min, 0);
- _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_max, _sgp2_cwin->yv_min, 1);
- _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_max, _sgp2_cwin->yv_max, 1);
- _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_min, _sgp2_cwin->yv_max, 1);
- _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_min, _sgp2_cwin->yv_min, 1);
+#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
}
-/* NAME
- * calc_wc_to_ndc Calculate transform matrix
- */
-
void
-calc_wc_to_ndc (void)
+SGP::setMarker (int idMarke, int iColor)
{
- double sx, sy;
-
- if (_sgp2_cwin == NULL)
- return;
+}
- sx = (_sgp2_cwin->xv_max - _sgp2_cwin->xv_min) / (_sgp2_cwin->xw_max - _sgp2_cwin->xw_min);
- sy = (_sgp2_cwin->yv_max - _sgp2_cwin->yv_min) / (_sgp2_cwin->yw_max - _sgp2_cwin->yw_min);
-
- ident_gmtx_2 (_sgp2_cwin->wc_to_ndc_x);
- _sgp2_cwin->wc_to_ndc_x[0][0] = sx;
- _sgp2_cwin->wc_to_ndc_x[2][0] = _sgp2_cwin->xv_min - sx * _sgp2_cwin->xw_min;
- _sgp2_cwin->wc_to_ndc_x[1][1] = sy;
- _sgp2_cwin->wc_to_ndc_x[2][1] = _sgp2_cwin->yv_min - sy * _sgp2_cwin->yw_min;
-
- _sgp2_cwin->recalc_mc_to_ndc = TRUE;
- _sgp2_cwin->recalc_ndc_to_mc = TRUE;
+//==============================================================
+// set line style. Pass 16 bit repeating pattern
+//==============================================================
+void
+SGP::setLineStyle (int style)
+{
}
+//==============================================================
+// absolute draw to
+//*==============================================================
void
-calc_ndc_to_mc (void)
+SGP::lineAbs (double x, double y)
{
- if (_sgp2_cwin == NULL)
- return;
-
- if (_sgp2_cwin->recalc_mc_to_ndc) {
- mult_gmtx_2 (_sgp2_cwin->ctm_2_x, _sgp2_cwin->wc_to_ndc_x, _sgp2_cwin->mc_to_ndc_x);
- _sgp2_cwin->recalc_mc_to_ndc = FALSE;
- }
-
- invert_gmtx_2 (_sgp2_cwin->mc_to_ndc_x, _sgp2_cwin->ndc_to_mc_x);
- _sgp2_cwin->recalc_ndc_to_mc = FALSE;
+ if (m_bRecalcTransform)
+ calc_transform();
+
+ double x1 = m_dCurrentWorldX;
+ double y1 = m_dCurrentWorldY;
+ mc_to_ndc.transformPoint (&x1, &y1);
+
+ double x2 = x;
+ double y2 = y;
+ mc_to_ndc.transformPoint (&x2, &y2);
+
+ 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
+ }
+
+ m_dCurrentWorldX = x;
+ m_dCurrentWorldY = y;
}
+void
+SGP::moveAbs (double x, double y)
+{
+ m_dCurrentWorldX = x;
+ m_dCurrentWorldY = y; /* moves are not clipped */
+}
-/* NAME
- * wc_to_ndc Map from world coordinates to NDC
- */
+void
+SGP::lineRel (double x, double y)
+{
+ lineAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY);
+}
void
-wc_to_ndc (double xw, double yw, double *xn, double *yn)
+SGP::moveRel (double x, double y)
{
- if (_sgp2_cwin == NULL)
- return;
+ moveAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY);
+}
- if (_sgp2_cwin->recalc_mc_to_ndc) {
- mult_gmtx_2 (_sgp2_cwin->ctm_2_x, _sgp2_cwin->wc_to_ndc_x, _sgp2_cwin->mc_to_ndc_x);
- _sgp2_cwin->recalc_mc_to_ndc = FALSE;
- }
+void
+SGP::setTextSize (double height)
+{
+ if (m_driver.isG2())
+ g2_set_font_size(m_driver.idG2(), (height * m_iPhysicalYSize));
+}
- *xn = xw * _sgp2_cwin->mc_to_ndc_x[0][0] + yw * _sgp2_cwin->mc_to_ndc_x[1][0] + _sgp2_cwin->mc_to_ndc_x[2][0];
- *yn = xw * _sgp2_cwin->mc_to_ndc_x[0][1] + yw * _sgp2_cwin->mc_to_ndc_x[1][1] + _sgp2_cwin->mc_to_ndc_x[2][1];
+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<double>(deviceW) / static_cast<double>(m_iPhysicalXSize);;
+ *worldH = static_cast<double>(deviceH) / static_cast<double>(m_iPhysicalYSize);
+ // cout << deviceW << ", " << deviceH << ", " << *worldW << ", " << *worldH << endl;
+ *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<double>(m_iPhysicalYSize);;
+ }
+#endif
+ return (dHeight * (xw_max - xw_min));
+}
-/*==============================================================*/
-/* map from normalized device coords. to world coordinates */
-/*==============================================================*/
void
-ndc_to_wc (double xn, double yn, double *xw, double *yw)
+SGP::setTextAngle (double angle)
{
- if (_sgp2_cwin == NULL)
- return;
+ m_dTextAngle = angle;
+}
- if (_sgp2_cwin->recalc_ndc_to_mc) {
- calc_ndc_to_mc();
- _sgp2_cwin->recalc_ndc_to_mc = FALSE;
+void
+SGP::polylineAbs (double x[], double y[], int n)
+{
+ if (m_bRecalcTransform)
+ calc_transform();
+
+ double x1 = x[0], y1 = y[0];
+ mc_to_ndc.transformPoint (&x1, &y1);
+ 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
+
+ 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
+ x2 = x[i]; y2 = y[i];
+ mc_to_ndc.transformPoint (&x2, &y2);
+ xt = x2;
+ yt = y2;
+ if (clip_rect (x1, y1, xt, yt, viewNDC)) {
+ stylusNDC (x1, y1, false);
+ stylusNDC (xt, yt, true);
}
-
- *xw = xn * _sgp2_cwin->ndc_to_mc_x[0][0] + yn * _sgp2_cwin->ndc_to_mc_x[1][0] + _sgp2_cwin->ndc_to_mc_x[2][0];
- *yw = xn * _sgp2_cwin->ndc_to_mc_x[0][1] + yn * _sgp2_cwin->ndc_to_mc_x[1][1] + _sgp2_cwin->ndc_to_mc_x[2][1];
+ }
}
-/*==============================================================*/
-/* set the color */
-/*==============================================================*/
void
-sgp2_color (int icol)
+SGP::markerAbs (double x, double y)
{
- setcolor(icol);
+ if (m_bRecalcTransform)
+ calc_transform();
+
+ double xndc = x;
+ 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;
}
-/*==============================================================*/
-/* set line style. Pass 16 bit repeating pattern */
-/*==============================================================*/
+
void
-sgp2_line_style (int style)
+SGP::markerRel (double x, double y)
{
- setlinestyle(style);
+ markerAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY);
}
-/*==============================================================*/
-/* absolute draw to */
-/*==============================================================*/
+
void
-sgp2_line_abs (double x, double y)
+SGP::pointAbs (double x, double y)
{
- double x1, y1, x2, y2;
+ if (m_bRecalcTransform)
+ calc_transform();
+ 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;
+}
- if (_sgp2_cwin == NULL)
- return;
- wc_to_ndc (_sgp2_cwin->curx, _sgp2_cwin->cury, &x1, &y1);
- wc_to_ndc (x, y, &x2, &y2);
+void
+SGP::pointRel (double x, double y)
+{
+ pointAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY);
+}
- if (clip_rect (x1, y1, x2, y2, _sgp2_cwin->view) == TRUE) { /* clip to viewport */
- _sgp2_stylus (_sgp2_cwin, x1, y1, 0); /* move to first point */
- _sgp2_stylus (_sgp2_cwin, x2, y2, 1); /* draw to second point */
- }
- _sgp2_cwin->curx = x;
- _sgp2_cwin->cury = y;
+void
+SGP::drawText (const string& rsMessage)
+{
+ drawText (rsMessage.c_str());
}
-/*==============================================================*/
-/* absolute move to */
-/*==============================================================*/
void
-sgp2_move_abs (double x, double y)
+SGP::drawText (const char *pszMessage)
{
- if (_sgp2_cwin == NULL)
- return;
+ if (m_bRecalcTransform)
+ calc_transform();
+
+ double xndc = m_dCurrentWorldX;
+ double yndc = m_dCurrentWorldY;
+ mc_to_ndc.transformPoint (&xndc, &yndc);
+
+ stylusNDC (xndc, yndc, false); // move to location
- _sgp2_cwin->curx = x;
- _sgp2_cwin->cury = y; /* moves are not clipped */
+#if HAVE_G2_H
+ if (m_driver.isG2()) {
+ g2_string (m_driver.idG2(), m_iCurrentPhysicalX, m_iCurrentPhysicalY, const_cast<char*>(pszMessage));
+ }
+#endif
+#if HAVE_WXWINDOWS
+ if (m_driver.isWX()) {
+ wxString str (pszMessage);
+ m_driver.idWX()->DrawRotatedText (str, m_iCurrentPhysicalX, m_iCurrentPhysicalY, m_dTextAngle);
+ }
+#endif
}
-/*==============================================================*/
-/* vector draw */
-/*==============================================================*/
-void
-sgp2_line_rel (double x, double y)
+
+// NAME
+// 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
+//
+// NOTES
+// This routine leaves the current position of graphic cursor at lower
+// left corner of box.
+
+void
+SGP::drawRect (double xmin, double ymin, double xmax, double ymax)
{
- if (_sgp2_cwin != NULL)
- sgp2_line_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
+ moveAbs (xmin, ymin);
+ lineAbs (xmax, ymin);
+ lineAbs (xmax, ymax);
+ lineAbs (xmin, ymax);
+ lineAbs (xmin, ymin);
}
-/*==============================================================*/
-/* vector move */
-/*==============================================================*/
+// FUNCTION
+// sgp2_circle - draw circle of radius r at current center
+
void
-sgp2_move_rel (double x, double y)
+SGP::drawCircle (const double r)
{
- if (_sgp2_cwin != NULL)
- sgp2_move_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
+ drawArc (r, 0.0, TWOPI);
}
-/*==============================================================*/
-/* draw text */
-/*==============================================================*/
+//==============================================================
+// draw arc around current center. angles in radius
+//==============================================================
+
void
-sgp2_draw_text (char *message)
+SGP::drawArc (const double r, double start, double stop)
{
- double sx,sy;
- if (_sgp2_cwin == NULL)
- return;
-
- wc_to_ndc (_sgp2_cwin->curx, _sgp2_cwin->cury, &sx, &sy);
- _sgp2_stylus (_sgp2_cwin, sx, sy, 0); /* move to location */
- _sgp2_dev_text (_sgp2_cwin, message);
+ 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
+
+ const double thetaIncrement = (5 * (TWOPI / 360));
+ 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);
+ 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);
+
+ x = r * cos (stop);
+ y = r * sin (stop);
+ moveRel (-x, -y); // move back to center of circle
}
+
+
+///////////////////////////////////////////////////////////////////////
+// Coordinate Transformations
+///////////////////////////////////////////////////////////////////////
+
+
void
-charsize (double wid, double height)
+SGP::transformNDCtoMC (double* x, double* y)
{
- _sgp2_set_text (_sgp2_cwin, wid, height, cspec.textangle, cspec.font);
+ if (m_bRecalcTransform)
+ calc_transform();
+ ndc_to_mc.transformPoint (x, y);
}
+
void
-textangle (double angle)
+SGP::transformMCtoNDC (double* x, double* y)
{
- _sgp2_set_text (_sgp2_cwin, cspec.width, cspec.height, angle, cspec.font);
+ if (m_bRecalcTransform)
+ calc_transform();
+ mc_to_ndc.transformPoint (x, y);
}
-void
-sgp2_polyline_abs (double x[], double y[], int n)
+
+void
+SGP::transformMCtoNDC (double xIn, double yIn, double* x, double* y)
{
- double x1, y1, x2, y2;
- int i;
- double xt, yt;
+ if (m_bRecalcTransform)
+ calc_transform();
+ *x = xIn;
+ *y = yIn;
+ mc_to_ndc.transformPoint (x, y);
+}
- if (_sgp2_cwin == NULL || n < 2)
- return;
- wc_to_ndc (x[0], y[0], &x1, &y1);
- wc_to_ndc (x[1], y[1], &x2, &y2);
+// NAME
+// calc_transform Calculate transform matrices
- xt = x2; /* don't pass (x2,y2) to clip, we need them */
- yt = y2; /* as the beginning point of the next line */
+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;
+ wc_to_ndc.mtx[1][1] = scaleY;
+ wc_to_ndc.mtx[2][1] = yv_min - scaleY * yw_min;
- if (clip_rect (x1, y1, xt, yt, _sgp2_cwin->view) == TRUE) {
- _sgp2_stylus (_sgp2_cwin, x1, y1, 0);
- _sgp2_stylus (_sgp2_cwin, xt, yt, 1);
- }
+ mc_to_ndc = m_ctm * wc_to_ndc;
+ ndc_to_mc = mc_to_ndc.invert();
- for (i = 2; i < n; i++) {
- x1 = x2; /* NDC endpoint of last line */
- y1 = y2;
- wc_to_ndc (x[i], y[i], &x2, &y2);
- xt = x2;
- yt = y2;
- if (clip_rect (x1, y1, xt, yt, _sgp2_cwin->view) == TRUE) {
- _sgp2_stylus (_sgp2_cwin, x1, y1, 0);
- _sgp2_stylus (_sgp2_cwin, xt, yt, 1);
- }
- }
+ m_bRecalcTransform = false;
}
+void
+SGP::ctmClear ()
+{
+ m_ctm.setIdentity();
+ calc_transform();
+}
void
-sgp2_mark_abs (double x, double y)
+SGP::ctmSet (const TransformationMatrix2D& m)
{
- double xndc, yndc;
-
- if (_sgp2_cwin == NULL)
- return;
-
- wc_to_ndc (x, y, &xndc, &yndc);
- markndc (_sgp2_cwin, xndc, yndc);
- _sgp2_cwin->curx = x;
- _sgp2_cwin->cury = y;
+ m_ctm = m;
+ calc_transform();
}
-void
-sgp2_mark_rel (double x, double y)
+void
+SGP::preTranslate (double x, double y)
{
- sgp2_mark_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
+ TransformationMatrix2D m;
+
+ m.setTranslate (x, y);
+ ctmSet (m * m_ctm);
}
void
-sgp2_point_abs (double x, double y)
+SGP::postTranslate (double x, double y)
{
- double xndc, yndc;
-
- if (_sgp2_cwin == NULL)
- return;;
+ TransformationMatrix2D m;
- wc_to_ndc (x, y, &xndc, &yndc);
- pntndc (_sgp2_cwin, xndc, yndc);
- _sgp2_cwin->curx = x;
- _sgp2_cwin->cury = y;
+ m.setTranslate (x, y);
+ ctmSet (m_ctm * m);
}
void
-sgp2_point_rel (double x, double y)
+SGP::preScale (double sx, double sy)
{
- sgp2_point_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
+ TransformationMatrix2D m;
+
+ m.setScale (sx, sy);
+ ctmSet (m * m_ctm);
}
-/*----------------------------------------------------------------------*/
-/* Current Transformation Matrix Routine */
-/*----------------------------------------------------------------------*/
+void
+SGP::postScale (double sx, double sy)
+{
+ TransformationMatrix2D m;
+ m.setScale (sx, sy);
+ m_ctm = m_ctm * m;
+ ctmSet (m_ctm * m);
+}
-/* NAME
- * ctm_clr_2 Clear current transformation matrix
- *
- * SYNOPSIS
- * ctm_clr_2()
- */
void
-ctm_clr_2 (void)
+SGP::preRotate (double theta)
{
- GRFMTX_2D m;
+ TransformationMatrix2D m;
- ident_gmtx_2 (m);
- ctm_set_2 (m);
+ m.setRotate (theta);
+ m_ctm = m * m_ctm;
+ ctmSet (m * m_ctm);
}
-/* NAME
- * ctm_get_2 Get ctm
- *
- * SYNOPSIS
- * ctm_get_2 (m)
- * OUT GRFMTX_2D m Copy of ctm
- */
-
void
-ctm_get_2 (GRFMTX_2D m)
+SGP::postRotate (double theta)
{
- int x, y;
+ TransformationMatrix2D m;
- if (_sgp2_cwin == NULL)
- return;
-
- for (x = 0; x < 3; x++)
- for (y = 0; y < 3; y++)
- m[x][y] = _sgp2_cwin->ctm_2_x[x][y];
+ m.setRotate (theta);
+ ctmSet (m_ctm * m);
}
-/* NAME
- * ctm_set_2 Set ctm to a matrix
- *
- * SYNOPSIS
- * ctm_get_ctm_2 (m)
- * IN GRFMTX m New ctm
- */
-
void
-ctm_set_2 (GRFMTX_2D m)
+SGP::preShear (double shrx, double shry)
{
- int x, y;
- if (_sgp2_cwin == NULL)
- return;
-
- for (x = 0; x < 3; x++)
- for (y = 0; y < 3; y++)
- _sgp2_cwin->ctm_2_x[x][y] = m[x][y];
+ TransformationMatrix2D m;
- _sgp2_cwin->recalc_ndc_to_mc = TRUE;
- _sgp2_cwin->recalc_mc_to_ndc = TRUE;
+ m.setShear (shrx, shry);
+ ctmSet (m * m_ctm);
}
void
-ctm_pre_mult_2 (GRFMTX_2D m)
+SGP::postShear (double shrx, double shry)
{
- GRFMTX_2D new_ctm;
+ TransformationMatrix2D m;
- mult_gmtx_2 (m, _sgp2_cwin->ctm_2_x, new_ctm);
- ctm_set_2 (new_ctm);
+ m.setShear (shrx, shry);
+ ctmSet (m_ctm * m);
}
-void
-ctm_post_mult_2 (GRFMTX_2D m)
-{
- GRFMTX_2D new_ctm;
+////////////////////////////////////////////////////////////////////////
+// Bitmap Markers
+////////////////////////////////////////////////////////////////////////
- mult_gmtx_2 (_sgp2_cwin->ctm_2_x, m, new_ctm);
- ctm_set_2 (new_ctm);
+// 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
+};
+
+
+#if HAVE_WXWINDOWS
+void
+SGP::setDC (wxDC* pDC)
+{
+ if (m_driver.isWX())
+ m_driver.setDC(pDC);
}
+#endif