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, wxDefaultPosition, wxDefaultSize, 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 _bitmap_functions=NULL;
00412
00413 real_guideLine_X = -1;
00414 real_guideLine_Y = -1;
00415 drawGuides = true;
00416 type=1;
00417
00418 m_popmenu.Append( mpID_CENTER, _("Center"), _("Center plot view to this position"));
00419 m_popmenu.Append( mpID_FIT, _("Fit"), _("Set plot view to show all items"));
00420 m_popmenu.Append( mpID_ZOOM_IN, _("Zoom in"), _("Zoom in plot view."));
00421 m_popmenu.Append( mpID_ZOOM_OUT, _("Zoom out"), _("Zoom out plot view."));
00422 m_popmenu.AppendCheckItem( mpID_LOCKASPECT, _("Lock aspect"), _("Lock horizontal and vertical zoom aspect."));
00423
00424 m_popmenu.AppendCheckItem( mpID_LINE_GUIDES, _("Turn off guide lines"), _("Enables/Disables the guide lines"));
00425
00426 m_layers.DeleteContents(TRUE);
00427 SetBackgroundColour( *wxWHITE );
00428 EnableScrolling(FALSE, FALSE);
00429 SetSizeHints(128, 128);
00430
00431
00432
00433 UpdateAll();
00434 }
00435
00436 mpWindow::~mpWindow()
00437 {
00438 }
00439
00440 void mpWindow::Fit()
00441 {
00442 if (UpdateBBox())
00443 {
00444 int cx, cy;
00445 GetClientSize( &cx, &cy);
00446
00447 double d;
00448 d = m_maxX - m_minX;
00449 if (d!=0)
00450 {
00451 m_scaleX = cx/d;
00452 m_posX = m_minX + d/2;
00453 }
00454 d = m_maxY - m_minY;
00455 if (d!=0)
00456 {
00457 m_scaleY = cy/d;
00458 m_posY = m_minY + d/2;
00459 }
00460
00461 if (m_lockaspect)
00462 {
00463 double s = (m_scaleX + m_scaleY)/2;
00464 m_scaleX = s;
00465 m_scaleY = s;
00466 }
00467
00468 UpdateAll();
00469 }
00470 }
00471
00472 void mpWindow::ZoomIn()
00473 {
00474 m_scaleX = m_scaleX * 2;
00475 m_scaleY = m_scaleY * 2;
00476 UpdateAll();
00477 }
00478
00479 void mpWindow::ZoomOut()
00480 {
00481 m_scaleX = m_scaleX / 2;
00482 m_scaleY = m_scaleY / 2;
00483 UpdateAll();
00484 }
00485
00486 void mpWindow::LockAspect(bool enable)
00487 {
00488 m_lockaspect = enable;
00489
00490 m_popmenu.Check(mpID_LOCKASPECT, enable);
00491
00492 if (m_lockaspect)
00493 {
00494 double s = (m_scaleX + m_scaleY)/2;
00495 m_scaleX = s;
00496 m_scaleY = s;
00497 }
00498
00499 UpdateAll();
00500 }
00501
00502 void mpWindow::OnShowPopupMenu(wxMouseEvent &event)
00503 {
00504 m_clickedX = event.GetX();
00505 m_clickedY = event.GetY();
00506 PopupMenu( &m_popmenu, event.GetX(), event.GetY());
00507 }
00508
00509 void mpWindow::OnLockAspect(wxCommandEvent &event)
00510 {
00511 LockAspect( !m_popmenu.IsChecked(mpID_LOCKASPECT) );
00512 }
00513
00514 void mpWindow::OnFit(wxCommandEvent &event)
00515 {
00516 Fit();
00517 }
00518
00519 void mpWindow::OnCenter(wxCommandEvent &event)
00520 {
00521 int cx, cy;
00522 GetClientSize(&cx, &cy);
00523 SetPos( (double)(m_clickedX-cx/2) / m_scaleX + m_posX, (double)(cy/2-m_clickedY) / m_scaleY + m_posY);
00524 }
00525
00526 void mpWindow::OnZoomIn(wxCommandEvent &event)
00527 {
00528 int cx, cy;
00529 GetClientSize(&cx, &cy);
00530 m_posX = (double)(m_clickedX-cx/2) / m_scaleX + m_posX;
00531 m_posY = (double)(cy/2-m_clickedY) / m_scaleY + m_posY;
00532 ZoomIn();
00533 }
00534
00535 void mpWindow::OnZoomOut(wxCommandEvent &event)
00536 {
00537 ZoomOut();
00538 }
00539
00540 void mpWindow::OnSize( wxSizeEvent &event )
00541 {
00542 UpdateAll();
00543 }
00544
00545 bool mpWindow::AddLayer( mpLayer* layer)
00546 {
00547 bool ret = m_layers.Append( layer) != NULL;
00548 UpdateAll();
00549 return ret;
00550 }
00551
00552 void mpWindow::DelLayer( mpLayer* layer)
00553 {
00554 m_layers.DeleteObject( layer);
00555 UpdateAll();
00556 }
00557
00558 void mpWindow::Refresh(bool eraseBackground, const wxRect* rect)
00559 {
00560 wxScrolledWindow::Refresh(false);
00561 }
00562
00563
00564 void mpWindow::OnPaint( wxPaintEvent &event )
00565 {
00566 wxPaintDC dc(this);
00567 dc.GetSize(&m_scrX, &m_scrY);
00568 printf("EED mpWindow::OnPaint %d %d\n",m_scrX,m_scrY);
00569
00570
00571
00572
00573 wxMemoryDC temp_dc;
00574
00575
00576 _bitmap_functions=new wxBitmap(m_scrX,m_scrY);
00577 temp_dc.SelectObject(*_bitmap_functions);
00578
00579
00580
00581 temp_dc.SetBrush(wxBrush( *wxWHITE_BRUSH ) );
00582 temp_dc.SetPen(wxPen( *wxBLACK_PEN ));
00583 temp_dc.DrawRectangle(0,0,m_scrX,m_scrY);
00584
00585
00586 wxNode *node = m_layers.GetFirst();
00587 while (node)
00588 {
00589 ((mpLayer*)node->GetData())->Plot( temp_dc, *this);
00590 node = node->GetNext();
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600 temp_dc.SetDeviceOrigin(0,0);
00601 dc.Blit(0,0, m_scrX, m_scrY, &temp_dc,0,0);
00602
00603
00604 delete _bitmap_functions;
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
00654 void mpWindow::OnScroll2(wxScrollWinEvent &event)
00655 {
00656 int width, height;
00657 GetClientSize( &width, &height);
00658 int px, py;
00659 GetViewStart( &px, &py);
00660
00661 if (event.GetOrientation() == wxHORIZONTAL)
00662 {
00663 SetPosX( (double)px / GetScaleX() + m_minX + (double)(width>>1)/GetScaleX());
00664 }
00665 else
00666 {
00667 SetPosY( m_maxY - (double)py / GetScaleY() - (double)(height>>1)/GetScaleY());
00668 }
00669 event.Skip();
00670 }
00671
00672 bool mpWindow::UpdateBBox()
00673 {
00674 bool first = TRUE;
00675
00676 wxNode *node = m_layers.GetFirst();
00677
00678 while(node)
00679 {
00680 mpLayer* f = (mpLayer*)node->GetData();
00681
00682 if (f->HasBBox())
00683 {
00684 if (first)
00685 {
00686 first = FALSE;
00687 m_minX = f->GetMinX(); m_maxX=f->GetMaxX();
00688 m_minY = f->GetMinY(); m_maxY=f->GetMaxY();
00689 }
00690 else
00691 {
00692 if (f->GetMinX()<m_minX) m_minX=f->GetMinX(); if (f->GetMaxX()>m_maxX) m_maxX=f->GetMaxX();
00693 if (f->GetMinY()<m_minY) m_minY=f->GetMinY(); if (f->GetMaxY()>m_maxY) m_maxY=f->GetMaxY();
00694 }
00695 }
00696 node = node->GetNext();
00697 }
00698
00699 return first == FALSE;
00700 }
00701
00702 void mpWindow::UpdateAll()
00703 {
00704 if (UpdateBBox())
00705 {
00706 int cx, cy;
00707 GetClientSize( &cx, &cy);
00708 printf("EED mpWindow::UpdateAll %d %d\n",cx,cy);
00709
00710
00711
00712
00713
00714
00715 }
00716
00717 FitInside();
00718 Refresh( false );
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
00747 bool mpWindow::drawGuideLines()
00748 {
00749 return drawGuides;
00750 }
00751