21 #if defined(__GNUG__) && !defined(__clang__) 22 # pragma implementation "mathplot.h" 26 #include <wx/window.h> 39 #include "wx/object.h" 41 #include "wx/colour.h" 42 #include "wx/settings.h" 46 #include "wx/dcclient.h" 47 #include "wx/cursor.h" 50 #include <mrpt/otherlibs/mathplot/mathplot.h> 52 #include <wx/bmpbuttn.h> 53 #include <wx/module.h> 54 #include <wx/msgdlg.h> 56 #include <wx/tipwin.h> 58 #define _USE_MATH_DEFINES // (For VS to define M_PI, etc. in cmath) 72 #define mpLEGEND_MARGIN 5 73 #define mpLEGEND_LINEWIDTH 10 76 #define mpMIN_X_AXIS_LABEL_SEPARATION 64 77 #define mpMIN_Y_AXIS_LABEL_SEPARATION 32 80 #define mpSCROLL_NUM_PIXELS_PER_LINE 10 83 double mpWindow::zoomIncrementalFactor = 1.5;
89 IMPLEMENT_ABSTRACT_CLASS(mpLayer, wxObject)
91 mpLayer::mpLayer() : m_type(mpLAYER_UNDEF)
93 SetPen((wxPen&) *wxBLACK_PEN);
94 SetFont((wxFont&) *wxNORMAL_FONT);
97 m_drawOutsideMargins =
TRUE;
101 wxBitmap mpLayer::GetColourSquare(
int side)
103 wxBitmap
square(side, side, -1);
104 wxColour filler = m_pen.GetColour();
105 wxBrush brush(filler, wxSOLID);
108 dc.SetBackground(brush);
110 dc.SelectObject(wxNullBitmap);
117 IMPLEMENT_DYNAMIC_CLASS(mpInfoLayer, mpLayer)
119 mpInfoLayer::mpInfoLayer()
121 m_dim = wxRect(0,0,1,1);
122 m_brush = *wxTRANSPARENT_BRUSH;
123 m_reference.x = 0; m_reference.y = 0;
126 m_type = mpLAYER_INFO;
129 mpInfoLayer::mpInfoLayer(wxRect rect,
const wxBrush* brush) : m_dim(rect)
132 m_reference.x = rect.x;
133 m_reference.y = rect.y;
136 m_type = mpLAYER_INFO;
139 mpInfoLayer::~mpInfoLayer()
144 void mpInfoLayer::UpdateInfo(mpWindow&
w, wxEvent& event)
149 bool mpInfoLayer::Inside(wxPoint& point)
151 return m_dim.Contains(point);
154 void mpInfoLayer::Move(wxPoint delta)
156 m_dim.SetX(m_reference.x + delta.x);
157 m_dim.SetY(m_reference.y + delta.y);
160 void mpInfoLayer::UpdateReference()
162 m_reference.x = m_dim.x;
163 m_reference.y = m_dim.y;
167 void mpInfoLayer::Plot(wxDC & dc, mpWindow &
w)
171 int scrx =
w.GetScrX();
172 int scry =
w.GetScrY();
174 if(scrx == 0) scrx=1;
175 if(scry == 0) scry=1;
177 if ((m_winX != scrx) || (m_winY != scry)) {
178 #ifdef MATHPLOT_DO_LOGGING 181 if (m_winX != 1) m_dim.x = (int) floor((
double)(m_dim.x*scrx/m_winX));
183 m_dim.y = (int) floor((
double)(m_dim.y*scry/m_winY));
194 dc.SetBrush(m_brush);
195 dc.DrawRectangle(m_dim.x, m_dim.y, m_dim.width, m_dim.height);
199 wxPoint mpInfoLayer::GetPosition()
201 return m_dim.GetPosition();
204 wxSize mpInfoLayer::GetSize()
206 return m_dim.GetSize();
209 mpInfoCoords::mpInfoCoords() : mpInfoLayer()
214 mpInfoCoords::mpInfoCoords(wxRect rect,
const wxBrush* brush) : mpInfoLayer(rect, brush)
219 mpInfoCoords::~mpInfoCoords()
224 void mpInfoCoords::UpdateInfo(mpWindow&
w, wxEvent& event)
226 if (event.GetEventType() == wxEVT_MOTION) {
227 int mouseX = ((wxMouseEvent&)event).GetX();
228 int mouseY = ((wxMouseEvent&)event).GetY();
233 m_content.Printf(wxT(
"x = %f y = %f"),
w.p2x(mouseX),
w.p2y(mouseY));
235 m_content.Printf(wxT(
"x = %f\ny = %f"),
w.p2x(mouseX),
w.p2y(mouseY));
240 void mpInfoCoords::Plot(wxDC & dc, mpWindow &
w)
244 int scrx =
w.GetScrX();
245 int scry =
w.GetScrY();
246 if ((m_winX != scrx) || (m_winY != scry)) {
247 #ifdef MATHPLOT_DO_LOGGING 250 if (m_winX != 1) m_dim.x = (int) floor((
double)(m_dim.x*scrx/m_winX));
252 m_dim.y = (int) floor((
double)(m_dim.y*scry/m_winY));
263 dc.SetBrush(m_brush);
266 dc.GetTextExtent(m_content, &textX, &textY);
267 if (m_dim.width < textX + 10) m_dim.width = textX + 10;
268 if (m_dim.height < textY + 10) m_dim.height = textY + 10;
269 dc.DrawRectangle(m_dim.x, m_dim.y, m_dim.width, m_dim.height);
270 dc.DrawText(m_content, m_dim.x + 5, m_dim.y + 5);
274 mpInfoLegend::mpInfoLegend() : mpInfoLayer()
279 mpInfoLegend::mpInfoLegend(wxRect rect,
const wxBrush* brush) : mpInfoLayer(rect, brush)
284 mpInfoLegend::~mpInfoLegend()
289 void mpInfoLegend::UpdateInfo(mpWindow&
w, wxEvent& event)
294 void mpInfoLegend::Plot(wxDC & dc, mpWindow &
w)
298 int scrx =
w.GetScrX();
299 int scry =
w.GetScrY();
300 if ((m_winX != scrx) || (m_winY != scry)) {
301 #ifdef MATHPLOT_DO_LOGGING 304 if (m_winX != 1) m_dim.x = (int) floor((
double)(m_dim.x*scrx/m_winX));
306 m_dim.y = (int) floor((
double)(m_dim.y*scry/m_winY));
316 dc.SetBrush(m_brush);
322 int tmpX = 0, tmpY = 0;
326 for (
unsigned int p = 0;
p <
w.CountAllLayers();
p++) {
328 if ((ly->GetLayerType() == mpLAYER_PLOT) && (ly->IsVisible())) {
329 label = ly->GetName();
330 dc.GetTextExtent(label, &tmpX, &tmpY);
331 textX = (textX > (tmpX + baseWidth)) ? textX : (tmpX + baseWidth +
mpLEGEND_MARGIN);
333 #ifdef MATHPLOT_DO_LOGGING 339 dc.SetBrush(m_brush);
343 m_dim.height = textY;
344 dc.DrawRectangle(m_dim.x, m_dim.y, m_dim.width, m_dim.height);
345 for (
unsigned int p2 = 0; p2 <
w.CountAllLayers(); p2++) {
347 if ((ly->GetLayerType() == mpLAYER_PLOT) && (ly->IsVisible())) {
348 label = ly->GetName();
350 dc.GetTextExtent(label, &tmpX, &tmpY);
360 dc.DrawText(label, m_dim.x + baseWidth, m_dim.y +
mpLEGEND_MARGIN + plotCount*tmpY);
374 IMPLEMENT_ABSTRACT_CLASS(mpFX, mpLayer)
376 mpFX::mpFX(wxString
name,
int flags)
380 m_type = mpLAYER_PLOT;
383 void mpFX::Plot(wxDC & dc, mpWindow &
w)
388 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
389 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX() :
w.GetScrX() -
w.GetMarginRight();
390 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
391 wxCoord maxYpx = m_drawOutsideMargins ?
w.GetScrY() :
w.GetScrY() -
w.GetMarginBottom();
394 if (m_pen.GetWidth() <= 1)
396 for (wxCoord i = startPx; i < endPx; ++i)
398 iy =
w.y2p( GetY(
w.p2x(i)));
400 if (m_drawOutsideMargins || ((iy >= minYpx) && (iy <= maxYpx)))
401 dc.DrawPoint(i, iy );
406 for (wxCoord i = startPx; i < endPx; ++i)
408 iy =
w.y2p( GetY(
w.p2x(i)));
410 if (m_drawOutsideMargins || ((iy >= minYpx) && (iy <= maxYpx)))
411 dc.DrawLine( i, iy, i, iy);
417 if (!m_name.IsEmpty() && m_showName)
422 dc.GetTextExtent(m_name, &tx, &
ty);
431 if ((m_flags & mpALIGNMASK) == mpALIGN_RIGHT)
432 tx = (
w.GetScrX() - tx) -
w.GetMarginRight() - 8;
433 else if ((m_flags & mpALIGNMASK) == mpALIGN_CENTER)
434 tx = ((
w.GetScrX() -
w.GetMarginRight() -
w.GetMarginLeft() - tx) / 2) +
w.GetMarginLeft();
436 tx =
w.GetMarginLeft() + 8;
437 dc.DrawText( m_name, tx,
w.y2p(GetY(
w.p2x(tx))) );
442 IMPLEMENT_ABSTRACT_CLASS(mpFY, mpLayer)
444 mpFY::mpFY(wxString
name,
int flags)
448 m_type = mpLAYER_PLOT;
451 void mpFY::Plot(wxDC & dc, mpWindow &
w)
458 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
459 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX() :
w.GetScrX() -
w.GetMarginRight();
460 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
461 wxCoord maxYpx = m_drawOutsideMargins ?
w.GetScrY() :
w.GetScrY() -
w.GetMarginBottom();
463 if (m_pen.GetWidth() <= 1)
465 for (i = minYpx; i < maxYpx; ++i)
467 ix =
w.x2p(GetX(
w.p2y(i)));
468 if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx)))
474 for (i=0;i<
w.GetScrY(); ++i)
476 ix =
w.x2p(GetX(
w.p2y(i)));
477 if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx)))
478 dc.DrawLine(ix, i, ix, i);
484 if (!m_name.IsEmpty() && m_showName)
489 dc.GetTextExtent(m_name, &tx, &
ty);
491 if ((m_flags & mpALIGNMASK) == mpALIGN_TOP)
492 ty =
w.GetMarginTop() + 8;
493 else if ((m_flags & mpALIGNMASK) == mpALIGN_CENTER)
494 ty = ((
w.GetScrY() -
w.GetMarginTop() -
w.GetMarginBottom() -
ty) / 2) +
w.GetMarginTop();
496 ty =
w.GetScrY() - 8 -
ty -
w.GetMarginBottom();
498 dc.DrawText( m_name,
w.x2p(GetX(
w.p2y(
ty))),
ty );
503 IMPLEMENT_ABSTRACT_CLASS(mpFXY, mpLayer)
505 mpFXY::mpFXY(wxString
name,
int flags)
509 m_type = mpLAYER_PLOT;
512 void mpFXY::UpdateViewBoundary(wxCoord xnew, wxCoord ynew)
515 maxDrawX = (xnew > maxDrawX) ? xnew : maxDrawX;
516 minDrawX = (xnew < minDrawX) ? xnew : minDrawX;
517 maxDrawY = (maxDrawY > ynew) ? maxDrawY : ynew;
518 minDrawY = (minDrawY < ynew) ? minDrawY : ynew;
522 void mpFXY::Plot(wxDC & dc, mpWindow &
w)
529 Rewind(); GetNextXY(
x,
y);
530 maxDrawX =
x; minDrawX =
x; maxDrawY =
y; minDrawY =
y;
534 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
535 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX() :
w.GetScrX() -
w.GetMarginRight();
536 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
537 wxCoord maxYpx = m_drawOutsideMargins ?
w.GetScrY() :
w.GetScrY() -
w.GetMarginBottom();
539 wxCoord ix = 0, iy = 0;
545 if (m_pen.GetWidth() <= 1)
547 while (GetNextXY(
x,
y))
551 if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx) && (iy >= minYpx) && (iy <= maxYpx))) {
552 dc.DrawPoint(ix, iy);
553 UpdateViewBoundary(ix, iy);
559 while (GetNextXY(
x,
y))
563 if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx) && (iy >= minYpx) && (iy <= maxYpx))) {
564 dc.DrawLine(ix, iy, ix, iy);
565 UpdateViewBoundary(ix, iy);
576 while (GetNextXY(
x,
y))
578 wxCoord x1 =
w.x2p(
x);
579 wxCoord c1 =
w.y2p(
y);
586 if((x1 >= startPx)&&(x0 <= endPx)) {
587 outDown = (c0 > maxYpx) && (c1 > maxYpx);
588 outUp = (c0 < minYpx) && (c1 < minYpx);
589 if (!outUp && !outDown) {
592 x0 = (int)(((
float)(minYpx - c0))/((float)(c1 - c0))*(x1-x0)) + x0;
596 x0 = (int)(((
float)(maxYpx - c0))/((float)(c1 - c0))*(x1-x0)) + x0;
602 x1 = (int)(((
float)(minYpx - c0))/((float)(c1 - c0))*(x1-x0)) + x0;
606 x1 = (int)(((
float)(maxYpx - c0))/((float)(c1 - c0))*(x1-x0)) + x0;
614 c0 = (int)(((
float)(startPx - x0))/((float)(x1 -x0))*(c1 -c0)) + c0;
618 c1 = (int)(((
float)(endPx - x0))/((float)(x1 -x0))*(c1 -c0)) + c0;
622 dc.DrawLine(x0, c0, x1, c1);
623 UpdateViewBoundary(x1, c1);
630 if (!m_name.IsEmpty() && m_showName)
635 dc.GetTextExtent(m_name, &tx, &
ty);
642 if ((m_flags & mpALIGNMASK) == mpALIGN_NW)
647 else if ((m_flags & mpALIGNMASK) == mpALIGN_NE)
649 tx = maxDrawX - tx - 8;
652 else if ((m_flags & mpALIGNMASK) == mpALIGN_SE)
654 tx = maxDrawX - tx - 8;
655 ty = minDrawY -
ty - 8;
660 ty = minDrawY -
ty - 8;
664 dc.DrawText( m_name, tx,
ty);
673 IMPLEMENT_ABSTRACT_CLASS(mpProfile, mpLayer)
675 mpProfile::mpProfile(wxString
name,
int flags)
679 m_type = mpLAYER_PLOT;
682 void mpProfile::Plot(wxDC & dc, mpWindow &
w)
687 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
688 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX() :
w.GetScrX() -
w.GetMarginRight();
689 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
690 wxCoord maxYpx = m_drawOutsideMargins ?
w.GetScrY() :
w.GetScrY() -
w.GetMarginBottom();
693 for (wxCoord i = startPx; i < endPx; ++i) {
694 wxCoord c0 =
w.y2p( GetY(
w.p2x(i)) );
695 wxCoord c1 =
w.y2p( GetY(
w.p2x(i+1)) );
698 if (!m_drawOutsideMargins) {
699 c0 = (c0 <= maxYpx) ? ((c0 >= minYpx) ? c0 : minYpx) : maxYpx;
700 c1 = (c1 <= maxYpx) ? ((c1 >= minYpx) ? c1 : minYpx) : maxYpx;
702 dc.DrawLine(i, c0, i+1, c1);
704 if (!m_name.IsEmpty()) {
708 dc.GetTextExtent(m_name, &tx, &
ty);
710 if ((m_flags & mpALIGNMASK) == mpALIGN_RIGHT)
711 tx = (
w.GetScrX() - tx) -
w.GetMarginRight() - 8;
712 else if ((m_flags & mpALIGNMASK) == mpALIGN_CENTER)
713 tx = ((
w.GetScrX() -
w.GetMarginRight() -
w.GetMarginLeft() - tx) / 2) +
w.GetMarginLeft();
715 tx =
w.GetMarginLeft() + 8;
717 dc.DrawText( m_name, tx,
w.y2p( GetY(
w.p2x(tx) ) ) );
726 #define mpLN10 2.3025850929940456840179914546844 728 IMPLEMENT_DYNAMIC_CLASS(mpScaleX, mpLayer)
730 mpScaleX::mpScaleX(wxString
name,
int flags,
bool ticks,
unsigned int type)
733 SetFont( (wxFont&) *wxSMALL_FONT);
734 SetPen( (wxPen&) *wxGREY_PEN);
738 m_type = mpLAYER_AXIS;
739 m_labelFormat = wxT(
"");
742 void mpScaleX::Plot(wxDC & dc, mpWindow &
w)
749 const int extend =
w.GetScrX();
750 if (m_flags == mpALIGN_CENTER)
752 if (m_flags == mpALIGN_TOP) {
753 if (m_drawOutsideMargins)
754 orgy = X_BORDER_SEPARATION;
756 orgy =
w.GetMarginTop();
758 if (m_flags == mpALIGN_BOTTOM) {
759 if (m_drawOutsideMargins)
760 orgy = X_BORDER_SEPARATION;
762 orgy =
w.GetScrY() -
w.GetMarginBottom();
764 if (m_flags == mpALIGN_BORDER_BOTTOM )
765 orgy =
w.GetScrY() - 1;
766 if (m_flags == mpALIGN_BORDER_TOP )
769 dc.DrawLine( 0, orgy,
w.GetScrX(), orgy);
777 const double dig = floor( log( 128.0 /
w.GetScaleX() ) /
mpLN10 );
778 const double step = exp(
mpLN10 * dig);
779 const double end =
w.GetPosX() + (double)extend /
w.GetScaleX();
785 if (m_labelType == mpX_NORMAL) {
786 if (!m_labelFormat.IsEmpty()) {
793 fmt.Printf(wxT(
"%%.%df"), tmp >= -1 ? 2 : -tmp);
798 if (m_labelType == mpX_DATETIME) {
799 fmt = (wxT(
"%04.0f-%02.0f-%02.0fT%02.0f:%02.0f:%02.0f"));
800 }
else if (m_labelType == mpX_DATE) {
801 fmt = (wxT(
"%04.0f-%02.0f-%02.0f"));
802 }
else if ((m_labelType == mpX_TIME) && (
end/60 < 2)) {
803 fmt = (wxT(
"%02.0f:%02.3f"));
805 fmt = (wxT(
"%02.0f:%02.0f:%02.0f"));
810 double n0 = floor( (
w.GetPosX() ) / step ) * step ;
812 #ifdef MATHPLOT_DO_LOGGING 813 wxLogMessage(wxT(
"mpScaleX::Plot: dig: %f , step: %f, end: %f, n: %f"), dig, step,
end, n0);
815 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
816 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX() :
w.GetScrX() -
w.GetMarginRight();
817 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
818 wxCoord maxYpx = m_drawOutsideMargins ?
w.GetScrY() :
w.GetScrY() -
w.GetMarginBottom();
823 for (
n = n0;
n <
end;
n += step) {
824 const int p = (int)((
n -
w.GetPosX()) *
w.GetScaleX());
825 #ifdef MATHPLOT_DO_LOGGING 826 wxLogMessage(wxT(
"mpScaleX::Plot: n: %f -> p = %d"),
n,
p);
828 if ((
p >= startPx) && (
p <= endPx)) {
830 if (m_flags == mpALIGN_BORDER_BOTTOM)
831 dc.DrawLine(
p, orgy,
p, orgy-4);
833 dc.DrawLine(
p, orgy,
p, orgy+4);
835 #if wxCHECK_VERSION(3, 0, 0) 836 m_pen.SetStyle(wxPENSTYLE_DOT);
838 m_pen.SetStyle(wxDOT);
841 if ((m_flags == mpALIGN_BOTTOM) && !m_drawOutsideMargins) {
842 dc.DrawLine(
p, orgy+4,
p, minYpx );
844 if ((m_flags == mpALIGN_TOP) && !m_drawOutsideMargins) {
845 dc.DrawLine(
p, orgy-4,
p, maxYpx );
847 dc.DrawLine(
p, 0,
p,
w.GetScrY() );
850 #if wxCHECK_VERSION(3, 0, 0) 851 m_pen.SetStyle(wxPENSTYLE_SOLID);
853 m_pen.SetStyle(wxSOLID);
858 if (m_labelType == mpX_NORMAL)
860 else if (m_labelType == mpX_DATETIME) {
861 time_t when = (time_t)
n;
862 struct tm tm = *localtime(&when);
863 s.Printf(fmt, (
double)tm.tm_year+1900, (
double)tm.tm_mon+1, (
double)tm.tm_mday, (
double)tm.tm_hour, (
double)tm.tm_min, (
double)tm.tm_sec);
864 }
else if (m_labelType == mpX_DATE) {
865 time_t when = (time_t)
n;
866 struct tm tm = *localtime(&when);
867 s.Printf(fmt, (
double)tm.tm_year+1900, (
double)tm.tm_mon+1, (
double)tm.tm_mday);
868 }
else if ((m_labelType == mpX_TIME) || (m_labelType == mpX_HOURS)) {
869 double modulus = fabs(
n);
870 double sign =
n/modulus;
871 double hh = floor(modulus/3600);
872 double mm = floor((modulus - hh*3600)/60);
873 double ss = modulus - hh*3600 - mm*60;
874 #ifdef MATHPLOT_DO_LOGGING 875 wxLogMessage(wxT(
"%02.0f Hours, %02.0f minutes, %02.0f seconds"),
sign*hh, mm, ss);
876 #endif // MATHPLOT_DO_LOGGING 878 s.Printf(fmt,
sign*hh, mm, floor(ss));
880 s.Printf(fmt,
sign*mm, ss);
882 dc.GetTextExtent(
s, &tx, &
ty);
883 labelH = (labelH <=
ty) ?
ty : labelH;
893 maxExtent = (tx > maxExtent) ? tx : maxExtent;
898 for (
n = n0;
n <
end;
n += labelStep) {
899 const int p = (int)((
n -
w.GetPosX()) *
w.GetScaleX());
900 #ifdef MATHPLOT_DO_LOGGING 901 wxLogMessage(wxT(
"mpScaleX::Plot: n_label = %f -> p_label = %d"),
n,
p);
903 if ((
p >= startPx) && (
p <= endPx)) {
905 if (m_labelType == mpX_NORMAL)
907 else if (m_labelType == mpX_DATETIME) {
908 time_t when = (time_t)
n;
909 struct tm tm = *localtime(&when);
910 s.Printf(fmt, (
double)tm.tm_year+1900, (
double)tm.tm_mon+1, (
double)tm.tm_mday, (
double)tm.tm_hour, (
double)tm.tm_min, (
double)tm.tm_sec);
911 }
else if (m_labelType == mpX_DATE) {
912 time_t when = (time_t)
n;
913 struct tm tm = *localtime(&when);
914 s.Printf(fmt, (
double)tm.tm_year+1900, (
double)tm.tm_mon+1, (
double)tm.tm_mday);
915 }
else if ((m_labelType == mpX_TIME) || (m_labelType == mpX_HOURS)) {
916 double modulus = fabs(
n);
917 double sign =
n/modulus;
918 double hh = floor(modulus/3600);
919 double mm = floor((modulus - hh*3600)/60);
920 double ss = modulus - hh*3600 - mm*60;
921 #ifdef MATHPLOT_DO_LOGGING 922 wxLogMessage(wxT(
"%02.0f Hours, %02.0f minutes, %02.0f seconds"),
sign*hh, mm, ss);
923 #endif // MATHPLOT_DO_LOGGING 925 s.Printf(fmt,
sign*hh, mm, floor(ss));
927 s.Printf(fmt,
sign*mm, ss);
929 dc.GetTextExtent(
s, &tx, &
ty);
930 if ((m_flags == mpALIGN_BORDER_BOTTOM) || (m_flags == mpALIGN_TOP)) {
931 dc.DrawText(
s,
p-tx/2, orgy-4-
ty);
933 dc.DrawText(
s,
p-tx/2, orgy+4);
939 dc.GetTextExtent(m_name, &tx, &
ty);
941 case mpALIGN_BORDER_BOTTOM:
942 dc.DrawText( m_name, extend - tx - 4, orgy - 8 -
ty - labelH);
944 case mpALIGN_BOTTOM: {
945 if ((!m_drawOutsideMargins) && (
w.GetMarginBottom() > (
ty + labelH + 8))) {
946 dc.DrawText( m_name, (endPx - startPx - tx)>>1, orgy + 6 + labelH);
948 dc.DrawText( m_name, extend - tx - 4, orgy - 4 -
ty);
952 dc.DrawText( m_name, extend - tx - 4, orgy - 4 -
ty);
955 if ((!m_drawOutsideMargins) && (
w.GetMarginTop() > (
ty + labelH + 8))) {
956 dc.DrawText( m_name, (endPx - startPx - tx)>>1, orgy - 6 -
ty - labelH);
958 dc.DrawText( m_name, extend - tx - 4, orgy + 4);
961 case mpALIGN_BORDER_TOP:
962 dc.DrawText( m_name, extend - tx - 4, orgy + 6 + labelH);
978 IMPLEMENT_DYNAMIC_CLASS(mpScaleY, mpLayer)
980 mpScaleY::mpScaleY(wxString
name,
int flags,
bool ticks)
983 SetFont( (wxFont&) *wxSMALL_FONT);
984 SetPen( (wxPen&) *wxGREY_PEN);
987 m_type = mpLAYER_AXIS;
988 m_labelFormat = wxT(
"");
991 void mpScaleY::Plot(wxDC & dc, mpWindow &
w)
998 const int extend =
w.GetScrY();
999 if (m_flags == mpALIGN_CENTER)
1001 if (m_flags == mpALIGN_LEFT) {
1002 if (m_drawOutsideMargins)
1003 orgx = Y_BORDER_SEPARATION;
1005 orgx =
w.GetMarginLeft();
1007 if (m_flags == mpALIGN_RIGHT) {
1008 if (m_drawOutsideMargins)
1009 orgx =
w.GetScrX() - Y_BORDER_SEPARATION;
1011 orgx =
w.GetScrX() -
w.GetMarginRight();
1013 if (m_flags == mpALIGN_BORDER_RIGHT )
1014 orgx =
w.GetScrX() - 1;
1015 if (m_flags == mpALIGN_BORDER_LEFT )
1020 dc.DrawLine( orgx, 0, orgx, extend);
1028 const double dig = floor( log( 128.0 /
w.GetScaleY() ) /
mpLN10 );
1029 const double step = exp(
mpLN10 * dig);
1030 const double end =
w.GetPosY() + (double)extend /
w.GetScaleY();
1036 double maxScaleAbs = fabs(
w.GetDesiredYmax());
1037 double minScaleAbs = fabs(
w.GetDesiredYmin());
1038 double endscale = (maxScaleAbs > minScaleAbs) ? maxScaleAbs : minScaleAbs;
1039 if (m_labelFormat.IsEmpty()) {
1040 if ((endscale < 1e4) && (endscale > 1e-3))
1045 fmt = m_labelFormat;
1057 double n = floor( (
w.GetPosY() - (double)(extend -
w.GetMarginTop() -
w.GetMarginBottom())/
w.GetScaleY()) / step ) * step ;
1060 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX() :
w.GetScrX() -
w.GetMarginRight();
1061 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
1062 wxCoord maxYpx = m_drawOutsideMargins ?
w.GetScrY() :
w.GetScrY() -
w.GetMarginBottom();
1067 int labelHeigth = 0;
1069 dc.GetTextExtent(
s, &tx, &labelHeigth);
1070 for (;
n <
end;
n += step) {
1071 const int p = (int)((
w.GetPosY() -
n) *
w.GetScaleY());
1072 if ((
p >= minYpx) && (
p <= maxYpx)) {
1074 if (m_flags == mpALIGN_BORDER_LEFT) {
1075 dc.DrawLine( orgx,
p, orgx+4,
p);
1077 dc.DrawLine( orgx-4,
p, orgx,
p);
1080 #if wxCHECK_VERSION(3, 0, 0) 1081 m_pen.SetStyle(wxPENSTYLE_DOT);
1083 m_pen.SetStyle(wxDOT);
1086 if ((m_flags == mpALIGN_LEFT) && !m_drawOutsideMargins) {
1087 dc.DrawLine( orgx-4,
p, endPx,
p);
1089 if ((m_flags == mpALIGN_RIGHT) && !m_drawOutsideMargins) {
1090 dc.DrawLine( minYpx,
p, orgx+4,
p);
1092 dc.DrawLine( 0,
p,
w.GetScrX(),
p);
1095 #if wxCHECK_VERSION(3, 0, 0) 1096 m_pen.SetStyle(wxPENSTYLE_SOLID);
1098 m_pen.SetStyle(wxSOLID);
1104 dc.GetTextExtent(
s, &tx, &
ty);
1105 #ifdef MATHPLOT_DO_LOGGING 1106 if (
ty != labelHeigth) wxLogMessage(wxT(
"mpScaleY::Plot: ty(%f) and labelHeigth(%f) differ!"),
ty, labelHeigth);
1108 labelW = (labelW <= tx) ? tx : labelW;
1110 if ((m_flags == mpALIGN_BORDER_LEFT) || (m_flags == mpALIGN_RIGHT))
1111 dc.DrawText(
s, orgx+4,
p-
ty/2);
1113 dc.DrawText(
s, orgx-4-tx,
p-
ty/2);
1114 tmp=
p-labelHeigth/2;
1120 dc.GetTextExtent(m_name, &tx, &
ty);
1122 case mpALIGN_BORDER_LEFT:
1123 dc.DrawText( m_name, labelW + 8, 4);
1125 case mpALIGN_LEFT: {
1126 if ((!m_drawOutsideMargins) && (
w.GetMarginLeft() > (
ty + labelW + 8))) {
1127 dc.DrawRotatedText( m_name, orgx - 6 - labelW -
ty, (maxYpx - minYpx + tx)>>1, 90);
1129 dc.DrawText( m_name, orgx + 4, 4);
1132 case mpALIGN_CENTER:
1133 dc.DrawText( m_name, orgx + 4, 4);
1135 case mpALIGN_RIGHT: {
1136 if ((!m_drawOutsideMargins) && (
w.GetMarginRight() > (
ty + labelW + 8))) {
1137 dc.DrawRotatedText( m_name, orgx + 6 + labelW, (maxYpx - minYpx + tx)>>1, 90);
1139 dc.DrawText( m_name, orgx - tx - 4, 4);
1142 case mpALIGN_BORDER_RIGHT:
1143 dc.DrawText( m_name, orgx - 6 - tx -labelW, 4);
1167 IMPLEMENT_DYNAMIC_CLASS(mpWindow, wxWindow)
1169 BEGIN_EVENT_TABLE(mpWindow, wxWindow)
1170 EVT_PAINT ( mpWindow::OnPaint)
1171 EVT_SIZE ( mpWindow::OnSize)
1172 EVT_SCROLLWIN_THUMBTRACK(mpWindow::OnScrollThumbTrack)
1173 EVT_SCROLLWIN_PAGEUP(mpWindow::OnScrollPageUp)
1174 EVT_SCROLLWIN_PAGEDOWN(mpWindow::OnScrollPageDown)
1175 EVT_SCROLLWIN_LINEUP(mpWindow::OnScrollLineUp)
1176 EVT_SCROLLWIN_LINEDOWN(mpWindow::OnScrollLineDown)
1177 EVT_SCROLLWIN_TOP(mpWindow::OnScrollTop)
1178 EVT_SCROLLWIN_BOTTOM(mpWindow::OnScrollBottom)
1180 EVT_MIDDLE_UP( mpWindow::OnShowPopupMenu)
1182 EVT_RIGHT_UP ( mpWindow::OnShowPopupMenu)
1183 EVT_MOUSEWHEEL( mpWindow::OnMouseWheel )
1184 EVT_MOTION( mpWindow::OnMouseMove )
1185 EVT_LEFT_DOWN( mpWindow::OnMouseLeftDown)
1186 EVT_LEFT_UP( mpWindow::OnMouseLeftRelease)
1188 EVT_MENU( mpID_CENTER, mpWindow::OnCenter)
1189 EVT_MENU( mpID_FIT, mpWindow::OnFit)
1190 EVT_MENU( mpID_ZOOM_IN, mpWindow::OnZoomIn)
1191 EVT_MENU( mpID_ZOOM_OUT, mpWindow::OnZoomOut)
1192 EVT_MENU( mpID_LOCKASPECT,mpWindow::OnLockAspect)
1193 EVT_MENU( mpID_HELP_MOUSE,mpWindow::OnMouseHelp)
1194 EVT_MENU( mpID_PRINT, mpWindow::OnPrintMenu)
1197 mpWindow::mpWindow( wxWindow *parent, wxWindowID
id, const wxPoint &pos, const wxSize &
size,
long flag )
1198 : wxWindow( parent,
id, pos,
size, flag, wxT("mathplot") )
1200 m_scaleX = m_scaleY = 1.0;
1201 m_posX = m_posY = 0;
1202 m_desiredXmin=m_desiredYmin=0;
1203 m_desiredXmax=m_desiredYmax=1;
1204 m_scrX = m_scrY = 64;
1205 m_minX = m_minY = 0;
1206 m_maxX = m_maxY = 0;
1207 m_last_lx= m_last_ly= 0;
1209 m_enableDoubleBuffer =
FALSE;
1210 m_enableMouseNavigation =
TRUE;
1211 m_mouseMovedAfterRightClick =
FALSE;
1212 m_movingInfoLayer = NULL;
1214 m_marginTop = 0; m_marginRight = 0; m_marginBottom = 0; m_marginLeft = 0;
1217 m_lockaspect =
FALSE;
1219 m_popmenu.Append( mpID_CENTER, _(
"Center"), _(
"Center plot view to this position"));
1220 m_popmenu.Append( mpID_FIT, _(
"Fit"), _(
"Set plot view to show all items"));
1221 m_popmenu.Append( mpID_ZOOM_IN, _(
"Zoom in"), _(
"Zoom in plot view."));
1222 m_popmenu.Append( mpID_ZOOM_OUT, _(
"Zoom out"), _(
"Zoom out plot view."));
1223 m_popmenu.AppendCheckItem( mpID_LOCKASPECT, _(
"Lock aspect"), _(
"Lock horizontal and vertical zoom aspect."));
1224 m_popmenu.Append( mpID_PRINT, _(
"Print..."), _(
"Allows printing the graph."));
1225 m_popmenu.Append( mpID_HELP_MOUSE, _(
"Show mouse commands..."), _(
"Show help about the mouse commands."));
1228 SetBackgroundColour( *wxWHITE );
1229 m_bgColour = *wxWHITE;
1230 m_fgColour = *wxBLACK;
1232 m_enableScrollBars =
false;
1233 SetSizeHints(128, 128);
1239 SetBackgroundStyle( wxBG_STYLE_CUSTOM );
1244 mpWindow::~mpWindow()
1247 DelAllLayers(
true,
false );
1258 void mpWindow::OnMouseRightDown(wxMouseEvent &event)
1260 m_mouseMovedAfterRightClick =
FALSE;
1261 m_mouseRClick_X =
event.GetX();
1262 m_mouseRClick_Y =
event.GetY();
1263 if (m_enableMouseNavigation)
1265 SetCursor( *wxCROSS_CURSOR );
1271 void mpWindow::OnMouseWheel( wxMouseEvent &event )
1273 if (!m_enableMouseNavigation)
1281 if (event.m_controlDown)
1283 wxPoint clickPt( event.GetX(),
event.GetY() );
1285 if (event.GetWheelRotation()>0)
1287 else ZoomOut( clickPt );
1292 int change = -
event.GetWheelRotation();
1293 float changeUnitsX = change / m_scaleX;
1294 float changeUnitsY = change / m_scaleY;
1296 if (event.m_shiftDown)
1298 m_posX += changeUnitsX;
1299 m_desiredXmax += changeUnitsX;
1300 m_desiredXmin += changeUnitsX;
1304 m_posY -= changeUnitsY;
1305 m_desiredYmax -= changeUnitsY;
1306 m_desiredYmax -= changeUnitsY;
1315 void mpWindow::OnMouseMove(wxMouseEvent &event)
1317 if (!m_enableMouseNavigation)
1323 if (event.m_rightDown)
1325 m_mouseMovedAfterRightClick =
TRUE;
1328 int Ax= m_mouseRClick_X -
event.GetX();
1329 int Ay= m_mouseRClick_Y -
event.GetY();
1332 m_mouseRClick_X =
event.GetX();
1333 m_mouseRClick_Y =
event.GetY();
1335 double Ax_units = Ax / m_scaleX;
1336 double Ay_units = -Ay / m_scaleY;
1340 m_desiredXmax += Ax_units;
1341 m_desiredXmin += Ax_units;
1342 m_desiredYmax += Ay_units;
1343 m_desiredYmin += Ay_units;
1347 #ifdef MATHPLOT_DO_LOGGING 1348 wxLogMessage(_(
"[mpWindow::OnMouseMove] Ax:%i Ay:%i m_posX:%f m_posY:%f"),Ax,Ay,m_posX,m_posY);
1351 if (event.m_leftDown) {
1352 if (m_movingInfoLayer == NULL) {
1353 wxClientDC dc(
this);
1354 wxPen pen(*wxBLACK, 1, wxDOT);
1356 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1357 dc.DrawRectangle(m_mouseLClick_X, m_mouseLClick_Y, event.GetX() - m_mouseLClick_X,
event.GetY() - m_mouseLClick_Y);
1359 wxPoint moveVector(event.GetX() - m_mouseLClick_X,
event.GetY() - m_mouseLClick_Y);
1360 m_movingInfoLayer->Move(moveVector);
1365 for (li = m_layers.begin(); li != m_layers.end(); ++li) {
1366 if ((*li)->IsInfo() && (*li)->IsVisible()) {
1367 mpInfoLayer* tmpLyr = (mpInfoLayer*) (*li);
1368 tmpLyr->UpdateInfo(*
this, event);
1370 RefreshRect(tmpLyr->GetRectangle());
1386 void mpWindow::OnMouseLeftDown (wxMouseEvent &event)
1388 m_mouseLClick_X =
event.GetX();
1389 m_mouseLClick_Y =
event.GetY();
1390 #ifdef MATHPLOT_DO_LOGGING 1391 wxLogMessage(_(
"mpWindow::OnMouseLeftDown() X = %d , Y = %d"), event.GetX(),
event.GetY());
1393 wxPoint pointClicked =
event.GetPosition();
1394 m_movingInfoLayer = IsInsideInfoLayer(pointClicked);
1395 if (m_movingInfoLayer != NULL) {
1396 #ifdef MATHPLOT_DO_LOGGING 1397 wxLogMessage(_(
"mpWindow::OnMouseLeftDown() started moving layer %lx"), (
long int) m_movingInfoLayer);
1403 void mpWindow::OnMouseLeftRelease (wxMouseEvent &event)
1407 wxPoint release(event.GetX(),
event.GetY());
1408 wxPoint press(m_mouseLClick_X, m_mouseLClick_Y);
1409 if (m_movingInfoLayer != NULL) {
1410 m_movingInfoLayer->UpdateReference();
1411 m_movingInfoLayer = NULL;
1413 if (release != press) {
1414 ZoomRect(press, release);
1428 void mpWindow::Fit()
1431 Fit(m_minX,m_maxX,m_minY,m_maxY );
1436 void mpWindow::Fit(
double xMin,
double xMax,
double yMin,
double yMax, wxCoord *printSizeX,wxCoord *printSizeY)
1439 m_desiredXmin=xMin; m_desiredXmax=xMax;
1440 m_desiredYmin=yMin; m_desiredYmax=yMax;
1442 if (printSizeX!=NULL && printSizeY!=NULL)
1445 m_scrX = *printSizeX;
1446 m_scrY = *printSizeY;
1451 GetClientSize( &m_scrX,&m_scrY);
1459 m_scaleX = (Ax!=0) ? (m_scrX - m_marginLeft - m_marginRight)/Ax : 1;
1460 m_scaleY = (Ay!=0) ? (m_scrY - m_marginTop - m_marginBottom)/Ay : 1;
1464 #ifdef MATHPLOT_DO_LOGGING 1465 wxLogMessage(_(
"mpWindow::Fit()(lock) m_scaleX=%f,m_scaleY=%f"), m_scaleX,m_scaleY);
1468 double s = m_scaleX < m_scaleY ? m_scaleX : m_scaleY;
1477 m_posX = (xMin+xMax)/2 - ((m_scrX - m_marginLeft - m_marginRight)/2. + m_marginLeft)/m_scaleX ;
1479 m_posY = (yMin+yMax)/2 + ((m_scrY - m_marginTop - m_marginBottom)/2. + m_marginTop)/m_scaleY;
1481 #ifdef MATHPLOT_DO_LOGGING 1482 wxLogMessage(_(
"mpWindow::Fit() m_desiredXmin=%f m_desiredXmax=%f m_desiredYmin=%f m_desiredYmax=%f"), xMin,xMax,yMin,yMax);
1483 wxLogMessage(_(
"mpWindow::Fit() m_scaleX = %f , m_scrX = %d,m_scrY=%d, Ax=%f, Ay=%f, m_posX=%f, m_posY=%f"), m_scaleX, m_scrX,m_scrY, Ax,Ay,m_posX,m_posY);
1488 if (printSizeX==NULL || printSizeY==NULL)
1493 void mpWindow::DoZoomInXCalc (
const int staticXpixel)
1496 double staticX = p2x( staticXpixel );
1498 m_scaleX = m_scaleX * zoomIncrementalFactor;
1500 m_posX = staticX - (staticXpixel / m_scaleX);
1502 m_desiredXmin = m_posX;
1503 m_desiredXmax = m_posX + (m_scrX - (m_marginLeft + m_marginRight)) / m_scaleX;
1504 #ifdef MATHPLOT_DO_LOGGING 1505 wxLogMessage(_(
"mpWindow::DoZoomInXCalc() prior X coord: (%f), new X coord: (%f) SHOULD BE EQUAL!!"), staticX, p2x(staticXpixel));
1509 void mpWindow::DoZoomInYCalc (
const int staticYpixel)
1512 double staticY = p2y( staticYpixel );
1514 m_scaleY = m_scaleY * zoomIncrementalFactor;
1516 m_posY = staticY + (staticYpixel / m_scaleY);
1518 m_desiredYmax = m_posY;
1519 m_desiredYmin = m_posY - (m_scrY - (m_marginTop + m_marginBottom)) / m_scaleY;
1520 #ifdef MATHPLOT_DO_LOGGING 1521 wxLogMessage(_(
"mpWindow::DoZoomInYCalc() prior Y coord: (%f), new Y coord: (%f) SHOULD BE EQUAL!!"), staticY, p2y(staticYpixel));
1525 void mpWindow::DoZoomOutXCalc (
const int staticXpixel)
1528 double staticX = p2x( staticXpixel );
1530 m_scaleX = m_scaleX / zoomIncrementalFactor;
1532 m_posX = staticX - (staticXpixel / m_scaleX);
1534 m_desiredXmin = m_posX;
1535 m_desiredXmax = m_posX + (m_scrX - (m_marginLeft + m_marginRight)) / m_scaleX;
1536 #ifdef MATHPLOT_DO_LOGGING 1537 wxLogMessage(_(
"mpWindow::DoZoomOutXCalc() prior X coord: (%f), new X coord: (%f) SHOULD BE EQUAL!!"), staticX, p2x(staticXpixel));
1541 void mpWindow::DoZoomOutYCalc (
const int staticYpixel)
1544 double staticY = p2y( staticYpixel );
1546 m_scaleY = m_scaleY / zoomIncrementalFactor;
1548 m_posY = staticY + (staticYpixel / m_scaleY);
1550 m_desiredYmax = m_posY;
1551 m_desiredYmin = m_posY - (m_scrY - (m_marginTop + m_marginBottom)) / m_scaleY;
1552 #ifdef MATHPLOT_DO_LOGGING 1553 wxLogMessage(_(
"mpWindow::DoZoomOutYCalc() prior Y coord: (%f), new Y coord: (%f) SHOULD BE EQUAL!!"), staticY, p2y(staticYpixel));
1558 void mpWindow::ZoomIn(
const wxPoint& centerPoint )
1560 wxPoint
c(centerPoint);
1561 if (
c == wxDefaultPosition)
1563 GetClientSize(&m_scrX, &m_scrY);
1564 c.x = (m_scrX - m_marginLeft - m_marginRight)/2 + m_marginLeft;
1565 c.y = (m_scrY - m_marginTop - m_marginBottom)/2 - m_marginTop;
1569 double prior_layer_x = p2x(
c.x );
1570 double prior_layer_y = p2y(
c.y );
1573 m_scaleX = m_scaleX * zoomIncrementalFactor;
1574 m_scaleY = m_scaleY * zoomIncrementalFactor;
1577 m_posX = prior_layer_x -
c.x / m_scaleX;
1578 m_posY = prior_layer_y +
c.y / m_scaleY;
1580 m_desiredXmin = m_posX;
1581 m_desiredXmax = m_posX + (m_scrX - m_marginLeft - m_marginRight) / m_scaleX;
1582 m_desiredYmax = m_posY;
1583 m_desiredYmin = m_posY - (m_scrY - m_marginTop - m_marginBottom) / m_scaleY;
1586 #ifdef MATHPLOT_DO_LOGGING 1587 wxLogMessage(_(
"mpWindow::ZoomIn() prior coords: (%f,%f), new coords: (%f,%f) SHOULD BE EQUAL!!"), prior_layer_x,prior_layer_y, p2x(
c.x),p2y(
c.y));
1593 void mpWindow::ZoomOut(
const wxPoint& centerPoint )
1595 wxPoint
c(centerPoint);
1596 if (
c == wxDefaultPosition)
1598 GetClientSize(&m_scrX, &m_scrY);
1599 c.x = (m_scrX - m_marginLeft - m_marginRight)/2 + m_marginLeft;
1600 c.y = (m_scrY - m_marginTop - m_marginBottom)/2 - m_marginTop;
1604 double prior_layer_x = p2x(
c.x );
1605 double prior_layer_y = p2y(
c.y );
1608 m_scaleX = m_scaleX / zoomIncrementalFactor;
1609 m_scaleY = m_scaleY / zoomIncrementalFactor;
1612 m_posX = prior_layer_x -
c.x / m_scaleX;
1613 m_posY = prior_layer_y +
c.y / m_scaleY;
1615 m_desiredXmin = m_posX;
1616 m_desiredXmax = m_posX + (m_scrX - m_marginLeft - m_marginRight) / m_scaleX;
1617 m_desiredYmax = m_posY;
1618 m_desiredYmin = m_posY - (m_scrY - m_marginTop - m_marginBottom) / m_scaleY;
1620 #ifdef MATHPLOT_DO_LOGGING 1621 wxLogMessage(_(
"mpWindow::ZoomOut() prior coords: (%f,%f), new coords: (%f,%f) SHOULD BE EQUAL!!"), prior_layer_x,prior_layer_y, p2x(
c.x),p2y(
c.y));
1626 void mpWindow::ZoomInX()
1628 m_scaleX = m_scaleX * zoomIncrementalFactor;
1632 void mpWindow::ZoomOutX()
1634 m_scaleX = m_scaleX / zoomIncrementalFactor;
1638 void mpWindow::ZoomInY()
1640 m_scaleY = m_scaleY * zoomIncrementalFactor;
1644 void mpWindow::ZoomOutY()
1646 m_scaleY = m_scaleY / zoomIncrementalFactor;
1650 void mpWindow::ZoomRect(wxPoint p0, wxPoint p1)
1653 double p0x = p2x(p0.x);
1654 double p0y = p2y(p0.y);
1655 double p1x = p2x(p1.x);
1656 double p1y = p2y(p1.y);
1659 double zoom_x_min = p0x<p1x ? p0x:p1x;
1660 double zoom_x_max = p0x>p1x ? p0x:p1x;
1661 double zoom_y_min = p0y<p1y ? p0y:p1y;
1662 double zoom_y_max = p0y>p1y ? p0y:p1y;
1664 #ifdef MATHPLOT_DO_LOGGING 1665 wxLogMessage(_(
"Zoom: (%f,%f)-(%f,%f)"),zoom_x_min,zoom_y_min,zoom_x_max,zoom_y_max);
1668 Fit(zoom_x_min,zoom_x_max,zoom_y_min,zoom_y_max);
1671 void mpWindow::LockAspect(
bool enable)
1673 m_lockaspect = enable;
1674 m_popmenu.Check(mpID_LOCKASPECT, enable);
1677 Fit( m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax );
1680 void mpWindow::OnShowPopupMenu(wxMouseEvent &event)
1683 if (m_enableMouseNavigation)
1685 SetCursor( *wxSTANDARD_CURSOR );
1688 if (!m_mouseMovedAfterRightClick)
1690 m_clickedX =
event.GetX();
1691 m_clickedY =
event.GetY();
1692 PopupMenu( &m_popmenu, event.GetX(),
event.GetY());
1696 void mpWindow::OnLockAspect(wxCommandEvent& WXUNUSED(event))
1698 LockAspect( !m_lockaspect );
1701 void mpWindow::OnMouseHelp(wxCommandEvent& WXUNUSED(event))
1703 wxMessageBox(_(
"Supported Mouse commands:\n \ 1704 - Left button down + Mark area: Rectangular zoom\n \ 1705 - Right button down + Move: Pan (Move)\n \ 1706 - Wheel: Vertical scroll\n \ 1707 - Wheel + SHIFT: Horizontal scroll\n \ 1708 - Wheel + CTRL: Zoom in/out"),_(
"wxMathPlot help"),wxOK,
this);
1711 void mpWindow::OnPrintMenu(wxCommandEvent& WXUNUSED(event))
1714 mpPrintout *plotPrint =
new mpPrintout(
this);
1715 mpPrintout *plotPrintPreview =
new mpPrintout(
this);
1716 wxPrintPreview *preview =
new wxPrintPreview(plotPrintPreview, plotPrint);
1717 wxPreviewFrame *frame =
new wxPreviewFrame(preview, NULL, wxT(
"Print Plot"), wxPoint(100, 100), wxSize(600, 650));
1718 frame->Centre(wxBOTH);
1719 frame->Initialize();
1724 void mpWindow::OnFit(wxCommandEvent& WXUNUSED(event))
1729 void mpWindow::OnCenter(wxCommandEvent& WXUNUSED(event))
1731 GetClientSize(&m_scrX, &m_scrY);
1732 int centerX = (m_scrX - m_marginLeft - m_marginRight)/2;
1733 int centerY = (m_scrY - m_marginTop - m_marginBottom)/2;
1734 SetPos( p2x(m_clickedX - centerX), p2y(m_clickedY - centerY) );
1738 void mpWindow::OnZoomIn(wxCommandEvent& WXUNUSED(event))
1740 ZoomIn( wxPoint(m_mouseRClick_X,m_mouseRClick_Y) );
1743 void mpWindow::OnZoomOut(wxCommandEvent& WXUNUSED(event))
1748 void mpWindow::OnSize( wxSizeEvent& WXUNUSED(event) )
1751 Fit( m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax );
1752 #ifdef MATHPLOT_DO_LOGGING 1753 wxLogMessage(_(
"mpWindow::OnSize() m_scrX = %d, m_scrY = %d"), m_scrX, m_scrY);
1754 #endif // MATHPLOT_DO_LOGGING 1757 bool mpWindow::AddLayer( mpLayer*
layer,
bool refreshDisplay )
1759 if (
layer != NULL) {
1760 m_layers.push_back(
layer );
1761 if (refreshDisplay) UpdateAll();
1767 bool mpWindow::DelLayer(
1769 bool alsoDeleteObject,
1770 bool refreshDisplay )
1773 for (layIt = m_layers.begin(); layIt != m_layers.end(); ++layIt)
1775 if (*layIt ==
layer)
1778 if (alsoDeleteObject)
1780 m_layers.erase(layIt);
1789 void mpWindow::DelAllLayers(
bool alsoDeleteObject,
bool refreshDisplay)
1791 while ( m_layers.size()>0 )
1794 if (alsoDeleteObject)
delete m_layers[0];
1795 m_layers.erase( m_layers.begin() );
1797 if (refreshDisplay) UpdateAll();
1805 void mpWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
1808 dc.GetSize(&m_scrX, &m_scrY);
1811 #ifdef MATHPLOT_DO_LOGGING 1814 GetViewStart( &px, &py );
1815 wxLogMessage(_(
"[mpWindow::OnPaint] vis.area:%ix%i px=%i py=%i"),m_scrX,m_scrY,px,py);
1823 if (m_enableDoubleBuffer)
1825 if (m_last_lx!=m_scrX || m_last_ly!=m_scrY)
1827 if (m_buff_bmp)
delete m_buff_bmp;
1828 m_buff_bmp =
new wxBitmap(m_scrX,m_scrY);
1829 m_buff_dc.SelectObject(*m_buff_bmp);
1842 trgDc->SetPen( *wxTRANSPARENT_PEN );
1843 wxBrush brush( GetBackgroundColour() );
1844 trgDc->SetBrush( brush );
1845 trgDc->SetTextForeground(m_fgColour);
1846 trgDc->DrawRectangle(0,0,m_scrX,m_scrY);
1851 for (li = m_layers.begin(); li != m_layers.end(); ++li)
1853 (*li)->Plot(*trgDc, *
this);
1857 if (m_enableDoubleBuffer)
1861 dc.Blit(0,0,m_scrX,m_scrY,trgDc,0,0);
1871 if (m_enableScrollBars) {
1933 void mpWindow::SetMPScrollbars(
bool status)
1936 m_enableScrollBars =
status;
1939 SetScrollbar(wxHORIZONTAL, 0, 0, 0);
1940 SetScrollbar(wxVERTICAL, 0, 0, 0);
1972 bool mpWindow::UpdateBBox()
1985 m_minX = f->GetMinX(); m_maxX=f->GetMaxX();
1986 m_minY = f->GetMinY(); m_maxY=f->GetMaxY();
1990 if (f->GetMinX()<m_minX) m_minX=f->GetMinX();
1991 if (f->GetMaxX()>m_maxX) m_maxX=f->GetMaxX();
1992 if (f->GetMinY()<m_minY) m_minY=f->GetMinY();
1993 if (f->GetMaxY()>m_maxY) m_maxY=f->GetMaxY();
1998 #ifdef MATHPLOT_DO_LOGGING 1999 wxLogDebug(wxT(
"[mpWindow::UpdateBBox] Bounding box: Xmin = %f, Xmax = %f, Ymin = %f, YMax = %f"), m_minX, m_maxX, m_minY, m_maxY);
2000 #endif // MATHPLOT_DO_LOGGING 2058 void mpWindow::UpdateAll()
2062 if (m_enableScrollBars)
2065 GetClientSize( &cx, &cy);
2069 double leftMargin = m_marginLeft / m_scaleX;
2071 double maxX = (m_desiredXmax > m_maxX) ? m_desiredXmax : m_maxX;
2072 double minX = (m_desiredXmin < m_minX) ? m_desiredXmin : m_minX;
2073 if ((m_posX + leftMargin) < minX)
2074 minX = m_posX + leftMargin;
2076 int sizeX = (int) ((maxX - minX) * m_scaleX);
2077 int thumbX = (int)(((m_posX + leftMargin) - minX) * m_scaleX);
2078 SetScrollbar(wxHORIZONTAL, thumbX, cx - (m_marginRight + m_marginLeft), sizeX);
2083 double topMargin = m_marginTop / m_scaleY;
2085 double maxY = (m_desiredYmax > m_maxY) ? m_desiredYmax : m_maxY;
2086 if ((m_posY - topMargin) > maxY)
2087 maxY = m_posY - topMargin;
2088 double minY = (m_desiredYmin < m_minY) ? m_desiredYmin : m_minY;
2090 int sizeY = (int)((maxY - minY) * m_scaleY);
2091 int thumbY = (int)((maxY - (m_posY - topMargin)) * m_scaleY);
2092 SetScrollbar(wxVERTICAL, thumbY, cy - (m_marginTop + m_marginBottom), sizeY);
2100 void mpWindow::DoScrollCalc (
const int position,
const int orientation)
2102 if (orientation == wxVERTICAL)
2106 double topMargin = m_marginTop / m_scaleY;
2108 double maxY = m_desiredYmax > m_maxY ? m_desiredYmax : m_maxY;
2110 SetPosY((maxY - (position / m_scaleY)) + topMargin);
2116 double leftMargin = m_marginLeft / m_scaleX;
2118 double minX = (m_desiredXmin < m_minX) ? m_desiredXmin : m_minX;
2120 SetPosX((minX + (position / m_scaleX)) - leftMargin);
2124 void mpWindow::OnScrollThumbTrack (wxScrollWinEvent &event)
2126 DoScrollCalc(event.GetPosition(),
event.GetOrientation());
2129 void mpWindow::OnScrollPageUp (wxScrollWinEvent &event)
2131 int scrollOrientation =
event.GetOrientation();
2133 int position = GetScrollPos(scrollOrientation);
2135 int thumbSize = GetScrollThumb(scrollOrientation);
2137 position -= thumbSize;
2141 DoScrollCalc(position, scrollOrientation);
2143 void mpWindow::OnScrollPageDown (wxScrollWinEvent &event)
2145 int scrollOrientation =
event.GetOrientation();
2147 int position = GetScrollPos(scrollOrientation);
2149 int thumbSize = GetScrollThumb(scrollOrientation);
2151 int scrollRange = GetScrollRange(scrollOrientation);
2153 position += thumbSize;
2154 if (position > (scrollRange - thumbSize))
2155 position = scrollRange - thumbSize;
2157 DoScrollCalc(position, scrollOrientation);
2160 void mpWindow::OnScrollLineUp (wxScrollWinEvent &event)
2162 int scrollOrientation =
event.GetOrientation();
2164 int position = GetScrollPos(scrollOrientation);
2170 DoScrollCalc(position, scrollOrientation);
2173 void mpWindow::OnScrollLineDown (wxScrollWinEvent &event)
2175 int scrollOrientation =
event.GetOrientation();
2177 int position = GetScrollPos(scrollOrientation);
2179 int thumbSize = GetScrollThumb(scrollOrientation);
2181 int scrollRange = GetScrollRange(scrollOrientation);
2184 if (position > (scrollRange - thumbSize))
2185 position = scrollRange - thumbSize;
2187 DoScrollCalc(position, scrollOrientation);
2190 void mpWindow::OnScrollTop(wxScrollWinEvent &event)
2192 DoScrollCalc(0, event.GetOrientation());
2195 void mpWindow::OnScrollBottom(wxScrollWinEvent &event)
2197 int scrollOrientation =
event.GetOrientation();
2199 int thumbSize = GetScrollThumb(scrollOrientation);
2201 int scrollRange = GetScrollRange(scrollOrientation);
2203 DoScrollCalc(scrollRange - thumbSize, scrollOrientation);
2207 void mpWindow::SetScaleX(
double scaleX)
2209 if (scaleX!=0) m_scaleX=scaleX;
2215 unsigned int mpWindow::CountLayers()
2218 unsigned int layerNo = 0;
2221 if ((*li)->HasBBox()) layerNo++;
2227 mpLayer* mpWindow::GetLayer(
int position)
2229 if ((position >= (
int) m_layers.size()) || position < 0)
return NULL;
2230 return m_layers[position];
2233 mpLayer* mpWindow::GetLayerByName(
const wxString &
name)
2236 if (! (*it)->GetName().Cmp(
name ) )
2241 void mpWindow::GetBoundingBox(
double* bbox)
2249 bool mpWindow::SaveScreenshot(
const wxString& filename,
int type, wxSize
imageSize,
bool fit)
2252 int bk_scrX, bk_scrY;
2261 SetScr(sizeX, sizeY);
2264 wxBitmap screenBuffer(sizeX,sizeY);
2265 wxMemoryDC screenDC;
2266 screenDC.SelectObject(screenBuffer);
2267 screenDC.SetPen( *wxTRANSPARENT_PEN );
2268 wxBrush brush( GetBackgroundColour() );
2269 screenDC.SetBrush( brush );
2270 screenDC.DrawRectangle(0,0,sizeX,sizeY);
2273 Fit(m_minX, m_maxX, m_minY, m_maxY, &sizeX, &sizeY);
2275 Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax, &sizeX, &sizeY);
2279 for (li = m_layers.begin(); li != m_layers.end(); ++li)
2280 (*li)->Plot(screenDC, *
this);
2284 SetScr(bk_scrX, bk_scrY);
2285 Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax, &bk_scrX, &bk_scrY);
2289 wxImage screenImage = screenBuffer.ConvertToImage();
2290 return screenImage.SaveFile(filename, (wxBitmapType)
type);
2293 void mpWindow::SetMargins(
int top,
int right,
int bottom,
int left)
2296 m_marginRight = right;
2297 m_marginBottom = bottom;
2298 m_marginLeft = left;
2301 mpInfoLayer* mpWindow::IsInsideInfoLayer(wxPoint& point)
2304 for (li = m_layers.begin(); li != m_layers.end(); ++li) {
2305 #ifdef MATHPLOT_DO_LOGGING 2306 wxLogMessage(_(
"mpWindow::IsInsideInfoLayer() examinining layer = %p"), (*li));
2307 #endif // MATHPLOT_DO_LOGGING 2308 if ((*li)->IsInfo()) {
2309 mpInfoLayer* tmpLyr = (mpInfoLayer*) (*li);
2310 #ifdef MATHPLOT_DO_LOGGING 2311 wxLogMessage(_(
"mpWindow::IsInsideInfoLayer() layer = %p"), (*li));
2312 #endif // MATHPLOT_DO_LOGGING 2313 if (tmpLyr->Inside(point)) {
2321 void mpWindow::SetLayerVisible(
const wxString &
name,
bool viewable)
2323 mpLayer* lx = GetLayerByName(
name);
2325 lx->SetVisible(viewable);
2330 bool mpWindow::IsLayerVisible(
const wxString &
name )
2332 mpLayer* lx = GetLayerByName(
name);
2333 return (lx) ? lx->IsVisible() :
false;
2336 void mpWindow::SetLayerVisible(
const unsigned int position,
bool viewable)
2338 mpLayer* lx = GetLayer(position);
2340 lx->SetVisible(viewable);
2345 bool mpWindow::IsLayerVisible(
const unsigned int position )
2347 mpLayer* lx = GetLayer(position);
2348 return (lx) ? lx->IsVisible() :
false;
2351 void mpWindow::SetColourTheme(
const wxColour& bgColour,
const wxColour& drawColour,
const wxColour& axesColour)
2353 SetBackgroundColour(bgColour);
2354 SetForegroundColour(drawColour);
2355 m_bgColour = bgColour;
2356 m_fgColour = drawColour;
2357 m_axColour = axesColour;
2360 for (li = m_layers.begin(); li != m_layers.end(); ++li) {
2361 if ((*li)->GetLayerType() == mpLAYER_AXIS) {
2362 wxPen axisPen = (*li)->GetPen();
2363 axisPen.SetColour(axesColour);
2364 (*li)->SetPen(axisPen);
2366 if ((*li)->GetLayerType() == mpLAYER_INFO) {
2367 wxPen infoPen = (*li)->GetPen();
2368 infoPen.SetColour(drawColour);
2369 (*li)->SetPen(infoPen);
2433 IMPLEMENT_DYNAMIC_CLASS(mpFXYVector, mpFXY)
2436 mpFXYVector::mpFXYVector(wxString
name,
int flags ) : mpFXY(
name,flags)
2443 m_type = mpLAYER_PLOT;
2446 void mpFXYVector::Rewind()
2451 bool mpFXYVector::GetNextXY(
double &
x,
double &
y)
2453 if (m_index>=m_xs.size())
2458 y = m_ys[m_index++];
2459 return m_index<=m_xs.size();
2463 void mpFXYVector::Clear()
2469 void mpFXYVector::SetData(
const std::vector<float> &xs,
const std::vector<float> &ys)
2472 if (xs.size() != ys.size()) {
2473 wxLogError(_(
"wxMathPlot error: X and Y vector are not of the same length!"));
2476 const size_t N=xs.size();
2477 std::vector<double> Xd(N),Yd(N);
2478 for (
size_t i=0;i<xs.size();i++) {
2485 void mpFXYVector::SetData(
const std::vector<double> &xs,
const std::vector<double> &ys)
2488 if (xs.size() != ys.size()) {
2489 wxLogError(_(
"wxMathPlot error: X and Y vector are not of the same length!"));
2507 for (it=xs.begin();it!=xs.end();++it)
2509 if (*it<m_minX) m_minX=*it;
2510 if (*it>m_maxX) m_maxX=*it;
2512 for (it=ys.begin();it!=ys.end();++it)
2514 if (*it<m_minY) m_minY=*it;
2515 if (*it>m_maxY) m_maxY=*it;
2531 void mpFXYVector::AppendDataPoint(
float x,
float y)
2544 const double margX = std::max(fabs(m_minX),fabs(m_maxX))*0.05;
2545 const double margY = std::max(fabs(m_minY),fabs(m_maxY))*0.05;
2555 m_maxX = std::max(
x+fabs(
x)*0.05 , m_maxX);
2557 m_maxY = std::max(
y+fabs(
y)*0.05 , m_maxY);
2566 IMPLEMENT_DYNAMIC_CLASS(mpText, mpLayer)
2573 mpText::mpText( wxString
name,
int offsetx,
int offsety )
2577 if (offsetx >= 0 && offsetx <= 100)
2578 m_offsetx = offsetx;
2582 if (offsety >= 0 && offsety <= 100)
2583 m_offsety = offsety;
2586 m_type = mpLAYER_INFO;
2593 void mpText::Plot(wxDC & dc, mpWindow &
w)
2600 dc.GetTextExtent( GetName(), &tw, &th);
2610 int px = m_offsetx*(
w.GetScrX() -
w.GetMarginLeft() -
w.GetMarginRight())/100;
2611 int py = m_offsety*(
w.GetScrY() -
w.GetMarginTop() -
w.GetMarginBottom())/100;
2612 dc.DrawText( GetName(), px, py);
2620 mpPrintout::mpPrintout(mpWindow *drawWindow,
const wxChar *title) : wxPrintout(title)
2623 plotWindow = drawWindow;
2626 bool mpPrintout::OnPrintPage(
int page)
2629 wxDC *trgDc = GetDC();
2630 if ((trgDc) && (page == 1)) {
2631 wxCoord m_prnX, m_prnY;
2634 trgDc->GetSize(&m_prnX, &m_prnY);
2636 m_prnX -= (2*marginX);
2637 m_prnY -= (2*marginY);
2638 trgDc->SetDeviceOrigin(marginX, marginY);
2640 #ifdef MATHPLOT_DO_LOGGING 2641 wxLogMessage(wxT(
"Print Size: %d x %d\n"), m_prnX, m_prnY);
2642 wxLogMessage(wxT(
"Screen Size: %d x %d\n"), plotWindow->GetScrX(), plotWindow->GetScrY());
2647 plotWindow->GetDesiredXmin(),
2648 plotWindow->GetDesiredXmax(),
2649 plotWindow->GetDesiredYmin(),
2650 plotWindow->GetDesiredYmax(),
2655 wxColour oldBgColour = plotWindow->GetBackgroundColour();
2656 wxColour oldFgColour = plotWindow->GetForegroundColour();
2657 wxColour oldAxColour = plotWindow->GetAxesColour();
2660 trgDc->SetPen( *wxTRANSPARENT_PEN );
2662 wxBrush brush = *wxWHITE_BRUSH;
2663 trgDc->SetBrush( brush );
2664 trgDc->DrawRectangle(0,0,m_prnX,m_prnY);
2669 for (
unsigned int li = 0; li < plotWindow->CountAllLayers(); ++li) {
2670 layer = plotWindow->GetLayer(li);
2671 layer->Plot(*trgDc, *plotWindow);
2676 plotWindow->SetColourTheme(oldBgColour, oldFgColour, oldAxColour);
2678 plotWindow->Fit(plotWindow->GetDesiredXmin(), plotWindow->GetDesiredXmax(), plotWindow->GetDesiredYmin(), plotWindow->GetDesiredYmax(), NULL, NULL);
2679 plotWindow->UpdateAll();
2684 bool mpPrintout::HasPage(
int page)
2693 void mpMovableObject::TranslatePoint(
double x,
double y,
double &out_x,
double &out_y )
2695 double ccos = cos( m_reference_phi );
2696 double csin = sin( m_reference_phi );
2698 out_x = m_reference_x + ccos *
x - csin *
y;
2699 out_y = m_reference_y + csin *
x + ccos *
y;
2703 void mpMovableObject::ShapeUpdated()
2706 if (m_shape_xs.size()!=m_shape_ys.size())
2708 wxLogError(wxT(
"[mpMovableObject::ShapeUpdated] Error, m_shape_xs and m_shape_ys have different lengths!"));
2712 double ccos = cos( m_reference_phi );
2713 double csin = sin( m_reference_phi );
2715 m_trans_shape_xs.resize(m_shape_xs.size());
2716 m_trans_shape_ys.resize(m_shape_xs.size());
2722 m_bbox_max_x=-1e300;
2724 m_bbox_max_y=-1e300;
2726 for (itXo=m_trans_shape_xs.begin(),itYo=m_trans_shape_ys.begin(),itXi=m_shape_xs.begin(),itYi=m_shape_ys.begin();
2727 itXo!=m_trans_shape_xs.end(); ++itXo,++itYo,++itXi,++itYi)
2729 *itXo = m_reference_x + ccos * (*itXi) - csin * (*itYi);
2730 *itYo = m_reference_y + csin * (*itXi) + ccos * (*itYi);
2733 if (*itXo < m_bbox_min_x) m_bbox_min_x = *itXo;
2734 if (*itXo > m_bbox_max_x) m_bbox_max_x = *itXo;
2735 if (*itYo < m_bbox_min_y) m_bbox_min_y = *itYo;
2736 if (*itYo > m_bbox_max_y) m_bbox_max_y = *itYo;
2741 void mpMovableObject::Plot(wxDC & dc, mpWindow &
w)
2754 if (m_pen.GetWidth() <= 1)
2756 while (itX!=m_trans_shape_xs.end())
2758 dc.DrawPoint(
w.x2p(*(itX++)),
w.y2p( *(itY++) ) );
2763 while (itX!=m_trans_shape_xs.end())
2765 wxCoord cx =
w.x2p(*(itX++));
2766 wxCoord cy =
w.y2p(*(itY++));
2767 dc.DrawLine(cx, cy, cx, cy);
2773 wxCoord cx0=0,cy0=0;
2775 while (itX!=m_trans_shape_xs.end())
2777 wxCoord cx =
w.x2p(*(itX++));
2778 wxCoord cy =
w.y2p(*(itY++));
2784 dc.DrawLine(cx0, cy0, cx, cy);
2789 if (!m_name.IsEmpty() && m_showName)
2794 dc.GetTextExtent(m_name, &tx, &
ty);
2798 wxCoord sx = (wxCoord) (( m_bbox_max_x -
w.GetPosX()) *
w.GetScaleX());
2799 wxCoord sy = (wxCoord) ((
w.GetPosY() - m_bbox_max_y ) *
w.GetScaleY());
2806 const int sx =
w.GetScrX()>>1;
2807 const int sy =
w.GetScrY()>>1;
2809 if ((m_flags & mpALIGNMASK) == mpALIGN_NE)
2814 else if ((m_flags & mpALIGNMASK) == mpALIGN_NW)
2819 else if ((m_flags & mpALIGNMASK) == mpALIGN_SW)
2831 dc.DrawText( m_name, tx,
ty);
2841 void mpCovarianceEllipse::RecalculateShape()
2847 if (m_quantiles<0) { wxLogError(wxT(
"[mpCovarianceEllipse] Error: quantiles must be non-negative"));
return; }
2848 if (m_cov_00<0) { wxLogError(wxT(
"[mpCovarianceEllipse] Error: cov(0,0) must be non-negative"));
return; }
2849 if (m_cov_11<0) { wxLogError(wxT(
"[mpCovarianceEllipse] Error: cov(1,1) must be non-negative"));
return; }
2851 m_shape_xs.resize( m_segments,0 );
2852 m_shape_ys.resize( m_segments,0 );
2856 double b = -m_cov_00 - m_cov_11;
2857 double c = m_cov_00*m_cov_11 - m_cov_01*m_cov_01;
2859 double D =
b*
b - 4*
c;
2861 if (D<0) { wxLogError(wxT(
"[mpCovarianceEllipse] Error: cov is not positive definite"));
return; }
2863 double eigenVal0 =0.5*( -
b + sqrt(D) );
2864 double eigenVal1 =0.5*( -
b - sqrt(D) );
2868 double eigenVec0_x,eigenVec0_y;
2869 double eigenVec1_x,eigenVec1_y;
2877 if (fabs(eigenVal0 - m_cov_00)>1e-6)
2879 double k1x = m_cov_01 / ( eigenVal0 - m_cov_00 );
2881 eigenVec0_x = eigenVec0_y * k1x;
2885 double k1y = m_cov_01 / ( eigenVal0 - m_cov_11 );
2887 eigenVec0_y = eigenVec0_x * k1y;
2896 if (fabs(eigenVal1 - m_cov_00)>1e-6)
2898 double k2x = m_cov_01 / ( eigenVal1 - m_cov_00 );
2900 eigenVec1_x = eigenVec1_y * k2x;
2904 double k2y = m_cov_01 / ( eigenVal1 - m_cov_11 );
2906 eigenVec1_y = eigenVec1_x * k2y;
2910 double len = sqrt( eigenVec0_x*eigenVec0_x + eigenVec0_y*eigenVec0_y );
2914 len = sqrt( eigenVec1_x*eigenVec1_x + eigenVec1_y*eigenVec1_y );
2920 eigenVal0 = sqrt(eigenVal0);
2921 eigenVal1 = sqrt(eigenVal1);
2924 double M_00 = eigenVec0_x * eigenVal0;
2925 double M_01 = eigenVec0_y * eigenVal0;
2927 double M_10 = eigenVec1_x * eigenVal1;
2928 double M_11 = eigenVec1_y * eigenVal1;
2932 double Aang = 6.283185308/(m_segments-1);
2934 for (i=0,ang=0;i<m_segments;i++,ang+= Aang )
2936 double ccos = cos(ang);
2937 double csin = sin(ang);
2939 m_shape_xs[i] = m_quantiles * (ccos * M_00 + csin * M_10 );
2940 m_shape_ys[i] = m_quantiles * (ccos * M_01 + csin * M_11 );
2950 void mpPolygon::setPoints(
2951 const std::vector<double>& points_xs,
2952 const std::vector<double>& points_ys,
2955 if ( points_xs.size()!=points_ys.size() )
2957 wxLogError(wxT(
"[mpPolygon] Error: points_xs and points_ys must have the same number of elements"));
2961 m_shape_xs = points_xs;
2962 m_shape_ys = points_ys;
2964 if ( closedShape && !points_xs.empty())
2966 m_shape_xs.push_back( points_xs[0] );
2967 m_shape_ys.push_back( points_ys[0] );
2973 void mpPolygon::setPoints(
2974 const std::vector<float>& points_xs,
2975 const std::vector<float>& points_ys,
2978 if ( points_xs.size()!=points_ys.size() )
2980 wxLogError(wxT(
"[mpPolygon] Error: points_xs and points_ys must have the same number of elements"));
2984 m_shape_xs.resize(points_xs.size());
2985 m_shape_ys.resize(points_xs.size());
2987 if (!points_xs.empty())
2991 for (itX=points_xs.begin(),itY=points_ys.begin(),itXo=m_shape_xs.begin(),itYo=m_shape_ys.begin();
2992 itX!=points_xs.end();++itX,++itY,++itXo,++itYo)
2994 *itXo = (double) *itX;
2995 *itYo = (double) *itY;
3000 m_shape_xs.push_back( (
double)points_xs[0] );
3001 m_shape_ys.push_back( (
double)points_ys[0] );
3012 void mpBitmapLayer::GetBitmapCopy( wxImage &outBmp )
const 3018 void mpBitmapLayer::SetBitmap(
const wxImage &inBmp,
double x,
double y,
double lx,
double ly )
3022 wxLogError(wxT(
"[mpBitmapLayer] Assigned bitmap is not Ok()!"));
3026 if (lx<0) { wxLogError(wxT(
"[mpBitmapLayer::SetBitmap] Assigned lx is negative!!")); }
3027 if (ly<0) { wxLogError(wxT(
"[mpBitmapLayer::SetBitmap] Assigned ly is negative!!")); }
3039 void mpBitmapLayer::Plot(wxDC & dc, mpWindow &
w)
3041 if (m_visible && m_validImg)
3061 wxCoord x0 =
w.x2p(m_min_x);
3062 wxCoord y0 =
w.y2p(m_max_y);
3063 wxCoord x1 =
w.x2p(m_max_x);
3064 wxCoord y1 =
w.y2p(m_min_y);
3068 double screenPixelX = ( x1-x0 ) / (
double)m_bitmap.GetWidth();
3069 double screenPixelY = ( y1-y0 ) / (
double)m_bitmap.GetHeight();
3072 wxCoord borderMarginX = (wxCoord)(screenPixelX+1);
3073 wxCoord borderMarginY = (wxCoord)(screenPixelY+1);
3076 wxCoord dx0=x0,dx1=x1,dy0=y0,dy1=y1;
3077 if (dx0<0) dx0=-borderMarginX;
3078 if (dy0<0) dy0=-borderMarginY;
3079 if (dx1>
w.GetScrX()) dx1=
w.GetScrX()+borderMarginX;
3080 if (dy1>
w.GetScrY()) dy1=
w.GetScrY()+borderMarginY;
3083 wxCoord d_width = dx1-dx0+1;
3084 wxCoord d_height = dy1-dy0+1;
3087 wxCoord offset_x= (wxCoord) ( (dx0-x0)/screenPixelX );
3088 wxCoord offset_y= (wxCoord) ( (dy0-y0)/screenPixelY );
3091 wxCoord b_width = (wxCoord) ( (dx1-dx0+1)/screenPixelX );
3092 wxCoord b_height = (wxCoord) ( (dy1-dy0+1)/screenPixelY );
3094 #ifdef MATHPLOT_DO_LOGGING 3095 wxLogMessage(_(
"[mpBitmapLayer::Plot] screenPixel: x=%f y=%f d_width=%ix%i"),screenPixelX,screenPixelY,d_width,d_height);
3096 wxLogMessage(_(
"[mpBitmapLayer::Plot] offset: x=%i y=%i bmpWidth=%ix%i"),offset_x,offset_y,b_width,b_height);
3100 if (d_width>0 && d_height>0)
3103 if (m_scaledBitmap.GetWidth()!=d_width ||
3104 m_scaledBitmap.GetHeight()!=d_height ||
3105 m_scaledBitmap_offset_x != offset_x ||
3106 m_scaledBitmap_offset_y != offset_y )
3108 wxRect
r(wxRect(offset_x,offset_y,b_width,b_height));
3112 if (
r.width>m_bitmap.GetWidth())
r.width=m_bitmap.GetWidth();
3113 if (
r.height>m_bitmap.GetHeight())
r.height=m_bitmap.GetHeight();
3115 m_scaledBitmap = wxBitmap(
3116 wxBitmap(m_bitmap).GetSubBitmap(
r ).ConvertToImage()
3117 .Scale(d_width,d_height) );
3118 m_scaledBitmap_offset_x = offset_x;
3119 m_scaledBitmap_offset_y = offset_y;
3123 dc.DrawBitmap( m_scaledBitmap, dx0,dy0,
true );
3128 if (!m_name.IsEmpty() && m_showName)
3133 dc.GetTextExtent(m_name, &tx, &
ty);
3137 wxCoord sx = (wxCoord) (( m_max_x -
w.GetPosX()) *
w.GetScaleX());
3138 wxCoord sy = (wxCoord) ((
w.GetPosY() - m_max_y ) *
w.GetScaleY());
3145 const int sx =
w.GetScrX()>>1;
3146 const int sy =
w.GetScrY()>>1;
3148 if ((m_flags & mpALIGNMASK) == mpALIGN_NE)
3153 else if ((m_flags & mpALIGNMASK) == mpALIGN_NW)
3158 else if ((m_flags & mpALIGNMASK) == mpALIGN_SW)
3170 dc.DrawText( m_name, tx,
ty);
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei imageSize
const int INVALID_CLICK_COORDS
const Scalar * const_iterator
GLubyte GLubyte GLubyte GLubyte w
T square(const T x)
Inline function for the square of a number.
#define mpMIN_Y_AXIS_LABEL_SEPARATION
int sign(T x)
Returns the sign of X as "1" or "-1".
GLdouble GLdouble GLdouble r
GLuint const GLchar * name
#define mpSCROLL_NUM_PIXELS_PER_LINE
GLenum GLuint GLint GLint layer
#define mpMIN_X_AXIS_LABEL_SEPARATION
EVT_RIGHT_DOWN(mpWindow::OnMouseRightDown) EVT_MOUSEWHEEL(mpWindow
GLuint GLuint GLsizei GLenum type
#define mpLEGEND_LINEWIDTH