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 #ifndef _USE_MATH_DEFINES 59 #define _USE_MATH_DEFINES // (For VS to define M_PI, etc. in cmath) 74 #define mpLEGEND_MARGIN 5 75 #define mpLEGEND_LINEWIDTH 10 78 #define mpMIN_X_AXIS_LABEL_SEPARATION 64 79 #define mpMIN_Y_AXIS_LABEL_SEPARATION 32 82 #define mpSCROLL_NUM_PIXELS_PER_LINE 10 85 double mpWindow::zoomIncrementalFactor = 1.5;
91 IMPLEMENT_ABSTRACT_CLASS(mpLayer, wxObject)
93 mpLayer::mpLayer() : m_type(mpLAYER_UNDEF)
95 SetPen((wxPen&)*wxBLACK_PEN);
96 SetFont((wxFont&)*wxNORMAL_FONT);
99 m_drawOutsideMargins =
TRUE;
103 wxBitmap mpLayer::GetColourSquare(
int side)
105 wxBitmap
square(side, side, -1);
106 wxColour filler = m_pen.GetColour();
107 wxBrush brush(filler, wxSOLID);
110 dc.SetBackground(brush);
112 dc.SelectObject(wxNullBitmap);
119 IMPLEMENT_DYNAMIC_CLASS(mpInfoLayer, mpLayer)
121 mpInfoLayer::mpInfoLayer()
123 m_dim = wxRect(0, 0, 1, 1);
124 m_brush = *wxTRANSPARENT_BRUSH;
129 m_type = mpLAYER_INFO;
132 mpInfoLayer::mpInfoLayer(wxRect rect,
const wxBrush* brush) : m_dim(rect)
135 m_reference.x = rect.x;
136 m_reference.y = rect.y;
139 m_type = mpLAYER_INFO;
142 mpInfoLayer::~mpInfoLayer() {}
143 void mpInfoLayer::UpdateInfo(mpWindow&
w, wxEvent& event) {}
144 bool mpInfoLayer::Inside(wxPoint& point) {
return m_dim.Contains(point); }
145 void mpInfoLayer::Move(wxPoint delta)
147 m_dim.SetX(m_reference.x + delta.x);
148 m_dim.SetY(m_reference.y + delta.y);
151 void mpInfoLayer::UpdateReference()
153 m_reference.x = m_dim.x;
154 m_reference.y = m_dim.y;
157 void mpInfoLayer::Plot(wxDC& dc, mpWindow&
w)
162 int scrx =
w.GetScrX();
163 int scry =
w.GetScrY();
165 if (scrx == 0) scrx = 1;
166 if (scry == 0) scry = 1;
168 if ((m_winX != scrx) || (m_winY != scry))
170 #ifdef MATHPLOT_DO_LOGGING 175 m_dim.x = (int)floor((
double)(m_dim.x * scrx / m_winX));
178 m_dim.y = (int)floor((
double)(m_dim.y * scry / m_winY));
189 dc.SetBrush(m_brush);
190 dc.DrawRectangle(m_dim.x, m_dim.y, m_dim.width, m_dim.height);
194 wxPoint mpInfoLayer::GetPosition()
const {
return m_dim.GetPosition(); }
195 wxSize mpInfoLayer::GetSize() {
return m_dim.GetSize(); }
196 mpInfoCoords::mpInfoCoords() : mpInfoLayer() {}
197 mpInfoCoords::mpInfoCoords(wxRect rect,
const wxBrush* brush)
198 : mpInfoLayer(rect, brush)
202 mpInfoCoords::~mpInfoCoords() {}
203 void mpInfoCoords::UpdateInfo(mpWindow&
w, wxEvent& event)
205 if (event.GetEventType() == wxEVT_MOTION)
207 int mouseX = ((wxMouseEvent&)event).GetX();
208 int mouseY = ((wxMouseEvent&)event).GetY();
215 m_content.Printf(wxT(
"x = %f y = %f"),
w.p2x(mouseX),
w.p2y(mouseY));
217 m_content.Printf(wxT(
"x = %f\ny = %f"),
w.p2x(mouseX),
w.p2y(mouseY));
222 void mpInfoCoords::Plot(wxDC& dc, mpWindow&
w)
227 int scrx =
w.GetScrX();
228 int scry =
w.GetScrY();
229 if ((m_winX != scrx) || (m_winY != scry))
231 #ifdef MATHPLOT_DO_LOGGING 236 m_dim.x = (int)floor((
double)(m_dim.x * scrx / m_winX));
239 m_dim.y = (int)floor((
double)(m_dim.y * scry / m_winY));
250 dc.SetBrush(m_brush);
253 dc.GetTextExtent(m_content, &textX, &textY);
254 if (m_dim.width < textX + 10) m_dim.width = textX + 10;
255 if (m_dim.height < textY + 10) m_dim.height = textY + 10;
256 dc.DrawRectangle(m_dim.x, m_dim.y, m_dim.width, m_dim.height);
257 dc.DrawText(m_content, m_dim.x + 5, m_dim.y + 5);
261 mpInfoLegend::mpInfoLegend() : mpInfoLayer() {}
262 mpInfoLegend::mpInfoLegend(wxRect rect,
const wxBrush* brush)
263 : mpInfoLayer(rect, brush)
267 mpInfoLegend::~mpInfoLegend() {}
268 void mpInfoLegend::UpdateInfo(mpWindow&
w, wxEvent& event) {}
269 void mpInfoLegend::Plot(wxDC& dc, mpWindow&
w)
274 int scrx =
w.GetScrX();
275 int scry =
w.GetScrY();
276 if ((m_winX != scrx) || (m_winY != scry))
278 #ifdef MATHPLOT_DO_LOGGING 283 m_dim.x = (int)floor((
double)(m_dim.x * scrx / m_winX));
286 m_dim.y = (int)floor((
double)(m_dim.y * scry / m_winY));
296 dc.SetBrush(m_brush);
302 int tmpX = 0, tmpY = 0;
303 mpLayer* ly =
nullptr;
306 for (
unsigned int p = 0;
p <
w.CountAllLayers();
p++)
309 if ((ly->GetLayerType() == mpLAYER_PLOT) && (ly->IsVisible()))
311 label = ly->GetName();
312 dc.GetTextExtent(label, &tmpX, &tmpY);
313 textX = (textX > (tmpX + baseWidth))
317 #ifdef MATHPLOT_DO_LOGGING 324 dc.SetBrush(m_brush);
329 m_dim.height = textY;
330 dc.DrawRectangle(m_dim.x, m_dim.y, m_dim.width, m_dim.height);
331 for (
unsigned int p2 = 0; p2 <
w.CountAllLayers(); p2++)
334 if ((ly->GetLayerType() == mpLAYER_PLOT) && (ly->IsVisible()))
336 label = ly->GetName();
338 dc.GetTextExtent(label, &tmpX, &tmpY);
354 label, m_dim.x + baseWidth,
367 IMPLEMENT_ABSTRACT_CLASS(mpFX, mpLayer)
369 mpFX::mpFX(wxString
name,
int flags)
373 m_type = mpLAYER_PLOT;
376 void mpFX::Plot(wxDC& dc, mpWindow&
w)
382 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
383 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
384 :
w.GetScrX() -
w.GetMarginRight();
385 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
386 wxCoord maxYpx = m_drawOutsideMargins
388 :
w.GetScrY() -
w.GetMarginBottom();
391 if (m_pen.GetWidth() <= 1)
393 for (wxCoord i = startPx; i < endPx; ++i)
395 iy =
w.y2p(GetY(
w.p2x(i)));
398 if (m_drawOutsideMargins || ((iy >= minYpx) && (iy <= maxYpx)))
406 for (wxCoord i = startPx; i < endPx; ++i)
408 iy =
w.y2p(GetY(
w.p2x(i)));
411 if (m_drawOutsideMargins || ((iy >= minYpx) && (iy <= maxYpx)))
412 dc.DrawLine(i, iy, i, iy);
419 if (!m_name.IsEmpty() && m_showName)
424 dc.GetTextExtent(m_name, &tx, &
ty);
433 if ((m_flags & mpALIGNMASK) == mpALIGN_RIGHT)
434 tx = (
w.GetScrX() - tx) -
w.GetMarginRight() - 8;
435 else if ((m_flags & mpALIGNMASK) == mpALIGN_CENTER)
436 tx = ((
w.GetScrX() -
w.GetMarginRight() -
w.GetMarginLeft() -
441 tx =
w.GetMarginLeft() + 8;
443 m_name, tx,
w.y2p(GetY(
w.p2x(tx))));
452 IMPLEMENT_ABSTRACT_CLASS(mpFY, mpLayer)
454 mpFY::mpFY(wxString
name,
int flags)
458 m_type = mpLAYER_PLOT;
461 void mpFY::Plot(wxDC& dc, mpWindow&
w)
469 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
470 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
471 :
w.GetScrX() -
w.GetMarginRight();
472 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
473 wxCoord maxYpx = m_drawOutsideMargins
475 :
w.GetScrY() -
w.GetMarginBottom();
477 if (m_pen.GetWidth() <= 1)
479 for (i = minYpx; i < maxYpx; ++i)
481 ix =
w.x2p(GetX(
w.p2y(i)));
482 if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx)))
488 for (i = 0; i <
w.GetScrY(); ++i)
490 ix =
w.x2p(GetX(
w.p2y(i)));
491 if (m_drawOutsideMargins || ((ix >= startPx) && (ix <= endPx)))
492 dc.DrawLine(ix, i, ix, i);
500 if (!m_name.IsEmpty() && m_showName)
505 dc.GetTextExtent(m_name, &tx, &
ty);
507 if ((m_flags & mpALIGNMASK) == mpALIGN_TOP)
508 ty =
w.GetMarginTop() + 8;
509 else if ((m_flags & mpALIGNMASK) == mpALIGN_CENTER)
510 ty = ((
w.GetScrY() -
w.GetMarginTop() -
w.GetMarginBottom() -
515 ty =
w.GetScrY() - 8 -
ty -
w.GetMarginBottom();
518 m_name,
w.x2p(GetX(
w.p2y(
ty))),
525 IMPLEMENT_ABSTRACT_CLASS(mpFXY, mpLayer)
527 mpFXY::mpFXY(wxString
name,
int flags)
531 m_type = mpLAYER_PLOT;
534 void mpFXY::UpdateViewBoundary(wxCoord xnew, wxCoord ynew)
537 maxDrawX = (xnew > maxDrawX) ? xnew : maxDrawX;
538 minDrawX = (xnew < minDrawX) ? xnew : minDrawX;
539 maxDrawY = (maxDrawY > ynew) ? maxDrawY : ynew;
540 minDrawY = (minDrawY < ynew) ? minDrawY : ynew;
544 void mpFXY::Plot(wxDC& dc, mpWindow&
w)
562 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
563 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
564 :
w.GetScrX() -
w.GetMarginRight();
565 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
566 wxCoord maxYpx = m_drawOutsideMargins
568 :
w.GetScrY() -
w.GetMarginBottom();
570 wxCoord ix = 0, iy = 0;
576 if (m_pen.GetWidth() <= 1)
578 while (GetNextXY(
x,
y))
582 if (m_drawOutsideMargins ||
583 ((ix >= startPx) && (ix <= endPx) && (iy >= minYpx) &&
586 dc.DrawPoint(ix, iy);
587 UpdateViewBoundary(ix, iy);
593 while (GetNextXY(
x,
y))
597 if (m_drawOutsideMargins ||
598 ((ix >= startPx) && (ix <= endPx) && (iy >= minYpx) &&
601 dc.DrawLine(ix, iy, ix, iy);
602 UpdateViewBoundary(ix, iy);
611 wxCoord x0 = 0, c0 = 0;
613 while (GetNextXY(
x,
y))
626 if ((x1 >= startPx) && (x0 <= endPx))
628 outDown = (c0 > maxYpx) && (c1 > maxYpx);
629 outUp = (c0 < minYpx) && (c1 < minYpx);
630 if (!outUp && !outDown)
637 (int)(((
float)(minYpx - c0)) / ((float)(c1 - c0)) * (x1 - x0)) +
644 (int)(((
float)(maxYpx - c0)) / ((float)(c1 - c0)) * (x1 - x0)) +
654 (int)(((
float)(minYpx - c0)) / ((float)(c1 - c0)) * (x1 - x0)) +
661 (int)(((
float)(maxYpx - c0)) / ((float)(c1 - c0)) * (x1 - x0)) +
675 (int)(((
float)(startPx - x0)) / ((float)(x1 - x0)) * (c1 - c0)) +
682 (int)(((
float)(endPx - x0)) / ((float)(x1 - x0)) * (c1 - c0)) +
687 dc.DrawLine(x0, c0, x1, c1);
688 UpdateViewBoundary(x1, c1);
696 if (!m_name.IsEmpty() && m_showName)
701 dc.GetTextExtent(m_name, &tx, &
ty);
708 if ((m_flags & mpALIGNMASK) == mpALIGN_NW)
713 else if ((m_flags & mpALIGNMASK) == mpALIGN_NE)
715 tx = maxDrawX - tx - 8;
718 else if ((m_flags & mpALIGNMASK) == mpALIGN_SE)
720 tx = maxDrawX - tx - 8;
721 ty = minDrawY -
ty - 8;
726 ty = minDrawY -
ty - 8;
730 dc.DrawText(m_name, tx,
ty);
739 IMPLEMENT_ABSTRACT_CLASS(mpProfile, mpLayer)
741 mpProfile::mpProfile(wxString
name,
int flags)
745 m_type = mpLAYER_PLOT;
748 void mpProfile::Plot(wxDC& dc, mpWindow&
w)
754 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
755 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
756 :
w.GetScrX() -
w.GetMarginRight();
757 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
758 wxCoord maxYpx = m_drawOutsideMargins
760 :
w.GetScrY() -
w.GetMarginBottom();
764 for (wxCoord i = startPx; i < endPx; ++i)
766 wxCoord c0 =
w.y2p(GetY(
w.p2x(i)));
771 w.y2p(GetY(
w.p2x(i + 1)));
776 if (!m_drawOutsideMargins)
778 c0 = (c0 <= maxYpx) ? ((c0 >= minYpx) ? c0 : minYpx) : maxYpx;
779 c1 = (c1 <= maxYpx) ? ((c1 >= minYpx) ? c1 : minYpx) : maxYpx;
781 dc.DrawLine(i, c0, i + 1, c1);
783 if (!m_name.IsEmpty())
788 dc.GetTextExtent(m_name, &tx, &
ty);
790 if ((m_flags & mpALIGNMASK) == mpALIGN_RIGHT)
791 tx = (
w.GetScrX() - tx) -
w.GetMarginRight() - 8;
792 else if ((m_flags & mpALIGNMASK) == mpALIGN_CENTER)
793 tx = ((
w.GetScrX() -
w.GetMarginRight() -
w.GetMarginLeft() -
798 tx =
w.GetMarginLeft() + 8;
800 dc.DrawText(m_name, tx,
w.y2p(GetY(
w.p2x(tx))));
815 #define mpLN10 2.3025850929940456840179914546844 817 IMPLEMENT_DYNAMIC_CLASS(mpScaleX, mpLayer)
819 mpScaleX::mpScaleX(wxString
name,
int flags,
bool ticks,
unsigned int type)
822 SetFont((wxFont&)*wxSMALL_FONT);
823 SetPen((wxPen&)*wxGREY_PEN);
827 m_type = mpLAYER_AXIS;
828 m_labelFormat = wxT(
"");
831 void mpScaleX::Plot(wxDC& dc, mpWindow&
w)
839 const int extend =
w.GetScrX();
840 if (m_flags == mpALIGN_CENTER)
842 if (m_flags == mpALIGN_TOP)
844 if (m_drawOutsideMargins)
845 orgy = X_BORDER_SEPARATION;
847 orgy =
w.GetMarginTop();
849 if (m_flags == mpALIGN_BOTTOM)
851 if (m_drawOutsideMargins)
852 orgy = X_BORDER_SEPARATION;
854 orgy =
w.GetScrY() -
w.GetMarginBottom();
856 if (m_flags == mpALIGN_BORDER_BOTTOM)
857 orgy =
w.GetScrY() - 1;
858 if (m_flags == mpALIGN_BORDER_TOP) orgy = 1;
860 dc.DrawLine(0, orgy,
w.GetScrX(), orgy);
869 const double dig = floor(log(128.0 /
w.GetScaleX()) /
mpLN10);
870 const double step = exp(
mpLN10 * dig);
871 const double end =
w.GetPosX() + (double)extend /
w.GetScaleX();
877 if (m_labelType == mpX_NORMAL)
879 if (!m_labelFormat.IsEmpty())
892 fmt.Printf(wxT(
"%%.%df"), tmp >= -1 ? 2 : -tmp);
899 if (m_labelType == mpX_DATETIME)
901 fmt = (wxT(
"%04.0f-%02.0f-%02.0fT%02.0f:%02.0f:%02.0f"));
903 else if (m_labelType == mpX_DATE)
905 fmt = (wxT(
"%04.0f-%02.0f-%02.0f"));
907 else if ((m_labelType == mpX_TIME) && (
end / 60 < 2))
909 fmt = (wxT(
"%02.0f:%02.3f"));
913 fmt = (wxT(
"%02.0f:%02.0f:%02.0f"));
925 #ifdef MATHPLOT_DO_LOGGING 927 wxT(
"mpScaleX::Plot: dig: %f , step: %f, end: %f, n: %f"), dig,
930 wxCoord startPx = m_drawOutsideMargins ? 0 :
w.GetMarginLeft();
931 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
932 :
w.GetScrX() -
w.GetMarginRight();
933 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
934 wxCoord maxYpx = m_drawOutsideMargins
936 :
w.GetScrY() -
w.GetMarginBottom();
942 for (
n = n0;
n <
end;
n += step)
944 const int p = (int)((
n -
w.GetPosX()) *
w.GetScaleX());
945 #ifdef MATHPLOT_DO_LOGGING 946 wxLogMessage(wxT(
"mpScaleX::Plot: n: %f -> p = %d"),
n,
p);
948 if ((
p >= startPx) && (
p <= endPx))
952 if (m_flags == mpALIGN_BORDER_BOTTOM)
953 dc.DrawLine(
p, orgy,
p, orgy - 4);
955 dc.DrawLine(
p, orgy,
p, orgy + 4);
959 #if wxCHECK_VERSION(3, 0, 0) 960 m_pen.SetStyle(wxPENSTYLE_DOT);
962 m_pen.SetStyle(wxDOT);
965 if ((m_flags == mpALIGN_BOTTOM) && !m_drawOutsideMargins)
967 dc.DrawLine(
p, orgy + 4,
p, minYpx);
971 if ((m_flags == mpALIGN_TOP) && !m_drawOutsideMargins)
973 dc.DrawLine(
p, orgy - 4,
p, maxYpx);
977 dc.DrawLine(
p, 0 ,
p,
w.GetScrY());
980 #if wxCHECK_VERSION(3, 0, 0) 981 m_pen.SetStyle(wxPENSTYLE_SOLID);
983 m_pen.SetStyle(wxSOLID);
988 if (m_labelType == mpX_NORMAL)
990 else if (m_labelType == mpX_DATETIME)
992 time_t when = (time_t)
n;
993 struct tm tm = *localtime(&when);
995 fmt, (
double)tm.tm_year + 1900, (
double)tm.tm_mon + 1,
996 (
double)tm.tm_mday, (
double)tm.tm_hour,
997 (
double)tm.tm_min, (
double)tm.tm_sec);
999 else if (m_labelType == mpX_DATE)
1001 time_t when = (time_t)
n;
1002 struct tm tm = *localtime(&when);
1004 fmt, (
double)tm.tm_year + 1900, (
double)tm.tm_mon + 1,
1005 (
double)tm.tm_mday);
1008 (m_labelType == mpX_TIME) || (m_labelType == mpX_HOURS))
1010 double modulus = fabs(
n);
1011 double sign =
n / modulus;
1012 double hh = floor(modulus / 3600);
1013 double mm = floor((modulus - hh * 3600) / 60);
1014 double ss = modulus - hh * 3600 - mm * 60;
1015 #ifdef MATHPLOT_DO_LOGGING 1017 wxT(
"%02.0f Hours, %02.0f minutes, %02.0f seconds"),
1019 #endif // MATHPLOT_DO_LOGGING 1020 if (fmt.Len() == 20)
1021 s.Printf(fmt,
sign * hh, mm, floor(ss));
1023 s.Printf(fmt,
sign * mm, ss);
1025 dc.GetTextExtent(
s, &tx, &
ty);
1026 labelH = (labelH <=
ty) ?
ty : labelH;
1039 maxExtent = (tx > maxExtent)
1046 double labelStep = ceil(
1048 (
w.GetScaleX() * step)) *
1050 for (
n = n0;
n <
end;
n += labelStep)
1052 const int p = (int)((
n -
w.GetPosX()) *
w.GetScaleX());
1053 #ifdef MATHPLOT_DO_LOGGING 1055 wxT(
"mpScaleX::Plot: n_label = %f -> p_label = %d"),
n,
p);
1057 if ((
p >= startPx) && (
p <= endPx))
1060 if (m_labelType == mpX_NORMAL)
1062 else if (m_labelType == mpX_DATETIME)
1064 time_t when = (time_t)
n;
1065 struct tm tm = *localtime(&when);
1067 fmt, (
double)tm.tm_year + 1900, (
double)tm.tm_mon + 1,
1068 (
double)tm.tm_mday, (
double)tm.tm_hour,
1069 (
double)tm.tm_min, (
double)tm.tm_sec);
1071 else if (m_labelType == mpX_DATE)
1073 time_t when = (time_t)
n;
1074 struct tm tm = *localtime(&when);
1076 fmt, (
double)tm.tm_year + 1900, (
double)tm.tm_mon + 1,
1077 (
double)tm.tm_mday);
1080 (m_labelType == mpX_TIME) || (m_labelType == mpX_HOURS))
1082 double modulus = fabs(
n);
1083 double sign =
n / modulus;
1084 double hh = floor(modulus / 3600);
1085 double mm = floor((modulus - hh * 3600) / 60);
1086 double ss = modulus - hh * 3600 - mm * 60;
1087 #ifdef MATHPLOT_DO_LOGGING 1089 wxT(
"%02.0f Hours, %02.0f minutes, %02.0f seconds"),
1091 #endif // MATHPLOT_DO_LOGGING 1092 if (fmt.Len() == 20)
1093 s.Printf(fmt,
sign * hh, mm, floor(ss));
1095 s.Printf(fmt,
sign * mm, ss);
1097 dc.GetTextExtent(
s, &tx, &
ty);
1098 if ((m_flags == mpALIGN_BORDER_BOTTOM) ||
1099 (m_flags == mpALIGN_TOP))
1101 dc.DrawText(
s,
p - tx / 2, orgy - 4 -
ty);
1105 dc.DrawText(
s,
p - tx / 2, orgy + 4);
1111 dc.GetTextExtent(m_name, &tx, &
ty);
1114 case mpALIGN_BORDER_BOTTOM:
1115 dc.DrawText(m_name, extend - tx - 4, orgy - 8 -
ty - labelH);
1117 case mpALIGN_BOTTOM:
1119 if ((!m_drawOutsideMargins) &&
1120 (
w.GetMarginBottom() > (
ty + labelH + 8)))
1123 m_name, (endPx - startPx - tx) >> 1, orgy + 6 + labelH);
1127 dc.DrawText(m_name, extend - tx - 4, orgy - 4 -
ty);
1131 case mpALIGN_CENTER:
1132 dc.DrawText(m_name, extend - tx - 4, orgy - 4 -
ty);
1136 if ((!m_drawOutsideMargins) &&
1137 (
w.GetMarginTop() > (
ty + labelH + 8)))
1140 m_name, (endPx - startPx - tx) >> 1,
1141 orgy - 6 -
ty - labelH);
1145 dc.DrawText(m_name, extend - tx - 4, orgy + 4);
1149 case mpALIGN_BORDER_TOP:
1150 dc.DrawText(m_name, extend - tx - 4, orgy + 6 + labelH);
1168 IMPLEMENT_DYNAMIC_CLASS(mpScaleY, mpLayer)
1170 mpScaleY::mpScaleY(wxString
name,
int flags,
bool ticks)
1173 SetFont((wxFont&)*wxSMALL_FONT);
1174 SetPen((wxPen&)*wxGREY_PEN);
1177 m_type = mpLAYER_AXIS;
1178 m_labelFormat = wxT(
"");
1181 void mpScaleY::Plot(wxDC& dc, mpWindow&
w)
1189 const int extend =
w.GetScrY();
1190 if (m_flags == mpALIGN_CENTER)
1192 if (m_flags == mpALIGN_LEFT)
1194 if (m_drawOutsideMargins)
1195 orgx = Y_BORDER_SEPARATION;
1197 orgx =
w.GetMarginLeft();
1199 if (m_flags == mpALIGN_RIGHT)
1201 if (m_drawOutsideMargins)
1202 orgx =
w.GetScrX() - Y_BORDER_SEPARATION;
1204 orgx =
w.GetScrX() -
w.GetMarginRight();
1206 if (m_flags == mpALIGN_BORDER_RIGHT)
1207 orgx =
w.GetScrX() - 1;
1208 if (m_flags == mpALIGN_BORDER_LEFT)
1212 dc.DrawLine(orgx, 0, orgx, extend);
1221 const double dig = floor(log(128.0 /
w.GetScaleY()) /
mpLN10);
1222 const double step = exp(
mpLN10 * dig);
1223 const double end =
w.GetPosY() + (double)extend /
w.GetScaleY();
1229 double maxScaleAbs = fabs(
w.GetDesiredYmax());
1230 double minScaleAbs = fabs(
w.GetDesiredYmin());
1232 (maxScaleAbs > minScaleAbs) ? maxScaleAbs : minScaleAbs;
1233 if (m_labelFormat.IsEmpty())
1235 if ((endscale < 1e4) && (endscale > 1e-3))
1242 fmt = m_labelFormat;
1257 (double)(extend -
w.GetMarginTop() -
w.GetMarginBottom()) /
1263 wxCoord endPx = m_drawOutsideMargins ?
w.GetScrX()
1264 :
w.GetScrX() -
w.GetMarginRight();
1265 wxCoord minYpx = m_drawOutsideMargins ? 0 :
w.GetMarginTop();
1266 wxCoord maxYpx = m_drawOutsideMargins
1268 :
w.GetScrY() -
w.GetMarginBottom();
1273 int labelHeigth = 0;
1275 dc.GetTextExtent(
s, &tx, &labelHeigth);
1276 for (;
n <
end;
n += step)
1278 const int p = (int)((
w.GetPosY() -
n) *
w.GetScaleY());
1279 if ((
p >= minYpx) && (
p <= maxYpx))
1283 if (m_flags == mpALIGN_BORDER_LEFT)
1285 dc.DrawLine(orgx,
p, orgx + 4,
p);
1290 orgx - 4,
p, orgx,
p);
1295 #if wxCHECK_VERSION(3, 0, 0) 1296 m_pen.SetStyle(wxPENSTYLE_DOT);
1298 m_pen.SetStyle(wxDOT);
1301 if ((m_flags == mpALIGN_LEFT) && !m_drawOutsideMargins)
1303 dc.DrawLine(orgx - 4,
p, endPx,
p);
1307 if ((m_flags == mpALIGN_RIGHT) && !m_drawOutsideMargins)
1309 dc.DrawLine(minYpx,
p, orgx + 4,
p);
1313 dc.DrawLine(0 ,
p,
w.GetScrX(),
p);
1316 #if wxCHECK_VERSION(3, 0, 0) 1317 m_pen.SetStyle(wxPENSTYLE_SOLID);
1319 m_pen.SetStyle(wxSOLID);
1325 dc.GetTextExtent(
s, &tx, &
ty);
1326 #ifdef MATHPLOT_DO_LOGGING 1327 if (
ty != labelHeigth)
1329 wxT(
"mpScaleY::Plot: ty(%f) and labelHeigth(%f) " 1333 labelW = (labelW <= tx) ? tx : labelW;
1336 if ((m_flags == mpALIGN_BORDER_LEFT) ||
1337 (m_flags == mpALIGN_RIGHT))
1338 dc.DrawText(
s, orgx + 4,
p -
ty / 2);
1343 tmp =
p - labelHeigth / 2;
1349 dc.GetTextExtent(m_name, &tx, &
ty);
1352 case mpALIGN_BORDER_LEFT:
1353 dc.DrawText(m_name, labelW + 8, 4);
1357 if ((!m_drawOutsideMargins) &&
1358 (
w.GetMarginLeft() > (
ty + labelW + 8)))
1361 m_name, orgx - 6 - labelW -
ty,
1362 (maxYpx - minYpx + tx) >> 1, 90);
1366 dc.DrawText(m_name, orgx + 4, 4);
1370 case mpALIGN_CENTER:
1371 dc.DrawText(m_name, orgx + 4, 4);
1375 if ((!m_drawOutsideMargins) &&
1376 (
w.GetMarginRight() > (
ty + labelW + 8)))
1379 m_name, orgx + 6 + labelW, (maxYpx - minYpx + tx) >> 1,
1384 dc.DrawText(m_name, orgx - tx - 4, 4);
1388 case mpALIGN_BORDER_RIGHT:
1389 dc.DrawText(m_name, orgx - 6 - tx - labelW, 4);
1413 IMPLEMENT_DYNAMIC_CLASS(mpWindow, wxWindow)
1415 BEGIN_EVENT_TABLE(mpWindow, wxWindow)
1416 EVT_PAINT(mpWindow::OnPaint)
1417 EVT_SIZE(mpWindow::OnSize)
1418 EVT_SCROLLWIN_THUMBTRACK(mpWindow::OnScrollThumbTrack)
1419 EVT_SCROLLWIN_PAGEUP(mpWindow::OnScrollPageUp)
1420 EVT_SCROLLWIN_PAGEDOWN(mpWindow::OnScrollPageDown)
1421 EVT_SCROLLWIN_LINEUP(mpWindow::OnScrollLineUp)
1422 EVT_SCROLLWIN_LINEDOWN(mpWindow::OnScrollLineDown)
1423 EVT_SCROLLWIN_TOP(mpWindow::OnScrollTop)
1424 EVT_SCROLLWIN_BOTTOM(mpWindow::OnScrollBottom)
1426 EVT_MIDDLE_UP(mpWindow::OnShowPopupMenu)
1428 EVT_RIGHT_UP(mpWindow::OnShowPopupMenu)
1429 EVT_MOUSEWHEEL(mpWindow::OnMouseWheel)
1430 EVT_MOTION(mpWindow::OnMouseMove)
1431 EVT_LEFT_DOWN(mpWindow::OnMouseLeftDown)
1432 EVT_LEFT_UP(mpWindow::OnMouseLeftRelease)
1434 EVT_MENU(mpID_CENTER, mpWindow::OnCenter)
1435 EVT_MENU(mpID_FIT, mpWindow::OnFit)
1436 EVT_MENU(mpID_ZOOM_IN, mpWindow::OnZoomIn)
1437 EVT_MENU(mpID_ZOOM_OUT, mpWindow::OnZoomOut)
1438 EVT_MENU(mpID_LOCKASPECT, mpWindow::OnLockAspect)
1439 EVT_MENU(mpID_HELP_MOUSE, mpWindow::OnMouseHelp)
1440 EVT_MENU(mpID_PRINT, mpWindow::OnPrintMenu)
1444 wxWindow* parent, wxWindowID
id, const wxPoint& pos, const wxSize&
size,
1446 : wxWindow(parent,
id, pos,
size, flag, wxT("mathplot"))
1448 m_scaleX = m_scaleY = 1.0;
1449 m_posX = m_posY = 0;
1450 m_desiredXmin = m_desiredYmin = 0;
1451 m_desiredXmax = m_desiredYmax = 1;
1452 m_scrX = m_scrY = 64;
1453 m_minX = m_minY = 0;
1454 m_maxX = m_maxY = 0;
1455 m_last_lx = m_last_ly = 0;
1456 m_buff_bmp =
nullptr;
1457 m_enableDoubleBuffer =
FALSE;
1458 m_enableMouseNavigation =
TRUE;
1459 m_mouseMovedAfterRightClick =
FALSE;
1460 m_movingInfoLayer =
nullptr;
1467 m_lockaspect =
FALSE;
1470 mpID_CENTER, _(
"Center"), _(
"Center plot view to this position"));
1471 m_popmenu.Append(mpID_FIT, _(
"Fit"), _(
"Set plot view to show all items"));
1472 m_popmenu.Append(mpID_ZOOM_IN, _(
"Zoom in"), _(
"Zoom in plot view."));
1473 m_popmenu.Append(mpID_ZOOM_OUT, _(
"Zoom out"), _(
"Zoom out plot view."));
1474 m_popmenu.AppendCheckItem(
1475 mpID_LOCKASPECT, _(
"Lock aspect"),
1476 _(
"Lock horizontal and vertical zoom aspect."));
1478 mpID_PRINT, _(
"Print..."), _(
"Allows printing the graph."));
1480 mpID_HELP_MOUSE, _(
"Show mouse commands..."),
1481 _(
"Show help about the mouse commands."));
1484 SetBackgroundColour(*wxWHITE);
1485 m_bgColour = *wxWHITE;
1486 m_fgColour = *wxBLACK;
1488 m_enableScrollBars =
false;
1489 SetSizeHints(128, 128);
1495 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
1500 mpWindow::~mpWindow()
1503 DelAllLayers(
true,
false);
1508 m_buff_bmp =
nullptr;
1515 void mpWindow::OnMouseRightDown(wxMouseEvent& event)
1517 m_mouseMovedAfterRightClick =
FALSE;
1518 m_mouseRClick_X =
event.GetX();
1519 m_mouseRClick_Y =
event.GetY();
1520 if (m_enableMouseNavigation)
1522 SetCursor(*wxCROSS_CURSOR);
1528 void mpWindow::OnMouseWheel(wxMouseEvent& event)
1530 if (!m_enableMouseNavigation)
1538 if (event.m_controlDown)
1540 wxPoint clickPt(event.GetX(),
event.GetY());
1542 if (event.GetWheelRotation() > 0)
1551 -
event.GetWheelRotation();
1552 float changeUnitsX = change / m_scaleX;
1553 float changeUnitsY = change / m_scaleY;
1555 if (event.m_shiftDown)
1557 m_posX += changeUnitsX;
1558 m_desiredXmax += changeUnitsX;
1559 m_desiredXmin += changeUnitsX;
1563 m_posY -= changeUnitsY;
1564 m_desiredYmax -= changeUnitsY;
1565 m_desiredYmax -= changeUnitsY;
1574 void mpWindow::OnMouseMove(wxMouseEvent& event)
1576 if (!m_enableMouseNavigation)
1582 if (event.m_rightDown)
1584 m_mouseMovedAfterRightClick =
1588 int Ax = m_mouseRClick_X -
event.GetX();
1589 int Ay = m_mouseRClick_Y -
event.GetY();
1592 m_mouseRClick_X =
event.GetX();
1593 m_mouseRClick_Y =
event.GetY();
1595 double Ax_units = Ax / m_scaleX;
1596 double Ay_units = -Ay / m_scaleY;
1600 m_desiredXmax += Ax_units;
1601 m_desiredXmin += Ax_units;
1602 m_desiredYmax += Ay_units;
1603 m_desiredYmin += Ay_units;
1607 #ifdef MATHPLOT_DO_LOGGING 1609 _(
"[mpWindow::OnMouseMove] Ax:%i Ay:%i m_posX:%f m_posY:%f"), Ax,
1610 Ay, m_posX, m_posY);
1615 if (event.m_leftDown)
1617 if (m_movingInfoLayer ==
nullptr)
1619 wxClientDC dc(
this);
1620 wxPen pen(*wxBLACK, 1, wxDOT);
1622 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1624 m_mouseLClick_X, m_mouseLClick_Y,
1625 event.GetX() - m_mouseLClick_X,
1626 event.GetY() - m_mouseLClick_Y);
1631 event.GetX() - m_mouseLClick_X,
1632 event.GetY() - m_mouseLClick_Y);
1633 m_movingInfoLayer->Move(moveVector);
1640 for (li = m_layers.begin(); li != m_layers.end(); ++li)
1642 if ((*li)->IsInfo() && (*li)->IsVisible())
1644 mpInfoLayer* tmpLyr = (mpInfoLayer*)(*li);
1645 tmpLyr->UpdateInfo(*
this, event);
1647 RefreshRect(tmpLyr->GetRectangle());
1665 void mpWindow::OnMouseLeftDown(wxMouseEvent& event)
1667 m_mouseLClick_X =
event.GetX();
1668 m_mouseLClick_Y =
event.GetY();
1669 #ifdef MATHPLOT_DO_LOGGING 1671 _(
"mpWindow::OnMouseLeftDown() X = %d , Y = %d"), event.GetX(),
1674 wxPoint pointClicked =
event.GetPosition();
1675 m_movingInfoLayer = IsInsideInfoLayer(pointClicked);
1676 if (m_movingInfoLayer !=
nullptr)
1678 #ifdef MATHPLOT_DO_LOGGING 1680 _(
"mpWindow::OnMouseLeftDown() started moving layer %lx"),
1681 (
long int)m_movingInfoLayer);
1687 void mpWindow::OnMouseLeftRelease(wxMouseEvent& event)
1692 wxPoint release(event.GetX(),
event.GetY());
1693 wxPoint press(m_mouseLClick_X, m_mouseLClick_Y);
1694 if (m_movingInfoLayer !=
nullptr)
1696 m_movingInfoLayer->UpdateReference();
1697 m_movingInfoLayer =
nullptr;
1701 if (release != press)
1703 ZoomRect(press, release);
1718 void mpWindow::Fit()
1720 if (UpdateBBox()) Fit(m_minX, m_maxX, m_minY, m_maxY);
1725 double xMin,
double xMax,
double yMin,
double yMax, wxCoord* printSizeX,
1726 wxCoord* printSizeY)
1729 m_desiredXmin = xMin;
1730 m_desiredXmax = xMax;
1731 m_desiredYmin = yMin;
1732 m_desiredYmax = yMax;
1734 if (printSizeX !=
nullptr && printSizeY !=
nullptr)
1737 m_scrX = *printSizeX;
1738 m_scrY = *printSizeY;
1743 GetClientSize(&m_scrX, &m_scrY);
1751 m_scaleX = (Ax != 0) ? (m_scrX - m_marginLeft - m_marginRight) / Ax
1753 m_scaleY = (Ay != 0) ? (m_scrY - m_marginTop - m_marginBottom) / Ay
1758 #ifdef MATHPLOT_DO_LOGGING 1760 _(
"mpWindow::Fit()(lock) m_scaleX=%f,m_scaleY=%f"), m_scaleX,
1765 double s = m_scaleX < m_scaleY ? m_scaleX : m_scaleY;
1774 m_posX = (xMin + xMax) / 2 -
1775 ((m_scrX - m_marginLeft - m_marginRight) / 2. + m_marginLeft) /
1779 m_posY = (yMin + yMax) / 2 +
1780 ((m_scrY - m_marginTop - m_marginBottom) / 2. + m_marginTop) /
1783 #ifdef MATHPLOT_DO_LOGGING 1785 _(
"mpWindow::Fit() m_desiredXmin=%f m_desiredXmax=%f m_desiredYmin=%f " 1786 "m_desiredYmax=%f"),
1787 xMin, xMax, yMin, yMax);
1789 _(
"mpWindow::Fit() m_scaleX = %f , m_scrX = %d,m_scrY=%d, Ax=%f, " 1790 "Ay=%f, m_posX=%f, m_posY=%f"),
1791 m_scaleX, m_scrX, m_scrY, Ax, Ay, m_posX, m_posY);
1798 if (printSizeX ==
nullptr || printSizeY ==
nullptr) UpdateAll();
1802 void mpWindow::DoZoomInXCalc(
const int staticXpixel)
1805 double staticX = p2x(staticXpixel);
1807 m_scaleX = m_scaleX * zoomIncrementalFactor;
1809 m_posX = staticX - (staticXpixel / m_scaleX);
1811 m_desiredXmin = m_posX;
1813 m_posX + (m_scrX - (m_marginLeft + m_marginRight)) / m_scaleX;
1814 #ifdef MATHPLOT_DO_LOGGING 1816 _(
"mpWindow::DoZoomInXCalc() prior X coord: (%f), new X coord: (%f) " 1817 "SHOULD BE EQUAL!!"),
1818 staticX, p2x(staticXpixel));
1822 void mpWindow::DoZoomInYCalc(
const int staticYpixel)
1825 double staticY = p2y(staticYpixel);
1827 m_scaleY = m_scaleY * zoomIncrementalFactor;
1829 m_posY = staticY + (staticYpixel / m_scaleY);
1831 m_desiredYmax = m_posY;
1833 m_posY - (m_scrY - (m_marginTop + m_marginBottom)) / m_scaleY;
1834 #ifdef MATHPLOT_DO_LOGGING 1836 _(
"mpWindow::DoZoomInYCalc() prior Y coord: (%f), new Y coord: (%f) " 1837 "SHOULD BE EQUAL!!"),
1838 staticY, p2y(staticYpixel));
1842 void mpWindow::DoZoomOutXCalc(
const int staticXpixel)
1845 double staticX = p2x(staticXpixel);
1847 m_scaleX = m_scaleX / zoomIncrementalFactor;
1849 m_posX = staticX - (staticXpixel / m_scaleX);
1851 m_desiredXmin = m_posX;
1853 m_posX + (m_scrX - (m_marginLeft + m_marginRight)) / m_scaleX;
1854 #ifdef MATHPLOT_DO_LOGGING 1856 _(
"mpWindow::DoZoomOutXCalc() prior X coord: (%f), new X coord: (%f) " 1857 "SHOULD BE EQUAL!!"),
1858 staticX, p2x(staticXpixel));
1862 void mpWindow::DoZoomOutYCalc(
const int staticYpixel)
1865 double staticY = p2y(staticYpixel);
1867 m_scaleY = m_scaleY / zoomIncrementalFactor;
1869 m_posY = staticY + (staticYpixel / m_scaleY);
1871 m_desiredYmax = m_posY;
1873 m_posY - (m_scrY - (m_marginTop + m_marginBottom)) / m_scaleY;
1874 #ifdef MATHPLOT_DO_LOGGING 1876 _(
"mpWindow::DoZoomOutYCalc() prior Y coord: (%f), new Y coord: (%f) " 1877 "SHOULD BE EQUAL!!"),
1878 staticY, p2y(staticYpixel));
1882 void mpWindow::ZoomIn(
const wxPoint& centerPoint)
1884 wxPoint
c(centerPoint);
1885 if (
c == wxDefaultPosition)
1887 GetClientSize(&m_scrX, &m_scrY);
1888 c.x = (m_scrX - m_marginLeft - m_marginRight) / 2 +
1890 c.y = (m_scrY - m_marginTop - m_marginBottom) / 2 -
1895 double prior_layer_x = p2x(
c.x);
1896 double prior_layer_y = p2y(
c.y);
1899 m_scaleX = m_scaleX * zoomIncrementalFactor;
1900 m_scaleY = m_scaleY * zoomIncrementalFactor;
1903 m_posX = prior_layer_x -
c.x / m_scaleX;
1904 m_posY = prior_layer_y +
c.y / m_scaleY;
1906 m_desiredXmin = m_posX;
1909 (m_scrX - m_marginLeft - m_marginRight) /
1911 m_desiredYmax = m_posY;
1914 (m_scrY - m_marginTop - m_marginBottom) /
1917 #ifdef MATHPLOT_DO_LOGGING 1919 _(
"mpWindow::ZoomIn() prior coords: (%f,%f), new coords: (%f,%f) " 1920 "SHOULD BE EQUAL!!"),
1921 prior_layer_x, prior_layer_y, p2x(
c.x), p2y(
c.y));
1927 void mpWindow::ZoomOut(
const wxPoint& centerPoint)
1929 wxPoint
c(centerPoint);
1930 if (
c == wxDefaultPosition)
1932 GetClientSize(&m_scrX, &m_scrY);
1933 c.x = (m_scrX - m_marginLeft - m_marginRight) / 2 +
1935 c.y = (m_scrY - m_marginTop - m_marginBottom) / 2 -
1940 double prior_layer_x = p2x(
c.x);
1941 double prior_layer_y = p2y(
c.y);
1944 m_scaleX = m_scaleX / zoomIncrementalFactor;
1945 m_scaleY = m_scaleY / zoomIncrementalFactor;
1948 m_posX = prior_layer_x -
c.x / m_scaleX;
1949 m_posY = prior_layer_y +
c.y / m_scaleY;
1951 m_desiredXmin = m_posX;
1954 (m_scrX - m_marginLeft - m_marginRight) /
1956 m_desiredYmax = m_posY;
1959 (m_scrY - m_marginTop - m_marginBottom) /
1962 #ifdef MATHPLOT_DO_LOGGING 1964 _(
"mpWindow::ZoomOut() prior coords: (%f,%f), new coords: (%f,%f) " 1965 "SHOULD BE EQUAL!!"),
1966 prior_layer_x, prior_layer_y, p2x(
c.x), p2y(
c.y));
1971 void mpWindow::ZoomInX()
1973 m_scaleX = m_scaleX * zoomIncrementalFactor;
1977 void mpWindow::ZoomOutX()
1979 m_scaleX = m_scaleX / zoomIncrementalFactor;
1983 void mpWindow::ZoomInY()
1985 m_scaleY = m_scaleY * zoomIncrementalFactor;
1989 void mpWindow::ZoomOutY()
1991 m_scaleY = m_scaleY / zoomIncrementalFactor;
1995 void mpWindow::ZoomRect(wxPoint p0, wxPoint p1)
1998 double p0x = p2x(p0.x);
1999 double p0y = p2y(p0.y);
2000 double p1x = p2x(p1.x);
2001 double p1y = p2y(p1.y);
2004 double zoom_x_min = p0x < p1x ? p0x : p1x;
2005 double zoom_x_max = p0x > p1x ? p0x : p1x;
2006 double zoom_y_min = p0y < p1y ? p0y : p1y;
2007 double zoom_y_max = p0y > p1y ? p0y : p1y;
2009 #ifdef MATHPLOT_DO_LOGGING 2011 _(
"Zoom: (%f,%f)-(%f,%f)"), zoom_x_min, zoom_y_min, zoom_x_max,
2015 Fit(zoom_x_min, zoom_x_max, zoom_y_min, zoom_y_max);
2018 void mpWindow::LockAspect(
bool enable)
2020 m_lockaspect = enable;
2021 m_popmenu.Check(mpID_LOCKASPECT, enable);
2024 Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax);
2027 void mpWindow::OnShowPopupMenu(wxMouseEvent& event)
2030 if (m_enableMouseNavigation)
2032 SetCursor(*wxSTANDARD_CURSOR);
2035 if (!m_mouseMovedAfterRightClick)
2037 m_clickedX =
event.GetX();
2038 m_clickedY =
event.GetY();
2039 PopupMenu(&m_popmenu, event.GetX(),
event.GetY());
2043 void mpWindow::OnLockAspect(wxCommandEvent& WXUNUSED(event))
2045 LockAspect(!m_lockaspect);
2048 void mpWindow::OnMouseHelp(wxCommandEvent& WXUNUSED(event))
2051 _(
"Supported Mouse commands:\n \ 2052 - Left button down + Mark area: Rectangular zoom\n \ 2053 - Right button down + Move: Pan (Move)\n \ 2054 - Wheel: Vertical scroll\n \ 2055 - Wheel + SHIFT: Horizontal scroll\n \ 2056 - Wheel + CTRL: Zoom in/out"),
2057 _(
"wxMathPlot help"), wxOK,
this);
2060 void mpWindow::OnPrintMenu(wxCommandEvent& WXUNUSED(event))
2063 mpPrintout* plotPrint =
new mpPrintout(
this);
2064 mpPrintout* plotPrintPreview =
new mpPrintout(
this);
2065 wxPrintPreview* preview =
new wxPrintPreview(plotPrintPreview, plotPrint);
2066 wxPreviewFrame* frame =
new wxPreviewFrame(
2067 preview,
nullptr, wxT(
"Print Plot"), wxPoint(100, 100),
2069 frame->Centre(wxBOTH);
2070 frame->Initialize();
2074 void mpWindow::OnFit(wxCommandEvent& WXUNUSED(event)) { Fit(); }
2075 void mpWindow::OnCenter(wxCommandEvent& WXUNUSED(event))
2077 GetClientSize(&m_scrX, &m_scrY);
2078 int centerX = (m_scrX - m_marginLeft - m_marginRight) /
2080 int centerY = (m_scrY - m_marginTop - m_marginBottom) /
2082 SetPos(p2x(m_clickedX - centerX), p2y(m_clickedY - centerY));
2088 void mpWindow::OnZoomIn(wxCommandEvent& WXUNUSED(event))
2090 ZoomIn(wxPoint(m_mouseRClick_X, m_mouseRClick_Y));
2093 void mpWindow::OnZoomOut(wxCommandEvent& WXUNUSED(event)) { ZoomOut(); }
2094 void mpWindow::OnSize(wxSizeEvent& WXUNUSED(event))
2097 Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax);
2098 #ifdef MATHPLOT_DO_LOGGING 2100 _(
"mpWindow::OnSize() m_scrX = %d, m_scrY = %d"), m_scrX, m_scrY);
2101 #endif // MATHPLOT_DO_LOGGING 2104 bool mpWindow::AddLayer(mpLayer*
layer,
bool refreshDisplay)
2106 if (
layer !=
nullptr)
2108 m_layers.push_back(
layer);
2109 if (refreshDisplay) UpdateAll();
2115 bool mpWindow::DelLayer(
2116 mpLayer*
layer,
bool alsoDeleteObject,
bool refreshDisplay)
2119 for (layIt = m_layers.begin(); layIt != m_layers.end(); ++layIt)
2121 if (*layIt ==
layer)
2124 if (alsoDeleteObject)
delete *layIt;
2125 m_layers.erase(layIt);
2126 if (refreshDisplay) UpdateAll();
2133 void mpWindow::DelAllLayers(
bool alsoDeleteObject,
bool refreshDisplay)
2135 while (m_layers.size() > 0)
2138 if (alsoDeleteObject)
delete m_layers[0];
2139 m_layers.erase(m_layers.begin());
2141 if (refreshDisplay) UpdateAll();
2149 void mpWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
2152 dc.GetSize(&m_scrX, &m_scrY);
2155 #ifdef MATHPLOT_DO_LOGGING 2158 GetViewStart(&px, &py);
2160 _(
"[mpWindow::OnPaint] vis.area:%ix%i px=%i py=%i"), m_scrX, m_scrY,
2169 if (m_enableDoubleBuffer)
2171 if (m_last_lx != m_scrX || m_last_ly != m_scrY)
2173 if (m_buff_bmp)
delete m_buff_bmp;
2174 m_buff_bmp =
new wxBitmap(m_scrX, m_scrY);
2175 m_buff_dc.SelectObject(*m_buff_bmp);
2188 trgDc->SetPen(*wxTRANSPARENT_PEN);
2189 wxBrush brush(GetBackgroundColour());
2190 trgDc->SetBrush(brush);
2191 trgDc->SetTextForeground(m_fgColour);
2192 trgDc->DrawRectangle(0, 0, m_scrX, m_scrY);
2197 for (li = m_layers.begin(); li != m_layers.end(); ++li)
2199 (*li)->Plot(*trgDc, *
this);
2203 if (m_enableDoubleBuffer)
2207 dc.Blit(0, 0, m_scrX, m_scrY, trgDc, 0, 0);
2218 if (m_enableScrollBars)
2297 void mpWindow::SetMPScrollbars(
bool status)
2300 m_enableScrollBars =
status;
2303 SetScrollbar(wxHORIZONTAL, 0, 0, 0);
2304 SetScrollbar(wxVERTICAL, 0, 0, 0);
2340 bool mpWindow::UpdateBBox()
2354 m_minX = f->GetMinX();
2355 m_maxX = f->GetMaxX();
2356 m_minY = f->GetMinY();
2357 m_maxY = f->GetMaxY();
2361 if (f->GetMinX() < m_minX) m_minX = f->GetMinX();
2362 if (f->GetMaxX() > m_maxX) m_maxX = f->GetMaxX();
2363 if (f->GetMinY() < m_minY) m_minY = f->GetMinY();
2364 if (f->GetMaxY() > m_maxY) m_maxY = f->GetMaxY();
2369 #ifdef MATHPLOT_DO_LOGGING 2371 wxT(
"[mpWindow::UpdateBBox] Bounding box: Xmin = %f, Xmax = %f, Ymin = " 2373 m_minX, m_maxX, m_minY, m_maxY);
2374 #endif // MATHPLOT_DO_LOGGING 2435 void mpWindow::UpdateAll()
2439 if (m_enableScrollBars)
2442 GetClientSize(&cx, &cy);
2446 double leftMargin = m_marginLeft / m_scaleX;
2448 double maxX = (m_desiredXmax > m_maxX) ? m_desiredXmax : m_maxX;
2449 double minX = (m_desiredXmin < m_minX) ? m_desiredXmin : m_minX;
2450 if ((m_posX + leftMargin) < minX) minX = m_posX + leftMargin;
2452 int sizeX = (int)((maxX - minX) * m_scaleX);
2453 int thumbX = (int)(((m_posX + leftMargin) - minX) * m_scaleX);
2455 wxHORIZONTAL, thumbX, cx - (m_marginRight + m_marginLeft),
2461 double topMargin = m_marginTop / m_scaleY;
2463 double maxY = (m_desiredYmax > m_maxY) ? m_desiredYmax : m_maxY;
2464 if ((m_posY - topMargin) > maxY) maxY = m_posY - topMargin;
2465 double minY = (m_desiredYmin < m_minY) ? m_desiredYmin : m_minY;
2467 int sizeY = (int)((maxY - minY) * m_scaleY);
2468 int thumbY = (int)((maxY - (m_posY - topMargin)) * m_scaleY);
2470 wxVERTICAL, thumbY, cy - (m_marginTop + m_marginBottom),
2479 void mpWindow::DoScrollCalc(
const int position,
const int orientation)
2481 if (orientation == wxVERTICAL)
2485 double topMargin = m_marginTop / m_scaleY;
2487 double maxY = m_desiredYmax > m_maxY ? m_desiredYmax : m_maxY;
2489 SetPosY((maxY - (position / m_scaleY)) + topMargin);
2495 double leftMargin = m_marginLeft / m_scaleX;
2497 double minX = (m_desiredXmin < m_minX) ? m_desiredXmin : m_minX;
2499 SetPosX((minX + (position / m_scaleX)) - leftMargin);
2503 void mpWindow::OnScrollThumbTrack(wxScrollWinEvent& event)
2505 DoScrollCalc(event.GetPosition(),
event.GetOrientation());
2508 void mpWindow::OnScrollPageUp(wxScrollWinEvent& event)
2510 int scrollOrientation =
event.GetOrientation();
2512 int position = GetScrollPos(scrollOrientation);
2514 int thumbSize = GetScrollThumb(scrollOrientation);
2516 position -= thumbSize;
2517 if (position < 0) position = 0;
2519 DoScrollCalc(position, scrollOrientation);
2521 void mpWindow::OnScrollPageDown(wxScrollWinEvent& event)
2523 int scrollOrientation =
event.GetOrientation();
2525 int position = GetScrollPos(scrollOrientation);
2527 int thumbSize = GetScrollThumb(scrollOrientation);
2529 int scrollRange = GetScrollRange(scrollOrientation);
2531 position += thumbSize;
2532 if (position > (scrollRange - thumbSize))
2533 position = scrollRange - thumbSize;
2535 DoScrollCalc(position, scrollOrientation);
2538 void mpWindow::OnScrollLineUp(wxScrollWinEvent& event)
2540 int scrollOrientation =
event.GetOrientation();
2542 int position = GetScrollPos(scrollOrientation);
2545 if (position < 0) position = 0;
2547 DoScrollCalc(position, scrollOrientation);
2550 void mpWindow::OnScrollLineDown(wxScrollWinEvent& event)
2552 int scrollOrientation =
event.GetOrientation();
2554 int position = GetScrollPos(scrollOrientation);
2556 int thumbSize = GetScrollThumb(scrollOrientation);
2558 int scrollRange = GetScrollRange(scrollOrientation);
2561 if (position > (scrollRange - thumbSize))
2562 position = scrollRange - thumbSize;
2564 DoScrollCalc(position, scrollOrientation);
2567 void mpWindow::OnScrollTop(wxScrollWinEvent& event)
2569 DoScrollCalc(0, event.GetOrientation());
2572 void mpWindow::OnScrollBottom(wxScrollWinEvent& event)
2574 int scrollOrientation =
event.GetOrientation();
2576 int thumbSize = GetScrollThumb(scrollOrientation);
2578 int scrollRange = GetScrollRange(scrollOrientation);
2580 DoScrollCalc(scrollRange - thumbSize, scrollOrientation);
2584 void mpWindow::SetScaleX(
double scaleX)
2586 if (scaleX != 0) m_scaleX = scaleX;
2592 unsigned int mpWindow::CountLayers()
2595 unsigned int layerNo = 0;
2599 if ((*li)->HasBBox()) layerNo++;
2605 mpLayer* mpWindow::GetLayer(
int position)
2607 if ((position >= (
int)m_layers.size()) || position < 0)
return nullptr;
2608 return m_layers[position];
2611 mpLayer* mpWindow::GetLayerByName(
const wxString&
name)
2615 if (!(*it)->GetName().Cmp(
name))
return *it;
2619 void mpWindow::GetBoundingBox(
double* bbox)
2627 bool mpWindow::SaveScreenshot(
2628 const wxString& filename,
int type, wxSize
imageSize,
bool fit)
2631 int bk_scrX, bk_scrY;
2643 SetScr(sizeX, sizeY);
2646 wxBitmap screenBuffer(sizeX, sizeY);
2647 wxMemoryDC screenDC;
2648 screenDC.SelectObject(screenBuffer);
2649 screenDC.SetPen(*wxTRANSPARENT_PEN);
2650 wxBrush brush(GetBackgroundColour());
2651 screenDC.SetBrush(brush);
2652 screenDC.DrawRectangle(0, 0, sizeX, sizeY);
2656 Fit(m_minX, m_maxX, m_minY, m_maxY, &sizeX, &sizeY);
2660 Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax, &sizeX,
2665 for (li = m_layers.begin(); li != m_layers.end(); ++li)
2666 (*li)->Plot(screenDC, *
this);
2671 SetScr(bk_scrX, bk_scrY);
2672 Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax,
2673 &bk_scrX, &bk_scrY);
2677 wxImage screenImage = screenBuffer.ConvertToImage();
2678 return screenImage.SaveFile(filename, (wxBitmapType)
type);
2681 void mpWindow::SetMargins(
int top,
int right,
int bottom,
int left)
2684 m_marginRight = right;
2685 m_marginBottom = bottom;
2686 m_marginLeft = left;
2689 mpInfoLayer* mpWindow::IsInsideInfoLayer(wxPoint& point)
2692 for (li = m_layers.begin(); li != m_layers.end(); ++li)
2694 #ifdef MATHPLOT_DO_LOGGING 2696 _(
"mpWindow::IsInsideInfoLayer() examinining layer = %p"), (*li));
2697 #endif // MATHPLOT_DO_LOGGING 2698 if ((*li)->IsInfo())
2700 mpInfoLayer* tmpLyr = (mpInfoLayer*)(*li);
2701 #ifdef MATHPLOT_DO_LOGGING 2702 wxLogMessage(_(
"mpWindow::IsInsideInfoLayer() layer = %p"), (*li));
2703 #endif // MATHPLOT_DO_LOGGING 2704 if (tmpLyr->Inside(point))
2713 void mpWindow::SetLayerVisible(
const wxString&
name,
bool viewable)
2715 mpLayer* lx = GetLayerByName(
name);
2718 lx->SetVisible(viewable);
2723 bool mpWindow::IsLayerVisible(
const wxString&
name)
2725 mpLayer* lx = GetLayerByName(
name);
2726 return (lx) ? lx->IsVisible() :
false;
2729 void mpWindow::SetLayerVisible(
const unsigned int position,
bool viewable)
2731 mpLayer* lx = GetLayer(position);
2734 lx->SetVisible(viewable);
2739 bool mpWindow::IsLayerVisible(
const unsigned int position)
2741 mpLayer* lx = GetLayer(position);
2742 return (lx) ? lx->IsVisible() :
false;
2745 void mpWindow::SetColourTheme(
2746 const wxColour& bgColour,
const wxColour& drawColour,
2747 const wxColour& axesColour)
2749 SetBackgroundColour(bgColour);
2750 SetForegroundColour(drawColour);
2751 m_bgColour = bgColour;
2752 m_fgColour = drawColour;
2753 m_axColour = axesColour;
2756 for (li = m_layers.begin(); li != m_layers.end(); ++li)
2758 if ((*li)->GetLayerType() == mpLAYER_AXIS)
2760 wxPen axisPen = (*li)->GetPen();
2762 axisPen.SetColour(axesColour);
2763 (*li)->SetPen(axisPen);
2765 if ((*li)->GetLayerType() == mpLAYER_INFO)
2767 wxPen infoPen = (*li)->GetPen();
2769 infoPen.SetColour(drawColour);
2770 (*li)->SetPen(infoPen);
2839 IMPLEMENT_DYNAMIC_CLASS(mpFXYVector, mpFXY)
2842 mpFXYVector::mpFXYVector(wxString
name,
int flags) : mpFXY(
name, flags)
2849 m_type = mpLAYER_PLOT;
2852 void mpFXYVector::Rewind() { m_index = 0; }
2853 bool mpFXYVector::GetNextXY(
double&
x,
double&
y)
2855 if (m_index >= m_xs.size())
2860 y = m_ys[m_index++];
2861 return m_index <= m_xs.size();
2865 void mpFXYVector::Clear()
2871 void mpFXYVector::SetData(
2872 const std::vector<float>& xs,
const std::vector<float>& ys)
2875 if (xs.size() != ys.size())
2878 _(
"wxMathPlot error: X and Y vector are not of the same length!"));
2881 const size_t N = xs.size();
2882 std::vector<double> Xd(N), Yd(N);
2883 for (
size_t i = 0; i < xs.size(); i++)
2891 void mpFXYVector::SetData(
2892 const std::vector<double>& xs,
const std::vector<double>& ys)
2895 if (xs.size() != ys.size())
2898 _(
"wxMathPlot error: X and Y vector are not of the same length!"));
2915 for (it = xs.begin(); it != xs.end(); ++it)
2917 if (*it < m_minX) m_minX = *it;
2918 if (*it > m_maxX) m_maxX = *it;
2920 for (it = ys.begin(); it != ys.end(); ++it)
2922 if (*it < m_minY) m_minY = *it;
2923 if (*it > m_maxY) m_maxY = *it;
2939 void mpFXYVector::AppendDataPoint(
float x,
float y)
2945 if (m_xs.size() == 1)
2952 const double margX = std::max(fabs(m_minX), fabs(m_maxX)) * 0.05;
2953 const double margY = std::max(fabs(m_minY), fabs(m_maxY)) * 0.05;
2962 m_minX =
std::min(
x - fabs(
x) * 0.05, m_minX);
2963 m_maxX = std::max(
x + fabs(
x) * 0.05, m_maxX);
2964 m_minY =
std::min(
y - fabs(
y) * 0.05, m_minY);
2965 m_maxY = std::max(
y + fabs(
y) * 0.05, m_maxY);
2973 IMPLEMENT_DYNAMIC_CLASS(mpText, mpLayer)
2979 mpText::mpText(wxString
name,
int offsetx,
int offsety)
2983 if (offsetx >= 0 && offsetx <= 100)
2984 m_offsetx = offsetx;
2988 if (offsety >= 0 && offsety <= 100)
2989 m_offsety = offsety;
2992 m_type = mpLAYER_INFO;
2999 void mpText::Plot(wxDC& dc, mpWindow&
w)
3006 wxCoord tw = 0, th = 0;
3007 dc.GetTextExtent(GetName(), &tw, &th);
3017 int px = m_offsetx *
3018 (
w.GetScrX() -
w.GetMarginLeft() -
w.GetMarginRight()) / 100;
3019 int py = m_offsety *
3020 (
w.GetScrY() -
w.GetMarginTop() -
w.GetMarginBottom()) / 100;
3021 dc.DrawText(GetName(), px, py);
3029 mpPrintout::mpPrintout(mpWindow* drawWindow,
const wxChar* title)
3033 plotWindow = drawWindow;
3036 bool mpPrintout::OnPrintPage(
int page)
3038 wxDC* trgDc = GetDC();
3039 if ((trgDc) && (page == 1))
3041 wxCoord m_prnX, m_prnY;
3044 trgDc->GetSize(&m_prnX, &m_prnY);
3046 m_prnX -= (2 * marginX);
3047 m_prnY -= (2 * marginY);
3048 trgDc->SetDeviceOrigin(marginX, marginY);
3050 #ifdef MATHPLOT_DO_LOGGING 3051 wxLogMessage(wxT(
"Print Size: %d x %d\n"), m_prnX, m_prnY);
3053 wxT(
"Screen Size: %d x %d\n"), plotWindow->GetScrX(),
3054 plotWindow->GetScrY());
3059 plotWindow->GetDesiredXmin(), plotWindow->GetDesiredXmax(),
3060 plotWindow->GetDesiredYmin(), plotWindow->GetDesiredYmax(), &m_prnX,
3064 wxColour oldBgColour = plotWindow->GetBackgroundColour();
3065 wxColour oldFgColour = plotWindow->GetForegroundColour();
3066 wxColour oldAxColour = plotWindow->GetAxesColour();
3069 trgDc->SetPen(*wxTRANSPARENT_PEN);
3071 wxBrush brush = *wxWHITE_BRUSH;
3072 trgDc->SetBrush(brush);
3073 trgDc->DrawRectangle(0, 0, m_prnX, m_prnY);
3079 for (
unsigned int li = 0; li < plotWindow->CountAllLayers(); ++li)
3081 layer = plotWindow->GetLayer(li);
3082 layer->Plot(*trgDc, *plotWindow);
3087 plotWindow->SetColourTheme(oldBgColour, oldFgColour, oldAxColour);
3090 plotWindow->GetDesiredXmin(), plotWindow->GetDesiredXmax(),
3091 plotWindow->GetDesiredYmin(), plotWindow->GetDesiredYmax(),
nullptr,
3093 plotWindow->UpdateAll();
3098 bool mpPrintout::HasPage(
int page) {
return (page == 1); }
3102 void mpMovableObject::TranslatePoint(
3103 double x,
double y,
double& out_x,
double& out_y)
3105 double ccos = cos(m_reference_phi);
3106 double csin = sin(m_reference_phi);
3108 out_x = m_reference_x + ccos *
x - csin *
y;
3109 out_y = m_reference_y + csin *
x + ccos *
y;
3114 void mpMovableObject::ShapeUpdated()
3117 if (m_shape_xs.size() != m_shape_ys.size())
3120 wxT(
"[mpMovableObject::ShapeUpdated] Error, m_shape_xs and " 3121 "m_shape_ys have different lengths!"));
3125 double ccos = cos(m_reference_phi);
3126 double csin = sin(m_reference_phi);
3128 m_trans_shape_xs.resize(m_shape_xs.size());
3129 m_trans_shape_ys.resize(m_shape_xs.size());
3134 m_bbox_min_x = 1e300;
3135 m_bbox_max_x = -1e300;
3136 m_bbox_min_y = 1e300;
3137 m_bbox_max_y = -1e300;
3139 for (itXo = m_trans_shape_xs.begin(), itYo = m_trans_shape_ys.begin(),
3140 itXi = m_shape_xs.begin(), itYi = m_shape_ys.begin();
3141 itXo != m_trans_shape_xs.end(); ++itXo, ++itYo, ++itXi, ++itYi)
3143 *itXo = m_reference_x + ccos * (*itXi) - csin * (*itYi);
3144 *itYo = m_reference_y + csin * (*itXi) + ccos * (*itYi);
3147 if (*itXo < m_bbox_min_x) m_bbox_min_x = *itXo;
3148 if (*itXo > m_bbox_max_x) m_bbox_max_x = *itXo;
3149 if (*itYo < m_bbox_min_y) m_bbox_min_y = *itYo;
3150 if (*itYo > m_bbox_max_y) m_bbox_max_y = *itYo;
3155 void mpMovableObject::Plot(wxDC& dc, mpWindow&
w)
3168 if (m_pen.GetWidth() <= 1)
3170 while (itX != m_trans_shape_xs.end())
3172 dc.DrawPoint(
w.x2p(*(itX++)),
w.y2p(*(itY++)));
3177 while (itX != m_trans_shape_xs.end())
3179 wxCoord cx =
w.x2p(*(itX++));
3180 wxCoord cy =
w.y2p(*(itY++));
3181 dc.DrawLine(cx, cy, cx, cy);
3187 wxCoord cx0 = 0, cy0 = 0;
3189 while (itX != m_trans_shape_xs.end())
3191 wxCoord cx =
w.x2p(*(itX++));
3192 wxCoord cy =
w.y2p(*(itY++));
3199 dc.DrawLine(cx0, cy0, cx, cy);
3205 if (!m_name.IsEmpty() && m_showName)
3210 dc.GetTextExtent(m_name, &tx, &
ty);
3215 (wxCoord)((m_bbox_max_x -
w.GetPosX()) *
w.GetScaleX());
3217 (wxCoord)((
w.GetPosY() - m_bbox_max_y) *
w.GetScaleY());
3224 const int sx =
w.GetScrX() >> 1;
3225 const int sy =
w.GetScrY() >> 1;
3227 if ((m_flags & mpALIGNMASK) == mpALIGN_NE)
3232 else if ((m_flags & mpALIGNMASK) == mpALIGN_NW)
3237 else if ((m_flags & mpALIGNMASK) == mpALIGN_SW)
3249 dc.DrawText(m_name, tx,
ty);
3260 void mpCovarianceEllipse::RecalculateShape()
3266 if (m_quantiles < 0)
3269 wxT(
"[mpCovarianceEllipse] Error: quantiles must be non-negative"));
3275 wxT(
"[mpCovarianceEllipse] Error: cov(0,0) must be non-negative"));
3281 wxT(
"[mpCovarianceEllipse] Error: cov(1,1) must be non-negative"));
3285 m_shape_xs.resize(m_segments, 0);
3286 m_shape_ys.resize(m_segments, 0);
3290 double b = -m_cov_00 - m_cov_11;
3291 double c = m_cov_00 * m_cov_11 - m_cov_01 * m_cov_01;
3293 double D =
b *
b - 4 *
c;
3298 wxT(
"[mpCovarianceEllipse] Error: cov is not positive definite"));
3302 double eigenVal0 = 0.5 * (-
b + sqrt(D));
3303 double eigenVal1 = 0.5 * (-
b - sqrt(D));
3307 double eigenVec0_x, eigenVec0_y;
3308 double eigenVec1_x, eigenVec1_y;
3315 else if (fabs(eigenVal0 - m_cov_00) > 1e-6)
3317 double k1x = m_cov_01 / (eigenVal0 - m_cov_00);
3319 eigenVec0_x = eigenVec0_y * k1x;
3323 double k1y = m_cov_01 / (eigenVal0 - m_cov_11);
3325 eigenVec0_y = eigenVec0_x * k1y;
3333 else if (fabs(eigenVal1 - m_cov_00) > 1e-6)
3335 double k2x = m_cov_01 / (eigenVal1 - m_cov_00);
3337 eigenVec1_x = eigenVec1_y * k2x;
3341 double k2y = m_cov_01 / (eigenVal1 - m_cov_11);
3343 eigenVec1_y = eigenVec1_x * k2y;
3347 double len = sqrt(eigenVec0_x * eigenVec0_x + eigenVec0_y * eigenVec0_y);
3351 len = sqrt(eigenVec1_x * eigenVec1_x + eigenVec1_y * eigenVec1_y);
3356 eigenVal0 = sqrt(eigenVal0);
3357 eigenVal1 = sqrt(eigenVal1);
3361 double M_00 = eigenVec0_x * eigenVal0;
3362 double M_01 = eigenVec0_y * eigenVal0;
3364 double M_10 = eigenVec1_x * eigenVal1;
3365 double M_11 = eigenVec1_y * eigenVal1;
3369 double Aang = 6.283185308 / (m_segments - 1);
3371 for (i = 0, ang = 0; i < m_segments; i++, ang += Aang)
3373 double ccos = cos(ang);
3374 double csin = sin(ang);
3376 m_shape_xs[i] = m_quantiles * (ccos * M_00 + csin * M_10);
3377 m_shape_ys[i] = m_quantiles * (ccos * M_01 + csin * M_11);
3386 void mpPolygon::setPoints(
3387 const std::vector<double>& points_xs,
const std::vector<double>& points_ys,
3390 if (points_xs.size() != points_ys.size())
3393 wxT(
"[mpPolygon] Error: points_xs and points_ys must have the same " 3394 "number of elements"));
3398 m_shape_xs = points_xs;
3399 m_shape_ys = points_ys;
3401 if (closedShape && !points_xs.empty())
3403 m_shape_xs.push_back(points_xs[0]);
3404 m_shape_ys.push_back(points_ys[0]);
3410 void mpPolygon::setPoints(
3411 const std::vector<float>& points_xs,
const std::vector<float>& points_ys,
3414 if (points_xs.size() != points_ys.size())
3417 wxT(
"[mpPolygon] Error: points_xs and points_ys must have the same " 3418 "number of elements"));
3422 m_shape_xs.resize(points_xs.size());
3423 m_shape_ys.resize(points_xs.size());
3425 if (!points_xs.empty())
3429 for (itX = points_xs.begin(), itY = points_ys.begin(),
3430 itXo = m_shape_xs.begin(), itYo = m_shape_ys.begin();
3431 itX != points_xs.end(); ++itX, ++itY, ++itXo, ++itYo)
3433 *itXo = (double)*itX;
3434 *itYo = (double)*itY;
3439 m_shape_xs.push_back((
double)points_xs[0]);
3440 m_shape_ys.push_back((
double)points_ys[0]);
3451 void mpBitmapLayer::GetBitmapCopy(wxImage& outBmp)
const 3453 if (m_validImg) outBmp = m_bitmap;
3456 void mpBitmapLayer::SetBitmap(
3457 const wxImage& inBmp,
double x,
double y,
double lx,
double ly)
3461 wxLogError(wxT(
"[mpBitmapLayer] Assigned bitmap is not Ok()!"));
3468 wxT(
"[mpBitmapLayer::SetBitmap] Assigned lx is negative!!"));
3473 wxT(
"[mpBitmapLayer::SetBitmap] Assigned ly is negative!!"));
3486 void mpBitmapLayer::Plot(wxDC& dc, mpWindow&
w)
3488 if (m_visible && m_validImg)
3516 wxCoord x0 =
w.x2p(m_min_x);
3517 wxCoord y0 =
w.y2p(m_max_y);
3518 wxCoord x1 =
w.x2p(m_max_x);
3519 wxCoord y1 =
w.y2p(m_min_y);
3524 double screenPixelX = (x1 - x0) / (
double)m_bitmap.GetWidth();
3525 double screenPixelY = (y1 - y0) / (
double)m_bitmap.GetHeight();
3529 wxCoord borderMarginX = (wxCoord)(screenPixelX + 1);
3530 wxCoord borderMarginY = (wxCoord)(screenPixelY + 1);
3534 wxCoord dx0 = x0, dx1 = x1, dy0 = y0, dy1 = y1;
3535 if (dx0 < 0) dx0 = -borderMarginX;
3536 if (dy0 < 0) dy0 = -borderMarginY;
3537 if (dx1 >
w.GetScrX()) dx1 =
w.GetScrX() + borderMarginX;
3538 if (dy1 >
w.GetScrY()) dy1 =
w.GetScrY() + borderMarginY;
3542 wxCoord d_width = dx1 - dx0 + 1;
3543 wxCoord d_height = dy1 - dy0 + 1;
3546 wxCoord offset_x = (wxCoord)((dx0 - x0) / screenPixelX);
3547 wxCoord offset_y = (wxCoord)((dy0 - y0) / screenPixelY);
3551 wxCoord b_width = (wxCoord)((dx1 - dx0 + 1) / screenPixelX);
3552 wxCoord b_height = (wxCoord)((dy1 - dy0 + 1) / screenPixelY);
3554 #ifdef MATHPLOT_DO_LOGGING 3556 _(
"[mpBitmapLayer::Plot] screenPixel: x=%f y=%f d_width=%ix%i"),
3557 screenPixelX, screenPixelY, d_width, d_height);
3559 _(
"[mpBitmapLayer::Plot] offset: x=%i y=%i bmpWidth=%ix%i"),
3560 offset_x, offset_y, b_width, b_height);
3564 if (d_width > 0 && d_height > 0)
3567 if (m_scaledBitmap.GetWidth() != d_width ||
3568 m_scaledBitmap.GetHeight() != d_height ||
3569 m_scaledBitmap_offset_x != offset_x ||
3570 m_scaledBitmap_offset_y != offset_y)
3572 wxRect
r(wxRect(offset_x, offset_y, b_width, b_height));
3574 if (
r.x < 0)
r.x = 0;
3575 if (
r.y < 0)
r.y = 0;
3576 if (
r.width > m_bitmap.GetWidth())
3577 r.width = m_bitmap.GetWidth();
3578 if (
r.height > m_bitmap.GetHeight())
3579 r.height = m_bitmap.GetHeight();
3581 m_scaledBitmap = wxBitmap(
3582 wxBitmap(m_bitmap).GetSubBitmap(
r).ConvertToImage().Scale(
3583 d_width, d_height));
3584 m_scaledBitmap_offset_x = offset_x;
3585 m_scaledBitmap_offset_y = offset_y;
3589 dc.DrawBitmap(m_scaledBitmap, dx0, dy0,
true);
3594 if (!m_name.IsEmpty() && m_showName)
3599 dc.GetTextExtent(m_name, &tx, &
ty);
3603 wxCoord sx = (wxCoord)((m_max_x -
w.GetPosX()) *
w.GetScaleX());
3604 wxCoord sy = (wxCoord)((
w.GetPosY() - m_max_y) *
w.GetScaleY());
3611 const int sx =
w.GetScrX() >> 1;
3612 const int sy =
w.GetScrY() >> 1;
3614 if ((m_flags & mpALIGNMASK) == mpALIGN_NE)
3619 else if ((m_flags & mpALIGNMASK) == mpALIGN_NW)
3624 else if ((m_flags & mpALIGNMASK) == mpALIGN_SW)
3636 dc.DrawText(m_name, tx,
ty);
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei imageSize
const int INVALID_CLICK_COORDS
GLubyte GLubyte GLubyte GLubyte w
T square(const T x)
Inline function for the square of a number.
#define mpMIN_Y_AXIS_LABEL_SEPARATION
GLdouble GLdouble GLdouble r
GLuint const GLchar * name
#define mpSCROLL_NUM_PIXELS_PER_LINE
int sign(T x)
Returns the sign of X as "1" or "-1".
GLenum GLuint GLint GLint layer
#define mpMIN_X_AXIS_LABEL_SEPARATION
EVT_RIGHT_DOWN(mpWindow::OnMouseRightDown) EVT_MOUSEWHEEL(mpWindow
const Scalar * const_iterator
GLuint GLuint GLsizei GLenum type
#define mpLEGEND_LINEWIDTH