8a555ce2cc4e705ebb9708a8c63a8418edc8cca4
[ctsim.git] / src / views.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:          view.cpp
5 **   Purpose:       View & Canvas routines for CTSim program
6 **   Programmer:    Kevin Rosenberg
7 **   Date Started:  July 2000
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2000 Kevin Rosenberg
11 **
12 **  $Id: views.cpp,v 1.1 2000/07/13 07:01:59 kevin Exp $
13 **
14 **  This program is free software; you can redistribute it and/or modify
15 **  it under the terms of the GNU General Public License (version 2) as
16 **  published by the Free Software Foundation.
17 **
18 **  This program is distributed in the hope that it will be useful,
19 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 **  GNU General Public License for more details.
22 **
23 **  You should have received a copy of the GNU General Public License
24 **  along with this program; if not, write to the Free Software
25 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 ******************************************************************************/
27
28 #ifdef __GNUG__
29 // #pragma implementation
30 #endif
31
32 // For compilers that support precompilation, includes "wx/wx.h".
33 #include "wx/wxprec.h"
34
35 #ifdef __BORLANDC__
36 #pragma hdrstop
37 #endif
38
39 #ifndef WX_PRECOMP
40 #include "wx/wx.h"
41 #endif
42
43 #if !wxUSE_DOC_VIEW_ARCHITECTURE
44 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
45 #endif
46
47 #include "ctsim.h"
48 #include "docs.h"
49 #include "views.h"
50 #include <sstream>
51 #include "ct.h"
52 //#include "imagefile.h"
53 //#include "phantom.h"
54 //#include "scanner.h"
55 //#include "projections.h"
56
57 // ImageFileCanvas
58
59 BEGIN_EVENT_TABLE(ImageFileCanvas, wxScrolledWindow)
60     EVT_MOUSE_EVENTS(ImageFileCanvas::OnMouseEvent)
61 END_EVENT_TABLE()
62
63
64 ImageFileCanvas::ImageFileCanvas (ImageFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
65   : wxScrolledWindow(frame, -1, pos, size, style)
66 {
67     m_pView = v;
68 }
69
70 void 
71 ImageFileCanvas::OnDraw(wxDC& dc)
72 {
73     if (m_pView)
74         m_pView->OnDraw(& dc);
75 }
76
77 void 
78 ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
79 {
80     if (! m_pView)
81         return;
82     
83     wxClientDC dc(this);
84     PrepareDC(dc);
85     
86     dc.SetPen(*wxBLACK_PEN);
87     
88     wxPoint pt(event.GetLogicalPosition(dc));
89
90     if (event.LeftUp())
91       cout << pt.x << "x" << pt.y << endl;
92 }
93
94
95 // ImageFileView
96
97 IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView)
98
99 BEGIN_EVENT_TABLE(ImageFileView, wxView)
100     EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties)
101 END_EVENT_TABLE()
102
103 bool ImageFileView::m_bPColoursInitialized = false;
104 wxColour* ImageFileView::m_pColours[256];
105
106 ImageFileView::ImageFileView(void) 
107   : wxView(), m_canvas(NULL), m_frame(NULL), m_bMinSpecified(false), m_bMaxSpecified(false)
108 {
109     if (! m_bPColoursInitialized) {
110         for (int i = 0; i < 256; i++)
111             m_pColours[i] = new wxColour (i, i, i);
112
113         m_bPColoursInitialized = true;
114     }
115 }
116
117 ImageFileView::~ImageFileView(void)
118 {
119 }
120
121 void
122 ImageFileView::OnProperties (wxCommandEvent& event)
123 {
124   double min, max, mean, mode, median, stddev;
125   const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
126   const string& rFilename = rIF.getFilename();
127   rIF.statistics (min, max, mean, mode, median, stddev);
128   ostringstream os;
129   os << "file: " << rFilename << "\nmin: "<<min<<"\nmax: "<<max<<"\nmean: "<<mean<<"\nmode: "<<mode<<"\nstddev: "<<stddev;
130   wxMessageBox(os.str().c_str(), "Image Properties", wxOK | wxICON_INFORMATION, m_frame);
131 }
132
133
134 ImageFileCanvas* 
135 ImageFileView::CreateCanvas (wxView *view, wxFrame *parent)
136 {
137     ImageFileCanvas* pCanvas;
138     int width, height;
139     parent->GetClientSize(&width, &height);
140     
141     pCanvas = new ImageFileCanvas (dynamic_cast<ImageFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
142     
143     pCanvas->SetScrollbars(20, 20, 50, 50);
144     pCanvas->SetBackgroundColour(*wxWHITE);
145     pCanvas->Clear();
146     
147     return pCanvas;
148 }
149
150 wxFrame*
151 ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
152 {
153     wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, dynamic_cast<CTSimApp*>(wxTheApp)->getMainFrame(), -1, "ImageFile Frame", wxPoint(10, 10), wxSize(300, 300), wxDEFAULT_FRAME_STYLE);
154     
155     wxMenu *file_menu = new wxMenu;
156     
157     file_menu->Append(wxID_NEW, "&New...");
158     file_menu->Append(wxID_OPEN, "&Open...");
159     file_menu->Append(wxID_CLOSE, "&Close");
160     file_menu->Append(wxID_SAVE, "&Save");
161     file_menu->Append(wxID_SAVEAS, "Save &As...");
162     
163     file_menu->AppendSeparator();
164     file_menu->Append(IFMENU_FILE_PROPERTIES, "P&roperties");
165
166     file_menu->AppendSeparator();
167     file_menu->Append(wxID_PRINT, "&Print...");
168     file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
169     file_menu->Append(wxID_PREVIEW, "Print Pre&view");
170     
171     wxMenu *help_menu = new wxMenu;
172     help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
173     
174     wxMenuBar *menu_bar = new wxMenuBar;
175     
176     menu_bar->Append(file_menu, "&File");
177     menu_bar->Append(help_menu, "&Help");
178     
179     subframe->SetMenuBar(menu_bar);
180     
181     subframe->Centre(wxBOTH);
182     
183     return subframe;
184 }
185
186
187 bool 
188 ImageFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
189 {
190     m_frame = CreateChildFrame(doc, this);
191     
192     m_bMinSpecified = false;
193     m_bMaxSpecified = false;
194
195     int width, height;
196     m_frame->GetClientSize(&width, &height);
197     m_frame->SetTitle("ImageFileView");
198     m_canvas = CreateCanvas(this, m_frame);
199
200 #ifdef __X__
201     int x, y;  // X requires a forced resize
202     m_frame->GetSize(&x, &y);
203     m_frame->SetSize(-1, -1, x, y);
204 #endif
205
206     m_frame->Show(true);
207     Activate(true);
208     
209     return true;
210 }
211
212 void 
213 ImageFileView::OnDraw (wxDC* dc)
214 {
215     const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
216   dc->Blit(static_cast<wxCoord>(0), static_cast<wxCoord>(0), static_cast<wxCoord>(rIF.nx()), static_cast<wxCoord>(rIF.ny()), &m_memoryDC, static_cast<wxCoord>(0), static_cast<wxCoord>(0));
217 }
218
219
220 void 
221 ImageFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
222 {
223     const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
224     ImageFileArrayConst v = rIF.getArray();
225     int nx = rIF.nx();
226     int ny = rIF.ny();
227     if (v != NULL && nx != 0 && ny != 0) {
228         if (! m_bMinSpecified || ! m_bMaxSpecified) {
229             double min, max;
230             rIF.getMinMax (min, max);
231             if (! m_bMinSpecified)
232                 m_minPixel = min;
233             if (! m_bMaxSpecified)
234                 m_maxPixel = max;
235         }
236         double scaleWidth = m_maxPixel - m_minPixel;
237     
238         m_pBitmap = new wxBitmap (rIF.nx(), rIF.ny());
239         m_memoryDC.SelectObject (*m_pBitmap);
240         m_memoryDC.BeginDrawing();
241
242         wxPen pen (*m_pColours[128], 1, wxDOT);
243         m_memoryDC.SetPen (pen);
244         for (int ix = 0; ix < nx; ix++) {
245             for (int iy = 0; iy < ny; iy++) {
246                 double scaleValue = ((v[ix][iy] - m_minPixel) / scaleWidth) * 255;
247                 int intensity = static_cast<int>(scaleValue + 0.5);
248                 intensity = clamp (intensity, 0, 255);
249                 pen.SetColour (*m_pColours[intensity]);
250                 m_memoryDC.SetPen(pen);
251                 m_memoryDC.DrawPoint(ix, ny - iy);
252             }
253         }
254     } 
255     m_memoryDC.EndDrawing();
256
257     if (m_canvas) {
258         //      m_canvas->SetScrollbars (50, 50, nx / 50, ny / 50, 0, 0, false);
259         m_canvas->Refresh();
260     }
261
262 #ifdef __WXMSW__
263   if (m_canvas)
264     m_canvas->Refresh();
265 #else
266   if (m_canvas) {
267     wxClientDC dc(m_canvas);
268     dc.Clear();
269     OnDraw (&dc);
270   }
271 #endif
272 }
273
274 bool 
275 ImageFileView::OnClose (bool deleteWindow)
276 {
277     if (!GetDocument()->Close())
278         return false;
279
280     m_canvas->Clear();
281     m_canvas->m_pView = NULL;
282     m_canvas = NULL;
283     wxString s(wxTheApp->GetAppName());
284     if (m_frame)
285       m_frame->SetTitle(s);
286     SetFrame(NULL);
287
288     Activate(false);
289     
290     if (deleteWindow) {
291         delete m_frame;
292         return true;
293     }
294     return true;
295 }
296
297
298
299 // ProjectionFileCanvas
300
301 ProjectionFileCanvas::ProjectionFileCanvas (ProjectionFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
302   : wxScrolledWindow(frame, -1, pos, size, style)
303 {
304     m_pView = v;
305 }
306
307 void 
308 ProjectionFileCanvas::OnDraw(wxDC& dc)
309 {
310     if (m_pView)
311         m_pView->OnDraw(& dc);
312 }
313
314 // ProjectionFileView
315
316 IMPLEMENT_DYNAMIC_CLASS(ProjectionFileView, wxView)
317
318 BEGIN_EVENT_TABLE(ProjectionFileView, wxView)
319     EVT_MENU(PJMENU_FILE_PROPERTIES, ProjectionFileView::OnProperties)
320     EVT_MENU(PJMENU_FILE_RECONSTRUCT, ProjectionFileView::OnReconstruct)
321 END_EVENT_TABLE()
322
323 bool ProjectionFileView::m_bPColoursInitialized = false;
324 wxColour* ProjectionFileView::m_pColours[256];
325
326 ProjectionFileView::ProjectionFileView(void) 
327   : wxView(), m_canvas(NULL), m_frame(NULL)
328 {
329     if (! m_bPColoursInitialized) {
330         for (int i = 0; i < 256; i++)
331             m_pColours[i] = new wxColour (i, i, i);
332
333         m_bPColoursInitialized = true;
334     }
335 }
336
337 ProjectionFileView::~ProjectionFileView(void)
338 {
339 }
340
341 void
342 ProjectionFileView::OnProperties (wxCommandEvent& event)
343 {
344   const Projections& rProj = dynamic_cast<ProjectionFileDocument*>(GetDocument())->getProjections();
345   const string& rFilename = rProj.getFilename();
346   ostringstream os;
347   os << "file: " << rFilename << "\nDetectors: " << rProj.nDet() << "\nViews: " << rProj.nView();
348   wxMessageBox(os.str().c_str(), "Projection Properties", wxOK | wxICON_INFORMATION, m_frame);
349 }
350
351
352 void
353 ProjectionFileView::OnReconstruct (wxCommandEvent& event)
354 {
355   const Projections& rProj = dynamic_cast<ProjectionFileDocument*>(GetDocument())->getProjections();
356   const string& rFilename = rProj.getFilename();
357   ostringstream os;
358   os << "Reconstruct file " << rFilename;
359   wxMessageBox(os.str().c_str(), "Reconstruction Dialog", wxOK | wxICON_INFORMATION, m_frame);
360 }
361
362
363 ProjectionFileCanvas* 
364 ProjectionFileView::CreateCanvas (wxView *view, wxFrame *parent)
365 {
366     ProjectionFileCanvas* pCanvas;
367     int width, height;
368     parent->GetClientSize(&width, &height);
369     
370     pCanvas = new ProjectionFileCanvas (dynamic_cast<ProjectionFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
371     
372     pCanvas->SetScrollbars(20, 20, 50, 50);
373     pCanvas->SetBackgroundColour(*wxWHITE);
374     pCanvas->Clear();
375     
376     return pCanvas;
377 }
378
379 wxFrame*
380 ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
381 {
382     wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, dynamic_cast<CTSimApp*>(wxTheApp)->getMainFrame(), -1, "ProjectionFile Frame", wxPoint(10, 10), wxSize(300, 300), wxDEFAULT_FRAME_STYLE);
383     
384     wxMenu *file_menu = new wxMenu;
385     
386     file_menu->Append(wxID_NEW, "&New...");
387     file_menu->Append(wxID_OPEN, "&Open...");
388     file_menu->Append(wxID_CLOSE, "&Close");
389     file_menu->Append(wxID_SAVE, "&Save");
390     file_menu->Append(wxID_SAVEAS, "Save &As...");
391     
392     file_menu->AppendSeparator();
393     file_menu->Append(PJMENU_FILE_RECONSTRUCT, "R&econstuct");
394     file_menu->Append(PJMENU_FILE_PROPERTIES, "P&roperties");
395
396     file_menu->AppendSeparator();
397     file_menu->Append(wxID_PRINT, "&Print...");
398     file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
399     file_menu->Append(wxID_PREVIEW, "Print Pre&view");
400     
401     wxMenu *help_menu = new wxMenu;
402     help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
403     
404     wxMenuBar *menu_bar = new wxMenuBar;
405     
406     menu_bar->Append(file_menu, "&File");
407     menu_bar->Append(help_menu, "&Help");
408     
409     subframe->SetMenuBar(menu_bar);
410     
411     subframe->Centre(wxBOTH);
412     
413     return subframe;
414 }
415
416
417 bool 
418 ProjectionFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
419 {
420     m_frame = CreateChildFrame(doc, this);
421     
422     int width, height;
423     m_frame->GetClientSize(&width, &height);
424     m_frame->SetTitle("ProjectionFileView");
425     m_canvas = CreateCanvas(this, m_frame);
426
427 #ifdef __X__
428     int x, y;  // X requires a forced resize
429     m_frame->GetSize(&x, &y);
430     m_frame->SetSize(-1, -1, x, y);
431 #endif
432
433     m_frame->Show(true);
434     Activate(true);
435     
436     return true;
437 }
438
439 void 
440 ProjectionFileView::OnDraw (wxDC* dc)
441 {
442     const Projections& rProj = dynamic_cast<ProjectionFileDocument*>(GetDocument())->getProjections();
443   dc->Blit(static_cast<wxCoord>(0), static_cast<wxCoord>(0), static_cast<wxCoord>(rProj.nDet()), static_cast<wxCoord>(rProj.nView()), &m_memoryDC, static_cast<wxCoord>(0), static_cast<wxCoord>(0));
444 }
445
446
447 void 
448 ProjectionFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
449 {
450     const Projections& rProj = dynamic_cast<ProjectionFileDocument*>(GetDocument())->getProjections();
451     const DetectorArray& detarray = rProj.getDetectorArray (0);
452     const DetectorValue* detval = detarray.detValues();
453     double min = detval[0];
454     double max = detval[0];
455     for (int iy = 0; iy < rProj.nView(); iy++) {
456       const DetectorArray& detarray = rProj.getDetectorArray (iy);
457       detval = detarray.detValues();
458       for (int ix = 0; ix < rProj.nDet(); ix++) {
459         if (min > detval[ix])
460           min = detval[ix];
461         else if (max < detval[ix])
462           max = detval[ix];
463       }
464     }
465
466     double scaleWidth = max - min;
467     
468     m_pBitmap = new wxBitmap (rProj.nDet(), rProj.nView());
469     m_memoryDC.SelectObject (*m_pBitmap);
470     m_memoryDC.BeginDrawing();
471
472     wxPen pen (*m_pColours[128], 1, wxDOT);
473     m_memoryDC.SetPen (pen);
474     for (int iy = 0; iy < rProj.nView(); iy++) {
475       const DetectorArray& detarray = rProj.getDetectorArray (iy);
476       detval = detarray.detValues();
477       for (int ix = 0; ix < rProj.nDet(); ix++) {
478         double scaleValue = ((detval[ix] - min) / scaleWidth) * 255;
479         int intensity = static_cast<int>(scaleValue + 0.5);
480         intensity = clamp (intensity, 0, 255);
481         pen.SetColour (*m_pColours[intensity]);
482         m_memoryDC.SetPen(pen);
483         m_memoryDC.DrawPoint(ix, iy);
484       }
485     }
486     m_memoryDC.EndDrawing();
487
488     if (m_canvas) {
489         //      m_canvas->SetScrollbars (50, 50, nx / 50, ny / 50, 0, 0, false);
490         m_canvas->Refresh();
491     }
492
493 #ifdef __WXMSW__
494   if (m_canvas)
495     m_canvas->Refresh();
496 #else
497   if (m_canvas) {
498     wxClientDC dc(m_canvas);
499     dc.Clear();
500     OnDraw (&dc);
501   }
502 #endif
503 }
504
505 bool 
506 ProjectionFileView::OnClose (bool deleteWindow)
507 {
508     if (!GetDocument()->Close())
509         return false;
510
511     m_canvas->Clear();
512     m_canvas->m_pView = NULL;
513     m_canvas = NULL;
514     wxString s(wxTheApp->GetAppName());
515     if (m_frame)
516       m_frame->SetTitle(s);
517     SetFrame(NULL);
518
519     Activate(false);
520     
521     if (deleteWindow) {
522         delete m_frame;
523         return true;
524     }
525     return true;
526 }
527