From 6bfb747f8163381d94a02c03a0351e9ca6815d22 Mon Sep 17 00:00:00 2001 From: "Kevin M. Rosenberg" Date: Sun, 27 Aug 2000 20:32:55 +0000 Subject: [PATCH] r185: *** empty log message *** --- ChangeLog | 9 +- INSTALL | 2 +- include/procsignal.h | 13 +- include/projections.h | 4 +- include/scanner.h | 88 +++++---- include/sgp.h | 10 +- include/trace.h | 45 +++-- libctgraphics/sgp.cpp | 98 +++++++-- libctsim/phantom.cpp | 7 +- libctsim/procsignal.cpp | 32 +-- libctsim/projections.cpp | 38 ++-- libctsim/scanner.cpp | 417 +++++++++++++++++++++++---------------- libctsim/trace.cpp | 93 ++++++--- src/Makefile.am | 2 +- src/dialogs.cpp | 72 ++++--- src/dialogs.h | 9 +- src/dlgprojections.cpp | 186 +++++++++++++++++ src/dlgprojections.h | 100 ++++++++++ src/views.cpp | 48 +++-- tools/phm2if.cpp | 18 +- tools/phm2pj.cpp | 20 +- tools/pjrec.cpp | 20 +- 22 files changed, 946 insertions(+), 385 deletions(-) create mode 100644 src/dlgprojections.cpp create mode 100644 src/dlgprojections.h diff --git a/ChangeLog b/ChangeLog index 9c6984f..bd59494 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,12 @@ -2.0.0-b10 - 8/31/00 +2.0.0-b10 - 8/25/00 + ctsim: Added animation of projection collection processs ctsim: Added Auto Scaling for image windows - ctsim: Change title from "windowing" to "display scaling" + ctsim: Change menus from "windowing" to "display scaling" Added FieldOfView and FocalLength ratio parameters to projection collection + Added FocalLength & FieldOfView fields to projection data files + Added Projection collection for Equilinear and Equiangular geometries Changed name of Rowland Phantom to correct name of Shepp-Logan - Added data collection for equilinear scanner geometry Fixed bug in backprojection selection - Improved projection collection animation 2.0.0-b9 - 8/22/00 Added RCS Id strings to executable files diff --git a/INSTALL b/INSTALL index d797072..160aa2d 100644 --- a/INSTALL +++ b/INSTALL @@ -18,7 +18,7 @@ fftw (http://www.fftw.org) wxWindows (http://www.wxwindows.org) Used by CTSim (src/*) graphic front-end. Platform independent for - UNIX and Windows + GTK, Motif, and Windows32 API's. g2 (http://g2.sourceforge.net) Currently, used partially by SGP (Simple Graphics Package) for diff --git a/include/procsignal.h b/include/procsignal.h index 8995dd6..e8e9679 100644 --- a/include/procsignal.h +++ b/include/procsignal.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: procsignal.h,v 1.2 2000/08/22 07:02:48 kevin Exp $ +** $Id: procsignal.h,v 1.3 2000/08/27 20:32:54 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 @@ -58,14 +58,14 @@ class ProcessSignal { static const int FILTER_GENERATION_DIRECT; static const int FILTER_GENERATION_INVERSE_FOURIER; - ProcessSignal (const char* szFilterName, const char* szFilterMethodName,double bw, double signalIncrement, int n, double param, const char* szDomainName, const char* szFilterGenerationName, const int zeropad = 0, const int preinterpolationFactor = 1, const int iTraceLevel = TRACE_NONE); + ProcessSignal (const char* szFilterName, const char* szFilterMethodName,double bw, double signalIncrement, int n, double param, const char* szDomainName, const char* szFilterGenerationName, const int zeropad = 0, const int preinterpolationFactor = 1, const int iTraceLevel = Trace::TRACE_NONE, int iGeometry = Scanner::GEOMETRY_PARALLEL); - ProcessSignal (const int idFilter, int idFilterMethod, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const int idDomain, int idFilterGeneration, const int iZeropad = 0, const int iPreinterpolationFactor = 1, const int iTraceLevel = TRACE_NONE); + ProcessSignal (const int idFilter, int idFilterMethod, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const int idDomain, int idFilterGeneration, const int iZeropad = 0, const int iPreinterpolationFactor = 1, const int iTraceLevel = Trace::TRACE_NONE); ~ProcessSignal(); - void filterSignal (const double input[], double output[]) const; - void filterSignal (const float input[], double output[]) const; + void filterSignal (const double input[], double output[], int view =0) const; + void filterSignal (const float input[], double output[], int view = 0) const; bool fail(void) const {return m_fail;} const string& failMessage(void) const {return m_failMessage;} @@ -132,6 +132,7 @@ class ProcessSignal { int m_iZeropad; int m_nOutputPoints; int m_iPreinterpolationFactor; + int m_idGeometry; bool m_fail; string m_failMessage; @@ -150,7 +151,7 @@ class ProcessSignal { fftw_plan m_complexPlanForward, m_complexPlanBackward; #endif - void init (const int idFilter, int idFilterMethod, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const int idDomain, int idFilterGeneration, const int iZeropad, const int iPreinterpolationFactor, const int iTraceLevel); + void init (const int idFilter, int idFilterMethod, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const int idDomain, int idFilterGeneration, const int iZeropad, const int iPreinterpolationFactor, const int iTraceLevel, const int iGeometry); // transforms that use precalculated trig tables, therefore don't // require number of data points (n) as an argument diff --git a/include/projections.h b/include/projections.h index cb08fb4..38828a1 100644 --- a/include/projections.h +++ b/include/projections.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: projections.h,v 1.11 2000/08/03 09:57:33 kevin Exp $ +** $Id: projections.h,v 1.12 2000/08/27 20:32:55 kevin Exp $ ** ** ** This program is free software; you can redistribute it and/or modify @@ -95,6 +95,8 @@ class Projections double m_detStart; // distance of beginning detector to center phantom double m_detInc; // increment between detectors double m_phmLen; // Length of phantom edge (phm is square) + double m_focalLength; + double m_fieldOfView; kuint32 m_year; // Creation date & time kuint32 m_month; kuint32 m_day; diff --git a/include/scanner.h b/include/scanner.h index 79eee68..fa6ea1d 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.12 2000/08/25 15:59:13 kevin Exp $ +** $Id: scanner.h,v 1.13 2000/08/27 20:32:55 kevin Exp $ ** ** ** This program is free software; you can redistribute it and/or modify @@ -45,12 +45,12 @@ class DetectorArray { public: DetectorArray (const int ndet); - ~DetectorArray (void); + ~DetectorArray (); - const int nDet(void) const {return m_nDet;} - const double viewAngle(void) const {return m_viewAngle;} - DetectorValue* detValues(void) {return m_detValues;} - const DetectorValue* detValues(void) const {return m_detValues;} + const int nDet() const {return m_nDet;} + const double viewAngle() const {return m_viewAngle;} + DetectorValue* detValues() {return m_detValues;} + const DetectorValue* detValues() const {return m_detValues;} void setViewAngle (double viewAngle) { m_viewAngle = viewAngle; } @@ -77,22 +77,24 @@ class Scanner Scanner (const Phantom& phm, const char* const geometryName, int nDet, int nView, int nSample, const double rot_anglen, double dFieldOfView, double dFocalLength); ~Scanner(); - void collectProjections (Projections& proj, const Phantom& phm, const int trace = TRACE_NONE, SGP* pSGP = NULL); + void collectProjections (Projections& proj, const Phantom& phm, const int trace = Trace::TRACE_NONE, SGP* pSGP = NULL); - void collectProjections (Projections& proj, const Phantom& phm, const int iStartView, const int iNumViews, bool bStoreAtViewPosition, const int trace = TRACE_NONE, SGP* pSGP = NULL); + void collectProjections (Projections& proj, const Phantom& phm, const int iStartView, const int iNumViews, bool bStoreAtViewPosition, const int trace = Trace::TRACE_NONE, SGP* pSGP = NULL); void setNView (int nView); - const bool fail(void) const {return m_fail;} - const string& failMessage(void) const {return m_failMessage;} - const unsigned int nDet(void) const {return m_nDet;} - const unsigned int nView(void) const {return m_nView;} - const double phmLen(void) const {return m_phmLen;} - const double rotInc(void) const {return m_rotInc;} - const double detInc(void) const {return m_detInc;} - const double detLen(void) const {return m_detLen;} - - static const int getGeometryCount() {return s_iGeometryCount;} + bool fail() const {return m_fail;} + const string& failMessage() const {return m_failMessage;} + unsigned int nDet() const {return m_nDet;} + unsigned int nView() const {return m_nView;} + double phmLen() const {return m_phmLen;} + double rotInc() const {return m_rotInc;} + double detInc() const {return m_detInc;} + double detLen() const {return m_detLen;} + double focalLength() const {return m_dFocalLength;} + double fieldOfView() const {return m_dFieldOfView;} + + static int getGeometryCount() {return s_iGeometryCount;} static const char** getGeometryNameArray() {return s_aszGeometryName;} static const char** getGeometryTitleArray() {return s_aszGeometryTitle;} static int convertGeometryNameToID (const char* const geometryName); @@ -107,12 +109,17 @@ class Scanner unsigned int m_nView; /* Number of rotated views */ unsigned int m_nSample; /* Number of rays per detector */ double m_dFieldOfView; // Field of View - double m_dFocalLength; // Focal Length + double m_dFocalLength; // Focal Length + double m_dFieldOfViewRatio; // Field of View Ratio to diameter phmLen + double m_dFocalLengthRatio; // Focal Length ratio to radius phmLen double m_detLen; // Total length of detector array double m_rotLen; // Rotation angle length in radians (norm 2PI) double m_detInc; // Increment between centers of detectors double m_rotInc; // Increment in rotation angle between views double m_phmLen; // Maximum Length of phantom or area of interest + double m_dXCenter; // Center of Phantom + double m_dYCenter; + int m_trace; struct { double xd1,yd1,xd2,yd2; /* Coordinates of detector endpoints */ @@ -120,32 +127,45 @@ class Scanner double angle; /* Starting angle */ } m_initPos; + GRFMTX_2D m_rotmtxIncrement; + +#if HAVE_SGP + SGP* m_pSGP; // Pointer to graphics device + double m_dXMinWin; // Extent of graphics window + double m_dXMaxWin; + double m_dYMinWin; + double m_dYMaxWin; + double m_dTextHeight; +#endif + static const char* s_aszGeometryName[]; static const char* s_aszGeometryTitle[]; static const int s_iGeometryCount; - 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); + 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, const double dDetAngle); - double projectSingleLine (const Phantom& phm, const double x1, const double y1, const double x2, const double y2, SGP* pSGP); + double projectSingleLine (const Phantom& phm, 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); + double projectLineAgainstPElem (const PhantomElement& pelem, const double x1, const double y1, const double x2, const double y2); - void traceShowParam (SGP* pSGP, const char *label, const char *fmt, int row, int color, ...); + void traceShowParam (const char* szLabel, const char *fmt, int row, int color, ...); + void traceShowParamXOR (const char* szLabel, const char *fmt, int row, int color, ...); + void traceShowParamRasterOp (int iRasterOp, const char* szLabel, const char* fmt, int row, int color, va_list va); }; -const static int RAYSUM_TRACE_ROW_TITLE=1; -const static int RAYSUM_TRACE_ROW_TITLE2=2; -const static int RAYSUM_TRACE_ROW_PHANT_ID=4; -const static int RAYSUM_TRACE_ROW_CHROMATIC=7; -const static int RAYSUM_TRACE_ROW_SCATTER=8; -const static int RAYSUM_TRACE_ROW_PHOT_STAT=9; -const static int RAYSUM_TRACE_ROW_NDET=12; -const static int RAYSUM_TRACE_ROW_NVIEW=13; -const static int RAYSUM_TRACE_ROW_SAMPLES=14; -const static int RAYSUM_TRACE_ROW_CURR_VIEW=17; -const static int RAYSUM_TRACE_ROW_ATTEN=18; +const static int PROJECTION_TRACE_ROW_TITLE=0; +const static int PROJECTION_TRACE_ROW_TITLE2=1; +const static int PROJECTION_TRACE_ROW_PHANT_ID=3; +const static int PROJECTION_TRACE_ROW_GEOMETRY=4; +const static int PROJECTION_TRACE_ROW_FOCAL_LENGTH=5; +const static int PROJECTION_TRACE_ROW_FIELD_OF_VIEW=6; +const static int PROJECTION_TRACE_ROW_NDET=7; +const static int PROJECTION_TRACE_ROW_NVIEW=8; +const static int PROJECTION_TRACE_ROW_SAMPLES=9; +const static int PROJECTION_TRACE_ROW_CURR_VIEW=10; +const static int PROJECTION_TRACE_ROW_ATTEN=11; diff --git a/include/sgp.h b/include/sgp.h index 6240752..0a5fe03 100644 --- a/include/sgp.h +++ b/include/sgp.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: sgp.h,v 1.14 2000/08/25 15:59:13 kevin Exp $ +** $Id: sgp.h,v 1.15 2000/08/27 20:32:55 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 @@ -138,7 +138,7 @@ private: static int s_iRGBColorCount; #if HAVE_WXWINDOWS - wxPen* m_pPen; + wxPen m_pen; #endif public: @@ -171,7 +171,7 @@ public: SGP (const SGPDriver& driver); void drawCircle (const double r); - void drawArc (double start, double stop, const double r); + void drawArc (const double r, double start, double stop); void drawRect (double xmin, double ymin, double xmax, double ymax); void lineAbs(double x, double y); void moveAbs(double x, double y); @@ -195,9 +195,13 @@ public: void setTextSize (double height); void setTextAngle (double angle); void setTextColor (int iFGcolor, int iBGcolor); + void setPenWidth (int width); void setMarker (int idMarker, int color); void setRasterOp (int ro); + void getTextExtent (const char *szText, double* x, double* y); + double getCharHeight (); + void ctmClear (); void ctmSet (const TransformationMatrix2D& m); void preTranslate (double x, double y); diff --git a/include/trace.h b/include/trace.h index 64826e9..4924d7a 100644 --- a/include/trace.h +++ b/include/trace.h @@ -1,25 +1,25 @@ #ifndef TRACE_H #define TRACE_H -static const int TRACE_INVALID = 0xFFFF; -static const int TRACE_NONE = 0x0000; -static const int TRACE_TEXT = 0x0001; -static const int TRACE_PHM = 0x0002; -static const int TRACE_RAYS = 0x0004; -static const int TRACE_PLOT = 0x0008; -static const int TRACE_CLIPPING = 0x0010; - -class TraceLevel + +class Trace { public: - static const char TRACE_NONE_STR[]; - static const char TRACE_TEXT_STR[]; - static const char TRACE_PHM_STR[]; - static const char TRACE_RAYS_STR[]; - static const char TRACE_PLOT_STR[]; - static const char TRACE_CLIPPING_STR[]; - - TraceLevel (const char* const traceString); + static const int TRACE_INVALID; + static const int TRACE_NONE; + static const int TRACE_CONSOLE; + static const int TRACE_PHANTOM; + static const int TRACE_PROJECTIONS; + static const int TRACE_PLOT; + static const int TRACE_CLIPPING; + + static const int BIT_CONSOLE; + static const int BIT_PHANTOM; + static const int BIT_PROJECTIONS; + static const int BIT_PLOT; + static const int BIT_CLIPPING; + + Trace (const char* const traceString); void addTrace (const char* const traceString); @@ -28,12 +28,23 @@ class TraceLevel int getTraceLevel(void) const { return m_traceLevel; } static int convertTraceNameToID (const char* traceName); + static const char* convertTraceIDToTitle (int idTrace); + static const char* convertTraceIDToName (int idTrace); + + static const int getTraceCount() {return s_iTraceCount;} + static const char** getTraceNameArray() {return s_aszTraceName;} + static const char** getTraceTitleArray() {return s_aszTraceTitle;} private: int m_traceLevel; bool addTraceElements (const char* const traceString); + + static const char* s_aszTraceName[]; + static const char* s_aszTraceTitle[]; + static const int s_iTraceCount; + }; diff --git a/libctgraphics/sgp.cpp b/libctgraphics/sgp.cpp index 6b826d7..52a2430 100644 --- a/libctgraphics/sgp.cpp +++ b/libctgraphics/sgp.cpp @@ -7,7 +7,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: sgp.cpp,v 1.10 2000/08/25 15:59:13 kevin Exp $ +** $Id: sgp.cpp,v 1.11 2000/08/27 20:32:55 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 @@ -81,9 +81,6 @@ SGPDriver::~SGPDriver () SGP::SGP (const SGPDriver& driver) : m_driver (driver) -#if HAVE_WXWINDOWS - , m_pPen(NULL) -#endif { m_iPhysicalXSize = m_driver.getPhysicalXSize(); m_iPhysicalYSize = m_driver.getPhysicalYSize(); @@ -93,6 +90,11 @@ SGP::SGP (const SGPDriver& driver) ndc_to_mc.setIdentity(); m_ctm.setIdentity(); +#if HAVE_WXWINDOWS + m_pen.SetWidth(1); + m_pen.SetStyle(wxSOLID); +#endif + setWindow (0., 0., 1., 1.); setViewport (0., 0., 1., 1.); moveAbs (0., 0.); @@ -101,6 +103,7 @@ SGP::SGP (const SGPDriver& driver) setTextAngle (0.); setTextSize (1. / 25.); setColor (C_BLACK); + } @@ -203,16 +206,28 @@ SGP::setViewport (double xmin, double ymin, double xmax, double ymax) void SGP::frameViewport (void) { - stylusNDC (xv_min, yv_min, 0); - stylusNDC (xv_max, yv_min, 1); - stylusNDC (xv_max, yv_max, 1); - stylusNDC (xv_min, yv_max, 1); - stylusNDC (xv_min, yv_min, 1); + stylusNDC (xv_min, yv_min, false); + stylusNDC (xv_max, yv_min, true); + stylusNDC (xv_max, yv_max, true); + stylusNDC (xv_min, yv_max, true); + stylusNDC (xv_min, yv_min, true); } void SGP::setTextColor (int iFGcolor, int iBGcolor) { +#if HAVE_WXWINDOWS + if (m_driver.isWX()) { + if (iFGcolor >= 0) { + wxColor colour (s_aRGBColor[iFGcolor].getRed(), s_aRGBColor[iFGcolor].getGreen(), s_aRGBColor[iFGcolor].getBlue()); + m_driver.idWX()->SetTextForeground (colour); + } + if (iBGcolor >= 0) { + wxColor colour (s_aRGBColor[iBGcolor].getRed(), s_aRGBColor[iBGcolor].getGreen(), s_aRGBColor[iBGcolor].getBlue()); + m_driver.idWX()->SetTextBackground (colour); + } + } +#endif } void @@ -228,9 +243,21 @@ SGP::setColor (int icol) #if HAVE_WXWINDOWS if (m_driver.isWX()) { wxColor colour (s_aRGBColor[icol].getRed(), s_aRGBColor[icol].getGreen(), s_aRGBColor[icol].getBlue()); - delete m_pPen; - m_pPen = new wxPen (colour, 1, wxSOLID); - m_driver.idWX()->SetPen (*m_pPen); + m_pen.SetColour (colour); + m_driver.idWX()->SetPen (m_pen); + } +#endif + } +} + +void +SGP::setPenWidth (int iWidth) +{ + if (iWidth >= 0) { +#if HAVE_WXWINDOWS + if (m_driver.isWX()) { + m_pen.SetWidth (iWidth); + m_driver.idWX()->SetPen (m_pen); } #endif } @@ -331,8 +358,8 @@ SGP::lineAbs (double x, double y) mc_to_ndc.transformPoint (&x2, &y2); if (clip_rect (x1, y1, x2, y2, viewNDC) == true) { // clip to viewport - stylusNDC (x1, y1, 0); // move to first point - stylusNDC (x2, y2, 1); // draw to second point + stylusNDC (x1, y1, false); // move to first point + stylusNDC (x2, y2, true); // draw to second point } m_dCurrentWorldX = x; @@ -365,6 +392,37 @@ SGP::setTextSize (double height) g2_set_font_size(m_driver.idG2(), (height * m_iPhysicalYSize)); } +void +SGP::getTextExtent (const char* szText, double* worldW, double* worldH) +{ +#if HAVE_WXWINDOWS + if (m_driver.isWX()) { + wxString sText (szText); + wxCoord deviceW, deviceH; + m_driver.idWX()->GetTextExtent (sText, &deviceW, &deviceH); + *worldW = static_cast(deviceW) / static_cast(m_iPhysicalXSize);; + *worldH = static_cast(deviceH) / static_cast(m_iPhysicalYSize); + // cout << deviceW << ", " << deviceH << ", " << *worldW << ", " << *worldH << endl; + *worldW *= (xw_max - xw_min); + *worldH *= (yw_max - yw_min); + } +#endif +} + +double +SGP::getCharHeight () +{ + double dHeight = (1. / 25.); + +#if HAVE_WXWINDOWS + if (m_driver.isWX()) { + dHeight = m_driver.idWX()->GetCharHeight(); + dHeight /= static_cast(m_iPhysicalYSize);; + } +#endif + return (dHeight * (xw_max - xw_min)); +} + void SGP::setTextAngle (double angle) { @@ -386,8 +444,8 @@ SGP::polylineAbs (double x[], double y[], int n) double yt = y2; // as the beginning point of the next line if (clip_rect (x1, y1, xt, yt, viewNDC)) { - stylusNDC (x1, y1, 0); - stylusNDC (xt, yt, 1); + stylusNDC (x1, y1, false); + stylusNDC (xt, yt, true); } for (int i = 2; i < n; i++) { @@ -397,8 +455,8 @@ SGP::polylineAbs (double x[], double y[], int n) xt = x2; yt = y2; if (clip_rect (x1, y1, xt, yt, viewNDC)) { - stylusNDC (x1, y1, 0); - stylusNDC (xt, yt, 1); + stylusNDC (x1, y1, false); + stylusNDC (xt, yt, true); } } } @@ -508,7 +566,7 @@ SGP::drawRect (double xmin, double ymin, double xmax, double ymax) void SGP::drawCircle (const double r) { - drawArc (0.0, 7.0, r); + drawArc (r, 0.0, 7.0); } // ============================================================= @@ -516,7 +574,7 @@ SGP::drawCircle (const double r) //============================================================== void -SGP::drawArc (double start, double stop, const double r) +SGP::drawArc (const double r, double start, double stop) { if ((stop-start) > 2 * PI) stop = start + 2 * PI; diff --git a/libctsim/phantom.cpp b/libctsim/phantom.cpp index c74c37a..cb2d3ff 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.16 2000/08/25 15:59:13 kevin Exp $ +** $Id: phantom.cpp,v 1.17 2000/08/27 20:32:55 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 @@ -203,6 +203,7 @@ Phantom::createFromFile (const char* const fname) if ((fp = fopen (fname, "r")) == NULL) return (false); + m_name = fname; do { if (! feof(fp)) { double cx, cy, u, v, rot, dens; @@ -386,7 +387,7 @@ void Phantom::addStdSheppLoganBordered () { addStdSheppLogan (); - addPElem ("rectangle", 0.000, 0.0000, 0.7500, 1.000, 0.0, 0.00); + addPElem ("rectangle", 0.000, 0.0000, 0.8600, 1.150, 0.0, 0.00); } /* NAME @@ -421,7 +422,7 @@ void Phantom::addStdHermanBordered () { addStdHerman(); - addPElem ("rectangle", 0.000, 0.00, 9.000, 6.800, 0.00, 0.000); + addPElem ("rectangle", 0.000, 0.00, 10.780, 8.110, 90.00, 0.000); } diff --git a/libctsim/procsignal.cpp b/libctsim/procsignal.cpp index 8156252..e38fae2 100644 --- a/libctsim/procsignal.cpp +++ b/libctsim/procsignal.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: procsignal.cpp,v 1.3 2000/08/25 15:59:13 kevin Exp $ +** $Id: procsignal.cpp,v 1.4 2000/08/27 20:32:55 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 @@ -77,7 +77,7 @@ const int ProcessSignal::s_iFilterGenerationCount = sizeof(s_aszFilterGeneration // CLASS IDENTIFICATION // ProcessSignal // -ProcessSignal::ProcessSignal (const char* szFilterName, const char* szFilterMethodName, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const char* szDomainName, const char* szFilterGenerationName, int iZeropad, int iPreinterpolationFactor, int iTraceLevel) +ProcessSignal::ProcessSignal (const char* szFilterName, const char* szFilterMethodName, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const char* szDomainName, const char* szFilterGenerationName, int iZeropad, int iPreinterpolationFactor, int iTraceLevel, int iGeometry) : m_adFourierCosTable(NULL), m_adFourierSinTable(NULL), m_adFilter(NULL), m_fail(false) { m_idFilterMethod = convertFilterMethodNameToID (szFilterMethodName); @@ -109,17 +109,19 @@ ProcessSignal::ProcessSignal (const char* szFilterName, const char* szFilterMeth return; } - init (m_idFilter, m_idFilterMethod, dBandwidth, dSignalIncrement, nSignalPoints, dFilterParam, m_idDomain, m_idFilterGeneration, iZeropad, iPreinterpolationFactor, iTraceLevel); + init (m_idFilter, m_idFilterMethod, dBandwidth, dSignalIncrement, nSignalPoints, dFilterParam, m_idDomain, m_idFilterGeneration, iZeropad, iPreinterpolationFactor, iTraceLevel, iGeometry); } void -ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const int idDomain, const int idFilterGeneration, const int iZeropad, const int iPreinterpolationFactor, int iTraceLevel) +ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const int idDomain, const int idFilterGeneration, const int iZeropad, const int iPreinterpolationFactor, int iTraceLevel, int iGeometry) { m_idFilter = idFilter; m_idDomain = idDomain; m_idFilterMethod = idFilterMethod; m_idFilterGeneration = idFilterGeneration; + m_idGeometry = iGeometry; + if (m_idFilter == SignalFilter::FILTER_INVALID || m_idDomain == SignalFilter::DOMAIN_INVALID || m_idFilterMethod == FILTER_METHOD_INVALID || m_idFilterGeneration == FILTER_GENERATION_INVALID) { m_fail = true; return; @@ -168,7 +170,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw m_adFilter = new double[ m_nFilterPoints ]; double adFrequencyFilter [m_nFilterPoints]; filter.copyFilterData (adFrequencyFilter, 0, m_nFilterPoints); - if (m_traceLevel >= TRACE_PLOT) { + if (m_traceLevel >= Trace::TRACE_PLOT) { SGPDriver sgpDriver ("Frequency Filter: Natural Order"); SGP sgp (sgpDriver); EZPlot ezplot (sgp); @@ -181,7 +183,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw } shuffleNaturalToFourierOrder (adFrequencyFilter, m_nFilterPoints); - if (m_traceLevel >= TRACE_PLOT) { + if (m_traceLevel >= Trace::TRACE_PLOT) { SGPDriver sgpDriver ("Frequency Filter: Fourier Order"); SGP sgp (sgpDriver); EZPlot ezplot (sgp); @@ -193,7 +195,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw cio_kb_getc (); } ProcessSignal::finiteFourierTransform (adFrequencyFilter, m_adFilter, m_nFilterPoints, -1); - if (m_traceLevel >= TRACE_PLOT) { + if (m_traceLevel >= Trace::TRACE_PLOT) { SGPDriver sgpDriver ("Inverse Fourier Frequency: Fourier Order"); SGP sgp (sgpDriver); EZPlot ezplot (sgp); @@ -205,7 +207,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw cio_kb_getc (); } shuffleFourierToNaturalOrder (m_adFilter, m_nFilterPoints); - if (m_traceLevel >= TRACE_PLOT) { + if (m_traceLevel >= Trace::TRACE_PLOT) { SGPDriver sgpDriver ("Inverse Fourier Frequency: Natural Order"); SGP sgp (sgpDriver); EZPlot ezplot (sgp); @@ -235,7 +237,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw nextPowerOf2++; nextPowerOf2 += (m_iZeropad - 1); m_nFilterPoints = 1 << nextPowerOf2; - if (m_traceLevel >= TRACE_TEXT) + if (m_traceLevel >= Trace::TRACE_CONSOLE) cout << "nFilterPoints = " << m_nFilterPoints << endl; } m_nOutputPoints = m_nFilterPoints * m_iPreinterpolationFactor; @@ -254,7 +256,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw SignalFilter filter (m_idFilter, m_dFilterMin, m_dFilterMax, m_nFilterPoints, m_dBandwidth, m_dFilterParam, SignalFilter::DOMAIN_FREQUENCY); m_adFilter = new double [m_nFilterPoints]; filter.copyFilterData (m_adFilter, 0, m_nFilterPoints); - if (m_traceLevel >= TRACE_PLOT) { + if (m_traceLevel >= Trace::TRACE_PLOT) { SGPDriver sgpDriver ("Frequency Filter: Natural Order"); SGP sgp (sgpDriver); EZPlot ezplot (sgp); @@ -266,7 +268,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw cio_kb_getc (); } shuffleNaturalToFourierOrder (m_adFilter, m_nFilterPoints); - if (m_traceLevel >= TRACE_PLOT) { + if (m_traceLevel >= Trace::TRACE_PLOT) { SGPDriver sgpDriver ("Frequency Filter: Fourier Order"); SGP sgp (sgpDriver); EZPlot ezplot (sgp); @@ -293,12 +295,12 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw m_nFilterPoints = 1 << nextPowerOf2; } m_nOutputPoints = m_nFilterPoints * m_iPreinterpolationFactor; - if (m_traceLevel >= TRACE_TEXT) + if (m_traceLevel >= Trace::TRACE_CONSOLE) cout << "nFilterPoints = " << m_nFilterPoints << endl; double adSpatialFilter [m_nFilterPoints]; SignalFilter filter (m_idFilter, m_dFilterMin, m_dFilterMax, nSpatialPoints, m_dBandwidth, m_dFilterParam, SignalFilter::DOMAIN_SPATIAL); filter.copyFilterData (adSpatialFilter, 0, nSpatialPoints); - if (m_traceLevel >= TRACE_PLOT) { + if (m_traceLevel >= Trace::TRACE_PLOT) { SGPDriver sgpDriver ("Spatial Filter: Natural Order"); SGP sgp (sgpDriver); EZPlot ezplot (sgp); @@ -317,7 +319,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw finiteFourierTransform (adSpatialFilter, acInverseFilter, m_nFilterPoints, 1); for (int i = 0; i < m_nFilterPoints; i++) m_adFilter[i] = abs(acInverseFilter[i]) * m_dSignalInc; - if (m_traceLevel >= TRACE_PLOT) { + if (m_traceLevel >= Trace::TRACE_PLOT) { SGPDriver sgpDriver ("Spatial Filter: Inverse"); SGP sgp (sgpDriver); EZPlot ezplot (sgp); @@ -468,7 +470,7 @@ ProcessSignal::convertFilterGenerationIDToTitle (const int fgID) } void -ProcessSignal::filterSignal (const float input[], double output[]) const +ProcessSignal::filterSignal (const float input[], double output[], int iView) const { if (m_idFilterMethod == FILTER_METHOD_CONVOLUTION) { for (int i = 0; i < m_nSignalPoints; i++) diff --git a/libctsim/projections.cpp b/libctsim/projections.cpp index df7ccd2..da298f0 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.22 2000/08/25 15:59:13 kevin Exp $ +** $Id: projections.cpp,v 1.23 2000/08/27 20:32:55 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 @@ -80,6 +80,8 @@ Projections::initFromScanner (const Scanner& scanner) m_phmLen = scanner.phmLen(); m_rotInc = scanner.rotInc(); m_detInc = scanner.detInc(); + m_focalLength = scanner.focalLength(); + m_fieldOfView = scanner.fieldOfView(); m_rotStart = 0; m_detStart = -(scanner.detLen() / 2) + (scanner.detInc() / 2); } @@ -157,7 +159,9 @@ Projections::headerWrite (fnetorderstream& fs) kfloat64 _detStart = m_detStart; kfloat64 _detInc = m_detInc; kfloat64 _phmLen = m_phmLen; - + kfloat64 _fieldOfView = m_fieldOfView; + kfloat64 _focalLength = m_focalLength; + fs.seekp(0); if (! fs) return false; @@ -173,6 +177,8 @@ Projections::headerWrite (fnetorderstream& fs) fs.writeFloat64 (_detStart); fs.writeFloat64 (_detInc); fs.writeFloat64 (_phmLen); + fs.writeFloat64 (_focalLength); + fs.writeFloat64 (_fieldOfView); fs.writeInt16 (_year); fs.writeInt16 (_month); fs.writeInt16 (_day); @@ -201,7 +207,7 @@ Projections::headerRead (fnetorderstream& fs) { kuint16 _hsize, _signature, _year, _month, _day, _hour, _minute, _second, _remarksize = 0; kuint32 _nView, _nDet, _geom; - kfloat64 _calcTime, _rotStart, _rotInc, _detStart, _detInc, _phmLen; + kfloat64 _calcTime, _rotStart, _rotInc, _detStart, _detInc, _phmLen, _focalLength, _fieldOfView; fs.seekg(0); if (! fs) @@ -218,6 +224,8 @@ Projections::headerRead (fnetorderstream& fs) fs.readFloat64 (_detStart); fs.readFloat64 (_detInc); fs.readFloat64 (_phmLen); + fs.readFloat64 (_focalLength); + fs.readFloat64 (_fieldOfView); fs.readInt16 (_year); fs.readInt16 (_month); fs.readInt16 (_day); @@ -261,6 +269,8 @@ Projections::headerRead (fnetorderstream& fs) m_detStart = _detStart; m_detInc = _detInc; m_phmLen = _phmLen; + m_focalLength = _focalLength; + m_fieldOfView = _fieldOfView; m_year = _year; m_month = _month; m_day = _day; @@ -434,10 +444,10 @@ Projections::printProjectionData (void) { printf("Projections Print\n\n"); printf("Description: %s\n", m_remark.c_str()); - printf("nView = %d nDet = %d\n", m_nView, m_nDet); - printf("rotStart = %8.4f rotInc = %8.4f\n", m_rotStart, m_rotInc); - printf("detStart = %8.4f detInc = %8.4f\n", m_detStart, m_detInc); - + printf("nView = %8d nDet = %8d\n", m_nView, m_nDet); + printf("rotStart = %8.4f rotInc = %8.4f\n", m_rotStart, m_rotInc); + printf("detStart = %8.4f detInc = %8.4f\n", m_detStart, m_detInc); + printf("focalLength = %8.4f fieldOfView = %8.4f\n", m_focalLength, m_fieldOfView); if (m_projData != NULL) { for (int ir = 0; ir < m_nView; ir++) { DetectorValue* detval = m_projData[ir]->detValues(); @@ -502,7 +512,7 @@ Projections::reconstruct (ImageFile& im, const char* const filterName, double fi #endif double filterBW = 1. / detInc; - ProcessSignal processSignal (filterName, filterMethodName, filterBW, m_detInc, m_nDet, filt_param, "spatial", filterGenerationName, zeropad, interpFactor, trace); + ProcessSignal processSignal (filterName, filterMethodName, filterBW, m_detInc, m_nDet, filt_param, "spatial", filterGenerationName, zeropad, interpFactor, trace, m_geometry); if (processSignal.fail()) { sys_error (ERR_SEVERE, "%s [Projections::reconstruct]", processSignal.failMessage().c_str()); @@ -516,7 +526,7 @@ Projections::reconstruct (ImageFile& im, const char* const filterName, double fi int nVecFilter = processSignal.getNFilterPoints(); double plot_xaxis [nVecFilter]; // array for plotting - if (trace > TRACE_TEXT && nVecFilter > 0) { + if (trace > Trace::TRACE_CONSOLE && nVecFilter > 0) { int i; double f; double filterInc = processSignal.getFilterIncrement(); @@ -535,7 +545,7 @@ Projections::reconstruct (ImageFile& im, const char* const filterName, double fi cio_kb_getc (); } } - if (trace >= TRACE_TEXT) { + if (trace >= Trace::TRACE_CONSOLE) { printf ("nview=%d, ndet=%d, det_start=%.4f, detInc=%.4f\n", m_nView, m_nDet, m_detStart, m_detInc); } #endif //HAVE_SGP @@ -547,20 +557,20 @@ Projections::reconstruct (ImageFile& im, const char* const filterName, double fi } for (int iview = 0; iview < m_nView; iview++) { - if (trace >= TRACE_TEXT) + if (trace >= Trace::TRACE_CONSOLE) printf ("Reconstructing view %d (last = %d)\n", iview, m_nView - 1); const DetectorArray& darray = getDetectorArray (iview); const DetectorValue* detval = darray.detValues(); - processSignal.filterSignal (detval, filteredProj); + processSignal.filterSignal (detval, filteredProj, iview); #ifdef HAVE_BSPLINE_INTERP if (interp_type == I_BSPLINE) bspline (m_nDet, zoom_factor, spline_order, filteredProj, filteredProj); #ifdef HAVE_SGP - if (trace >= TRACE_PLOT && interp_type == I_BSPLINE) { + if (trace >= Trace::TRACE_PLOT && interp_type == I_BSPLINE) { bspline (m_nDet, zoom_factor, spline_order, filteredProj, filteredProj); ezplot_1d (filteredProj, n_filteredProj); } @@ -570,7 +580,7 @@ Projections::reconstruct (ImageFile& im, const char* const filterName, double fi bj.BackprojectView (filteredProj, darray.viewAngle()); #ifdef HAVE_SGP - if (trace >= TRACE_PLOT) { + if (trace >= Trace::TRACE_PLOT) { SGPDriver sgpDriverProj ("Projection"); SGP sgpProj (sgpDriverProj); EZPlot ezplotProj (sgpProj); diff --git a/libctsim/scanner.cpp b/libctsim/scanner.cpp index c4fc4d0..c45d4fd 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.11 2000/08/25 15:59:13 kevin Exp $ +** $Id: scanner.cpp,v 1.12 2000/08/27 20:32:55 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 @@ -107,9 +107,13 @@ Scanner::Scanner (const Phantom& phm, const char* const geometryName, int nDet, m_nDet = nDet; m_nView = nView; m_nSample = nSample; + m_dFocalLengthRatio = dFocalLengthRatio; + m_dFieldOfViewRatio = dFieldOfViewRatio; m_dFocalLength = (m_phmLen * SQRT2 / 2) * dFocalLengthRatio; m_dFieldOfView = m_phmLen * SQRT2 * dFieldOfViewRatio; + m_dXCenter = phm.xmin() + (phm.xmax() - phm.xmin()) / 2; + m_dYCenter = phm.ymin() + (phm.ymax() - phm.ymin()) / 2; if (m_idGeometry == GEOMETRY_PARALLEL) { m_detLen = m_dFieldOfView; m_detInc = m_detLen / m_nDet; @@ -117,17 +121,17 @@ Scanner::Scanner (const Phantom& phm, const char* const geometryName, int nDet, m_rotInc = m_rotLen / m_nView; double dHalfDetLen = m_detLen / 2; - m_initPos.xs1 = -m_dFocalLength; - m_initPos.ys1 = -dHalfDetLen; - m_initPos.xs2 = -m_dFocalLength; - m_initPos.ys2 = dHalfDetLen; - m_initPos.xd1 = m_dFocalLength; - m_initPos.yd1 = -dHalfDetLen; - m_initPos.xd2 = m_dFocalLength; - m_initPos.yd2 = dHalfDetLen; + m_initPos.xs1 = m_dXCenter - m_dFocalLength; + m_initPos.ys1 = m_dYCenter - dHalfDetLen; + m_initPos.xs2 = m_dXCenter - m_dFocalLength; + m_initPos.ys2 = m_dYCenter + dHalfDetLen; + m_initPos.xd1 = m_dXCenter + m_dFocalLength; + m_initPos.yd1 = m_dYCenter - dHalfDetLen; + m_initPos.xd2 = m_dXCenter + m_dFocalLength; + m_initPos.yd2 = m_dYCenter + dHalfDetLen; m_initPos.angle = 0.0; } else if (m_idGeometry == GEOMETRY_EQUILINEAR) { - double dHalfSquare = m_phmLen / 2; + double dHalfSquare = m_dFieldOfView / SQRT2 / 2; double dFocalPastPhm = m_dFocalLength - dHalfSquare; if (dFocalPastPhm <= 0.) { m_fail = true; @@ -142,26 +146,44 @@ Scanner::Scanner (const Phantom& phm, const char* const geometryName, int nDet, m_rotLen = rot_anglen; m_rotInc = m_rotLen / m_nView; - m_initPos.xs1 = -m_dFocalLength; - m_initPos.ys1 = 0; - m_initPos.xs2 = -m_dFocalLength; - m_initPos.ys2 = 0; - m_initPos.xd1 = m_dFocalLength; - m_initPos.yd1 = -dHalfDetLen; - m_initPos.xd2 = m_dFocalLength; - m_initPos.yd2 = dHalfDetLen; + m_initPos.xs1 = m_dXCenter - m_dFocalLength; + m_initPos.ys1 = m_dYCenter; + m_initPos.xs2 = m_dXCenter - m_dFocalLength; + m_initPos.ys2 = m_dYCenter; + m_initPos.xd1 = m_dXCenter + m_dFocalLength; + m_initPos.yd1 = m_dYCenter - dHalfDetLen; + m_initPos.xd2 = m_dXCenter + m_dFocalLength; + m_initPos.yd2 = m_dYCenter + dHalfDetLen; m_initPos.angle = 0.0; } else if (m_idGeometry == GEOMETRY_EQUIANGULAR) { - double dHalfSquare = m_phmLen / 2; + double dHalfSquare = m_dFieldOfView / SQRT2 / 2; double dFocalPastPhm = m_dFocalLength - dHalfSquare; if (dFocalPastPhm <= 0.) { m_fail = true; m_failMessage = "Focal Point inside of phantom"; return; } - double dAngle = atan( dHalfSquare / dFocalPastPhm ); - m_detLen = dAngle * 2; + double dAngle = 2 * atan( dHalfSquare / dFocalPastPhm ); + m_detLen = 2 * dAngle; + m_detInc = m_detLen / m_nDet; + m_rotLen = rot_anglen; + m_rotInc = m_rotLen / m_nView; + + m_initPos.xs1 = m_dXCenter - m_dFocalLength; + m_initPos.ys1 = m_dYCenter; + m_initPos.xs2 = m_dXCenter - m_dFocalLength; + m_initPos.ys2 = m_dYCenter; + m_initPos.angle = -dAngle; } + + // Calculate incrementatal rotation matrix + GRFMTX_2D temp; + xlat_mtx2 (m_rotmtxIncrement, -m_dXCenter, -m_dYCenter); + rot_mtx2 (temp, m_rotInc); + mult_mtx2 (m_rotmtxIncrement, temp, m_rotmtxIncrement); + xlat_mtx2 (temp, m_dXCenter, m_dYCenter); + mult_mtx2 (m_rotmtxIncrement, temp, m_rotmtxIncrement); + } Scanner::~Scanner (void) @@ -227,119 +249,130 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int tr void Scanner::collectProjections (Projections& proj, const Phantom& phm, const int iStartView, const int iNumViews, bool bStoreAtViewPosition, const int trace, SGP* pSGP) { - GRFMTX_2D rotmtx_initial, temp; - GRFMTX_2D rotmtx_incr; - - double start_angle = iStartView * proj.rotInc(); - double xcent = phm.xmin() + (phm.xmax() - phm.xmin()) / 2; - double ycent = phm.ymin() + (phm.ymax() - phm.ymin()) / 2; - - double xd1 = xcent + m_initPos.xd1; - double yd1 = ycent + m_initPos.yd1; - double xd2 = xcent + m_initPos.xd2; - double yd2 = ycent + m_initPos.yd2; - double xs1 = xcent + m_initPos.xs1; - double ys1 = ycent + m_initPos.ys1; - double xs2 = xcent + m_initPos.xs2; - double ys2 = ycent + m_initPos.ys2; - m_trace = trace; + double start_angle = iStartView * proj.rotInc(); -/* Calculate initial rotation matrix */ - xlat_mtx2 (rotmtx_initial, -xcent, -ycent); + // Calculate initial rotation matrix + GRFMTX_2D rotmtx_initial, temp; + xlat_mtx2 (rotmtx_initial, -m_dXCenter, -m_dYCenter); rot_mtx2 (temp, start_angle); mult_mtx2 (rotmtx_initial, temp, rotmtx_initial); - xlat_mtx2 (temp, xcent, ycent); + xlat_mtx2 (temp, m_dXCenter, m_dYCenter); mult_mtx2 (rotmtx_initial, temp, rotmtx_initial); - xform_mtx2 (rotmtx_initial, xd1, yd1); /* rotate detector endpoints */ - xform_mtx2 (rotmtx_initial, xd2, yd2); /* to initial view_angle */ - xform_mtx2 (rotmtx_initial, xs1, ys1); - xform_mtx2 (rotmtx_initial, xs2, ys2); - -/* Calculate incrementatal rotation matrix */ - xlat_mtx2 (rotmtx_incr, -xcent, -ycent); - rot_mtx2 (temp, proj.rotInc()); - mult_mtx2 (rotmtx_incr, temp, rotmtx_incr); - xlat_mtx2 (temp, xcent, ycent); - mult_mtx2 (rotmtx_incr, temp, rotmtx_incr); + double xd1=0, yd1=0, xd2=0, yd2=0, dDetAngle=0; + if (m_idGeometry == GEOMETRY_EQUIANGULAR) + dDetAngle = m_initPos.angle + start_angle; + else { + xd1 = m_initPos.xd1; + yd1 = m_initPos.yd1; + xd2 = m_initPos.xd2; + yd2 = m_initPos.yd2; + xform_mtx2 (rotmtx_initial, xd1, yd1); // rotate detector endpoints + xform_mtx2 (rotmtx_initial, xd2, yd2); // to initial view_angle + } - int iview; + double xs1 = m_initPos.xs1; + double ys1 = m_initPos.ys1; + double xs2 = m_initPos.xs2; + double ys2 = m_initPos.ys2; + xform_mtx2 (rotmtx_initial, xs1, ys1); // rotate source endpoints to + xform_mtx2 (rotmtx_initial, xs2, ys2); // initial view angle + + int iView; double viewAngle; - for (iview = 0, viewAngle = start_angle; iview < iNumViews; iview++, viewAngle += proj.rotInc()) { - int iStoragePosition = iview; + for (iView = 0, viewAngle = start_angle; iView < iNumViews; iView++, viewAngle += proj.rotInc()) { + int iStoragePosition = iView; if (bStoreAtViewPosition) iStoragePosition += iStartView; DetectorArray& detArray = proj.getDetectorArray( iStoragePosition ); #ifdef HAVE_SGP - if (pSGP && m_trace >= TRACE_PHM) { - pSGP->eraseWindow(); - double dWindowSize = max(m_detLen, m_dFocalLength * 2) * SQRT2; - double dHalfWindowSize = dWindowSize / 2; - double dHalfPhmLen = m_phmLen / 2; - - pSGP->setRasterOp (RO_SET); - pSGP->eraseWindow (); - pSGP->setWindow (xcent - dHalfWindowSize, ycent - dHalfWindowSize, xcent + dHalfWindowSize, ycent + dHalfWindowSize); - pSGP->setColor (C_BROWN); - pSGP->moveAbs (0., 0.); - pSGP->drawRect (xcent - dHalfPhmLen, ycent - dHalfPhmLen, xcent + dHalfPhmLen, ycent + dHalfPhmLen); - -#if 0 - traceShowParam (pSGP, "X-Ray Simulator", "%s", RAYSUM_TRACE_ROW_TITLE, C_BLACK, " "); - traceShowParam (pSGP, "---------------", "%s", RAYSUM_TRACE_ROW_TITLE2, C_BLACK, " "); - traceShowParam (pSGP, "Phantom:", "%s", RAYSUM_TRACE_ROW_PHANT_ID, C_YELLOW, " Herman"); - traceShowParam (pSGP, "Chomaticity :", "%s", RAYSUM_TRACE_ROW_CHROMATIC, C_LTGREEN, "Mono"); - traceShowParam (pSGP, "Scatter :", "%5.1f", RAYSUM_TRACE_ROW_SCATTER, C_LTGREEN, 0.); - traceShowParam (pSGP, "Photon Uncert:", "%5.1f", RAYSUM_TRACE_ROW_PHOT_STAT, C_LTGREEN, 0.); - traceShowParam (pSGP, "Num Detectors:", "%5d", RAYSUM_TRACE_ROW_NDET, C_LTRED, proj.nDet()); - traceShowParam (pSGP, "Num Views :", "%5d", RAYSUM_TRACE_ROW_NVIEW, C_LTRED, proj.nViews()); - traceShowParam (pSGP, "Samples / Ray:", "%5d", RAYSUM_TRACE_ROW_SAMPLES, C_LTRED, m_nSample); -#endif - - pSGP->setColor (C_RED); - phm.draw (*pSGP); + if (pSGP && m_trace >= Trace::TRACE_PHANTOM) { + m_pSGP = pSGP; + m_pSGP->eraseWindow(); + double dWindowSize = max(m_detLen, m_dFocalLength * 2) * SQRT2; + double dHalfWindowSize = dWindowSize / 2; + m_dXMinWin = m_dXCenter - dHalfWindowSize; + m_dXMaxWin = m_dXCenter + dHalfWindowSize; + m_dYMinWin = m_dYCenter - dHalfWindowSize; + m_dYMaxWin = m_dYCenter + dHalfWindowSize; + double dHalfPhmLen = m_phmLen / 2; + + m_pSGP->eraseWindow (); + m_pSGP->setWindow (m_dXMinWin, m_dYMinWin, m_dXMaxWin, m_dYMaxWin); + m_pSGP->setRasterOp (RO_COPY); + m_pSGP->setColor (C_BLUE); + m_pSGP->moveAbs (0., 0.); + m_pSGP->drawRect (m_dXCenter - dHalfPhmLen, m_dYCenter - dHalfPhmLen, m_dXCenter + dHalfPhmLen, m_dYCenter + dHalfPhmLen); + m_pSGP->moveAbs (0., 0.); + m_pSGP->drawCircle (m_dFocalLength); + m_pSGP->setColor (C_RED); + phm.draw (*m_pSGP); + m_dTextHeight = m_pSGP->getCharHeight (); + + traceShowParam ("Projection Collector", "%s", PROJECTION_TRACE_ROW_TITLE, C_BLACK, " "); + traceShowParam ("________________", "%s", PROJECTION_TRACE_ROW_TITLE2, C_LTGRAY, " "); + traceShowParam ("Phantom:", "%s", PROJECTION_TRACE_ROW_PHANT_ID, C_BLACK, phm.name().c_str()); + traceShowParam ("Geometry:", "%s", PROJECTION_TRACE_ROW_GEOMETRY, C_BLUE, convertGeometryIDToName(m_idGeometry)); + traceShowParam ("Focal Length Ratio:", "%.2f", PROJECTION_TRACE_ROW_FOCAL_LENGTH, C_BLUE, m_dFocalLengthRatio); + traceShowParam ("Field Of View Ratio:", "%.2f", PROJECTION_TRACE_ROW_FIELD_OF_VIEW, C_BLUE, m_dFieldOfViewRatio); + traceShowParam ("Num Detectors:", "%d", PROJECTION_TRACE_ROW_NDET, C_BLUE, proj.nDet()); + traceShowParam ("Num Views:", "%d", PROJECTION_TRACE_ROW_NVIEW, C_BLUE, proj.nView()); + traceShowParam ("Samples / Ray:", "%d", PROJECTION_TRACE_ROW_SAMPLES, C_BLUE, m_nSample); - pSGP->setMarker (SGP::MARK_BDIAMOND, C_LTGREEN); + m_pSGP->setMarker (SGP::MARK_BDIAMOND, C_LTGREEN); } #endif #ifdef HAVE_SGP - if (pSGP && m_trace >= TRACE_PHM) { - pSGP->setRasterOp (RO_XOR); - pSGP->setColor (C_RED); - pSGP->moveAbs (xd1, yd1); - pSGP->lineAbs (xd2, yd2); - pSGP->moveAbs (xs1, ys1); - pSGP->lineAbs (xs2, ys2); - pSGP->setRasterOp (RO_SET); + if (m_pSGP && m_trace >= Trace::TRACE_PHANTOM) { + m_pSGP->setColor (C_BLACK); + m_pSGP->setPenWidth (2); + if (m_idGeometry == GEOMETRY_PARALLEL) { + m_pSGP->moveAbs (xs1, ys1); + m_pSGP->lineAbs (xs2, ys2); + m_pSGP->moveAbs (xd1, yd1); + m_pSGP->lineAbs (xd2, yd2); + } else if (m_idGeometry == GEOMETRY_EQUILINEAR) { + m_pSGP->setPenWidth (4); + m_pSGP->moveAbs (xs1, ys1); + m_pSGP->lineAbs (xs2, ys2); + m_pSGP->setPenWidth (2); + m_pSGP->moveAbs (xd1, yd1); + m_pSGP->lineAbs (xd2, yd2); + } else if (m_idGeometry == GEOMETRY_EQUIANGULAR) { + m_pSGP->setPenWidth (4); + m_pSGP->moveAbs (xs1, ys1); + m_pSGP->lineAbs (xs2, ys2); + m_pSGP->setPenWidth (2); + m_pSGP->moveAbs (0., 0.); + m_pSGP->drawArc (m_dFocalLength, start_angle + m_initPos.angle, start_angle - m_initPos.angle); + } + m_pSGP->setPenWidth (1); } - if (m_trace >= TRACE_TEXT) - traceShowParam (pSGP, "Current View :", "%5d", RAYSUM_TRACE_ROW_CURR_VIEW, C_LTMAGENTA, iview); + if (m_trace >= Trace::TRACE_CONSOLE) + traceShowParam ("Current View:", "%d (%.0f%%)", PROJECTION_TRACE_ROW_CURR_VIEW, C_RED, iView + iStartView, (iView + iStartView) / m_nView * 100.); #endif - projectSingleView (phm, detArray, xd1, yd1, xd2, yd2, xs1, ys1, xs2, ys2, pSGP); + projectSingleView (phm, detArray, xd1, yd1, xd2, yd2, xs1, ys1, xs2, ys2, dDetAngle); detArray.setViewAngle (viewAngle); #ifdef HAVE_SGP - if (pSGP && m_trace >= TRACE_PHM) { - // rs_plot (detArray, xd1, yd1, xcent, ycent, theta); - pSGP->setColor (C_RED); - pSGP->setRasterOp (RO_XOR); - pSGP->moveAbs (xd1, yd1); - pSGP->lineAbs (xd2, yd2); - pSGP->moveAbs (xs1, ys1); - pSGP->lineAbs (xs2, ys2); - pSGP->setRasterOp (RO_SET); + if (m_pSGP && m_trace >= Trace::TRACE_PHANTOM) { + // rs_plot (detArray, xd1, yd1, dXCenter, dYCenter, theta); } #endif - xform_mtx2 (rotmtx_incr, xd1, yd1); // rotate detector endpoints - xform_mtx2 (rotmtx_incr, xd2, yd2); - xform_mtx2 (rotmtx_incr, xs1, ys1); - xform_mtx2 (rotmtx_incr, xs2, ys2); - } /* for each iview */ + xform_mtx2 (m_rotmtxIncrement, xs1, ys1); + xform_mtx2 (m_rotmtxIncrement, xs2, ys2); + if (m_idGeometry == GEOMETRY_EQUIANGULAR) + dDetAngle += m_detInc; + else { + xform_mtx2 (m_rotmtxIncrement, xd1, yd1); // rotate detector endpoints + xform_mtx2 (m_rotmtxIncrement, xd2, yd2); + } + } /* for each iView */ } @@ -367,23 +400,33 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int iS */ 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, SGP* pSGP) +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, const double dDetAngle) { - double ddx = (xd2 - xd1) / detArray.nDet(); // change in coords between detectors - double ddy = (yd2 - yd1) / detArray.nDet(); - double sdx = (xs2 - xs1) / detArray.nDet(); // change in coords between source - double sdy = (ys2 - ys1) / detArray.nDet(); - - double ddx2 = ddx / m_nSample; // Incr. between rays with detector cell - double ddy2 = ddy / m_nSample; // Doesn't include detector endpoints - double ddx2_ofs = ddx2 / 2; // offset of 1st ray from start of detector cell - double ddy2_ofs = ddy2 / 2; - - double xd_maj = xd1 + ddx2_ofs; // Incr. between detector cells - double yd_maj = yd1 + ddy2_ofs; + + double sdx = (xs2 - xs1) / detArray.nDet(); // change in coords + double sdy = (ys2 - ys1) / detArray.nDet(); // between source double xs_maj = xs1 + (sdx / 2); // put ray source in center of cell double ys_maj = ys1 + (sdy / 2); + double ddx=0, ddy=0, ddx2=0, ddy2=0, ddx2_ofs=0, ddy2_ofs=0, xd_maj=0, yd_maj=0; + double dAngleInc=0, dAngleSampleInc=0, dAngleSampleOffset=0, dAngleMajor=0; + if (m_idGeometry == GEOMETRY_EQUIANGULAR) { + dAngleInc = m_detInc; + dAngleSampleInc = dAngleInc / m_nSample; + dAngleSampleOffset = dAngleSampleInc / 2; + dAngleMajor = dDetAngle + dAngleSampleOffset; + } else { + ddx = (xd2 - xd1) / detArray.nDet(); // change in coords + ddy = (yd2 - yd1) / detArray.nDet(); // between detectors + ddx2 = ddx / m_nSample; // Incr. between rays with detector cell + ddy2 = ddy / m_nSample; // Doesn't include detector endpoints + ddx2_ofs = ddx2 / 2; // offset of 1st ray from start of detector cell + ddy2_ofs = ddy2 / 2; + + xd_maj = xd1 + ddx2_ofs; // Incr. between detector cells + yd_maj = yd1 + ddy2_ofs; + } + DetectorValue* detval = detArray.detValues(); if (phm.getComposition() == P_UNIT_PULSE) { // put unit pulse in center of view @@ -393,80 +436,118 @@ Scanner::projectSingleView (const Phantom& phm, DetectorArray& detArray, const d else detval[d] = 0; } else { - for (int d = 0; d < detArray.nDet(); d++) { - double xd = xd_maj; - double yd = yd_maj; + for (int d = 0; d < detArray.nDet(); d++) { double xs = xs_maj; double ys = ys_maj; + double xd=0, yd=0, dAngle=0; + if (m_idGeometry == GEOMETRY_EQUIANGULAR) { + dAngle = dAngleMajor; + } else { + xd = xd_maj; + yd = yd_maj; + } double sum = 0.0; for (unsigned int i = 0; i < m_nSample; i++) { + if (m_idGeometry == GEOMETRY_EQUIANGULAR) { + xd = m_dFocalLength * cos (dAngle); + yd = m_dFocalLength * sin (dAngle); + } + #ifdef HAVE_SGP - if (pSGP && m_trace >= TRACE_RAYS) { - pSGP->setColor (C_LTBLUE); - pSGP->setRasterOp (RO_XOR); - pSGP->moveAbs (xs, ys); - pSGP->lineAbs (xd, yd); - pSGP->setRasterOp (RO_SET); + if (m_pSGP && m_trace >= Trace::TRACE_PROJECTIONS) { + m_pSGP->setColor (C_YELLOW); + m_pSGP->setRasterOp (RO_OR_REVERSE); + m_pSGP->moveAbs (xs, ys); + m_pSGP->lineAbs (xd, yd); + m_pSGP->setRasterOp (RO_SET); } #endif - sum += projectSingleLine (phm, xd, yd, xs, ys, pSGP); + + sum += projectSingleLine (phm, xd, yd, xs, ys); #ifdef HAVE_SGP - if (m_trace >= TRACE_RAYS) { - traceShowParam (pSGP, "Attenuation :", "%5.2f", RAYSUM_TRACE_ROW_ATTEN, C_LTMAGENTA, sum); + if (m_trace >= Trace::TRACE_CLIPPING) { + traceShowParam ("Attenuation:", "%s", PROJECTION_TRACE_ROW_ATTEN, C_LTMAGENTA, " "); + traceShowParam ("Attenuation:", "%.3f", PROJECTION_TRACE_ROW_ATTEN, C_LTMAGENTA, sum); } - if (pSGP && m_trace >= TRACE_RAYS) { - pSGP->setColor (C_LTBLUE); - pSGP->setRasterOp (RO_XOR); - pSGP->moveAbs (xs, ys); - pSGP->lineAbs (xd, yd); - pSGP->setRasterOp (RO_SET); - } + // if (m_pSGP && m_trace >= Trace::TRACE_PROJECTIONS) { + // m_pSGP->setColor (C_YELLOW); + // m_pSGP->setRasterOp (RO_XOR); + // m_pSGP->moveAbs (xs, ys); + // m_pSGP->lineAbs (xd, yd); + // m_pSGP->setRasterOp (RO_SET); + // } #endif - xd += ddx2; - yd += ddy2; - } + if (m_idGeometry == GEOMETRY_EQUIANGULAR) + dAngle += dAngleSampleInc; + else { + xd += ddx2; + yd += ddy2; + } + } // for each sample in detector detval[d] = sum / m_nSample; - xd_maj += ddx; - yd_maj += ddy; xs_maj += sdx; ys_maj += sdy; + if (m_idGeometry == GEOMETRY_EQUIANGULAR) + dAngleMajor += dAngleInc; + else { + xd_maj += ddx; + yd_maj += ddy; + } } /* for each detector */ } /* if not unit pulse */ } void -Scanner::traceShowParam (SGP* pSGP, const char *label, const char *fmt, int row, int color, ...) +Scanner::traceShowParam (const char *szLabel, const char *fmt, int row, int color, ...) { - char s[256]; va_list arg; + va_start(arg, color); + traceShowParamRasterOp (RO_COPY, szLabel, fmt, row, color, arg); + va_end(arg); +} +void +Scanner::traceShowParamXOR (const char *szLabel, const char *fmt, int row, int color, ...) +{ + va_list arg; va_start(arg, color); - snprintf (s, sizeof(s), label, "%s"); - string strOut(s); - vsnprintf (s, sizeof(s), fmt, arg); - strOut += s; + traceShowParamRasterOp (RO_XOR, szLabel, fmt, row, color, arg); + va_end(arg); +} + +void +Scanner::traceShowParamRasterOp (int iRasterOp, const char *szLabel, const char *fmt, int row, int color, va_list args) +{ + char szValue[256]; + + vsnprintf (szValue, sizeof(szValue), fmt, args); // cio_set_cpos (raysum_trace_menu_column, row); // cio_set_text_clr (color - 8, 0); // cio_set_text_clr (color, 0); - if (pSGP) { - pSGP->moveAbs (0., row * 0.04); - pSGP->setTextColor (color, -1); - pSGP->drawText (strOut); + if (m_pSGP) { + m_pSGP->setRasterOp (iRasterOp); + double dYPos = m_dYMaxWin - (row * m_dTextHeight); + m_pSGP->moveAbs (m_dXMinWin, dYPos); + m_pSGP->setTextColor (color, -1); + m_pSGP->drawText (szLabel); + double dValueOffset = (m_dXMaxWin - m_dXMinWin) / 5; + m_pSGP->moveAbs (m_dXMinWin + dValueOffset, dYPos); + m_pSGP->drawText (szValue); } else { - cio_put_str (strOut.c_str()); + cio_put_str (szLabel); + cio_put_str (szValue); cio_put_str ("\n"); } - - va_end(arg); } + /* NAME * projectSingleLine INTERNAL: Calculates raysum along a line for a Phantom * @@ -478,12 +559,12 @@ Scanner::traceShowParam (SGP* pSGP, const char *label, const char *fmt, int row, */ double -Scanner::projectSingleLine (const Phantom& phm, const double x1, const double y1, const double x2, const double y2, SGP* pSGP) +Scanner::projectSingleLine (const Phantom& phm, const double x1, const double y1, const double x2, const double y2) { // 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, pSGP); + rsum += projectLineAgainstPElem (**i, x1, y1, x2, y2); return (rsum); } @@ -500,23 +581,23 @@ 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, SGP* pSGP) +Scanner::projectLineAgainstPElem (const PhantomElement& pelem, double x1, double y1, double x2, double y2) { if (! pelem.clipLineWorldCoords (x1, y1, x2, y2)) { - if (m_trace == TRACE_CLIPPING) + if (m_trace == Trace::TRACE_CLIPPING) cio_tone (1000., 0.05); return (0.0); } #ifdef HAVE_SGP - if (pSGP && m_trace == TRACE_CLIPPING) { - pSGP->setRasterOp (RO_XOR); - pSGP->moveAbs (x1, y1); - pSGP->lineAbs (x2, y2); + if (m_pSGP && m_trace == Trace::TRACE_CLIPPING) { + m_pSGP->setRasterOp (RO_XOR); + m_pSGP->moveAbs (x1, y1); + m_pSGP->lineAbs (x2, y2); cio_tone (8000., 0.05); - pSGP->moveAbs (x1, y1); - pSGP->lineAbs (x2, y2); - pSGP->setRasterOp (RO_SET); + m_pSGP->moveAbs (x1, y1); + m_pSGP->lineAbs (x2, y2); + m_pSGP->setRasterOp (RO_SET); } #endif diff --git a/libctsim/trace.cpp b/libctsim/trace.cpp index dced2c6..3fe33f0 100644 --- a/libctsim/trace.cpp +++ b/libctsim/trace.cpp @@ -8,7 +8,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: trace.cpp,v 1.2 2000/08/25 15:59:13 kevin Exp $ +** $Id: trace.cpp,v 1.3 2000/08/27 20:32:55 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 @@ -26,33 +26,76 @@ #include "ct.h" -const char TraceLevel::TRACE_NONE_STR[]= "none"; -const char TraceLevel::TRACE_TEXT_STR[]= "text"; -const char TraceLevel::TRACE_PHM_STR[]= "phm"; -const char TraceLevel::TRACE_RAYS_STR[]= "rays"; -const char TraceLevel::TRACE_PLOT_STR[]= "plot"; -const char TraceLevel::TRACE_CLIPPING_STR[]= "clipping"; +const int Trace::TRACE_INVALID = -1; +const int Trace::TRACE_NONE = 0; +const int Trace::TRACE_CONSOLE = 1; +const int Trace::TRACE_PHANTOM = 2; +const int Trace::TRACE_PROJECTIONS = 3; +const int Trace::TRACE_PLOT = 4; +const int Trace::TRACE_CLIPPING = 5; +const int Trace::BIT_CONSOLE = 0x0001; +const int Trace::BIT_PHANTOM = 0x0002; +const int Trace::BIT_PROJECTIONS = 0x0004; +const int Trace::BIT_PLOT = 0x0008; +const int Trace::BIT_CLIPPING = 0x0010; -int -TraceLevel::convertTraceNameToID (const char *traceString) +const char* Trace::s_aszTraceName[] = +{ + {"none"}, + {"console"}, + {"phantom"}, + {"proj"}, + {"plot"}, + {"clipping"}, +}; + +const char* Trace::s_aszTraceTitle[] = +{ + {"None"}, + {"Console"}, + {"Phantom"}, + {"Projections"}, + {"Plot"}, + {"Clipping"}, +}; + +const int Trace::s_iTraceCount = sizeof(s_aszTraceName) / sizeof(const char*); + + +const char* +Trace::convertTraceIDToName (const int idTrace) +{ + const char *name = ""; + + if (idTrace >= 0 && idTrace < s_iTraceCount) + return (s_aszTraceName[idTrace]); + + return (name); +} + +const char* +Trace::convertTraceIDToTitle (const int idTrace) { - int traceID = TRACE_INVALID; - - if (strcasecmp (traceString, TRACE_NONE_STR) == 0) - traceID = TRACE_NONE; - else if (strcasecmp (traceString, TRACE_TEXT_STR) == 0) - traceID = TRACE_TEXT; - else if (strcasecmp (traceString, TRACE_PHM_STR) == 0) - traceID = TRACE_PHM; - else if (strcasecmp (traceString, TRACE_PLOT_STR) == 0) - traceID = TRACE_PLOT; - else if (strcasecmp (traceString, TRACE_CLIPPING_STR) == 0) - traceID = TRACE_CLIPPING; - else if (strcasecmp (traceString, TRACE_RAYS_STR) == 0) - traceID = TRACE_RAYS; - - return (traceID); + const char *title = ""; + + if (idTrace >= 0 && idTrace < s_iTraceCount) + return (s_aszTraceName[idTrace]); + + return (title); } + +int +Trace::convertTraceNameToID (const char* const traceName) +{ + int id = Trace::TRACE_INVALID; + for (int i = 0; i < s_iTraceCount; i++) + if (strcasecmp (traceName, s_aszTraceName[i]) == 0) { + id = i; + break; + } + + return (id); +} diff --git a/src/Makefile.am b/src/Makefile.am index f3fab1e..6d252c1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS=ctsim -ctsim_SOURCES=ctsim.cpp docs.cpp views.cpp dialogs.cpp ctsim.h docs.h views.h dialogs.h +ctsim_SOURCES=ctsim.cpp docs.cpp views.cpp dialogs.cpp ctsim.h docs.h views.h dialogs.h dlgprojections.cpp dlgprojections.h ctsim_DEPENDENCIES=../libctgraphics/libctgraphics.a ../libctsupport/libctsupport.a ../libctsim/libctsim.a ../include/ct.h ctsim_LDADD=-L../libctgraphics -L../libctsupport -L../libctsim @ctlibs@ diff --git a/src/dialogs.cpp b/src/dialogs.cpp index ef5ece2..a3c27f7 100644 --- a/src/dialogs.cpp +++ b/src/dialogs.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: dialogs.cpp,v 1.9 2000/08/25 15:59:13 kevin Exp $ +** $Id: dialogs.cpp,v 1.10 2000/08/27 20:32:55 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 @@ -63,7 +63,7 @@ StringValueAndTitleListBox::StringValueAndTitleListBox (wxDialog* pParent, int n for (int i = 0; i < nChoices; i++) asTitle[i] = aszTitle[i]; - Create (pParent, -1, wxDefaultPosition, wxDefaultSize, nChoices, asTitle, wxLB_SINGLE | wxLB_NEEDED_SB); + Create (pParent, -1, wxDefaultPosition, wxSize(200,-1), nChoices, asTitle, wxLB_SINGLE | wxLB_NEEDED_SB); m_ppszValues = aszValue; }; @@ -81,9 +81,9 @@ DialogGetPhantom::DialogGetPhantom (wxFrame* pParent, int iDefaultPhantom = Phan { wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL); - pTopSizer->Add (new wxStaticText (this, -1, "Select Phantom"), 0, wxALIGN_CENTER | wxTOP | wxLEFT | wxRIGHT, 5); + pTopSizer->Add (new wxStaticText (this, -1, "Select Phantom"), 0, wxALIGN_CENTER | wxALL, 5); - pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); + pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxALL, 5); m_pListBoxPhantom = new StringValueAndTitleListBox (this, Phantom::getPhantomCount(), Phantom::getPhantomTitleArray(), Phantom::getPhantomNameArray()); m_pListBoxPhantom->SetSelection (iDefaultPhantom); @@ -128,7 +128,7 @@ DialogGetImageMinMax::DialogGetImageMinMax (wxFrame* pParent, const ImageFile& r osMax << dDefaultMax; m_pTextCtrlMax = new wxTextCtrl (this, -1, osMax.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); - wxGridSizer *pGridSizer = new wxGridSizer (2, 2, 5); + wxGridSizer *pGridSizer = new wxGridSizer (2); pGridSizer->Add (new wxStaticText (this, -1, "Minimum"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (m_pTextCtrlMin, 0, wxALIGN_CENTER_VERTICAL); pGridSizer->Add (new wxStaticText (this, -1, "Maximum"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); @@ -207,7 +207,7 @@ DialogGetRasterParameters::DialogGetRasterParameters (wxFrame* pParent, int iDef osNSamples << iDefaultNSamples; m_pTextCtrlNSamples = new wxTextCtrl (this, -1, osNSamples.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); - wxGridSizer *pGridSizer = new wxGridSizer (2, 3, 5); + wxGridSizer *pGridSizer = new wxGridSizer (2); pGridSizer->Add (new wxStaticText (this, -1, "X Size"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (m_pTextCtrlXSize, 0, wxALIGN_CENTER_VERTICAL); pGridSizer->Add (new wxStaticText (this, -1, "Y Size"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); @@ -280,7 +280,7 @@ DialogGetRasterParameters::getNSamples (void) ///////////////////////////////////////////////////////////////////// -DialogGetProjectionParameters::DialogGetProjectionParameters (wxFrame* pParent, int iDefaultNDet = 0, int iDefaultNView = 0, int iDefaultNSamples = 1, double dDefaultRotAngle = 1., double dDefaultFocalLength = 1, double dDefaultFieldOfView = 1., int iDefaultGeometry = Scanner::GEOMETRY_PARALLEL) +DialogGetProjectionParameters::DialogGetProjectionParameters (wxFrame* pParent, int iDefaultNDet = 0, int iDefaultNView = 0, int iDefaultNSamples = 1, double dDefaultRotAngle = 1., double dDefaultFocalLength = 1, double dDefaultFieldOfView = 1., int iDefaultGeometry = Scanner::GEOMETRY_PARALLEL, int iDefaultTrace = Trace::TRACE_NONE) : wxDialog (pParent, -1, "Set Projection Parameters", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxCAPTION) { wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL); @@ -291,6 +291,7 @@ DialogGetProjectionParameters::DialogGetProjectionParameters (wxFrame* pParent, m_iDefaultNSamples = iDefaultNSamples; m_iDefaultNView = iDefaultNView; m_iDefaultNDet = iDefaultNDet; + m_iDefaultTrace = iDefaultTrace; pTopSizer->Add (new wxStaticText (this, -1, "Set Projection Parameters"), 0, wxALIGN_CENTER | wxTOP | wxLEFT | wxRIGHT, 5); @@ -298,7 +299,6 @@ DialogGetProjectionParameters::DialogGetProjectionParameters (wxFrame* pParent, m_pListBoxGeometry = new StringValueAndTitleListBox (this, Scanner::getGeometryCount(), Scanner::getGeometryTitleArray(), Scanner::getGeometryNameArray()); m_pListBoxGeometry->SetSelection (iDefaultGeometry); - pTopSizer->Add (m_pListBoxGeometry, 0, wxALL | wxALIGN_CENTER | wxEXPAND); ostringstream os; os << iDefaultNDet; @@ -319,7 +319,12 @@ DialogGetProjectionParameters::DialogGetProjectionParameters (wxFrame* pParent, osFieldOfView << dDefaultFieldOfView; m_pTextCtrlFieldOfView = new wxTextCtrl (this, -1, osFieldOfView.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); - wxGridSizer *pGridSizer = new wxGridSizer (2, 4, 5); + wxGridSizer* pGeometryGridSizer = new wxGridSizer (2); + pGeometryGridSizer->Add (new wxStaticText (this, -1, "Scanner Geometry"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pGeometryGridSizer->Add (m_pListBoxGeometry, 0, wxALL | wxALIGN_CENTER | wxEXPAND); + pTopSizer->Add (pGeometryGridSizer, 1, wxALL, 10); + + wxGridSizer* pGridSizer = new wxGridSizer (2); pGridSizer->Add (new wxStaticText (this, -1, "Detectors"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (m_pTextCtrlNDet, 0, wxALIGN_CENTER_VERTICAL); pGridSizer->Add (new wxStaticText (this, -1, "Views"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); @@ -334,6 +339,14 @@ DialogGetProjectionParameters::DialogGetProjectionParameters (wxFrame* pParent, pGridSizer->Add (m_pTextCtrlFieldOfView, 0, wxALIGN_CENTER_VERTICAL); pTopSizer->Add (pGridSizer, 1, wxALL, 10); + m_pListBoxTrace = new StringValueAndTitleListBox (this, Trace::getTraceCount(), Trace::getTraceTitleArray(), Trace::getTraceNameArray()); + m_pListBoxTrace->SetSelection (iDefaultTrace); + + wxGridSizer *pTraceGridSizer = new wxGridSizer (2); + pTraceGridSizer->Add (new wxStaticText (this, -1, "Trace Level"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pTraceGridSizer->Add (m_pListBoxTrace, 0, wxALL | wxALIGN_CENTER | wxEXPAND); + pTopSizer->Add (pTraceGridSizer, 1, wxALL, 10); + pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); wxBoxSizer* pButtonSizer = new wxBoxSizer (wxHORIZONTAL); @@ -428,6 +441,12 @@ DialogGetProjectionParameters::getGeometry (void) return m_pListBoxGeometry->getSelectionStringValue(); } +int +DialogGetProjectionParameters::getTrace (void) +{ + return Trace::convertTraceNameToID(m_pListBoxTrace->getSelectionStringValue()); +} + ///////////////////////////////////////////////////////////////////// @@ -446,24 +465,32 @@ DialogGetReconstructionParameters::DialogGetReconstructionParameters (wxFrame* p pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); + wxGridSizer* pFilterGrid = new wxGridSizer (2); + pFilterGrid->Add (new wxStaticText (this, -1, "Filter"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); m_pListBoxFilter = new StringValueAndTitleListBox (this, SignalFilter::getFilterCount(), SignalFilter::getFilterTitleArray(), SignalFilter::getFilterNameArray()); m_pListBoxFilter->SetSelection (iDefaultFilterID); - pTopSizer->Add (m_pListBoxFilter, 0, wxALL | wxALIGN_CENTER | wxEXPAND); + pFilterGrid->Add (m_pListBoxFilter, 0, wxALL | wxALIGN_LEFT | wxEXPAND); m_pListBoxFilterMethod = new StringValueAndTitleListBox (this, ProcessSignal::getFilterMethodCount(), ProcessSignal::getFilterMethodTitleArray(), ProcessSignal::getFilterMethodNameArray()); m_pListBoxFilterMethod->SetSelection (iDefaultFilterMethodID); - pTopSizer->Add (m_pListBoxFilterMethod, 0, wxALL | wxALIGN_CENTER | wxEXPAND); + pFilterGrid->Add (new wxStaticText (this, -1, "Filter Method"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); + pFilterGrid->Add (m_pListBoxFilterMethod, 0, wxALL | wxALIGN_LEFT | wxEXPAND); m_pListBoxFilterGeneration = new StringValueAndTitleListBox (this, ProcessSignal::getFilterGenerationCount(), ProcessSignal::getFilterGenerationTitleArray(), ProcessSignal::getFilterGenerationNameArray()); m_pListBoxFilterGeneration->SetSelection (iDefaultFilterGenerationID); - pTopSizer->Add (m_pListBoxFilterGeneration, 0, wxALL | wxALIGN_CENTER | wxEXPAND); + pFilterGrid->Add (new wxStaticText (this, -1, "Filter Generation"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); + pFilterGrid->Add (m_pListBoxFilterGeneration, 0, wxALL | wxALIGN_LEFT | wxEXPAND); m_pListBoxBackproject = new StringValueAndTitleListBox (this, Backprojector::getBackprojectCount(), Backprojector::getBackprojectTitleArray(), Backprojector::getBackprojectNameArray()); m_pListBoxBackproject->SetSelection (iDefaultBackprojectID); - pTopSizer->Add (m_pListBoxBackproject, 0, wxALL | wxALIGN_CENTER | wxEXPAND); + pFilterGrid->Add (new wxStaticText (this, -1, "Backprojection"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); + pFilterGrid->Add (m_pListBoxBackproject, 0, wxALL | wxALIGN_RIGHT | wxEXPAND); m_pListBoxInterp = new StringValueAndTitleListBox (this, Backprojector::getInterpCount(), Backprojector::getInterpTitleArray(), Backprojector::getInterpNameArray()); m_pListBoxInterp->SetSelection (iDefaultInterpID); - pTopSizer->Add (m_pListBoxInterp, 0, wxALL | wxALIGN_CENTER | wxEXPAND); + pFilterGrid->Add (new wxStaticText (this, -1, "Interpolation"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); + pFilterGrid->Add (m_pListBoxInterp, 0, wxALL | wxALIGN_RIGHT | wxEXPAND); + + pTopSizer->Add (pFilterGrid, 1, wxALL); ostringstream os; os << iDefaultXSize; @@ -481,18 +508,18 @@ DialogGetReconstructionParameters::DialogGetReconstructionParameters (wxFrame* p osInterpParam << iDefaultInterpParam; m_pTextCtrlInterpParam = new wxTextCtrl (this, -1, osInterpParam.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); - wxGridSizer *pGridSizer = new wxGridSizer (2, 5, 5); + wxGridSizer* pGridSizer = new wxGridSizer (2); pGridSizer->Add (new wxStaticText (this, -1, "X Size"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - pGridSizer->Add (m_pTextCtrlXSize, 0, wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlXSize, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (new wxStaticText (this, -1, "Y Size"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - pGridSizer->Add (m_pTextCtrlYSize, 0, wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlYSize, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (new wxStaticText (this, -1, "Filter Parameter"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - pGridSizer->Add (m_pTextCtrlFilterParam, 0, wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlFilterParam, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (new wxStaticText (this, -1, "Zeropad"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - pGridSizer->Add (m_pTextCtrlZeropad, 0, wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlZeropad, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (new wxStaticText (this, -1, "Interpolation Parameter"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - pGridSizer->Add (m_pTextCtrlInterpParam, 0, wxALIGN_CENTER_VERTICAL); - pTopSizer->Add (pGridSizer, 1, wxALL, 10); + pGridSizer->Add (m_pTextCtrlInterpParam, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + pTopSizer->Add (pGridSizer, 1, wxALL, 3); pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); @@ -506,6 +533,7 @@ DialogGetReconstructionParameters::DialogGetReconstructionParameters (wxFrame* p SetAutoLayout (true); SetSizer (pTopSizer); + pTopSizer->Layout(); pTopSizer->Fit (this); pTopSizer->SetSizeHints (this); } @@ -620,7 +648,7 @@ DialogAutoScaleParameters::DialogAutoScaleParameters (wxFrame *pParent, const Im m_pListBoxCenter->SetSelection (0); pTopSizer->Add (m_pListBoxCenter, 0, wxALL | wxALIGN_CENTER | wxEXPAND); - wxGridSizer *pGridSizer = new wxGridSizer (2, 2, 5); + wxGridSizer *pGridSizer = new wxGridSizer (2); pGridSizer->Add (new wxStaticText (this, -1, "Standard Deviation Factor"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); m_pTextCtrlStdDevFactor = new wxTextCtrl (this, -1, "1.0", wxDefaultPosition, wxSize(100, 25), 0); pGridSizer->Add (m_pTextCtrlStdDevFactor, 0, wxALIGN_CENTER_VERTICAL); diff --git a/src/dialogs.h b/src/dialogs.h index 7298348..77b7cbf 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.10 2000/08/25 15:59:13 kevin Exp $ +** $Id: dialogs.h,v 1.11 2000/08/27 20:32:55 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 @@ -31,6 +31,7 @@ #include "wx/wx.h" #include +#include "ctsupport.h" #include "scanner.h" #include "phantom.h" #include "procsignal.h" @@ -109,12 +110,14 @@ class DialogGetRasterParameters : public wxDialog class DialogGetProjectionParameters : public wxDialog { public: - DialogGetProjectionParameters (wxFrame* pParent, int iDefaultNDet = 0, int iDefaultNView = 0, int iDefaultNSamples = 1, double dDefaultRotAngle = 1., double dDefaultFocalLength = 1, double dDefaultFieldOfView = 1., int iDefaultGeometry = Scanner::GEOMETRY_PARALLEL); + DialogGetProjectionParameters (wxFrame* pParent, int iDefaultNDet = 0, int iDefaultNView = 0, int iDefaultNSamples = 1, double dDefaultRotAngle = 1., double dDefaultFocalLength = 1, double dDefaultFieldOfView = 1., int iDefaultGeometry = Scanner::GEOMETRY_PARALLEL, int iDefaultTrace = Trace::TRACE_NONE); ~DialogGetProjectionParameters (void); unsigned int getNDet (void); unsigned int getNView (void); unsigned int getNSamples (void); + int getTrace (void); + double getRotAngle (void); double getFieldOfViewRatio (void); double getFocalLengthRatio (void); @@ -129,10 +132,12 @@ class DialogGetProjectionParameters : public wxDialog wxTextCtrl* m_pTextCtrlFieldOfView; StringValueAndTitleListBox* m_pListBoxGeometry; + StringValueAndTitleListBox* m_pListBoxTrace; int m_iDefaultNDet; int m_iDefaultNView; int m_iDefaultNSamples; + int m_iDefaultTrace; double m_dDefaultRotAngle; double m_dDefaultFocalLength; double m_dDefaultFieldOfView; diff --git a/src/dlgprojections.cpp b/src/dlgprojections.cpp new file mode 100644 index 0000000..8f66dc3 --- /dev/null +++ b/src/dlgprojections.cpp @@ -0,0 +1,186 @@ +/***************************************************************************** +** FILE IDENTIFICATION +** +** Name: dlgprojections.cpp +** Purpose: Projection Collection Animation Dialog +** Programmer: Kevin Rosenberg +** Date Started: August 2000 +** +** This is part of the CTSim program +** Copyright (C) 1983-2000 Kevin Rosenberg +** +** $Id: dlgprojections.cpp,v 1.1 2000/08/27 20:32:55 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 +******************************************************************************/ + +#ifdef __GNUG__ + #pragma implementation "dlgprojections.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/utils.h" + #include "wx/frame.h" + #include "wx/button.h" + #include "wx/stattext.h" + #include "wx/layout.h" + #include "wx/event.h" + #include "wx/intl.h" + #include "wx/settings.h" + #include "wx/dcclient.h" + #include "wx/timer.h" +#endif + +#include "dlgprojections.h" +#include "ct.h" + + +static const int LAYOUT_X_MARGIN = 4; +static const int LAYOUT_Y_MARGIN = 4; + +BEGIN_EVENT_TABLE(ProjectionsDialog, wxDialog) + EVT_BUTTON(wxID_CANCEL, ProjectionsDialog::OnCancel) + EVT_CLOSE(ProjectionsDialog::OnClose) +END_EVENT_TABLE() + +IMPLEMENT_CLASS(ProjectionsDialog, wxDialog) + + +ProjectionsDialog::ProjectionsDialog (Scanner& rScanner, Projections& rProj, const Phantom& rPhantom, const int iTrace, wxWindow *parent) + : wxDialog(parent, -1, "Collect Projections"), m_rScanner(rScanner), m_rProjections(rProj), m_rPhantom(rPhantom), m_pSGPDriver(NULL), m_pSGP(NULL), m_iTrace(iTrace), m_pDC(NULL) +{ + m_state = Continue; + + m_parentTop = parent; + while ( m_parentTop && m_parentTop->GetParent() ) + m_parentTop = m_parentTop->GetParent(); + + m_btnAbort = new wxButton(this, wxID_CANCEL, _("Cancel")); + wxLayoutConstraints* c = new wxLayoutConstraints; + c->right.SameAs(this, wxRight, 2*LAYOUT_X_MARGIN); + c->bottom.SameAs(this, wxBottom, 2*LAYOUT_Y_MARGIN); + + wxSize sizeBtn = wxButton::GetDefaultSize(); + c->width.Absolute(sizeBtn.x); + c->height.Absolute(sizeBtn.y); + + m_btnAbort->SetConstraints(c); + + SetAutoLayout(TRUE); + Layout(); + + wxSize sizeDlg (600,600); + if (sizeDlg.x != sizeDlg.y) { + sizeDlg.x = max(sizeDlg.x,sizeDlg.y); + sizeDlg.y = max(sizeDlg.x,sizeDlg.y); + } + SetClientSize(sizeDlg); + + Centre(wxCENTER_FRAME | wxBOTH); + + if ( m_parentTop ) + m_parentTop->Enable(FALSE); + + Show(TRUE); + Enable(TRUE); // enable this window + + m_pDC = dynamic_cast (new wxClientDC (this)); + int x, y; + this->GetClientSize(&x, &y); + m_pSGPDriver = new SGPDriver (m_pDC, x, y); + m_pSGP = new SGP (*m_pSGPDriver); + + wxYield(); // Update the display + +#ifdef __WXMAC__ + MacUpdateImmediately(); +#endif +} + +bool +ProjectionsDialog::projectView (int iViewNumber) +{ + if ( iViewNumber < m_rProjections.nView() ) { + m_rScanner.collectProjections (m_rProjections, m_rPhantom, iViewNumber, 1, true, m_iTrace, m_pSGP); + wxYield(); // update the display + } else { + m_state = Finished; // so that we return TRUE below and + // that [Cancel] handler knew what to do +#if 0 + if ( m_btnAbort ) + m_btnAbort->SetLabel(_("Close")); // tell the user what he should do... + wxYield(); + + (void)ShowModal(); +#endif + } + +#ifdef __WXMAC__ + MacUpdateImmediately(); +#endif + + return m_state != Canceled; +} + + +// EVENT HANDLERS + +void ProjectionsDialog::OnCancel (wxCommandEvent& event) +{ + if ( m_state == Finished ) { + // this means that the count down is already finished and we're being + // shown as a modal dialog - so just let the default handler do the job + event.Skip(); + } else { + // request to cancel was received, the next time Update() is called we + // will handle it + m_state = Canceled; + + // update the button state immediately so that the user knows that the + // request has been noticed + m_btnAbort->Disable(); + } +} + +void ProjectionsDialog::OnClose(wxCloseEvent& event) +{ + if ( m_state == Uncancelable ) + event.Veto(TRUE); // can't close this dialog + else if ( m_state == Finished ) + event.Skip(); // let the default handler close the window as we already terminated + else + m_state = Canceled; // next Update() will notice it +} + + +///////////////////////////////////////////////////// +// destruction + +ProjectionsDialog::~ProjectionsDialog() +{ + if ( m_parentTop ) + m_parentTop->Enable(TRUE); + + delete m_pSGP; + delete m_pSGPDriver; + delete m_pDC; +} + diff --git a/src/dlgprojections.h b/src/dlgprojections.h new file mode 100644 index 0000000..440d2ff --- /dev/null +++ b/src/dlgprojections.h @@ -0,0 +1,100 @@ +/***************************************************************************** +** FILE IDENTIFICATION +** +** Name: dlgprojections.h +** Purpose: Headers for Projection Collection Animation Dialog +** Programmer: Kevin Rosenberg +** Date Started: August 2000 +** +** This is part of the CTSim program +** Copyright (C) 1983-2000 Kevin Rosenberg +** +** $Id: dlgprojections.h,v 1.1 2000/08/27 20:32:55 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 __DLGPROJECTIONS_H_ +#define __DLGPROJECTIONS_H_ + +#ifdef __GNUG__ +#pragma interface "dlgprojections.h" +#endif + +#include "wx/setup.h" +#include "wx/dialog.h" + +class wxButton; +class wxStaticText; +class Projections; +class Phantom; +class SGP; +class Scanner; +class SGP; +class SGPDriver; + +class ProjectionsDialog : public wxDialog +{ + DECLARE_DYNAMIC_CLASS(ProjectionsDialog) + +public: + ProjectionsDialog (Scanner& rScanner, Projections& rProj, const Phantom& rPhantom, const int iTrace, wxWindow *parent); + + ~ProjectionsDialog(); + + /* Perform projection on view number + return true if ABORT button has not been pressed + */ + bool projectView(int iViewNumber); + + /* Can be called to continue after the cancel button has been pressed, but + the program decided to continue the operation (e.g., user didn't + confirm it) + */ + void Resume() { m_state = Continue; } + + // implementation from now on + // callback for optional abort button + void OnCancel(wxCommandEvent& event); + // callback to disable "hard" window closing + void OnClose(wxCloseEvent& event); + +private: + // parent top level window (may be NULL) + wxWindow *m_parentTop; + + // continue processing or not (return value for Update()) + enum + { + Uncancelable = -1, // dialog can't be canceled + Canceled, // can be cancelled and, in fact, was + Continue, // can be cancelled but wasn't + Finished // finished, waiting to be removed from screen + } m_state; + + // the abort button (or NULL if none) + wxButton *m_btnAbort; + + Scanner& m_rScanner; + Projections& m_rProjections; + const Phantom& m_rPhantom; + SGPDriver* m_pSGPDriver; + SGP* m_pSGP; + const int m_iTrace; + wxDC* m_pDC; + + DECLARE_EVENT_TABLE() +}; +#endif + diff --git a/src/views.cpp b/src/views.cpp index 1cd730e..edc35e6 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.16 2000/08/25 15:59:13 kevin Exp $ +** $Id: views.cpp,v 1.17 2000/08/27 20:32:55 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 @@ -51,6 +51,7 @@ #include "docs.h" #include "views.h" #include "dialogs.h" +#include "dlgprojections.h" #include #include "backprojectors.h" @@ -214,9 +215,9 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom..."); file_menu->Append(wxID_OPEN, "&Open..."); - file_menu->Append(wxID_CLOSE, "&Close"); file_menu->Append(wxID_SAVE, "&Save"); file_menu->Append(wxID_SAVEAS, "Save &As..."); + file_menu->Append(wxID_CLOSE, "&Close"); file_menu->AppendSeparator(); file_menu->Append(IFMENU_FILE_PROPERTIES, "P&roperties"); @@ -251,6 +252,7 @@ bool ImageFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) { m_frame = CreateChildFrame(doc, this); + SetFrame(m_frame); m_bMinSpecified = false; m_bMaxSpecified = false; @@ -402,12 +404,13 @@ PhantomView::OnProperties (wxCommandEvent& event) void PhantomView::OnProjections (wxCommandEvent& event) { - DialogGetProjectionParameters dialogProjection (m_frame, 367, 320, 1, 1., 1., 1., Scanner::GEOMETRY_PARALLEL); + DialogGetProjectionParameters dialogProjection (m_frame, 367, 320, 1, 1., 1., 1., Scanner::GEOMETRY_PARALLEL, Trace::TRACE_NONE); int retVal = dialogProjection.ShowModal(); if (retVal == wxID_OK) { int nDet = dialogProjection.getNDet(); int nView = dialogProjection.getNView(); int nSamples = dialogProjection.getNSamples(); + int iTrace = dialogProjection.getTrace(); double dRotAngle = dialogProjection.getRotAngle(); double dFocalLengthRatio = dialogProjection.getFocalLengthRatio(); double dFieldOfViewRatio = dialogProjection.getFieldOfViewRatio(); @@ -424,23 +427,24 @@ PhantomView::OnProjections (wxCommandEvent& event) } rProj.initFromScanner (theScanner); -#if 1 - wxFrame frame (m_frame, -1, "", wxDefaultPosition, wxSize(500,500)); - frame.Show(); - wxClientDC dc (&frame); - int x, y; - frame.GetClientSize(&x, &y); - SGPDriver driver (dynamic_cast(&dc), x, y); - SGP sgp (driver); - for (int iView = 0; iView < rProj.nView(); iView++) { - theScanner.collectProjections (rProj, rPhantom, iView, 1, true, TRACE_RAYS, &sgp); - } -#else - theScanner.collectProjections (rProj, rPhantom); -#endif + if (iTrace > Trace::TRACE_CONSOLE) { + ProjectionsDialog dialogProjections (theScanner, rProj, rPhantom, iTrace, dynamic_cast(m_frame)); + for (int iView = 0; iView < rProj.nView(); iView++) { + if (! dialogProjections.projectView (iView)) { + pProjectionDoc->DeleteAllViews(); + return; + } + ::wxYield(); + } + } else + theScanner.collectProjections (rProj, rPhantom); pProjectionDoc->Modify(true); pProjectionDoc->UpdateAllViews(this); + if (wxView* pView = pProjectionDoc->GetFirstView()) + if (wxFrame* pFrame = pView->GetFrame()) { + pFrame->SetFocus(); + } ostringstream os; os << "Projections for " << rPhantom.name() << ": nDet=" << nDet << ", nView=" << nView << ", nSamples=" << nSamples << ", RotAngle=" << dRotAngle << ", FocalLengthRatio=" << dFocalLengthRatio << ", FieldOfViewRatio=" << dFieldOfViewRatio << ", Geometry=" << sGeometry.c_str() << "\n"; *theApp->getLog() << os.str().c_str(); @@ -466,7 +470,7 @@ PhantomView::OnRasterize (wxCommandEvent& event) ImageFile& imageFile = pRasterDoc->getImageFile(); imageFile.setArraySize (xSize, ySize); - rPhantom.convertToImagefile (imageFile, nSamples, TRACE_NONE); + rPhantom.convertToImagefile (imageFile, nSamples, Trace::TRACE_NONE); pRasterDoc->Modify(true); pRasterDoc->UpdateAllViews(this); @@ -538,7 +542,8 @@ bool PhantomView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) { m_frame = CreateChildFrame(doc, this); - + SetFrame(m_frame); + int width, height; m_frame->GetClientSize(&width, &height); m_frame->SetTitle("PhantomView"); @@ -667,7 +672,7 @@ ProjectionFileView::OnReconstruct (wxCommandEvent& event) ImageFile& imageFile = pReconDoc->getImageFile(); const Projections& rProj = GetDocument()->getProjections(); imageFile.setArraySize (xSize, ySize); - rProj.reconstruct (imageFile, optFilterName.c_str(), optFilterParam, optFilterMethodName.c_str(), optZeropad, optFilterGenerationName.c_str(), optInterpName.c_str(), optInterpParam, optBackprojectName.c_str(), TRACE_NONE); + rProj.reconstruct (imageFile, optFilterName.c_str(), optFilterParam, optFilterMethodName.c_str(), optZeropad, optFilterGenerationName.c_str(), optInterpName.c_str(), optInterpParam, optBackprojectName.c_str(), Trace::TRACE_NONE); pReconDoc->Modify(true); pReconDoc->UpdateAllViews(this); ostringstream os; @@ -703,6 +708,8 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view) file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom..."); file_menu->Append(wxID_OPEN, "&Open..."); + file_menu->Append(wxID_SAVE, "&Save"); + file_menu->Append(wxID_SAVEAS, "Save &As..."); file_menu->Append(wxID_CLOSE, "&Close"); file_menu->AppendSeparator(); @@ -739,6 +746,7 @@ bool ProjectionFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) { m_frame = CreateChildFrame(doc, this); + SetFrame(m_frame); int width, height; m_frame->GetClientSize(&width, &height); diff --git a/tools/phm2if.cpp b/tools/phm2if.cpp index 9ff3b9a..53abeab 100644 --- a/tools/phm2if.cpp +++ b/tools/phm2if.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phm2if.cpp,v 1.10 2000/08/25 15:59:13 kevin Exp $ +** $Id: phm2if.cpp,v 1.11 2000/08/27 20:32:55 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 @@ -50,7 +50,7 @@ static struct option my_options[] = {0, 0, 0, 0} }; -static const char* g_szIdStr = "$Id: phm2if.cpp,v 1.10 2000/08/25 15:59:13 kevin Exp $"; +static const char* g_szIdStr = "$Id: phm2if.cpp,v 1.11 2000/08/27 20:32:55 kevin Exp $"; void phm2if_usage (const char *program) @@ -88,9 +88,9 @@ phm2if_usage (const char *program) cout << " --nsample Number of samples per axis per pixel (default = 1)" << endl; cout << " --trace Trace level to use" << endl; cout << " none No tracing (default)" << endl; - cout << " text Trace text level" << endl; - cout << " phm Trace phantom" << endl; - cout << " rays Trace rays" << endl; + cout << " console Trace text level" << endl; + cout << " phantom Trace phantom" << endl; + cout << " proj Trace projections" << endl; cout << " plot Trace plot" << endl; cout << " clipping Trace clipping" << endl; cout << " --debug Debug mode" << endl; @@ -119,7 +119,7 @@ phm2if_main (int argc, char* argv[]) int opt_nsample = 1; double optFilterParam = 1.; double optFilterBW = 1.; - int optTrace = TRACE_NONE; + int optTrace = Trace::TRACE_NONE; bool optVerbose = false; bool optDebug = false; char *endptr = NULL; @@ -150,7 +150,7 @@ phm2if_main (int argc, char* argv[]) optDebug = true; break; case O_TRACE: - if ((optTrace = TraceLevel::convertTraceNameToID(optarg)) == TRACE_INVALID) { + if ((optTrace = Trace::convertTraceNameToID(optarg)) == Trace::TRACE_INVALID) { phm2if_usage(argv[0]); return (1); } @@ -333,7 +333,7 @@ phm2if_main (int argc, char* argv[]) pImGlobal->filterResponse (optDomainName.c_str(), optFilterBW, optFilterName.c_str(), optFilterParam); } else { #if HAVE_SGP - if (optTrace >= TRACE_PHM) + if (optTrace >= Trace::TRACE_PHANTOM) phm.show(); #endif phm.convertToImagefile (*pImGlobal, opt_nsample, optTrace); @@ -350,7 +350,7 @@ phm2if_main (int argc, char* argv[]) if (optVerbose) cout << "Time to rasterized phantom: " << calctime << " seconds" << endl; - if (optTrace >= TRACE_PHM) { + if (optTrace >= Trace::TRACE_PHANTOM) { double dmin, dmax; int nscale; diff --git a/tools/phm2pj.cpp b/tools/phm2pj.cpp index 2bc4d98..0459f53 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.10 2000/08/25 15:59:13 kevin Exp $ +** $Id: phm2pj.cpp,v 1.11 2000/08/27 20:32:55 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 @@ -50,7 +50,7 @@ static struct option phm2pj_options[] = {0, 0, 0, 0} }; -static const char* g_szIdStr = "$Id: phm2pj.cpp,v 1.10 2000/08/25 15:59:13 kevin Exp $"; +static const char* g_szIdStr = "$Id: phm2pj.cpp,v 1.11 2000/08/27 20:32:55 kevin Exp $"; void @@ -58,7 +58,7 @@ phm2pj_usage (const char *program) { cout << "usage: " << fileBasename(program) << " outfile ndet nview [--phantom phantom-name] [--phmfile filename] [OPTIONS]\n"; cout << "Calculate (projections) through phantom object, either a predefined --phantom or a --phmfile\n\n"; - cout << " outfile Name of output file for raysums\n"; + cout << " outfile Name of output file for projections\n"; cout << " ndet Number of detectors\n"; cout << " nview Number of rotated views\n"; cout << " --phantom Phantom to use for projection\n"; @@ -78,9 +78,9 @@ phm2pj_usage (const char *program) cout << " (default = 1)\n"; cout << " --trace Trace level to use\n"; cout << " none No tracing (default)\n"; - cout << " text Trace text level\n"; - cout << " phm Trace phantom image\n"; - cout << " rays Trace rays\n"; + cout << " console Trace text level\n"; + cout << " phantom Trace phantom image\n"; + cout << " proj Trace projections\n"; cout << " plot Trace plot\n"; cout << " clipping Trace clipping\n"; cout << " --verbose Verbose mode\n"; @@ -106,7 +106,7 @@ phm2pj_main (int argc, char* argv[]) int opt_nray = 1; double dOptFocalLength = 1.; double dOptFieldOfView = 1.; - int opt_trace = 0; + int opt_trace = Trace::TRACE_NONE; string optPhmName (Phantom::convertPhantomIDToName(Phantom::PHM_HERMAN)); int opt_verbose = 0; int opt_debug = 0; @@ -144,7 +144,7 @@ phm2pj_main (int argc, char* argv[]) break; break; case O_TRACE: - if ((opt_trace = TraceLevel::convertTraceNameToID(optarg)) == TRACE_INVALID) { + if ((opt_trace = Trace::convertTraceNameToID(optarg)) == Trace::TRACE_INVALID) { phm2pj_usage(argv[0]); return (1); } @@ -320,12 +320,12 @@ phm2pj_main (int argc, char* argv[]) #if HAVE_SGP SGPDriver* pSGPDriver = NULL; SGP* pSGP = NULL; - if (opt_trace >= TRACE_PHM) { + if (opt_trace >= Trace::TRACE_PHANTOM) { pSGPDriver = new SGPDriver ("phm2pj", 600, 600); pSGP = new SGP (*pSGPDriver); } scanner.collectProjections (pjGlobal, phm, opt_trace, pSGP); - if (opt_trace >= TRACE_PHM) { + if (opt_trace >= Trace::TRACE_PHANTOM) { cout << "Press enter to continue\n"; cio_kb_getc(); delete pSGP; pSGP = NULL; diff --git a/tools/pjrec.cpp b/tools/pjrec.cpp index 19b9b86..157d658 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.14 2000/08/25 15:59:13 kevin Exp $ +** $Id: pjrec.cpp,v 1.15 2000/08/27 20:32:55 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 @@ -49,7 +49,7 @@ static struct option my_options[] = {0, 0, 0, 0} }; -static const char* g_szIdStr = "$Id: pjrec.cpp,v 1.14 2000/08/25 15:59:13 kevin Exp $"; +static const char* g_szIdStr = "$Id: pjrec.cpp,v 1.15 2000/08/27 20:32:55 kevin Exp $"; void pjrec_usage (const char *program) @@ -103,12 +103,12 @@ pjrec_usage (const char *program) cout << " idiff3 Highly-optimized difference method with integer math" << endl; cout << " --filter-param Alpha level for Hamming filter" << endl; cout << " --trace Set tracing to level" << endl; - cout << " none No tracing (default)" << endl; - cout << " text Text level tracing" << endl; - cout << " phm Trace phantom" << endl; - cout << " rays Trace allrays" << endl; - cout << " plot Trace plotting" << endl; - cout << " clipping Trace clipping" << endl; + cout << " none No tracing (default)" << endl; + cout << " console Text level tracing" << endl; + cout << " phantom Trace phantom" << endl; + cout << " proj Trace allrays" << endl; + cout << " plot Trace plotting" << endl; + cout << " clipping Trace clipping" << endl; cout << " --verbose Turn on verbose mode" << endl; cout << " --debug Turn on debug mode" << endl; cout << " --version Print version" << endl; @@ -133,7 +133,7 @@ pjrec_main (int argc, char * argv[]) bool bOptVerbose = false; bool bOptDebug = 1; int iOptZeropad = 1; - int optTrace = TRACE_NONE; + int optTrace = Trace::TRACE_NONE; double dOptFilterParam = -1; string sOptFilterName (SignalFilter::convertFilterIDToName (SignalFilter::FILTER_ABS_BANDLIMIT)); string sOptFilterMethodName (ProcessSignal::convertFilterMethodIDToName (ProcessSignal::FILTER_METHOD_CONVOLUTION)); @@ -207,7 +207,7 @@ pjrec_main (int argc, char * argv[]) bOptDebug = true; break; case O_TRACE: - if ((optTrace = TraceLevel::convertTraceNameToID(optarg)) == TRACE_INVALID) { + if ((optTrace = Trace::convertTraceNameToID(optarg)) == Trace::TRACE_INVALID) { pjrec_usage(argv[0]); return (1); } -- 2.34.1