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;
127 m_type = mpLAYER_INFO;
130 mpInfoLayer::mpInfoLayer(wxRect rect,
const wxBrush* brush) : m_dim(rect)
133 m_reference.x = rect.x;
134 m_reference.y = rect.y;
137 m_type = mpLAYER_INFO;
140 mpInfoLayer::~mpInfoLayer() {}
141 void mpInfoLayer::UpdateInfo(mpWindow&
w, wxEvent& event) {}
142 bool mpInfoLayer::Inside(wxPoint& point) {
return m_dim.Contains(point); }
143 void mpInfoLayer::Move(wxPoint delta)
145 m_dim.SetX(m_reference.x + delta.x);
146 m_dim.SetY(m_reference.y + delta.y);
149 void mpInfoLayer::UpdateReference()
151 m_reference.x = m_dim.x;
152 m_reference.y = m_dim.y;
155 void mpInfoLayer::Plot(wxDC& dc, mpWindow&
w)
160 int scrx =
w.GetScrX();
161 int scry =
w.GetScrY();
163 if (scrx == 0) scrx = 1;
164 if (scry == 0) scry = 1;
166 if ((m_winX != scrx) || (m_winY != scry))
168 #ifdef MATHPLOT_DO_LOGGING 173 m_dim.x = (int)floor((
double)(m_dim.x * scrx / m_winX));
176 m_dim.y = (int)floor((
double)(m_dim.y * scry / m_winY));
187 dc.SetBrush(m_brush);
188 dc.DrawRectangle(m_dim.x, m_dim.y, m_dim.width, m_dim.height);
192 wxPoint mpInfoLayer::GetPosition() {
return m_dim.GetPosition(); }
193 wxSize mpInfoLayer::GetSize() {
return m_dim.GetSize(); }
194 mpInfoCoords::mpInfoCoords() : mpInfoLayer() {}
195 mpInfoCoords::mpInfoCoords(wxRect rect,
const wxBrush* brush)
196 : mpInfoLayer(rect, brush)
200 mpInfoCoords::~mpInfoCoords() {}
201 void mpInfoCoords::UpdateInfo(mpWindow&
w, wxEvent& event)
203 if (event.GetEventType() == wxEVT_MOTION)
205 int mouseX = ((wxMouseEvent&)event).GetX();
206 int mouseY = ((wxMouseEvent&)event).GetY();
213 m_content.Printf(wxT(
"x = %f y = %f"),
w.p2x(mouseX),
w.p2y(mouseY));
215 m_content.Printf(wxT(
"x = %f\ny = %f"),
w.p2x(mouseX),
w.p2y(mouseY));
220 void mpInfoCoords::Plot(wxDC& dc, mpWindow&
w)
225 int scrx =
w.GetScrX();
226 int scry =
w.GetScrY();
227 if ((m_winX != scrx) || (m_winY != scry))
229 #ifdef MATHPLOT_DO_LOGGING 234 m_dim.x = (int)floor((
double)(m_dim.x * scrx / m_winX));
237 m_dim.y = (int)floor((
double)(m_dim.y * scry / m_winY));
248 dc.SetBrush(m_brush);
251 dc.GetTextExtent(m_content, &textX, &textY);
252 if (m_dim.width < textX + 10) m_dim.width = textX + 10;
253 if (m_dim.height < textY + 10) m_dim.height = textY + 10;
254 dc.DrawRectangle(m_dim.x, m_dim.y, m_dim.width, m_dim.height);
255 dc.DrawText(m_content, m_dim.x + 5, m_dim.y + 5);
259 mpInfoLegend::mpInfoLegend() : mpInfoLayer() {}
260 mpInfoLegend::mpInfoLegend(wxRect rect,
const wxBrush* brush)
261 : mpInfoLayer(rect, brush)
265 mpInfoLegend::~mpInfoLegend() {}
266 void mpInfoLegend::UpdateInfo(mpWindow&
w, wxEvent& event) {}
267 void mpInfoLegend::Plot(wxDC& dc, mpWindow&
w)
272 int scrx =
w.GetScrX();
273 int scry =
w.GetScrY();
274 if ((m_winX != scrx) || (m_winY != scry))
276 #ifdef MATHPLOT_DO_LOGGING 281 m_dim.x = (int)floor((
double)(m_dim.x * scrx / m_winX));
284 m_dim.y = (int)floor((
double)(m_dim.y * scry / m_winY));
294 dc.SetBrush(m_brush);
300 int tmpX = 0, tmpY = 0;
301 mpLayer* ly =
nullptr;
304 for (
unsigned int p = 0;
p <
w.CountAllLayers();
p++)
307 if ((ly->GetLayerType() == mpLAYER_PLOT) && (ly->IsVisible()))
309 label = ly->GetName();
310 dc.GetTextExtent(label, &tmpX, &tmpY);
311 textX = (textX > (tmpX + baseWidth))
315 #ifdef MATHPLOT_DO_LOGGING 322 dc.SetBrush(m_brush);
327 m_dim.height = textY;
328 dc.DrawRectangle(m_dim.x, m_dim.y, m_dim.width, m_dim.height);
329 for (
unsigned int p2 = 0; p2 <
w.CountAllLayers(); p2++)
332 if ((ly->GetLayerType() == mpLAYER_PLOT) && (ly->IsVisible()))
334 label = ly->GetName();
336 dc.GetTextExtent(label, &tmpX, &tmpY);
352 label, m_dim.x + baseWidth,
365 IMPLEMENT_ABSTRACT_CLASS(mpFX, mpLayer)
367 mpFX::mpFX(wxString
name,
int flags)
371 m_type = mpLAYER_PLOT;
374 void mpFX::Plot(wxDC& dc, mpWindow&
w)
380 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
381 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
382 :
w.GetScrX() -
w.GetMarginRight();
383 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
384 wxCoord maxYpx = m_drawOutsideMargins
386 :
w.GetScrY() -
w.GetMarginBottom();
389 if (m_pen.GetWidth() <= 1)
391 for (wxCoord i = startPx; i < endPx; ++i)
393 iy =
w.y2p(GetY(
w.p2x(i)));
396 if (m_drawOutsideMargins || ((iy >= minYpx) && (iy <= maxYpx)))
404 for (wxCoord i = startPx; i < endPx; ++i)
406 iy =
w.y2p(GetY(
w.p2x(i)));
409 if (m_drawOutsideMargins || ((iy >= minYpx) && (iy <= maxYpx)))
410 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() -
439 tx =
w.GetMarginLeft() + 8;
441 m_name, tx,
w.y2p(GetY(
w.p2x(tx))));
450 IMPLEMENT_ABSTRACT_CLASS(mpFY, mpLayer)
452 mpFY::mpFY(wxString
name,
int flags)
456 m_type = mpLAYER_PLOT;
459 void mpFY::Plot(wxDC& dc, mpWindow&
w)
467 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
468 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
469 :
w.GetScrX() -
w.GetMarginRight();
470 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
471 wxCoord maxYpx = m_drawOutsideMargins
473 :
w.GetScrY() -
w.GetMarginBottom();
475 if (m_pen.GetWidth() <= 1)
477 for (i = minYpx; i < maxYpx; ++i)
479 ix =
w.x2p(GetX(
w.p2y(i)));
480 if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx)))
486 for (i = 0; i <
w.GetScrY(); ++i)
488 ix =
w.x2p(GetX(
w.p2y(i)));
489 if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx)))
490 dc.DrawLine(ix, i, ix, i);
498 if (!m_name.IsEmpty() && m_showName)
503 dc.GetTextExtent(m_name, &tx, &
ty);
505 if ((m_flags & mpALIGNMASK) == mpALIGN_TOP)
506 ty =
w.GetMarginTop() + 8;
507 else if ((m_flags & mpALIGNMASK) == mpALIGN_CENTER)
508 ty = ((
w.GetScrY() -
w.GetMarginTop() -
w.GetMarginBottom() -
513 ty =
w.GetScrY() - 8 -
ty -
w.GetMarginBottom();
516 m_name,
w.x2p(GetX(
w.p2y(
ty))),
523 IMPLEMENT_ABSTRACT_CLASS(mpFXY, mpLayer)
525 mpFXY::mpFXY(wxString
name,
int flags)
529 m_type = mpLAYER_PLOT;
532 void mpFXY::UpdateViewBoundary(wxCoord xnew, wxCoord ynew)
535 maxDrawX = (xnew > maxDrawX) ? xnew : maxDrawX;
536 minDrawX = (xnew < minDrawX) ? xnew : minDrawX;
537 maxDrawY = (maxDrawY > ynew) ? maxDrawY : ynew;
538 minDrawY = (minDrawY < ynew) ? minDrawY : ynew;
542 void mpFXY::Plot(wxDC& dc, mpWindow&
w)
560 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
561 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
562 :
w.GetScrX() -
w.GetMarginRight();
563 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
564 wxCoord maxYpx = m_drawOutsideMargins
566 :
w.GetScrY() -
w.GetMarginBottom();
568 wxCoord ix = 0, iy = 0;
574 if (m_pen.GetWidth() <= 1)
576 while (GetNextXY(
x,
y))
580 if (m_drawOutsideMargins ||
581 ((ix >= startPx) && (ix <= endPx) && (iy >= minYpx) &&
584 dc.DrawPoint(ix, iy);
585 UpdateViewBoundary(ix, iy);
591 while (GetNextXY(
x,
y))
595 if (m_drawOutsideMargins ||
596 ((ix >= startPx) && (ix <= endPx) && (iy >= minYpx) &&
599 dc.DrawLine(ix, iy, ix, iy);
600 UpdateViewBoundary(ix, iy);
609 wxCoord x0 = 0, c0 = 0;
611 while (GetNextXY(
x,
y))
624 if ((x1 >= startPx) && (x0 <= endPx))
626 outDown = (c0 > maxYpx) && (c1 > maxYpx);
627 outUp = (c0 < minYpx) && (c1 < minYpx);
628 if (!outUp && !outDown)
635 (int)(((
float)(minYpx - c0)) / ((float)(c1 - c0)) * (x1 - x0)) +
642 (int)(((
float)(maxYpx - c0)) / ((float)(c1 - c0)) * (x1 - x0)) +
652 (int)(((
float)(minYpx - c0)) / ((float)(c1 - c0)) * (x1 - x0)) +
659 (int)(((
float)(maxYpx - c0)) / ((float)(c1 - c0)) * (x1 - x0)) +
673 (int)(((
float)(startPx - x0)) / ((float)(x1 - x0)) * (c1 - c0)) +
680 (int)(((
float)(endPx - x0)) / ((float)(x1 - x0)) * (c1 - c0)) +
685 dc.DrawLine(x0, c0, x1, c1);
686 UpdateViewBoundary(x1, c1);
694 if (!m_name.IsEmpty() && m_showName)
699 dc.GetTextExtent(m_name, &tx, &
ty);
706 if ((m_flags & mpALIGNMASK) == mpALIGN_NW)
711 else if ((m_flags & mpALIGNMASK) == mpALIGN_NE)
713 tx = maxDrawX - tx - 8;
716 else if ((m_flags & mpALIGNMASK) == mpALIGN_SE)
718 tx = maxDrawX - tx - 8;
719 ty = minDrawY -
ty - 8;
724 ty = minDrawY -
ty - 8;
728 dc.DrawText(m_name, tx,
ty);
737 IMPLEMENT_ABSTRACT_CLASS(mpProfile, mpLayer)
739 mpProfile::mpProfile(wxString
name,
int flags)
743 m_type = mpLAYER_PLOT;
746 void mpProfile::Plot(wxDC& dc, mpWindow&
w)
752 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
753 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
754 :
w.GetScrX() -
w.GetMarginRight();
755 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
756 wxCoord maxYpx = m_drawOutsideMargins
758 :
w.GetScrY() -
w.GetMarginBottom();
762 for (wxCoord i = startPx; i < endPx; ++i)
764 wxCoord c0 =
w.y2p(GetY(
w.p2x(i)));
769 w.y2p(GetY(
w.p2x(i + 1)));
774 if (!m_drawOutsideMargins)
776 c0 = (c0 <= maxYpx) ? ((c0 >= minYpx) ? c0 : minYpx) : maxYpx;
777 c1 = (c1 <= maxYpx) ? ((c1 >= minYpx) ? c1 : minYpx) : maxYpx;
779 dc.DrawLine(i, c0, i + 1, c1);
781 if (!m_name.IsEmpty())
786 dc.GetTextExtent(m_name, &tx, &
ty);
788 if ((m_flags & mpALIGNMASK) == mpALIGN_RIGHT)
789 tx = (
w.GetScrX() - tx) -
w.GetMarginRight() - 8;
790 else if ((m_flags & mpALIGNMASK) == mpALIGN_CENTER)
791 tx = ((
w.GetScrX() -
w.GetMarginRight() -
w.GetMarginLeft() -
796 tx =
w.GetMarginLeft() + 8;
798 dc.DrawText(m_name, tx,
w.y2p(GetY(
w.p2x(tx))));
813 #define mpLN10 2.3025850929940456840179914546844 815 IMPLEMENT_DYNAMIC_CLASS(mpScaleX, mpLayer)
817 mpScaleX::mpScaleX(wxString
name,
int flags,
bool ticks,
unsigned int type)
820 SetFont((wxFont&)*wxSMALL_FONT);
821 SetPen((wxPen&)*wxGREY_PEN);
825 m_type = mpLAYER_AXIS;
826 m_labelFormat = wxT(
"");
829 void mpScaleX::Plot(wxDC& dc, mpWindow&
w)
837 const int extend =
w.GetScrX();
838 if (m_flags == mpALIGN_CENTER)
840 if (m_flags == mpALIGN_TOP)
842 if (m_drawOutsideMargins)
843 orgy = X_BORDER_SEPARATION;
845 orgy =
w.GetMarginTop();
847 if (m_flags == mpALIGN_BOTTOM)
849 if (m_drawOutsideMargins)
850 orgy = X_BORDER_SEPARATION;
852 orgy =
w.GetScrY() -
w.GetMarginBottom();
854 if (m_flags == mpALIGN_BORDER_BOTTOM)
855 orgy =
w.GetScrY() - 1;
856 if (m_flags == mpALIGN_BORDER_TOP) orgy = 1;
858 dc.DrawLine(0, orgy,
w.GetScrX(), orgy);
867 const double dig = floor(log(128.0 /
w.GetScaleX()) /
mpLN10);
868 const double step = exp(
mpLN10 * dig);
869 const double end =
w.GetPosX() + (double)extend /
w.GetScaleX();
875 if (m_labelType == mpX_NORMAL)
877 if (!m_labelFormat.IsEmpty())
890 fmt.Printf(wxT(
"%%.%df"), tmp >= -1 ? 2 : -tmp);
897 if (m_labelType == mpX_DATETIME)
899 fmt = (wxT(
"%04.0f-%02.0f-%02.0fT%02.0f:%02.0f:%02.0f"));
901 else if (m_labelType == mpX_DATE)
903 fmt = (wxT(
"%04.0f-%02.0f-%02.0f"));
905 else if ((m_labelType == mpX_TIME) && (
end / 60 < 2))
907 fmt = (wxT(
"%02.0f:%02.3f"));
911 fmt = (wxT(
"%02.0f:%02.0f:%02.0f"));
923 #ifdef MATHPLOT_DO_LOGGING 925 wxT(
"mpScaleX::Plot: dig: %f , step: %f, end: %f, n: %f"), dig,
928 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
929 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
930 :
w.GetScrX() -
w.GetMarginRight();
931 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
932 wxCoord maxYpx = m_drawOutsideMargins
934 :
w.GetScrY() -
w.GetMarginBottom();
940 for (
n = n0;
n <
end;
n += step)
942 const int p = (int)((
n -
w.GetPosX()) *
w.GetScaleX());
943 #ifdef MATHPLOT_DO_LOGGING 944 wxLogMessage(wxT(
"mpScaleX::Plot: n: %f -> p = %d"),
n,
p);
946 if ((
p >= startPx) && (
p <= endPx))
950 if (m_flags == mpALIGN_BORDER_BOTTOM)
951 dc.DrawLine(
p, orgy,
p, orgy - 4);
953 dc.DrawLine(
p, orgy,
p, orgy + 4);
957 #if wxCHECK_VERSION(3, 0, 0) 958 m_pen.SetStyle(wxPENSTYLE_DOT);
960 m_pen.SetStyle(wxDOT);
963 if ((m_flags == mpALIGN_BOTTOM) && !m_drawOutsideMargins)
965 dc.DrawLine(
p, orgy + 4,
p, minYpx);
969 if ((m_flags == mpALIGN_TOP) && !m_drawOutsideMargins)
971 dc.DrawLine(
p, orgy - 4,
p, maxYpx);
975 dc.DrawLine(
p, 0 ,
p,
w.GetScrY());
978 #if wxCHECK_VERSION(3, 0, 0) 979 m_pen.SetStyle(wxPENSTYLE_SOLID);
981 m_pen.SetStyle(wxSOLID);
986 if (m_labelType == mpX_NORMAL)
988 else if (m_labelType == mpX_DATETIME)
990 time_t when = (time_t)
n;
991 struct tm tm = *localtime(&when);
993 fmt, (
double)tm.tm_year + 1900, (
double)tm.tm_mon + 1,
994 (
double)tm.tm_mday, (
double)tm.tm_hour,
995 (
double)tm.tm_min, (
double)tm.tm_sec);
997 else if (m_labelType == mpX_DATE)
999 time_t when = (time_t)
n;
1000 struct tm tm = *localtime(&when);
1002 fmt, (
double)tm.tm_year + 1900, (
double)tm.tm_mon + 1,
1003 (
double)tm.tm_mday);
1006 (m_labelType == mpX_TIME) || (m_labelType == mpX_HOURS))
1008 double modulus = fabs(
n);
1009 double sign =
n / modulus;
1010 double hh = floor(modulus / 3600);
1011 double mm = floor((modulus - hh * 3600) / 60);
1012 double ss = modulus - hh * 3600 - mm * 60;
1013 #ifdef MATHPLOT_DO_LOGGING 1015 wxT(
"%02.0f Hours, %02.0f minutes, %02.0f seconds"),
1017 #endif // MATHPLOT_DO_LOGGING 1018 if (fmt.Len() == 20)
1019 s.Printf(fmt,
sign * hh, mm, floor(ss));
1021 s.Printf(fmt,
sign * mm, ss);
1023 dc.GetTextExtent(
s, &tx, &
ty);
1024 labelH = (labelH <=
ty) ?
ty : labelH;
1037 maxExtent = (tx > maxExtent)
1044 double labelStep = ceil(
1046 (
w.GetScaleX() * step)) *
1048 for (
n = n0;
n <
end;
n += labelStep)
1050 const int p = (int)((
n -
w.GetPosX()) *
w.GetScaleX());
1051 #ifdef MATHPLOT_DO_LOGGING 1053 wxT(
"mpScaleX::Plot: n_label = %f -> p_label = %d"),
n,
p);
1055 if ((
p >= startPx) && (
p <= endPx))
1058 if (m_labelType == mpX_NORMAL)
1060 else if (m_labelType == mpX_DATETIME)
1062 time_t when = (time_t)
n;
1063 struct tm tm = *localtime(&when);
1065 fmt, (
double)tm.tm_year + 1900, (
double)tm.tm_mon + 1,
1066 (
double)tm.tm_mday, (
double)tm.tm_hour,
1067 (
double)tm.tm_min, (
double)tm.tm_sec);
1069 else if (m_labelType == mpX_DATE)
1071 time_t when = (time_t)
n;
1072 struct tm tm = *localtime(&when);
1074 fmt, (
double)tm.tm_year + 1900, (
double)tm.tm_mon + 1,
1075 (
double)tm.tm_mday);
1078 (m_labelType == mpX_TIME) || (m_labelType == mpX_HOURS))
1080 double modulus = fabs(
n);
1081 double sign =
n / modulus;
1082 double hh = floor(modulus / 3600);
1083 double mm = floor((modulus - hh * 3600) / 60);
1084 double ss = modulus - hh * 3600 - mm * 60;
1085 #ifdef MATHPLOT_DO_LOGGING 1087 wxT(
"%02.0f Hours, %02.0f minutes, %02.0f seconds"),
1089 #endif // MATHPLOT_DO_LOGGING 1090 if (fmt.Len() == 20)
1091 s.Printf(fmt,
sign * hh, mm, floor(ss));
1093 s.Printf(fmt,
sign * mm, ss);
1095 dc.GetTextExtent(
s, &tx, &
ty);
1096 if ((m_flags == mpALIGN_BORDER_BOTTOM) ||
1097 (m_flags == mpALIGN_TOP))
1099 dc.DrawText(
s,
p - tx / 2, orgy - 4 -
ty);
1103 dc.DrawText(
s,
p - tx / 2, orgy + 4);
1109 dc.GetTextExtent(m_name, &tx, &
ty);
1112 case mpALIGN_BORDER_BOTTOM:
1113 dc.DrawText(m_name, extend - tx - 4, orgy - 8 -
ty - labelH);
1115 case mpALIGN_BOTTOM:
1117 if ((!m_drawOutsideMargins) &&
1118 (
w.GetMarginBottom() > (
ty + labelH + 8)))
1121 m_name, (endPx - startPx - tx) >> 1, orgy + 6 + labelH);
1125 dc.DrawText(m_name, extend - tx - 4, orgy - 4 -
ty);
1129 case mpALIGN_CENTER:
1130 dc.DrawText(m_name, extend - tx - 4, orgy - 4 -
ty);
1134 if ((!m_drawOutsideMargins) &&
1135 (
w.GetMarginTop() > (
ty + labelH + 8)))
1138 m_name, (endPx - startPx - tx) >> 1,
1139 orgy - 6 -
ty - labelH);
1143 dc.DrawText(m_name, extend - tx - 4, orgy + 4);
1147 case mpALIGN_BORDER_TOP:
1148 dc.DrawText(m_name, extend - tx - 4, orgy + 6 + labelH);
1166 IMPLEMENT_DYNAMIC_CLASS(mpScaleY, mpLayer)
1168 mpScaleY::mpScaleY(wxString
name,
int flags,
bool ticks)
1171 SetFont((wxFont&)*wxSMALL_FONT);
1172 SetPen((wxPen&)*wxGREY_PEN);
1175 m_type = mpLAYER_AXIS;
1176 m_labelFormat = wxT(
"");
1179 void mpScaleY::Plot(wxDC& dc, mpWindow&
w)
1187 const int extend =
w.GetScrY();
1188 if (m_flags == mpALIGN_CENTER)
1190 if (m_flags == mpALIGN_LEFT)
1192 if (m_drawOutsideMargins)
1193 orgx = Y_BORDER_SEPARATION;
1195 orgx =
w.GetMarginLeft();
1197 if (m_flags == mpALIGN_RIGHT)
1199 if (m_drawOutsideMargins)
1200 orgx =
w.GetScrX() - Y_BORDER_SEPARATION;
1202 orgx =
w.GetScrX() -
w.GetMarginRight();
1204 if (m_flags == mpALIGN_BORDER_RIGHT)
1205 orgx =
w.GetScrX() - 1;
1206 if (m_flags == mpALIGN_BORDER_LEFT)
1210 dc.DrawLine(orgx, 0, orgx, extend);
1219 const double dig = floor(log(128.0 /
w.GetScaleY()) /
mpLN10);
1220 const double step = exp(
mpLN10 * dig);
1221 const double end =
w.GetPosY() + (double)extend /
w.GetScaleY();
1227 double maxScaleAbs = fabs(
w.GetDesiredYmax());
1228 double minScaleAbs = fabs(
w.GetDesiredYmin());
1230 (maxScaleAbs > minScaleAbs) ? maxScaleAbs : minScaleAbs;
1231 if (m_labelFormat.IsEmpty())
1233 if ((endscale < 1e4) && (endscale > 1e-3))
1240 fmt = m_labelFormat;
1255 (double)(extend -
w.GetMarginTop() -
w.GetMarginBottom()) /
1261 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
1262 :
w.GetScrX() -
w.GetMarginRight();
1263 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
1264 wxCoord maxYpx = m_drawOutsideMargins
1266 :
w.GetScrY() -
w.GetMarginBottom();
1271 int labelHeigth = 0;
1273 dc.GetTextExtent(
s, &tx, &labelHeigth);
1274 for (;
n <
end;
n += step)
1276 const int p = (int)((
w.GetPosY() -
n) *
w.GetScaleY());
1277 if ((
p >= minYpx) && (
p <= maxYpx))
1281 if (m_flags == mpALIGN_BORDER_LEFT)
1283 dc.DrawLine(orgx,
p, orgx + 4,
p);
1288 orgx - 4,
p, orgx,
p);
1293 #if wxCHECK_VERSION(3, 0, 0) 1294 m_pen.SetStyle(wxPENSTYLE_DOT);
1296 m_pen.SetStyle(wxDOT);
1299 if ((m_flags == mpALIGN_LEFT) && !m_drawOutsideMargins)
1301 dc.DrawLine(orgx - 4,
p, endPx,
p);
1305 if ((m_flags == mpALIGN_RIGHT) && !m_drawOutsideMargins)
1307 dc.DrawLine(minYpx,
p, orgx + 4,
p);
1311 dc.DrawLine(0 ,
p,
w.GetScrX(),
p);
1314 #if wxCHECK_VERSION(3, 0, 0) 1315 m_pen.SetStyle(wxPENSTYLE_SOLID);
1317 m_pen.SetStyle(wxSOLID);
1323 dc.GetTextExtent(
s, &tx, &
ty);
1324 #ifdef MATHPLOT_DO_LOGGING 1325 if (
ty != labelHeigth)
1327 wxT(
"mpScaleY::Plot: ty(%f) and labelHeigth(%f) " 1331 labelW = (labelW <= tx) ? tx : labelW;
1334 if ((m_flags == mpALIGN_BORDER_LEFT) ||
1335 (m_flags == mpALIGN_RIGHT))
1336 dc.DrawText(
s, orgx + 4,
p -
ty / 2);
1341 tmp =
p - labelHeigth / 2;
1347 dc.GetTextExtent(m_name, &tx, &
ty);
1350 case mpALIGN_BORDER_LEFT:
1351 dc.DrawText(m_name, labelW + 8, 4);
1355 if ((!m_drawOutsideMargins) &&
1356 (
w.GetMarginLeft() > (
ty + labelW + 8)))
1359 m_name, orgx - 6 - labelW -
ty,
1360 (maxYpx - minYpx + tx) >> 1, 90);
1364 dc.DrawText(m_name, orgx + 4, 4);
1368 case mpALIGN_CENTER:
1369 dc.DrawText(m_name, orgx + 4, 4);
1373 if ((!m_drawOutsideMargins) &&
1374 (
w.GetMarginRight() > (
ty + labelW + 8)))
1377 m_name, orgx + 6 + labelW, (maxYpx - minYpx + tx) >> 1,
1382 dc.DrawText(m_name, orgx - tx - 4, 4);
1386 case mpALIGN_BORDER_RIGHT:
1387 dc.DrawText(m_name, orgx - 6 - tx - labelW, 4);
1411 IMPLEMENT_DYNAMIC_CLASS(mpWindow, wxWindow)
1413 BEGIN_EVENT_TABLE(mpWindow, wxWindow)
1414 EVT_PAINT(mpWindow::OnPaint)
1415 EVT_SIZE(mpWindow::OnSize)
1416 EVT_SCROLLWIN_THUMBTRACK(mpWindow::OnScrollThumbTrack)
1417 EVT_SCROLLWIN_PAGEUP(mpWindow::OnScrollPageUp)
1418 EVT_SCROLLWIN_PAGEDOWN(mpWindow::OnScrollPageDown)
1419 EVT_SCROLLWIN_LINEUP(mpWindow::OnScrollLineUp)
1420 EVT_SCROLLWIN_LINEDOWN(mpWindow::OnScrollLineDown)
1421 EVT_SCROLLWIN_TOP(mpWindow::OnScrollTop)
1422 EVT_SCROLLWIN_BOTTOM(mpWindow::OnScrollBottom)
1424 EVT_MIDDLE_UP(mpWindow::OnShowPopupMenu)
1426 EVT_RIGHT_UP(mpWindow::OnShowPopupMenu)
1427 EVT_MOUSEWHEEL(mpWindow::OnMouseWheel)
1428 EVT_MOTION(mpWindow::OnMouseMove)
1429 EVT_LEFT_DOWN(mpWindow::OnMouseLeftDown)
1430 EVT_LEFT_UP(mpWindow::OnMouseLeftRelease)
1432 EVT_MENU(mpID_CENTER, mpWindow::OnCenter)
1433 EVT_MENU(mpID_FIT, mpWindow::OnFit)
1434 EVT_MENU(mpID_ZOOM_IN, mpWindow::OnZoomIn)
1435 EVT_MENU(mpID_ZOOM_OUT, mpWindow::OnZoomOut)
1436 EVT_MENU(mpID_LOCKASPECT, mpWindow::OnLockAspect)
1437 EVT_MENU(mpID_HELP_MOUSE, mpWindow::OnMouseHelp)
1438 EVT_MENU(mpID_PRINT, mpWindow::OnPrintMenu)
1442 wxWindow* parent, wxWindowID
id, const wxPoint& pos, const wxSize&
size,
1444 : wxWindow(parent,
id, pos,
size, flag, wxT("mathplot"))
1446 m_scaleX = m_scaleY = 1.0;
1447 m_posX = m_posY = 0;
1448 m_desiredXmin = m_desiredYmin = 0;
1449 m_desiredXmax = m_desiredYmax = 1;
1450 m_scrX = m_scrY = 64;
1451 m_minX = m_minY = 0;
1452 m_maxX = m_maxY = 0;
1453 m_last_lx = m_last_ly = 0;
1454 m_buff_bmp =
nullptr;
1455 m_enableDoubleBuffer =
FALSE;
1456 m_enableMouseNavigation =
TRUE;
1457 m_mouseMovedAfterRightClick =
FALSE;
1458 m_movingInfoLayer =
nullptr;
1465 m_lockaspect =
FALSE;
1468 mpID_CENTER, _(
"Center"), _(
"Center plot view to this position"));
1469 m_popmenu.Append(mpID_FIT, _(
"Fit"), _(
"Set plot view to show all items"));
1470 m_popmenu.Append(mpID_ZOOM_IN, _(
"Zoom in"), _(
"Zoom in plot view."));
1471 m_popmenu.Append(mpID_ZOOM_OUT, _(
"Zoom out"), _(
"Zoom out plot view."));
1472 m_popmenu.AppendCheckItem(
1473 mpID_LOCKASPECT, _(
"Lock aspect"),
1474 _(
"Lock horizontal and vertical zoom aspect."));
1476 mpID_PRINT, _(
"Print..."), _(
"Allows printing the graph."));
1478 mpID_HELP_MOUSE, _(
"Show mouse commands..."),
1479 _(
"Show help about the mouse commands."));
1482 SetBackgroundColour(*wxWHITE);
1483 m_bgColour = *wxWHITE;
1484 m_fgColour = *wxBLACK;
1486 m_enableScrollBars =
false;
1487 SetSizeHints(128, 128);
1493 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
1498 mpWindow::~mpWindow()
1501 DelAllLayers(
true,
false);
1506 m_buff_bmp =
nullptr;
1513 void mpWindow::OnMouseRightDown(wxMouseEvent& event)
1515 m_mouseMovedAfterRightClick =
FALSE;
1516 m_mouseRClick_X =
event.GetX();
1517 m_mouseRClick_Y =
event.GetY();
1518 if (m_enableMouseNavigation)
1520 SetCursor(*wxCROSS_CURSOR);
1526 void mpWindow::OnMouseWheel(wxMouseEvent& event)
1528 if (!m_enableMouseNavigation)
1536 if (event.m_controlDown)
1538 wxPoint clickPt(event.GetX(),
event.GetY());
1540 if (event.GetWheelRotation() > 0)
1549 -
event.GetWheelRotation();
1550 float changeUnitsX = change / m_scaleX;
1551 float changeUnitsY = change / m_scaleY;
1553 if (event.m_shiftDown)
1555 m_posX += changeUnitsX;
1556 m_desiredXmax += changeUnitsX;
1557 m_desiredXmin += changeUnitsX;
1561 m_posY -= changeUnitsY;
1562 m_desiredYmax -= changeUnitsY;
1563 m_desiredYmax -= changeUnitsY;
1572 void mpWindow::OnMouseMove(wxMouseEvent& event)
1574 if (!m_enableMouseNavigation)
1580 if (event.m_rightDown)
1582 m_mouseMovedAfterRightClick =
1586 int Ax = m_mouseRClick_X -
event.GetX();
1587 int Ay = m_mouseRClick_Y -
event.GetY();
1590 m_mouseRClick_X =
event.GetX();
1591 m_mouseRClick_Y =
event.GetY();
1593 double Ax_units = Ax / m_scaleX;
1594 double Ay_units = -Ay / m_scaleY;
1598 m_desiredXmax += Ax_units;
1599 m_desiredXmin += Ax_units;
1600 m_desiredYmax += Ay_units;
1601 m_desiredYmin += Ay_units;
1605 #ifdef MATHPLOT_DO_LOGGING 1607 _(
"[mpWindow::OnMouseMove] Ax:%i Ay:%i m_posX:%f m_posY:%f"), Ax,
1608 Ay, m_posX, m_posY);
1613 if (event.m_leftDown)
1615 if (m_movingInfoLayer ==
nullptr)
1617 wxClientDC dc(
this);
1618 wxPen pen(*wxBLACK, 1, wxDOT);
1620 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1622 m_mouseLClick_X, m_mouseLClick_Y,
1623 event.GetX() - m_mouseLClick_X,
1624 event.GetY() - m_mouseLClick_Y);
1629 event.GetX() - m_mouseLClick_X,
1630 event.GetY() - m_mouseLClick_Y);
1631 m_movingInfoLayer->Move(moveVector);
1638 for (li = m_layers.begin(); li != m_layers.end(); ++li)
1640 if ((*li)->IsInfo() && (*li)->IsVisible())
1642 mpInfoLayer* tmpLyr = (mpInfoLayer*)(*li);
1643 tmpLyr->UpdateInfo(*
this, event);
1645 RefreshRect(tmpLyr->GetRectangle());
1663 void mpWindow::OnMouseLeftDown(wxMouseEvent& event)
1665 m_mouseLClick_X =
event.GetX();
1666 m_mouseLClick_Y =
event.GetY();
1667 #ifdef MATHPLOT_DO_LOGGING 1669 _(
"mpWindow::OnMouseLeftDown() X = %d , Y = %d"), event.GetX(),
1672 wxPoint pointClicked =
event.GetPosition();
1673 m_movingInfoLayer = IsInsideInfoLayer(pointClicked);
1674 if (m_movingInfoLayer !=
nullptr)
1676 #ifdef MATHPLOT_DO_LOGGING 1678 _(
"mpWindow::OnMouseLeftDown() started moving layer %lx"),
1679 (
long int)m_movingInfoLayer);
1685 void mpWindow::OnMouseLeftRelease(wxMouseEvent& event)
1690 wxPoint release(event.GetX(),
event.GetY());
1691 wxPoint press(m_mouseLClick_X, m_mouseLClick_Y);
1692 if (m_movingInfoLayer !=
nullptr)
1694 m_movingInfoLayer->UpdateReference();
1695 m_movingInfoLayer =
nullptr;
1699 if (release != press)
1701 ZoomRect(press, release);
1716 void mpWindow::Fit()
1718 if (UpdateBBox()) Fit(m_minX, m_maxX, m_minY, m_maxY);
1723 double xMin,
double xMax,
double yMin,
double yMax, wxCoord* printSizeX,
1724 wxCoord* printSizeY)
1727 m_desiredXmin = xMin;
1728 m_desiredXmax = xMax;
1729 m_desiredYmin = yMin;
1730 m_desiredYmax = yMax;
1732 if (printSizeX !=
nullptr && printSizeY !=
nullptr)
1735 m_scrX = *printSizeX;
1736 m_scrY = *printSizeY;
1741 GetClientSize(&m_scrX, &m_scrY);
1749 m_scaleX = (Ax != 0) ? (m_scrX - m_marginLeft - m_marginRight) / Ax
1751 m_scaleY = (Ay != 0) ? (m_scrY - m_marginTop - m_marginBottom) / Ay
1756 #ifdef MATHPLOT_DO_LOGGING 1758 _(
"mpWindow::Fit()(lock) m_scaleX=%f,m_scaleY=%f"), m_scaleX,
1763 double s = m_scaleX < m_scaleY ? m_scaleX : m_scaleY;
1772 m_posX = (xMin + xMax) / 2 -
1773 ((m_scrX - m_marginLeft - m_marginRight) / 2. + m_marginLeft) /
1777 m_posY = (yMin + yMax) / 2 +
1778 ((m_scrY - m_marginTop - m_marginBottom) / 2. + m_marginTop) /
1781 #ifdef MATHPLOT_DO_LOGGING 1783 _(
"mpWindow::Fit() m_desiredXmin=%f m_desiredXmax=%f m_desiredYmin=%f " 1784 "m_desiredYmax=%f"),
1785 xMin, xMax, yMin, yMax);
1787 _(
"mpWindow::Fit() m_scaleX = %f , m_scrX = %d,m_scrY=%d, Ax=%f, " 1788 "Ay=%f, m_posX=%f, m_posY=%f"),
1789 m_scaleX, m_scrX, m_scrY, Ax, Ay, m_posX, m_posY);
1796 if (printSizeX ==
nullptr || printSizeY ==
nullptr) UpdateAll();
1800 void mpWindow::DoZoomInXCalc(
const int staticXpixel)
1803 double staticX = p2x(staticXpixel);
1805 m_scaleX = m_scaleX * zoomIncrementalFactor;
1807 m_posX = staticX - (staticXpixel / m_scaleX);
1809 m_desiredXmin = m_posX;
1811 m_posX + (m_scrX - (m_marginLeft + m_marginRight)) / m_scaleX;
1812 #ifdef MATHPLOT_DO_LOGGING 1814 _(
"mpWindow::DoZoomInXCalc() prior X coord: (%f), new X coord: (%f) " 1815 "SHOULD BE EQUAL!!"),
1816 staticX, p2x(staticXpixel));
1820 void mpWindow::DoZoomInYCalc(
const int staticYpixel)
1823 double staticY = p2y(staticYpixel);
1825 m_scaleY = m_scaleY * zoomIncrementalFactor;
1827 m_posY = staticY + (staticYpixel / m_scaleY);
1829 m_desiredYmax = m_posY;
1831 m_posY - (m_scrY - (m_marginTop + m_marginBottom)) / m_scaleY;
1832 #ifdef MATHPLOT_DO_LOGGING 1834 _(
"mpWindow::DoZoomInYCalc() prior Y coord: (%f), new Y coord: (%f) " 1835 "SHOULD BE EQUAL!!"),
1836 staticY, p2y(staticYpixel));
1840 void mpWindow::DoZoomOutXCalc(
const int staticXpixel)
1843 double staticX = p2x(staticXpixel);
1845 m_scaleX = m_scaleX / zoomIncrementalFactor;
1847 m_posX = staticX - (staticXpixel / m_scaleX);
1849 m_desiredXmin = m_posX;
1851 m_posX + (m_scrX - (m_marginLeft + m_marginRight)) / m_scaleX;
1852 #ifdef MATHPLOT_DO_LOGGING 1854 _(
"mpWindow::DoZoomOutXCalc() prior X coord: (%f), new X coord: (%f) " 1855 "SHOULD BE EQUAL!!"),
1856 staticX, p2x(staticXpixel));
1860 void mpWindow::DoZoomOutYCalc(
const int staticYpixel)
1863 double staticY = p2y(staticYpixel);
1865 m_scaleY = m_scaleY / zoomIncrementalFactor;
1867 m_posY = staticY + (staticYpixel / m_scaleY);
1869 m_desiredYmax = m_posY;
1871 m_posY - (m_scrY - (m_marginTop + m_marginBottom)) / m_scaleY;
1872 #ifdef MATHPLOT_DO_LOGGING 1874 _(
"mpWindow::DoZoomOutYCalc() prior Y coord: (%f), new Y coord: (%f) " 1875 "SHOULD BE EQUAL!!"),
1876 staticY, p2y(staticYpixel));
1880 void mpWindow::ZoomIn(
const wxPoint& centerPoint)
1882 wxPoint
c(centerPoint);
1883 if (
c == wxDefaultPosition)
1885 GetClientSize(&m_scrX, &m_scrY);
1886 c.x = (m_scrX - m_marginLeft - m_marginRight) / 2 +
1888 c.y = (m_scrY - m_marginTop - m_marginBottom) / 2 -
1893 double prior_layer_x = p2x(
c.x);
1894 double prior_layer_y = p2y(
c.y);
1897 m_scaleX = m_scaleX * zoomIncrementalFactor;
1898 m_scaleY = m_scaleY * zoomIncrementalFactor;
1901 m_posX = prior_layer_x -
c.x / m_scaleX;
1902 m_posY = prior_layer_y +
c.y / m_scaleY;
1904 m_desiredXmin = m_posX;
1907 (m_scrX - m_marginLeft - m_marginRight) /
1909 m_desiredYmax = m_posY;
1912 (m_scrY - m_marginTop - m_marginBottom) /
1915 #ifdef MATHPLOT_DO_LOGGING 1917 _(
"mpWindow::ZoomIn() prior coords: (%f,%f), new coords: (%f,%f) " 1918 "SHOULD BE EQUAL!!"),
1919 prior_layer_x, prior_layer_y, p2x(
c.x), p2y(
c.y));
1925 void mpWindow::ZoomOut(
const wxPoint& centerPoint)
1927 wxPoint
c(centerPoint);
1928 if (
c == wxDefaultPosition)
1930 GetClientSize(&m_scrX, &m_scrY);
1931 c.x = (m_scrX - m_marginLeft - m_marginRight) / 2 +
1933 c.y = (m_scrY - m_marginTop - m_marginBottom) / 2 -
1938 double prior_layer_x = p2x(
c.x);
1939 double prior_layer_y = p2y(
c.y);
1942 m_scaleX = m_scaleX / zoomIncrementalFactor;
1943 m_scaleY = m_scaleY / zoomIncrementalFactor;
1946 m_posX = prior_layer_x -
c.x / m_scaleX;
1947 m_posY = prior_layer_y +
c.y / m_scaleY;
1949 m_desiredXmin = m_posX;
1952 (m_scrX - m_marginLeft - m_marginRight) /
1954 m_desiredYmax = m_posY;
1957 (m_scrY - m_marginTop - m_marginBottom) /
1960 #ifdef MATHPLOT_DO_LOGGING 1962 _(
"mpWindow::ZoomOut() prior coords: (%f,%f), new coords: (%f,%f) " 1963 "SHOULD BE EQUAL!!"),
1964 prior_layer_x, prior_layer_y, p2x(
c.x), p2y(
c.y));
1969 void mpWindow::ZoomInX()
1971 m_scaleX = m_scaleX * zoomIncrementalFactor;
1975 void mpWindow::ZoomOutX()
1977 m_scaleX = m_scaleX / zoomIncrementalFactor;
1981 void mpWindow::ZoomInY()
1983 m_scaleY = m_scaleY * zoomIncrementalFactor;
1987 void mpWindow::ZoomOutY()
1989 m_scaleY = m_scaleY / zoomIncrementalFactor;
1993 void mpWindow::ZoomRect(wxPoint p0, wxPoint p1)
1996 double p0x = p2x(p0.x);
1997 double p0y = p2y(p0.y);
1998 double p1x = p2x(p1.x);
1999 double p1y = p2y(p1.y);
2002 double zoom_x_min = p0x < p1x ? p0x : p1x;
2003 double zoom_x_max = p0x > p1x ? p0x : p1x;
2004 double zoom_y_min = p0y < p1y ? p0y : p1y;
2005 double zoom_y_max = p0y > p1y ? p0y : p1y;
2007 #ifdef MATHPLOT_DO_LOGGING 2009 _(
"Zoom: (%f,%f)-(%f,%f)"), zoom_x_min, zoom_y_min, zoom_x_max,
2013 Fit(zoom_x_min, zoom_x_max, zoom_y_min, zoom_y_max);
2016 void mpWindow::LockAspect(
bool enable)
2018 m_lockaspect = enable;
2019 m_popmenu.Check(mpID_LOCKASPECT, enable);
2022 Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax);
2025 void mpWindow::OnShowPopupMenu(wxMouseEvent& event)
2028 if (m_enableMouseNavigation)
2030 SetCursor(*wxSTANDARD_CURSOR);
2033 if (!m_mouseMovedAfterRightClick)
2035 m_clickedX =
event.GetX();
2036 m_clickedY =
event.GetY();
2037 PopupMenu(&m_popmenu, event.GetX(),
event.GetY());
2041 void mpWindow::OnLockAspect(wxCommandEvent& WXUNUSED(event))
2043 LockAspect(!m_lockaspect);
2046 void mpWindow::OnMouseHelp(wxCommandEvent& WXUNUSED(event))
2049 _(
"Supported Mouse commands:\n \ 2050 - Left button down + Mark area: Rectangular zoom\n \ 2051 - Right button down + Move: Pan (Move)\n \ 2052 - Wheel: Vertical scroll\n \ 2053 - Wheel + SHIFT: Horizontal scroll\n \ 2054 - Wheel + CTRL: Zoom in/out"),
2055 _(
"wxMathPlot help"), wxOK,
this);
2058 void mpWindow::OnPrintMenu(wxCommandEvent& WXUNUSED(event))
2061 mpPrintout* plotPrint =
new mpPrintout(
this);
2062 mpPrintout* plotPrintPreview =
new mpPrintout(
this);
2063 wxPrintPreview* preview =
new wxPrintPreview(plotPrintPreview, plotPrint);
2064 wxPreviewFrame* frame =
new wxPreviewFrame(
2065 preview,
nullptr, wxT(
"Print Plot"), wxPoint(100, 100),
2067 frame->Centre(wxBOTH);
2068 frame->Initialize();
2072 void mpWindow::OnFit(wxCommandEvent& WXUNUSED(event)) { Fit(); }
2073 void mpWindow::OnCenter(wxCommandEvent& WXUNUSED(event))
2075 GetClientSize(&m_scrX, &m_scrY);
2076 int centerX = (m_scrX - m_marginLeft - m_marginRight) /
2078 int centerY = (m_scrY - m_marginTop - m_marginBottom) /
2080 SetPos(p2x(m_clickedX - centerX), p2y(m_clickedY - centerY));
2086 void mpWindow::OnZoomIn(wxCommandEvent& WXUNUSED(event))
2088 ZoomIn(wxPoint(m_mouseRClick_X, m_mouseRClick_Y));
2091 void mpWindow::OnZoomOut(wxCommandEvent& WXUNUSED(event)) { ZoomOut(); }
2092 void mpWindow::OnSize(wxSizeEvent& WXUNUSED(event))
2095 Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax);
2096 #ifdef MATHPLOT_DO_LOGGING 2098 _(
"mpWindow::OnSize() m_scrX = %d, m_scrY = %d"), m_scrX, m_scrY);
2099 #endif // MATHPLOT_DO_LOGGING 2102 bool mpWindow::AddLayer(mpLayer*
layer,
bool refreshDisplay)
2104 if (
layer !=
nullptr)
2106 m_layers.push_back(
layer);
2107 if (refreshDisplay) UpdateAll();
2113 bool mpWindow::DelLayer(
2114 mpLayer*
layer,
bool alsoDeleteObject,
bool refreshDisplay)
2117 for (layIt = m_layers.begin(); layIt != m_layers.end(); ++layIt)
2119 if (*layIt ==
layer)
2122 if (alsoDeleteObject)
delete *layIt;
2123 m_layers.erase(layIt);
2124 if (refreshDisplay) UpdateAll();
2131 void mpWindow::DelAllLayers(
bool alsoDeleteObject,
bool refreshDisplay)
2133 while (m_layers.size() > 0)
2136 if (alsoDeleteObject)
delete m_layers[0];
2137 m_layers.erase(m_layers.begin());
2139 if (refreshDisplay) UpdateAll();
2147 void mpWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
2150 dc.GetSize(&m_scrX, &m_scrY);
2153 #ifdef MATHPLOT_DO_LOGGING 2156 GetViewStart(&px, &py);
2158 _(
"[mpWindow::OnPaint] vis.area:%ix%i px=%i py=%i"), m_scrX, m_scrY,
2167 if (m_enableDoubleBuffer)
2169 if (m_last_lx != m_scrX || m_last_ly != m_scrY)
2171 if (m_buff_bmp)
delete m_buff_bmp;
2172 m_buff_bmp =
new wxBitmap(m_scrX, m_scrY);
2173 m_buff_dc.SelectObject(*m_buff_bmp);
2186 trgDc->SetPen(*wxTRANSPARENT_PEN);
2187 wxBrush brush(GetBackgroundColour());
2188 trgDc->SetBrush(brush);
2189 trgDc->SetTextForeground(m_fgColour);
2190 trgDc->DrawRectangle(0, 0, m_scrX, m_scrY);
2195 for (li = m_layers.begin(); li != m_layers.end(); ++li)
2197 (*li)->Plot(*trgDc, *
this);
2201 if (m_enableDoubleBuffer)
2205 dc.Blit(0, 0, m_scrX, m_scrY, trgDc, 0, 0);
2216 if (m_enableScrollBars)
2294 void mpWindow::SetMPScrollbars(
bool status)
2297 m_enableScrollBars =
status;
2300 SetScrollbar(wxHORIZONTAL, 0, 0, 0);
2301 SetScrollbar(wxVERTICAL, 0, 0, 0);
2337 bool mpWindow::UpdateBBox()
2351 m_minX = f->GetMinX();
2352 m_maxX = f->GetMaxX();
2353 m_minY = f->GetMinY();
2354 m_maxY = f->GetMaxY();
2358 if (f->GetMinX() < m_minX) m_minX = f->GetMinX();
2359 if (f->GetMaxX() > m_maxX) m_maxX = f->GetMaxX();
2360 if (f->GetMinY() < m_minY) m_minY = f->GetMinY();
2361 if (f->GetMaxY() > m_maxY) m_maxY = f->GetMaxY();
2366 #ifdef MATHPLOT_DO_LOGGING 2368 wxT(
"[mpWindow::UpdateBBox] Bounding box: Xmin = %f, Xmax = %f, Ymin = " 2370 m_minX, m_maxX, m_minY, m_maxY);
2371 #endif // MATHPLOT_DO_LOGGING 2432 void mpWindow::UpdateAll()
2436 if (m_enableScrollBars)
2439 GetClientSize(&cx, &cy);
2443 double leftMargin = m_marginLeft / m_scaleX;
2445 double maxX = (m_desiredXmax > m_maxX) ? m_desiredXmax : m_maxX;
2446 double minX = (m_desiredXmin < m_minX) ? m_desiredXmin : m_minX;
2447 if ((m_posX + leftMargin) < minX) minX = m_posX + leftMargin;
2449 int sizeX = (int)((maxX - minX) * m_scaleX);
2450 int thumbX = (int)(((m_posX + leftMargin) - minX) * m_scaleX);
2452 wxHORIZONTAL, thumbX, cx - (m_marginRight + m_marginLeft),
2458 double topMargin = m_marginTop / m_scaleY;
2460 double maxY = (m_desiredYmax > m_maxY) ? m_desiredYmax : m_maxY;
2461 if ((m_posY - topMargin) > maxY) maxY = m_posY - topMargin;
2462 double minY = (m_desiredYmin < m_minY) ? m_desiredYmin : m_minY;
2464 int sizeY = (int)((maxY - minY) * m_scaleY);
2465 int thumbY = (int)((maxY - (m_posY - topMargin)) * m_scaleY);
2467 wxVERTICAL, thumbY, cy - (m_marginTop + m_marginBottom),
2476 void mpWindow::DoScrollCalc(
const int position,
const int orientation)
2478 if (orientation == wxVERTICAL)
2482 double topMargin = m_marginTop / m_scaleY;
2484 double maxY = m_desiredYmax > m_maxY ? m_desiredYmax : m_maxY;
2486 SetPosY((maxY - (position / m_scaleY)) + topMargin);
2492 double leftMargin = m_marginLeft / m_scaleX;
2494 double minX = (m_desiredXmin < m_minX) ? m_desiredXmin : m_minX;
2496 SetPosX((minX + (position / m_scaleX)) - leftMargin);
2500 void mpWindow::OnScrollThumbTrack(wxScrollWinEvent& event)
2502 DoScrollCalc(event.GetPosition(),
event.GetOrientation());
2505 void mpWindow::OnScrollPageUp(wxScrollWinEvent& event)
2507 int scrollOrientation =
event.GetOrientation();
2509 int position = GetScrollPos(scrollOrientation);
2511 int thumbSize = GetScrollThumb(scrollOrientation);
2513 position -= thumbSize;
2514 if (position < 0) position = 0;
2516 DoScrollCalc(position, scrollOrientation);
2518 void mpWindow::OnScrollPageDown(wxScrollWinEvent& event)
2520 int scrollOrientation =
event.GetOrientation();
2522 int position = GetScrollPos(scrollOrientation);
2524 int thumbSize = GetScrollThumb(scrollOrientation);
2526 int scrollRange = GetScrollRange(scrollOrientation);
2528 position += thumbSize;
2529 if (position > (scrollRange - thumbSize))
2530 position = scrollRange - thumbSize;
2532 DoScrollCalc(position, scrollOrientation);
2535 void mpWindow::OnScrollLineUp(wxScrollWinEvent& event)
2537 int scrollOrientation =
event.GetOrientation();
2539 int position = GetScrollPos(scrollOrientation);
2542 if (position < 0) position = 0;
2544 DoScrollCalc(position, scrollOrientation);
2547 void mpWindow::OnScrollLineDown(wxScrollWinEvent& event)
2549 int scrollOrientation =
event.GetOrientation();
2551 int position = GetScrollPos(scrollOrientation);
2553 int thumbSize = GetScrollThumb(scrollOrientation);
2555 int scrollRange = GetScrollRange(scrollOrientation);
2558 if (position > (scrollRange - thumbSize))
2559 position = scrollRange - thumbSize;
2561 DoScrollCalc(position, scrollOrientation);
2564 void mpWindow::OnScrollTop(wxScrollWinEvent& event)
2566 DoScrollCalc(0, event.GetOrientation());
2569 void mpWindow::OnScrollBottom(wxScrollWinEvent& event)
2571 int scrollOrientation =
event.GetOrientation();
2573 int thumbSize = GetScrollThumb(scrollOrientation);
2575 int scrollRange = GetScrollRange(scrollOrientation);
2577 DoScrollCalc(scrollRange - thumbSize, scrollOrientation);
2581 void mpWindow::SetScaleX(
double scaleX)
2583 if (scaleX != 0) m_scaleX = scaleX;
2589 unsigned int mpWindow::CountLayers()
2592 unsigned int layerNo = 0;
2596 if ((*li)->HasBBox()) layerNo++;
2602 mpLayer* mpWindow::GetLayer(
int position)
2604 if ((position >= (
int)m_layers.size()) || position < 0)
return nullptr;
2605 return m_layers[position];
2608 mpLayer* mpWindow::GetLayerByName(
const wxString&
name)
2612 if (!(*it)->GetName().Cmp(
name))
return *it;
2616 void mpWindow::GetBoundingBox(
double* bbox)
2624 bool mpWindow::SaveScreenshot(
2625 const wxString& filename,
int type, wxSize
imageSize,
bool fit)
2628 int bk_scrX, bk_scrY;
2640 SetScr(sizeX, sizeY);
2643 wxBitmap screenBuffer(sizeX, sizeY);
2644 wxMemoryDC screenDC;
2645 screenDC.SelectObject(screenBuffer);
2646 screenDC.SetPen(*wxTRANSPARENT_PEN);
2647 wxBrush brush(GetBackgroundColour());
2648 screenDC.SetBrush(brush);
2649 screenDC.DrawRectangle(0, 0, sizeX, sizeY);
2653 Fit(m_minX, m_maxX, m_minY, m_maxY, &sizeX, &sizeY);
2657 Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax, &sizeX,
2662 for (li = m_layers.begin(); li != m_layers.end(); ++li)
2663 (*li)->Plot(screenDC, *
this);
2668 SetScr(bk_scrX, bk_scrY);
2669 Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax,
2670 &bk_scrX, &bk_scrY);
2674 wxImage screenImage = screenBuffer.ConvertToImage();
2675 return screenImage.SaveFile(filename, (wxBitmapType)
type);
2678 void mpWindow::SetMargins(
int top,
int right,
int bottom,
int left)
2681 m_marginRight = right;
2682 m_marginBottom = bottom;
2683 m_marginLeft = left;
2686 mpInfoLayer* mpWindow::IsInsideInfoLayer(wxPoint& point)
2689 for (li = m_layers.begin(); li != m_layers.end(); ++li)
2691 #ifdef MATHPLOT_DO_LOGGING 2693 _(
"mpWindow::IsInsideInfoLayer() examinining layer = %p"), (*li));
2694 #endif // MATHPLOT_DO_LOGGING 2695 if ((*li)->IsInfo())
2697 mpInfoLayer* tmpLyr = (mpInfoLayer*)(*li);
2698 #ifdef MATHPLOT_DO_LOGGING 2699 wxLogMessage(_(
"mpWindow::IsInsideInfoLayer() layer = %p"), (*li));
2700 #endif // MATHPLOT_DO_LOGGING 2701 if (tmpLyr->Inside(point))
2710 void mpWindow::SetLayerVisible(
const wxString&
name,
bool viewable)
2712 mpLayer* lx = GetLayerByName(
name);
2715 lx->SetVisible(viewable);
2720 bool mpWindow::IsLayerVisible(
const wxString&
name)
2722 mpLayer* lx = GetLayerByName(
name);
2723 return (lx) ? lx->IsVisible() :
false;
2726 void mpWindow::SetLayerVisible(
const unsigned int position,
bool viewable)
2728 mpLayer* lx = GetLayer(position);
2731 lx->SetVisible(viewable);
2736 bool mpWindow::IsLayerVisible(
const unsigned int position)
2738 mpLayer* lx = GetLayer(position);
2739 return (lx) ? lx->IsVisible() :
false;
2742 void mpWindow::SetColourTheme(
2743 const wxColour& bgColour,
const wxColour& drawColour,
2744 const wxColour& axesColour)
2746 SetBackgroundColour(bgColour);
2747 SetForegroundColour(drawColour);
2748 m_bgColour = bgColour;
2749 m_fgColour = drawColour;
2750 m_axColour = axesColour;
2753 for (li = m_layers.begin(); li != m_layers.end(); ++li)
2755 if ((*li)->GetLayerType() == mpLAYER_AXIS)
2757 wxPen axisPen = (*li)->GetPen();
2759 axisPen.SetColour(axesColour);
2760 (*li)->SetPen(axisPen);
2762 if ((*li)->GetLayerType() == mpLAYER_INFO)
2764 wxPen infoPen = (*li)->GetPen();
2766 infoPen.SetColour(drawColour);
2767 (*li)->SetPen(infoPen);
2836 IMPLEMENT_DYNAMIC_CLASS(mpFXYVector, mpFXY)
2839 mpFXYVector::mpFXYVector(wxString
name,
int flags) : mpFXY(
name, flags)
2846 m_type = mpLAYER_PLOT;
2849 void mpFXYVector::Rewind() { m_index = 0; }
2850 bool mpFXYVector::GetNextXY(
double&
x,
double&
y)
2852 if (m_index >= m_xs.size())
2857 y = m_ys[m_index++];
2858 return m_index <= m_xs.size();
2862 void mpFXYVector::Clear()
2868 void mpFXYVector::SetData(
2869 const std::vector<float>& xs,
const std::vector<float>& ys)
2872 if (xs.size() != ys.size())
2875 _(
"wxMathPlot error: X and Y vector are not of the same length!"));
2878 const size_t N = xs.size();
2879 std::vector<double> Xd(N), Yd(N);
2880 for (
size_t i = 0; i < xs.size(); i++)
2888 void mpFXYVector::SetData(
2889 const std::vector<double>& xs,
const std::vector<double>& ys)
2892 if (xs.size() != ys.size())
2895 _(
"wxMathPlot error: X and Y vector are not of the same length!"));
2912 for (it = xs.begin(); it != xs.end(); ++it)
2914 if (*it < m_minX) m_minX = *it;
2915 if (*it > m_maxX) m_maxX = *it;
2917 for (it = ys.begin(); it != ys.end(); ++it)
2919 if (*it < m_minY) m_minY = *it;
2920 if (*it > m_maxY) m_maxY = *it;
2936 void mpFXYVector::AppendDataPoint(
float x,
float y)
2942 if (m_xs.size() == 1)
2949 const double margX = std::max(fabs(m_minX), fabs(m_maxX)) * 0.05;
2950 const double margY = std::max(fabs(m_minY), fabs(m_maxY)) * 0.05;
2959 m_minX =
std::min(
x - fabs(
x) * 0.05, m_minX);
2960 m_maxX = std::max(
x + fabs(
x) * 0.05, m_maxX);
2961 m_minY =
std::min(
y - fabs(
y) * 0.05, m_minY);
2962 m_maxY = std::max(
y + fabs(
y) * 0.05, m_maxY);
2970 IMPLEMENT_DYNAMIC_CLASS(mpText, mpLayer)
2976 mpText::mpText(wxString
name,
int offsetx,
int offsety)
2980 if (offsetx >= 0 && offsetx <= 100)
2981 m_offsetx = offsetx;
2985 if (offsety >= 0 && offsety <= 100)
2986 m_offsety = offsety;
2989 m_type = mpLAYER_INFO;
2996 void mpText::Plot(wxDC& dc, mpWindow&
w)
3003 wxCoord tw = 0, th = 0;
3004 dc.GetTextExtent(GetName(), &tw, &th);
3014 int px = m_offsetx *
3015 (
w.GetScrX() -
w.GetMarginLeft() -
w.GetMarginRight()) / 100;
3016 int py = m_offsety *
3017 (
w.GetScrY() -
w.GetMarginTop() -
w.GetMarginBottom()) / 100;
3018 dc.DrawText(GetName(), px, py);
3026 mpPrintout::mpPrintout(mpWindow* drawWindow,
const wxChar* title)
3030 plotWindow = drawWindow;
3033 bool mpPrintout::OnPrintPage(
int page)
3035 wxDC* trgDc = GetDC();
3036 if ((trgDc) && (page == 1))
3038 wxCoord m_prnX, m_prnY;
3041 trgDc->GetSize(&m_prnX, &m_prnY);
3043 m_prnX -= (2 * marginX);
3044 m_prnY -= (2 * marginY);
3045 trgDc->SetDeviceOrigin(marginX, marginY);
3047 #ifdef MATHPLOT_DO_LOGGING 3048 wxLogMessage(wxT(
"Print Size: %d x %d\n"), m_prnX, m_prnY);
3050 wxT(
"Screen Size: %d x %d\n"), plotWindow->GetScrX(),
3051 plotWindow->GetScrY());
3056 plotWindow->GetDesiredXmin(), plotWindow->GetDesiredXmax(),
3057 plotWindow->GetDesiredYmin(), plotWindow->GetDesiredYmax(), &m_prnX,
3061 wxColour oldBgColour = plotWindow->GetBackgroundColour();
3062 wxColour oldFgColour = plotWindow->GetForegroundColour();
3063 wxColour oldAxColour = plotWindow->GetAxesColour();
3066 trgDc->SetPen(*wxTRANSPARENT_PEN);
3068 wxBrush brush = *wxWHITE_BRUSH;
3069 trgDc->SetBrush(brush);
3070 trgDc->DrawRectangle(0, 0, m_prnX, m_prnY);
3076 for (
unsigned int li = 0; li < plotWindow->CountAllLayers(); ++li)
3078 layer = plotWindow->GetLayer(li);
3079 layer->Plot(*trgDc, *plotWindow);
3084 plotWindow->SetColourTheme(oldBgColour, oldFgColour, oldAxColour);
3087 plotWindow->GetDesiredXmin(), plotWindow->GetDesiredXmax(),
3088 plotWindow->GetDesiredYmin(), plotWindow->GetDesiredYmax(),
nullptr,
3090 plotWindow->UpdateAll();
3095 bool mpPrintout::HasPage(
int page) {
return (page == 1); }
3099 void mpMovableObject::TranslatePoint(
3100 double x,
double y,
double& out_x,
double& out_y)
3102 double ccos = cos(m_reference_phi);
3103 double csin = sin(m_reference_phi);
3105 out_x = m_reference_x + ccos *
x - csin *
y;
3106 out_y = m_reference_y + csin *
x + ccos *
y;
3111 void mpMovableObject::ShapeUpdated()
3114 if (m_shape_xs.size() != m_shape_ys.size())
3117 wxT(
"[mpMovableObject::ShapeUpdated] Error, m_shape_xs and " 3118 "m_shape_ys have different lengths!"));
3122 double ccos = cos(m_reference_phi);
3123 double csin = sin(m_reference_phi);
3125 m_trans_shape_xs.resize(m_shape_xs.size());
3126 m_trans_shape_ys.resize(m_shape_xs.size());
3131 m_bbox_min_x = 1e300;
3132 m_bbox_max_x = -1e300;
3133 m_bbox_min_y = 1e300;
3134 m_bbox_max_y = -1e300;
3136 for (itXo = m_trans_shape_xs.begin(), itYo = m_trans_shape_ys.begin(),
3137 itXi = m_shape_xs.begin(), itYi = m_shape_ys.begin();
3138 itXo != m_trans_shape_xs.end(); ++itXo, ++itYo, ++itXi, ++itYi)
3140 *itXo = m_reference_x + ccos * (*itXi) - csin * (*itYi);
3141 *itYo = m_reference_y + csin * (*itXi) + ccos * (*itYi);
3144 if (*itXo < m_bbox_min_x) m_bbox_min_x = *itXo;
3145 if (*itXo > m_bbox_max_x) m_bbox_max_x = *itXo;
3146 if (*itYo < m_bbox_min_y) m_bbox_min_y = *itYo;
3147 if (*itYo > m_bbox_max_y) m_bbox_max_y = *itYo;
3152 void mpMovableObject::Plot(wxDC& dc, mpWindow&
w)
3165 if (m_pen.GetWidth() <= 1)
3167 while (itX != m_trans_shape_xs.end())
3169 dc.DrawPoint(
w.x2p(*(itX++)),
w.y2p(*(itY++)));
3174 while (itX != m_trans_shape_xs.end())
3176 wxCoord cx =
w.x2p(*(itX++));
3177 wxCoord cy =
w.y2p(*(itY++));
3178 dc.DrawLine(cx, cy, cx, cy);
3184 wxCoord cx0 = 0, cy0 = 0;
3186 while (itX != m_trans_shape_xs.end())
3188 wxCoord cx =
w.x2p(*(itX++));
3189 wxCoord cy =
w.y2p(*(itY++));
3196 dc.DrawLine(cx0, cy0, cx, cy);
3202 if (!m_name.IsEmpty() && m_showName)
3207 dc.GetTextExtent(m_name, &tx, &
ty);
3212 (wxCoord)((m_bbox_max_x -
w.GetPosX()) *
w.GetScaleX());
3214 (wxCoord)((
w.GetPosY() - m_bbox_max_y) *
w.GetScaleY());
3221 const int sx =
w.GetScrX() >> 1;
3222 const int sy =
w.GetScrY() >> 1;
3224 if ((m_flags & mpALIGNMASK) == mpALIGN_NE)
3229 else if ((m_flags & mpALIGNMASK) == mpALIGN_NW)
3234 else if ((m_flags & mpALIGNMASK) == mpALIGN_SW)
3246 dc.DrawText(m_name, tx,
ty);
3257 void mpCovarianceEllipse::RecalculateShape()
3263 if (m_quantiles < 0)
3266 wxT(
"[mpCovarianceEllipse] Error: quantiles must be non-negative"));
3272 wxT(
"[mpCovarianceEllipse] Error: cov(0,0) must be non-negative"));
3278 wxT(
"[mpCovarianceEllipse] Error: cov(1,1) must be non-negative"));
3282 m_shape_xs.resize(m_segments, 0);
3283 m_shape_ys.resize(m_segments, 0);
3287 double b = -m_cov_00 - m_cov_11;
3288 double c = m_cov_00 * m_cov_11 - m_cov_01 * m_cov_01;
3290 double D =
b *
b - 4 *
c;
3295 wxT(
"[mpCovarianceEllipse] Error: cov is not positive definite"));
3299 double eigenVal0 = 0.5 * (-
b + sqrt(D));
3300 double eigenVal1 = 0.5 * (-
b - sqrt(D));
3304 double eigenVec0_x, eigenVec0_y;
3305 double eigenVec1_x, eigenVec1_y;
3312 else if (fabs(eigenVal0 - m_cov_00) > 1e-6)
3314 double k1x = m_cov_01 / (eigenVal0 - m_cov_00);
3316 eigenVec0_x = eigenVec0_y * k1x;
3320 double k1y = m_cov_01 / (eigenVal0 - m_cov_11);
3322 eigenVec0_y = eigenVec0_x * k1y;
3330 else if (fabs(eigenVal1 - m_cov_00) > 1e-6)
3332 double k2x = m_cov_01 / (eigenVal1 - m_cov_00);
3334 eigenVec1_x = eigenVec1_y * k2x;
3338 double k2y = m_cov_01 / (eigenVal1 - m_cov_11);
3340 eigenVec1_y = eigenVec1_x * k2y;
3344 double len = sqrt(eigenVec0_x * eigenVec0_x + eigenVec0_y * eigenVec0_y);
3348 len = sqrt(eigenVec1_x * eigenVec1_x + eigenVec1_y * eigenVec1_y);
3353 eigenVal0 = sqrt(eigenVal0);
3354 eigenVal1 = sqrt(eigenVal1);
3358 double M_00 = eigenVec0_x * eigenVal0;
3359 double M_01 = eigenVec0_y * eigenVal0;
3361 double M_10 = eigenVec1_x * eigenVal1;
3362 double M_11 = eigenVec1_y * eigenVal1;
3366 double Aang = 6.283185308 / (m_segments - 1);
3368 for (i = 0, ang = 0; i < m_segments; i++, ang += Aang)
3370 double ccos = cos(ang);
3371 double csin = sin(ang);
3373 m_shape_xs[i] = m_quantiles * (ccos * M_00 + csin * M_10);
3374 m_shape_ys[i] = m_quantiles * (ccos * M_01 + csin * M_11);
3383 void mpPolygon::setPoints(
3384 const std::vector<double>& points_xs,
const std::vector<double>& points_ys,
3387 if (points_xs.size() != points_ys.size())
3390 wxT(
"[mpPolygon] Error: points_xs and points_ys must have the same " 3391 "number of elements"));
3395 m_shape_xs = points_xs;
3396 m_shape_ys = points_ys;
3398 if (closedShape && !points_xs.empty())
3400 m_shape_xs.push_back(points_xs[0]);
3401 m_shape_ys.push_back(points_ys[0]);
3407 void mpPolygon::setPoints(
3408 const std::vector<float>& points_xs,
const std::vector<float>& points_ys,
3411 if (points_xs.size() != points_ys.size())
3414 wxT(
"[mpPolygon] Error: points_xs and points_ys must have the same " 3415 "number of elements"));
3419 m_shape_xs.resize(points_xs.size());
3420 m_shape_ys.resize(points_xs.size());
3422 if (!points_xs.empty())
3426 for (itX = points_xs.begin(), itY = points_ys.begin(),
3427 itXo = m_shape_xs.begin(), itYo = m_shape_ys.begin();
3428 itX != points_xs.end(); ++itX, ++itY, ++itXo, ++itYo)
3430 *itXo = (double)*itX;
3431 *itYo = (double)*itY;
3436 m_shape_xs.push_back((
double)points_xs[0]);
3437 m_shape_ys.push_back((
double)points_ys[0]);
3448 void mpBitmapLayer::GetBitmapCopy(wxImage& outBmp)
const 3450 if (m_validImg) outBmp = m_bitmap;
3453 void mpBitmapLayer::SetBitmap(
3454 const wxImage& inBmp,
double x,
double y,
double lx,
double ly)
3458 wxLogError(wxT(
"[mpBitmapLayer] Assigned bitmap is not Ok()!"));
3465 wxT(
"[mpBitmapLayer::SetBitmap] Assigned lx is negative!!"));
3470 wxT(
"[mpBitmapLayer::SetBitmap] Assigned ly is negative!!"));
3483 void mpBitmapLayer::Plot(wxDC& dc, mpWindow&
w)
3485 if (m_visible && m_validImg)
3513 wxCoord x0 =
w.x2p(m_min_x);
3514 wxCoord y0 =
w.y2p(m_max_y);
3515 wxCoord x1 =
w.x2p(m_max_x);
3516 wxCoord y1 =
w.y2p(m_min_y);
3521 double screenPixelX = (x1 - x0) / (
double)m_bitmap.GetWidth();
3522 double screenPixelY = (y1 - y0) / (
double)m_bitmap.GetHeight();
3526 wxCoord borderMarginX = (wxCoord)(screenPixelX + 1);
3527 wxCoord borderMarginY = (wxCoord)(screenPixelY + 1);
3531 wxCoord dx0 = x0, dx1 = x1, dy0 = y0, dy1 = y1;
3532 if (dx0 < 0) dx0 = -borderMarginX;
3533 if (dy0 < 0) dy0 = -borderMarginY;
3534 if (dx1 >
w.GetScrX()) dx1 =
w.GetScrX() + borderMarginX;
3535 if (dy1 >
w.GetScrY()) dy1 =
w.GetScrY() + borderMarginY;
3539 wxCoord d_width = dx1 - dx0 + 1;
3540 wxCoord d_height = dy1 - dy0 + 1;
3543 wxCoord offset_x = (wxCoord)((dx0 - x0) / screenPixelX);
3544 wxCoord offset_y = (wxCoord)((dy0 - y0) / screenPixelY);
3548 wxCoord b_width = (wxCoord)((dx1 - dx0 + 1) / screenPixelX);
3549 wxCoord b_height = (wxCoord)((dy1 - dy0 + 1) / screenPixelY);
3551 #ifdef MATHPLOT_DO_LOGGING 3553 _(
"[mpBitmapLayer::Plot] screenPixel: x=%f y=%f d_width=%ix%i"),
3554 screenPixelX, screenPixelY, d_width, d_height);
3556 _(
"[mpBitmapLayer::Plot] offset: x=%i y=%i bmpWidth=%ix%i"),
3557 offset_x, offset_y, b_width, b_height);
3561 if (d_width > 0 && d_height > 0)
3564 if (m_scaledBitmap.GetWidth() != d_width ||
3565 m_scaledBitmap.GetHeight() != d_height ||
3566 m_scaledBitmap_offset_x != offset_x ||
3567 m_scaledBitmap_offset_y != offset_y)
3569 wxRect
r(wxRect(offset_x, offset_y, b_width, b_height));
3571 if (
r.x < 0)
r.x = 0;
3572 if (
r.y < 0)
r.y = 0;
3573 if (
r.width > m_bitmap.GetWidth())
3574 r.width = m_bitmap.GetWidth();
3575 if (
r.height > m_bitmap.GetHeight())
3576 r.height = m_bitmap.GetHeight();
3578 m_scaledBitmap = wxBitmap(
3579 wxBitmap(m_bitmap).GetSubBitmap(
r).ConvertToImage().Scale(
3580 d_width, d_height));
3581 m_scaledBitmap_offset_x = offset_x;
3582 m_scaledBitmap_offset_y = offset_y;
3586 dc.DrawBitmap(m_scaledBitmap, dx0, dy0,
true);
3591 if (!m_name.IsEmpty() && m_showName)
3596 dc.GetTextExtent(m_name, &tx, &
ty);
3600 wxCoord sx = (wxCoord)((m_max_x -
w.GetPosX()) *
w.GetScaleX());
3601 wxCoord sy = (wxCoord)((
w.GetPosY() - m_max_y) *
w.GetScaleY());
3608 const int sx =
w.GetScrX() >> 1;
3609 const int sy =
w.GetScrY() >> 1;
3611 if ((m_flags & mpALIGNMASK) == mpALIGN_NE)
3616 else if ((m_flags & mpALIGNMASK) == mpALIGN_NW)
3621 else if ((m_flags & mpALIGNMASK) == mpALIGN_SW)
3633 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