From 711cae0ee02e046370fdb4d6c6f440596ff71980 Mon Sep 17 00:00:00 2001 From: "Kevin M. Rosenberg" Date: Fri, 28 Jul 2000 08:28:08 +0000 Subject: [PATCH] r162: *** empty log message *** --- ChangeLog | 3 + NEWS | 3 +- doc/Makefile.am | 4 +- doc/ctsim.tex | 71 +- include/Makefile.am | 3 +- include/ezplot.h | 419 ++++---- include/phantom.h | 8 +- include/scanner.h | 13 +- include/sgp.h | 390 +++---- include/transformmatrix.h | 60 ++ libctgraphics/Makefile.am | 2 +- libctgraphics/ezplot.cpp | 1634 +++++++++++++++-------------- libctgraphics/ezset.cpp | 1097 +++++++++---------- libctgraphics/ezsupport.cpp | 192 +--- libctgraphics/sgp.cpp | 802 +++++++------- libctgraphics/sgpdriver.cpp | 528 ---------- libctgraphics/sgptext.cpp | 102 -- libctgraphics/transformmatrix.cpp | 159 +++ libctsim/phantom.cpp | 45 +- libctsim/projections.cpp | 57 +- libctsim/scanner.cpp | 88 +- man/Makefile.am | 3 +- src/dialogs.h | 3 +- src/views.cpp | 24 +- src/views.h | 7 +- tools/if-2.cpp | 58 +- tools/if2img.cpp | 3 +- tools/phm2pj.cpp | 21 +- tools/pjrec.cpp | 5 +- 29 files changed, 2534 insertions(+), 3270 deletions(-) create mode 100644 include/transformmatrix.h delete mode 100644 libctgraphics/sgpdriver.cpp delete mode 100644 libctgraphics/sgptext.cpp create mode 100644 libctgraphics/transformmatrix.cpp diff --git a/ChangeLog b/ChangeLog index c824c4d..3609c14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ 2.0.0-b7 - 7/25/00 Finished support for dmallocxx library Fixed bug in SignalFilter::convertFilterMethodNameToID() + Rewrote SGP & EZPlot to use C++ object-oriented. SGP can now write to + G2 windows and well as WXWindows. + Now, "Create Phantom" in ctsim shows phantom object 2.0.0-b6 - 7/22/00 ctsim program: improved initial size and scroll area for image diff --git a/NEWS b/NEWS index 5048b79..8baa493 100644 --- a/NEWS +++ b/NEWS @@ -3,8 +3,7 @@ Version 2.0 of CTSim is near completion! New Features of CTSim version 2.0: -- Entire code-base, except for SGP & EZPlot, cleaned up, - re-written, and converted from C to C++. +- Entire code-base cleaned up, re-written, and converted from C to C++. - Integrated G2 library for graphical display from command line tools (UNIX only) diff --git a/doc/Makefile.am b/doc/Makefile.am index d41b239..29d4c6b 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,4 +1,6 @@ -EXTRA_DIST=sgp.doc ctsim.tex texhelp.sty +docs=sgp.doc ctsim.tex texhelp.sty +info_INFO=ctsim.texi +EXTRA_DIST = ${docs} $(info_INFO) dvi: ctsim.tex latex ctsim.tex diff --git a/doc/ctsim.tex b/doc/ctsim.tex index 8f89aac..bb38e0a 100644 --- a/doc/ctsim.tex +++ b/doc/ctsim.tex @@ -1,29 +1,65 @@ -\documentstyle[a4,texhelp]{report} +\documentclass[11pt,texhelp]{report} +\usepackage[dvips]{graphics} + +\begin{document} + +\newcommand{\ctsim}{{\tt ctsim}} + + \title{CTSim - An Open-Source Computed Tomography Simulator} -\author{Kevin Rosenberg} +\author{Kevin Rosenberg, MD\footnote{San Juan Regional Medical Center, 801 W. Maple, Farmington NM 87401. Phone: (505) 599-6103. E-mail: kevin@rosenberg.net}} \date{July 2000} -\begin{document} \maketitle \chapter{Introduction} -Welcome to CT. -\section{Theory} -Theory of CT. +Computed Tomography is the process of taking projection of X-ray data +though and object and using sophisticated mathematics to estimate +information about the interior of that object. + +\chapter{Installation} +\subsection{Requirements} +\begin{itemize} + + \item Apache or other CGI compatible web server + + \item Perl (version 4.0 or higher) + + \item A client web browser than can display PNG files. Most + current web browswer do support PNG. + +\end{itemize} + +\subsection{Download} +\subsection{Install Binary Distribution} +\subsection{Build From Sources} + +\chapter{The Programs} -\chapter{The Programs} \section{ctsim - The Graphical User Interface} -{\tt ctsim} is the graphical shell for the CTSim project. {\tt ctsim} has most of the capabilities of the CTSim project. There are still functions that are only available to the command line tools. +\ctsim\ is the graphical shell for the CTSim project. It is +written using the wxLibrary for cross-platform compatibility with GTK, +Motif, and Microsoft Windows. + +\ctsim\ incorporates most of the capabilities of the CTSim +project. There are still functions that are only available to the +command line tools. + +\subsection{Usage} +ctsim [OPTIONS] [files to open...] + +\ctsim\ can open projection files and image files. \section{The Web Browser CGI Interface} \subsection{Overview} +The CGI program {\tt ctsim.cgi} takes projections of a standard +phantom object, performs reconstruction, and then compares the +rasterized phantom object with the reconstruction. The comparison is +performed both visually by an image subtraction as well as by standard +statistics as described by Herman\cite{HERMAN80}. -\subsection{Requirements} - -\section{tools - The Command Line Lnterface} +\section{tools - The Command Line Interface} \subsection{phm2pj} -\begin{description} Converts a phantom object to a set of projections -\end{description} {\tt phm2pj} simulates the process of collection of X-Ray projection data such as collected by a CT scanner. @@ -31,12 +67,9 @@ such as collected by a CT scanner. \subsection{pjrec} \subsection{phm2if} -\centerline{This is a centered line} -\begin{center} -This is a -centered paragraph. -\end{center} -{\bf This is in bold font} +\bibliographystyle{abbrv} +\bibliography{yes} + \end{document} diff --git a/include/Makefile.am b/include/Makefile.am index 15c2b69..28950d3 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,4 +1,5 @@ -noinst_HEADERS=ct.h ezplot.h pol.h sgp.h array2d.h imagefile.h backprojectors.h mpiworld.h fnetorderstream.h phantom.h timer.h sstream scanner.h projections.h ctsupport.h filter.h array2dfile.h trace.h +noinst_HEADERS=ct.h ezplot.h pol.h sgp.h array2d.h imagefile.h backprojectors.h mpiworld.h fnetorderstream.h phantom.h timer.h sstream scanner.h projections.h ctsupport.h filter.h array2dfile.h trace.h transformmatrix.h + diff --git a/include/ezplot.h b/include/ezplot.h index 30fe4e5..06601db 100644 --- a/include/ezplot.h +++ b/include/ezplot.h @@ -1,8 +1,13 @@ /***************************************************************************** +** FILE IDENTIFICATION +** +** Name: ezplot.h +** Purpose: Header file for EZplot library +** ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ezplot.h,v 1.9 2000/07/15 08:36:13 kevin Exp $ +** $Id: ezplot.h,v 1.10 2000/07/28 08:28:08 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 @@ -18,15 +23,10 @@ ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ******************************************************************************/ -/*----------------------------------------------------------------------*/ -/* EZPLOT */ -/* */ -/*----------------------------------------------------------------------*/ #ifndef __H_EZPLOT #define __H_EZPLOT - #include #include #include @@ -34,26 +34,200 @@ #include "ctsupport.h" #include "sgp.h" -#define MAXLABEL 40 /* maximum length of axis label */ -#define MAXTITLE 40 /* maximum length of a title */ -#define MAXLEGEND 20 /* maximum length of a legend */ -#define MAXCURVES 10 /* maximum number of curves that can be plotted */ -#define MAXPTS 200 /* max number of points that can be read with - DATA command in INTERACTIVE mode */ - -struct ezp_curve_st { - int numpts; - double *x, *y; - int linestyle; - int symbol; - int symfreq; - int color; - char legend[MAXLEGEND+1]; + +class EZPlotCurve { + public: + double *x; + double *y; + int m_iPointCount; + int m_iLineStyle; + int m_iSymbol; + int m_iSymbolFreq; + int m_iColor; + string m_sLegend; + + EZPlotCurve (const double* x, const double* y, int n, int color, int linestyle, int symbol, int sumbolFreq, const string& legend); + + ~EZPlotCurve(); }; -#define XBUF_DEF 600 -#define YBUF_DEF 600 -#define PRTMODE_DEF 1 +/*----------------------------------------------------------------------*/ +/* GLOBAL VARIABLES */ +/*----------------------------------------------------------------------*/ + +/* axis definitions */ +#define LINEAR 1 /* linear axis */ +#define LOG 2 /* logrithmic axis */ +#define NOAXIS 3 /* don't plot axis */ + +/* tick definitions */ +#define ABOVE 1 +#define BELOW 2 +#define RIGHT 4 +#define LEFT 8 + +/* line types */ +#define NOLINE 0 +#define SOLID 1 +#define DASH 2 +#define DASH1 10 +#define DASH2 11 +#define DASH3 12 +#define DASH4 13 + +/* symbol definitions */ +#define SB_CROSS 1 +#define SB_PLUS 2 +#define SB_BOX 3 +#define SB_CIRCLE 4 +#define SB_ERRORBAR 5 +#define MAXSYMBOL 5 + +#define INSIDE 1 /* values of o_legendbox */ +#define OUTSIDE 2 +#define NOLEGEND 3 + +/*----------------------------------------------------------------------------- + * GLOBAL VARIABLES + * + * Naming Convention: + * i_ Internal variable + * Not user changable + * o_ Option variable + * Normal variable that is user modifiable + * These variables must always have a valid value + * d_ Device variable + * Variables controlling devices + * clr_ Color variable + * Holds a color value + * c_ Character string variable + * Contains a character string + * v_ Value variable + * User modifiable variable associated with the set variable (s_) + * These variables do not always have a valid value + * These variables change assumption EZPLOT makes about the plot + * s_ Set variable. + * TRUE if associated value variable (v_) has been set by the user + *---------------------------------------------------------------------------*/ + +#include +using namespace std; + +typedef vector::iterator EZPlotCurveIterator; +typedef vector::const_iterator EZPlotCurveConstIterator; + +class SGP; +class EZPlot { + private: + vector m_vecCurves; + + // Colors + int clr_axis; /* color of all axis lines */ + int clr_title; /* color of main title */ + int clr_label; /* color of axis labels */ + int clr_legend; /* color of legend box */ + int clr_grid; /* color of grid lines */ + int clr_number; /* color of axis number labels */ + + // Options + int o_reqcurves; /* # of curves specified in CURVES command */ + /* default value is 1, so that a call to EZPLOT + will force a plot */ + bool o_unknowncurves; /* TRUE when the user specifies that the + number of curves is unknown */ + + double o_xporigin, o_yporigin; /* origin of plot frame in NDC */ + double o_xlength, o_ylength; /* length of plot frame in NDC */ + + string c_xlabel; /* label for x axis */ + string c_ylabel; /* label for y axis */ + string c_title; /* title to print above graph */ + string c_legend;; /* current legend specified */ + + int o_linestyle, o_color; /* style to use for curves all subsequent curves to EZPLOT */ + bool o_xaxis, o_yaxis; /* Specifies where axis & labels are drawn */ + bool o_grid; /* Flag to draw a grid at major ticks */ + bool o_box; /* Flag to draw a box around the graph */ + + int o_xticks, o_yticks; /* direction to draw tick marks */ + bool o_xtlabel, o_ytlabel; /* TRUE if label tick marks */ + + int o_xmajortick, o_ymajortick; /* number of major ticks to draw */ + int o_xminortick, o_yminortick; /* number of minor ticks between major ticks */ + + int o_symbol; /* Symbol type, (0 = no symbol) */ + int o_symfreq; /* frequency to draw symbols at curve points */ + + int o_legendbox; /* controls whether legend is inside or outside of the axis extents */ + int o_tag; /* controls whether to draw tag at end of axes */ + + // VALUE & SET variables + double v_xmin, v_xmax, v_ymin, v_ymax; /* user supplied axis endpoints */ + bool s_xmin, s_xmax, s_ymin, s_ymax; /* TRUE is endpoint has been set */ + double v_xtitle, v_ytitle; /* NDC position to plot title */ + bool s_xtitle, s_ytitle; /* TRUE if set position for title */ + double v_xcross, v_ycross; /* position that axes cross */ + bool s_xcross, s_ycross; /* TRUE if set axes cross position */ + double v_xlegend, v_ylegend; /* upper-left position of legend box in NDC */ + bool s_xlegend, s_ylegend; /* TRUE if set position of legend box */ + int v_lxfrac, v_lyfrac; /* number of digits to right of decimal place */ + bool s_lxfrac, s_lyfrac; /* TRUE if set number of fractional digits */ + double v_textsize; /* size of text in NDC */ + bool s_textsize; /* TRUE if user set size of text */ + + // Global variables + double charheight; /* Height of characters in NDC */ + double charwidth; /* Height of characters in NDC */ + double xp_min, xp_max, yp_min, yp_max; /* boundry of plot frame in NDC */ + double xa_min, xa_max, ya_min, ya_max; /* extent of axes in NDC */ + double xgw_min, xgw_max, ygw_min, ygw_max; /* boundary of graph in input coords */ + double xgn_min, xgn_max, ygn_min, ygn_max; /* boundy of graph in NDC */ + double xt_min, xt_max, yt_min, yt_max; /* boundary of axis ticks */ + double xl_min, xl_max, yl_min, yl_max; /* boundary of legend box */ + double title_row; /* y-coord of title row */ + double xtl_ofs; /* Offset y-coord of x tick labels from axis */ + double ytl_ofs; /* Offset x-coord of y tick labels from axis */ + double xlbl_row; /* row of x label in world coord */ + double ylbl_col; /* column of y label in world coord */ + double xw_tickinc, yw_tickinc; /* increment between major ticks in WC */ + double xn_tickinc, yn_tickinc; /* increment between major ticks in NDC */ + int x_nint, y_nint; /* number of intervals along x & y axes */ + int x_fldwid, x_frac; /* numeric field sizes & number of digits */ + int y_fldwid, y_frac; /* in fraction of number, used for printf() */ + double xtl_wid, ytl_wid; /* length of ticks labels in NDC */ + double tl_height; /* height of tick labels in NDC */ + char x_numfmt[20]; /* format to print x tick labels */ + char y_numfmt[20]; /* format to print y tick labels */ + + void drawAxes(void); + void symbol (int sym, double symwidth, double symheight); + void make_numfmt(char *fmtstr, int *fldwid, int *nfrac, double min, double max, int nint); + int axis_scale (double min, double max, int nint, double *minp, double *maxp, int *nintp); + + SGP& rSGP; + + void clearCurves (); + + bool ezcmd (char *comm); + int do_cmd(int lx); + void bad_option(char *opt); + static void initkw(void); + + int curveinteract; + static bool ezset_initialized; + + public: + EZPlot (SGP& sgp); + ~EZPlot (); + + int ezset (char *command); + + void addCurve (const float* x, const double* y, int num); + void addCurve (const double* x, const double* y, int num); + void addCurve (const double* y, int n); + + void plot (); +}; /*----------------------------------------------------------------------*/ /* Codes from LEX */ @@ -117,8 +291,6 @@ struct ezp_curve_st { #define S_CLEAR -61 #define S_STORE -62 #define S_RESTORE -63 -#define S_USTART -64 -#define S_UFINISH -65 #define S_AMARK -66 #define S_NO -67 #define S_INTERACTIVE -68 @@ -136,202 +308,7 @@ struct ezp_curve_st { #define S_LEGENDBOX -107 #define S_TAG -108 -#define S_EPSON -110 -#define S_CRT -111 - #define S_TEXTSIZE -120 -#define S_XBUF -121 -#define S_YBUF -122 -#define S_PRTMODE -123 - -/*----------------------------------------------------------------------*/ -/* GLOBAL VARIABLES */ -/*----------------------------------------------------------------------*/ - -/* axis definitions */ -#define LINEAR 1 /* linear axis */ -#define LOG 2 /* logrithmic axis */ -#define NOAXIS 3 /* don't plot axis */ - -/* tick definitions */ -#define ABOVE 1 -#define BELOW 2 -#define RIGHT 4 -#define LEFT 8 - -/* line types */ -#define NOLINE 0 -#define SOLID 1 -#define DASH 2 -#define DASH1 10 -#define DASH2 11 -#define DASH3 12 -#define DASH4 13 - -/* symbol definitions */ -#define SB_CROSS 1 -#define SB_PLUS 2 -#define SB_BOX 3 -#define SB_CIRCLE 4 -#define SB_ERRORBAR 5 -#define MAXSYMBOL 5 - -#define INSIDE 1 /* values of o_legendbox */ -#define OUTSIDE 2 -#define NOLEGEND 3 - -/*----------------------------------------------------------------------------- - * GLOBAL VARIABLES - * - * Naming Convention: - * i_ Internal variable - * Not user changable - * o_ Option variable - * Normal variable that is user modifiable - * These variables must always have a valid value - * d_ Device variable - * Variables controlling devices - * clr_ Color variable - * Holds a color value - * c_ Character string variable - * Contains a character string - * v_ Value variable - * User modifiable variable associated with the set variable (s_) - * These variables do not always have a valid value - * These variables change assumption EZPLOT makes about the plot - * s_ Set variable. - * TRUE if associated value variable (v_) has been set by the user - *---------------------------------------------------------------------------*/ - - -struct ezplot_var { - -/*-------------*/ -/* USER CURVES */ -/*-------------*/ - -struct ezp_curve_st curve[MAXCURVES]; - -/*--------------------*/ -/* INTERNAL VARIABLES */ -/*--------------------*/ - -bool i_plotimmediate; /* indicates that a call to EZPLOT is a signal - to print all received arrays. EZSET uses - this variable to force EZPLOT to replot - its stored curves */ -int i_numcurves; /* number of curves received by EZPLOT */ - -/*------------------*/ -/* DEVICE VARIABLES */ -/*------------------*/ - -bool d_usecrt; /* TRUE if want to use CRT as output device */ -bool d_useprt; /* TRUE if wamt to use printer as output device */ - -int d_crtmode; /* Controls which crt mode to use for plot */ -int d_prtmode; /* Controls mode of printer output */ - -int d_xprtbuf, d_yprtbuf; /* Size of printer buffer in pixels */ - -/*-----------------*/ -/* COLOR VARIABLES */ -/*-----------------*/ - -int clr_axis; /* color of all axis lines */ -int clr_title; /* color of main title */ -int clr_label; /* color of axis labels */ -int clr_legend; /* color of legend box */ -int clr_grid; /* color of grid lines */ -int clr_number; /* color of axis number labels */ - -/*------------------*/ -/* OPTION VARIABLES */ -/*------------------*/ - -int o_reqcurves; /* # of curves specified in CURVES command */ - /* default value is 1, so that a call to EZPLOT - will force a plot */ -bool o_unknowncurves; /* TRUE when the user specifies that the - number of curves is unknown */ - -bool o_ustart, o_ufinish; /* TRUE if user initiates or terminate sgp */ - -double o_xporigin, o_yporigin; /* origin of plot frame in NDC */ -double o_xlength, o_ylength; /* length of plot frame in NDC */ - -char c_xlabel[MAXLABEL+1]; /* label for x axis */ -char c_ylabel[MAXLABEL+1]; /* label for y axis */ -char c_title[MAXTITLE+1]; /* title to print above graph */ -char c_legend[MAXLEGEND+1]; /* current legend specified */ - -int o_linestyle, o_color; /* style to use for curves all subsequent */ - /* curves to EZPLOT */ -bool o_xaxis, o_yaxis; /* Specifies where axis & labels are drawn */ -bool o_grid; /* Flag to draw a grid at major ticks */ -bool o_box; /* Flag to draw a box around the graph */ - -int o_xticks, o_yticks; /* direction to draw tick marks */ -bool o_xtlabel, o_ytlabel; /* TRUE if label tick marks */ - -int o_xmajortick, o_ymajortick; /* number of major ticks to draw */ -int o_xminortick, o_yminortick; /* number of minor ticks between major ticks */ - -int o_symbol; /* Symbol type, (0 = no symbol) */ -int o_symfreq; /* frequency to draw symbols at curve points */ - -int o_legendbox; /* controls whether legend is inside */ - /* or outside of the axis extents */ -int o_tag; /* controls whether to draw tag at end of axes */ - -/*-----------------------*/ -/* VALUE & SET variables */ -/*-----------------------*/ - -double v_xmin, v_xmax, v_ymin, v_ymax; /* user supplied axis endpoints */ -bool s_xmin, s_xmax, s_ymin, s_ymax; /* TRUE is endpoint has been set */ - -double v_xtitle, v_ytitle; /* NDC position to plot title */ -bool s_xtitle, s_ytitle; /* TRUE if set position for title */ -double v_xcross, v_ycross; /* position that axes cross */ -bool s_xcross, s_ycross; /* TRUE if set axes cross position */ - -double v_xlegend, v_ylegend; /* upper-left position of legend box in NDC */ -bool s_xlegend, s_ylegend; /* TRUE if set position of legend box */ - -int v_lxfrac, v_lyfrac; /* number of digits to right of decimal place */ -bool s_lxfrac, s_lyfrac; /* TRUE if set number of fractional digits */ - -double v_textsize; /* size of text in NDC */ -bool s_textsize; /* TRUE if user set size of text */ - -}; /* end of EZPLOT VARIABLES */ - - - -extern struct ezplot_var ez; -extern bool ezplot_firstcall; /* set to false on first call to EZSET or EZPLOT */ - - -/* ezplot.cpp */ -SGP_ID ezplot (const float x[], const double y[], int num); -SGP_ID ezplot (const double x[], const double y[], int num); -void ezinit(void); -void ezfree(void); -void ezclear(void); - -/* ezset.cpp */ -int ezset(char *command); - -/* ezplot1d.cpp */ -void ezplot_1d(double *y, int n); - -/* makefmt.cpp */ -void make_numfmt(char *fmtstr, int *fldwid, int *nfrac, double min, double max, int nint); - -/* axis.cpp */ -int axis_scale (double min, double max, int nint, double *minp, double *maxp, int *nintp); - #endif diff --git a/include/phantom.h b/include/phantom.h index 416b833..ae6a235 100644 --- a/include/phantom.h +++ b/include/phantom.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phantom.h,v 1.10 2000/07/22 15:45:33 kevin Exp $ +** $Id: phantom.h,v 1.11 2000/07/28 08:28:08 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 @@ -30,8 +30,6 @@ #include #include "ctsupport.h" -#include "backprojectors.h" -class ImageFile; using namespace std; @@ -129,6 +127,8 @@ typedef enum { // Phantom Class Declaration ////////////////////////////////////////////////////// +class SGP; +class ImageFile; class Phantom { public: @@ -171,7 +171,7 @@ class Phantom #if HAVE_SGP void show () const; - void draw () const; + void draw (SGP& sgp) const; #endif void addStdHerman (); diff --git a/include/scanner.h b/include/scanner.h index c446280..0ab132c 100644 --- a/include/scanner.h +++ b/include/scanner.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: scanner.h,v 1.8 2000/07/22 15:45:33 kevin Exp $ +** $Id: scanner.h,v 1.9 2000/07/28 08:28:08 kevin Exp $ ** ** ** This program is free software; you can redistribute it and/or modify @@ -29,9 +29,12 @@ #ifndef SCANNER_H #define SCANNER_H +#include "trace.h" + class Projections; class Phantom; class PhantomElement; +class SGP; // Projections are collected along an array of ndet detectors. The data // for these detectors is stored in the class DetectorArray @@ -74,7 +77,7 @@ class Scanner Scanner (const Phantom& phm, const char* const geometryName, int nDet, int nView, int nSample, const double rot_anglen); ~Scanner(); - void collectProjections (Projections& proj, const Phantom& phm, const int start_view, const int trace); + void collectProjections (Projections& proj, const Phantom& phm, const int start_view, const int trace = TRACE_NONE, SGP* pSGP = NULL); void setNView (int nView); @@ -119,11 +122,11 @@ class Scanner static const int s_iGeometryCount; static const int N_EXTRA_DETECTORS=4; /* Number of extra detectors widths when calculating detlen */ - void projectSingleView (const Phantom& phm, DetectorArray& darray, const double xd1, const double yd1, const double xd2, const double yd2, const double xs1, const double ys1, const double xs2, const double ys2); + void projectSingleView (const Phantom& phm, DetectorArray& darray, const double xd1, const double yd1, const double xd2, const double yd2, const double xs1, const double ys1, const double xs2, const double ys2, SGP* pSGP); - double projectSingleLine (const Phantom& phm, const double x1, const double y1, const double x2, const double y2); + double projectSingleLine (const Phantom& phm, const double x1, const double y1, const double x2, const double y2, SGP* pSGP); - double projectLineAgainstPElem (const PhantomElement& pelem, const double x1, const double y1, const double x2, const double y2); + double projectLineAgainstPElem (const PhantomElement& pelem, const double x1, const double y1, const double x2, const double y2, SGP* pSGP); void traceShowParam (const char *label, const char *fmt, int row, int color, ...); diff --git a/include/sgp.h b/include/sgp.h index 15f0c35..b2d31ee 100644 --- a/include/sgp.h +++ b/include/sgp.h @@ -1,8 +1,15 @@ /***************************************************************************** +** FILE IDENTIFICATION +** +** Name: sgp.h +** Purpose: Header file for Simple Graphics Package +** Author: Kevin Rosenberg +** Date Started: 1984 +** ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: sgp.h,v 1.10 2000/06/19 19:04:05 kevin Exp $ +** $Id: sgp.h,v 1.11 2000/07/28 08:28:08 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 @@ -18,10 +25,6 @@ ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ******************************************************************************/ -/*----------------------------------------------------------------------*/ -/* Standard Graphics Package Header File */ -/*----------------------------------------------------------------------*/ - #ifndef __H_SGP #define __H_SGP @@ -29,7 +32,11 @@ #include "config.h" #endif -#include "ctsupport.h" +#include "transformmatrix.h" + +#ifdef HAVE_WXWINDOWS +#include +#endif #if HAVE_G2_H extern "C" { @@ -38,225 +45,168 @@ extern "C" { } #endif -/* device names */ - -#define CRTDEV 1 -#define PRTDEV 2 -#define MEMDEV 4 -#define FILEDEV 8 - -/* linestyles */ - -#define LS_NOLINE 0 -#define LS_SOLID 0xffff -#define LS_DASH1 0xff00 -#define LS_DASH2 0xf0f0 -#define LS_DASH3 0xcccc -#define LS_DASH4 0xff3e -#define LS_DOTTED 0xaaaa - -#define MAXDASH 4 -#define MAXCOLOR 63 - -/* data structures */ - -struct sgp_window_st { - int pw_xsize; /* Physical Window size */ - int pw_ysize; - char title[256]; - int g2_id; - double xw_min; /* Window extents */ - double yw_min; - double xw_max; - double yw_max; - double xv_min; /* Viewport extents */ - double yv_min; - double xv_max; - double yv_max; - double view[4]; /* Viewport array for clip_rect() */ - double curx; /* Current stylus position in world coords */ - double cury; - int recalc_mc_to_ndc; - int recalc_ndc_to_mc; - GRFMTX_2D wc_to_ndc_x; /* World coord to NDC matrix */ - GRFMTX_2D mc_to_ndc_x; /* Master to NDC */ - GRFMTX_2D ndc_to_mc_x; /* NDC to Master */ - GRFMTX_2D ctm_2_x; /* Current transfromation matrix */ - - int phys_curx; - int phys_cury; -}; +#include -typedef struct sgp_window_st SGP_WINDOW; -typedef struct sgp_window_st *SGP_ID; - -struct device_st { - int open; /* TRUE if device is open for output */ - int xsize, ysize; /* Size of device in pixels */ - int xmin, ymin; /* smallest coordinates */ - int xmax, ymax; /* Maximum coordinates */ - int colormax; /* Maximum color number of device */ - int style; /* Current linestyle of device */ - int width; /* Current width of device */ - int color; /* Current color of device */ - int icurx, icury; /* Current position */ - int icwidth, icheight; /* Size of characters in pixels */ - int cfore, cback; /* Character foregnd & backgnd colors */ - float asp; /* Aspect ratio. Multipy x coord */ - int (*dotfunc)(int x1, int y1, int color); /* Dot function for device */ - int (*linefunc)(int x1, int y1, int x2, int y2, int color); /* Line function for device */ - unsigned int nbytes; /* Size of buffer in bytes */ - char *buf; /* Pointer to buffer */ - unsigned int bufseg, bufoff; /* Buffer memory location */ - int mode; /* Device mode */ -}; -struct charsp_st { - float width, height; /* size of characters in NDC */ - float textangle; /* text angle in radians */ - float charupangle; /* character up angle */ - int font; /* font for characters */ - int updir, textdir; /* text direct & character orientation */ - int fore, back; /* foreground & background color */ - /* if back = -1, then transparent back */ -}; +class SGPDriver { +private: + int m_iPhysicalXSize; + int m_iPhysicalYSize; + string m_sWindowTitle; + int m_idDriver; + +#ifdef HAVE_WXWINDOWS + wxDC* m_pDC; +#endif + int m_idG2; + +public: + enum { + SGPDRIVER_WXWINDOWS = 1, + SGPDRIVER_G2 = 2, + SGPDRIVER_OPENGL = 4, + }; + +#ifdef HAVE_WXWINDOWS + SGPDriver (wxDC* pDC, const char* szWinTitle = "", int xsize = 640, int ysize = 480); +#endif + + SGPDriver (const char* szWinTitle = "", int xsize = 640, int ysize = 480); + + ~SGPDriver (); + + int getPhysicalXSize () const + { return m_iPhysicalXSize; } + + int getPhysicalYSize () const + { return m_iPhysicalYSize; } + + const string& getWindowTitle () const + { return m_sWindowTitle; } -struct state_st { - int foregnd, backgnd; /* current foregound & background colors */ - int linestyle; /* current 16 bit linestyle */ - int linewidth; /* current width of line (in pixels) */ - int marktype; /* current marker type */ - int markcolor; /* current marker color */ - float xndc, yndc; /* current position in NDC */ + bool isWX () const + { return (m_idDriver & SGPDRIVER_WXWINDOWS); } + + bool isG2 () const + { return (m_idDriver & SGPDRIVER_G2); } + + int idG2 () const + { return m_idG2; } + +#ifdef HAVE_WXWINDOWS + wxDC* idWX () const + { return m_pDC; } +#endif }; -typedef struct device_st DEVICE; -typedef struct charsp_st CHARSPEC; -typedef struct state_st GRFSTATE; - -struct point {double x, y, z;}; - - -/* Constants */ - -/* Flagcodes for motion directions */ -#define XPLUS 001 /* right */ -#define XMINUS 002 /* left */ -#define YPLUS 004 /* up */ -#define YMINUS 010 /* down */ - -/* Codes for marker symbols */ -#define POINT 0 /* small dot */ -#define SQUARE 1 /* empty square */ -#define FSQUARE 2 /* filled square */ -#define DIAMOND 3 /* empty diamond */ -#define FDIAMOND 4 /* filled diamond */ -#define CROSS 5 /* cross */ -#define XCROSS 6 /* x */ -#define CERCLE 7 /* open circle */ -#define FCERCLE 8 /* filled circle */ -#define BSQUARE 9 /* big open square */ -#define BDIAMOND 10 /* big open diamond */ - -#define NMARKERS 11 /* Number of available symbol types */ - -/*-------------------------------------------------------------------------*/ - -#define PSET 0 /* codes for raster merging */ -#define PRESET 1 -#define OR 2 -#define AND 3 -#define XOR 4 - -/*-------------------------------------------------------------------------*/ - -/* circle.cpp */ -void sgp2_draw_circle(const double r); -void sgp2_draw_arc(double start, double stop, const double r); - -/* ctm.cpp */ -void ctm_xlat_pre_2(double x, double y); -void ctm_xlat_post_2(double x, double y); -void ctm_scale_pre_2(double sx, double sy); -void ctm_scale_post_2(double sx, double sy); -void ctm_rotate_pre_2(double theta); -void ctm_rotate_post_2(double theta); -void ctm_shear_pre_2(double shrx, double shry); -void ctm_shear_post_2(double shrx, double shry); -void xlat_gmtx_2(GRFMTX_2D m, double x, double y); -void scale_gmtx_2(GRFMTX_2D m, double sx, double sy); -void shear_gmtx_2(GRFMTX_2D m, double shrx, double shry); -void rotate_gmtx_2(GRFMTX_2D m, double theta); -void ident_gmtx_2(GRFMTX_2D m); -void mult_gmtx_2(GRFMTX_2D a, GRFMTX_2D b, GRFMTX_2D c); -void invert_gmtx_2(GRFMTX_2D a, GRFMTX_2D b); -double determ_gmtx_2(GRFMTX_2D a); - -/* drawbox.cpp */ -void sgp2_draw_rect (double xmin, double ymin, double xmax, double ymax); - -/* sgp.cpp */ -SGP_ID sgp2_init (int xsize, int ysize, const char *title); -void sgp2_close (SGP_ID gid); -void sgp2_set_active_win (SGP_ID); -SGP_ID sgp2_get_active_win (void); -void sgp2_clear (void); -void sgp2_window(double xmin, double ymin, double xmax, double ymax); -void sgp2_viewport(double xmin, double ymin, double xmax, double ymax); -void sgp2_frame_vpt(void); -void calc_wc_to_ndc(void); -void calc_ndc_to_mc(void); -void wc_to_ndc(double xw, double yw, double *xn, double *yn); -void ndc_to_wc(double xn, double yn, double *xw, double *yw); -void sgp2_color(int icol); -void sgp2_line_style(int style); -void sgp2_line_abs(double x, double y); -void sgp2_move_abs(double x, double y); -void sgp2_line_rel(double x, double y); -void sgp2_move_rel(double x, double y); -void sgp2_draw_text(char *message); -void sgp2_polyline_abs(double x[], double y[], int n); -void sgp2_mark_abs(double x, double y); -void sgp2_mark_rel(double x, double y); -void sgp2_point_abs(double x, double y); -void sgp2_point_rel(double x, double y); -void charsize(double wid, double height); -void textangle(double angle); -void ctm_clr_2(void); -void ctm_get_2(GRFMTX_2D m); -void ctm_set_2(GRFMTX_2D m); -void ctm_pre_mult_2(GRFMTX_2D m); -void ctm_post_mult_2(GRFMTX_2D m); - -/* sgpdrive.cpp */ -int _sgp2_init_dev(SGP_ID gid); -int initdevice(int dev, int mode, int xsize, int ysize); -int opendevice(int dev); -void closedevice(int dev); -void termdevice(int dev); -void _sgp2_stylus(SGP_ID gid, double x, double y, int beam); -void pntndc (SGP_ID gid, double x, double y); -void markndc (SGP_ID gid, double x, double y); -GRFSTATE *inqstate(void); -void gp_set_aspect(int dev, double asp); -void setlinestyle(int style); -void setlinewidth(int wid); -DEVICE *inqdev(int dev); -void _sgp2_set_text(SGP_ID gid, double width, double height, double textangle, int font); -void settextclr(int fore, int back); -void setcolor(int fore); -void setbackg(int back); -int initmarker(int marker, int color); -int settextdir(int direction); -void _sgp2_dev_text(SGP_ID gid, char *message); -void termgrf2(void); -void flushdevice(int dev); - -/* sgptext.cpp */ -void wrtsymbol(int sym, int x, int y, DEVICE *dev); -void wrtchar(int ch, int x, int y, CHARSPEC *cspec, DEVICE *dev); -void wrttext(char txtstr[], int x, int y, CHARSPEC *cspec, DEVICE *dev); -void crtcolor(int mode, int *f, int *b); + +class SGP { +private: + int m_iPhysicalXSize; // Physical Window size + int m_iPhysicalYSize; + const SGPDriver m_driver; + + double xw_min; // Window extents + double yw_min; + double xw_max; + double yw_max; + double xv_min; // Viewport extents + double yv_min; + double xv_max; + double yv_max; + double viewNDC[4]; // Viewport array for clip_rect() + + int m_iCurrentPhysicalX; + int m_iCurrentPhysicalY; + double m_dCurrentWorldX; + double m_dCurrentWorldY; + double m_dTextAngle; + bool m_bRecalcTransform; + + // Master coordinates are coordinates before CTM transformation + // World coordinates are coordinates defined by setWindow() + // Normalized device coordinates range from 0. to 1. in both axes + TransformationMatrix2D wc_to_ndc; // World coord to NDC matrix + TransformationMatrix2D mc_to_ndc; // Master to NDC + TransformationMatrix2D ndc_to_mc; // NDC to Master + TransformationMatrix2D m_ctm; // Current transfromation matrix + + void calc_transform (); + +public: + enum { // linestyles + LS_NOLINE = 0, + LS_SOLID = 0xffff, + LS_DASH1 = 0xff00, + LS_DASH2 = 0xf0f0, + LS_DASH3 = 0xcccc, + LS_DASH4 = 0xff3e, + LS_DOTTED = 0xaaaa, + }; + + enum { // Codes for marker symbols + MARK_POINT = 0, // small dot + MARK_SQUARE = 1, // empty square + MARK_FSQUARE = 2, // filled square + MARK_DIAMOND = 3, // empty diamond + MARK_FDIAMOND = 4, // filled diamond + MARK_CROSS = 5, // cross + MARK_XCROSS = 6, // x + MARK_CIRCLE = 7, // open circle + MARK_FCIRCLE = 8, // filled circle + MARK_BSQUARE = 9, // big open square + MARK_BDIAMOND = 10, // big open diamond + }; + static const int MARK_COUNT = 11; + static const unsigned char MARKER_BITMAP[MARK_COUNT][5]; + + SGP (const SGPDriver& driver); + + void drawCircle (const double r); + void drawArc (double start, double stop, const double r); + void drawRect (double xmin, double ymin, double xmax, double ymax); + void lineAbs(double x, double y); + void moveAbs(double x, double y); + void lineRel(double x, double y); + void moveRel(double x, double y); + void drawText(const char *szMessage); + void drawText(const string& rsMessage); + void polylineAbs(double x[], double y[], int n); + void markerAbs (double x, double y); + void markerRel(double x, double y); + void pointAbs(double x, double y); + void pointRel(double x, double y); + + void eraseWindow (); + void setWindow (double xmin, double ymin, double xmax, double ymax); + void setViewport (double xmin, double ymin, double xmax, double ymax); + void frameViewport(); + + void setColor (int icol); + void setLineStyle (int style); + void setTextSize (double height); + void setTextAngle (double angle); + void setTextColor (int iFGcolor, int iBGcolor); + void setMarker (int idMarker, int color); + + void ctmClear (); + void ctmSet (const TransformationMatrix2D& m); + void preTranslate (double x, double y); + void postTranslate (double x, double y); + void preScale (double sx, double sy); + void postScale (double sx, double sy); + void preRotate (double theta); + void postRotate (double theta); + void preShear (double shrx, double shry); + void postShear (double shrx, double shry); + void transformNDCtoMC (double* x, double* y); + void transformMCtoNDC (double* x, double* y); + void transformMCtoNDC (double xIn, double yIn, double* xOut, double* yOut); + + void stylusNDC (double x, double y, bool beam); + void pointNDC (double x, double y); + void markerNDC (double x, double y); +}; #endif diff --git a/include/transformmatrix.h b/include/transformmatrix.h new file mode 100644 index 0000000..5274b30 --- /dev/null +++ b/include/transformmatrix.h @@ -0,0 +1,60 @@ +/***************************************************************************** +** FILE IDENTIFICATION +** +** Name: sgp.h +** Purpose: Header file for Simple Graphics Package +** Author: Kevin Rosenberg +** Date Started: 1984 +** +** This is part of the CTSim program +** Copyright (C) 1983-2000 Kevin Rosenberg +** +** $Id: transformmatrix.h,v 1.1 2000/07/28 08:28:08 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 +** published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +******************************************************************************/ + +#ifndef __H_TRANSFORMMATRIX +#define __H_TRANSFORMMATRIX + +class ostream; +class TransformationMatrix2D { +public: + double mtx[3][3]; + + TransformationMatrix2D () {}; + TransformationMatrix2D (double m[3][3]); + + void setIdentity(); + void setTranslate (double x, double y); + void setScale (double sx, double sy); + void setShear (double shrx, double shry); + void setRotate (double theta); + + double determinant () const; + + const TransformationMatrix2D invert () const; + + void transformPoint (double *pX, double *pY) const; + + void print (ostream& ostr) const; + + friend const TransformationMatrix2D operator* (const TransformationMatrix2D& lhs, const TransformationMatrix2D& rhs); + +}; + + +const TransformationMatrix2D operator* (const TransformationMatrix2D& lhs, const TransformationMatrix2D& rhs); + +#endif diff --git a/libctgraphics/Makefile.am b/libctgraphics/Makefile.am index 5daeb60..a7f9f27 100644 --- a/libctgraphics/Makefile.am +++ b/libctgraphics/Makefile.am @@ -1,5 +1,5 @@ noinst_LIBRARIES = libctgraphics.a -libctgraphics_a_SOURCES=ezplot.cpp ezsupport.cpp ezset.cpp ezpol.cpp ctm.cpp sgp.cpp sgpdriver.cpp sgptext.cpp +libctgraphics_a_SOURCES=ezplot.cpp ezset.cpp ezpol.cpp sgp.cpp transformmatrix.cpp INCLUDES=@my_includes@ EXTRA_DIST=Makefile.nt diff --git a/libctgraphics/ezplot.cpp b/libctgraphics/ezplot.cpp index 7b7bb55..6ffd0b0 100644 --- a/libctgraphics/ezplot.cpp +++ b/libctgraphics/ezplot.cpp @@ -6,7 +6,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ezplot.cpp,v 1.6 2000/07/15 08:36:13 kevin Exp $ +** $Id: ezplot.cpp,v 1.7 2000/07/28 08:28:08 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 @@ -23,162 +23,171 @@ ******************************************************************************/ #include "ezplot.h" -#include "algo.h" +#include -static int plot (SGP_ID *gid); -static void drawaxis(void); -static void symbol (int sym, double symwidth, double symheight); +// Defaults +static const double TICKRATIO = 0.4; // ratio of minor to major tick lengths +static const int MAXNUMFMT = 15; // maximum length of a numeric format +static const double DEF_CHARHEIGHT = (1./43.); //size of characters in NDC +static const double DEF_CHARWIDTH = (1./80.); // size of characters in NDC +static const int DEF_CURVE_CLR = C_YELLOW; -/*-------------------------------------*/ -/* GLOBAL variables for EZPLOT & EZSET */ -/*-------------------------------------*/ -bool ezplot_firstcall = TRUE; /* set to false on first call to EZSET or EZPLOT */ -struct ezplot_var ez; /* ezplot variables */ -/*----------------*/ -/* DEFAULT values */ -/*----------------*/ - -#define TICKRATIO 0.4 /* ratio of minor to major tick lengths */ -#define MAXNUMFMT 15 /* maximum length of a numeric format */ - -#define DEF_CRTMODE 0 /*GM_HIGHRES*/ /* default crt mode */ -#define DEF_CHARHEIGHT (1./43.) /* default size of characters in NDC */ -#define DEF_CHARWIDTH (1./80.) - -#define DEF_CURVE_CLR C_YELLOW - - -/*----------------------------------------------------------------------*/ -/* GLOBAL VARIABLES */ -/*----------------------------------------------------------------------*/ - -static -double charwidth, charheight; /* Size of characters in NDC */ - -static -double xp_min, xp_max, - yp_min, yp_max; /* boundry of plot frame in NDC */ -static -double xa_min, xa_max, - ya_min, ya_max; /* extent of axes in NDC */ -static -double xgw_min, xgw_max, - ygw_min, ygw_max; /* boundary of graph in input coords */ -static -double xgn_min, xgn_max, - ygn_min, ygn_max; /* boundy of graph in NDC */ -static -double xt_min, xt_max, - yt_min, yt_max; /* boundary of axis ticks */ - -static -double xl_min, xl_max, - yl_min, yl_max; /* boundary of legend box */ - -static double title_row; /* y-coord of title row */ - -static double xtl_ofs; /* Offset y-coord of x tick labels from axis */ -static double ytl_ofs; /* Offset x-coord of y tick labels from axis */ - -static double xlbl_row; /* row of x label in world coord */ -static double ylbl_col; /* column of y label in world coord */ - -static -double xw_tickinc, yw_tickinc; /* increment between major ticks in WC */ - -static -double xn_tickinc, yn_tickinc; /* increment between major ticks in NDC */ +EZPlotCurve::EZPlotCurve (const double* xData, const double* yData, int n, int color, int linestyle, int symbol, int symfreq, const string& legend) + : x(NULL), y(NULL), m_sLegend (legend) +{ + x = new double [n]; + y = new double [n]; + +#if 1 + for (int i = 0; i < n; i++) { + x[i] = xData[i]; + y[i] = yData[i]; + } +#else + int copyCount = n * sizeof(double); + memcpy (x, xData, copyCount); + memcpy (y, yData, copyCount); +#endif + m_iPointCount = n; + m_iColor = color; + m_iLineStyle = linestyle; + m_iSymbol = symbol; + m_iSymbolFreq = symfreq; +} -static int x_nint, y_nint; /* number of intervals along x & y axes */ -static int x_fldwid, x_frac; /* numeric field sizes & number of digits */ -static int y_fldwid, y_frac; /* in fraction of number, used for printf() */ +EZPlotCurve::~EZPlotCurve () +{ + delete x; + delete y; +} -static double xtl_wid, ytl_wid; /* length of ticks labels in NDC */ -static double tl_height; /* height of tick labels in NDC */ -static char x_numfmt[20]; /* format to print x tick labels */ -static char y_numfmt[20]; /* format to print y tick labels */ +void +EZPlot::addCurve (const double *y, int n) +{ + double x [n]; + for (int i = 0; i < n; i++) + x[i] = i; -/*---------------------------------------------------------------------- - * FUNCTION IDENTICIFATION - * - * Name: EZPLOT - * Programmer: Kevin Rosenberg - * Date: 5-83 Version 1 - * 11-84 Version 2 - * - * SYNOPSIS - * ezplot (x, y, n) - * double x[] x-coordinates of point makeing up a curve - * double y[] y-coordinates of points makeing up a curve - * int n Number of points in curve - * - * DESCRIPTION - * This is a sophisticated plotting program. - * - *----------------------------------------------------------------------*/ + addCurve (x, y, n); +} -SGP_ID -ezplot (const float x[], const double y[], int num) +void +EZPlot::addCurve (const float x[], const double y[], int num) { double dx [num]; for (int i = 0; i < num; i++) dx[i] = x[i]; - return ezplot (dx, y, num); + addCurve (dx, y, num); } -SGP_ID -ezplot (const double x[], const double y[], int num) +void +EZPlot::addCurve (const double x[], const double y[], int num) { - unsigned int size; - SGP_ID gid = NULL; + if (num < 1) + return; - if (ez.i_plotimmediate == TRUE) { - plot (&gid); - return (gid); - } + int iNumCurves = m_vecCurves.size(); - if (num < 1) - return (NULL); + if (o_unknowncurves == FALSE && iNumCurves >= o_reqcurves) + clearCurves (); - if (ezplot_firstcall == TRUE) - ezinit(); + if (o_unknowncurves == TRUE || iNumCurves < o_reqcurves) { + EZPlotCurve* pCurve = new EZPlotCurve (x, y, num, o_color, o_linestyle, o_symbol, o_symfreq, c_legend); + m_vecCurves.push_back (pCurve); + } + + iNumCurves = m_vecCurves.size(); // recalculate + if (o_unknowncurves == FALSE && iNumCurves >= o_reqcurves) { + plot (); + clearCurves (); + } +} - if (ez.o_unknowncurves == FALSE && ez.i_numcurves >= ez.o_reqcurves) - ezclear (); - if (ez.i_numcurves < MAXCURVES && - (ez.o_unknowncurves == TRUE || ez.i_numcurves < ez.o_reqcurves)) { - size = num * sizeof(double); - ez.curve[ez.i_numcurves].x = new double [size]; - ez.curve[ez.i_numcurves].y = new double [size]; - for (int i = 0; i < num; i++) { - ez.curve[ez.i_numcurves].x[i] = x[i]; - ez.curve[ez.i_numcurves].y[i] = y[i]; - } - ez.curve[ez.i_numcurves].numpts = num; - ez.curve[ez.i_numcurves].color = ez.o_color; - ez.curve[ez.i_numcurves].linestyle = ez.o_linestyle; - ez.curve[ez.i_numcurves].symbol = ez.o_symbol; - ez.curve[ez.i_numcurves].symfreq = ez.o_symfreq; - strncpy (ez.curve[ez.i_numcurves].legend, ez.c_legend, MAXLEGEND); - ++ez.i_numcurves; - } - - if (ez.o_unknowncurves == FALSE && ez.i_numcurves >= ez.o_reqcurves) { - plot (&gid); - ezclear (); - } +EZPlot::~EZPlot () +{ + for (EZPlotCurveIterator i = m_vecCurves.begin(); i != m_vecCurves.end(); i++) + delete *i; +} + +void +EZPlot::clearCurves () +{ + for (EZPlotCurveIterator i = m_vecCurves.begin(); i != m_vecCurves.end(); i++) delete *i; + m_vecCurves.erase (m_vecCurves.begin(), m_vecCurves.end()); +} + - return (gid); +EZPlot::EZPlot (SGP& sgp) + : rSGP (sgp) +{ + curveinteract = -1; + + charwidth = DEF_CHARWIDTH; + charheight = DEF_CHARHEIGHT; + + c_xlabel = "X axis"; + c_ylabel = "Y axis"; + c_title = ""; + c_legend = ""; + + o_reqcurves = 1; + o_unknowncurves = FALSE; + + o_xporigin = 0.0; + o_yporigin = 0.0; + o_xlength = 1.0; + o_ylength = 1.0; + + o_xaxis = LINEAR; + o_yaxis = LINEAR; + + o_grid = FALSE; + o_box = FALSE; + + o_xmajortick = 10; + o_ymajortick = 8; + o_xminortick = 4; + o_yminortick = 4; + + o_color = DEF_CURVE_CLR; + o_symfreq = 1; + o_symbol = -1; + o_linestyle = SGP::LS_SOLID; + + o_xtlabel = TRUE; + o_ytlabel = TRUE; + o_xticks = BELOW; + o_yticks = LEFT; + + o_legendbox = INSIDE; + o_tag = FALSE; + + s_xtitle = FALSE; + s_ytitle = FALSE; + s_xcross = FALSE; + s_ycross = FALSE; + s_lxfrac = FALSE; + s_lyfrac = FALSE; + s_xlegend = FALSE; + s_ylegend = FALSE; + s_textsize = FALSE; + + clr_axis = C_WHITE; /* set fixed colors */ + clr_title = (C_CYAN+8); + clr_label = (C_CYAN+8); + clr_legend = (C_RED+8); + clr_number = (C_GREEN+8); + clr_grid = (C_BLACK+8); } @@ -195,731 +204,760 @@ ezplot (const double x[], const double y[], int num) * EZPLOT() only * * CALLS - * drawaxis() & make_numfmt() + * drawAxes() & make_numfmt() */ -static int plot (SGP_ID *gid) +void +EZPlot::plot () { - double xmin, xmax; /* extend of curves in world coord */ - double ymin, ymax; - double x_added_ticks; /* number of tick spaces added to axis */ - double y_added_ticks; - double symwidth, symheight; /* size of symbol in NDC */ - double leg_width, leg_height; /* size of legend box */ - int num_leg; /* number of legend titles */ - int max_leg; /* longest legend in characters */ - int i, j, ip, ic, n; - - if (ez.i_numcurves <= 0) - return (FALSE); - - if (ez.o_ustart == FALSE && *gid == NULL) { - *gid = sgp2_init (0, 0, "Ezplot"); + double x_added_ticks; /* number of tick spaces added to axis */ + double y_added_ticks; + double symwidth, symheight; /* size of symbol in NDC */ + double leg_width, leg_height; /* size of legend box */ + int i, j, ip, n; + + if (m_vecCurves.size() <= 0) + return; + + if (s_textsize == TRUE) + charheight = v_textsize; + else + charheight = DEF_CHARHEIGHT; + + const EZPlotCurve& firstCurve = *m_vecCurves[0]; + double xmin = firstCurve.x[0]; // extent of curves in world coord + double xmax = xmin; + double ymin = firstCurve.y[0]; + double ymax = ymin; + + for (EZPlotCurveConstIterator iterCurve = m_vecCurves.begin(); iterCurve != m_vecCurves.end(); iterCurve++) { + const EZPlotCurve& curve = **iterCurve; + + for (ip = 0; ip < curve.m_iPointCount; ip++) { + if (curve.x[ip] > xmax) + xmax = curve.x[ip]; + else if (curve.x[ip] < xmin) + xmin = curve.x[ip]; + if (curve.y[ip] > ymax) + ymax = curve.y[ip]; + else if (curve.y[ip] < ymin) + ymin = curve.y[ip]; } + } + + // extend graph limits for user defined axis cross positions + if (s_xcross == TRUE) { + if (v_xcross < xmin) + xmin = v_xcross; + else if (v_xcross > xmax) + xmax = v_xcross; + } - if (ez.s_textsize == TRUE) - charheight = ez.v_textsize; - else - charheight = DEF_CHARHEIGHT; - - gp_set_aspect (CRTDEV, 1.0); + if (s_ycross == TRUE) { + if (v_ycross < ymin) + ymin = v_ycross; + else if (v_ycross > ymax) + ymax = v_ycross; + } - xmin = xmax = ez.curve[0].x[0]; - ymin = ymax = ez.curve[0].y[0]; + /* find nice endpoints for axes */ + axis_scale (xmin, xmax, o_xmajortick - 1, &xgw_min, &xgw_max, &x_nint); + axis_scale (ymin, ymax, o_ymajortick - 1, &ygw_min, &ygw_max, &y_nint); - for (ic = 0; ic < ez.i_numcurves; ic++) { - for (ip = 0; ip < ez.curve[ic].numpts; ip++) { - if (ez.curve[ic].x[ip] > xmax) - xmax = ez.curve[ic].x[ip]; - else if (ez.curve[ic].x[ip] < xmin) - xmin = ez.curve[ic].x[ip]; - if (ez.curve[ic].y[ip] > ymax) - ymax = ez.curve[ic].y[ip]; - else if (ez.curve[ic].y[ip] < ymin) - ymin = ez.curve[ic].y[ip]; - } - } + /* check if user set x-axis extents */ + if (s_xmin == TRUE) { + xgw_min = v_xmin; + x_nint = o_xmajortick - 1; + } + if (s_xmax == TRUE) { + xgw_max = v_xmax; + x_nint = o_xmajortick - 1; + } + + /* check if user set y-axis extents */ + if (s_ymin == TRUE) { + ygw_min = v_ymin; + y_nint = o_ymajortick - 1; + } + if (s_ymax == TRUE) { + ygw_max = v_ymax; + y_nint = o_ymajortick - 1; + } - /* extend graph limits for user defined axis cross positions */ + /* calculate increment between major axis in world coordinates */ + xw_tickinc = (xgw_max - xgw_min) / x_nint; + yw_tickinc = (ygw_max - ygw_min) / y_nint; - if (ez.s_xcross == TRUE) - { - if (ez.v_xcross < xmin) - xmin = ez.v_xcross; - else if (ez.v_xcross > xmax) - xmax = ez.v_xcross; - } + /* we have now calcuated xgw_min, xyw_max, ygw_min, & ygw_max */ + + // set the number of decimal point to users' setting or default + // Two formats for numbers: Fixed: -nnn.f and Exponent: -n.fffE+eee + if (s_lxfrac == TRUE) + x_frac = v_lxfrac; + else + x_frac = -1; - if (ez.s_ycross == TRUE) - { - if (ez.v_ycross < ymin) - ymin = ez.v_ycross; - else if (ez.v_ycross > ymax) - ymax = ez.v_ycross; - } + if (s_lyfrac == TRUE) + y_frac = v_lyfrac; + else + y_frac = -1; - /* find nice endpoints for axes */ - - axis_scale (xmin, xmax, ez.o_xmajortick - 1, &xgw_min, &xgw_max, &x_nint); - axis_scale (ymin, ymax, ez.o_ymajortick - 1, &ygw_min, &ygw_max, &y_nint); + make_numfmt (x_numfmt, &x_fldwid, &x_frac, xgw_min, xgw_max, x_nint); + make_numfmt (y_numfmt, &y_fldwid, &y_frac, ygw_min, ygw_max, y_nint); - /* check if user set x-axis extents */ + xtl_wid = x_fldwid * charwidth; /* calc size of tick labels */ + ytl_wid = y_fldwid * charwidth; + tl_height = charheight; + + /* calculate the extent of the plot frame */ + xp_min = o_xporigin; + yp_min = o_yporigin; + xp_max = xp_min + o_xlength; + yp_max = yp_min + o_ylength; + + xp_min = clamp (xp_min, 0., 1.); + xp_max = clamp (xp_max, 0., 1.); + yp_min = clamp (yp_min, 0., 1.); + yp_max = clamp (yp_max, 0., 1.); + + xa_min = xp_min; /* extent of axes */ + xa_max = xp_max; + ya_min = yp_min; + ya_max = yp_max; - if (ez.s_xmin == TRUE) { - xgw_min = ez.v_xmin; - x_nint = ez.o_xmajortick - 1; + /* adjust frame for title */ + if (c_title.length() > 0) + ya_max -= 2.5 * charheight; + title_row = ya_max + 0.5 * charheight; + + /* calculate legend box boundaries */ + int max_leg = 0; /* longest legend in characters */ + int num_leg = 0; /* number of legend titles */ + for (EZPlotCurveConstIterator iterCurve = m_vecCurves.begin(); iterCurve != m_vecCurves.end(); iterCurve++) { + const EZPlotCurve& curve = **iterCurve; + if ((n = curve.m_sLegend.length()) > 0) { + ++num_leg; + max_leg = max (max_leg, n); } - if (ez.s_xmax == TRUE) { - xgw_max = ez.v_xmax; - x_nint = ez.o_xmajortick - 1; - } - - /* check if user set y-axis extents */ + } + + if (num_leg > 0 && o_legendbox != NOLEGEND) { + leg_width = (max_leg + 2) * charwidth; + leg_height = num_leg * 3 * charheight; - if (ez.s_ymin == TRUE) { - ygw_min = ez.v_ymin; - y_nint = ez.o_ymajortick - 1; + if (s_xlegend == TRUE) + xl_max = v_xlegend; + else { + xl_max = xa_max; + if (o_legendbox == OUTSIDE) + xa_max -= (leg_width + 0.5 * charwidth); } - if (ez.s_ymax == TRUE) { - ygw_max = ez.v_ymax; - y_nint = ez.o_ymajortick - 1; - } - - /* calculate increment between major axis in world coordinates */ + xl_min = xl_max - leg_width; - xw_tickinc = (xgw_max - xgw_min) / x_nint; - yw_tickinc = (ygw_max - ygw_min) / y_nint; - - /* we have now calcuated xgw_min, xyw_max, ygw_min, & ygw_max */ - - /* set the number of decimal point to users' setting or default */ - /* Two formats for numbers - Fixed: -nnn.f - Exponent: -n.fffE+eee - */ - - if (ez.s_lxfrac == TRUE) - x_frac = ez.v_lxfrac; - else - x_frac = -1; - - if (ez.s_lyfrac == TRUE) - y_frac = ez.v_lyfrac; + if (s_ylegend == TRUE) + yl_max = v_ylegend; else - y_frac = -1; - - make_numfmt (x_numfmt, &x_fldwid, &x_frac, xgw_min, xgw_max, x_nint); - make_numfmt (y_numfmt, &y_fldwid, &y_frac, ygw_min, ygw_max, y_nint); - - xtl_wid = x_fldwid * charwidth; /* calc size of tick labels */ - ytl_wid = y_fldwid * charwidth; - tl_height = charheight; - - /* calculate the extent of the plot frame */ - - xp_min = ez.o_xporigin; - yp_min = ez.o_yporigin; - xp_max = xp_min + ez.o_xlength; - yp_max = yp_min + ez.o_ylength; - - xp_min = clamp (xp_min, 0., 1.); - xp_max = clamp (xp_max, 0., 1.); - yp_min = clamp (yp_min, 0., 1.); - yp_max = clamp (yp_max, 0., 1.); - - xa_min = xp_min; /* extent of axes */ - xa_max = xp_max; - ya_min = yp_min; - ya_max = yp_max; + yl_max = ya_max; - /* adjust frame for title */ - - if (strlen(ez.c_title) != 0) - ya_max -= 2.5 * charheight; - title_row = ya_max + 0.5 * charheight; - - /* calculate legend box boundaries */ - - max_leg = 0; /* longest legend in characters */ - num_leg = 0; /* number of legend titles */ - for (i = 0; i < ez.i_numcurves; i++) - if ((n = strlen(ez.curve[i].legend)) > 0) { - ++num_leg; - max_leg = max(max_leg, n); - } - - if (num_leg > 0 && ez.o_legendbox != NOLEGEND) { - leg_width = (max_leg + 2) * charwidth; - leg_height = num_leg * 3 * charheight; - - if (ez.s_xlegend == TRUE) - xl_max = ez.v_xlegend; - else { - xl_max = xa_max; - if (ez.o_legendbox == OUTSIDE) - xa_max -= (leg_width + 0.5 * charwidth); - } - xl_min = xl_max - leg_width; - - if (ez.s_ylegend == TRUE) - yl_max = ez.v_ylegend; - else - yl_max = ya_max; - - yl_min = yl_max - leg_height; - - sgp2_window (xl_min, yl_min, xl_max, yl_max); - sgp2_viewport (xl_min, yl_min, xl_max, yl_max); - - sgp2_color (ez.clr_legend); - sgp2_draw_rect (xl_min, yl_min, xl_max, yl_max); - - n = 0; /* current legend position */ - for (i = 0; i < ez.i_numcurves; i++) { - double xmin, xmax, xinc, y; - - if (strlen(ez.curve[i].legend) == 0) - continue; - - xmin = xl_min + 1.0 * charwidth; - xmax = xl_max - 1.0 * charwidth; - y = yl_max - (2.0 + n * 3) * charheight; - - sgp2_move_abs (xmin, y + 0.5 * charheight); - sgp2_draw_text (ez.curve[i].legend); - sgp2_color (ez.curve[i].color); - if (ez.curve[i].linestyle != LS_NOLINE) { - sgp2_line_style (ez.curve[i].linestyle); - sgp2_move_abs (xmin, y); - sgp2_line_abs (xmax, y); - } - if (ez.curve[i].symbol > 0) { - xinc = (xmax - xmin) / (5 - 1); - sgp2_line_style (LS_SOLID); - for (j = 0; j < 5; j++) { - sgp2_move_abs (xmin + j * xinc, y); - symbol(ez.curve[i].symbol, - 0.5 * charwidth, 0.5 * charheight); - } - } - ++n; /* move to next legend position */ - } - } /* end legend printing */ - - /* calculate the extent of the axes */ - - /*-------------------------*/ - /* adjust frame for labels */ - /*-------------------------*/ + yl_min = yl_max - leg_height; - /* x-label */ + rSGP.setWindow (xl_min, yl_min, xl_max, yl_max); + rSGP.setViewport (xl_min, yl_min, xl_max, yl_max); + rSGP.setColor (clr_legend); + rSGP.drawRect (xl_min, yl_min, xl_max, yl_max); - if (strlen(ez.c_xlabel) > 0) - ya_min += 3.0 * charheight; - xlbl_row = xp_min; /* put x-label on bottom of plot frame */ - - /* y-label */ - - if (strlen(ez.c_ylabel) > 0) - xa_min += 3.0 * charwidth; /* reverse charsize because writing */ - /* text sideways */ - ylbl_col = xp_min + 2 * charwidth; - - /*------------------------------*/ - /* adjust frame for tick labels */ - /*------------------------------*/ - - /* calc offset of tick labels from axes */ - - if (ez.o_xaxis == NOAXIS || ez.o_xtlabel == FALSE) - xtl_ofs = 0.0; - else if (ez.o_xticks == BELOW) - xtl_ofs = -2.5 * charheight; - else if (ez.o_xticks == ABOVE) - xtl_ofs = 1.5 * charheight; - - if (ez.o_yaxis == NOAXIS || ez.o_ytlabel == FALSE) - ytl_ofs = 0.0; - else if (ez.o_yticks == LEFT) - ytl_ofs = -(1 + y_fldwid) * charwidth; - else if (ez.o_yticks == RIGHT) - ytl_ofs = 1.5 * charwidth; - - /* see if need to shrink axis extents and/or tick extents */ + n = 0; /* current legend position */ + for (EZPlotCurveIterator iterCurve = m_vecCurves.begin(); iterCurve != m_vecCurves.end(); iterCurve++) { + const EZPlotCurve& curve = **iterCurve; + + if (curve.m_sLegend.length() == 0) + continue; - if (xtl_ofs != 0.0 && ez.s_ycross == FALSE) { - if (ez.o_xticks == BELOW) { - ya_min += 2.5 * charheight; - yt_min = ya_min; - } else if (ez.o_xticks == ABOVE) { - ya_min += 0.0; - yt_min = ya_min + 2.5 * charheight; + double xmin = xl_min + 1.0 * charwidth; + double xmax = xl_max - 1.0 * charwidth; + double y = yl_max - (2.0 + n * 3) * charheight; + + rSGP.moveAbs (xmin, y + 0.5 * charheight); + rSGP.drawText (curve.m_sLegend); + rSGP.setColor (curve.m_iColor); + if (curve.m_iLineStyle != SGP::LS_NOLINE) { + rSGP.setLineStyle (curve.m_iLineStyle); + rSGP.moveAbs (xmin, y); + rSGP.lineAbs (xmax, y); } - } else /* noaxis, no t-labels, or user set cross */ - yt_min = ya_min; - - if (ytl_ofs != 0.0 && ez.s_xcross == FALSE) { - if (ez.o_yticks == LEFT) { - xa_min += (1 + y_fldwid) * charwidth; - xt_min = xa_min; - } else if (ez.o_yticks == RIGHT) { - xa_min += 0.0; - xt_min = xa_min + ytl_ofs + y_fldwid * charwidth; + if (curve.m_iSymbol > 0) { + double xinc = (xmax - xmin) / (5 - 1); + rSGP.setLineStyle (SGP::LS_SOLID); + for (j = 0; j < 5; j++) { + rSGP.moveAbs (xmin + j * xinc, y); + symbol(curve.m_iSymbol, 0.5 * charwidth, 0.5 * charheight); } - } else - xt_min = xa_min; - - xt_max = xa_max; - yt_max = ya_max; - - /* decrease size of graph, if necessary, to accommadate space */ - /* between axis boundary and boundary of ticks */ - - x_added_ticks = -1; - y_added_ticks = -1; - - if (ez.o_xaxis == NOAXIS || ez.o_xtlabel == FALSE) - x_added_ticks = 0; - if (ez.o_yaxis == NOAXIS || ez.o_ytlabel == FALSE) - y_added_ticks = 0; - - if (ez.o_grid == TRUE) { - if (x_added_ticks < 0) - x_added_ticks = 2; - if (y_added_ticks < 0) - y_added_ticks = 2; + } + ++n; /* move to next legend position */ } - - if (x_added_ticks < 0) - { - if (ez.o_yticks == LEFT || ez.s_ycross) - x_added_ticks = 1; - else - x_added_ticks = 2; - } - - if (y_added_ticks < 0) - { - if (ez.o_xticks == BELOW || ez.s_xcross) - y_added_ticks = 1; - else - y_added_ticks = 2; - } - - xn_tickinc = (xt_max - xt_min) / (x_nint + x_added_ticks); - yn_tickinc = (yt_max - yt_min) / (y_nint + y_added_ticks); - - xt_min += 0.5 * x_added_ticks * xn_tickinc; - xt_max -= 0.5 * x_added_ticks * xn_tickinc; - yt_min += 0.5 * y_added_ticks * yn_tickinc; - yt_max -= 0.5 * y_added_ticks * yn_tickinc; - - xgn_min = xt_min; - xgn_max = xt_max; - ygn_min = yt_min; - ygn_max = yt_max; - - /*---------------------------------------------------------------------------*/ - - /* PLOT CURVES */ - - sgp2_line_style (LS_SOLID); - drawaxis(); - - /* Convert WC in graph boundary to axis boundary */ - { - double xmin, xmax, ymin, ymax; - - sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max); /* Graph boundary */ - sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max); - - ndc_to_wc (xa_min, ya_min, &xmin, &ymin); /* calc WC of axis */ - ndc_to_wc (xa_max, ya_max, &xmax, &ymax); /* boundaries */ - - sgp2_window (xmin, ymin, xmax, ymax); /* Set window to axis */ - sgp2_viewport (xa_min, ya_min, xa_max, ya_max); /* boundaries */ + } /* end legend printing */ + + /* calculate the extent of the axes */ + + /*-------------------------*/ + /* adjust frame for labels */ + /*-------------------------*/ + + /* x-label */ + if (c_xlabel.length() > 0) + ya_min += 3.0 * charheight; + xlbl_row = xp_min; /* put x-label on bottom of plot frame */ + + /* y-label */ + if (c_ylabel.length() > 0) + xa_min += 3.0 * charwidth; /* reverse rSGP.setTextSize because writing text sideways */ + ylbl_col = xp_min + 2 * charwidth; + + /*------------------------------*/ + /* adjust frame for tick labels */ + /*------------------------------*/ + + /* calc offset of tick labels from axes */ + if (o_xaxis == NOAXIS || o_xtlabel == FALSE) + xtl_ofs = 0.0; + else if (o_xticks == BELOW) + xtl_ofs = -2.5 * charheight; + else if (o_xticks == ABOVE) + xtl_ofs = 1.5 * charheight; + + if (o_yaxis == NOAXIS || o_ytlabel == FALSE) + ytl_ofs = 0.0; + else if (o_yticks == LEFT) + ytl_ofs = -(1 + y_fldwid) * charwidth; + else if (o_yticks == RIGHT) + ytl_ofs = 1.5 * charwidth; + + /* see if need to shrink axis extents and/or tick extents */ + if (xtl_ofs != 0.0 && s_ycross == FALSE) { + if (o_xticks == BELOW) { + ya_min += 2.5 * charheight; + yt_min = ya_min; + } else if (o_xticks == ABOVE) { + ya_min += 0.0; + yt_min = ya_min + 2.5 * charheight; } - - symwidth = charwidth * (xgw_max - xgw_min); - symheight = charheight * (ygw_max - ygw_min); - - for (ic = 0; ic < ez.i_numcurves; ic++) { - sgp2_color (ez.curve[ic].color); - if (ez.curve[ic].linestyle != LS_NOLINE) { - sgp2_line_style (ez.curve[ic].linestyle); - sgp2_polyline_abs (ez.curve[ic].x, ez.curve[ic].y, ez.curve[ic].numpts); - } - if (ez.curve[ic].symbol > 0) { - sgp2_line_style(LS_SOLID); - sgp2_move_abs (ez.curve[ic].x[0], ez.curve[ic].y[0]); - symbol (ez.curve[ic].symbol, symwidth, symheight); - for (i = 1; i < ez.curve[ic].numpts; i++) - if (i % ez.curve[ic].symfreq == 0 || i == ez.curve[ic].numpts - 1) { - sgp2_move_abs (ez.curve[ic].x[i], ez.curve[ic].y[i]); - symbol (ez.curve[ic].symbol, symwidth, symheight); - } - } + } else /* noaxis, no t-labels, or user set cross */ + yt_min = ya_min; + + if (ytl_ofs != 0.0 && s_xcross == FALSE) { + if (o_yticks == LEFT) { + xa_min += (1 + y_fldwid) * charwidth; + xt_min = xa_min; + } else if (o_yticks == RIGHT) { + xa_min += 0.0; + xt_min = xa_min + ytl_ofs + y_fldwid * charwidth; } + } else + xt_min = xa_min; + + xt_max = xa_max; + yt_max = ya_max; + + /* decrease size of graph, if necessary, to accommadate space */ + /* between axis boundary and boundary of ticks */ + + x_added_ticks = -1; + y_added_ticks = -1; + + if (o_xaxis == NOAXIS || o_xtlabel == FALSE) + x_added_ticks = 0; + if (o_yaxis == NOAXIS || o_ytlabel == FALSE) + y_added_ticks = 0; + + if (o_grid == TRUE) { + if (x_added_ticks < 0) + x_added_ticks = 2; + if (y_added_ticks < 0) + y_added_ticks = 2; + } + + if (x_added_ticks < 0) { + if (o_yticks == LEFT || s_ycross) + x_added_ticks = 1; + else + x_added_ticks = 2; + } + + if (y_added_ticks < 0) { + if (o_xticks == BELOW || s_xcross) + y_added_ticks = 1; + else + y_added_ticks = 2; + } + + xn_tickinc = (xt_max - xt_min) / (x_nint + x_added_ticks); + yn_tickinc = (yt_max - yt_min) / (y_nint + y_added_ticks); + + xt_min += 0.5 * x_added_ticks * xn_tickinc; + xt_max -= 0.5 * x_added_ticks * xn_tickinc; + yt_min += 0.5 * y_added_ticks * yn_tickinc; + yt_max -= 0.5 * y_added_ticks * yn_tickinc; + + xgn_min = xt_min; + xgn_max = xt_max; + ygn_min = yt_min; + ygn_max = yt_max; + + /*---------------------------------------------------------------------------*/ + + /* PLOT CURVES */ + + rSGP.setLineStyle (SGP::LS_SOLID); + drawAxes(); + + /* Convert WC in graph boundary to axis boundary */ + rSGP.setWindow (xgw_min, ygw_min, xgw_max, ygw_max); /* Graph boundary */ + rSGP.setViewport (xgn_min, ygn_min, xgn_max, ygn_max); - if (ez.o_ufinish == FALSE) - termgrf2 (); - - return (TRUE); + double xminTemp = xa_min, xmaxTemp = xa_max; + double yminTemp = ya_min, ymaxTemp = ya_max; + rSGP.transformNDCtoMC (&xminTemp, &yminTemp); // calc WC to axis boundaries + rSGP.transformNDCtoMC (&yminTemp, &ymaxTemp); + + rSGP.setWindow (xminTemp, yminTemp, xmaxTemp, ymaxTemp); // Set window to axis boundaries + rSGP.setViewport (xa_min, ya_min, xa_max, ya_max); + + symwidth = charwidth * (xgw_max - xgw_min); + symheight = charheight * (ygw_max - ygw_min); + + for (EZPlotCurveIterator iterCurve = m_vecCurves.begin(); iterCurve != m_vecCurves.end(); iterCurve++) { + const EZPlotCurve& curve = **iterCurve; + + rSGP.setColor (curve.m_iColor); + if (curve.m_iLineStyle != SGP::LS_NOLINE) { + rSGP.setLineStyle (curve.m_iLineStyle); + rSGP.polylineAbs (curve.x, curve.y, curve.m_iPointCount); + } + if (curve.m_iSymbol > 0) { + rSGP.setLineStyle (SGP::LS_SOLID); + rSGP.moveAbs (curve.x[0], curve.y[0]); + symbol (curve.m_iSymbol, symwidth, symheight); + for (i = 1; i < curve.m_iPointCount; i++) + if (i % curve.m_iSymbolFreq == 0 || i == curve.m_iPointCount - 1) { + rSGP.moveAbs (curve.x[i], curve.y[i]); + symbol (curve.m_iSymbol, symwidth, symheight); + } + } + } } /* NAME - * drawaxis INTERNAL routine to draw axis & label them + * drawAxes INTERNAL routine to draw axis & label them * * SYNOPSIS - * drawaxis() + * drawAxes() */ -static void drawaxis(void) + +void +EZPlot::drawAxes(void) { - double xticklen = 0, yticklen = 0; /* length of ticks in NDC */ - double minorinc; /* increment between minor axes */ - double xaxispos, yaxispos; /* crossing of axes */ - double x, y, x2, y2; - bool axis_near; /* TRUE if axis too close to print t-label */ - int i, j; - char str[100]; - char *numstr; - - charsize (charwidth, charheight); - settextclr (1, -1); - - if (ez.o_xticks == ABOVE) - xticklen = charheight; - else if (ez.o_xticks == BELOW) - xticklen = -charheight; - - if (ez.o_yticks == RIGHT) - yticklen = charwidth; - else if (ez.o_yticks == LEFT) - yticklen = -charwidth; - - sgp2_window (xp_min, yp_min, xp_max, yp_max); - sgp2_viewport (xp_min, yp_min, xp_max, yp_max); - - if (strlen (ez.c_title) != 0) { - sgp2_move_abs (xa_min + (xa_max-xa_min)/2 - strlen(ez.c_title)*charwidth, title_row); - charsize (charwidth * 2.0, charheight * 2.0); - settextclr (ez.clr_title, -1); - sgp2_draw_text (ez.c_title); - charsize (charwidth, charheight); + double xticklen = 0, yticklen = 0; /* length of ticks in NDC */ + double minorinc; /* increment between minor axes */ + double xaxispos, yaxispos; /* crossing of axes */ + double x, y, x2, y2; + bool axis_near; /* TRUE if axis too close to print t-label */ + int i, j; + char str[100]; + char *numstr; + + rSGP.setTextSize (charheight); + rSGP.setTextColor (1, -1); + + if (o_xticks == ABOVE) + xticklen = charheight; + else if (o_xticks == BELOW) + xticklen = -charheight; + + if (o_yticks == RIGHT) + yticklen = charwidth; + else if (o_yticks == LEFT) + yticklen = -charwidth; + + rSGP.setWindow (xp_min, yp_min, xp_max, yp_max); + rSGP.setViewport (xp_min, yp_min, xp_max, yp_max); + + if (c_title.length() > 0) { + rSGP.moveAbs (xa_min + (xa_max-xa_min)/2 - c_title.length()*charwidth, title_row); + rSGP.setTextSize (charheight * 2.0); + rSGP.setTextColor (clr_title, -1); + rSGP.drawText (c_title); + rSGP.setTextSize (charheight); + } + + if (o_grid == TRUE || o_box == TRUE) { + rSGP.setColor (clr_axis); + rSGP.moveAbs (xa_min, ya_min); + rSGP.lineAbs (xa_max, ya_min); + rSGP.lineAbs (xa_max, ya_max); + rSGP.lineAbs (xa_min, ya_max); + rSGP.lineAbs (xa_min, ya_min); + } + + /* calculate position of axes */ + + /* x-axis */ + if (s_ycross == TRUE) { /* convert users' world-coord */ + xaxispos = v_ycross; /* axis to its position in NDC */ + rSGP.setWindow (xgw_min, ygw_min, xgw_max, ygw_max); + rSGP.setViewport (xgn_min, ygn_min, xgn_max, ygn_max); + x = xgw_min; + rSGP.transformMCtoNDC (x, xaxispos, &x, &xaxispos); + } else + xaxispos = ya_min; + + /* y-axis */ + if (s_xcross == TRUE) { /* convert users' world-coord */ + yaxispos = v_xcross; /* axis to its NDC position */ + rSGP.setWindow (xgw_min, ygw_min, xgw_max, ygw_max); + rSGP.setViewport (xgn_min, ygn_min, xgn_max, ygn_max); + y = ygw_min; + rSGP.transformMCtoNDC (yaxispos, y, &yaxispos, &y); + } else + yaxispos = xa_min; + + /*-------------*/ + /* draw x-axis */ + /*-------------*/ + + if (o_xaxis == LINEAR) { + rSGP.setWindow (xp_min, yp_min, xp_max, yp_max); + rSGP.setViewport (xp_min, yp_min, xp_max, yp_max); + + /* draw axis line */ + + rSGP.setColor (clr_axis); + if (o_tag && !o_grid && !o_box && s_xcross) { + rSGP.moveAbs (xa_min, xaxispos - charheight); + rSGP.lineAbs (xa_min, xaxispos + charheight); } - - if (ez.o_grid == TRUE || ez.o_box == TRUE) { - sgp2_color (ez.clr_axis); - sgp2_move_abs (xa_min, ya_min); - sgp2_line_abs (xa_max, ya_min); - sgp2_line_abs (xa_max, ya_max); - sgp2_line_abs (xa_min, ya_max); - sgp2_line_abs (xa_min, ya_min); + rSGP.moveAbs (xa_min, xaxispos); + rSGP.lineAbs (xa_max, xaxispos); + if (o_tag && !o_grid && !o_box) { + rSGP.moveAbs (xa_max, xaxispos - charheight); + rSGP.lineAbs (xa_max, xaxispos + charheight); } - - /* calculate position of axes */ - - /* x-axis */ - if (ez.s_ycross == TRUE) { /* convert users' world-coord */ - xaxispos = ez.v_ycross; /* axis to its position in NDC */ - sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max); - sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max); - x = xgw_min; - wc_to_ndc (x, xaxispos, &x, &xaxispos); - } else - xaxispos = ya_min; - - /* y-axis */ - if (ez.s_xcross == TRUE) { /* convert users' world-coord */ - yaxispos = ez.v_xcross; /* axis to its NDC position */ - sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max); - sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max); - y = ygw_min; - wc_to_ndc (yaxispos, y, &yaxispos, &y); - } else - yaxispos = xa_min; - - /*-------------*/ - /* draw x-axis */ - /*-------------*/ - - if (ez.o_xaxis == LINEAR) { - sgp2_window (xp_min, yp_min, xp_max, yp_max); - sgp2_viewport (xp_min, yp_min, xp_max, yp_max); - - /* draw axis line */ - - sgp2_color (ez.clr_axis); - if (ez.o_tag && !ez.o_grid && !ez.o_box && ez.s_xcross) { - sgp2_move_abs (xa_min, xaxispos - charheight); - sgp2_line_abs (xa_min, xaxispos + charheight); + + if (o_grid == TRUE) { + rSGP.setColor (clr_grid); + for (i = 0; i <= x_nint; i++) { + rSGP.moveAbs (xt_min + xn_tickinc * i, ya_max); + rSGP.lineAbs (xt_min + xn_tickinc * i, ya_min); + } + } + rSGP.moveAbs (xa_min + (xa_max-xa_min)/2 - c_xlabel.length()*charwidth, xlbl_row); + rSGP.setTextSize (charheight * 2.0); + rSGP.setTextColor (clr_label, -1); + rSGP.drawText (c_xlabel); + rSGP.setTextSize (charheight); + minorinc = xn_tickinc / (o_xminortick + 1); + + for (i = 0; i <= x_nint; i++) { + x = xt_min + xn_tickinc * i; + rSGP.setColor (clr_axis); + rSGP.moveAbs (x, xaxispos); + rSGP.lineAbs (x, xaxispos + xticklen); + if (i != x_nint) + for (j = 1; j <= o_xminortick; j++) { + x2 = x + minorinc * j; + rSGP.moveAbs (x2, xaxispos); + rSGP.lineAbs (x2, xaxispos + TICKRATIO * xticklen); } - sgp2_move_abs (xa_min, xaxispos); - sgp2_line_abs (xa_max, xaxispos); - if (ez.o_tag && !ez.o_grid && !ez.o_box) { - sgp2_move_abs (xa_max, xaxispos - charheight); - sgp2_line_abs (xa_max, xaxispos + charheight); + axis_near = FALSE; + if (xaxispos + xtl_ofs > ya_min && o_yaxis != NOAXIS) { + double xw, x, y, d; + + xw = xgw_min + i * xw_tickinc; + rSGP.setWindow (xgw_min, ygw_min, xgw_max, ygw_max); + rSGP.setViewport (xgn_min, ygn_min, xgn_max, ygn_max); + rSGP.transformMCtoNDC (xw, y, &x, &y); + rSGP.setWindow (xp_min, yp_min, xp_max, yp_max); + rSGP.setViewport (xp_min, yp_min, xp_max, yp_max); + d = x - yaxispos; + if (o_yticks == RIGHT && d >= 0 && d < 0.9 * xn_tickinc) + axis_near = TRUE; + if (o_yticks == LEFT && d <= 0 && d > -0.9 * xn_tickinc) + axis_near = TRUE; + } + + if (o_xtlabel == TRUE && axis_near == FALSE) { + snprintf (str, sizeof(str), x_numfmt, xgw_min + xw_tickinc * i); + numstr = str_skip_head (str, " "); + rSGP.moveAbs (x-strlen(numstr)*charwidth/2,xaxispos + xtl_ofs); + rSGP.setTextColor (clr_number, -1); + rSGP.drawText (numstr); + } + } + } /* x - axis */ + + + /*--------*/ + /* y-axis */ + /*--------*/ + + if (o_yaxis == LINEAR) { + rSGP.setWindow (xp_min, yp_min, xp_max, yp_max); + rSGP.setViewport (xp_min, yp_min, xp_max, yp_max); + + rSGP.setColor (clr_axis); + if (o_tag && !o_grid && !o_box && s_ycross) { + rSGP.moveAbs (yaxispos - charwidth, ya_min); + rSGP.lineAbs (yaxispos + charwidth, ya_min); + } + rSGP.moveAbs (yaxispos, ya_min); + rSGP.lineAbs (yaxispos, ya_max); + if (o_tag && !o_grid && !o_box) { + rSGP.moveAbs (yaxispos - charwidth, ya_max); + rSGP.lineAbs (yaxispos + charwidth, ya_max); + } + + if (o_grid == TRUE) { + rSGP.setColor (clr_grid); + for (i = 0; i <= y_nint; i++) { + y = yt_min + yn_tickinc * i; + rSGP.moveAbs (xa_max, y); + rSGP.lineAbs (xa_min, y); + } + } + rSGP.moveAbs (ylbl_col,ya_min + (ya_max-ya_min)/2 - c_ylabel.length()*charheight); + rSGP.setTextAngle (HALFPI); + rSGP.setTextSize (2 * charheight); + rSGP.setTextColor (clr_label, -1); + rSGP.drawText (c_ylabel); + rSGP.setTextAngle (0.0); + rSGP.setTextSize (charheight); + minorinc = yn_tickinc / (o_yminortick + 1); + + for (i = 0; i <= y_nint; i++) { + y = yt_min + yn_tickinc * i; + rSGP.setColor (clr_axis); + rSGP.moveAbs (yaxispos, y); + rSGP.lineAbs (yaxispos + yticklen, y); + if (i != y_nint) + for (j = 1; j <= o_yminortick; j++) { + y2 = y + minorinc * j; + rSGP.moveAbs (yaxispos, y2); + rSGP.lineAbs (yaxispos + TICKRATIO * yticklen, y2); } + axis_near = FALSE; + if (yaxispos + ytl_ofs > xa_min && o_xaxis != NOAXIS) { + double yw, x, y, d; + + yw = ygw_min + i * yw_tickinc; + rSGP.setWindow (xgw_min, ygw_min, xgw_max, ygw_max); + rSGP.setViewport (xgn_min, ygn_min, xgn_max, ygn_max); + rSGP.transformMCtoNDC (x, yw, &x, &y); + rSGP.setWindow (xp_min, yp_min, xp_max, yp_max); + rSGP.setViewport (xp_min, yp_min, xp_max, yp_max); + d = y - xaxispos; + if (o_xticks == ABOVE && d >= 0 && d < 0.9 * yn_tickinc) + axis_near = TRUE; + if (o_xticks == BELOW && d <= 0 && d > -0.9 * yn_tickinc) + axis_near = TRUE; + } + if (o_ytlabel == TRUE && axis_near == FALSE) { + snprintf (str, sizeof(str), y_numfmt, ygw_min + yw_tickinc * i); + rSGP.moveAbs (yaxispos + ytl_ofs, y - 0.5 * charheight); + rSGP.setTextColor (clr_number, -1); + rSGP.drawText (str); + } + } + } /* y - axis */ +} - if (ez.o_grid == TRUE) { - sgp2_color (ez.clr_grid); - for (i = 0; i <= x_nint; i++) { - sgp2_move_abs (xt_min + xn_tickinc * i, ya_max); - sgp2_line_abs (xt_min + xn_tickinc * i, ya_min); - } - } - sgp2_move_abs (xa_min + (xa_max-xa_min)/2 - strlen(ez.c_xlabel)*charwidth, xlbl_row); - charsize (charwidth * 2.0, charheight * 2.0); - settextclr (ez.clr_label, -1); - sgp2_draw_text (ez.c_xlabel); - charsize (charwidth, charheight); - minorinc = xn_tickinc / (ez.o_xminortick + 1); - - for (i = 0; i <= x_nint; i++) { - x = xt_min + xn_tickinc * i; - sgp2_color (ez.clr_axis); - sgp2_move_abs (x, xaxispos); - sgp2_line_abs (x, xaxispos + xticklen); - if (i != x_nint) - for (j = 1; j <= ez.o_xminortick; j++) { - x2 = x + minorinc * j; - sgp2_move_abs (x2, xaxispos); - sgp2_line_abs (x2, xaxispos + TICKRATIO * xticklen); - } - axis_near = FALSE; - if (xaxispos + xtl_ofs > ya_min && ez.o_yaxis != NOAXIS) { - double xw, x, y, d; - - xw = xgw_min + i * xw_tickinc; - sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max); - sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max); - wc_to_ndc (xw, y, &x, &y); - sgp2_window (xp_min, yp_min, xp_max, yp_max); - sgp2_viewport (xp_min, yp_min, xp_max, yp_max); - d = x - yaxispos; - if (ez.o_yticks == RIGHT && d >= 0 && d < 0.9 * xn_tickinc) - axis_near = TRUE; - if (ez.o_yticks == LEFT && d <= 0 && d > -0.9 * xn_tickinc) - axis_near = TRUE; - } - - if (ez.o_xtlabel == TRUE && axis_near == FALSE) { - snprintf (str, sizeof(str), x_numfmt, xgw_min + xw_tickinc * i); - numstr = str_skip_head (str, " "); - sgp2_move_abs (x-strlen(numstr)*charwidth/2,xaxispos + xtl_ofs); - settextclr (ez.clr_number, -1); - sgp2_draw_text (numstr); - } - } - } /* x - axis */ +void +EZPlot::symbol (int sym, double symwidth, double symheight) +{ + if (sym <= 0) + return; + + if (sym == SB_CROSS) { + rSGP.moveRel (-0.5 * symwidth, -0.5 * symheight); + rSGP.lineRel (symwidth, symheight); + rSGP.moveRel (-symwidth, 0.0); + rSGP.lineRel (symwidth, -symheight); + rSGP.moveRel (-0.5 * symwidth, 0.5 * symheight); + } else if (sym == SB_PLUS) { + rSGP.moveRel (-0.5 * symwidth, 0.0); + rSGP.lineRel (symwidth, 0.0); + rSGP.moveRel (-0.5 * symwidth, -0.5 * symheight); + rSGP.lineRel (0.0, symheight); + rSGP.moveRel (0.0, -0.5 * symheight); + } else if (sym == SB_BOX) { + rSGP.moveRel (-0.5 * symwidth, -0.5 * symheight); + rSGP.lineRel (symwidth, 0.0); + rSGP.lineRel (0.0, symheight); + rSGP.lineRel (-symwidth, 0.0); + rSGP.lineRel (0.0, -symheight); + rSGP.moveRel (0.5 * symwidth, 0.5 * symheight); + } else if (sym == SB_CIRCLE) { + rSGP.drawCircle (symwidth); + } else if (sym == SB_ERRORBAR) { + rSGP.moveRel (-0.5 * symwidth, 0.5 * symheight); + rSGP.lineRel (symwidth, 0.0); + rSGP.moveRel (-0.5 * symwidth, 0.0); + rSGP.lineRel (0.0, -symheight); + rSGP.moveRel (-0.5 * symwidth, 0.0); + rSGP.lineRel (symwidth, 0.0); + rSGP.moveRel (-0.5 * symwidth, 0.5 * symheight); + } +} - /*--------*/ - /* y-axis */ - /*--------*/ - if (ez.o_yaxis == LINEAR) { - sgp2_window (xp_min, yp_min, xp_max, yp_max); - sgp2_viewport (xp_min, yp_min, xp_max, yp_max); - sgp2_color (ez.clr_axis); - if (ez.o_tag && !ez.o_grid && !ez.o_box && ez.s_ycross) { - sgp2_move_abs (yaxispos - charwidth, ya_min); - sgp2_line_abs (yaxispos + charwidth, ya_min); - } - sgp2_move_abs (yaxispos, ya_min); - sgp2_line_abs (yaxispos, ya_max); - if (ez.o_tag && !ez.o_grid && !ez.o_box) { - sgp2_move_abs (yaxispos - charwidth, ya_max); - sgp2_line_abs (yaxispos + charwidth, ya_max); - } +/* NAME + * axis_scale calculates graph axis scaling + * + * SYNOPSIS: + * retval = axis_scale (min, max, nint, minp, maxp, nintp, + * rec_total, rec_frac) + * + * INPUT: + * double min Smallest value to plot + * double max Largest value to plot + * int nint Number of intervals desired + * + * OUTPUT: + * int retval FALSE if illegal parameters, else TRUE + * double *minp Minimum graph value + * double *maxp Maximum graph value + * int *nintp Number of intervals for graph + * int *rec_total Recommended field width for printing out the number + * int *rec_frac Recommended number of digits for print fraction + */ - if (ez.o_grid == TRUE) { - sgp2_color (ez.clr_grid); - for (i = 0; i <= y_nint; i++) { - y = yt_min + yn_tickinc * i; - sgp2_move_abs (xa_max, y); - sgp2_line_abs (xa_min, y); - } - } - sgp2_move_abs (ylbl_col,ya_min + (ya_max-ya_min)/2 - strlen(ez.c_ylabel)*charheight); - textangle (HALFPI); - charsize (2 * charheight, 2 * charwidth); /* axis reversed */ - settextclr (ez.clr_label, -1); - sgp2_draw_text (ez.c_ylabel); - textangle (0.0); - charsize (charwidth, charheight); - minorinc = yn_tickinc / (ez.o_yminortick + 1); - - for (i = 0; i <= y_nint; i++) { - y = yt_min + yn_tickinc * i; - sgp2_color (ez.clr_axis); - sgp2_move_abs (yaxispos, y); - sgp2_line_abs (yaxispos + yticklen, y); - if (i != y_nint) - for (j = 1; j <= ez.o_yminortick; j++) { - y2 = y + minorinc * j; - sgp2_move_abs (yaxispos, y2); - sgp2_line_abs (yaxispos + TICKRATIO * yticklen, y2); - } - axis_near = FALSE; - if (yaxispos + ytl_ofs > xa_min && ez.o_xaxis != NOAXIS) { - double yw, x, y, d; - - yw = ygw_min + i * yw_tickinc; - sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max); - sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max); - wc_to_ndc (x, yw, &x, &y); - sgp2_window (xp_min, yp_min, xp_max, yp_max); - sgp2_viewport (xp_min, yp_min, xp_max, yp_max); - d = y - xaxispos; - if (ez.o_xticks == ABOVE && d >= 0 && d < 0.9 * yn_tickinc) - axis_near = TRUE; - if (ez.o_xticks == BELOW && d <= 0 && d > -0.9 * yn_tickinc) - axis_near = TRUE; - } - if (ez.o_ytlabel == TRUE && axis_near == FALSE) { - snprintf (str, sizeof(str), y_numfmt, ygw_min + yw_tickinc * i); - sgp2_move_abs (yaxispos + ytl_ofs, y - 0.5 * charheight); - settextclr (ez.clr_number, -1); - sgp2_draw_text (str); - } - } - } /* y - axis */ +int +EZPlot::axis_scale (double min, double max, int nint, double *minp, double *maxp, int *nintp) +{ + if (min >= max || nint < 1) { + sys_error (ERR_WARNING, "Invalid params: min=%lf, min=%lf, num intervals=%d [axis_scale]", min, max, nint); + return (FALSE); + } + + double eps = 0.025; + double a = fabs(min); + if (fabs(min) < fabs(max)) + a = fabs(max); + double scale = pow (10.0, floor(log10(a))); + loop: + double mina = min / scale; + double maxa = max / scale; + double d = (maxa - mina) / nint; + double j = d * eps; + double e = floor (log10(d)); + double f = d / pow (10.0, e); + double v = 10.0; + if (f < sqrt(2.0)) + v = 1.0; + else if (f < sqrt (10.0)) + v = 2.0; + else if (f < sqrt (50.0)) + v = 5.0; + double wdt = v * pow (10.0, e); + double g = floor (mina / wdt); + if (fabs(g + 1 - mina / wdt) < j) + g = g + 1; + *minp = wdt * g; + double h = floor (maxa / wdt) + 1.0; + if (fabs(maxa / wdt + 1 - h) < j) + h = h - 1; + *maxp = wdt * h; + *nintp = static_cast(h - g); + if (fabs(*maxp) >= 10.0 || fabs(*minp) >= 10.0) { + scale = scale * 10.0; + goto loop; + } + + *minp *= scale; + *maxp *= scale; + + return (TRUE); } -static void -symbol (int sym, double symwidth, double symheight) +/* NAME + * make_numfmt Make a numeric format string + * + * SYNOPSIS + * make_numfmt (fmtstr, fldwid, nfrac, min, max, nint) + * char *fmtstr Returned format string for printf() + * int *fldwid Returned field width + * int *nfrac If < 0, then calculate best number of + * fraction places & return that value + * If >= 0, then use that number of places + * double min Minimum value + * double max Maximum value + * int nint Number of intervals between min & max + * + * DESCRIPTION + * This routine is written as an INTERNAL routine for EZPLOT + */ + +static inline double +trunc (double x) { - if (sym <= 0) - return; - - if (sym == SB_CROSS) { - sgp2_move_rel (-0.5 * symwidth, -0.5 * symheight); - sgp2_line_rel (symwidth, symheight); - sgp2_move_rel (-symwidth, 0.0); - sgp2_line_rel (symwidth, -symheight); - sgp2_move_rel (-0.5 * symwidth, 0.5 * symheight); - } else if (sym == SB_PLUS) { - sgp2_move_rel (-0.5 * symwidth, 0.0); - sgp2_line_rel (symwidth, 0.0); - sgp2_move_rel (-0.5 * symwidth, -0.5 * symheight); - sgp2_line_rel (0.0, symheight); - sgp2_move_rel (0.0, -0.5 * symheight); - } else if (sym == SB_BOX) { - sgp2_move_rel (-0.5 * symwidth, -0.5 * symheight); - sgp2_line_rel (symwidth, 0.0); - sgp2_line_rel (0.0, symheight); - sgp2_line_rel (-symwidth, 0.0); - sgp2_line_rel (0.0, -symheight); - sgp2_move_rel (0.5 * symwidth, 0.5 * symheight); - } else if (sym == SB_CIRCLE) { - sgp2_draw_circle (symwidth); - } else if (sym == SB_ERRORBAR) { - sgp2_move_rel (-0.5 * symwidth, 0.5 * symheight); - sgp2_line_rel (symwidth, 0.0); - sgp2_move_rel (-0.5 * symwidth, 0.0); - sgp2_line_rel (0.0, -symheight); - sgp2_move_rel (-0.5 * symwidth, 0.0); - sgp2_line_rel (symwidth, 0.0); - sgp2_move_rel (-0.5 * symwidth, 0.5 * symheight); - } + double integer; + + modf (x, &integer); + + return (integer); } - -void ezinit(void) +void +EZPlot::make_numfmt (char *fmtstr, int *fldwid, int *nfrac, double minval, double maxval, int nint) { - /* EZPLOT Variables */ + int wid, frac, expon; - charwidth = DEF_CHARWIDTH; /* KR_FIX: Make these ez.o_ variables */ - charheight = DEF_CHARHEIGHT; + double delta = (maxval - minval) / nint; + double absmin = fabs(minval); + double absmax = fabs(maxval); + double logt = log10( max(absmin, absmax) ); - /* EZPLOT & EZSET Variables */ - - strcpy (ez.c_xlabel, "X axis"); - strcpy (ez.c_ylabel, "Y axis"); - strcpy (ez.c_title, ""); - strcpy (ez.c_legend, ""); - - ezplot_firstcall = FALSE; - - ez.i_numcurves = 0; - ez.i_plotimmediate = FALSE; - - ez.o_reqcurves = 1; - ez.o_unknowncurves = FALSE; - - ez.o_ustart = FALSE; - ez.o_ufinish = FALSE; - - ez.o_xporigin = 0.0; - ez.o_yporigin = 0.0; - ez.o_xlength = 1.0; - ez.o_ylength = 1.0; - - ez.o_xaxis = LINEAR; - ez.o_yaxis = LINEAR; - - ez.o_grid = FALSE; - ez.o_box = FALSE; - - ez.o_xmajortick = 10; - ez.o_ymajortick = 8; - ez.o_xminortick = 4; - ez.o_yminortick = 4; - - ez.o_color = DEF_CURVE_CLR; - ez.o_symfreq = 1; - ez.o_symbol = -1; - ez.o_linestyle = LS_SOLID; - - ez.o_xtlabel = TRUE; - ez.o_ytlabel = TRUE; - ez.o_xticks = BELOW; - ez.o_yticks = LEFT; - - ez.o_legendbox = INSIDE; - ez.o_tag = FALSE; - - ez.s_xtitle = FALSE; - ez.s_ytitle = FALSE; - ez.s_xcross = FALSE; - ez.s_ycross = FALSE; - ez.s_lxfrac = FALSE; - ez.s_lyfrac = FALSE; - ez.s_xlegend = FALSE; - ez.s_ylegend = FALSE; - ez.s_textsize = FALSE; - - ez.d_usecrt = TRUE; - ez.d_useprt = FALSE; - ez.d_crtmode = DEF_CRTMODE; - ez.d_prtmode = PRTMODE_DEF; - ez.d_xprtbuf = XBUF_DEF; - ez.d_yprtbuf = YBUF_DEF; - - ez.clr_axis = C_WHITE; /* set fixed colors */ - ez.clr_title = (C_CYAN+8); - ez.clr_label = (C_CYAN+8); - ez.clr_legend = (C_RED+8); - ez.clr_number = (C_GREEN+8); - ez.clr_grid = (C_BLACK+8); -} + if (fabs(logt) >= 6) { /* use exponential format */ + if (fabs(logt) > 99) + expon = 5; /* E+102 */ + else + expon = 4; /* E+00 */ + + if (*nfrac < 0) { /* calculate frac */ + delta /= pow (10., floor(logt)); /* scale delta */ + frac = static_cast(fabs(trunc(log10(delta)))) + 1; + if (frac < 1) + frac = 1; /* to be safe, add decimal pt */ + } else /* use users' frac */ + frac = *nfrac; + + wid = 2 + frac + expon; + if (minval < 0. || maxval < 0.) + ++wid; + sprintf (fmtstr, "%s%d%s%d%s", "%", wid, ".", frac, "g"); + } else { /* use fixed format */ + wid = static_cast(trunc(logt)) + 1; + if (wid < 1) + wid = 1; + if (minval < 0. || maxval < 0.) + ++wid; + + if (*nfrac < 0) { /* calculate frac */ + if (delta >= 0.999999) + frac = 1; /* add a decimal pt to be safe */ + else + frac = static_cast(fabs(trunc(log10(delta)))) + 1; + } else /* use users' frac */ + frac = *nfrac; + + wid += 1 + frac; + sprintf (fmtstr, "%s%d%s%d%s", "%", wid, ".", frac, "f"); + } -void ezfree(void) -{ - for (int i = 0; i < ez.i_numcurves; i++) { - delete ez.curve[i].x; - delete ez.curve[i].y; - } - ez.i_numcurves = 0; + *fldwid = wid; + *nfrac = frac; } -void ezclear(void) -{ - ezfree(); - ezinit(); -} diff --git a/libctgraphics/ezset.cpp b/libctgraphics/ezset.cpp index 7b95e30..6623513 100644 --- a/libctgraphics/ezset.cpp +++ b/libctgraphics/ezset.cpp @@ -1,559 +1,412 @@ /***************************************************************************** -** FILE IDENTIFICATION -** -** EZSET - Parameter control for EZPLOT -** -** This is part of the CTSim program -** Copyright (C) 1983-2000 Kevin Rosenberg -** -** $Id: ezset.cpp,v 1.4 2000/07/13 07:03:21 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 -** published by the Free Software Foundation. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -******************************************************************************/ -/*----------------------------------------------------------------------*/ -/* */ -/*----------------------------------------------------------------------*/ + ** FILE IDENTIFICATION + ** + ** EZSET - Parameter control for EZPLOT + ** + ** This is part of the CTSim program + ** Copyright (C) 1983-2000 Kevin Rosenberg + ** + ** $Id: ezset.cpp,v 1.5 2000/07/28 08:28:08 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 + ** published by the Free Software Foundation. + ** + ** This program is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program; if not, write to the Free Software + ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + ******************************************************************************/ #include "ctsupport.h" #include "ezplot.h" #include "pol.h" -static int ezcmd (char *comm); -static int do_cmd(int lx); -static void do_data(void); -static void do_help(void); -static void bad_option(char *opt); -static void initkw(void); - -static int modeinteract = FALSE; -static int curveinteract = -1; -static int ezset_firstcall = TRUE; +bool EZPlot::ezset_initialized = false; int -ezset (char *command) +EZPlot::ezset (char *command) { - if (ezplot_firstcall == TRUE) { - ezinit (); - } - if (ezset_firstcall == TRUE) { - pol_init(); - initkw(); - pol_skpword ("please"); - pol_skpword ("use"); - pol_skpword ("are"); - pol_skpword ("and"); - pol_skpword ("is"); - pol_skpword ("the"); - pol_skpword ("equals"); - pol_skpchar ("="); - ezset_firstcall = FALSE; - - pol_usefile (P_USE_STR,""); - set_inputline ("!eoc ,"); - pol_reader (); - pol_closefile (); - } - return (ezcmd (command)); + if (! ezset_initialized) { + pol_init(); + initkw(); + pol_skpword ("please"); + pol_skpword ("use"); + pol_skpword ("are"); + pol_skpword ("and"); + pol_skpword ("is"); + pol_skpword ("the"); + pol_skpword ("equals"); + pol_skpchar ("="); + + pol_usefile (P_USE_STR,""); + set_inputline ("!eoc ,"); + pol_reader (); + pol_closefile (); + ezset_initialized = true; + } + return (ezcmd (command)); } -static int -ezcmd (char *comm) +bool +EZPlot::ezcmd (char *comm) { - char str[MAXTOK+1]; - int code, retval; - - retval = TRUE; - pol_usefile (P_USE_STR, ""); - set_inputline (comm); - - if (pol_usertok (str, &code) == FALSE) { - fputs("Illegal EZSET command\n", stderr); - pol_reader(); - retval = FALSE; - goto ezexit; - } - - if (code != S_INTERACTIVE) { - retval = do_cmd (code); - } else { - modeinteract = TRUE; - pol_reader(); - do { - fputs ("Enter EZSET command, DATA, EXIT, or HELP\n>", stderr); - if (get_inputline (stdin) != TRUE) - goto ezexit; - while (pol_lookchar() != EOF) { - if (pol_usertok (str, &code) == FALSE) { - if (pol_lookchar() != EOF) { - fputs ("illegal EZSET command\n", stderr); - pol_reader(); - } - } else if (code == S_DATA) { - pol_reader (); - do_data (); - } else if (code == S_HELP) { - pol_reader(); - do_help (); - } else if (code == S_EXIT) { - pol_reader(); - goto ezexit; - } else - do_cmd (code); - } - putc (NEWLINE, stderr); - } while (TRUE); - modeinteract = FALSE; - curveinteract = -1; - } -ezexit: - pol_closefile(); /* close input string file */ - return (retval); + pol_usefile (P_USE_STR, ""); + set_inputline (comm); + + char str[MAXTOK+1]; + int code; + bool retval = true; + if (! pol_usertok (str, &code)) { + cerr << "Illegal EZSET command: " << str << endl; + pol_reader(); + retval = false; + } + else + retval = do_cmd (code); + + pol_closefile(); /* close input string file */ + return (retval); } -static int -do_cmd (int lx) +int +EZPlot::do_cmd (int lx) { - char str [MAXTOK+1]; - int n; - double f; - - switch (lx) { - case S_CRT: - if (pol_word("no", 2) == TRUE) - ez.d_usecrt = FALSE; - else { - ez.d_usecrt = TRUE; - } - break; - case S_EPSON: - if (pol_word("no", 2) == TRUE) - ez.d_useprt = FALSE; - else - ez.d_useprt = TRUE; - break; - case S_TEXTSIZE: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) - { - if (f >= 0.0 && f <= 1.0) { - ez.v_textsize = f; - ez.s_textsize = TRUE; - } else - ez.s_textsize = FALSE; - } - break; - case S_PRTMODE: - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) - { - if (n >= 0 && n <= 6) - ez.d_prtmode = n; - else - ez.d_prtmode = PRTMODE_DEF; - } - break; - case S_XBUF: - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) - { - if (n > 2 && n <= 960) - ez.d_xprtbuf = n; - else - ez.d_xprtbuf = XBUF_DEF; - } - break; - case S_YBUF: - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) - { - if (n > 2 && n <= 960) - ez.d_yprtbuf = n; - else - ez.d_yprtbuf = YBUF_DEF; - } - break; - case S_REPLOT: - ez.i_plotimmediate = TRUE; - ezplot (static_cast(NULL), static_cast(NULL), 0); -#if 0 - if (modeinteract == TRUE) - WAITKEY(); -#endif - ez.i_plotimmediate = FALSE; - break; - case S_CLEAR: - ezclear (); - break; - case S_TITLE: - gettext (ez.c_title, MAXTITLE); - break; - case S_LEGEND: - gettext (ez.c_legend, MAXLEGEND); - if (modeinteract == TRUE && curveinteract >= 0) - strncpy (ez.curve[curveinteract].legend, ez.c_legend, MAXLEGEND); - break; - case S_XLABEL: - gettext (ez.c_xlabel, MAXLABEL); - break; - case S_YLABEL: - gettext (ez.c_ylabel, MAXLABEL); - break; - case S_XCROSS: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { - ez.v_xcross = f; - ez.s_xcross = TRUE; - } else - ez.s_xcross = FALSE; - break; - case S_YCROSS: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { - ez.v_ycross = f; - ez.s_ycross = TRUE; - } else - ez.s_ycross = FALSE; - break; - case S_NOXAXIS: - ez.o_xaxis = NOAXIS; - break; - case S_NOYAXIS: - ez.o_yaxis = NOAXIS; - break; - case S_XLIN: - ez.o_xaxis = LINEAR; - break; - case S_YLIN: - ez.o_yaxis = LINEAR; - break; - case S_XLOG: - ez.o_xaxis = LOG; - break; - case S_YLOG: - ez.o_yaxis = LOG; - break; - case S_XAUTOSCALE: - ez.s_xmin = FALSE; - ez.s_xmax = FALSE; - break; - case S_YAUTOSCALE: - ez.s_ymin = FALSE; - ez.s_ymax = FALSE; - break; - case S_XMIN: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { - ez.v_xmin = f; - ez.s_xmin = TRUE; - } - break; - case S_XMAX: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { - ez.v_xmax = f; - ez.s_xmax = TRUE; - } - break; - case S_YMIN: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { - ez.v_ymin = f; - ez.s_ymin = TRUE; - } - break; - case S_YMAX: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { - ez.v_ymax = f; - ez.s_ymax = TRUE; - } - break; - case S_SOLID: - ez.o_linestyle = LS_SOLID; - if (modeinteract == TRUE && curveinteract >= 0) - ez.curve[curveinteract].linestyle = LS_SOLID; - break; - case S_DASH: - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { - if (n == 1) - ez.o_linestyle = LS_DASH1; - else if (n == 2) - ez.o_linestyle = LS_DASH2; - else if (n == 3) - ez.o_linestyle = LS_DASH3; - else if (n == 4) - ez.o_linestyle = LS_DASH4; - else - ez.o_linestyle = LS_DASH1; - } else - ez.o_linestyle = LS_DASH1; - if (modeinteract == TRUE && curveinteract >= 0) - ez.curve[curveinteract].linestyle = ez.o_linestyle; - break; - case S_NOLINE: - ez.o_linestyle = LS_NOLINE; - if (modeinteract == TRUE && curveinteract >= 0) - ez.curve[curveinteract].linestyle = LS_NOLINE; - break; - case S_PEN: - case S_COLOR: - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) - { - if (n >= 0 && n <= MAXCOLOR) - ez.o_color = n; - else - bad_option("The color you picked"); - } - if (modeinteract == TRUE && curveinteract >= 0) - ez.curve[curveinteract].color = ez.o_color; - break; - case S_BOX: - ez.o_box = TRUE; - break; - case S_NOBOX: - ez.o_box = FALSE; - break; - case S_GRID: - ez.o_grid = TRUE; - break; - case S_NOGRID: - ez.o_grid = FALSE; - break; - case S_XLENGTH: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) - if (f > 0.0 && f <= 1.0) - ez.o_xlength = f; - break; - case S_YLENGTH: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) - if (f > 0.0 && f <= 1.0) - ez.o_ylength = f; - break; - case S_XPORIGIN: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) - if (f >= 0.0 && f < 1.0) - ez.o_xporigin = f; - break; - case S_YPORIGIN: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) - if (f >= 0.0 && f < 1.0) - ez.o_yporigin = f; - break; - case S_TAG: - if (pol_word("no", 2) == TRUE) - ez.o_tag = FALSE; - else if (pol_word("off", 2) == TRUE) - ez.o_tag = FALSE; - else - ez.o_tag = TRUE; - break; - case S_LEGENDBOX: - if (pol_word("inside", 2) == TRUE) - ez.o_legendbox = INSIDE; - else if (pol_word("outside", 3) == TRUE) - ez.o_legendbox = OUTSIDE; - else if (pol_word("none",2) == TRUE) - ez.o_legendbox = NOLEGEND; - else { - gettext (str, MAXTOK); - bad_option(str); - } - break; - case S_XLEGEND: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) - { - if (f >= 0.0 && f < 1.0) { - ez.v_xlegend = f; - ez.s_xlegend = TRUE; - } - else - ez.s_xlegend = FALSE; - } - break; - case S_YLEGEND: - if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) - { - if (f >= 0.0 && f < 1.0) { - ez.v_ylegend = f; - ez.s_ylegend = TRUE; - } - else - ez.s_ylegend = FALSE; - } - break; - case S_CURVES: - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { - if (n < 1) - n = 1; - else if (n > MAXCURVES) - n = MAXCURVES; - if (modeinteract == TRUE) { - curveinteract = n - 1; - if (ez.o_unknowncurves == FALSE && ez.o_reqcurves < n) - ez.o_reqcurves = n; - } else { - ezfree (); - ez.o_reqcurves = n; - } - } else { - if (pol_word ("unknown", 7) == TRUE) - ez.o_unknowncurves = TRUE; - else if (pol_word ("end", 3) == TRUE) { - ez.o_unknowncurves = FALSE; - ez.o_reqcurves = ez.i_numcurves; - ez.i_plotimmediate = TRUE; - ezplot (static_cast(NULL), static_cast(NULL), 0); - ez.i_plotimmediate = FALSE; - } - } - break; - case S_SYMBOL: - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { - if (n > 0 && n <= MAXSYMBOL) - ez.o_symbol = n; - else - ez.o_symbol = 1; - if (modeinteract == TRUE && curveinteract >= 0) - ez.curve[curveinteract].symbol = ez.o_symbol; - } else { - if (pol_word("every",5) == TRUE) { - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { - if (n > 0) - ez.o_symfreq = n; - else - ez.o_symfreq = 1; - if (modeinteract == TRUE && curveinteract >= 0) - ez.curve[curveinteract].symfreq = ez.o_symfreq; - } - } else if (pol_word ("none",4) == TRUE) { - ez.o_symbol = -1; - if (modeinteract == TRUE && curveinteract >= 0) - ez.curve[curveinteract].symbol = ez.o_symbol; - } - } - break; - case S_XTICKS: - if (pol_usertok(str,&lx) == FALSE) - break; - if (lx == S_ABOVE) - ez.o_xticks = ABOVE; - else if (lx == S_BELOW) - ez.o_xticks = BELOW; - else if (lx == S_NOLABEL) - ez.o_xtlabel = FALSE; - else if (lx == S_LABEL) - ez.o_xtlabel = TRUE; - else if (lx == S_MAJOR) { - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) - if (n > 1 && n < 100) - ez.o_xmajortick = n; - } else if (lx == S_MINOR) - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) - if (n >= 0 && n < 100) - ez.o_xminortick = n; - break; - case S_YTICKS: - if (pol_usertok(str,&lx) == FALSE) - break; - if (lx == S_RIGHT) - ez.o_yticks = RIGHT; - else if (lx == S_LEFT) - ez.o_yticks = LEFT; - else if (lx == S_NOLABEL) - ez.o_ytlabel = FALSE; - else if (lx == S_LABEL) - ez.o_ytlabel = TRUE; - else if (lx == S_MAJOR) { - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) - if (n > 1 && n < 100) - ez.o_ymajortick = n; - } else if (lx == S_MINOR) - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) - if (n >= 0 && n < 100) - ez.o_yminortick = n; - break; - case S_LXFRAC: - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { - if (n >= 0) { - ez.v_lxfrac = n; - ez.s_lxfrac = TRUE; - } - } else - ez.s_lxfrac = FALSE; - break; - case S_LYFRAC: - if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { - if (n >= 0) { - ez.v_lyfrac = n; - ez.s_lyfrac = TRUE; - } - } else - ez.s_lyfrac = FALSE; - break; - case S_USTART: - if (pol_word("no", 2) == TRUE) - ez.o_ustart = FALSE; - else - ez.o_ustart = TRUE; - break; - case S_UFINISH: - if (pol_word("no", 2) == TRUE) - ez.o_ufinish = FALSE; - else - ez.o_ufinish = TRUE; - break; - default: - fprintf (stderr, "Unimplemented EZPLOT command\n"); - break; + char str [1024]; + char strIn [1024]; + int n; + double f; + + switch (lx) { + case S_TEXTSIZE: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) + { + if (f >= 0.0 && f <= 1.0) { + v_textsize = f; + s_textsize = TRUE; + } else + s_textsize = FALSE; + } + break; + case S_REPLOT: + plot (); + break; + case S_CLEAR: + clearCurves (); + break; + case S_TITLE: + gettext (strIn, sizeof(strIn)); + c_title = strIn; + break; + case S_LEGEND: + gettext (strIn, sizeof(strIn)); + c_legend = strIn; + break; + case S_XLABEL: + gettext (strIn, sizeof(strIn)); + c_xlabel = strIn; + break; + case S_YLABEL: + gettext (strIn, sizeof(strIn)); + c_ylabel = strIn; + break; + case S_XCROSS: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { + v_xcross = f; + s_xcross = TRUE; + } else + s_xcross = FALSE; + break; + case S_YCROSS: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { + v_ycross = f; + s_ycross = TRUE; + } else + s_ycross = FALSE; + break; + case S_NOXAXIS: + o_xaxis = NOAXIS; + break; + case S_NOYAXIS: + o_yaxis = NOAXIS; + break; + case S_XLIN: + o_xaxis = LINEAR; + break; + case S_YLIN: + o_yaxis = LINEAR; + break; + case S_XLOG: + o_xaxis = LOG; + break; + case S_YLOG: + o_yaxis = LOG; + break; + case S_XAUTOSCALE: + s_xmin = FALSE; + s_xmax = FALSE; + break; + case S_YAUTOSCALE: + s_ymin = FALSE; + s_ymax = FALSE; + break; + case S_XMIN: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { + v_xmin = f; + s_xmin = TRUE; + } + break; + case S_XMAX: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { + v_xmax = f; + s_xmax = TRUE; + } + break; + case S_YMIN: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { + v_ymin = f; + s_ymin = TRUE; + } + break; + case S_YMAX: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) { + v_ymax = f; + s_ymax = TRUE; + } + break; + case S_SOLID: + o_linestyle = SGP::LS_SOLID; + break; + case S_DASH: + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { + if (n == 1) + o_linestyle = SGP::LS_DASH1; + else if (n == 2) + o_linestyle = SGP::LS_DASH2; + else if (n == 3) + o_linestyle = SGP::LS_DASH3; + else if (n == 4) + o_linestyle = SGP::LS_DASH4; + else + o_linestyle = SGP::LS_DASH1; + } else + o_linestyle = SGP::LS_DASH1; + break; + case S_NOLINE: + o_linestyle = SGP::LS_NOLINE; + break; + case S_PEN: + case S_COLOR: + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) + { + if (n >= 0) + o_color = n; + else + bad_option("The color you picked"); + } + break; + case S_BOX: + o_box = TRUE; + break; + case S_NOBOX: + o_box = FALSE; + break; + case S_GRID: + o_grid = TRUE; + break; + case S_NOGRID: + o_grid = FALSE; + break; + case S_XLENGTH: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) + if (f > 0.0 && f <= 1.0) + o_xlength = f; + break; + case S_YLENGTH: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) + if (f > 0.0 && f <= 1.0) + o_ylength = f; + break; + case S_XPORIGIN: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) + if (f >= 0.0 && f < 1.0) + o_xporigin = f; + break; + case S_YPORIGIN: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) + if (f >= 0.0 && f < 1.0) + o_yporigin = f; + break; + case S_TAG: + if (pol_word("no", 2) == TRUE) + o_tag = FALSE; + else if (pol_word("off", 2) == TRUE) + o_tag = FALSE; + else + o_tag = TRUE; + break; + case S_LEGENDBOX: + if (pol_word("inside", 2) == TRUE) + o_legendbox = INSIDE; + else if (pol_word("outside", 3) == TRUE) + o_legendbox = OUTSIDE; + else if (pol_word("none",2) == TRUE) + o_legendbox = NOLEGEND; + else { + gettext (str, MAXTOK); + bad_option(str); + } + break; + case S_XLEGEND: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) + { + if (f >= 0.0 && f < 1.0) { + v_xlegend = f; + s_xlegend = TRUE; } - - pol_reader (); - return (TRUE); -} - -static void do_data (void) -{ - double x[MAXPTS], y[MAXPTS], d; - int c, i; - - printf ("Enter your data in free format\n"); - printf ("Alternate X and Y coordinates\n"); - printf ("Type ^Z (control Z) to terminate data entry\n"); - - pol_usefile (P_USE_FILE, ""); - for (i = 0; i < MAXPTS; i++) { - if (pol_float (&d, TT_REAL, FALSE, 0, 0) == TRUE) - x[i] = d; - else - break; - if (pol_float (&d, TT_REAL, FALSE, 0, 0) == TRUE) - y[i] = d; - else - break; + else + s_xlegend = FALSE; + } + break; + case S_YLEGEND: + if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) + { + if (f >= 0.0 && f < 1.0) { + v_ylegend = f; + s_ylegend = TRUE; } - - if ((c = pol_inchar()) != EOF) { - ungetc (c, stdin); - printf("Error reading in points, read char %d, plotting %d points\n", c, i); + else + s_ylegend = FALSE; + } + break; + case S_CURVES: + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { + if (n < 1) + n = 1; + // if (modeinteract == TRUE) { + // curveinteract = n - 1; + // if (o_unknowncurves == FALSE && o_reqcurves < n) + // o_reqcurves = n; + // } else { + // clearCurve (); + // o_reqcurves = n; + // } + } else { + if (pol_word ("unknown", 7) == TRUE) + o_unknowncurves = TRUE; + else if (pol_word ("end", 3) == TRUE) { + // o_unknowncurves = FALSE; + // o_reqcurves = i_numcurves; + // i_plotimmediate = TRUE; + // ezplot (static_cast(NULL), static_cast(NULL), 0); + // i_plotimmediate = FALSE; + } + } + break; + case S_SYMBOL: + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { + if (n > 0 && n <= MAXSYMBOL) + o_symbol = n; + else + o_symbol = 1; + // if (modeinteract == TRUE && curveinteract >= 0) + // curve[curveinteract].symbol = o_symbol; + } else { + if (pol_word("every",5) == TRUE) { + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { + if (n > 0) + o_symfreq = n; + else + o_symfreq = 1; + // if (modeinteract == TRUE && curveinteract >= 0) + // curve[curveinteract].symfreq = o_symfreq; } - if (i > 0) - ezplot (x, y, i); - pol_closefile (); + } else if (pol_word ("none",4) == TRUE) { + o_symbol = -1; + // if (modeinteract == TRUE && curveinteract >= 0) + // curve[curveinteract].symbol = o_symbol; + } + } + break; + case S_XTICKS: + if (pol_usertok(str,&lx) == FALSE) + break; + if (lx == S_ABOVE) + o_xticks = ABOVE; + else if (lx == S_BELOW) + o_xticks = BELOW; + else if (lx == S_NOLABEL) + o_xtlabel = FALSE; + else if (lx == S_LABEL) + o_xtlabel = TRUE; + else if (lx == S_MAJOR) { + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) + if (n > 1 && n < 100) + o_xmajortick = n; + } else if (lx == S_MINOR) + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) + if (n >= 0 && n < 100) + o_xminortick = n; + break; + case S_YTICKS: + if (pol_usertok(str,&lx) == FALSE) + break; + if (lx == S_RIGHT) + o_yticks = RIGHT; + else if (lx == S_LEFT) + o_yticks = LEFT; + else if (lx == S_NOLABEL) + o_ytlabel = FALSE; + else if (lx == S_LABEL) + o_ytlabel = TRUE; + else if (lx == S_MAJOR) { + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) + if (n > 1 && n < 100) + o_ymajortick = n; + } else if (lx == S_MINOR) + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) + if (n >= 0 && n < 100) + o_yminortick = n; + break; + case S_LXFRAC: + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { + if (n >= 0) { + v_lxfrac = n; + s_lxfrac = TRUE; + } + } else + s_lxfrac = FALSE; + break; + case S_LYFRAC: + if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) { + if (n >= 0) { + v_lyfrac = n; + s_lyfrac = TRUE; + } + } else + s_lyfrac = FALSE; + break; + break; + default: + fprintf (stderr, "Unimplemented EZPLOT command\n"); + break; + } + + pol_reader (); + return (TRUE); } -static void do_help (void ) -{ - fputs ("EZSET Help: not available\n", stderr); -} - -static void -bad_option (char *opt) +void +EZPlot::bad_option (char *opt) { - fprintf(stderr,"%s is an INVALID option (sorry!)\n", opt); + cerr << opt << " is an INVALID option\n"; } /*----------------------------------------------------------------------*/ @@ -561,104 +414,98 @@ bad_option (char *opt) /*----------------------------------------------------------------------*/ static struct key { - char *keyword; - int code; + char *keyword; + int code; } keytab[] = { - {"solid", S_SOLID}, - {"dash", S_DASH}, - {"noline", S_NOLINE}, + {"solid", S_SOLID}, + {"dash", S_DASH}, + {"noline", S_NOLINE}, {"black", S_BLACK}, - {"red", S_RED}, - {"blue", S_BLUE}, - {"green", S_GREEN}, - {"pen", S_PEN}, - {"symbol", S_SYMBOL}, -/* "every", S_EVERY, */ -/* "none", S_NONE, */ - - {"curves", S_CURVES}, - {"curve", S_CURVES}, -/* "unknown", S_UNKNOWN, */ -/* "end", S_END, */ - - {"legend", S_LEGEND}, - {"xlegend", S_XLEGEND}, - {"ylegend", S_YLEGEND}, - - {"xlin", S_XLIN}, - {"ylin", S_YLIN}, - {"xlog", S_XLOG}, - {"ylog", S_YLOG}, - {"xlabel", S_XLABEL}, - {"ylabel", S_YLABEL}, - {"xlength", S_XLENGTH}, - {"ylength", S_YLENGTH}, - - {"xticks", S_XTICKS}, - {"yticks", S_YTICKS}, - {"above", S_ABOVE}, - {"label", S_LABEL}, - {"below", S_BELOW}, - {"nolabel", S_NOLABEL}, - {"right", S_RIGHT}, - {"left", S_LEFT}, - - {"xautoscale", S_XAUTOSCALE}, - {"yautoscale", S_YAUTOSCALE}, - {"xmin", S_XMIN}, - {"ymin", S_YMIN}, - {"xmax", S_XMAX}, - {"ymax", S_YMAX}, - {"lxfrac", S_LXFRAC}, - {"lyfrac", S_LYFRAC}, - {"xcross", S_XCROSS}, - {"ycross", S_YCROSS}, - {"noxaxis", S_NOXAXIS}, - {"noyaxis", S_NOYAXIS}, - {"xporigin", S_XPORIGIN}, - {"yporigin", S_YPORIGIN}, - {"title", S_TITLE}, - {"xtitle", S_XTITLE}, - {"ytitle", S_YTITLE}, - - {"replot", S_REPLOT}, - {"clear", S_CLEAR}, - {"store", S_STORE}, - {"restore", S_RESTORE}, - {"ustart", S_USTART}, - {"ufinish", S_UFINISH}, - {"amark", S_AMARK}, - {"interactive", S_INTERACTIVE}, - {"units", S_UNITS}, - {"inches", S_INCHES}, - {"user", S_USER}, - - {"data", S_DATA}, - {"help", S_HELP}, - {"exit", S_EXIT}, - - {"box", S_BOX}, - {"nobox", S_NOBOX}, - {"grid", S_GRID}, - {"nogrid", S_NOGRID}, - {"major", S_MAJOR}, - {"minor", S_MINOR}, - {"color", S_COLOR}, - {"legendbox", S_LEGENDBOX}, - - {"epson", S_EPSON}, - {"crt", S_CRT}, - {"no", S_NO}, - - {"textsize", S_TEXTSIZE}, - {"xbuf", S_XBUF}, - {"ybuf", S_YBUF}, - // {"prtmode", S_PRTMOD}, -}; + {"red", S_RED}, + {"blue", S_BLUE}, + {"green", S_GREEN}, + {"pen", S_PEN}, + {"symbol", S_SYMBOL}, + /* "every", S_EVERY, */ + /* "none", S_NONE, */ + + {"curves", S_CURVES}, + {"curve", S_CURVES}, + /* "unknown", S_UNKNOWN, */ + /* "end", S_END, */ + + {"legend", S_LEGEND}, + {"xlegend", S_XLEGEND}, + {"ylegend", S_YLEGEND}, + + {"xlin", S_XLIN}, + {"ylin", S_YLIN}, + {"xlog", S_XLOG}, + {"ylog", S_YLOG}, + {"xlabel", S_XLABEL}, + {"ylabel", S_YLABEL}, + {"xlength", S_XLENGTH}, + {"ylength", S_YLENGTH}, + + {"xticks", S_XTICKS}, + {"yticks", S_YTICKS}, + {"above", S_ABOVE}, + {"label", S_LABEL}, + {"below", S_BELOW}, + {"nolabel", S_NOLABEL}, + {"right", S_RIGHT}, + {"left", S_LEFT}, + + {"xautoscale", S_XAUTOSCALE}, + {"yautoscale", S_YAUTOSCALE}, + {"xmin", S_XMIN}, + {"ymin", S_YMIN}, + {"xmax", S_XMAX}, + {"ymax", S_YMAX}, + {"lxfrac", S_LXFRAC}, + {"lyfrac", S_LYFRAC}, + {"xcross", S_XCROSS}, + {"ycross", S_YCROSS}, + {"noxaxis", S_NOXAXIS}, + {"noyaxis", S_NOYAXIS}, + {"xporigin", S_XPORIGIN}, + {"yporigin", S_YPORIGIN}, + {"title", S_TITLE}, + {"xtitle", S_XTITLE}, + {"ytitle", S_YTITLE}, + + {"replot", S_REPLOT}, + {"clear", S_CLEAR}, + {"store", S_STORE}, + {"restore", S_RESTORE}, + {"amark", S_AMARK}, + {"interactive", S_INTERACTIVE}, + {"units", S_UNITS}, + {"inches", S_INCHES}, + {"user", S_USER}, + + {"data", S_DATA}, + {"help", S_HELP}, + {"exit", S_EXIT}, + + {"box", S_BOX}, + {"nobox", S_NOBOX}, + {"grid", S_GRID}, + {"nogrid", S_NOGRID}, + {"major", S_MAJOR}, + {"minor", S_MINOR}, + {"color", S_COLOR}, + {"legendbox", S_LEGENDBOX}, + + {"no", S_NO}, + + {"textsize", S_TEXTSIZE}, + }; static const unsigned int NKEYS=(sizeof(keytab) / sizeof(struct key)); -static void initkw(void) +void +EZPlot::initkw(void) { for (unsigned int i = 0; i < NKEYS; i++) if (pol_install(keytab[i].keyword, keytab[i].code) == FALSE) diff --git a/libctgraphics/ezsupport.cpp b/libctgraphics/ezsupport.cpp index f788b2e..a6a2cd5 100644 --- a/libctgraphics/ezsupport.cpp +++ b/libctgraphics/ezsupport.cpp @@ -2,7 +2,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ezsupport.cpp,v 1.4 2000/07/13 07:03:21 kevin Exp $ +** $Id: ezsupport.cpp,v 1.5 2000/07/28 08:28:08 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 @@ -24,193 +24,3 @@ #include "ezplot.h" -/* NAME - * axis_scale calculates graph axis scaling - * - * SYNOPSIS: - * retval = axis_scale (min, max, nint, minp, maxp, nintp, - * rec_total, rec_frac) - * - * INPUT: - * double min Smallest value to plot - * double max Largest value to plot - * int nint Number of intervals desired - * - * OUTPUT: - * int retval FALSE if illegal parameters, else TRUE - * double *minp Minimum graph value - * double *maxp Maximum graph value - * int *nintp Number of intervals for graph - * int *rec_total Recommended field width for printing out the number - * int *rec_frac Recommended number of digits for print fraction - */ - -int -axis_scale (double min, double max, int nint, double *minp, double *maxp, int *nintp) -{ - double eps, a, scale, mina, maxa, d, j, e, f, v, wdt, g, h; - - if (min >= max || nint < 1) { - sys_error (ERR_WARNING, "Invalid params: min=%lf, min=%lf, num intervals=%d [axis_scale]", min, max, nint); - return (FALSE); - } - - eps = 0.025; - a = fabs(min); - if (fabs(min) < fabs(max)) - a = fabs(max); - scale = pow (10.0, floor(log10(a))); - loop: - mina = min / scale; - maxa = max / scale; - d = (maxa - mina) / nint; - j = d * eps; - e = floor (log10(d)); - f = d / pow (10.0, e); - v = 10.0; - if (f < sqrt(2.0)) - v = 1.0; - else if (f < sqrt (10.0)) - v = 2.0; - else if (f < sqrt (50.0)) - v = 5.0; - wdt = v * pow (10.0, e); - g = floor (mina / wdt); - if (fabs(g + 1 - mina / wdt) < j) - g = g + 1; - *minp = wdt * g; - h = floor (maxa / wdt) + 1.0; - if (fabs(maxa / wdt + 1 - h) < j) - h = h - 1; - *maxp = wdt * h; - *nintp = static_cast(h - g); - if (fabs(*maxp) >= 10.0 || fabs(*minp) >= 10.0) { - scale = scale * 10.0; - goto loop; - } - - *minp *= scale; - *maxp *= scale; - - return (TRUE); -} - - -/* NAME - * make_numfmt Make a numeric format string - * - * SYNOPSIS - * make_numfmt (fmtstr, fldwid, nfrac, min, max, nint) - * char *fmtstr Returned format string for printf() - * int *fldwid Returned field width - * int *nfrac If < 0, then calculate best number of - * fraction places & return that value - * If >= 0, then use that number of places - * double min Minimum value - * double max Maximum value - * int nint Number of intervals between min & max - * - * DESCRIPTION - * This routine is written as an INTERNAL routine for EZPLOT - */ - -static inline double -trunc (double x) -{ - double integer; - - modf (x, &integer); - - return (integer); -} - -void -make_numfmt (char *fmtstr, int *fldwid, int *nfrac, double minval, double maxval, int nint) -{ - int wid, frac, expon; - - double delta = (maxval - minval) / nint; - double absmin = fabs(minval); - double absmax = fabs(maxval); - double logt = log10( max(absmin, absmax) ); - - if (fabs(logt) >= 6) { /* use exponential format */ - if (fabs(logt) > 99) - expon = 5; /* E+102 */ - else - expon = 4; /* E+00 */ - - if (*nfrac < 0) { /* calculate frac */ - delta /= pow (10., floor(logt)); /* scale delta */ - frac = static_cast(fabs(trunc(log10(delta)))) + 1; - if (frac < 1) - frac = 1; /* to be safe, add decimal pt */ - } else /* use users' frac */ - frac = *nfrac; - - wid = 2 + frac + expon; - if (minval < 0. || maxval < 0.) - ++wid; - sprintf (fmtstr, "%s%d%s%d%s", "%", wid, ".", frac, "g"); - } else { /* use fixed format */ - wid = static_cast(trunc(logt)) + 1; - if (wid < 1) - wid = 1; - if (minval < 0. || maxval < 0.) - ++wid; - - if (*nfrac < 0) { /* calculate frac */ - if (delta >= 0.999999) - frac = 1; /* add a decimal pt to be safe */ - else - frac = static_cast(fabs(trunc(log10(delta)))) + 1; - } else /* use users' frac */ - frac = *nfrac; - - wid += 1 + frac; - sprintf (fmtstr, "%s%d%s%d%s", "%", wid, ".", frac, "f"); - } - - *fldwid = wid; - *nfrac = frac; -} - -#ifdef TEST -int -main (void) -{ - double min, max; - double x, xinc; - int i, nint, wid, frac; - char fmtstr[10]; - - printf ("Enter min, max, & number of intervals -- "); - scanf ("%lf %lf %d", &min, &max, &nint); - - frac = -1; /* let makefmt determine fraction */ - - makefmt (fmtstr, &wid, &frac, min, max, nint); - - printf ("Format string = %s\n", fmtstr); - - xinc = (max - min) / nint; - - x = min; - for (i = 0; i <= nint; i++) { - printf (fmtstr, x); - x += xinc; - printf ("\n"); - } -} -#endif - -void -ezplot_1d (double *y, int n) -{ - double x [n]; - - for (int i = 0; i < n; i++) - x[i] = i; - - ezplot (x, y, n); -} diff --git a/libctgraphics/sgp.cpp b/libctgraphics/sgp.cpp index 8a5400f..e1a1142 100644 --- a/libctgraphics/sgp.cpp +++ b/libctgraphics/sgp.cpp @@ -1,13 +1,13 @@ /***************************************************************************** ** FILE IDENTIFICATION ** -** Name: sgp.c Simple Graphics Package +** 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.4 2000/07/11 10:32:44 kevin Exp $ +** $Id: sgp.cpp,v 1.5 2000/07/28 08:28:08 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,586 +29,580 @@ #include "sgp.h" -static SGP_ID _sgp2_cwin = NULL; -extern CHARSPEC cspec; +#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) +{ + m_pDC = pDC; + m_idDriver |= SGPDRIVER_WXWINDOWS; +} +#endif +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(szWinTitle), const_cast(szWinTitle), NULL, -1, -1); + m_idDriver |= SGPDRIVER_G2; +#endif +} -/* NAME - * sgp2_init Initialize 2 graphics system - * - * SYNOPSIS - * sgp2_init() - */ +SGPDriver::~SGPDriver () +{ + if (isG2()) + g2_close (m_idG2); +} -SGP_ID -sgp2_init (int xsize, int ysize, const char *win_title ) + +// NAME +// SGP::SGP Constructor for Simple Graphics Package + +SGP::SGP (const SGPDriver& driver) + : m_driver (driver) { - SGP_ID gid; + m_iPhysicalXSize = m_driver.getPhysicalXSize(); + m_iPhysicalYSize = m_driver.getPhysicalYSize(); - 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); -#endif + wc_to_ndc.setIdentity (); + mc_to_ndc.setIdentity(); + ndc_to_mc.setIdentity(); + m_ctm.setIdentity(); - _sgp2_init_dev (_sgp2_cwin); - - return (gid); + setWindow (0., 0., 1., 1.); + setViewport (0., 0., 1., 1.); + moveAbs (0., 0.); + m_iCurrentPhysicalX = 0; + m_iCurrentPhysicalY = 0; + + setTextAngle (0.); + setTextSize (1. / 25.); } void -sgp2_close (SGP_ID gid) +SGP::stylusNDC (double x, double y, bool beam) { -#if HAVE_G2_H - if (gid) - g2_close (gid->g2_id); -#endif - if (gid == _sgp2_cwin) - _sgp2_cwin = NULL; - - delete gid; + int xp = static_cast(x * m_iPhysicalXSize + 0.5); + int yp = static_cast(y * m_iPhysicalYSize + 0.5); + 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); + } + 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); -#endif + if (m_driver.isG2()) + g2_clear (m_driver.idG2()); + if (m_driver.isWX()) + m_driver.idWX()->Clear(); } -/* 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; - } - - _sgp2_cwin->xw_min = xmin; - _sgp2_cwin->yw_min = ymin; - _sgp2_cwin->xw_max = xmax; - _sgp2_cwin->yw_max = ymax; - calc_wc_to_ndc(); + 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; } -/* NAME - * sgp2_viewport Set viewport in NDC - */ +// NAME +// sgp2_viewport Set viewport in NDC void -sgp2_viewport (double xmin, double ymin, double xmax, double ymax) +SGP::setViewport (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_viewport]"); - return; - } + if (xmin >= xmax || ymin >= ymax) { + sys_error (ERR_WARNING, "Minimum > Maximum [sgp2_viewport]"); + return; + } - _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; + 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; } -/* NAME - * sgp2_frame_vpt draw box around viewport - */ +// NAME +// frameViewport draw box around viewport void -sgp2_frame_vpt (void) +SGP::frameViewport (void) { - 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); + 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); } - -/* NAME - * calc_wc_to_ndc Calculate transform matrix - */ - void -calc_wc_to_ndc (void) +SGP::setTextColor (int iFGcolor, int iBGcolor) { - 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; } - void -calc_ndc_to_mc (void) +SGP::setColor (int icol) { - 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; } +void +SGP::setMarker (int idMarke, int iColor) +{ +} -/* NAME - * wc_to_ndc Map from world coordinates to NDC - */ - +//============================================================== +// set line style. Pass 16 bit repeating pattern +//============================================================== void -wc_to_ndc (double xw, double yw, double *xn, double *yn) +SGP::setLineStyle (int style) { - 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; - } - - *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]; } +//============================================================== +// absolute draw to +//*============================================================== -/*==============================================================*/ -/* map from normalized device coords. to world coordinates */ -/*==============================================================*/ -void -ndc_to_wc (double xn, double yn, double *xw, double *yw) +void +SGP::lineAbs (double x, double y) { - if (_sgp2_cwin == NULL) - return; + if (m_bRecalcTransform) + calc_transform(); - if (_sgp2_cwin->recalc_ndc_to_mc) { - calc_ndc_to_mc(); - _sgp2_cwin->recalc_ndc_to_mc = FALSE; - } + double x1 = m_dCurrentWorldX; + double y1 = m_dCurrentWorldY; + mc_to_ndc.transformPoint (&x1, &y1); - *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]; -} + double x2 = x; + double y2 = y; + mc_to_ndc.transformPoint (&x1, &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 + } + m_dCurrentWorldX = x; + m_dCurrentWorldY = y; +} -/*==============================================================*/ -/* set the color */ -/*==============================================================*/ void -sgp2_color (int icol) +SGP::moveAbs (double x, double y) { - setcolor(icol); + m_dCurrentWorldX = x; + m_dCurrentWorldY = y; /* moves are not clipped */ } -/*==============================================================*/ -/* set line style. Pass 16 bit repeating pattern */ -/*==============================================================*/ void -sgp2_line_style (int style) +SGP::lineRel (double x, double y) { - setlinestyle(style); + lineAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY); } -/*==============================================================*/ -/* absolute draw to */ -/*==============================================================*/ void -sgp2_line_abs (double x, double y) +SGP::moveRel (double x, double y) { - double x1, y1, x2, y2; + moveAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY); +} - if (_sgp2_cwin == NULL) - return; +void +SGP::setTextSize (double height) +{ + if (m_driver.isG2()) + g2_set_font_size(m_driver.idG2(), (height * m_iPhysicalYSize)); +} - wc_to_ndc (_sgp2_cwin->curx, _sgp2_cwin->cury, &x1, &y1); - wc_to_ndc (x, y, &x2, &y2); +void +SGP::setTextAngle (double angle) +{ + m_dTextAngle = angle; +} - 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 */ +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, 0); + stylusNDC (xt, yt, 1); + } + + 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, 0); + stylusNDC (xt, yt, 1); } - - _sgp2_cwin->curx = x; - _sgp2_cwin->cury = y; + } } -/*==============================================================*/ -/* absolute move to */ -/*==============================================================*/ + void -sgp2_move_abs (double x, double y) +SGP::markerAbs (double x, double y) { - if (_sgp2_cwin == NULL) - return; + if (m_bRecalcTransform) + calc_transform(); - _sgp2_cwin->curx = x; - _sgp2_cwin->cury = y; /* moves are not clipped */ + 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; } -/*==============================================================*/ -/* vector draw */ -/*==============================================================*/ + void -sgp2_line_rel (double x, double y) +SGP::markerRel (double x, double y) { - if (_sgp2_cwin != NULL) - sgp2_line_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury); + markerAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY); } -/*==============================================================*/ -/* vector move */ -/*==============================================================*/ + void -sgp2_move_rel (double x, double y) +SGP::pointAbs (double x, double y) { - if (_sgp2_cwin != NULL) - sgp2_move_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury); + 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; } -/*==============================================================*/ -/* draw text */ -/*==============================================================*/ + void -sgp2_draw_text (char *message) +SGP::pointRel (double x, double y) { - 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); + pointAbs (x + m_dCurrentWorldX, y + m_dCurrentWorldY); } -void -charsize (double wid, double height) -{ - _sgp2_set_text (_sgp2_cwin, wid, height, cspec.textangle, cspec.font); -} void -textangle (double angle) +SGP::drawText (const string& rsMessage) { - _sgp2_set_text (_sgp2_cwin, cspec.width, cspec.height, angle, cspec.font); + drawText (rsMessage.c_str()); } void -sgp2_polyline_abs (double x[], double y[], int n) +SGP::drawText (const char *pszMessage) { - double x1, y1, x2, y2; - int i; - double xt, yt; + if (m_bRecalcTransform) + calc_transform(); - if (_sgp2_cwin == NULL || n < 2) - return; + double xndc = m_dCurrentWorldX; + double yndc = m_dCurrentWorldY; + mc_to_ndc.transformPoint (&xndc, &yndc); - wc_to_ndc (x[0], y[0], &x1, &y1); - wc_to_ndc (x[1], y[1], &x2, &y2); + stylusNDC (xndc, yndc, false); // move to location - xt = x2; /* don't pass (x2,y2) to clip, we need them */ - yt = y2; /* as the beginning point of the next line */ - - 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); - } - - 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); - } - } + if (m_driver.isG2()) { + if (m_dTextAngle == 0.) + g2_string (m_driver.idG2(), m_iCurrentPhysicalX, m_iCurrentPhysicalY, const_cast(pszMessage)); + } + if (m_driver.isWX()) { + } } -void -sgp2_mark_abs (double x, double y) -{ - double xndc, yndc; - - if (_sgp2_cwin == NULL) - return; +// 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. - wc_to_ndc (x, y, &xndc, &yndc); - markndc (_sgp2_cwin, xndc, yndc); - _sgp2_cwin->curx = x; - _sgp2_cwin->cury = y; +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); } - +// FUNCTION +// sgp2_circle - draw circle of radius r at current center + void -sgp2_mark_rel (double x, double y) +SGP::drawCircle (const double r) { - sgp2_mark_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury); + drawArc (0.0, 7.0, r); } +// ============================================================= +// draw arc around current center. pass angles and radius +//============================================================== void -sgp2_point_abs (double x, double y) +SGP::drawArc (double start, double stop, const double r) { - double xndc, yndc; + 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); + x = xp; y = yp; + } - if (_sgp2_cwin == NULL) - return;; + c = cos (stop - angle); + s = sin (stop - angle); + xp = c * x - s * y; + yp = s * x + c * y; + lineRel (xp - x, yp - y); - wc_to_ndc (x, y, &xndc, &yndc); - pntndc (_sgp2_cwin, xndc, yndc); - _sgp2_cwin->curx = x; - _sgp2_cwin->cury = y; + x = r * cos ((double) stop); + y = r * sin ((double) stop); + moveRel (-x, -y); // move back to center of circle } -void -sgp2_point_rel (double x, double y) + +/////////////////////////////////////////////////////////////////////// +// Coordinate Transformations +/////////////////////////////////////////////////////////////////////// + + +void +SGP::transformNDCtoMC (double* x, double* y) { - sgp2_point_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury); + if (m_bRecalcTransform) + calc_transform(); + ndc_to_mc.transformPoint (x, y); } -/* NAME - * sgp2_draw_rect 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::transformMCtoNDC (double* x, double* y) +{ + if (m_bRecalcTransform) + calc_transform(); + mc_to_ndc.transformPoint (x, y); +} + void -sgp2_draw_rect(double xmin, double ymin, double xmax, double ymax) +SGP::transformMCtoNDC (double xIn, double yIn, double* x, double* y) { - sgp2_move_abs (xmin, ymin); - sgp2_line_abs (xmax, ymin); - sgp2_line_abs (xmax, ymax); - sgp2_line_abs (xmin, ymax); - sgp2_line_abs (xmin, ymin); + if (m_bRecalcTransform) + calc_transform(); + *x = xIn; + *y = yIn; + mc_to_ndc.transformPoint (x, y); } -/* FUNCTION - * sgp2_circle - draw circle of radius r at current center - */ -void -sgp2_draw_circle (const double r) +// NAME +// calc_transform Calculate transform matrices + +void +SGP::calc_transform () { - sgp2_draw_arc (0.0, 7.0, r); + 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; + + mc_to_ndc = m_ctm * wc_to_ndc; + ndc_to_mc = mc_to_ndc.invert(); + + m_bRecalcTransform = false; } -/*==============================================================*/ -/* draw arc around current center. pass angles and radius */ -/*==============================================================*/ +void +SGP::ctmClear () +{ + m_ctm.setIdentity(); + calc_transform(); +} void -sgp2_draw_arc (double start, double stop, const double r) +SGP::ctmSet (const TransformationMatrix2D& m) { - double c, s, theta, angle; - float x, y, xp, yp; + m_ctm = m; + calc_transform(); +} - if ((stop-start) > 2 * PI) - stop = start + 2 * PI; - if ((start-stop) > 2 * PI) - stop = start + 2 * PI; - while (start >= stop) - stop += 2*PI; - x = r * cos ((double) start); - y = r * sin ((double) start); - sgp2_move_rel (x, y); /* move from center to start of arc */ +void +SGP::preTranslate (double x, double y) +{ + TransformationMatrix2D m; - theta = 5 * PI / 180; - c = cos(theta); - s = sin(theta); + m.setTranslate (x, y); + ctmSet (m * m_ctm); +} - for (angle = start; angle < stop - theta; angle += theta) { - xp = c * x - s * y; - yp = s * x + c * y; - sgp2_line_rel (xp - x, yp - y); - x = xp; y = yp; - } - c = cos (stop - angle); - s = sin (stop - angle); - xp = c * x - s * y; - yp = s * x + c * y; - sgp2_line_rel (xp - x, yp - y); +void +SGP::postTranslate (double x, double y) +{ + TransformationMatrix2D m; - x = r * cos ((double) stop); - y = r * sin ((double) stop); - sgp2_move_rel (-x, -y); /* move back to center of circle */ + m.setTranslate (x, y); + ctmSet (m_ctm * m); } -/*----------------------------------------------------------------------*/ -/* Current Transformation Matrix Routine */ -/*----------------------------------------------------------------------*/ +void +SGP::preScale (double sx, double sy) +{ + TransformationMatrix2D m; + m.setScale (sx, sy); + ctmSet (m * m_ctm); +} -/* NAME - * ctm_clr_2 Clear current transformation matrix - * - * SYNOPSIS - * ctm_clr_2() - */ void -ctm_clr_2 (void) +SGP::postScale (double sx, double sy) { - GRFMTX_2D m; + TransformationMatrix2D m; - ident_gmtx_2 (m); - ctm_set_2 (m); + m.setScale (sx, sy); + m_ctm = m_ctm * m; + ctmSet (m_ctm * m); } -/* 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::preRotate (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); + m_ctm = m * m_ctm; + ctmSet (m * m_ctm); } -/* 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::postRotate (double theta) { - int x, y; - if (_sgp2_cwin == NULL) - return; + TransformationMatrix2D m; - for (x = 0; x < 3; x++) - for (y = 0; y < 3; y++) - _sgp2_cwin->ctm_2_x[x][y] = m[x][y]; - - _sgp2_cwin->recalc_ndc_to_mc = TRUE; - _sgp2_cwin->recalc_mc_to_ndc = TRUE; + m.setRotate (theta); + ctmSet (m_ctm * m); } void -ctm_pre_mult_2 (GRFMTX_2D m) +SGP::preShear (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 * m_ctm); } void -ctm_post_mult_2 (GRFMTX_2D m) +SGP::postShear (double shrx, double shry) { - GRFMTX_2D new_ctm; + TransformationMatrix2D m; - mult_gmtx_2 (_sgp2_cwin->ctm_2_x, m, new_ctm); - ctm_set_2 (new_ctm); + m.setShear (shrx, shry); + ctmSet (m_ctm * m); } + + +//////////////////////////////////////////////////////////////////////// +// Bitmap Markers +//////////////////////////////////////////////////////////////////////// + +// 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 +}; diff --git a/libctgraphics/sgpdriver.cpp b/libctgraphics/sgpdriver.cpp deleted file mode 100644 index 76e08ef..0000000 --- a/libctgraphics/sgpdriver.cpp +++ /dev/null @@ -1,528 +0,0 @@ -/***************************************************************************** -** This is part of the CTSim program -** Copyright (C) 1983-2000 Kevin Rosenberg -** -** $Id: sgpdriver.cpp,v 1.1 2000/06/19 19:20:11 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 -** published by the Free Software Foundation. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -******************************************************************************/ - -/* Device Driver for IBM PC Kevin Rosenberg March 84 */ - -#include -#include -#include -#include "ctsupport.h" -#include "sgp.h" - - -static int init_prt(void); -static void term_prt(void); - -/*===========================================================*/ -/* fundamental device drivers */ -/*===========================================================*/ - -#define XCHARSIZ (1.0 / 80.0) /* size of standard characters */ -#define YCHARSIZ (1.0 / 25.0) /* on screen in NDC */ - -#define CRTASPT (0.75) /* for IBM ECD */ - -/*-------------------*/ -/* print buffer data */ -/*-------------------*/ -#define PRTINIT 1 -#define PRTLIN 2 -#define PRTTERM 3 - -#define PRTSIZE 200 -#define PRTMODE 1 /* Epson 120 dot/in graphic mode */ -#define PRTASPT (120.0 / 72.0) /* dots/in vectical / horizontal */ - -static DEVICE crt, prt; -CHARSPEC cspec; -static GRFSTATE state; - - - -/* NAME - * gp_init Initialize graphics package - * - * SYNOPSIS - * gp_init() - */ - - -int -_sgp2_init_dev (SGP_ID cwin) -{ -#if 0 - initdevice (CRTDEV, GM_ENHANCED, 0, 0); - initdevice (PRTDEV, PRTMODE, (int) (PRTSIZE * PRTASPT), PRTSIZE); - opendevice (CRTDEV); - setlinestyle (LS_SOLID); - setcolor (1); - _sgp2_set_text (XCHARSIZ, YCHARSIZ, 0.0, 0); - setbackg (0); - settextclr (1, 0); - gp_set_aspect (CRTDEV, CRTASPT); - gp_set_aspect (PRTDEV, 1.0); -#endif - - state.xndc = 10.; /* to guarntee a move */ - _sgp2_stylus (cwin, 0.0,0.0,0); /* move to starting corner */ - - return (TRUE); -} - - -/* NAME - * gp_initdev Initializes graphic device - * - * SYNOPSIS - * initdevice (dev, mode, xsize, ysize) - * int dev Device handle - * int mode Mode for device (device specific) - * int xsize Size of x buffer for PRTDEV - * int ysize Size of y buffer for PRTDEV - */ - -int -initdevice (int dev, int mode, int xsize, int ysize) -{ - if (dev & CRTDEV) - { - // crt.dotfunc = crt_wdot; - // crt.linefunc = crt_line; - crt.xmin = 0; - crt.ymin = 0; - switch (crt.mode) - { -#if 0 - case 4: - case 5: - crt.xmax = 319; - crt.xsize = 320; - crt.ymax = 199; - crt.ysize = 200; - crt.colormax = 3; - break; - case GM_640x200: - crt.xmax = 639; - crt.xsize = 640; - crt.ymax = 199; - crt.ysize = 200; - crt.colormax = 1; - break; - case GM_ENHANCED: - case GM_MONOGRF: - crt.xmax = 639; - crt.xsize = 640; - crt.ymax = 349; - crt.ysize = 350; - crt.colormax = 15; - break; - case GM_640x480x16: - crt.xmax = 639; - crt.xsize = 640; - crt.ymax = 479; - crt.ysize = 480; - crt.colormax = 15; - break; - case GM_640x480x256: - crt.xmax = 639; - crt.xsize = 640; - crt.ymax = 479; - crt.ysize = 480; - crt.colormax = 255; - break; - case GM_1024x768x16: - crt.xmax = 1023; - crt.xsize = 1024; - crt.ymax = 767; - crt.ysize = 768; - crt.colormax = 15; - break; - case GM_1024x768x256: - crt.xmax = 1023; - crt.xsize = 1024; - crt.ymax = 767; - crt.ysize = 768; - crt.colormax = 255; - break; -#endif - default: - return (FALSE); - } - // crt_set_mode (crt.mode, TRUE); /* Initialize device */ - } - - if (dev & PRTDEV) { - if (prt.open == TRUE) - closedevice (PRTDEV); - prt.buf = NULL; - if (mode < 0) - prt.mode = PRTMODE; - if (mode > 6) - prt.mode = PRTMODE; - else - prt.mode = mode; - - if (xsize > 1 && ysize > 1) { - prt.xsize = xsize; - prt.ysize = ysize; - prt.xmin = 0; - prt.ymin = 0; - prt.xmax = prt.xsize - 1; - prt.ymax = prt.ysize - 1; - } - - prt.colormax = 1; - // prt.dotfunc = prtdot; - // prt.linefunc = prtline; - - init_prt (); /* Initialize the device */ - } - - return (TRUE); -} - - -/* NAME - * gp_opendev Open device for output - * - * SYNOPSIS - * gp_opendev (dev) - * int dev Device handle - * devices are number in powers of two - */ - -int -opendevice (int dev) -{ - if (dev & CRTDEV) - crt.open = TRUE; - - if (dev & PRTDEV) - prt.open = TRUE; - - return(TRUE); -} - - -/* NAME - * gp_closedev Close device for output - * - * SYNOPSIS - * gp_closedev (dev) - * int dev Device handle - * - * DESCRIPTION - * Temporarily suspends output from going to a device - */ - -void -closedevice (int dev) -{ - if (dev & CRTDEV) /* close crt */ - crt.open = FALSE; - - if (dev & PRTDEV) - prt.open = FALSE; -} - - -void -termdevice (int dev) -{ - if (dev & PRTDEV) - term_prt (); -} - -static int init_prt(void) -{ - return(0); -} - - -static void term_prt(void) -{ -} - -/*===========================================================*/ -/* stylus draws a line to the absolute point x,y in NDC's */ -/* t=0 for move, t=1 for draw */ -/*===========================================================*/ -void -_sgp2_stylus (SGP_ID cwin, double x, double y, int beam) -{ - int xp, yp; - - if ((state.xndc == x) && (state.yndc == y) && (beam == 0)) - return; /* no need to move */ - - state.xndc = x; /* save current beam location */ - state.yndc = y; - - if (cwin != NULL) { - xp = (int) (x * cwin->pw_xsize + 0.5); - yp = (int) (y * cwin->pw_ysize + 0.5); -#if HAVE_G2_H - if (beam != 0) - g2_line (cwin->g2_id, (double) cwin->phys_curx, (double) cwin->phys_cury, (double) xp, (double) yp); -#endif - cwin->phys_curx = xp; - cwin->phys_cury = yp; - } -} - -void -pntndc (SGP_ID cwin, double x, double y) -{ - _sgp2_stylus (cwin, x, y, 0); /* move to point */ - // if (crt.open == TRUE) - // cpix_set (crt.icurx, crt.icury, crt.color); -} - -void -markndc (SGP_ID cwin, double x, double y) -{ - _sgp2_stylus (cwin, x, y, 0); /* move to point */ - - if (crt.open == TRUE) - wrtsymbol (state.marktype, crt.icurx, crt.icury, &crt); - - if (prt.open == TRUE) - wrtsymbol (state.marktype, prt.icurx, prt.icury, &prt); -} - -GRFSTATE * -inqstate (void) -{ - return (&state); -} - -void -gp_set_aspect (int dev, double asp) -{ - if (asp > 0.0) { - if (dev & CRTDEV) - crt.asp = asp; - if (dev & PRTDEV) - prt.asp = asp; - } -} - -void -setlinestyle (int style) -{ - if (style == state.linestyle) - return; - - state.linestyle = style; - - crt.style = style; - prt.style = style; - - // crt_line_style (crt.style); -} - -void -setlinewidth (int wid) -{ - state.linewidth = wid; -} - -DEVICE * -inqdev (int dev) -{ - if (dev & CRTDEV) - return (&crt); - else if (dev & PRTDEV) - return (&prt); - else - return (NULL); -} - -/*===========================================================*/ -/* set text size */ -/*===========================================================*/ -void -_sgp2_set_text ( SGP_ID cwin, - double width, - double height, /* size of character in NDC */ - double textangle, /* text angle */ - int font /* text font */ - ) -{ - double temp; - -#if HAVE_G2_H - g2_set_font_size(cwin->g2_id, (height * cwin->pw_ysize)); -#endif - height = clamp (height, 0.0, 1.0); - width = clamp (width, 0.0, 1.0); - /* textangle = textangle - (2 * PI * (int) (textangle / (2 * PI))); - */ - cspec.width = width; - cspec.height = height; - cspec.textangle = textangle; - cspec.font = font; - - if (textangle > - HALFPI / 2 && textangle < HALFPI / 2) { - cspec.updir = YPLUS; - cspec.textdir = XPLUS; - } else if (textangle > HALFPI / 2 && textangle < 3 * HALFPI / 2) { - cspec.updir = XMINUS; - cspec.textdir = YPLUS; - } else if (textangle > 3 * HALFPI / 2 && textangle < 5 * HALFPI / 2) { - cspec.updir = YMINUS; - cspec.textdir = XMINUS; - } else if (textangle > 5 * HALFPI / 2 && textangle < 7 * HALFPI / 2) { - cspec.updir = XPLUS; - cspec.textdir = YMINUS; - } else { - cspec.updir = YPLUS; - cspec.textdir = XPLUS; - } - - if (cspec.updir == XMINUS || cspec.updir == XPLUS) { - temp = height; - height = width; - width = temp; - } - - crt.icwidth = (int) (width * crt.xsize + 0.5); - crt.icheight = (int) (height * crt.ysize + 0.5); - crt.icwidth = clamp (crt.icwidth, 8, crt.xsize); - crt.icheight = clamp (crt.icheight, 8, crt.ysize); - - prt.icwidth = (int) (width * prt.xsize + 0.5); - prt.icheight = (int) (height * prt.ysize + 0.5); - prt.icwidth = clamp (prt.icwidth, 8, prt.xsize); - prt.icheight = clamp (prt.icheight, 8, prt.ysize); -} - -void -settextclr (int fore, int back) -{ - cspec.fore = fore; - cspec.back = back; - crt.cfore = fore; - crt.cback = back; - prt.cfore = clamp (fore, 0, prt.colormax); - prt.cback = back; -} - -void -setcolor (int fore) -{ - int back; - - state.foregnd = fore; - back = state.backgnd; - crtcolor (crt.mode, &fore, &back); /* set colors on crt */ - crt.color = fore; - prt.color = clamp (fore, 0, prt.colormax); -} - -void -setbackg (int back) -{ - int fore; - - state.backgnd = back; - fore = state.foregnd; - crtcolor (crt.mode, &fore, &back); -} - -/* - * INITMARKER () - * - * Sets the current marker symbol (cross, square, diamond..) - */ -int -initmarker (int marker, int color) -{ - if (marker > NMARKERS || marker < 0) - return(-1); - else { - state.marktype = marker; - state.markcolor = color; - } - return(0); -} /* end initmarker */ - -/* - * SETCHARDIR ( ) - * - * indicates in which direction a string should be printed, e.g.: - * direction = YPLUS -> print on the horizontal from left to right - * direction = YMINUS -> print upside-down characters from right to left - * direction = XMINUS -> print on the vertical from down to up - * direction = XPLUS -> print on the vertical from up to down - */ -int -settextdir ( - int direction /* direction flag */ - ) -{ - - if (direction != XPLUS && - direction != XMINUS && - direction != YPLUS && - direction != YMINUS ) { - printf("Error in character direction: %d\n", direction); - return(-1); - } - cspec.textdir = direction; - charsize (cspec.width, cspec.height); - - return(0); -} /* end setchardir */ - - -void -_sgp2_dev_text (SGP_ID cwin, char *message) -{ -#if HAVE_G2_H - g2_string (cwin->g2_id, cwin->phys_curx, cwin->phys_cury, message); -#endif -} - -/*===========================================================*/ -/* terminate graphics to current device */ -/* close any files, and output any buffers */ -/*===========================================================*/ -void -termgrf2 (void) -{ - if (prt.open == TRUE) { - flushdevice (PRTDEV); - closedevice (PRTDEV); - termdevice (PRTDEV); - } - - if (crt.open == TRUE) { - closedevice (CRTDEV); - } -} - - -void -flushdevice (int dev) -{ - // if (dev & PRTDEV) - // prtline (PRTTERM, 0, 0, 0, 0, 0, 0); /* print contents of printer buffer */ -} diff --git a/libctgraphics/sgptext.cpp b/libctgraphics/sgptext.cpp deleted file mode 100644 index 9657a07..0000000 --- a/libctgraphics/sgptext.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/***************************************************************************** -** This is part of the CTSim program -** Copyright (C) 1983-2000 Kevin Rosenberg -** -** $Id: sgptext.cpp,v 1.2 2000/06/19 19:04:05 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 -** published by the Free Software Foundation. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -******************************************************************************/ - -/* FILE - * sgptext.c Text routines for graphics package - */ - -#include -#include "ctsupport.h" -#include "sgp.h" - - -/* Pixel patterns of marker symbols (1x1 to 5x5 matrix) */ -char MARKER[NMARKERS][5] = { - { '\0', '\0', '\010', '\0', '\0'}, /* small dot */ - { '\0', '\034', '\024', '\034', '\0'}, /* empty square */ - { '\0', '\034', '\034', '\034', '\0'}, /* filled square */ - { '\0', '\010', '\024', '\010', '\0'}, /* empty diamond */ - { '\0', '\010', '\034', '\010', '\0'}, /* filled diamond */ - { '\010', '\010', '\076', '\010', '\010'}, /* cross */ - { '\0', '\024', '\010', '\024', '\0'}, /* 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 */ - -/* WRTSYMBOL (sym, x, y, dev) - * - * puts marker symbols on the screen - * input in screen pixels - * Calls: dot() - */ - -void -wrtsymbol ( - int sym, - int x, - int y, /* Coordinates in screen pixels */ - DEVICE *dev -) -{ -} - -/* - * WRTCHAR(, , , cspec, dev) - * - * puts marker symbols on the screen - * input in screen pixels - * Calls: dot(), peek() - */ - -void -wrtchar ( - int ch, /* Character to be put on the screen */ - int x, - int y, /* Coordinates in screen pixels of lower left corner*/ - CHARSPEC *cspec, - DEVICE *dev -) -{ -} - -/* - * WRTTEXT () - * - * prints a string starting from current position writing in the current - * printing direction (at right angle to the character direction) - * The pen is return to the original position. - */ - -void -wrttext (char txtstr[], int x, int y, CHARSPEC *cspec, DEVICE *dev) -{ -} - - -/* - * SETCOLOR( ) - * - * Set current color - */ -void -crtcolor (int mode, int *f, int *b) -{ -} diff --git a/libctgraphics/transformmatrix.cpp b/libctgraphics/transformmatrix.cpp new file mode 100644 index 0000000..12c5192 --- /dev/null +++ b/libctgraphics/transformmatrix.cpp @@ -0,0 +1,159 @@ +/***************************************************************************** +** FILE IDENTIFICATION +** +** Name: transformmatrix.cpp +** Function: Transform Matrix routine for graphic library +** Programmer: Kevin Rosenberg +** Date Started: 1-22-85 +** +** This is part of the CTSim program +** Copyright (C) 1983-2000 Kevin Rosenberg +** +** $Id: transformmatrix.cpp,v 1.1 2000/07/28 08:28:08 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 +** published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +******************************************************************************/ + +#include "ctsupport.h" +#include "transformmatrix.h" +#include + + +TransformationMatrix2D::TransformationMatrix2D (double m[3][3]) +{ + mtx[0][0] = m[0][0]; mtx[0][1] = m[0][1]; mtx[0][2] = m[0][2]; + mtx[1][0] = m[1][0]; mtx[1][1] = m[1][1]; mtx[1][2] = m[1][2]; + mtx[2][0] = m[2][0]; mtx[2][1] = m[2][1]; mtx[2][2] = m[2][2]; +} + +void +TransformationMatrix2D::setTranslate (double x, double y) +{ + setIdentity(); + mtx[2][0] = x; + mtx[2][1] = y; +} + + +void +TransformationMatrix2D::setScale (double sx, double sy) +{ + setIdentity(); + mtx[0][0] = sx; + mtx[1][1] = sy; +} + + +void +TransformationMatrix2D::setShear (double shrx, double shry) +{ + setIdentity(); + mtx[1][0] = shrx; + mtx[0][1] = shry; +} + +void +TransformationMatrix2D::setRotate (double theta) +{ + double s = sin (theta); + double c = cos (theta); + + setIdentity(); + + mtx[0][0] = c; mtx[0][1] = s; + mtx[1][0] = -s; mtx[1][1] = c; +} + + +void +TransformationMatrix2D::setIdentity () +{ + mtx[0][0] = 1.; mtx[0][1] = 0.; mtx[0][2] = 0.; + mtx[1][0] = 0.; mtx[1][1] = 1.; mtx[1][2] = 0.; + mtx[2][0] = 0.; mtx[2][1] = 0.; mtx[2][2] = 1.; +} + + +const TransformationMatrix2D +TransformationMatrix2D::invert () const +{ + double b[3][3]; + + double determ = determinant (); + if (fabs(determ) < 1E-6) { + sys_error (ERR_WARNING, "Determinant = %g [TransformationMatrix2D::invert]", determ); + print (cout); + cout << endl; + } + + b[0][0] = (mtx[1][1] * mtx[2][2] - mtx[2][1] * mtx[1][2]) / determ; + b[1][0] = -(mtx[1][0] * mtx[2][2] - mtx[2][0] * mtx[1][2]) / determ; + b[2][0] = (mtx[1][0] * mtx[2][1] - mtx[2][0] * mtx[1][1]) / determ; + + b[0][1] = -(mtx[0][1] * mtx[2][2] - mtx[2][1] * mtx[0][2]) / determ; + b[1][1] = (mtx[0][0] * mtx[2][2] - mtx[2][0] * mtx[0][2]) / determ; + b[2][1] = -(mtx[0][0] * mtx[2][1] - mtx[2][0] * mtx[0][1]) / determ; + + b[0][2] = (mtx[0][1] * mtx[1][2] - mtx[1][1] * mtx[0][2]) / determ; + b[1][2] = -(mtx[0][0] * mtx[1][2] - mtx[1][0] * mtx[0][2]) / determ; + b[2][2] = (mtx[0][0] * mtx[1][1] - mtx[1][0] * mtx[0][1]) / determ; + + return TransformationMatrix2D (b); +} + + +double +TransformationMatrix2D::determinant () const +{ + return + (mtx[0][0] * mtx[1][1] * mtx[2][2] - mtx[0][0] * mtx[2][1] * mtx[1][2] - + mtx[0][1] * mtx[1][0] * mtx[2][2] + mtx[0][1] * mtx[2][0] * mtx[1][2] + + mtx[0][2] * mtx[1][0] * mtx[2][1] - mtx[0][2] * mtx[2][0] * mtx[1][1]); +} + + +void +TransformationMatrix2D::transformPoint (double* pX, double *pY) const +{ + double x = *pX * mtx[0][0] + *pY * mtx[1][0] + mtx[2][0]; + double y = *pX * mtx[0][1] + *pY * mtx[1][1] + mtx[2][1]; + + *pX = x; + *pY = y; +} + +void +TransformationMatrix2D::print (ostream& ostr) const +{ + cout << mtx[0][0] << " " << mtx[0][1] << " " << mtx[0][2] << endl; + cout << mtx[1][0] << " " << mtx[1][1] << " " << mtx[1][2] << endl; + cout << mtx[2][0] << " " << mtx[2][1] << " " << mtx[2][2] << endl; +} + + +// Friend of TransformMatrix2D + +const TransformationMatrix2D operator* (const TransformationMatrix2D& a, const TransformationMatrix2D& b) +{ + double c[3][3]; + + for (int row = 0; row < 3; row++) + for (int col = 0; col < 3; col++) { + c[row][col] = 0.; + for (int calc = 0; calc < 3; calc++) + c[row][col] += a.mtx[row][calc] * b.mtx[calc][col]; + } + + return TransformationMatrix2D (c); +} diff --git a/libctsim/phantom.cpp b/libctsim/phantom.cpp index 2063683..f8b1278 100644 --- a/libctsim/phantom.cpp +++ b/libctsim/phantom.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phantom.cpp,v 1.10 2000/07/22 15:45:33 kevin Exp $ +** $Id: phantom.cpp,v 1.11 2000/07/28 08:28:08 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 @@ -306,29 +306,12 @@ Phantom::print () const void Phantom::show () const { - double wsize = m_xmax - m_xmin; - double xmin = m_xmin; - double ymin = m_ymin; - double xmax, ymax; - SGP_ID gid; - - if ((m_ymax - m_ymin) > wsize) - wsize = m_ymax - m_ymin; - wsize *= 1.1; - - xmax = xmin + wsize; - ymax = ymin + wsize; - - printf("Drawing Phantom:\n\n"); - printf(" data limits: %9.3g, %9.3g, %9.3g, %9.3g\n", m_xmin, m_ymin, m_xmax, m_ymax); - printf(" window size: %9.3g, %9.3g, %9.3g, %9.3g\n", xmin, ymin, xmax, ymax); - - gid = sgp2_init (0, 0, "Phantom Show"); - sgp2_window (xmin, ymin, xmax, ymax); + SGPDriver driverSGP ("Phantom Show"); + SGP sgp (driverSGP); + draw (sgp); - draw(); - - sgp2_close (gid); + cout << "Press return to continue"; + cio_kb_getc(); } #endif @@ -342,10 +325,22 @@ Phantom::show () const #ifdef HAVE_SGP void -Phantom::draw () const +Phantom::draw (SGP& sgp) const { + double wsize = m_xmax - m_xmin; + double xmin = m_xmin; + double ymin = m_ymin; + + if ((m_ymax - m_ymin) > wsize) + wsize = m_ymax - m_ymin; + wsize *= 1.1; + + double xmax = xmin + wsize; + double ymax = ymin + wsize; + + sgp.setWindow (xmin, ymin, xmax, ymax); for (PElemIterator i = m_listPElem.begin(); i != m_listPElem.end(); i++) - sgp2_polyline_abs ((*i)->xOutline(), (*i)->yOutline(), (*i)->nOutlinePoints()); + sgp.polylineAbs ((*i)->xOutline(), (*i)->yOutline(), (*i)->nOutlinePoints()); } #endif diff --git a/libctsim/projections.cpp b/libctsim/projections.cpp index a29d7c5..35d8418 100644 --- a/libctsim/projections.cpp +++ b/libctsim/projections.cpp @@ -8,7 +8,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: projections.cpp,v 1.15 2000/07/15 08:36:13 kevin Exp $ +** $Id: projections.cpp,v 1.16 2000/07/28 08:28:08 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 @@ -515,7 +515,6 @@ Projections::reconstruct (ImageFile& im, const char* const filterName, double fi cout << "Reconstruct: filter="<= TRACE_TEXT) { @@ -555,26 +557,30 @@ Projections::reconstruct (ImageFile& im, const char* const filterName, double fi #ifdef HAVE_SGP if (trace >= TRACE_PLOT) { - ezset ("clear."); - ezset ("xticks major 5."); - ezset ("xlabel "); - ezset ("ylabel "); - ezset ("xlength .5."); - ezset ("box."); - ezset ("grid."); - ezset ("ufinish yes."); - ezplot (detval, plot_xaxis, m_nDet); - ezset ("clear."); - ezset ("xticks major 5."); - ezset ("xlabel "); - ezset ("ylabel "); - ezset ("ustart yes."); - ezset ("xporigin .5."); - ezset ("xlength .5."); - ezset ("box"); - - ezset ("grid"); - gid = ezplot (filteredProj, plot_xaxis, n_filteredProj); + SGPDriver sgpDriverProj ("Projection"); + SGP sgpProj (sgpDriverProj); + EZPlot ezplotProj (sgpProj); + + ezplotProj.ezset ("clear"); + ezplotProj.ezset ("xticks major 5."); + ezplotProj.ezset ("xlabel "); + ezplotProj.ezset ("ylabel "); + ezplotProj.ezset ("xlength .5."); + ezplotProj.ezset ("box."); + ezplotProj.ezset ("grid."); + ezplotProj.addCurve (detval, plot_xaxis, m_nDet); + ezplotProj.ezset ("clear."); + ezplotProj.ezset ("xticks major 5."); + ezplotProj.ezset ("xlabel "); + ezplotProj.ezset ("ylabel "); + ezplotProj.ezset ("xporigin .5."); + ezplotProj.ezset ("xlength .5."); + ezplotProj.ezset ("box"); + ezplotProj.ezset ("grid"); + ezplotProj.addCurve (filteredProj, plot_xaxis, n_filteredProj); + ezplotProj.plot (); + cout << "Press enter to continue\n"; + cio_kb_getc(); } #endif //HAVE_SGP @@ -597,7 +603,6 @@ Projections::reconstruct (ImageFile& im, const char* const filterName, double fi char str[256]; printf ("Do you want to exit with current pic (y/n) -- "); fgets(str, sizeof(str), stdin); - sgp2_close (sgp2_get_active_win()); if (tolower(str[0]) == 'y') { break; } diff --git a/libctsim/scanner.cpp b/libctsim/scanner.cpp index ae665f2..d4a398e 100644 --- a/libctsim/scanner.cpp +++ b/libctsim/scanner.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: scanner.cpp,v 1.5 2000/07/22 15:45:33 kevin Exp $ +** $Id: scanner.cpp,v 1.6 2000/07/28 08:28:08 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 @@ -180,7 +180,7 @@ Scanner::convertGeometryNameToID (const char* const geomName) */ void -Scanner::collectProjections (Projections& proj, const Phantom& phm, const int start_view, const int trace) +Scanner::collectProjections (Projections& proj, const Phantom& phm, const int start_view, const int trace = TRACE_NONE, SGP* pSGP = NULL) { GRFMTX_2D rotmtx_initial, temp; GRFMTX_2D rotmtx_incr; @@ -201,23 +201,21 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int st m_trace = trace; #ifdef HAVE_SGP - SGP_ID gid; - if (m_trace >= TRACE_PHM) { + if (pSGP && m_trace >= TRACE_PHM) { double wsize = 1.42 * m_phmLen / 2; /* sqrt(2) * radius */ - - gid = sgp2_init (512, 512, "RayCollect"); - sgp2_color (C_LTBLUE); - sgp2_window (xcent - wsize, ycent - wsize, xcent + wsize, ycent + wsize); - sgp2_color (C_BROWN); + + pSGP->setColor (C_LTBLUE); + pSGP->setWindow (xcent - wsize, ycent - wsize, xcent + wsize, ycent + wsize); + pSGP->setColor (C_BROWN); #if RADIUS - sgp2_draw_circle (m_phmLen / 2); + pSGP->drawCircle (m_phmLen / 2); #else - sgp2_draw_rect (xcent - m_phmLen / 2, ycent - m_phmLen / 2, + pSGP->drawRect (xcent - m_phmLen / 2, ycent - m_phmLen / 2, xcent + m_phmLen / 2, ycent + m_phmLen / 2); #endif - sgp2_color (C_BROWN); - sgp2_move_abs (0., 0.); - sgp2_draw_circle (wsize); + pSGP->setColor (C_BROWN); + pSGP->moveAbs (0., 0.); + pSGP->drawCircle (wsize); // raysum_trace_menu_column = (crt->xsize * crt->asp) / 8 + 3; traceShowParam ("X-Ray Simulator", "%s", RAYSUM_TRACE_ROW_TITLE, 8+C_LTWHITE, " "); traceShowParam ("---------------", "%s", RAYSUM_TRACE_ROW_TITLE2, 8+C_LTWHITE, " "); @@ -229,10 +227,10 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int st traceShowParam ("Num Views :", "%5d", RAYSUM_TRACE_ROW_NVIEW, C_LTRED, proj.nView()); traceShowParam ("Samples / Ray:", "%5d", RAYSUM_TRACE_ROW_SAMPLES, C_LTRED, m_nSample); - sgp2_color (C_LTGREEN); - phm.draw(); + pSGP->setColor (C_LTGREEN); + phm.draw (*pSGP); - initmarker (BDIAMOND, 129); + pSGP->setMarker (SGP::MARK_BDIAMOND, C_LTGREEN); } #endif @@ -261,26 +259,26 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int st DetectorArray& detArray = proj.getDetectorArray( iview ); #ifdef HAVE_SGP - if (m_trace >= TRACE_PHM) { - sgp2_move_abs (xd1, yd1); - sgp2_line_abs (xd2, yd2); - sgp2_move_abs (xs1, ys1); - sgp2_line_abs (xs2, ys2); + if (pSGP && m_trace >= TRACE_PHM) { + pSGP->moveAbs (xd1, yd1); + pSGP->lineAbs (xd2, yd2); + pSGP->moveAbs (xs1, ys1); + pSGP->lineAbs (xs2, ys2); } #endif if (m_trace) traceShowParam ("Current View :", "%5d", RAYSUM_TRACE_ROW_CURR_VIEW, C_LTMAGENTA, iview); - projectSingleView (phm, detArray, xd1, yd1, xd2, yd2, xs1, ys1, xs2, ys2); + projectSingleView (phm, detArray, xd1, yd1, xd2, yd2, xs1, ys1, xs2, ys2, pSGP); detArray.setViewAngle (viewAngle); #ifdef HAVE_SGP - if (m_trace >= TRACE_PHM) { + if (pSGP && m_trace >= TRACE_PHM) { // rs_plot (detArray, xd1, yd1, xcent, ycent, theta); - sgp2_move_abs (xd1, yd1); - sgp2_line_abs (xd2, yd2); - sgp2_move_abs (xs1, ys1); - sgp2_line_abs (xs2, ys2); + pSGP->moveAbs (xd1, yd1); + pSGP->lineAbs (xd2, yd2); + pSGP->moveAbs (xs1, ys1); + pSGP->lineAbs (xs2, ys2); } #endif xform_mtx2 (rotmtx_incr, xd1, yd1); // rotate detector endpoints @@ -315,7 +313,7 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int st */ void -Scanner::projectSingleView (const Phantom& phm, DetectorArray& detArray, const double xd1, const double yd1, const double xd2, const double yd2, const double xs1, const double ys1, const double xs2, const double ys2) +Scanner::projectSingleView (const Phantom& phm, DetectorArray& detArray, const double xd1, const double yd1, const double xd2, const double yd2, const double xs1, const double ys1, const double xs2, const double ys2, SGP* pSGP) { double ddx = (xd2 - xd1) / detArray.nDet(); // change in coords between detectors double ddy = (yd2 - yd1) / detArray.nDet(); @@ -349,20 +347,20 @@ Scanner::projectSingleView (const Phantom& phm, DetectorArray& detArray, const d double sum = 0.0; for (unsigned int i = 0; i < m_nSample; i++) { #ifdef HAVE_SGP - if (m_trace >= TRACE_RAYS) { - sgp2_move_abs (xs, ys); - sgp2_line_abs (xd, yd); + if (pSGP && m_trace >= TRACE_RAYS) { + pSGP->moveAbs (xs, ys); + pSGP->lineAbs (xd, yd); } #endif - sum += projectSingleLine (phm, xd, yd, xs, ys); + sum += projectSingleLine (phm, xd, yd, xs, ys, pSGP); if (m_trace >= TRACE_RAYS) traceShowParam ("Attenuation :", "%5.2f", RAYSUM_TRACE_ROW_ATTEN, C_LTMAGENTA, "sum"); #ifdef HAVE_SGP - if (m_trace >= TRACE_RAYS) { - sgp2_move_abs (xs, ys); - sgp2_line_abs (xd, yd); + if (pSGP && m_trace >= TRACE_RAYS) { + pSGP->moveAbs (xs, ys); + pSGP->lineAbs (xd, yd); } #endif xd += ddx2; @@ -393,7 +391,7 @@ Scanner::traceShowParam (const char *label, const char *fmt, int row, int color, vsnprintf (s, sizeof(s), fmt, arg); // cio_set_text_clr (color, 0); cio_put_str (s); - + cout << "\n"; va_end(arg); } @@ -409,12 +407,12 @@ Scanner::traceShowParam (const char *label, const char *fmt, int row, int color, */ double -Scanner::projectSingleLine (const Phantom& phm, const double x1, const double y1, const double x2, const double y2) +Scanner::projectSingleLine (const Phantom& phm, const double x1, const double y1, const double x2, const double y2, SGP* pSGP) { // check ray against each pelem in Phantom double rsum = 0.0; for (PElemConstIterator i = phm.listPElem().begin(); i != phm.listPElem().end(); i++) - rsum += projectLineAgainstPElem (**i, x1, y1, x2, y2); + rsum += projectLineAgainstPElem (**i, x1, y1, x2, y2, pSGP); return (rsum); } @@ -431,7 +429,7 @@ Scanner::projectSingleLine (const Phantom& phm, const double x1, const double y1 */ double -Scanner::projectLineAgainstPElem (const PhantomElement& pelem, double x1, double y1, double x2, double y2) +Scanner::projectLineAgainstPElem (const PhantomElement& pelem, double x1, double y1, double x2, double y2, SGP* pSGP) { if (! pelem.clipLineWorldCoords (x1, y1, x2, y2)) { if (m_trace == TRACE_CLIPPING) @@ -440,12 +438,12 @@ Scanner::projectLineAgainstPElem (const PhantomElement& pelem, double x1, double } #ifdef HAVE_SGP - if (m_trace == TRACE_CLIPPING) { - sgp2_move_abs (x1, y1); - sgp2_line_abs (x2, y2); + if (pSGP && m_trace == TRACE_CLIPPING) { + pSGP->moveAbs (x1, y1); + pSGP->lineAbs (x2, y2); cio_tone (8000., 0.05); - sgp2_move_abs (x1, y1); - sgp2_line_abs (x2, y2); + pSGP->moveAbs (x1, y1); + pSGP->lineAbs (x2, y2); } #endif diff --git a/man/Makefile.am b/man/Makefile.am index 18b5ae4..825aa32 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -1,3 +1,2 @@ man_MANS=ctrec.1 phm2rs.1 phm2if.1 if2img.1 ifinfo.1 if-1.1 -info_INFO=ctsim.texi -EXTRA_DIST = $(man_MANS) $(info_INFO) +EXTRA_DIST = $(man_MANS) diff --git a/src/dialogs.h b/src/dialogs.h index e942d33..6dcc298 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: dialogs.h,v 1.7 2000/07/22 16:14:49 kevin Exp $ +** $Id: dialogs.h,v 1.8 2000/07/28 08:28:08 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 @@ -132,6 +132,7 @@ class DialogGetProjectionParameters : public wxDialog }; +#include "backprojectors.h" class DialogGetReconstructionParameters : public wxDialog { public: diff --git a/src/views.cpp b/src/views.cpp index 536db90..8ec1df2 100644 --- a/src/views.cpp +++ b/src/views.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: views.cpp,v 1.8 2000/07/22 15:45:33 kevin Exp $ +** $Id: views.cpp,v 1.9 2000/07/28 08:28:08 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 @@ -341,7 +341,7 @@ ImageFileView::OnClose (bool deleteWindow) // PhantomCanvas PhantomCanvas::PhantomCanvas (PhantomView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style) - : wxPanel(frame, -1, pos, size, style) + : wxScrolledWindow(frame, -1, pos, size, style) { m_pView = v; } @@ -353,6 +353,7 @@ PhantomCanvas::OnDraw(wxDC& dc) m_pView->OnDraw(& dc); } + // PhantomView IMPLEMENT_DYNAMIC_CLASS(PhantomView, wxView) @@ -518,15 +519,8 @@ PhantomView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) m_frame->Show(true); Activate(true); - - return true; -} -void -PhantomView::OnDraw (wxDC* dc) -{ - // if (m_bitmap.Ok()) - // dc->DrawBitmap (m_bitmap, 0, 0, false); + return true; } @@ -560,6 +554,16 @@ PhantomView::OnClose (bool deleteWindow) return true; } +void +PhantomView::OnDraw (wxDC* dc) +{ + int xsize, ysize; + m_canvas->GetClientSize (&xsize, &ysize); + SGPDriver driver (dc, "", xsize, ysize); + SGP sgp (driver); + const Phantom& rPhantom = GetDocument()->getPhantom(); + rPhantom.draw (sgp); +} // ProjectionCanvas diff --git a/src/views.h b/src/views.h index 4375133..3c29c77 100644 --- a/src/views.h +++ b/src/views.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: views.h,v 1.5 2000/07/18 16:20:53 kevin Exp $ +** $Id: views.h,v 1.6 2000/07/28 08:28:08 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 @@ -144,9 +144,9 @@ public: virtual ~PhantomView(void); bool OnCreate(wxDocument *doc, long flags); - void OnDraw(wxDC* dc); void OnUpdate(wxView *sender, wxObject *hint = NULL); bool OnClose (bool deleteWindow = true); + void OnDraw(wxDC* dc); void OnProperties (wxCommandEvent& event); void OnRasterize (wxCommandEvent& event); void OnProjections (wxCommandEvent& event); @@ -157,12 +157,13 @@ public: DECLARE_EVENT_TABLE() }; -class PhantomCanvas: public wxPanel +class PhantomCanvas: public wxScrolledWindow { public: PhantomView* m_pView; PhantomCanvas (PhantomView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style); + virtual void OnDraw(wxDC& dc); }; diff --git a/tools/if-2.cpp b/tools/if-2.cpp index 525330e..2558360 100644 --- a/tools/if-2.cpp +++ b/tools/if-2.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: if-2.cpp,v 1.1 2000/07/13 07:01:35 kevin Exp $ +** $Id: if-2.cpp,v 1.2 2000/07/28 08:28:08 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 @@ -228,22 +228,20 @@ if2_main (int argc, char *const argv[]) for (int i = 0; i < nx; i++) plot_xaxis[i] = i; #if HAVE_SGP -#if 0 -#else - ezset ("clear."); - ezset ("xticks major 5."); - ezset ("xlabel Column"); - ezset ("ylabel Pixel"); - ezset ("curves 2"); - ezset ("box."); - ezset ("grid."); - ezplot (v1[opt_columnPlot], plot_xaxis, im_in1.ny()); - ezplot (v2[opt_columnPlot], plot_xaxis, im_in2.ny()); -#endif - char str[256]; + SGPDriver driver ("Column Plot"); + SGP sgp (driver); + EZPlot ezplot (sgp); + ezplot.ezset ("clear."); + ezplot.ezset ("xticks major 5."); + ezplot.ezset ("xlabel Column"); + ezplot.ezset ("ylabel Pixel"); + ezplot.ezset ("curves 2"); + ezplot.ezset ("box."); + ezplot.ezset ("grid."); + ezplot.addCurve (v1[opt_columnPlot], plot_xaxis, im_in1.ny()); + ezplot.addCurve (v2[opt_columnPlot], plot_xaxis, im_in2.ny()); cout << "Press enter to continue" << flush; - fgets(str, sizeof(str), stdin); - sgp2_close (sgp2_get_active_win()); + cio_kb_getc(); #endif } @@ -263,22 +261,20 @@ if2_main (int argc, char *const argv[]) v2Row[i] = v2[opt_rowPlot][i]; #if HAVE_SGP -#if 0 -#else - ezset ("clear."); - ezset ("xticks major 5."); - ezset ("xlabel Column"); - ezset ("ylabel Pixel"); - ezset ("curves 2"); - ezset ("box."); - ezset ("grid."); - ezplot (v1Row, plot_xaxis, im_in1.nx()); - ezplot (v2Row, plot_xaxis, im_in2.nx()); -#endif - char str[256]; + SGPDriver driver ("Column Plot"); + SGP sgp (driver); + EZPlot ezplot (sgp); + ezplot.ezset ("clear."); + ezplot.ezset ("xticks major 5."); + ezplot.ezset ("xlabel Column"); + ezplot.ezset ("ylabel Pixel"); + ezplot.ezset ("curves 2"); + ezplot.ezset ("box."); + ezplot.ezset ("grid."); + ezplot.addCurve (v1Row, plot_xaxis, im_in1.nx()); + ezplot.addCurve (v2Row, plot_xaxis, im_in2.nx()); cout << "Press enter to continue" << flush; - fgets(str, sizeof(str), stdin); - sgp2_close (sgp2_get_active_win()); + cio_kb_getc(); #endif } diff --git a/tools/if2img.cpp b/tools/if2img.cpp index b00c177..fcf214d 100644 --- a/tools/if2img.cpp +++ b/tools/if2img.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: if2img.cpp,v 1.1 2000/07/13 07:01:35 kevin Exp $ +** $Id: if2img.cpp,v 1.2 2000/07/28 08:28:08 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 @@ -357,7 +357,6 @@ if2img_main (int argc, char *const argv[]) im.displayScaling (opt_scale, densmin, densmax); cout << "Press enter to continue\n"; cio_kb_getc(); - sgp2_close(sgp2_get_active_win()); #endif } else diff --git a/tools/phm2pj.cpp b/tools/phm2pj.cpp index 4624611..4c12ecf 100644 --- a/tools/phm2pj.cpp +++ b/tools/phm2pj.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phm2pj.cpp,v 1.4 2000/07/23 01:49:03 kevin Exp $ +** $Id: phm2pj.cpp,v 1.5 2000/07/28 08:28:08 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 @@ -285,7 +285,24 @@ phm2pj_main (int argc, char* argv[]) #else Projections pjGlobal (scanner); - scanner.collectProjections (pjGlobal, phm, 0, opt_trace); + + SGPDriver* pSGPDriver = NULL; + SGP* pSGP = NULL; + + if (opt_trace >= TRACE_PHM) { + pSGPDriver = new SGPDriver ("phm2pj"); + pSGP = new SGP (*pSGPDriver); + } + + scanner.collectProjections (pjGlobal, phm, 0, opt_trace, pSGP); + + if (opt_trace >= TRACE_PHM) { + cout << "Press enter to continue\n"; + cio_kb_getc(); + delete pSGP; pSGP = NULL; + delete pSGPDriver; pSGPDriver = NULL; + } + #endif #ifdef HAVE_MPI diff --git a/tools/pjrec.cpp b/tools/pjrec.cpp index 03ee9e8..1cc9bd2 100644 --- a/tools/pjrec.cpp +++ b/tools/pjrec.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: pjrec.cpp,v 1.5 2000/07/22 15:45:33 kevin Exp $ +** $Id: pjrec.cpp,v 1.6 2000/07/28 08:28:08 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 @@ -89,6 +89,9 @@ pjrec_usage (const char *program) #endif cout << " --zeropad n Set zeropad level (default = 0)\n"; cout << " set n to number of powers to two to pad\n"; + cout << " --frequency-filter Set type of frequency filter\n"; + cout << " direct Use direct frequency filter\n"; + cout << " ifourier Use inverse fourier transform of spatial filter\n"; cout << " --backproj Backprojection Method" << endl; cout << " trig Trigometric functions at every point" << endl; cout << " table Trigometric functions with precalculated table" << endl; -- 2.34.1