r640: no message
authorKevin M. Rosenberg <kevin@rosenberg.net>
Sun, 18 Mar 2001 18:08:26 +0000 (18:08 +0000)
committerKevin M. Rosenberg <kevin@rosenberg.net>
Sun, 18 Mar 2001 18:08:26 +0000 (18:08 +0000)
19 files changed:
ChangeLog
NEWS
doc/ctsim-algorithms.tex
doc/ctsim.prj
include/fourier.h
include/imagefile.h
libctsim/backprojectors.cpp
libctsim/fourier.cpp
libctsim/imagefile.cpp
libctsim/procsignal.cpp
libctsim/projections.cpp
libctsim/scanner.cpp
msvc/ctsim/ctsim.plg
src/backgroundmgr.cpp
src/ctsim.h
src/graph3dview.cpp
src/graph3dview.h
src/views.cpp
src/views.h

index a9677d80ea8eb54a96f08e25d65238ea071b094d..fe1e67387d5354be7d6bd3f4f0b95990e59fc658 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
        background processing as well as taking advantage of multiple-CPU's 
        on SMP systems.
 
        background processing as well as taking advantage of multiple-CPU's 
        on SMP systems.
 
-       * ctsim: Added PPM/PGM and PNG file import to imagefile.
-
-       * ctsim: Added import of DICOM grayscale files.
-
-       * ctsim: Added imagefile export to DICOM files.
-
-       * ctsim: Added clipboard cut/copy/paste for image files.
-
+       * ctsim: Added plot t-theta sampling to projection file menu.
+       
        * ctsim: Added Reconstruction with Rebinning for faster
        divergent beam reconstructions.
        
        * ctsim: Added Reconstruction with Rebinning for faster
        divergent beam reconstructions.
        
-       * ctsim: Added plot t-theta sampling to projection file menu.
+       * ctsim: Added import and export of DICOM image files.
+
+       * ctsim: Added PPM, PGM, and PNG file import to imagefile.
+
+       * ctsim: Added FFT/IFFT of columns of image files.
        
        
+       * ctsim: Added clipboard cut/copy/paste for image files.
+
        * ctsim: Added region of interest to reconstructions.
 
        * ctsim: Added region of interest to reconstructions.
 
+       * ctsim: Added Convert Rectangular Image to Projection files
+       
        * ctsim: Added "Verbose Logging", "Startup Tips", and
        "Background processes" options  to Preferences dialog.
 
        * ctsim: Added "Verbose Logging", "Startup Tips", and
        "Background processes" options  to Preferences dialog.
 
+       * ctsim: Added plotting of projection file histograms.
+       
        * plotfile: Added scattergram plot functions
 
        * ctsim: Added accelerator key for File-Properties
 
        * plotfile: Added scattergram plot functions
 
        * ctsim: Added accelerator key for File-Properties
 
+       * ctsim: Improved wireframe 3-d display to remove hidden
+       surfaces.
+       
        * sgp.cpp/ezplot.cpp: Improved plotting with markers.
        
        * views.cpp: Added out of memory checks to display for huge
        * sgp.cpp/ezplot.cpp: Improved plotting with markers.
        
        * views.cpp: Added out of memory checks to display for huge
        * sgp.cpp: Fixed bug in drawCircle
 
        * filter.cpp: Fixed Hanning parameter to be 0.5 rather than 0.54
        * sgp.cpp: Fixed bug in drawCircle
 
        * filter.cpp: Fixed Hanning parameter to be 0.5 rather than 0.54
+
+       * imagefile.cpp: Fixed scaling factor in fftRows
+
+       * backprojectors.cpp: Added setting of axis extent and increment
+       to reconstructions.
        
 3.0.3 - Released 2/20/01
 
        
 3.0.3 - Released 2/20/01
 
diff --git a/NEWS b/NEWS
index a4a4c475181f4f79c3c40d6d181c8e1479b9b36e..aa4b9f7d6f18071749b55e6481a71e19a9681366 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -19,10 +19,11 @@ Version 3.5 New Features
 * Scattergram of T-Theta sampling. Useful for understand divergent beam
   scanning.
 
 * Scattergram of T-Theta sampling. Useful for understand divergent beam
   scanning.
 
-* Added startup-tips to help new users learn features.
+* Startup-tips to help new users learn features.
 
 
-* Added ability to place detector at any arbitray position
+* Ability to place detector at any arbitray position
 
 
+* Histogram plotting of projection files
 
 
 Version 3.0 New Features
 
 
 Version 3.0 New Features
@@ -46,7 +47,7 @@ Version 3.0 New Features
 
 * Plotting of row and column data of single and comparison images
 
 
 * Plotting of row and column data of single and comparison images
 
-* Histogram Plotting
+* Histogram Plotting of Image files.
 
 * Conversion of projections to polar images
 
 
 * Conversion of projections to polar images
 
index 504aba11397ed8a4c865b222a068b63438decd24..b9ac22fb3687e6b67c37e0655045d025454bdec6 100644 (file)
@@ -104,16 +104,9 @@ running on a SMP computer, and \ctsim\ is directed to perform
 reconstruction, rasterization, or projections, \ctsim\ will spawn
 a \emph{Background Supervisor} thread. This supervisor thread then
 creates a \emph{Supervisor Event Handler} (supervisor).  The
 reconstruction, rasterization, or projections, \ctsim\ will spawn
 a \emph{Background Supervisor} thread. This supervisor thread then
 creates a \emph{Supervisor Event Handler} (supervisor).  The
-supervisor communicates with the rest of \ctsim\ by using message
-passing to avoid issues with re-entrant code.
-
-Though the various threads do not directly call each other, it is
-prudent to lock the class data structures with \emph{Critical
-Sections}. Critical sections lock areas of code and prevent more
-than one thread to access a section of code at a time. This is
-used when maintaining the tables of worker threads in the
-supervisor and also when maintaining the tables of supervisors in
-the background manager.
+supervisor communicates with the rest of graphical user interface
+of  \ctsim\ by using message passing to avoid issues with
+re-entrant code.
 
 The supervisor registers itself via message passing with the
 \emph{Background Manager} which will display the execution
 
 The supervisor registers itself via message passing with the
 \emph{Background Manager} which will display the execution
@@ -125,17 +118,22 @@ supervisor directing the supervisor to cancel the calculation.
 After registering with \ctsim\ components, the supervisor creates
 \emph{Worker Threads}. These worker threads are the processes that
 actually perform the calculations. By default, \ctsim\ will create
 After registering with \ctsim\ components, the supervisor creates
 \emph{Worker Threads}. These worker threads are the processes that
 actually perform the calculations. By default, \ctsim\ will create
-one worker thread for every CPU in the system. The workers
-communicate with the supervisor via message passing. As the
-workers complete unit blocks, they send progress messages to the
-supervisor. The supervisor then sends progress messages to
-background manager which displays a gauge of the progress.
-
-After the workers have completed their tasks, they send a status
-message to the supervisor. When all the workers have finished, the
-supervisor will kill the worker threads. The supervisor then
-collates the work units from the workers and creates a new \ctsim\
-window to display the finished work.
+one worker thread for every CPU in the system. As the workers
+complete unit blocks, they notify the supervisor. The supervisor
+then sends progress messages to background manager which displays
+a gauge of the progress.
+
+As the worker threads directly call the supervisor, it is crucial
+to lock the class data structures with \emph{Critical Sections}.
+Critical sections lock areas of code and prevent more than one
+thread to access a section of code at a time. This is used when
+maintaining the tables of worker threads in the supervisor.
+
+After the workers have completed their tasks, they notify the
+supervisor. When all the workers have finished, the supervisor
+kills the worker threads. The supervisor then collates the work
+units from the workers and sends a message to \ctsim\ to create a
+new window to display the finished work.
 
 The supervisor then deregisters itself via messages with the
 background manager and the document. The background manager
 
 The supervisor then deregisters itself via messages with the
 background manager and the document. The background manager
@@ -155,8 +153,9 @@ This structure may seem more complex than is necessary, but it has
 several advantages:
 
 \begin{itemize}
 several advantages:
 
 \begin{itemize}
-\item Since the various threads do not call objects in other threads, problems
-with re-entrant code are eliminated.
+\item Since the background threads do not directly call objects in the graphical
+user interface thread, problems with re-entrant code in the
+graphical interface are eliminated.
 \item A supervisor can parallel process with any number of worker threads
 to take advantage of potentially large numbers of CPU's in SMP
 computers.
 \item A supervisor can parallel process with any number of worker threads
 to take advantage of potentially large numbers of CPU's in SMP
 computers.
@@ -175,14 +174,14 @@ include:
 results. When the worker threads finish, the supervisor allocates
 memory for the final result and collates the results for the
 workers. This collation results in a doubling of the memory
 results. When the worker threads finish, the supervisor allocates
 memory for the final result and collates the results for the
 workers. This collation results in a doubling of the memory
-requirements. Of course, after collation the supervisor
-deallocates the memory used by the workers.
+requirements. Of course, after collation the supervisor releases
+the memory used by the workers.
 \item Slower execution on single CPU systems. \\
 \item Slower execution on single CPU systems. \\
-The message passing between threads and collation
-of results for worker threads adds overhead compared to simply
-calculating the result directly in the foreground. On single CPU
-systems this results in slower processing compared to foreground
-processing. On dual-CPU and greater SMP systems, though, the
-advantage of using multiple CPU's in parallel exceeds the overhead
-of background processing.
+Creating multiple threads, sending progress messages to the
+background manager, and collation of results for worker threads
+adds overhead compared to simply calculating the result directly
+in the foreground. On single CPU systems this results in slower
+processing compared to foreground processing. On dual-CPU and
+greater SMP systems, though, the advantage of using multiple CPU's
+in parallel exceeds the overhead of background processing.
 \end{itemize}
 \end{itemize}
index e7dbe76c003f7ed0253aab0418e3bb021f45f511..33a26c60196f83bc02667a3578b0e09f8d160aba 100644 (file)
@@ -5,19 +5,19 @@
 1
 ctsim.tex
 21
 1
 ctsim.tex
 21
-4
-3
+0
+0
 
 
 ctsim-algorithms.tex
 TeX
 
 
 ctsim-algorithms.tex
 TeX
-4091 0 65 52 0 43 44 44 960 631
+268439547 0 179 17 187 1 44 44 960 631
 ctsim-concepts.tex
 TeX
 ctsim-concepts.tex
 TeX
-12282 0 302 40 280 44 110 110 1187 697
+268447738 0 302 40 280 44 110 110 1187 697
 ctsim.tex
 TeX
 ctsim.tex
 TeX
-134230010 0 50 12 33 1 22 22 1099 609
+402665466 0 50 12 33 1 22 22 1099 609
 ctsim-install.tex
 TeX
 268447738 0 70 62 71 1 110 110 1187 697
 ctsim-install.tex
 TeX
 268447738 0 70 62 71 1 110 110 1187 697
index c449b80e3385802de086a25b3e528110ab473f3e..5fce2f685fd3bb4f154b9d7b88a8610285506011 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: fourier.h,v 1.5 2001/01/28 19:20:15 kevin Exp $
+**  $Id: fourier.h,v 1.6 2001/03/18 18:08:25 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
 **
 **  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
@@ -40,6 +40,6 @@ public:
     static void shuffleFourierToNaturalOrder (float* pdVector, const int n);
     static void shuffleFourierToNaturalOrder (double* pdVector, const int n);
     static void shuffleFourierToNaturalOrder (std::complex<double>* pdVector, const int n);
     static void shuffleFourierToNaturalOrder (float* pdVector, const int n);
     static void shuffleFourierToNaturalOrder (double* pdVector, const int n);
     static void shuffleFourierToNaturalOrder (std::complex<double>* pdVector, const int n);
+};
 
 
-}; // namespace Fourier
 
 
index 5b440a03c0bde6a69de1076b723e390ba052ef21..140955c2bc5b32e4898470b63edaed6d4d3a72ff 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: imagefile.h,v 1.33 2001/03/02 02:08:14 kevin Exp $
+**  $Id: imagefile.h,v 1.34 2001/03/18 18:08:25 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
 **
 **  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
@@ -136,6 +136,7 @@ public:
 
   static const int EXPORT_FORMAT_INVALID;
   static const int IMPORT_FORMAT_INVALID;
 
   static const int EXPORT_FORMAT_INVALID;
   static const int IMPORT_FORMAT_INVALID;
+  static const int EXPORT_FORMAT_TEXT;
   static const int EXPORT_FORMAT_PGM;
   static const int EXPORT_FORMAT_PGMASCII;
   static const int IMPORT_FORMAT_PPM;
   static const int EXPORT_FORMAT_PGM;
   static const int EXPORT_FORMAT_PGMASCII;
   static const int IMPORT_FORMAT_PPM;
@@ -221,16 +222,17 @@ public:
 
   bool importImage (const char* const pszFormat, const char* const pszFilename);
 
 
   bool importImage (const char* const pszFormat, const char* const pszFilename);
 
-#if HAVE_PNG
+#ifdef HAVE_PNG
   bool writeImagePNG (const char* const outfile, int bitdepth, int nxcell, int nycell, double densmin, double densmax);
   bool readImagePNG (const char* const pszFile);
 #endif
   bool writeImagePNG (const char* const outfile, int bitdepth, int nxcell, int nycell, double densmin, double densmax);
   bool readImagePNG (const char* const pszFile);
 #endif
-#if HAVE_GD
+#ifdef HAVE_GD
   bool writeImageGIF (const char* const outfile, int nxcell, int nycell, double densmin, double densmax);
 #endif
   bool writeImagePGM (const char* const outfile, int nxcell, int nycell, double densmin, double densmax);
   bool writeImagePGMASCII (const char* const outfile, int nxcell, int nycell, double densmin, double densmax);
   bool readImagePPM (const char* const pszFile);
   bool writeImageGIF (const char* const outfile, int nxcell, int nycell, double densmin, double densmax);
 #endif
   bool writeImagePGM (const char* const outfile, int nxcell, int nycell, double densmin, double densmax);
   bool writeImagePGMASCII (const char* const outfile, int nxcell, int nycell, double densmin, double densmax);
   bool readImagePPM (const char* const pszFile);
+  bool writeImageText (const char* const outfile);
 
   static double redGrayscaleFactor() {return s_dRedGrayscaleFactor;}
   static double greenGrayscaleFactor() {return s_dGreenGrayscaleFactor;}
 
   static double redGrayscaleFactor() {return s_dRedGrayscaleFactor;}
   static double greenGrayscaleFactor() {return s_dGreenGrayscaleFactor;}
index 06ad159b9d9577d73f099aee7a9586a3e19b6052..825b1e33195c59ab837694879dff4e4c8f6ade4a 100644 (file)
@@ -8,7 +8,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: backprojectors.cpp,v 1.31 2001/03/11 15:27:30 kevin Exp $
+**  $Id: backprojectors.cpp,v 1.32 2001/03/18 18:08:25 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
 **
 **  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
@@ -313,6 +313,9 @@ Backproject::Backproject (const Projections& proj, ImageFile& im, int interpType
   xInc = (xMax - xMin) / nx;   // size of cells
   yInc = (yMax - yMin) / ny;
   
   xInc = (xMax - xMin) / nx;   // size of cells
   yInc = (yMax - yMin) / ny;
   
+  im.setAxisIncrement (xInc, yInc);
+  im.setAxisExtent (xMin, xMax, yMin, yMax);
+
   m_dFocalLength = proj.focalLength();
   m_dSourceDetectorLength = proj.sourceDetectorLength();
 }
   m_dFocalLength = proj.focalLength();
   m_dSourceDetectorLength = proj.sourceDetectorLength();
 }
index 06145a3c628495a3736ea7c3bda724beedff2020..f7357cdf5363272c496e0634e16b2794b9799deb 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: fourier.cpp,v 1.4 2001/01/28 19:10:18 kevin Exp $
+**  $Id: fourier.cpp,v 1.5 2001/03/18 18:08:25 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
 **
 **  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
@@ -112,7 +112,7 @@ Fourier::shuffleNaturalToFourierOrder (double* pdVector, const int n)
 {
   double* pdTemp = new double [n];
   int i;
 {
   double* pdTemp = new double [n];
   int i;
-  if (n % 2) { // Odd
+  if (isOdd(n)) { // Odd
     int iHalfN = (n - 1) / 2;
 
     pdTemp[0] = pdVector[iHalfN];
     int iHalfN = (n - 1) / 2;
 
     pdTemp[0] = pdVector[iHalfN];
@@ -139,7 +139,7 @@ Fourier::shuffleNaturalToFourierOrder (std::complex<double>* pdVector, const int
 {
   std::complex<double>* pdTemp = new std::complex<double> [n];
   int i;
 {
   std::complex<double>* pdTemp = new std::complex<double> [n];
   int i;
-  if (n % 2) { // Odd
+  if (isOdd(n)) { // Odd
     int iHalfN = (n - 1) / 2;
 
     pdTemp[0] = pdVector[iHalfN];
     int iHalfN = (n - 1) / 2;
 
     pdTemp[0] = pdVector[iHalfN];
@@ -167,7 +167,7 @@ Fourier::shuffleNaturalToFourierOrder (float* pdVector, const int n)
 {
   float* pdTemp = new float [n];
   int i;
 {
   float* pdTemp = new float [n];
   int i;
-  if (n % 2) { // Odd
+  if (isOdd (n)) { // Odd
     int iHalfN = (n - 1) / 2;
 
     pdTemp[0] = pdVector[iHalfN];
     int iHalfN = (n - 1) / 2;
 
     pdTemp[0] = pdVector[iHalfN];
@@ -196,7 +196,7 @@ Fourier::shuffleFourierToNaturalOrder (double* pdVector, const int n)
 {
   double* pdTemp = new double [n];
   int i;
 {
   double* pdTemp = new double [n];
   int i;
-  if (n % 2) { // Odd
+  if (isOdd(n)) { // Odd
     int iHalfN = (n - 1) / 2;
     
     pdTemp[iHalfN] = pdVector[0];
     int iHalfN = (n - 1) / 2;
     
     pdTemp[iHalfN] = pdVector[0];
@@ -224,7 +224,7 @@ Fourier::shuffleFourierToNaturalOrder (std::complex<double>* pdVector, const int
 {
   std::complex<double>* pdTemp = new std::complex<double> [n];
   int i;
 {
   std::complex<double>* pdTemp = new std::complex<double> [n];
   int i;
-  if (n % 2) { // Odd
+  if (isOdd(n)) { // Odd
     int iHalfN = (n - 1) / 2;
     
     pdTemp[iHalfN] = pdVector[0];
     int iHalfN = (n - 1) / 2;
     
     pdTemp[iHalfN] = pdVector[0];
@@ -254,7 +254,7 @@ Fourier::shuffleFourierToNaturalOrder (float* pVector, const int n)
 {
   float* pTemp = new float [n];
   int i;
 {
   float* pTemp = new float [n];
   int i;
-  if (n % 2) { // Odd
+  if (isOdd (n)) { // Odd
     int iHalfN = (n - 1) / 2;
     
     pTemp[iHalfN] = pVector[0];
     int iHalfN = (n - 1) / 2;
     
     pTemp[iHalfN] = pVector[0];
index 7c9e91e267b42159474d8b3bbd67abceb330df9c..1c8a063db7c05af76bde6ff2db25df9457bb557c 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: imagefile.cpp,v 1.40 2001/03/07 16:34:47 kevin Exp $
+**  $Id: imagefile.cpp,v 1.41 2001/03/18 18:08:25 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
 **
 **  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
@@ -36,18 +36,20 @@ const double ImageFile::s_dBlueGrayscaleFactor = 0.114;
 
 
 const int ImageFile::EXPORT_FORMAT_INVALID = -1;
 
 
 const int ImageFile::EXPORT_FORMAT_INVALID = -1;
-const int ImageFile::EXPORT_FORMAT_PGM = 0;
-const int ImageFile::EXPORT_FORMAT_PGMASCII = 1;
+const int ImageFile::EXPORT_FORMAT_TEXT = 0;
+const int ImageFile::EXPORT_FORMAT_PGM = 1;
+const int ImageFile::EXPORT_FORMAT_PGMASCII = 2;
 #ifdef HAVE_PNG
 #ifdef HAVE_PNG
-const int ImageFile::EXPORT_FORMAT_PNG = 2;
-const int ImageFile::EXPORT_FORMAT_PNG16 = 3;
+const int ImageFile::EXPORT_FORMAT_PNG = 3;
+const int ImageFile::EXPORT_FORMAT_PNG16 = 4;
 #endif
 #ifdef HAVE_CTN_DICOM
 #endif
 #ifdef HAVE_CTN_DICOM
-const int ImageFile::EXPORT_FORMAT_DICOM = 4;
+const int ImageFile::EXPORT_FORMAT_DICOM = 5;
 #endif
 
 const char* ImageFile::s_aszExportFormatName[] = 
 {
 #endif
 
 const char* ImageFile::s_aszExportFormatName[] = 
 {
+  {"text"},
   {"pgm"},
   {"pgmascii"},
 #ifdef HAVE_PNG
   {"pgm"},
   {"pgmascii"},
 #ifdef HAVE_PNG
@@ -61,6 +63,7 @@ const char* ImageFile::s_aszExportFormatName[] =
 
 const char* ImageFile::s_aszExportFormatTitle[] = 
 {
 
 const char* ImageFile::s_aszExportFormatTitle[] = 
 {
+  {"Text"},
   {"PGM"},
   {"PGM ASCII"},
   {"PNG"},
   {"PGM"},
   {"PGM ASCII"},
   {"PNG"},
@@ -926,8 +929,8 @@ ImageFile::fftRows (ImageFile& result) const
     
     Fourier::shuffleFourierToNaturalOrder (pcRow, m_nx);
     for (ix = 0; ix < m_nx; ix++) {
     
     Fourier::shuffleFourierToNaturalOrder (pcRow, m_nx);
     for (ix = 0; ix < m_nx; ix++) {
-      vReal[ix][iy] = pcRow[ix].real();
-      vImag[ix][iy] = pcRow[ix].imag();
+      vReal[ix][iy] = pcRow[ix].real() / m_nx;
+      vImag[ix][iy] = pcRow[ix].imag() / m_nx;
     }
   }
   delete [] pcRow;
     }
   }
   delete [] pcRow;
@@ -994,13 +997,105 @@ ImageFile::ifftRows (ImageFile& result) const
 bool
 ImageFile::fftCols (ImageFile& result) const
 {
 bool
 ImageFile::fftCols (ImageFile& result) const
 {
-  return false;
+  if (m_nx != result.nx() || m_ny != result.ny()) {
+    sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::fftRows]");
+    return false;
+  }
+  
+  if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
+    if (! result.convertRealToComplex ())
+      return false;
+  }
+  
+  fftw_complex* in = new fftw_complex [m_ny];
+  
+  ImageFileArrayConst vReal = getArray();
+  ImageFileArrayConst vImag = getImaginaryArray();
+  
+  fftw_plan plan = fftw_create_plan (m_ny, FFTW_FORWARD, FFTW_IN_PLACE);
+  std::complex<double>* pcCol = new std::complex<double> [m_ny];
+  
+  unsigned int ix, iy;
+  unsigned int iArray = 0;
+  for (ix = 0; ix < m_nx; ix++) {
+    for (iy = 0; iy < m_ny; iy++) {
+      in[iy].re = vReal[ix][iy];
+      if (isComplex())
+        in[iy].im = vImag[ix][iy];
+      else
+        in[iy].im = 0;
+    }
+    
+    fftw_one (plan, in, NULL);
+    
+    for (iy = 0; iy < m_ny; iy++)
+      pcCol[iy] = std::complex<double>(in[iy].re, in[iy].im);
+    
+    Fourier::shuffleFourierToNaturalOrder (pcCol, m_ny);
+    for (iy = 0; iy < m_ny; iy++) {
+      vReal[ix][iy] = pcCol[iy].real() / m_ny;
+      vImag[ix][iy] = pcCol[iy].imag() / m_ny;
+    }
+  }
+  delete [] pcCol;
+  
+  fftw_destroy_plan (plan);
+  delete in;
+  
+  return true;
 }
 
 bool
 ImageFile::ifftCols (ImageFile& result) const
 {
 }
 
 bool
 ImageFile::ifftCols (ImageFile& result) const
 {
-  return false;
+  if (m_nx != result.nx() || m_ny != result.ny()) {
+    sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::fftRows]");
+    return false;
+  }
+  
+  if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
+    if (! result.convertRealToComplex ())
+      return false;
+  }
+  
+  fftw_complex* in = new fftw_complex [m_ny];
+  
+  ImageFileArrayConst vReal = getArray();
+  ImageFileArrayConst vImag = getImaginaryArray();
+  
+  fftw_plan plan = fftw_create_plan (m_ny, FFTW_BACKWARD, FFTW_IN_PLACE);
+  std::complex<double>* pcCol = new std::complex<double> [m_ny];
+  
+  unsigned int ix, iy;
+  unsigned int iArray = 0;
+  for (ix = 0; ix < m_nx; ix++) {
+    for (iy = 0; iy < m_ny; iy++) {
+      double dImag = 0;
+      if (isComplex())
+        dImag = vImag[ix][iy];
+      pcCol[iy] = std::complex<double> (vReal[ix][iy], dImag);
+    }
+    
+    Fourier::shuffleNaturalToFourierOrder (pcCol, m_ny);
+    
+    for (iy = 0; iy < m_ny; iy++) {
+      in[iy].re = pcCol[iy].real();
+      in[iy].im = pcCol[iy].imag();
+    }
+    
+    fftw_one (plan, in, NULL);
+    
+    for (iy = 0; iy < m_ny; iy++) {
+      vReal[ix][iy] = in[iy].re;
+      vImag[ix][iy] = in[iy].im;
+    }
+  }
+  delete [] pcCol;
+  
+  fftw_destroy_plan (plan);
+  delete in;
+  
+  return true;
 }
 
 #endif // HAVE_FFTW
 }
 
 #endif // HAVE_FFTW
@@ -1564,10 +1659,14 @@ ImageFile::exportImage (const char* const pszFormat, const char* const pszFilena
     return writeImagePGM (pszFilename, nxcell, nycell, densmin, densmax);
   else if (iFormatID == EXPORT_FORMAT_PGMASCII)
     return writeImagePGMASCII (pszFilename, nxcell, nycell, densmin, densmax);
     return writeImagePGM (pszFilename, nxcell, nycell, densmin, densmax);
   else if (iFormatID == EXPORT_FORMAT_PGMASCII)
     return writeImagePGMASCII (pszFilename, nxcell, nycell, densmin, densmax);
+  else if (iFormatID == EXPORT_FORMAT_TEXT)
+    return writeImageText (pszFilename);
+#ifdef HAVE_PNG
   else if (iFormatID == EXPORT_FORMAT_PNG)
     return writeImagePNG (pszFilename, 8, nxcell, nycell, densmin, densmax);
   else if (iFormatID == EXPORT_FORMAT_PNG16)
     return writeImagePNG (pszFilename, 16, nxcell, nycell, densmin, densmax);
   else if (iFormatID == EXPORT_FORMAT_PNG)
     return writeImagePNG (pszFilename, 8, nxcell, nycell, densmin, densmax);
   else if (iFormatID == EXPORT_FORMAT_PNG16)
     return writeImagePNG (pszFilename, 16, nxcell, nycell, densmin, densmax);
+#endif
 #ifdef HAVE_CTN_DICOM
   else if (iFormatID == EXPORT_FORMAT_DICOM) {
     DicomExporter dicomExport (this);
 #ifdef HAVE_CTN_DICOM
   else if (iFormatID == EXPORT_FORMAT_DICOM) {
     DicomExporter dicomExport (this);
@@ -1660,6 +1759,36 @@ ImageFile::writeImagePGMASCII (const char* const outfile, int nxcell, int nycell
   return true;
 }
 
   return true;
 }
 
+bool
+ImageFile::writeImageText (const char* const outfile)
+{
+  FILE *fp;
+  int nx = m_nx;
+  int ny = m_ny;
+  ImageFileArray v = getArray();
+  ImageFileArray vImag = getImaginaryArray();
+
+  if ((fp = fopen (outfile, "w")) == NULL)
+    return false;
+  
+  for (int irow = ny - 1; irow >= 0; irow--) {
+    for (int icol = 0; icol < nx; icol++) {
+      if (isComplex()) {
+        if (vImag[icol][irow] >= 0)
+          fprintf (fp, "%.9g+%.9gi ", v[icol][irow], vImag[icol][irow]);
+        else
+          fprintf (fp, "%.9g-%.9gi ", v[icol][irow], -vImag[icol][irow]);
+      } else
+        fprintf (fp, "%12.8g ", v[icol][irow]);
+    }
+    fprintf(fp, "\n");
+  }
+  
+  fclose(fp);
+  
+  return true;
+}
+
 
 #ifdef HAVE_PNG
 bool
 
 #ifdef HAVE_PNG
 bool
index 711307f1d88be1aa5887b09c490be997797c1a96..2d6600d37e6b60767bd416e05c216a494416ec24 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: procsignal.cpp,v 1.28 2001/03/13 14:53:44 kevin Exp $
+**  $Id: procsignal.cpp,v 1.29 2001/03/18 18:08:25 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
 **
 **  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
@@ -261,7 +261,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw
       m_nFilterPoints = addZeropadFactor (m_nSignalPoints, m_iZeropad);
       m_nOutputPoints = m_nFilterPoints * m_iPreinterpolationFactor;
       
       m_nFilterPoints = addZeropadFactor (m_nSignalPoints, m_iZeropad);
       m_nOutputPoints = m_nFilterPoints * m_iPreinterpolationFactor;
       
-      if (m_nFilterPoints % 2) { // Odd
+      if (isOdd (m_nFilterPoints)) { // Odd
         m_dFilterMin = -1. / (2 * m_dSignalInc);
         m_dFilterMax = 1. / (2 * m_dSignalInc);
         m_dFilterInc = (m_dFilterMax - m_dFilterMin) / (m_nFilterPoints - 1);
         m_dFilterMin = -1. / (2 * m_dSignalInc);
         m_dFilterMax = 1. / (2 * m_dSignalInc);
         m_dFilterInc = (m_dFilterMax - m_dFilterMin) / (m_nFilterPoints - 1);
index 95cbc89a34c211c50e4abacf2f0a8bfafa0e56cb..1aee958e6fdcd42c4addfee161471ccb38780a74 100644 (file)
@@ -8,7 +8,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: projections.cpp,v 1.66 2001/03/13 14:53:44 kevin Exp $
+**  $Id: projections.cpp,v 1.67 2001/03/18 18:08:25 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
 **
 **  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
@@ -810,7 +810,7 @@ Projections::calcArrayPolarCoordinates (unsigned int nx, unsigned int ny, double
 
   // +1 is correct for frequency data, ndet-1 is correct for projections
   int iDetCenter = (iNumDetWithZeros - 1) / 2; // index refering to L=0 projection 
 
   // +1 is correct for frequency data, ndet-1 is correct for projections
   int iDetCenter = (iNumDetWithZeros - 1) / 2; // index refering to L=0 projection 
-  if (iNumDetWithZeros % 2 == 0)
+  if (isEven (iNumDetWithZeros))
     iDetCenter = (iNumDetWithZeros + 1) / 2;   
 
   // Calculates polar coordinates (view#, det#) for each point on phantom grid
     iDetCenter = (iNumDetWithZeros + 1) / 2;   
 
   // Calculates polar coordinates (view#, det#) for each point on phantom grid
@@ -1002,7 +1002,7 @@ Projections::interpolateToParallel () const
 #endif
   pProjNew->m_detStart = -m_dViewDiameter / 2;
   pProjNew->m_detInc = m_dViewDiameter / nDet;
 #endif
   pProjNew->m_detStart = -m_dViewDiameter / 2;
   pProjNew->m_detInc = m_dViewDiameter / nDet;
-  if (nDet % 2 == 0) // even
+  if (isEven (nDet)) // even
     pProjNew->m_detInc = m_dViewDiameter / (nDet - 1);
 
   ParallelRaysums parallel (this, ParallelRaysums::THETA_RANGE_NORMALIZE_TO_TWOPI);
     pProjNew->m_detInc = m_dViewDiameter / (nDet - 1);
 
   ParallelRaysums parallel (this, ParallelRaysums::THETA_RANGE_NORMALIZE_TO_TWOPI);
index 34899f5af643dbf94aff2a9795e1c5996349d412..88f99f00a87eaad8b19fafbaeccfc9c9b76e7d97 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: scanner.cpp,v 1.36 2001/03/11 15:27:30 kevin Exp $
+**  $Id: scanner.cpp,v 1.37 2001/03/18 18:08:25 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
 **
 **  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
@@ -130,7 +130,7 @@ Scanner::Scanner (const Phantom& phm, const char* const geometryName,
     double dDetectorArrayEndOffset = 0;
     // For even number of detectors, make detInc slightly larger so that center lies
     // at nDet/2. Also, extend detector array by one detInc so that all of the phantom is scanned
     double dDetectorArrayEndOffset = 0;
     // For even number of detectors, make detInc slightly larger so that center lies
     // at nDet/2. Also, extend detector array by one detInc so that all of the phantom is scanned
-    if (m_nDet % 2 == 0) { // Adjust for Even number of detectors
+    if (isEven (m_nDet)) { // Adjust for Even number of detectors
       m_detInc = m_detLen / (m_nDet - 1); // center detector = (nDet/2)
       dDetectorArrayEndOffset = m_detInc;
     }
       m_detInc = m_detLen / (m_nDet - 1); // center detector = (nDet/2)
       dDetectorArrayEndOffset = m_detInc;
     }
@@ -160,7 +160,7 @@ Scanner::Scanner (const Phantom& phm, const char* const geometryName,
     m_detStart = -dHalfDetLen;
     m_detInc  = m_detLen / m_nDet;
     double dDetectorArrayEndOffset = 0;
     m_detStart = -dHalfDetLen;
     m_detInc  = m_detLen / m_nDet;
     double dDetectorArrayEndOffset = 0;
-    if (m_nDet % 2 == 0) { // Adjust for Even number of detectors
+    if (isEven (m_nDet)) { // Adjust for Even number of detectors
       m_detInc = m_detLen / (m_nDet - 1); // center detector = (nDet/2)
       dDetectorArrayEndOffset = m_detInc;
       m_detLen += dDetectorArrayEndOffset;
       m_detInc = m_detLen / (m_nDet - 1); // center detector = (nDet/2)
       dDetectorArrayEndOffset = m_detInc;
       m_detLen += dDetectorArrayEndOffset;
@@ -189,7 +189,7 @@ Scanner::Scanner (const Phantom& phm, const char* const geometryName,
     m_detStart = -dAngle;
     m_detInc = m_detLen / m_nDet;
     double dDetectorArrayEndOffset = 0;
     m_detStart = -dAngle;
     m_detInc = m_detLen / m_nDet;
     double dDetectorArrayEndOffset = 0;
-    if (m_nDet % 2 == 0) { // Adjust for Even number of detectors
+    if (isEven (m_nDet)) { // Adjust for Even number of detectors
       m_detInc = m_detLen / (m_nDet - 1); // center detector = (nDet/2)
       dDetectorArrayEndOffset = m_detInc;
     }
       m_detInc = m_detLen / (m_nDet - 1); // center detector = (nDet/2)
       dDetectorArrayEndOffset = m_detInc;
     }
@@ -469,7 +469,7 @@ Scanner::projectSingleView (const Phantom& phm, DetectorArray& detArray, const d
   
   if (phm.getComposition() == P_UNIT_PULSE) {  // put unit pulse in center of view
     for (int d = 0; d < detArray.nDet(); d++)
   
   if (phm.getComposition() == P_UNIT_PULSE) {  // put unit pulse in center of view
     for (int d = 0; d < detArray.nDet(); d++)
-      if (detArray.nDet() / 2 == d && (d % 2) == 1)
+      if (detArray.nDet() / 2 == d && isOdd (d))
         detval[d] = 1;
       else
         detval[d] = 0;
         detval[d] = 1;
       else
         detval[d] = 0;
index efee3ceddc51b806581069e2dfa650e477f30183..4c73f269f37b705d3b091356aca78a824ee39443 100644 (file)
@@ -6,13 +6,13 @@
 --------------------Configuration: libctsim - Win32 Debug--------------------
 </h3>
 <h3>Command Lines</h3>
 --------------------Configuration: libctsim - Win32 Debug--------------------
 </h3>
 <h3>Command Lines</h3>
-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP282.tmp" with contents
+Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E5.tmp" with contents
 [
 /nologo /G6 /MTd /W3 /Gm /Gi /GR /GX /Zi /Od /Gy /I "..\..\..\wx2.2.5\src\png" /I "..\..\..\wx2.2.5\src\zlib" /I "..\..\INCLUDE" /I "..\..\getopt" /I "..\..\..\fftw-2.1.3\fftw" /I "..\..\..\fftw-2.1.3\rfftw" /I "..\..\..\wx2.2.5\include" /I "\dicom\ctn\include" /D "_DEBUG" /D "HAVE_WXWIN" /D "HAVE_STRING_H" /D "HAVE_GETOPT_H" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MSVC" /D "HAVE_FFTW" /D "HAVE_PNG" /D "HAVE_SGP" /D "HAVE_WXWINDOWS" /D "__WXMSW__" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "HAVE_CTN_DICOM" /D VERSION=\"3.1.0\" /FR"Debug/" /Fp"Debug/libctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c 
 [
 /nologo /G6 /MTd /W3 /Gm /Gi /GR /GX /Zi /Od /Gy /I "..\..\..\wx2.2.5\src\png" /I "..\..\..\wx2.2.5\src\zlib" /I "..\..\INCLUDE" /I "..\..\getopt" /I "..\..\..\fftw-2.1.3\fftw" /I "..\..\..\fftw-2.1.3\rfftw" /I "..\..\..\wx2.2.5\include" /I "\dicom\ctn\include" /D "_DEBUG" /D "HAVE_WXWIN" /D "HAVE_STRING_H" /D "HAVE_GETOPT_H" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MSVC" /D "HAVE_FFTW" /D "HAVE_PNG" /D "HAVE_SGP" /D "HAVE_WXWINDOWS" /D "__WXMSW__" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "HAVE_CTN_DICOM" /D VERSION=\"3.1.0\" /FR"Debug/" /Fp"Debug/libctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c 
-"C:\ctsim\libctsim\projections.cpp"
+"C:\ctsim\libctsim\imagefile.cpp"
 ]
 ]
-Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP282.tmp" 
-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP283.tmp" with contents
+Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E5.tmp" 
+Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E6.tmp" with contents
 [
 /nologo /out:"Debug\libctsim.lib" 
 .\Debug\array2dfile.obj
 [
 /nologo /out:"Debug\libctsim.lib" 
 .\Debug\array2dfile.obj
@@ -48,16 +48,16 @@ Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP283.tmp" with conten
 .\Debug\transformmatrix.obj
 .\Debug\xform.obj
 ]
 .\Debug\transformmatrix.obj
 .\Debug\xform.obj
 ]
-Creating command line "link.exe -lib @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP283.tmp"
+Creating command line "link.exe -lib @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E6.tmp"
 <h3>Output Window</h3>
 Compiling...
 <h3>Output Window</h3>
 Compiling...
-projections.cpp
+imagefile.cpp
 Creating library...
 <h3>
 --------------------Configuration: ctsim - Win32 Debug--------------------
 </h3>
 <h3>Command Lines</h3>
 Creating library...
 <h3>
 --------------------Configuration: ctsim - Win32 Debug--------------------
 </h3>
 <h3>Command Lines</h3>
-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP284.tmp" with contents
+Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E7.tmp" with contents
 [
 winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\..\..\fftw-2.1.3\Win32\FFTW2st\Debug\FFTW2st.lib ..\..\..\fftw-2.1.3\Win32\RFFTW2st\Debug\RFFTW2st.lib wxd.lib xpmd.lib tiffd.lib zlibd.lib pngd.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib htmlhelp.lib ctn_lib.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/ctsim.pdb" /debug /machine:I386 /out:"Debug/ctsim.exe" /pdbtype:sept /libpath:"\wx2.2.5\lib" /libpath:"\dicom\ctn\winctn\ctn_lib\Debug" 
 .\Debug\backgroundmgr.obj
 [
 winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\..\..\fftw-2.1.3\Win32\FFTW2st\Debug\FFTW2st.lib ..\..\..\fftw-2.1.3\Win32\RFFTW2st\Debug\RFFTW2st.lib wxd.lib xpmd.lib tiffd.lib zlibd.lib pngd.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib htmlhelp.lib ctn_lib.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/ctsim.pdb" /debug /machine:I386 /out:"Debug/ctsim.exe" /pdbtype:sept /libpath:"\wx2.2.5\lib" /libpath:"\dicom\ctn\winctn\ctn_lib\Debug" 
 .\Debug\backgroundmgr.obj
@@ -84,7 +84,7 @@ winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\..
 \wx2.2.5\lib\zlibd.lib
 \wx2.2.5\lib\tiffd.lib
 ]
 \wx2.2.5\lib\zlibd.lib
 \wx2.2.5\lib\tiffd.lib
 ]
-Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP284.tmp"
+Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E7.tmp"
 <h3>Output Window</h3>
 Linking...
 
 <h3>Output Window</h3>
 Linking...
 
index 274165ed07e816552c74637f5a6e216f8e58cec7..275f20bd01c8f2ee4e4d9825bf1db6ddb474e374 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2001 Kevin Rosenberg
 **
-**  $Id: backgroundmgr.cpp,v 1.19 2001/03/13 04:44:25 kevin Exp $
+**  $Id: backgroundmgr.cpp,v 1.20 2001/03/18 18:08:26 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
 **
 **  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
@@ -152,7 +152,6 @@ BackgroundManager::OnAddTask (wxCommandEvent& event)
   resizeWindow();
   if (m_iNumTasks == 1) {
     m_pCanvas->SetFocus();
   resizeWindow();
   if (m_iNumTasks == 1) {
     m_pCanvas->SetFocus();
-    pGauge->SetFocus();
     Show(true);  
   }
 }
     Show(true);  
   }
 }
@@ -188,9 +187,8 @@ BackgroundManager::OnRemoveTask (wxCommandEvent& event)
   pSupervisor->ackRemoveBackgroundManager();
   resizeWindow();
   if (m_iNumTasks <= 0) {
   pSupervisor->ackRemoveBackgroundManager();
   resizeWindow();
   if (m_iNumTasks <= 0) {
-    theApp->getMainFrame()->SetFocus();
+    m_pCanvas->SetFocus();
     Show(false);
     Show(false);
-    theApp->getMainFrame()->SetFocus();
   }
 }
 
   }
 }
 
index b7d20a9d31a7e6c5654085bd33ba6cad47fd953c..06d4cc34447ff5400761c456fd4525ae5e9a60d6 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: ctsim.h,v 1.59 2001/03/13 08:24:41 kevin Exp $
+**  $Id: ctsim.h,v 1.60 2001/03/18 18:08:26 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
 **
 **  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
@@ -308,10 +308,12 @@ enum {
     PJMENU_RECONSTRUCT_FBP,
     PJMENU_RECONSTRUCT_FBP_REBIN,
     PJMENU_RECONSTRUCT_FOURIER,
     PJMENU_RECONSTRUCT_FBP,
     PJMENU_RECONSTRUCT_FBP_REBIN,
     PJMENU_RECONSTRUCT_FOURIER,
+    PJMENU_CONVERT_RECTANGULAR,
     PJMENU_CONVERT_POLAR,
     PJMENU_CONVERT_FFT_POLAR,
     PJMENU_CONVERT_PARALLEL,
     PJMENU_PLOT_TTHETA_SAMPLING,
     PJMENU_CONVERT_POLAR,
     PJMENU_CONVERT_FFT_POLAR,
     PJMENU_CONVERT_PARALLEL,
     PJMENU_PLOT_TTHETA_SAMPLING,
+    PJMENU_PLOT_HISTOGRAM,
     PJMENU_ARTIFACT_REDUCTION,
     
     IFMENU_FILE_EXPORT,
     PJMENU_ARTIFACT_REDUCTION,
     
     IFMENU_FILE_EXPORT,
index d92912fb09a653f164d88460d4067eb86bfd8ac7..526ab6480ffd3032f3cf6c510b64deff7389ed59 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: graph3dview.cpp,v 1.19 2001/03/13 04:44:25 kevin Exp $
+**  $Id: graph3dview.cpp,v 1.20 2001/03/18 18:08:26 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
 **
 **  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
@@ -117,40 +117,20 @@ Graph3dFileView::intensityToColor (double dIntensity, GLfloat* vecColor)
 //     fNormalZ   == Z vector for the normal vector
 //*************************************************************************
 
 //     fNormalZ   == Z vector for the normal vector
 //*************************************************************************
 
-void 
-CalculateVectorNormal (GLfloat fVert1[], GLfloat fVert2[], 
-                       GLfloat fVert3[], GLfloat *fNormalX,
-                       GLfloat *fNormalY, GLfloat *fNormalZ)
-{
-  GLfloat Qx = fVert2[0] - fVert1[0];
-  GLfloat Qy = fVert2[1] - fVert1[1];
-  GLfloat Qz = fVert2[2] - fVert1[2];
-  GLfloat Px = fVert3[0] - fVert1[0];
-  GLfloat Py = fVert3[1] - fVert1[1];
-  GLfloat Pz = fVert3[2] - fVert1[2];
-  
-  *fNormalX = Py*Qz - Pz*Qy;
-  *fNormalY = Pz*Qx - Px*Qz;
-  *fNormalZ = Px*Qy - Py*Qx;
-  
-} 
-
-void 
-CalculateVectorNormal (GLdouble fVert1[], GLdouble fVert2[], 
-                       GLdouble fVert3[], GLdouble *fNormalX,
-                       GLdouble *fNormalY, GLdouble *fNormalZ)
+template<class T>
+static void 
+CalculateVectorNormal (T fVert1[], T fVert2[], T fVert3[], T *fNormalX, T *fNormalY, T *fNormalZ)
 {
 {
-  GLdouble Qx = fVert2[0] - fVert1[0];
-  GLdouble Qy = fVert2[1] - fVert1[1];
-  GLdouble Qz = fVert2[2] - fVert1[2];
-  GLdouble Px = fVert3[0] - fVert1[0];
-  GLdouble Py = fVert3[1] - fVert1[1];
-  GLdouble Pz = fVert3[2] - fVert1[2];
+  T Qx = fVert2[0] - fVert1[0];
+  T Qy = fVert2[1] - fVert1[1];
+  T Qz = fVert2[2] - fVert1[2];
+  T Px = fVert3[0] - fVert1[0];
+  T Py = fVert3[1] - fVert1[1];
+  T Pz = fVert3[2] - fVert1[2];
   
   *fNormalX = Py*Qz - Pz*Qy;
   *fNormalY = Pz*Qx - Px*Qz;
   *fNormalZ = Px*Qy - Py*Qx;
   
   *fNormalX = Py*Qz - Pz*Qy;
   *fNormalY = Pz*Qx - Px*Qz;
   *fNormalZ = Px*Qy - Py*Qx;
-  
 } 
 
 IMPLEMENT_DYNAMIC_CLASS(Graph3dFileView, wxView)
 } 
 
 IMPLEMENT_DYNAMIC_CLASS(Graph3dFileView, wxView)
@@ -171,15 +151,16 @@ Graph3dFileView::Graph3dFileView ()
 {
   m_bDoubleBuffer = true;
   m_bSmooth = true;
 {
   m_bDoubleBuffer = true;
   m_bSmooth = true;
-  m_bLighting = true;
-  m_bSurface = true;
-  m_bLighting = true;
-  m_bColor = false;
-  m_dXRotate = -45;
-  m_dYRotate = 0;
-  m_dZRotate = -45;
+  m_bLighting = false;
+  m_bSurface = false;
+  m_bLighting = false;
+  m_bColor = true;
+  m_dXRotate = -180;
+  m_dYRotate = -210;
+  m_dZRotate = -195;
   m_bColorScaleMinSet = false;
   m_bColorScaleMaxSet = false;
   m_bColorScaleMinSet = false;
   m_bColorScaleMaxSet = false;
+  m_bCalculatedSurfaceBackground = false;
 }
 
 Graph3dFileView::~Graph3dFileView()
 }
 
 Graph3dFileView::~Graph3dFileView()
@@ -236,6 +217,9 @@ Graph3dFileView::CreateCanvas (wxFrame* parent)
 void
 Graph3dFileView::DrawSurface()
 {
 void
 Graph3dFileView::DrawSurface()
 {
+  if (! GetDocument())
+    return;
+  
   if (m_bSmooth) {
     glShadeModel (GL_SMOOTH);
   } else {
   if (m_bSmooth) {
     glShadeModel (GL_SMOOTH);
   } else {
@@ -248,23 +232,37 @@ Graph3dFileView::DrawSurface()
     glDisable (GL_LIGHTING);
   }
   
     glDisable (GL_LIGHTING);
   }
   
-  if (m_bSurface)
-    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-  else
-    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-  
-  InitMaterials(); 
-  
-  if (! GetDocument())
-    return;
-  
   unsigned int nx = GetDocument()->nx();
   unsigned int ny = GetDocument()->ny();
   unsigned int nx = GetDocument()->nx();
   unsigned int ny = GetDocument()->ny();
+
   glRotated (m_dZRotate, 0.0, 1.0, 0.0);
   glRotated (m_dXRotate, 0.0, 0.0, 1.0);
   glRotated (m_dYRotate, 1.0, 0.0, 0.0);
   glTranslated (-static_cast<double>(nx - 1) / 2, 0.0, -static_cast<double>(ny - 1) / 2);
   glRotated (m_dZRotate, 0.0, 1.0, 0.0);
   glRotated (m_dXRotate, 0.0, 0.0, 1.0);
   glRotated (m_dYRotate, 1.0, 0.0, 0.0);
   glTranslated (-static_cast<double>(nx - 1) / 2, 0.0, -static_cast<double>(ny - 1) / 2);
-  glCallList (DISPLAYLIST_SURFACE);
+
+  InitMaterials();   
+  if (m_bSurface) {
+    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+    if (! m_bColor) {
+      glColor3f (1.0f, 1.0f, 1.0f);
+      glCallList (DISPLAYLIST_NO_COLOR);
+    } else
+      glCallList (DISPLAYLIST_COLOR);
+  }
+  else {
+    if (! m_bColor)
+      glColor3f (1.0f, 1.0f, 1.0f);
+    glPolygonOffset (1.0f, 1.0f);
+    glEnable (GL_POLYGON_OFFSET_FILL);
+    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+    glCallList (DISPLAYLIST_COLOR);
+
+    glColor3f (0.0f, 0.0f, 0.0f);
+    glPolygonOffset (0.0f, 0.0f);
+    glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+    glCallList (DISPLAYLIST_NO_COLOR);
+  }
+  
 }
 
 void
 }
 
 void
@@ -279,7 +277,7 @@ Graph3dFileView::CreateDisplayList()
   if (nx == 0 || ny == 0 || ! v)
     return;
   
   if (nx == 0 || ny == 0 || ! v)
     return;
   
-  glNewList (DISPLAYLIST_SURFACE, GL_COMPILE);
+  glNewList (DISPLAYLIST_COLOR, GL_COMPILE);
   
   double dMin = m_dColorScaleMin;
   double dIntensityScale = m_dColorScaleMax - m_dColorScaleMin;
   
   double dMin = m_dColorScaleMin;
   double dIntensityScale = m_dColorScaleMax - m_dColorScaleMin;
@@ -290,9 +288,6 @@ Graph3dFileView::CreateDisplayList()
   dXOffset = 0;
   dYOffset = 0;
 
   dXOffset = 0;
   dYOffset = 0;
 
-  if (! m_bColor)
-    glColor3f (1.0f, 1.0f, 1.0f);
-  
   double dXPos = -dXOffset;
   for (unsigned ix = 0; ix < nx - 1; ix++, dXPos++) {
     double dYPos = -dYOffset;
   double dXPos = -dXOffset;
   for (unsigned ix = 0; ix < nx - 1; ix++, dXPos++) {
     double dYPos = -dYOffset;
@@ -301,7 +296,7 @@ Graph3dFileView::CreateDisplayList()
     p1[0] = dXPos;  p1[1] = actScale * (v[ix][0] + actOffset); p1[2] = dYPos;
     p2[0] = dXPos+1; p2[1] = actScale * (v[ix+1][0] + actOffset); p2[2] = dYPos; 
     p3[0] = dXPos; p3[1] = actScale * (v[ix][1] + actOffset); p3[2] = dYPos + 1;
     p1[0] = dXPos;  p1[1] = actScale * (v[ix][0] + actOffset); p1[2] = dYPos;
     p2[0] = dXPos+1; p2[1] = actScale * (v[ix+1][0] + actOffset); p2[2] = dYPos; 
     p3[0] = dXPos; p3[1] = actScale * (v[ix][1] + actOffset); p3[2] = dYPos + 1;
-    CalculateVectorNormal (p1, p2, p3, &n1[0], &n1[1], &n1[2]);
+    CalculateVectorNormal<double> (p1, p2, p3, &n1[0], &n1[1], &n1[2]);
 
     double dIntensity1, dIntensity2;
     if (m_bColor) {
 
     double dIntensity1, dIntensity2;
     if (m_bColor) {
@@ -315,10 +310,8 @@ Graph3dFileView::CreateDisplayList()
     }
     glVertex3dv (p1); 
     glNormal3dv (n1);                                  
     }
     glVertex3dv (p1); 
     glNormal3dv (n1);                                  
-    if (m_bColor) {
       intensityToColor (dIntensity2, vecColor);
       glColor3fv (vecColor);
       intensityToColor (dIntensity2, vecColor);
       glColor3fv (vecColor);
-    }
     glVertex3dv (p2); 
     glNormal3dv (n1);                                  
     double lastP[3];
     glVertex3dv (p2); 
     glNormal3dv (n1);                                  
     double lastP[3];
@@ -328,19 +321,43 @@ Graph3dFileView::CreateDisplayList()
       p2[0] = dXPos+1;  p2[1] = actScale * (v[ix+1][iy] + actOffset); p2[2] = dYPos;
       CalculateVectorNormal (p1, p2, lastP, &n1[0], &n1[1], &n1[2]);
       lastP[0] = p1[0]; lastP[1] = p1[1]; lastP[2] = p1[2];
       p2[0] = dXPos+1;  p2[1] = actScale * (v[ix+1][iy] + actOffset); p2[2] = dYPos;
       CalculateVectorNormal (p1, p2, lastP, &n1[0], &n1[1], &n1[2]);
       lastP[0] = p1[0]; lastP[1] = p1[1]; lastP[2] = p1[2];
-      if (m_bColor) {
         dIntensity1 = (v[ix][iy] - dMin) / dIntensityScale;
         dIntensity2 = (v[ix+1][iy] - dMin) / dIntensityScale;
         dIntensity1 = (v[ix][iy] - dMin) / dIntensityScale;
         dIntensity2 = (v[ix+1][iy] - dMin) / dIntensityScale;
-      }
-      if (m_bColor) {
         intensityToColor (dIntensity1, vecColor);
         glColor3fv (vecColor);
         intensityToColor (dIntensity1, vecColor);
         glColor3fv (vecColor);
-      }
       glVertex3dv (p1); glNormal3dv (n1);                                      
       glVertex3dv (p1); glNormal3dv (n1);                                      
-      if (m_bColor) {
         intensityToColor (dIntensity2, vecColor);
         glColor3fv (vecColor);
         intensityToColor (dIntensity2, vecColor);
         glColor3fv (vecColor);
-      }
+      glVertex3dv (p2); glNormal3dv (n1);                                      
+    }                  
+    glEnd(); // QUAD_STRIP
+  }
+  glEndList();
+
+
+  glNewList (DISPLAYLIST_NO_COLOR, GL_COMPILE);
+  dXPos = -dXOffset;
+  for (ix = 0; ix < nx - 1; ix++, dXPos++) {
+    double dYPos = -dYOffset;
+    glBegin(GL_QUAD_STRIP);
+    double p1[3], p2[3], p3[3], n1[3]; 
+    p1[0] = dXPos;  p1[1] = actScale * (v[ix][0] + actOffset); p1[2] = dYPos;
+    p2[0] = dXPos+1; p2[1] = actScale * (v[ix+1][0] + actOffset); p2[2] = dYPos; 
+    p3[0] = dXPos; p3[1] = actScale * (v[ix][1] + actOffset); p3[2] = dYPos + 1;
+    CalculateVectorNormal<double> (p1, p2, p3, &n1[0], &n1[1], &n1[2]);
+
+    glVertex3dv (p1); 
+    glNormal3dv (n1);                                  
+    glVertex3dv (p2); 
+    glNormal3dv (n1);                                  
+    double lastP[3];
+    lastP[0] = ix; lastP[1] = actScale * (v[ix][0] + actOffset); lastP[2] = 0; 
+    for (unsigned int iy = 1; iy < ny - 1; iy++, dYPos++) {       
+      p1[0] = dXPos; p1[1] = actScale * (v[ix][iy] + actOffset); p1[2] = dYPos;
+      p2[0] = dXPos+1;  p2[1] = actScale * (v[ix+1][iy] + actOffset); p2[2] = dYPos;
+      CalculateVectorNormal (p1, p2, lastP, &n1[0], &n1[1], &n1[2]);
+      lastP[0] = p1[0]; lastP[1] = p1[1]; lastP[2] = p1[2];
+      glVertex3dv (p1); glNormal3dv (n1);                                      
       glVertex3dv (p2); glNormal3dv (n1);                                      
     }                  
     glEnd(); // QUAD_STRIP
       glVertex3dv (p2); glNormal3dv (n1);                                      
     }                  
     glEnd(); // QUAD_STRIP
@@ -349,6 +366,13 @@ Graph3dFileView::CreateDisplayList()
 }
 
 
 }
 
 
+void
+Graph3dFileView::calculateSurfaceBackground ()
+{
+  if (m_bCalculatedSurfaceBackground)
+    return;
+}
+
 void
 Graph3dFileView::OnProperties (wxCommandEvent& event)
 {
 void
 Graph3dFileView::OnProperties (wxCommandEvent& event)
 {
@@ -380,7 +404,7 @@ Graph3dFileView::OnColor (wxCommandEvent& event)
 {
   m_bColor = ! m_bColor;
   m_pViewMenu->Check (GRAPH3D_VIEW_COLOR, m_bColor);
 {
   m_bColor = ! m_bColor;
   m_pViewMenu->Check (GRAPH3D_VIEW_COLOR, m_bColor);
-  OnUpdate (this, NULL);
+  m_pCanvas->Refresh();
 }
 
 void
 }
 
 void
@@ -434,8 +458,8 @@ Graph3dFileView::InitMaterials()
 #if 1
   static float ambient[] = {0.1f, 0.1f, 0.1f, 1.0f};
   static float diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
 #if 1
   static float ambient[] = {0.1f, 0.1f, 0.1f, 1.0f};
   static float diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
-  static float position0[] = {-nx/2, -ny/2, -ny/2, 0.0f, 0.0f};
-  static float position1[] = {-nx/2, -ny/2, ny/2, 0.0f};
+  static float position0[] = {-nx/2, -ny/2, ny/2, 0.0f, 0.0f};
+  static float position1[] = {-nx/2, -ny/2, -ny/2, 0.0f};
   static float ambient1[] = {0.5f, 0.5f, 0.5f, 1.0f};
   static float diffuse1[] = {1.0f, 1.0f, 1.0f, 1.0f};
   //  static float position0[] = {0.0f, 0.0f, 20.0f, 0.0f};
   static float ambient1[] = {0.5f, 0.5f, 0.5f, 1.0f};
   static float diffuse1[] = {1.0f, 1.0f, 1.0f, 1.0f};
   //  static float position0[] = {0.0f, 0.0f, 20.0f, 0.0f};
@@ -600,7 +624,6 @@ Graph3dFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
       if (! m_bColorScaleMaxSet)
         m_dColorScaleMax = max;  
   }
       if (! m_bColorScaleMaxSet)
         m_dColorScaleMax = max;  
   }
-  
   double dRadius = maxValue<int> (nx, ny) * SQRT2 / 2;
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   double dRadius = maxValue<int> (nx, ny) * SQRT2 / 2;
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
index f5ae3e4afc19f78ecb175cb2ef0b384c2897269b..44adb86c4bc51da0317c98eb8654f0e1648d35f4 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: graph3dview.h,v 1.6 2001/02/04 22:58:41 kevin Exp $
+**  $Id: graph3dview.h,v 1.7 2001/03/18 18:08:26 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
 **
 **  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
@@ -59,7 +59,8 @@ private:
   bool m_bSurface;
   bool m_bColor;
   enum {
   bool m_bSurface;
   bool m_bColor;
   enum {
-    DISPLAYLIST_SURFACE = 1,
+    DISPLAYLIST_COLOR = 1,
+    DISPLAYLIST_NO_COLOR = 2,
   };
 
   double m_dGraphMin;
   };
 
   double m_dGraphMin;
@@ -68,6 +69,7 @@ private:
   double m_dColorScaleMax;
   bool m_bColorScaleMinSet;
   bool m_bColorScaleMaxSet;
   double m_dColorScaleMax;
   bool m_bColorScaleMinSet;
   bool m_bColorScaleMaxSet;
+  bool m_bCalculatedSurfaceBackground;
 
   void Draw();
   void DrawSurface();
 
   void Draw();
   void DrawSurface();
@@ -113,6 +115,7 @@ public:
   void OnScaleSet (wxCommandEvent& event);
   void OnScaleAuto (wxCommandEvent& event);
   void OnScaleFull (wxCommandEvent& event);
   void OnScaleSet (wxCommandEvent& event);
   void OnScaleAuto (wxCommandEvent& event);
   void OnScaleFull (wxCommandEvent& event);
+  void calculateSurfaceBackground();
 
 #if CTSIM_MDI
   wxDocMDIChildFrame* getFrame() { return m_pFrame; }
 
 #if CTSIM_MDI
   wxDocMDIChildFrame* getFrame() { return m_pFrame; }
index 56fe8cf1a1e069dd6d2867dd3cd4350eab50e142..6c59f8eb586a3303fd55c2a41034036dbb844a8f 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: views.cpp,v 1.138 2001/03/13 10:35:06 kevin Exp $
+**  $Id: views.cpp,v 1.139 2001/03/18 18:08:26 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
 **
 **  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
@@ -887,7 +887,7 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   view_menu->Append(IFMENU_VIEW_SCALE_FULL, "Display F&ull Scale\tCtrl-U");
   
   wxMenu* filter_menu = new wxMenu;
   view_menu->Append(IFMENU_VIEW_SCALE_FULL, "Display F&ull Scale\tCtrl-U");
   
   wxMenu* filter_menu = new wxMenu;
-  filter_menu->Append (IFMENU_FILTER_INVERTVALUES, "&Invert Values");
+  filter_menu->Append (IFMENU_FILTER_INVERTVALUES, "In&vert Values");
   filter_menu->Append (IFMENU_FILTER_SQUARE, "&Square");
   filter_menu->Append (IFMENU_FILTER_SQRT, "Square &Root");
   filter_menu->Append (IFMENU_FILTER_LOG, "&Log");
   filter_menu->Append (IFMENU_FILTER_SQUARE, "&Square");
   filter_menu->Append (IFMENU_FILTER_SQRT, "Square &Root");
   filter_menu->Append (IFMENU_FILTER_LOG, "&Log");
@@ -968,7 +968,7 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('C'), IFMENU_EDIT_COPY);
   accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('X'), IFMENU_EDIT_CUT);
   accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('V'), IFMENU_EDIT_PASTE);
   accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('C'), IFMENU_EDIT_COPY);
   accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('X'), IFMENU_EDIT_CUT);
   accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('V'), IFMENU_EDIT_PASTE);
-#if wxUSE_GLCANVAS
+#ifdef wxUSE_GLCANVAS
   accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('3'), IFMENU_IMAGE_CONVERT3D);
   wxAcceleratorTable accelTable (8, accelEntries);
 #else
   accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('3'), IFMENU_IMAGE_CONVERT3D);
   wxAcceleratorTable accelTable (8, accelEntries);
 #else
@@ -1203,6 +1203,10 @@ ImageFileView::OnExport (wxCommandEvent& event)
         strWildcard = "DICOM Files (*.*)|*.*";
       }
 #endif
         strWildcard = "DICOM Files (*.*)|*.*";
       }
 #endif
+      else if (m_iDefaultExportFormatID == ImageFile::EXPORT_FORMAT_TEXT) {
+        strExt = ".txt";
+        strWildcard = "Text (*.txt)|*.txt";
+      }
       else {
         strExt = "";
         strWildcard = "Miscellaneous (*.*)|*.*";
       else {
         strExt = "";
         strWildcard = "Miscellaneous (*.*)|*.*";
@@ -1873,7 +1877,7 @@ ImageFileView::OnPlotHistogram (wxCommandEvent& event)
         s += rIF.labelGet(iL).getLabelString();
         rPlotFile.addDescription (s.c_str());
       }
         s += rIF.labelGet(iL).getLabelString();
         rPlotFile.addDescription (s.c_str());
       }
-      os << " Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
+      os << "  plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
       *theApp->getLog() << os.str().c_str() << "\n";
       rPlotFile.addDescription (os.str().c_str());
       delete pX;
       *theApp->getLog() << os.str().c_str() << "\n";
       rPlotFile.addDescription (os.str().c_str());
       delete pX;
@@ -2380,10 +2384,12 @@ EVT_MENU(PJMENU_FILE_PROPERTIES, ProjectionFileView::OnProperties)
 EVT_MENU(PJMENU_RECONSTRUCT_FBP, ProjectionFileView::OnReconstructFBP)
 EVT_MENU(PJMENU_RECONSTRUCT_FBP_REBIN, ProjectionFileView::OnReconstructFBPRebin)
 EVT_MENU(PJMENU_RECONSTRUCT_FOURIER, ProjectionFileView::OnReconstructFourier)
 EVT_MENU(PJMENU_RECONSTRUCT_FBP, ProjectionFileView::OnReconstructFBP)
 EVT_MENU(PJMENU_RECONSTRUCT_FBP_REBIN, ProjectionFileView::OnReconstructFBPRebin)
 EVT_MENU(PJMENU_RECONSTRUCT_FOURIER, ProjectionFileView::OnReconstructFourier)
+EVT_MENU(PJMENU_CONVERT_RECTANGULAR, ProjectionFileView::OnConvertRectangular)
 EVT_MENU(PJMENU_CONVERT_POLAR, ProjectionFileView::OnConvertPolar)
 EVT_MENU(PJMENU_CONVERT_FFT_POLAR, ProjectionFileView::OnConvertFFTPolar)
 EVT_MENU(PJMENU_CONVERT_PARALLEL, ProjectionFileView::OnConvertParallel)
 EVT_MENU(PJMENU_PLOT_TTHETA_SAMPLING, ProjectionFileView::OnPlotTThetaSampling)
 EVT_MENU(PJMENU_CONVERT_POLAR, ProjectionFileView::OnConvertPolar)
 EVT_MENU(PJMENU_CONVERT_FFT_POLAR, ProjectionFileView::OnConvertFFTPolar)
 EVT_MENU(PJMENU_CONVERT_PARALLEL, ProjectionFileView::OnConvertParallel)
 EVT_MENU(PJMENU_PLOT_TTHETA_SAMPLING, ProjectionFileView::OnPlotTThetaSampling)
+EVT_MENU(PJMENU_PLOT_HISTOGRAM, ProjectionFileView::OnPlotHistogram)
 EVT_MENU(PJMENU_ARTIFACT_REDUCTION, ProjectionFileView::OnArtifactReduction)
 END_EVENT_TABLE()
 
 EVT_MENU(PJMENU_ARTIFACT_REDUCTION, ProjectionFileView::OnArtifactReduction)
 END_EVENT_TABLE()
 
@@ -2439,6 +2445,40 @@ ProjectionFileView::OnProperties (wxCommandEvent& event)
 }
 
 
 }
 
 
+void
+ProjectionFileView::OnConvertRectangular (wxCommandEvent& event)
+{
+  Projections& rProj = GetDocument()->getProjections();
+  
+  int nDet = rProj.nDet();
+  int nView = rProj.nView();
+  ImageFile* pIF = new ImageFile (nDet, nView);
+  ImageFileArray v = pIF->getArray();
+  for (int iv = 0; iv < nView; iv++) {
+    DetectorValue* detval = rProj.getDetectorArray(iv).detValues();
+    
+    for (int id = 0; id < nDet; id++)
+      v[id][iv] = detval[id];
+  }
+  
+  ImageFileDocument* pRectDoc = theApp->newImageDoc ();
+  if (! pRectDoc) {
+    sys_error (ERR_SEVERE, "Unable to create image file");
+    return;
+  }
+  pRectDoc->setImageFile (pIF);
+  pIF->labelAdd (rProj.getLabel().getLabelString().c_str(), rProj.calcTime());
+  std::ostringstream os;
+  os << "Convert projection file " << GetFrame()->GetTitle().c_str() << " to rectangular image";
+  *theApp->getLog() << os.str().c_str() << "\n";
+  pIF->labelAdd (os.str().c_str());
+  if (theApp->getAskDeleteNewDocs())
+    pRectDoc->Modify (true);
+  pRectDoc->getView()->getFrame()->Show(true);
+  pRectDoc->UpdateAllViews ();
+  pRectDoc->Activate();
+}
+
 void
 ProjectionFileView::OnConvertPolar (wxCommandEvent& event)
 {
 void
 ProjectionFileView::OnConvertPolar (wxCommandEvent& event)
 {
@@ -2564,6 +2604,80 @@ ProjectionFileView::OnPlotTThetaSampling (wxCommandEvent& event)
   pPlotDoc->Activate();
 }
 
   pPlotDoc->Activate();
 }
 
+
+void
+ProjectionFileView::OnPlotHistogram (wxCommandEvent& event)
+{ 
+  Projections& rProj = GetDocument()->getProjections();
+  int nDet = rProj.nDet();
+  int nView = rProj.nView();
+  
+  if (nDet < 1 || nView < 1)
+    return;
+
+  PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
+  if (! pPlotDoc) {
+    sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
+    return;
+  }
+    
+  DetectorValue* pdDetval = rProj.getDetectorArray(0).detValues();
+  double dMin = pdDetval[0], dMax = pdDetval[0];
+
+  for (int iv = 0; iv < nView; iv++) {
+    pdDetval = rProj.getDetectorArray(iv).detValues();
+    for (int id = 0; id < nDet; id++) {
+      double dV = pdDetval[id];
+      if (dV < dMin)
+        dMin = dV;
+      else if (dV > dMax)
+        dMax = dV;
+    }
+  }
+
+  double* pX = new double [NUMBER_HISTOGRAM_BINS];
+  double* pY = new double [NUMBER_HISTOGRAM_BINS];
+  double dBinWidth = (dMax - dMin) / NUMBER_HISTOGRAM_BINS;
+    
+  for (int i = 0; i < NUMBER_HISTOGRAM_BINS; i++) {
+    pX[i] = dMin + (i + 0.5) * dBinWidth;
+    pY[i] = 0;
+  }
+  for (int j = 0; j < nView; j++) {
+    pdDetval = rProj.getDetectorArray(j).detValues();
+    for (int id = 0; id < nDet; id++) {
+      int iBin = nearest<int> ((pdDetval[id] - dMin) / dBinWidth);
+      if (iBin >= 0 && iBin < NUMBER_HISTOGRAM_BINS)
+        pY[iBin] += 1;
+    }
+  }      
+  PlotFile& rPlotFile = pPlotDoc->getPlotFile();
+  std::ostringstream os;
+  os << "Histogram";
+  std::string title("title ");
+  title += os.str();
+  rPlotFile.addEzsetCommand (title.c_str());
+  rPlotFile.addEzsetCommand ("xlabel Detector Value");
+  rPlotFile.addEzsetCommand ("ylabel Count");
+  rPlotFile.addEzsetCommand ("box");
+  rPlotFile.addEzsetCommand ("grid");
+  rPlotFile.setCurveSize (2, NUMBER_HISTOGRAM_BINS);
+  rPlotFile.addColumn (0, pX);
+  rPlotFile.addColumn (1, pY);
+  rPlotFile.addDescription (rProj.remark());
+  os << " plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
+  *theApp->getLog() << os.str().c_str() << "\n";
+  rPlotFile.addDescription (os.str().c_str());
+  delete pX;
+  delete pY;
+  if (theApp->getAskDeleteNewDocs())
+    pPlotDoc->Modify (true);
+  pPlotDoc->getView()->getFrame()->Show(true);
+  pPlotDoc->UpdateAllViews ();
+  pPlotDoc->Activate();
+}
+
+
 void
 ProjectionFileView::OnConvertParallel (wxCommandEvent& event)
 {
 void
 ProjectionFileView::OnConvertParallel (wxCommandEvent& event)
 {
@@ -2657,7 +2771,7 @@ ProjectionFileView::doReconstructFBP (const Projections& rProj, bool bRebinToPar
   os << "Reconstruct " << rProj.getFilename() << ": xSize=" << m_iDefaultNX << ", ySize=" << m_iDefaultNY << ", Filter=" << optFilterName.c_str() << ", FilterParam=" << m_dDefaultFilterParam << ", FilterMethod=" << optFilterMethodName.c_str() << ", FilterGeneration=" << optFilterGenerationName.c_str() << ", Zeropad=" << m_iDefaultZeropad << ", Interpolation=" << optInterpName.c_str() << ", InterpolationParam=" << m_iDefaultInterpParam << ", Backprojection=" << optBackprojectName.c_str();
   if (bRebinToParallel)
     os << "; Interpolate to Parallel";
   os << "Reconstruct " << rProj.getFilename() << ": xSize=" << m_iDefaultNX << ", ySize=" << m_iDefaultNY << ", Filter=" << optFilterName.c_str() << ", FilterParam=" << m_dDefaultFilterParam << ", FilterMethod=" << optFilterMethodName.c_str() << ", FilterGeneration=" << optFilterGenerationName.c_str() << ", Zeropad=" << m_iDefaultZeropad << ", Interpolation=" << optInterpName.c_str() << ", InterpolationParam=" << m_iDefaultInterpParam << ", Backprojection=" << optBackprojectName.c_str();
   if (bRebinToParallel)
     os << "; Interpolate to Parallel";
-
+  
   Timer timerRecon;
   ImageFile* pImageFile = NULL;
   if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
   Timer timerRecon;
   ImageFile* pImageFile = NULL;
   if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
@@ -2805,8 +2919,9 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   GetDocumentManager()->FileHistoryUseMenu(m_pFileMenu);
   
   wxMenu *convert_menu = new wxMenu;
   GetDocumentManager()->FileHistoryUseMenu(m_pFileMenu);
   
   wxMenu *convert_menu = new wxMenu;
+  convert_menu->Append (PJMENU_CONVERT_RECTANGULAR, "&Rectangular Image");
   convert_menu->Append (PJMENU_CONVERT_POLAR, "&Polar Image...\tCtrl-L");
   convert_menu->Append (PJMENU_CONVERT_POLAR, "&Polar Image...\tCtrl-L");
-  convert_menu->Append (PJMENU_CONVERT_FFT_POLAR, "&FFT->Polar Image...\tCtrl-M");
+  convert_menu->Append (PJMENU_CONVERT_FFT_POLAR, "FF&T->Polar Image...\tCtrl-T");
   convert_menu->AppendSeparator();
   convert_menu->Append (PJMENU_CONVERT_PARALLEL, "&Interpolate to Parallel");
   
   convert_menu->AppendSeparator();
   convert_menu->Append (PJMENU_CONVERT_PARALLEL, "&Interpolate to Parallel");
   
@@ -2814,8 +2929,9 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   filter_menu->Append (PJMENU_ARTIFACT_REDUCTION, "&Artifact Reduction");
   
   wxMenu* analyze_menu = new wxMenu;
   filter_menu->Append (PJMENU_ARTIFACT_REDUCTION, "&Artifact Reduction");
   
   wxMenu* analyze_menu = new wxMenu;
-  analyze_menu->Append (PJMENU_PLOT_TTHETA_SAMPLING, "&Plot T-Theta Sampling\tCtrl-T");
-  
+  analyze_menu->Append (PJMENU_PLOT_HISTOGRAM, "&Plot Histogram");
+  analyze_menu->Append (PJMENU_PLOT_TTHETA_SAMPLING, "Plot T-T&heta Sampling...\tCtrl-H");
+
   wxMenu *reconstruct_menu = new wxMenu;
   reconstruct_menu->Append (PJMENU_RECONSTRUCT_FBP, "&Filtered Backprojection...\tCtrl-R", "Reconstruct image using filtered backprojection");
   reconstruct_menu->Append (PJMENU_RECONSTRUCT_FBP_REBIN, "Filtered &Backprojection (Rebin to Parallel)...\tCtrl-B", "Reconstruct image using filtered backprojection");
   wxMenu *reconstruct_menu = new wxMenu;
   reconstruct_menu->Append (PJMENU_RECONSTRUCT_FBP, "&Filtered Backprojection...\tCtrl-R", "Reconstruct image using filtered backprojection");
   reconstruct_menu->Append (PJMENU_RECONSTRUCT_FBP_REBIN, "Filtered &Backprojection (Rebin to Parallel)...\tCtrl-B", "Reconstruct image using filtered backprojection");
@@ -2842,12 +2958,12 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   
   wxAcceleratorEntry accelEntries[7];
   accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('L'), PJMENU_CONVERT_POLAR);
   
   wxAcceleratorEntry accelEntries[7];
   accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('L'), PJMENU_CONVERT_POLAR);
-  accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('M'), PJMENU_CONVERT_FFT_POLAR);
+  accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('T'), PJMENU_CONVERT_FFT_POLAR);
   accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('R'), PJMENU_RECONSTRUCT_FBP);
   accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('B'), PJMENU_RECONSTRUCT_FBP_REBIN);
   accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('E'), PJMENU_RECONSTRUCT_FOURIER);
   accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('I'), PJMENU_FILE_PROPERTIES);
   accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('R'), PJMENU_RECONSTRUCT_FBP);
   accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('B'), PJMENU_RECONSTRUCT_FBP_REBIN);
   accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('E'), PJMENU_RECONSTRUCT_FOURIER);
   accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('I'), PJMENU_FILE_PROPERTIES);
-  accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('T'), PJMENU_PLOT_TTHETA_SAMPLING);
+  accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('H'), PJMENU_PLOT_TTHETA_SAMPLING);
   wxAcceleratorTable accelTable (7, accelEntries);
   subframe->SetAcceleratorTable (accelTable);
   
   wxAcceleratorTable accelTable (7, accelEntries);
   subframe->SetAcceleratorTable (accelTable);
   
index 69c2a1424ee4f3dfe4b67481fc3ed3fecbeddae5..3f902cf27b81bb739e7cd1758022bd930b461f60 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: views.h,v 1.51 2001/03/13 08:24:41 kevin Exp $
+**  $Id: views.h,v 1.52 2001/03/18 18:08:26 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
 **
 **  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
@@ -243,9 +243,11 @@ public:
   void OnReconstructFBP (wxCommandEvent& event);
   void OnReconstructFBPRebin (wxCommandEvent& event);
   void OnReconstructFourier (wxCommandEvent& event);
   void OnReconstructFBP (wxCommandEvent& event);
   void OnReconstructFBPRebin (wxCommandEvent& event);
   void OnReconstructFourier (wxCommandEvent& event);
+  void OnConvertRectangular (wxCommandEvent& event);
   void OnConvertPolar (wxCommandEvent& event);
   void OnConvertFFTPolar (wxCommandEvent& event);
   void OnPlotTThetaSampling (wxCommandEvent& event);
   void OnConvertPolar (wxCommandEvent& event);
   void OnConvertFFTPolar (wxCommandEvent& event);
   void OnPlotTThetaSampling (wxCommandEvent& event);
+  void OnPlotHistogram (wxCommandEvent& event);
   void OnConvertParallel (wxCommandEvent& event);
   void OnArtifactReduction (wxCommandEvent& event);
 
   void OnConvertParallel (wxCommandEvent& event);
   void OnArtifactReduction (wxCommandEvent& event);