00001
00002
00003
00004
00005
00006
00007
00008
00010
00011
00012
00013
00014
00015
00016
00017 #include "wx/wxprec.h"
00018 #ifdef __BORLANDC__
00019 #pragma hdrstop
00020 #endif
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "mathplot.h"
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 IMPLEMENT_ABSTRACT_CLASS(mpLayer, wxObject)
00052
00053 mpLayer::mpLayer()
00054 {
00055
00056
00057
00058
00059 wxFont ff( *wxNORMAL_FONT);
00060 wxPen pp( *wxBLACK_PEN);
00061 SetPen( pp );
00062 SetFont( ff );
00063
00064 }
00065
00066
00067
00068
00069
00070 IMPLEMENT_ABSTRACT_CLASS(mpFX, mpLayer)
00071
00072 mpFX::mpFX(wxString name, int flags)
00073 {
00074 SetName(name);
00075 m_flags = flags;
00076 }
00077
00078 void mpFX::Plot(wxDC & dc, mpWindow & w)
00079 {
00080 dc.SetPen( m_pen);
00081
00082 if (m_pen.GetWidth() <= 1)
00083 {
00084 for (wxCoord i = -(w.GetScrX()>>1); i < (w.GetScrX()>>1); ++i)
00085 {
00086 dc.DrawPoint(i, (wxCoord) ((w.GetPosY() - GetY( (double)i / w.GetScaleX() + w.GetPosX()) ) * w.GetScaleY()));
00087 }
00088 }
00089 else
00090 {
00091 for (wxCoord i = -(w.GetScrX()>>1); i < (w.GetScrX()>>1); ++i)
00092 {
00093 wxCoord c = (wxCoord) ((w.GetPosY() - GetY( (double)i / w.GetScaleX() + w.GetPosX()) ) * w.GetScaleY());
00094 dc.DrawLine( i, c, i, c);
00095 }
00096 }
00097
00098 if (!m_name.IsEmpty())
00099 {
00100 dc.SetFont(m_font);
00101
00102 wxCoord tx, ty;
00103 dc.GetTextExtent(m_name, &tx, &ty);
00104
00105 if ((m_flags & mpALIGNMASK) == mpALIGN_RIGHT)
00106 tx = (w.GetScrX()>>1) - tx - 8;
00107 else if ((m_flags & mpALIGNMASK) == mpALIGN_CENTER)
00108 tx = -tx/2;
00109 else
00110 tx = -(w.GetScrX()>>1) + 8;
00111
00112 dc.DrawText( m_name, tx, (wxCoord) ((w.GetPosY() - GetY( (double)tx / w.GetScaleX() + w.GetPosX())) * w.GetScaleY()) );
00113 }
00114 }
00115
00116 IMPLEMENT_ABSTRACT_CLASS(mpFY, mpLayer)
00117
00118 mpFY::mpFY(wxString name, int flags)
00119 {
00120 SetName(name);
00121 m_flags = flags;
00122 }
00123
00124 void mpFY::Plot(wxDC & dc, mpWindow & w)
00125 {
00126 dc.SetPen( m_pen);
00127
00128 wxCoord i;
00129
00130 if (m_pen.GetWidth() <= 1)
00131 {
00132 for (i = -(w.GetScrY()>>1); i < (w.GetScrY()>>1); ++i)
00133 {
00134 dc.DrawPoint((wxCoord) ((GetX( (double)i / w.GetScaleY() + w.GetPosY()) - w.GetPosX()) * w.GetScaleX()), -i);
00135 }
00136 }
00137 else
00138 {
00139 for (i = -(w.GetScrY()>>1); i < (w.GetScrY()>>1); ++i)
00140 {
00141 wxCoord c = (wxCoord) ((GetX( (double)i / w.GetScaleY() + w.GetPosY()) - w.GetPosX()) * w.GetScaleX());
00142 dc.DrawLine(c, -i, c, -i);
00143 }
00144 }
00145
00146 if (!m_name.IsEmpty())
00147 {
00148 dc.SetFont(m_font);
00149
00150 wxCoord tx, ty;
00151 dc.GetTextExtent(m_name, &tx, &ty);
00152
00153 if ((m_flags & mpALIGNMASK) == mpALIGN_TOP)
00154 ty = (w.GetScrY()>>1) - 8;
00155 else if ((m_flags & mpALIGNMASK) == mpALIGN_CENTER)
00156 ty = 16 - ty/2;
00157 else
00158 ty = -(w.GetScrY()>>1) + 8;
00159
00160 dc.DrawText( m_name, (wxCoord) ((GetX( (double)i / w.GetScaleY() + w.GetPosY()) - w.GetPosX()) * w.GetScaleX()), -ty);
00161 }
00162 }
00163
00164 IMPLEMENT_ABSTRACT_CLASS(mpFXY, mpLayer)
00165
00166 mpFXY::mpFXY(wxString name, int flags)
00167 {
00168 SetName(name);
00169 m_flags = flags;
00170 }
00171
00172 void mpFXY::Plot(wxDC & dc, mpWindow & w)
00173 {
00174 dc.SetPen( m_pen);
00175
00176 double x, y;
00177 Rewind();
00178
00179
00180
00181
00182 if (m_pen.GetWidth() <= 1)
00183 {
00184 while (GetNextXY(x, y))
00185 {
00186 dc.DrawPoint( (wxCoord) ((x - w.GetPosX()) * w.GetScaleX()) ,
00187 (wxCoord) ((w.GetPosY() - y) * w.GetScaleY()) );
00188 }
00189 }
00190 else
00191 {
00192 while (GetNextXY(x, y))
00193 {
00194 wxCoord cx = (wxCoord) ((x - w.GetPosX()) * w.GetScaleX());
00195 wxCoord cy = (wxCoord) ((w.GetPosY() - y) * w.GetScaleY());
00196 dc.DrawLine(cx, cy, cx, cy);
00197 }
00198 }
00199
00200 if (!m_name.IsEmpty())
00201 {
00202 dc.SetFont(m_font);
00203
00204 wxCoord tx, ty;
00205 dc.GetTextExtent(m_name, &tx, &ty);
00206
00207
00208 {
00209 const int sx = w.GetScrX()>>1;
00210 const int sy = w.GetScrY()>>1;
00211
00212 if ((m_flags & mpALIGNMASK) == mpALIGN_NE)
00213 {
00214 tx = sx - tx - 8;
00215 ty = -sy + 8;
00216 }
00217 else if ((m_flags & mpALIGNMASK) == mpALIGN_NW)
00218 {
00219 tx = -sx + 8;
00220 ty = -sy + 8;
00221 }
00222 else if ((m_flags & mpALIGNMASK) == mpALIGN_SW)
00223 {
00224 tx = -sx + 8;
00225 ty = sy - 8 - ty;
00226 }
00227 else
00228 {
00229 tx = sx - tx - 8;
00230 ty = sy - 8 - ty;
00231 }
00232 }
00233
00234
00235
00236
00237 dc.DrawText( m_name, tx, ty);
00238 }
00239 }
00240
00241
00242
00243
00244
00245 #define mpLN10 2.3025850929940456840179914546844
00246
00247 IMPLEMENT_CLASS(mpScaleX, mpLayer)
00248
00249 mpScaleX::mpScaleX(wxString name)
00250 {
00251 SetName(name);
00252
00253
00254
00255 wxFont ff( *wxSMALL_FONT);
00256 wxPen pp( *wxGREY_PEN);
00257 SetPen( pp );
00258 SetFont( ff );
00259 }
00260
00261 void mpScaleX::Plot(wxDC & dc, mpWindow & w)
00262 {
00263 dc.SetPen( m_pen);
00264 dc.SetFont( m_font);
00265
00266 const int orgy = (int)(w.GetPosY() * w.GetScaleY());
00267 const int extend = w.GetScrX()/2;
00268
00269 dc.DrawLine( -extend, orgy, extend, orgy);
00270
00271 const double dig = floor( log( 128.0 / w.GetScaleX() ) / mpLN10 );
00272 const double step = exp( mpLN10 * dig);
00273 const double end = w.GetPosX() + (double)extend / w.GetScaleX();
00274
00275 wxCoord tx, ty;
00276 wxString s;
00277 wxString fmt;
00278 int tmp = (int)dig;
00279 if (tmp>=1)
00280 {
00281 fmt = wxT("%.f");
00282 }
00283 else
00284 {
00285 tmp=8-tmp;
00286 fmt.Printf(wxT("%%.%df"), tmp >= -1 ? 2 : -tmp);
00287 }
00288
00289 double n = floor( (w.GetPosX() - (double)extend / w.GetScaleX()) / step ) * step ;
00290
00291 tmp=-65535;
00292 for (;n < end; n += step)
00293 {
00294 const int p = (int)((n - w.GetPosX()) * w.GetScaleX());
00295 dc.DrawLine( p, orgy, p, orgy+4);
00296
00297 s.Printf(fmt, n);
00298 dc.GetTextExtent(s, &tx, &ty);
00299 if ((p-tx/2-tmp) > 64)
00300 {
00301 dc.DrawText( s, p-tx/2, orgy+4);
00302 tmp=p+tx/2;
00303 }
00304 }
00305
00306 dc.GetTextExtent(m_name, &tx, &ty);
00307 dc.DrawText( m_name, extend - tx - 4, orgy + 4 + ty);
00308 }
00309
00310 IMPLEMENT_CLASS(mpScaleY, mpLayer)
00311
00312 mpScaleY::mpScaleY(wxString name)
00313 {
00314 SetName(name);
00315
00316
00317 wxFont ff( *wxSMALL_FONT);
00318 wxPen pp( *wxGREY_PEN);
00319 SetPen( pp );
00320 SetFont( ff );
00321 }
00322
00323 void mpScaleY::Plot(wxDC & dc, mpWindow & w, int orgy)
00324 {
00325 dc.SetPen( m_pen);
00326 dc.SetFont( m_font);
00327
00328 const int orgx = -(int)(w.GetPosX() * w.GetScaleX());
00329 const int extend = w.GetScrY()/2;
00330
00331 double sizedc = dc.GetSize().GetHeight()-orgy;
00332
00333 dc.DrawLine( orgx, GetYTranslated(sizedc, -extend), orgx, GetYTranslated(sizedc, extend));
00334
00335 const double dig = floor( log( 128.0 / w.GetScaleY() ) / mpLN10 );
00336 const double step = exp( mpLN10 * dig);
00337 const double end = w.GetPosY() + (double)extend / w.GetScaleY();
00338
00339 wxCoord tx, ty;
00340 wxString s;
00341 wxString fmt;
00342 int tmp = (int)dig;
00343 if (tmp>=1)
00344 {
00345 fmt = wxT("%.f");
00346 }
00347 else
00348 {
00349 tmp=8-tmp;
00350 fmt.Printf(wxT("%%.%df"), tmp >= -1 ? 2 : -tmp);
00351 }
00352
00353 double n = floor( (w.GetPosY() - (double)extend / w.GetScaleY()) / step ) * step ;
00354
00355 tmp=65536;
00356 for (;n < end; n += step)
00357 {
00358 const int p = (int)((w.GetPosY() - n) * w.GetScaleY());
00359 dc.DrawLine( orgx, GetYTranslated(sizedc, p), orgx+4, GetYTranslated(sizedc,p));
00360
00361 s.Printf(fmt, n);
00362 dc.GetTextExtent(s, &tx, &ty);
00363 if ((tmp-p+ty/2) > 32)
00364 {
00365 dc.DrawText( s, orgx+4, GetYTranslated(sizedc,p-ty/2));
00366 tmp=p-ty/2;
00367 }
00368 }
00369
00370 dc.GetTextExtent(m_name, &tx, &ty);
00371 dc.DrawText( m_name, orgx-tx-4, GetYTranslated(sizedc,-extend + ty + 4));
00372 }
00373
00374
00375
00376
00377
00378 IMPLEMENT_DYNAMIC_CLASS(mpWindow, wxScrolledWindow)
00379
00380 BEGIN_EVENT_TABLE(mpWindow, wxScrolledWindow)
00381 EVT_PAINT ( mpWindow::OnPaint)
00382 EVT_SIZE ( mpWindow::OnSize)
00383 EVT_SCROLLWIN( mpWindow::OnScroll2)
00384
00385 EVT_MIDDLE_UP( mpWindow::OnShowPopupMenu)
00386 EVT_RIGHT_UP ( mpWindow::OnShowPopupMenu)
00387 EVT_MENU( mpID_CENTER, mpWindow::OnCenter)
00388 EVT_MENU( mpID_FIT, mpWindow::OnFit)
00389 EVT_MENU( mpID_ZOOM_IN, mpWindow::OnZoomIn)
00390 EVT_MENU( mpID_ZOOM_OUT, mpWindow::OnZoomOut)
00391
00392
00393 EVT_MENU( mpID_LOCKASPECT,mpWindow::OnLockAspect)
00394 END_EVENT_TABLE()
00395
00396 mpWindow::mpWindow( wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, int flag )
00397 : wxScrolledWindow( parent, id, pos, size, flag, wxT("wxPlotter") )
00398 {
00399 m_scaleX = m_scaleY = 1.0;
00400 m_posX = m_posY = 0;
00401 m_scrX = m_scrY = 64;
00402 m_minX = m_minY = 0;
00403 m_maxX = m_maxY = 0;
00404 maxScrX = maxScrY = 200;
00405 minScrX = minScrY = 0;
00406 m_clickedX = 0;
00407 m_clickedY = 5000;
00408 m_lockaspect = FALSE;
00409 offsetX = offsetY = 0;
00410 offsetPixelX = offsetPixelY= 0;
00411
00412 real_guideLine_X = -1;
00413 real_guideLine_Y = -1;
00414 drawGuides = true;
00415 type=1;
00416
00417 m_popmenu.Append( mpID_CENTER, _("Center"), _("Center plot view to this position"));
00418 m_popmenu.Append( mpID_FIT, _("Fit"), _("Set plot view to show all items"));
00419 m_popmenu.Append( mpID_ZOOM_IN, _("Zoom in"), _("Zoom in plot view."));
00420 m_popmenu.Append( mpID_ZOOM_OUT, _("Zoom out"), _("Zoom out plot view."));
00421 m_popmenu.AppendCheckItem( mpID_LOCKASPECT, _("Lock aspect"), _("Lock horizontal and vertical zoom aspect."));
00422
00423 m_popmenu.AppendCheckItem( mpID_LINE_GUIDES, _("Turn off guide lines"), _("Enables/Disables the guide lines"));
00424
00425 m_layers.DeleteContents(TRUE);
00426 SetBackgroundColour( *wxWHITE );
00427 EnableScrolling(FALSE, FALSE);
00428 SetSizeHints(128, 128);
00429
00430
00431
00432 UpdateAll();
00433 }
00434
00435 mpWindow::~mpWindow()
00436 {
00437 }
00438
00439 void mpWindow::Fit()
00440 {
00441 if (UpdateBBox())
00442 {
00443 int cx, cy;
00444 GetClientSize( &cx, &cy);
00445
00446 double d;
00447 d = m_maxX - m_minX;
00448 if (d!=0)
00449 {
00450 m_scaleX = cx/d;
00451 m_posX = m_minX + d/2;
00452 }
00453 d = m_maxY - m_minY;
00454 if (d!=0)
00455 {
00456 m_scaleY = cy/d;
00457 m_posY = m_minY + d/2;
00458 }
00459
00460 if (m_lockaspect)
00461 {
00462 double s = (m_scaleX + m_scaleY)/2;
00463 m_scaleX = s;
00464 m_scaleY = s;
00465 }
00466
00467 UpdateAll();
00468 }
00469 }
00470
00471 void mpWindow::ZoomIn()
00472 {
00473 m_scaleX = m_scaleX * 2;
00474 m_scaleY = m_scaleY * 2;
00475 UpdateAll();
00476 }
00477
00478 void mpWindow::ZoomOut()
00479 {
00480 m_scaleX = m_scaleX / 2;
00481 m_scaleY = m_scaleY / 2;
00482 UpdateAll();
00483 }
00484
00485 void mpWindow::LockAspect(bool enable)
00486 {
00487 m_lockaspect = enable;
00488
00489 m_popmenu.Check(mpID_LOCKASPECT, enable);
00490
00491 if (m_lockaspect)
00492 {
00493 double s = (m_scaleX + m_scaleY)/2;
00494 m_scaleX = s;
00495 m_scaleY = s;
00496 }
00497
00498 UpdateAll();
00499 }
00500
00501 void mpWindow::OnShowPopupMenu(wxMouseEvent &event)
00502 {
00503 m_clickedX = event.GetX();
00504 m_clickedY = event.GetY();
00505 PopupMenu( &m_popmenu, event.GetX(), event.GetY());
00506 }
00507
00508 void mpWindow::OnLockAspect(wxCommandEvent &event)
00509 {
00510 LockAspect( !m_popmenu.IsChecked(mpID_LOCKASPECT) );
00511 }
00512
00513 void mpWindow::OnFit(wxCommandEvent &event)
00514 {
00515 Fit();
00516 }
00517
00518 void mpWindow::OnCenter(wxCommandEvent &event)
00519 {
00520 int cx, cy;
00521 GetClientSize(&cx, &cy);
00522 SetPos( (double)(m_clickedX-cx/2) / m_scaleX + m_posX, (double)(cy/2-m_clickedY) / m_scaleY + m_posY);
00523 }
00524
00525 void mpWindow::OnZoomIn(wxCommandEvent &event)
00526 {
00527 int cx, cy;
00528 GetClientSize(&cx, &cy);
00529 m_posX = (double)(m_clickedX-cx/2) / m_scaleX + m_posX;
00530 m_posY = (double)(cy/2-m_clickedY) / m_scaleY + m_posY;
00531 ZoomIn();
00532 }
00533
00534 void mpWindow::OnZoomOut(wxCommandEvent &event)
00535 {
00536 ZoomOut();
00537 }
00538
00539 void mpWindow::OnSize( wxSizeEvent &event )
00540 {
00541 UpdateAll();
00542 }
00543
00544 bool mpWindow::AddLayer( mpLayer* layer)
00545 {
00546 bool ret = m_layers.Append( layer) != NULL;
00547 UpdateAll();
00548 return ret;
00549 }
00550
00551 void mpWindow::DelLayer( mpLayer* layer)
00552 {
00553 m_layers.DeleteObject( layer);
00554 UpdateAll();
00555 }
00556
00557 void mpWindow::Refresh(bool eraseBackground, const wxRect* rect)
00558 {
00559 wxScrolledWindow::Refresh(false);
00560 }
00561
00562
00563 void mpWindow::OnPaint( wxPaintEvent &event )
00564 {
00565 wxPaintDC dc(this);
00566 dc.GetSize(&m_scrX, &m_scrY);
00567 printf("EED mpWindow::OnPaint %d %d\n",m_scrX,m_scrY);
00568
00569
00570
00571
00572 wxMemoryDC temp_dc;
00573
00574
00575 _bitmap_functions=new wxBitmap(m_scrX,m_scrY);
00576 temp_dc.SelectObject(*_bitmap_functions);
00577
00578
00579
00580 temp_dc.SetBrush(wxBrush( *wxWHITE_BRUSH ) );
00581 temp_dc.SetPen(wxPen( *wxBLACK_PEN ));
00582 temp_dc.DrawRectangle(0,0,m_scrX,m_scrY);
00583
00584
00585 wxNode *node = m_layers.GetFirst();
00586 while (node)
00587 {
00588 ((mpLayer*)node->GetData())->Plot( temp_dc, *this);
00589 node = node->GetNext();
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599 temp_dc.SetDeviceOrigin(0,0);
00600 dc.Blit(0,0, m_scrX, m_scrY, &temp_dc,0,0);
00601
00602
00603 delete _bitmap_functions;
00604
00605
00606
00607
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 void mpWindow::OnScroll2(wxScrollWinEvent &event)
00654 {
00655 int width, height;
00656 GetClientSize( &width, &height);
00657 int px, py;
00658 GetViewStart( &px, &py);
00659
00660 if (event.GetOrientation() == wxHORIZONTAL)
00661 {
00662 SetPosX( (double)px / GetScaleX() + m_minX + (double)(width>>1)/GetScaleX());
00663 }
00664 else
00665 {
00666 SetPosY( m_maxY - (double)py / GetScaleY() - (double)(height>>1)/GetScaleY());
00667 }
00668 event.Skip();
00669 }
00670
00671 bool mpWindow::UpdateBBox()
00672 {
00673 bool first = TRUE;
00674
00675 wxNode *node = m_layers.GetFirst();
00676
00677 while(node)
00678 {
00679 mpLayer* f = (mpLayer*)node->GetData();
00680
00681 if (f->HasBBox())
00682 {
00683 if (first)
00684 {
00685 first = FALSE;
00686 m_minX = f->GetMinX(); m_maxX=f->GetMaxX();
00687 m_minY = f->GetMinY(); m_maxY=f->GetMaxY();
00688 }
00689 else
00690 {
00691 if (f->GetMinX()<m_minX) m_minX=f->GetMinX(); if (f->GetMaxX()>m_maxX) m_maxX=f->GetMaxX();
00692 if (f->GetMinY()<m_minY) m_minY=f->GetMinY(); if (f->GetMaxY()>m_maxY) m_maxY=f->GetMaxY();
00693 }
00694 }
00695 node = node->GetNext();
00696 }
00697
00698 return first == FALSE;
00699 }
00700
00701 void mpWindow::UpdateAll()
00702 {
00703 if (UpdateBBox())
00704 {
00705 int cx, cy;
00706 GetClientSize( &cx, &cy);
00707 printf("EED mpWindow::UpdateAll %d %d\n",cx,cy);
00708
00709
00710
00711
00712
00713
00714 }
00715
00716 FitInside();
00717 Refresh( false );
00718 }
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 bool mpWindow::drawGuideLines()
00747 {
00748 return drawGuides;
00749 }
00750