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