X-Git-Url: http://git.kpe.io/?p=ctsim.git;a=blobdiff_plain;f=src%2Fviews.cpp;h=68b03759361524e097517c4725b87ba3d5c27741;hp=81eb051098485141b32c14cdf0d802ae5f259476;hb=f7d2b7144f32a7bd157b7689022e62944b82fcc1;hpb=89997e727ff5d4d8828f6fdaee435d809b623ffe diff --git a/src/views.cpp b/src/views.cpp index 81eb051..68b0375 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.31 2000/12/19 21:37:51 kevin Exp $ +** $Id: views.cpp,v 1.35 2000/12/21 03:40:58 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -90,7 +90,7 @@ ImageFileCanvas::DrawRubberBandCursor (wxDC& dc, int x, int y) ImageFileArrayConst v = rIF.getArray(); int nx = rIF.nx(); int ny = rIF.ny(); - + dc.SetLogicalFunction (wxINVERT); dc.SetPen (*wxGREEN_PEN); dc.DrawLine (0, y, nx, y); @@ -103,7 +103,7 @@ ImageFileCanvas::GetCurrentCursor (int& x, int& y) { x = m_xCursor; y = m_yCursor; - + if (m_xCursor >= 0 && m_yCursor >= 0) return true; else @@ -120,7 +120,7 @@ ImageFileCanvas::OnMouseEvent(wxMouseEvent& event) PrepareDC(dc); wxPoint pt(event.GetLogicalPosition(dc)); - + if (event.RightIsDown()) { const ImageFile& rIF = m_pView->GetDocument()->getImageFile(); ImageFileArrayConst v = rIF.getArray(); @@ -134,7 +134,7 @@ ImageFileCanvas::OnMouseEvent(wxMouseEvent& event) } else *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << pt.y << ")\n"; } - else if (event.LeftIsDown()) { + else if (event.LeftIsDown() || event.LeftUp()) { const ImageFile& rIF = m_pView->GetDocument()->getImageFile(); ImageFileArrayConst v = rIF.getArray(); int nx = rIF.nx(); @@ -147,11 +147,13 @@ ImageFileCanvas::OnMouseEvent(wxMouseEvent& event) DrawRubberBandCursor (dc, pt.x, pt.y); m_xCursor = pt.x; m_yCursor = pt.y; + } else + *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << pt.y << ")\n"; + } + if (event.LeftUp()) { std::ostringstream os; os << "Selected column" << pt.x << " and row" << pt.y << "\n"; *theApp->getLog() << os.str().c_str(); - } else - *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << pt.y << ")\n"; } } @@ -163,7 +165,8 @@ BEGIN_EVENT_TABLE(ImageFileView, wxView) EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties) EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax) EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto) -EVT_MENU(IFMENU_PLOT_ROW, ImageFileView::OnPlotRow) +EVT_MENU(IFMENU_COMPARE_IMAGES, ImageFileView::OnCompare) +EVT_MENU(IFMENU_PLOT_ROW, ImageFileView::OnPlotRow) EVT_MENU(IFMENU_PLOT_COL, ImageFileView::OnPlotCol) END_EVENT_TABLE() @@ -198,17 +201,20 @@ void ImageFileView::OnScaleAuto (wxCommandEvent& event) { const ImageFile& rIF = GetDocument()->getImageFile(); - DialogAutoScaleParameters dialogAutoScale (m_frame, rIF, m_dAutoScaleFactor); + double min, max, mean, mode, median, stddev; + rIF.statistics(min, max, mean, mode, median, stddev); + DialogAutoScaleParameters dialogAutoScale (m_frame, mean, mode, median, stddev, m_dAutoScaleFactor); int iRetVal = dialogAutoScale.ShowModal(); if (iRetVal == wxID_OK) { m_bMinSpecified = true; m_bMaxSpecified = true; - double dMin, dMax; - dialogAutoScale.getMinMax (&dMin, &dMax); - m_dMinPixel = dMin; - m_dMaxPixel = dMax; - m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor(); - OnUpdate (this, NULL); + double dMin, dMax; + if (dialogAutoScale.getMinMax (&dMin, &dMax)) { + m_dMinPixel = dMin; + m_dMaxPixel = dMax; + m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor(); + OnUpdate (this, NULL); + } } } @@ -225,7 +231,7 @@ ImageFileView::OnScaleMinMax (wxCommandEvent& event) if (m_bMaxSpecified) max = m_dMaxPixel; - DialogGetImageMinMax dialogMinMax (m_frame, rIF, min, max); + DialogGetMinMax dialogMinMax (m_frame, "Set Image Minimum & Maximum", min, max); int retVal = dialogMinMax.ShowModal(); if (retVal == wxID_OK) { m_bMinSpecified = true; @@ -235,7 +241,31 @@ ImageFileView::OnScaleMinMax (wxCommandEvent& event) OnUpdate (this, NULL); } } - + +void +ImageFileView::OnCompare (wxCommandEvent& event) +{ + wxList& rListDocs = theApp->getDocManager()->GetDocuments(); + std::vector vecIF; + std::vector vecFilename; + int nCompares = 0; + for (wxNode* pNode = rListDocs.GetFirst(); pNode != NULL; pNode = pNode->GetNext()) { + wxDocument* pDoc = reinterpret_cast(pNode->GetData()); + ImageFileDocument* pIFDoc = dynamic_cast(pDoc); + if (pIFDoc) { + if (pIFDoc->GetFirstView() != this) { + std::string strFilename = pDoc->GetFilename(); + vecIF.push_back (pIFDoc); + vecFilename.push_back (strFilename); + nCompares++; + } + } + } + for (int i = 0; i < nCompares; i++) { + const std::string& s = vecFilename[i]; + *theApp->getLog() << s.c_str() << "\n"; + } +} ImageFileCanvas* ImageFileView::CreateCanvas (wxView *view, wxFrame *parent) @@ -281,7 +311,10 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) wxMenu *plot_menu = new wxMenu; plot_menu->Append (IFMENU_PLOT_ROW, "Plot &Row"); plot_menu->Append (IFMENU_PLOT_COL, "Plot &Column"); - + + wxMenu *compare_menu = new wxMenu; + compare_menu->Append (IFMENU_COMPARE_IMAGES, "&Compare Images"); + wxMenu *help_menu = new wxMenu; help_menu->Append(MAINMENU_HELP_ABOUT, "&About"); @@ -289,7 +322,8 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) menu_bar->Append(file_menu, "&File"); menu_bar->Append(view_menu, "&View"); - menu_bar->Append(plot_menu, "&Plot"); + menu_bar->Append(plot_menu, "&Plot"); + menu_bar->Append(compare_menu, "&Compare"); menu_bar->Append(help_menu, "&Help"); subframe->SetMenuBar(menu_bar); @@ -330,7 +364,7 @@ ImageFileView::OnDraw (wxDC* dc) { if (m_bitmap.Ok()) dc->DrawBitmap(m_bitmap, 0, 0, false); - + int xCursor, yCursor; if (m_canvas->GetCurrentCursor (xCursor, yCursor)) m_canvas->DrawRubberBandCursor (*dc, xCursor, yCursor); @@ -406,62 +440,46 @@ ImageFileView::OnClose (bool deleteWindow) #include "wx/plot.h" -class VectorPlotCurve : wxPlotCurve { -private: - int m_nPoints; - std::vector m_points; - -public: - VectorPlotCurve (const double* const points, int n, double minVal, double maxVal) - : wxPlotCurve (minVal, minVal, maxVal) - { - for (int i = 0; i < n; i++) - m_points.push_back(points[i]); - } - - wxInt32 GetStartX () - { return 0; } - - wxInt32 GetEndX () - { return m_nPoints - 1; } - - double GetY (wxInt32 x) - { return m_points[x]; } -}; - - void ImageFileView::OnPlotRow (wxCommandEvent& event) { int xCursor, yCursor; if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) { - // os << "No row selected. Please use left mouse button on image to select row\n"; + *theApp->getLog() << "No row selected. Please use left mouse button on image to select row\n"; return; } - + const ImageFile& rIF = dynamic_cast(GetDocument())->getImageFile(); ImageFileArrayConst v = rIF.getArray(); int nx = rIF.nx(); int ny = rIF.ny(); - + if (v != NULL && yCursor < ny) { - double* pVec = new double [nx]; - double minVal = v[0][yCursor]; - double maxVal = minVal; + double* pX = new double [nx]; + double* pY = new double [nx]; for (int i = 0; i < nx; i++) { - pVec[i] = v[i][yCursor]; - if (pVec[i] < minVal) - minVal = pVec[i]; - else if (pVec[i] > maxVal) - maxVal = pVec[i]; + pX[i] = i; + pY[i] = v[i][yCursor]; + } + PlotFileDocument* pPlotDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT)); + if (! pPlotDoc) { + sys_error (ERR_SEVERE, "Internal error: unable to create Plot file"); + } else { + PlotFile& rPlotFile = pPlotDoc->getPlotFile(); + std::ostringstream title; + title << "Row " << yCursor; + rPlotFile.setTitle(title.str()); + rPlotFile.setXLabel("Column"); + rPlotFile.setYLabel("Pixel Value"); + rPlotFile.setCurveSize (2, nx); + rPlotFile.addColumn (0, pX); + rPlotFile.addColumn (1, pY); } - VectorPlotCurve* plotCurve = new VectorPlotCurve (pVec, nx, minVal, maxVal); - wxPlotWindow* plotWindow = new wxPlotWindow (m_canvas, NULL, wxPoint(0,0), wxSize(500,300)); - plotWindow->Add (reinterpret_cast(plotCurve)); - plotWindow->Enable(TRUE); - plotWindow->Show(); + delete pX; + delete pY; + pPlotDoc->Modify(true); } - + } void @@ -472,27 +490,43 @@ ImageFileView::OnPlotCol (wxCommandEvent& event) // os << "No column selected. Please use left mouse button on image to select column\n"; return; } - + const ImageFile& rIF = dynamic_cast(GetDocument())->getImageFile(); ImageFileArrayConst v = rIF.getArray(); int nx = rIF.nx(); int ny = rIF.ny(); - + if (v != NULL && xCursor < nx) { - double* pVec = new double [ny]; + double* pX = new double [ny]; + double* pY = new double [ny]; double minVal = v[xCursor][0]; double maxVal = minVal; for (int i = 0; i < ny; i++) { - if (minVal < v[xCursor][i]) - minVal = v[xCursor][i]; - else if (maxVal > v[xCursor][i]) - maxVal = v[xCursor][i]; - pVec[i] = v[xCursor][i]; + double y = v[xCursor][i]; + if (minVal < y) + minVal = y; + else if (maxVal > y) + maxVal = y; + pX[i] = i; + pY[i] = y; } - - VectorPlotCurve* plotCurve = new VectorPlotCurve (pVec, ny, minVal, maxVal); - wxPlotWindow plotWindow (m_canvas, NULL, wxPoint(0,0), wxSize(500,300)); - plotWindow.Add (reinterpret_cast(plotCurve)); + PlotFileDocument* pPlotDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT)); + if (! pPlotDoc) { + sys_error (ERR_SEVERE, "Internal error: unable to create Plot file"); + } else { + PlotFile& rPlotFile = pPlotDoc->getPlotFile(); + std::ostringstream title; + title << "Column " << xCursor; + rPlotFile.setTitle(title.str()); + rPlotFile.setXLabel("Row"); + rPlotFile.setYLabel("Pixel Value"); + rPlotFile.setCurveSize (2, nx); + rPlotFile.addColumn (0, pX); + rPlotFile.addColumn (1, pY); + } + delete pX; + delete pY; + pPlotDoc->Modify(true); } } @@ -573,7 +607,11 @@ PhantomView::OnProjections (wxCommandEvent& event) if (m_iDefaultNDet > 0 && m_iDefaultNView > 0 && sGeometry != "") { const Phantom& rPhantom = GetDocument()->getPhantom(); - ProjectionFileDocument* pProjectionDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.pj", wxDOC_SILENT)); + ProjectionFileDocument* pProjectionDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.pj", wxDOC_SILENT)); + if (! pProjectionDoc) { + sys_error (ERR_SEVERE, "Unable to create projection document"); + return; + } Projections& rProj = pProjectionDoc->getProjections(); Scanner theScanner (rPhantom, sGeometry.c_str(), m_iDefaultNDet, m_iDefaultNView, m_iDefaultNSample, m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultFieldOfView); if (theScanner.fail()) { @@ -650,7 +688,11 @@ PhantomView::OnRasterize (wxCommandEvent& event) nSamples = 1; if (xSize > 0 && ySize > 0) { const Phantom& rPhantom = GetDocument()->getPhantom(); - ImageFileDocument* pRasterDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT)); + ImageFileDocument* pRasterDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT)); + if (! pRasterDoc) { + sys_error (ERR_SEVERE, "Unable to create image file"); + return; + } ImageFile& imageFile = pRasterDoc->getImageFile(); imageFile.setArraySize (xSize, ySize); @@ -885,7 +927,11 @@ ProjectionFileView::OnReconstruct (wxCommandEvent& event) m_iDefaultBackprojector = Backprojector::convertBackprojectNameToID (optBackprojectName.c_str()); m_iDefaultTrace = dialogReconstruction.getTrace(); if (m_iDefaultNX > 0 && m_iDefaultNY > 0) { - ImageFileDocument* pReconDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT)); + ImageFileDocument* pReconDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT)); + if (pReconDoc) { + sys_error (ERR_SEVERE, "Unable to create image file"); + return; + } ImageFile& imageFile = pReconDoc->getImageFile(); const Projections& rProj = GetDocument()->getProjections(); imageFile.setArraySize (m_iDefaultNX, m_iDefaultNY); @@ -1126,7 +1172,6 @@ ProjectionFileView::OnClose (bool deleteWindow) // PlotFileCanvas - PlotFileCanvas::PlotFileCanvas (PlotFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style) : wxScrolledWindow(frame, -1, pos, size, style) { @@ -1138,7 +1183,8 @@ PlotFileCanvas::OnDraw(wxDC& dc) { if (m_pView) m_pView->OnDraw(& dc); -} +} + // PlotFileView @@ -1146,6 +1192,8 @@ IMPLEMENT_DYNAMIC_CLASS(PlotFileView, wxView) BEGIN_EVENT_TABLE(PlotFileView, wxView) EVT_MENU(PJMENU_FILE_PROPERTIES, PlotFileView::OnProperties) +EVT_MENU(PLOTMENU_VIEW_SCALE_MINMAX, PlotFileView::OnScaleMinMax) +EVT_MENU(PLOTMENU_VIEW_SCALE_AUTO, PlotFileView::OnScaleAuto) END_EVENT_TABLE() PlotFileView::PlotFileView(void) @@ -1160,7 +1208,7 @@ PlotFileView::~PlotFileView(void) void PlotFileView::OnProperties (wxCommandEvent& event) { - const PlotFile& rProj = GetDocument()->getPlot(); + const PlotFile& rProj = GetDocument()->getPlotFile(); std::ostringstream os; os << "Columns: " << rProj.getNumColumns() << ", Records: " << rProj.getNumRecords() << "\n"; *theApp->getLog() << os.str().c_str(); @@ -1169,6 +1217,57 @@ PlotFileView::OnProperties (wxCommandEvent& event) } +void +PlotFileView::OnScaleAuto (wxCommandEvent& event) +{ + const PlotFile& rPlotFile = GetDocument()->getPlotFile(); + double min, max, mean, mode, median, stddev; + rPlotFile.statistics (1, min, max, mean, mode, median, stddev); + DialogAutoScaleParameters dialogAutoScale (m_frame, mean, mode, median, stddev, m_dAutoScaleFactor); + int iRetVal = dialogAutoScale.ShowModal(); + if (iRetVal == wxID_OK) { + m_bMinSpecified = true; + m_bMaxSpecified = true; + double dMin, dMax; + if (dialogAutoScale.getMinMax (&dMin, &dMax)) { + m_dMinPixel = dMin; + m_dMaxPixel = dMax; + m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor(); + OnUpdate (this, NULL); + } + } +} + +void +PlotFileView::OnScaleMinMax (wxCommandEvent& event) +{ + const PlotFile& rPlotFile = GetDocument()->getPlotFile(); + double min, max; + + if (! m_bMinSpecified && ! m_bMaxSpecified) { + if (! rPlotFile.getMinMax (1, min, max)) { + *theApp->getLog() << "Error: unable to find Min/Max\n"; + return; + } + } + + if (m_bMinSpecified) + min = m_dMinPixel; + if (m_bMaxSpecified) + max = m_dMaxPixel; + + DialogGetMinMax dialogMinMax (m_frame, "Set Y-axis Minimum & Maximum", min, max); + int retVal = dialogMinMax.ShowModal(); + if (retVal == wxID_OK) { + m_bMinSpecified = true; + m_bMaxSpecified = true; + m_dMinPixel = dialogMinMax.getMinimum(); + m_dMaxPixel = dialogMinMax.getMaximum(); + OnUpdate (this, NULL); + } +} + + PlotFileCanvas* PlotFileView::CreateCanvas (wxView *view, wxFrame *parent) { @@ -1205,6 +1304,10 @@ PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view) file_menu->Append(wxID_PRINT_SETUP, "Print &Setup..."); file_menu->Append(wxID_PREVIEW, "Print Pre&view"); + wxMenu *view_menu = new wxMenu; + view_menu->Append(PLOTMENU_VIEW_SCALE_MINMAX, "Display Scale &Set..."); + view_menu->Append(PLOTMENU_VIEW_SCALE_AUTO, "Display Scale &Auto..."); + wxMenu *help_menu = new wxMenu; help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents"); help_menu->AppendSeparator(); @@ -1212,7 +1315,8 @@ PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view) wxMenuBar *menu_bar = new wxMenuBar; - menu_bar->Append(file_menu, "&File"); + menu_bar->Append(file_menu, "&File"); + menu_bar->Append(view_menu, "&View"); menu_bar->Append(help_menu, "&Help"); subframe->SetMenuBar(menu_bar); @@ -1229,6 +1333,10 @@ PlotFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) m_frame = CreateChildFrame(doc, this); SetFrame(m_frame); + m_bMinSpecified = false; + m_bMaxSpecified = false; + m_dAutoScaleFactor = 1.; + int width, height; m_frame->GetClientSize(&width, &height); m_frame->SetTitle ("Plot File"); @@ -1249,25 +1357,71 @@ PlotFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) void PlotFileView::OnDraw (wxDC* dc) { - if (m_bitmap.Ok()) - dc->DrawBitmap (m_bitmap, 0, 0, false); + const PlotFile& rPlotFile = GetDocument()->getPlotFile(); + const int iNColumns = rPlotFile.getNumColumns(); + const int iNRecords = rPlotFile.getNumRecords(); + + if (iNColumns > 0 && iNRecords > 0) { + int xsize, ysize; + m_canvas->GetClientSize (&xsize, &ysize); + SGPDriver driver (dc, xsize, ysize); + SGP sgp (driver); + const PlotFile& rPhantom = GetDocument()->getPlotFile(); + EZPlot plot (sgp); + + if (! rPlotFile.getTitle().empty()) { + std::string s("title "); + s += rPlotFile.getTitle(); + plot.ezset (s); + } + if (! rPlotFile.getXLabel().empty()) { + std::string s("xlabel "); + s += rPlotFile.getXLabel(); + plot.ezset (s); + } + if (! rPlotFile.getYLabel().empty()) { + std::string s("ylabel "); + s += rPlotFile.getYLabel(); + plot.ezset (s); + } + + if (m_bMinSpecified) { + std::ostringstream os; + os << "ymin " << m_dMinPixel; + plot.ezset (os.str()); + } + + if (m_bMaxSpecified) { + std::ostringstream os; + os << "ymax " << m_dMaxPixel; + plot.ezset (os.str()); + } + + plot.ezset("box"); + plot.ezset("grid"); + + double* pdXaxis = new double [iNRecords]; + rPlotFile.getColumn (0, pdXaxis); + + double* pdY = new double [iNRecords]; + for (int iCol = 1; iCol < iNColumns; iCol++) { + rPlotFile.getColumn (iCol, pdY); + plot.addCurve (pdXaxis, pdY, iNRecords); + } + + delete pdXaxis; + delete pdY; + + plot.plot(); + } } void PlotFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) ) { - const PlotFile& rPlot = GetDocument()->getPlotFile(); - const int iNColumns = rPlot.getNumColumns(); - const int iNRecords = rPlot.getNumRecords(); - if (iNColumns > 0 && iNRecords > 0) { -// int xSize, ySize; -// m_frame->SetClientSize (xSize, ySize); -// m_canvas->SetScrollbars (20, 20, nDet/20, nView/20); - } - if (m_canvas) - m_canvas->Refresh(); + m_canvas->Refresh(); } bool @@ -1281,14 +1435,14 @@ PlotFileView::OnClose (bool deleteWindow) m_canvas = NULL; wxString s(wxTheApp->GetAppName()); if (m_frame) - m_frame->SetTitle(s); + m_frame->SetTitle(s); SetFrame(NULL); Activate(false); if (deleteWindow) { - delete m_frame; - return true; + delete m_frame; + return true; } return true; }