13 #include <wx/window.h> 24 #include "wx/object.h" 26 #include "wx/colour.h" 27 #include "wx/settings.h" 31 #include "wx/dcclient.h" 32 #include "wx/cursor.h" 36 #include <wx/bmpbuttn.h> 37 #include <wx/module.h> 38 #include <wx/msgdlg.h> 40 #include <wx/tipwin.h> 52 #define mpLEGEND_MARGIN 5 53 #define mpLEGEND_LINEWIDTH 10 56 #define mpMIN_X_AXIS_LABEL_SEPARATION 64 57 #define mpMIN_Y_AXIS_LABEL_SEPARATION 32 60 #define mpSCROLL_NUM_PIXELS_PER_LINE 10 69 IMPLEMENT_ABSTRACT_CLASS(
mpLayer, wxObject )
73 SetPen( (wxPen&) *wxBLACK_PEN );
74 SetFont( (wxFont&) *wxNORMAL_FONT );
77 m_drawOutsideMargins =
false;
84 wxBitmap square( side, side, -1 );
85 wxColour filler =
m_pen.GetColour();
86 wxBrush brush( filler, wxBRUSHSTYLE_SOLID );
89 dc.SelectObject( square );
90 dc.SetBackground( brush );
92 dc.SelectObject( wxNullBitmap );
104 m_dim = wxRect( 0, 0, 1, 1 );
105 m_brush = *wxTRANSPARENT_BRUSH;
106 m_reference.x = 0; m_reference.y = 0;
136 return m_dim.Contains( point );
171 #ifdef MATHPLOT_DO_LOGGING 201 return m_dim.GetPosition();
207 return m_dim.GetSize();
228 if( event.GetEventType() == wxEVT_MOTION )
252 #ifdef MATHPLOT_DO_LOGGING 277 dc.GetTextExtent(
m_content, &textX, &textY );
279 if(
m_dim.width < textX + 10 )
280 m_dim.width = textX + 10;
282 if(
m_dim.height < textY + 10 )
283 m_dim.height = textY + 10;
321 #ifdef MATHPLOT_DO_LOGGING 348 int tmpX = 0, tmpY = 0;
360 dc.GetTextExtent( label, &tmpX, &tmpY );
362 ( textX > (tmpX + baseWidth) ) ? textX : (tmpX + baseWidth +
mpLEGEND_MARGIN);
364 #ifdef MATHPLOT_DO_LOGGING 377 m_dim.height = textY;
388 dc.GetTextExtent( label, &tmpX, &tmpY );
410 double mpScaleXLog::X2p(
mpWindow& w,
double x )
416 double mpScaleXLog::P2x(
mpWindow& w,
double x )
422 double mpScaleX::X2p(
mpWindow& w,
double x )
428 double mpScaleX::P2x(
mpWindow& w,
double x )
434 double mpScaleY::X2p(
mpWindow& w,
double x )
440 double mpScaleY::P2x(
mpWindow& w,
double x )
476 if(
m_pen.GetWidth() <= 1 )
478 for( wxCoord
i = startPx;
i < endPx; ++
i )
480 iy = w.
y2p( GetY( w.
p2x(
i ) ) );
484 dc.DrawPoint(
i, iy );
489 for( wxCoord
i = startPx;
i < endPx; ++
i )
491 iy = w.
y2p( GetY( w.
p2x(
i ) ) );
495 dc.DrawLine(
i, iy,
i, iy );
507 dc.GetTextExtent(
m_name, &tx, &ty );
524 dc.DrawText(
m_name, tx, w.
y2p( GetY( w.
p2x( tx ) ) ) );
553 if(
m_pen.GetWidth() <= 1 )
555 for( i = minYpx; i < maxYpx; ++
i )
557 ix = w.
x2p( GetX( w.
p2y( i ) ) );
560 dc.DrawPoint( ix, i );
567 ix = w.
x2p( GetX( w.
p2y( i ) ) );
570 dc.DrawLine( ix, i, ix, i );
583 dc.GetTextExtent(
m_name, &tx, &ty );
593 dc.DrawText(
m_name, w.
x2p( GetX( w.
p2y( ty ) ) ), ty );
610 maxDrawX = minDrawX = maxDrawY = minDrawY = 0;
617 maxDrawX = (xnew > maxDrawX) ? xnew : maxDrawX;
618 minDrawX = (xnew < minDrawX) ? xnew : minDrawX;
619 maxDrawY = (maxDrawY > ynew) ? maxDrawY : ynew;
620 minDrawY = (minDrawY < ynew) ? minDrawY : ynew;
634 Rewind(); GetNextXY( x, y );
635 maxDrawX = x; minDrawX = x; maxDrawY = y; minDrawY = y;
644 dc.SetClippingRegion( startPx, minYpx, endPx - startPx + 1, maxYpx - minYpx + 1 );
646 wxCoord ix = 0, iy = 0;
652 if(
m_pen.GetWidth() <= 1 )
654 while( GetNextXY( x, y ) )
656 double px = m_scaleX->TransformToPlot( x );
657 double py = m_scaleY->TransformToPlot( y );
663 || ( (ix >= startPx) && (ix <= endPx) && (iy >= minYpx)
664 && (iy <= maxYpx) ) )
666 dc.DrawPoint( ix, iy );
667 UpdateViewBoundary( ix, iy );
673 while( GetNextXY( x, y ) )
675 double px = m_scaleX->TransformToPlot( x );
676 double py = m_scaleY->TransformToPlot( y );
682 || ( (ix >= startPx) && (ix <= endPx) && (iy >= minYpx)
683 && (iy <= maxYpx) ) )
685 dc.DrawLine( ix, iy, ix, iy );
686 UpdateViewBoundary( ix, iy );
697 wxCoord x0 = 0, c0 = 0;
700 while( GetNextXY( x, y ) )
702 double px = m_scaleX->TransformToPlot( x );
703 double py = m_scaleY->TransformToPlot( y );
705 if( py >= 0.0 && py <= 1.0 )
710 wxCoord x1 = w.
x2p( px );
711 wxCoord c1 = w.
y2p( py );
726 if( (x1 >= startPx)&&(x0 <= endPx) )
728 outDown = (c0 > maxYpx) && (c1 > maxYpx);
729 outUp = (c0 < minYpx) && (c1 < minYpx);
731 if( !outUp && !outDown )
733 dc.DrawLine( x0, c0, x1, c1 );
749 dc.GetTextExtent(
m_name, &tx, &ty );
761 else if( (m_flags & mpALIGNMASK) ==
mpALIGN_NE )
763 tx = maxDrawX - tx - 8;
766 else if( (m_flags & mpALIGNMASK) ==
mpALIGN_SE )
768 tx = maxDrawX - tx - 8;
769 ty = minDrawY - ty - 8;
775 ty = minDrawY - ty - 8;
779 dc.DrawText(
m_name, tx, ty );
783 dc.DestroyClippingRegion();
813 for( wxCoord
i = startPx;
i < endPx; ++
i )
815 wxCoord c0 = w.
y2p( GetY( w.
p2x(
i ) ) );
816 wxCoord c1 = w.
y2p( GetY( w.
p2x(
i + 1 ) ) );
822 c0 = (c0 <= maxYpx) ? ( (c0 >= minYpx) ? c0 : minYpx ) : maxYpx;
823 c1 = (c1 <= maxYpx) ? ( (c1 >= minYpx) ? c1 : minYpx ) : maxYpx;
826 dc.DrawLine(
i, c0,
i + 1, c1 );
836 dc.GetTextExtent(
m_name, &tx, &ty );
846 dc.DrawText(
m_name, tx, w.
y2p( GetY( w.
p2x( tx ) ) ) );
856 #define mpLN10 2.3025850929940456840179914546844 860 double minV, maxV, minVvis, maxVvis;
862 GetDataRange( minV, maxV );
863 getVisibleDataRange( w, minVvis, maxVvis );
869 m_tickValues.clear();
870 m_tickLabels.clear();
872 double minErr = 1000000000000.0;
873 double bestStep = 1.0;
875 for(
int i = 10;
i <= 20;
i += 2 )
877 double curr_step = fabs( maxVvis - minVvis ) / (double)
i;
878 double base = pow( 10, floor( log10( curr_step ) ) );
882 double stepInt = floor( curr_step / base ) * base;
883 double err = fabs( curr_step - stepInt );
895 double v = floor( minVvis / bestStep ) * bestStep;
897 double zeroOffset = 100000000.0;
902 m_tickValues.push_back( v );
904 if( fabs( v ) < zeroOffset )
905 zeroOffset = fabs( v );
911 if( zeroOffset <= bestStep )
913 for(
double& t : m_tickValues )
917 for(
double t : m_tickValues )
919 m_tickLabels.push_back(
TickLabel( t ) );
922 updateTickLabels( dc, w );
934 m_absVisibleMaxV = 0.0;
939 m_maxLabelHeight = 1;
944 int mpScaleBase::getLabelDecimalDigits(
int maxDigits )
948 for(
auto l : m_tickLabels )
963 m_maxLabelHeight = 0;
966 for(
int n = 0; n < labelCount(); n++ )
969 const wxString s = getLabel( n );
971 dc.GetTextExtent( s, &tx, &ty );
972 m_maxLabelHeight =
std::max( ty, m_maxLabelHeight );
973 m_maxLabelWidth =
std::max( tx, m_maxLabelWidth );
981 computeLabelExtents( dc, w );
1025 return m_tickValues.size();
1043 return m_tickValues[n];
1059 double pymin = w.
p2y( minYpx );
1060 double pymax = w.
p2y( maxYpx );
1064 minV = TransformFromPlot( pymax );
1065 maxV = TransformFromPlot( pymin );
1071 if( m_masterScale->m_tickValues.size() == 0 )
1074 m_tickValues.clear();
1075 m_tickLabels.clear();
1078 double p0 = m_masterScale->TransformToPlot( m_masterScale->m_tickValues[0] );
1079 double p1 = m_masterScale->TransformToPlot( m_masterScale->m_tickValues[1] );
1081 m_scale = 1.0 / ( m_maxV - m_minV );
1084 double y_slave0 = p0 / m_scale;
1085 double y_slave1 = p1 / m_scale;
1087 double dy_slave = (y_slave1 - y_slave0);
1088 double exponent = floor( log10( dy_slave ) );
1089 double base = dy_slave / pow( 10.0, exponent );
1091 double dy_scaled = ceil( 2.0 * base ) / 2.0 * pow( 10.0, exponent );
1093 double minvv, maxvv;
1095 getVisibleDataRange( w, minvv, maxvv );
1097 minvv = floor( minvv / dy_scaled ) * dy_scaled;
1099 m_scale = 1.0 / ( m_maxV - m_minV );
1100 m_scale *= dy_slave / dy_scaled;
1102 m_offset = p0 / m_scale - minvv;
1104 m_tickValues.clear();
1108 m_absVisibleMaxV = 0;
1110 for(
unsigned int i = 0;
i < m_masterScale->m_tickValues.size();
i++ )
1112 m = TransformFromPlot( m_masterScale->TransformToPlot( m_masterScale->m_tickValues[
i] ) );
1113 m_tickValues.push_back( m );
1114 m_tickLabels.push_back(
TickLabel( m ) );
1115 m_absVisibleMaxV =
std::max( m_absVisibleMaxV, fabs( m ) );
1126 computeSlaveTicks( w );
1127 updateTickLabels( dc, w );
1132 double minV, maxV, minVvis, maxVvis;
1133 GetDataRange( minV, maxV );
1134 getVisibleDataRange( w, minVvis, maxVvis );
1140 m_tickValues.clear();
1141 m_tickLabels.clear();
1144 double minErr = 1000000000000.0;
1145 double bestStep = 1.0;
1147 for(
int i = 10;
i <= 20;
i += 2 )
1149 double curr_step = fabs( maxVvis - minVvis ) / (double)
i;
1150 double base = pow( 10, floor( log10( curr_step ) ) );
1154 double stepInt = floor( curr_step / base ) * base;
1155 double err = fabs( curr_step - stepInt );
1167 double v = floor( minVvis / bestStep ) * bestStep;
1169 double zeroOffset = 100000000.0;
1172 const int iterLimit = 1000;
1175 while( v < maxVvis && i < iterLimit )
1177 m_tickValues.push_back( v );
1179 if( fabs( v ) < zeroOffset )
1180 zeroOffset = fabs( v );
1189 if( i == iterLimit )
1191 m_tickValues.clear();
1194 if( zeroOffset <= bestStep )
1196 for(
double& t : m_tickValues )
1200 for(
double t : m_tickValues )
1201 m_tickLabels.push_back(
TickLabel( t ) );
1209 updateTickLabels( dc, w );
1222 double pxmin = w.
p2x( startPx );
1223 double pxmax = w.
p2x( endPx );
1225 minV = TransformFromPlot( pxmin );
1226 maxV = TransformFromPlot( pxmax );
1232 double minV, maxV, minVvis, maxVvis;
1234 GetDataRange( minV, maxV );
1235 getVisibleDataRange( w, minVvis, maxVvis );
1238 double minDecade = pow( 10, floor( log10( minV ) ) );
1239 double maxDecade = pow( 10, ceil( log10( maxV ) ) );
1243 double visibleDecades = log( maxVvis / minVvis ) / log( 10 );
1247 m_tickValues.clear();
1248 m_tickLabels.clear();
1250 if( minDecade == 0.0 )
1254 for( d = minDecade; d<=maxDecade; d *= 10.0 )
1257 m_tickLabels.push_back(
TickLabel( d ) );
1259 for(
double dd = d; dd < d * 10; dd += d )
1261 if( visibleDecades < 2 )
1262 m_tickLabels.push_back(
TickLabel( dd ) );
1264 m_tickValues.push_back( dd );
1268 updateTickLabels( dc, w );
1279 SetFont( (wxFont&) *wxSMALL_FONT );
1280 SetPen( (wxPen&) *wxGREY_PEN );
1315 const int extend = w.
GetScrX();
1367 #ifdef MATHPLOT_DO_LOGGING 1368 wxLogMessage( wxT(
"mpScaleX::Plot: n: %f -> p = %d" ), n, p );
1371 if( (p >= startPx) && (p <= endPx) )
1376 dc.DrawLine( p, orgy, p, orgy - 4 );
1378 dc.DrawLine( p, orgy, p, orgy + 4 );
1382 m_pen.SetStyle( wxPENSTYLE_DOT );
1388 m_pen.SetStyle( wxPENSTYLE_DOT );
1390 dc.DrawLine( p, orgy + 4, p, minYpx );
1391 m_pen.SetStyle( wxPENSTYLE_SOLID );
1393 dc.DrawLine( p, orgy + 4, p, orgy - 4 );
1400 dc.DrawLine( p, orgy - 4, p, maxYpx );
1405 dc.DrawLine( p, minYpx, p, maxYpx );
1409 m_pen.SetStyle( wxPENSTYLE_SOLID );
1415 m_pen.SetStyle( wxPENSTYLE_SOLID );
1417 dc.DrawLine( startPx, minYpx, endPx, minYpx );
1418 dc.DrawLine( startPx, maxYpx, endPx, maxYpx );
1437 #ifdef MATHPLOT_DO_LOGGING 1438 wxLogMessage( wxT(
"mpScaleX::Plot: n_label = %f -> p_label = %d" ), n, p );
1441 if( (p >= startPx) && (p <= endPx) )
1446 dc.GetTextExtent( s, &tx, &ty );
1450 dc.DrawText( s, p - tx / 2, orgy - 4 - ty );
1454 dc.DrawText( s, p - tx / 2, orgy + 4 );
1460 dc.GetTextExtent(
m_name, &tx, &ty );
1465 dc.DrawText(
m_name, extend - tx - 4, orgy - 8 - ty - labelH );
1470 dc.DrawText(
m_name, (endPx + startPx) / 2 - tx / 2, orgy + 6 + labelH );
1475 dc.DrawText(
m_name, extend - tx - 4, orgy - 4 - ty );
1482 dc.DrawText(
m_name, (endPx - startPx - tx) >> 1, orgy - 6 - ty - labelH );
1486 dc.DrawText(
m_name, extend - tx - 4, orgy + 4 );
1492 dc.DrawText(
m_name, extend - tx - 4, orgy + 6 + labelH );
1507 SetFont( (wxFont&) *wxSMALL_FONT );
1508 SetPen( (wxPen&) *wxGREY_PEN );
1512 m_masterScale = NULL;
1562 dc.DrawLine( orgx, minYpx, orgx, maxYpx );
1573 int labelHeigth = 0;
1575 dc.GetTextExtent( s, &tx, &labelHeigth );
1588 if( (p >= minYpx) && (p <= maxYpx) )
1594 dc.DrawLine( orgx, p, orgx + 4, p );
1598 dc.DrawLine( orgx - 4, p, orgx, p );
1603 dc.DrawLine( orgx - 4, p, orgx + 4, p );
1605 m_pen.SetStyle( wxPENSTYLE_DOT );
1610 dc.DrawLine( orgx - 4, p, endPx, p );
1617 dc.DrawLine( orgx - 4, p, endPx, p );
1621 dc.DrawLine( orgx - 4, p, endPx, p );
1626 m_pen.SetStyle( wxPENSTYLE_SOLID );
1647 if( (p >= minYpx) && (p <= maxYpx) )
1650 dc.GetTextExtent( s, &tx, &ty );
1653 dc.DrawText( s, orgx + 4, p - ty / 2 );
1655 dc.DrawText( s, orgx - 4 - tx, p - ty / 2 );
1662 dc.GetTextExtent(
m_name, &tx, &ty );
1667 dc.DrawText(
m_name, labelW + 8, 4 );
1675 dc.DrawText(
m_name, orgx + 4, minYpx - ty - 4 );
1681 dc.DrawText(
m_name, orgx + 4, 4 );
1691 dc.DrawText(
m_name, orgx - tx - 4, minYpx - ty - 4 );
1697 dc.DrawText(
m_name, orgx - 6 - tx - labelW, 4 );
1711 IMPLEMENT_DYNAMIC_CLASS(
mpWindow, wxWindow )
1713 BEGIN_EVENT_TABLE(
mpWindow, wxWindow )
1725 EVT_RIGHT_UP(
mpWindow::OnShowPopupMenu )
1726 EVT_MOUSEWHEEL(
mpWindow::OnMouseWheel )
1727 EVT_MOTION(
mpWindow::OnMouseMove )
1728 EVT_LEFT_DOWN(
mpWindow::OnMouseLeftDown )
1729 EVT_LEFT_UP(
mpWindow::OnMouseLeftRelease )
1743 : wxWindow( parent,
id, pos, size, flag, wxT( "mathplot" ) )
1746 m_scaleX = m_scaleY = 1.0;
1747 m_posX = m_posY = 0;
1748 m_desiredXmin = m_desiredYmin = 0;
1749 m_desiredXmax = m_desiredYmax = 1;
1750 m_scrX = m_scrY = 64;
1751 m_minX = m_minY = 0;
1752 m_maxX = m_maxY = 0;
1753 m_last_lx = m_last_ly = 0;
1755 m_enableDoubleBuffer =
false;
1756 m_enableMouseNavigation =
true;
1757 m_enableLimitedView =
false;
1758 m_movingInfoLayer = NULL;
1760 m_marginTop = 0; m_marginRight = 0; m_marginBottom = 0; m_marginLeft = 0;
1763 m_lockaspect =
false;
1765 m_popmenu.Append(
mpID_CENTER, _(
"Center" ), _(
"Center plot view to this position" ) );
1766 m_popmenu.Append(
mpID_FIT, _(
"Fit on Screen" ), _(
"Set plot view to show all items" ) );
1767 m_popmenu.Append(
mpID_ZOOM_IN, _(
"Zoom In" ), _(
"Zoom in plot view." ) );
1768 m_popmenu.Append(
mpID_ZOOM_OUT, _(
"Zoom Out" ), _(
"Zoom out plot view." ) );
1773 SetBackgroundColour( *wxWHITE );
1774 m_bgColour = *wxWHITE;
1775 m_fgColour = *wxBLACK;
1777 m_enableScrollBars =
false;
1778 SetSizeHints( 128, 128 );
1781 SetBackgroundStyle( wxBG_STYLE_CUSTOM );
1790 DelAllLayers(
true,
false );
1804 m_mouseMClick.x =
event.GetX();
1805 m_mouseMClick.y =
event.GetY();
1813 if( !m_enableMouseNavigation )
1820 int change = -
event.GetWheelRotation();
1821 double changeUnitsX = change / m_scaleX;
1822 double changeUnitsY = change / m_scaleY;
1824 if( event.m_controlDown )
1827 SetXView( m_posX + changeUnitsX, m_desiredXmax + changeUnitsX,
1828 m_desiredXmin + changeUnitsX );
1830 else if( event.m_shiftDown )
1833 SetYView( m_posY - changeUnitsY, m_desiredYmax - changeUnitsY,
1834 m_desiredYmin - changeUnitsY );
1839 wxPoint clickPt( event.GetX(),
event.GetY() );
1841 if( event.GetWheelRotation() > 0 )
1855 if( !m_enableMouseNavigation )
1861 if( event.m_middleDown )
1864 int Ax = m_mouseMClick.x -
event.GetX();
1865 int Ay = m_mouseMClick.y -
event.GetY();
1868 m_mouseMClick.x =
event.GetX();
1869 m_mouseMClick.y =
event.GetY();
1871 double Ax_units = Ax / m_scaleX;
1872 double Ay_units = -Ay / m_scaleY;
1874 bool updateRequired =
false;
1875 updateRequired |= SetXView( m_posX + Ax_units,
1876 m_desiredXmax + Ax_units,
1877 m_desiredXmin + Ax_units );
1878 updateRequired |= SetYView( m_posY + Ay_units,
1879 m_desiredYmax + Ay_units,
1880 m_desiredYmin + Ay_units );
1882 if( updateRequired )
1885 #ifdef MATHPLOT_DO_LOGGING 1886 wxLogMessage(
"[mpWindow::OnMouseMove] Ax:%i Ay:%i m_posX:%f m_posY:%f",
1895 if( event.m_leftDown )
1897 if( m_movingInfoLayer == NULL )
1899 wxClientDC dc(
this );
1900 wxPen pen( m_fgColour, 1, wxPENSTYLE_DOT );
1902 dc.SetBrush( *wxTRANSPARENT_BRUSH );
1903 dc.DrawRectangle( m_mouseLClick.x, m_mouseLClick.y,
1904 event.GetX() - m_mouseLClick.x,
event.GetY() - m_mouseLClick.y );
1906 m_zoomRect.x = m_mouseLClick.x;
1907 m_zoomRect.y = m_mouseLClick.y;
1908 m_zoomRect.width =
event.GetX() - m_mouseLClick.x;
1909 m_zoomRect.height =
event.GetY() - m_mouseLClick.y;
1913 wxPoint moveVector( event.GetX() - m_mouseLClick.x,
1914 event.GetY() - m_mouseLClick.y );
1915 m_movingInfoLayer->Move( moveVector );
1924 wxLayerList::iterator li;
1926 for( li = m_layers.begin(); li != m_layers.end(); li++ )
1928 if( (*li)->IsInfo() && (*li)->IsVisible() )
1930 mpInfoLayer* tmpLyr = (mpInfoLayer*) (*li);
1955 m_mouseLClick.x =
event.GetX();
1956 m_mouseLClick.y =
event.GetY();
1958 #ifdef MATHPLOT_DO_LOGGING 1959 wxLogMessage(
"mpWindow::OnMouseLeftDown() X = %d , Y = %d", event.GetX(),
event.GetY() );
1961 wxPoint pointClicked =
event.GetPosition();
1962 m_movingInfoLayer = IsInsideInfoLayer( pointClicked );
1964 if( m_movingInfoLayer != NULL )
1966 #ifdef MATHPLOT_DO_LOGGING 1967 wxLogMessage(
"mpWindow::OnMouseLeftDown() started moving layer %lx",
1968 (
long int) m_movingInfoLayer );
1978 wxPoint release( event.GetX(),
event.GetY() );
1979 wxPoint press( m_mouseLClick.x, m_mouseLClick.y );
1983 if( m_movingInfoLayer != NULL )
1985 m_movingInfoLayer->UpdateReference();
1986 m_movingInfoLayer = NULL;
1990 if( release != press )
1992 ZoomRect( press, release );
2009 Fit( m_minX, m_maxX, m_minY, m_maxY );
2015 wxCoord* printSizeX, wxCoord* printSizeY )
2018 m_desiredXmin = xMin; m_desiredXmax = xMax;
2019 m_desiredYmin = yMin; m_desiredYmax = yMax;
2022 double xExtra = fabs( xMax - xMin ) * 0.00;
2023 double yExtra = fabs( yMax - yMin ) * 0.03;
2030 if( printSizeX!=NULL && printSizeY!=NULL )
2033 m_scrX = *printSizeX;
2034 m_scrY = *printSizeY;
2039 GetClientSize( &m_scrX, &m_scrY );
2047 m_scaleX = (Ax!=0) ? (m_scrX - m_marginLeft - m_marginRight) / Ax : 1;
2048 m_scaleY = (Ay!=0) ? (m_scrY - m_marginTop - m_marginBottom) / Ay : 1;
2052 #ifdef MATHPLOT_DO_LOGGING 2053 wxLogMessage(
"mpWindow::Fit()(lock) m_scaleX=%f,m_scaleY=%f", m_scaleX, m_scaleY );
2056 double s = m_scaleX < m_scaleY ? m_scaleX : m_scaleY;
2065 m_posX = (xMin + xMax) / 2 - ( (m_scrX - m_marginLeft - m_marginRight) / 2 + m_marginLeft ) /
2068 m_posY = (yMin + yMax) / 2 + ( (m_scrY - m_marginTop - m_marginBottom) / 2 + m_marginTop ) /
2071 #ifdef MATHPLOT_DO_LOGGING 2073 "mpWindow::Fit() m_desiredXmin=%f m_desiredXmax=%f m_desiredYmin=%f m_desiredYmax=%f",
2079 "mpWindow::Fit() m_scaleX = %f , m_scrX = %d,m_scrY=%d, Ax=%f, Ay=%f, m_posX=%f, m_posY=%f",
2091 if( printSizeX==NULL || printSizeY==NULL )
2100 double staticX = p2x( staticXpixel );
2103 m_scaleX = m_scaleX * zoomIncrementalFactor;
2105 m_posX = staticX - (staticXpixel / m_scaleX);
2107 m_desiredXmin = m_posX;
2108 m_desiredXmax = m_posX + ( m_scrX - (m_marginLeft + m_marginRight) ) / m_scaleX;
2109 #ifdef MATHPLOT_DO_LOGGING 2111 "mpWindow::DoZoomInXCalc() prior X coord: (%f), new X coord: (%f) SHOULD BE EQUAL!!",
2112 staticX, p2x( staticXpixel ) );
2120 double staticY = p2y( staticYpixel );
2123 m_scaleY = m_scaleY * zoomIncrementalFactor;
2125 m_posY = staticY + (staticYpixel / m_scaleY);
2127 m_desiredYmax = m_posY;
2128 m_desiredYmin = m_posY - ( m_scrY - (m_marginTop + m_marginBottom) ) / m_scaleY;
2129 #ifdef MATHPLOT_DO_LOGGING 2131 "mpWindow::DoZoomInYCalc() prior Y coord: (%f), new Y coord: (%f) SHOULD BE EQUAL!!",
2132 staticY, p2y( staticYpixel ) );
2140 double staticX = p2x( staticXpixel );
2143 m_scaleX = m_scaleX / zoomIncrementalFactor;
2145 m_posX = staticX - (staticXpixel / m_scaleX);
2147 m_desiredXmin = m_posX;
2148 m_desiredXmax = m_posX + ( m_scrX - (m_marginLeft + m_marginRight) ) / m_scaleX;
2149 #ifdef MATHPLOT_DO_LOGGING 2151 "mpWindow::DoZoomOutXCalc() prior X coord: (%f), new X coord: (%f) SHOULD BE EQUAL!!",
2152 staticX, p2x( staticXpixel ) );
2160 double staticY = p2y( staticYpixel );
2163 m_scaleY = m_scaleY / zoomIncrementalFactor;
2165 m_posY = staticY + (staticYpixel / m_scaleY);
2167 m_desiredYmax = m_posY;
2168 m_desiredYmin = m_posY - ( m_scrY - (m_marginTop + m_marginBottom) ) / m_scaleY;
2169 #ifdef MATHPLOT_DO_LOGGING 2171 "mpWindow::DoZoomOutYCalc() prior Y coord: (%f), new Y coord: (%f) SHOULD BE EQUAL!!",
2172 staticY, p2y( staticYpixel ) );
2179 if( !m_enableLimitedView )
2182 const double xMin = m_minX - m_marginLeft / m_scaleX;
2183 const double xMax = m_maxX - m_marginRight / m_scaleX;
2184 const double yMin = m_minY + m_marginTop / m_scaleY;
2185 const double yMax = m_maxY + m_marginBottom / m_scaleY;
2187 if( m_desiredXmin < xMin )
2189 double diff = xMin - m_desiredXmin;
2191 m_desiredXmax += diff;
2192 m_desiredXmin = xMin;
2195 if( m_desiredXmax > xMax )
2197 double diff = m_desiredXmax - xMax;
2199 m_desiredXmin -= diff;
2200 m_desiredXmax = xMax;
2203 if( m_desiredYmin < yMin )
2205 double diff = yMin - m_desiredYmin;
2207 m_desiredYmax += diff;
2208 m_desiredYmin = yMin;
2211 if( m_desiredYmax > yMax )
2213 double diff = m_desiredYmax - yMax;
2215 m_desiredYmin -= diff;
2216 m_desiredYmax = yMax;
2227 m_desiredXmax = desiredMax;
2228 m_desiredXmin = desiredMin;
2229 AdjustLimitedView();
2241 m_desiredYmax = desiredMax;
2242 m_desiredYmin = desiredMin;
2243 AdjustLimitedView();
2253 if( c == wxDefaultPosition )
2255 GetClientSize( &m_scrX, &m_scrY );
2256 c.
x = (m_scrX - m_marginLeft - m_marginRight) / 2 + m_marginLeft;
2257 c.
y = (m_scrY - m_marginTop - m_marginBottom) / 2 - m_marginTop;
2262 c.
x =
std::min( c.
x, m_scrX - m_marginRight );
2264 c.
y =
std::min( c.
y, m_scrY - m_marginBottom );
2268 double prior_layer_x = p2x( c.
x );
2269 double prior_layer_y = p2y( c.
y );
2273 double newScaleX = m_scaleX * zoomIncrementalFactor;
2274 double newScaleY = m_scaleY * zoomIncrementalFactor;
2277 if( newScaleX <= MAX_SCALE && newScaleY <= MAX_SCALE )
2279 m_scaleX = newScaleX;
2280 m_scaleY = newScaleY;
2288 m_posX = prior_layer_x - c.
x / m_scaleX;
2289 m_posY = prior_layer_y + c.
y / m_scaleY;
2291 m_desiredXmin = m_posX;
2292 m_desiredXmax = m_posX + (m_scrX - m_marginLeft - m_marginRight) / m_scaleX;
2293 m_desiredYmax = m_posY;
2294 m_desiredYmin = m_posY - (m_scrY - m_marginTop - m_marginBottom) / m_scaleY;
2295 AdjustLimitedView();
2297 #ifdef MATHPLOT_DO_LOGGING 2298 wxLogMessage(
"mpWindow::ZoomIn() prior coords: (%f,%f), new coords: (%f,%f) SHOULD BE EQUAL!!",
2299 prior_layer_x, prior_layer_y, p2x( c.
x ), p2y( c.
y ) );
2310 if( c == wxDefaultPosition )
2312 GetClientSize( &m_scrX, &m_scrY );
2313 c.
x = (m_scrX - m_marginLeft - m_marginRight) / 2 + m_marginLeft;
2314 c.
y = (m_scrY - m_marginTop - m_marginBottom) / 2 - m_marginTop;
2318 double prior_layer_x = p2x( c.
x );
2319 double prior_layer_y = p2y( c.
y );
2322 m_scaleX = m_scaleX / zoomIncrementalFactor;
2323 m_scaleY = m_scaleY / zoomIncrementalFactor;
2326 m_posX = prior_layer_x - c.
x / m_scaleX;
2327 m_posY = prior_layer_y + c.
y / m_scaleY;
2329 m_desiredXmin = m_posX;
2330 m_desiredXmax = m_posX + (m_scrX - m_marginLeft - m_marginRight) / m_scaleX;
2331 m_desiredYmax = m_posY;
2332 m_desiredYmin = m_posY - (m_scrY - m_marginTop - m_marginBottom) / m_scaleY;
2337 if( !CheckXLimits( m_desiredXmax,
2338 m_desiredXmin ) || !CheckYLimits( m_desiredYmax, m_desiredYmin ) )
2344 #ifdef MATHPLOT_DO_LOGGING 2346 "mpWindow::ZoomOut() prior coords: (%f,%f), new coords: (%f,%f) SHOULD BE EQUAL!!",
2347 prior_layer_x, prior_layer_y, p2x( c.
x ), p2y( c.
y ) );
2355 m_scaleX = m_scaleX * zoomIncrementalFactor;
2362 m_scaleX = m_scaleX / zoomIncrementalFactor;
2369 m_scaleY = m_scaleY * zoomIncrementalFactor;
2376 m_scaleY = m_scaleY / zoomIncrementalFactor;
2384 double p0x = p2x( p0.
x );
2385 double p0y = p2y( p0.
y );
2386 double p1x = p2x( p1.
x );
2387 double p1y = p2y( p1.
y );
2390 double zoom_x_min = p0x<p1x ? p0x : p1x;
2391 double zoom_x_max = p0x>p1x ? p0x : p1x;
2392 double zoom_y_min = p0y<p1y ? p0y : p1y;
2393 double zoom_y_max = p0y>p1y ? p0y : p1y;
2395 #ifdef MATHPLOT_DO_LOGGING 2396 wxLogMessage(
"Zoom: (%f,%f)-(%f,%f)", zoom_x_min, zoom_y_min, zoom_x_max, zoom_y_max );
2399 Fit( zoom_x_min, zoom_x_max, zoom_y_min, zoom_y_max );
2400 AdjustLimitedView();
2406 m_lockaspect = enable;
2410 Fit( m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax );
2416 m_clickedX =
event.GetX();
2417 m_clickedY =
event.GetY();
2418 PopupMenu( &m_popmenu, event.GetX(),
event.GetY() );
2424 LockAspect( !m_lockaspect );
2436 GetClientSize( &m_scrX, &m_scrY );
2437 int centerX = (m_scrX - m_marginLeft - m_marginRight) / 2;
2438 int centerY = (m_scrY - m_marginTop - m_marginBottom) / 2;
2439 SetPos( p2x( m_clickedX - centerX ), p2y( m_clickedY - centerY ) );
2446 ZoomIn(
wxPoint( m_mouseMClick.x, m_mouseMClick.y ) );
2459 Fit( m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax );
2460 #ifdef MATHPLOT_DO_LOGGING 2461 wxLogMessage(
"mpWindow::OnSize() m_scrX = %d, m_scrY = %d", m_scrX, m_scrY );
2462 #endif // MATHPLOT_DO_LOGGING 2470 m_layers.push_back( layer );
2472 if( refreshDisplay )
2484 bool alsoDeleteObject,
2485 bool refreshDisplay )
2487 wxLayerList::iterator layIt;
2489 for( layIt = m_layers.begin(); layIt != m_layers.end(); layIt++ )
2491 if( *layIt == layer )
2494 if( alsoDeleteObject )
2497 m_layers.erase( layIt );
2499 if( refreshDisplay )
2512 while( m_layers.size()>0 )
2515 if( alsoDeleteObject )
2518 m_layers.erase( m_layers.begin() );
2521 if( refreshDisplay )
2528 wxPaintDC dc(
this );
2530 dc.GetSize( &m_scrX, &m_scrY );
2532 #ifdef MATHPLOT_DO_LOGGING 2533 wxLogMessage(
"[mpWindow::OnPaint] vis.area: x %i y%i", m_scrX, m_scrY );
2540 if( m_enableDoubleBuffer )
2542 if( m_last_lx!=m_scrX || m_last_ly!=m_scrY )
2547 m_buff_bmp =
new wxBitmap( m_scrX, m_scrY );
2548 m_buff_dc.SelectObject( *m_buff_bmp );
2562 trgDc->SetPen( *wxTRANSPARENT_PEN );
2563 wxBrush brush( GetBackgroundColour() );
2564 trgDc->SetBrush( brush );
2565 trgDc->SetTextForeground( m_fgColour );
2566 trgDc->DrawRectangle( 0, 0, m_scrX, m_scrY );
2570 wxLayerList::iterator li;
2572 for( li = m_layers.begin(); li != m_layers.end(); li++ )
2574 (*li)->Plot( *trgDc, *
this );
2581 wxPen pen( m_fgColour, 1, wxPENSTYLE_DOT );
2582 trgDc->SetPen( pen );
2583 trgDc->SetBrush( *wxTRANSPARENT_BRUSH );
2584 trgDc->DrawRectangle( m_zoomRect );
2588 if( m_enableDoubleBuffer )
2592 dc.Blit( 0, 0, m_scrX, m_scrY, trgDc, 0, 0 );
2602 if( m_enableScrollBars )
2668 m_enableScrollBars = status;
2670 if( status ==
false )
2672 SetScrollbar( wxHORIZONTAL, 0, 0, 0 );
2673 SetScrollbar( wxVERTICAL, 0, 0, 0 );
2718 for( wxLayerList::iterator li = m_layers.begin(); li != m_layers.end(); li++ )
2749 #ifdef MATHPLOT_DO_LOGGING 2751 "[mpWindow::UpdateBBox] Bounding box: Xmin = %f, Xmax = %f, Ymin = %f, YMax = %f" ), m_minX, m_maxX, m_minY,
2753 #endif // MATHPLOT_DO_LOGGING 2755 return first ==
false;
2818 if( m_enableScrollBars )
2821 GetClientSize( &cx, &cy );
2825 double leftMargin = m_marginLeft / m_scaleX;
2827 double maxX = (m_desiredXmax > m_maxX) ? m_desiredXmax : m_maxX;
2828 double minX = (m_desiredXmin < m_minX) ? m_desiredXmin : m_minX;
2830 if( (m_posX + leftMargin) < minX )
2831 minX = m_posX + leftMargin;
2834 int sizeX = (int) ( (maxX - minX) * m_scaleX );
2835 int thumbX = (int) ( ( (m_posX + leftMargin) - minX ) * m_scaleX );
2836 SetScrollbar( wxHORIZONTAL, thumbX, cx - (m_marginRight + m_marginLeft), sizeX );
2841 double topMargin = m_marginTop / m_scaleY;
2843 double maxY = (m_desiredYmax > m_maxY) ? m_desiredYmax : m_maxY;
2845 if( (m_posY - topMargin) > maxY )
2846 maxY = m_posY - topMargin;
2848 double minY = (m_desiredYmin < m_minY) ? m_desiredYmin : m_minY;
2850 int sizeY = (int) ( (maxY - minY) * m_scaleY );
2851 int thumbY = (int) ( ( maxY - (m_posY - topMargin) ) * m_scaleY );
2852 SetScrollbar( wxVERTICAL, thumbY, cy - (m_marginTop + m_marginBottom), sizeY );
2863 if( orientation == wxVERTICAL )
2867 double topMargin = m_marginTop / m_scaleY;
2869 double maxY = m_desiredYmax > m_maxY ? m_desiredYmax : m_maxY;
2871 SetPosY( ( maxY - (position / m_scaleY) ) + topMargin );
2877 double leftMargin = m_marginLeft / m_scaleX;
2879 double minX = (m_desiredXmin < m_minX) ? m_desiredXmin : m_minX;
2881 SetPosX( ( minX + (position / m_scaleX) ) - leftMargin );
2888 DoScrollCalc( event.GetPosition(),
event.GetOrientation() );
2894 int scrollOrientation =
event.GetOrientation();
2896 int position = GetScrollPos( scrollOrientation );
2898 int thumbSize = GetScrollThumb( scrollOrientation );
2901 position -= thumbSize;
2906 DoScrollCalc( position, scrollOrientation );
2912 int scrollOrientation =
event.GetOrientation();
2914 int position = GetScrollPos( scrollOrientation );
2916 int thumbSize = GetScrollThumb( scrollOrientation );
2918 int scrollRange = GetScrollRange( scrollOrientation );
2921 position += thumbSize;
2923 if( position > (scrollRange - thumbSize) )
2924 position = scrollRange - thumbSize;
2926 DoScrollCalc( position, scrollOrientation );
2932 int scrollOrientation =
event.GetOrientation();
2934 int position = GetScrollPos( scrollOrientation );
2942 DoScrollCalc( position, scrollOrientation );
2948 int scrollOrientation =
event.GetOrientation();
2950 int position = GetScrollPos( scrollOrientation );
2952 int thumbSize = GetScrollThumb( scrollOrientation );
2954 int scrollRange = GetScrollRange( scrollOrientation );
2959 if( position > (scrollRange - thumbSize) )
2960 position = scrollRange - thumbSize;
2962 DoScrollCalc( position, scrollOrientation );
2968 DoScrollCalc( 0, event.GetOrientation() );
2974 int scrollOrientation =
event.GetOrientation();
2976 int thumbSize = GetScrollThumb( scrollOrientation );
2978 int scrollRange = GetScrollRange( scrollOrientation );
2980 DoScrollCalc( scrollRange - thumbSize, scrollOrientation );
3000 unsigned int layerNo = 0;
3002 for( wxLayerList::iterator li = m_layers.begin(); li != m_layers.end(); li++ )
3004 if( (*li)->HasBBox() )
3017 if( ( position >= (
int) m_layers.size() ) || position < 0 )
3020 return m_layers[position];
3026 for( wxLayerList::iterator it = m_layers.begin(); it!=m_layers.end(); it++ )
3027 if( !(*it)->GetName().Cmp( name ) )
3045 wxSize imageSize,
bool fit )
3048 int bk_scrX, bk_scrY;
3050 if( imageSize == wxDefaultSize )
3057 sizeX = imageSize.x;
3058 sizeY = imageSize.y;
3061 SetScr( sizeX, sizeY );
3064 wxBitmap screenBuffer( sizeX, sizeY );
3065 wxMemoryDC screenDC;
3066 screenDC.SelectObject( screenBuffer );
3067 screenDC.SetPen( *wxTRANSPARENT_PEN );
3068 wxBrush brush( GetBackgroundColour() );
3069 screenDC.SetBrush( brush );
3070 screenDC.DrawRectangle( 0, 0, sizeX, sizeY );
3074 Fit( m_minX, m_maxX, m_minY, m_maxY, &sizeX, &sizeY );
3078 Fit( m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax, &sizeX, &sizeY );
3082 wxLayerList::iterator li;
3084 for( li = m_layers.begin(); li != m_layers.end(); li++ )
3085 (*li)->Plot( screenDC, *
this );
3087 if( imageSize != wxDefaultSize )
3090 SetScr( bk_scrX, bk_scrY );
3091 Fit( m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax, &bk_scrX, &bk_scrY );
3096 wxImage screenImage = screenBuffer.ConvertToImage();
3097 return screenImage.SaveFile( filename, type );
3104 m_marginRight = right;
3105 m_marginBottom = bottom;
3106 m_marginLeft = left;
3112 wxLayerList::iterator li;
3114 for( li = m_layers.begin(); li != m_layers.end(); li++ )
3116 #ifdef MATHPLOT_DO_LOGGING 3117 wxLogMessage(
"mpWindow::IsInsideInfoLayer() examinining layer = %p", (*li) );
3118 #endif // MATHPLOT_DO_LOGGING 3120 if( (*li)->IsInfo() )
3122 mpInfoLayer* tmpLyr = (mpInfoLayer*) (*li);
3123 #ifdef MATHPLOT_DO_LOGGING 3124 wxLogMessage(
"mpWindow::IsInsideInfoLayer() layer = %p", (*li) );
3125 #endif // MATHPLOT_DO_LOGGING 3127 if( tmpLyr->
Inside( point ) )
3140 mpLayer* lx = GetLayerByName( name );
3152 mpLayer* lx = GetLayerByName( name );
3179 const wxColour& drawColour,
3180 const wxColour& axesColour )
3182 SetBackgroundColour( bgColour );
3183 SetForegroundColour( drawColour );
3184 m_bgColour = bgColour;
3185 m_fgColour = drawColour;
3186 m_axColour = axesColour;
3188 wxLayerList::iterator li;
3190 for( li = m_layers.begin(); li != m_layers.end(); li++ )
3194 wxPen axisPen = (*li)->GetPen();
3195 axisPen.SetColour( axesColour );
3196 (*li)->SetPen( axisPen );
3201 wxPen infoPen = (*li)->GetPen();
3202 infoPen.SetColour( drawColour );
3203 (*li)->SetPen( infoPen );
3309 double xlogmin = log10(
m_minV );
3310 double xlogmax = log10(
m_maxV );
3312 return ( log10( x ) - xlogmin) / (xlogmax - xlogmin);
3318 double xlogmin = log10(
m_minV );
3319 double xlogmax = log10(
m_maxV );
3321 return pow( 10.0, xplot * (xlogmax - xlogmin) + xlogmin );
3326 mpFSemiLogXVector::mpFSemiLogXVector( wxString
name,
int flags ) :
3332 IMPLEMENT_DYNAMIC_CLASS( mpFSemiLogXVector,
mpFXYVector )
3343 if( m_index>=m_xs.size() )
3348 y = m_ys[m_index++];
3349 return m_index<=m_xs.size();
3364 if( xs.size() != ys.size() )
3366 wxLogError(
"wxMathPlot error: X and Y vector are not of the same length!" );
3384 std::vector<double>::const_iterator it;
3386 for( it = xs.begin(); it!=xs.end(); it++ )
3395 for( it = ys.begin(); it!=ys.end(); it++ )
3432 if( offsetx >= 0 && offsetx <= 100 )
3433 m_offsetx = offsetx;
3437 if( offsety >= 0 && offsety <= 100 )
3438 m_offsety = offsety;
3457 wxCoord tw = 0, th = 0;
3458 dc.GetTextExtent(
GetName(), &tw, &th );
3470 dc.DrawText(
GetName(), px, py );
3488 wxDC* trgDc = GetDC();
3490 if( (trgDc) && (page == 1) )
3492 wxCoord m_prnX, m_prnY;
3495 trgDc->GetSize( &m_prnX, &m_prnY );
3497 m_prnX -= (2 * marginX);
3498 m_prnY -= (2 * marginY);
3499 trgDc->SetDeviceOrigin( marginX, marginY );
3501 #ifdef MATHPLOT_DO_LOGGING 3502 wxLogMessage( wxT(
"Print Size: %d x %d\n" ), m_prnX, m_prnY );
3517 wxColour oldBgColour =
plotWindow->GetBackgroundColour();
3518 wxColour oldFgColour =
plotWindow->GetForegroundColour();
3522 trgDc->SetPen( *wxTRANSPARENT_PEN );
3524 wxBrush brush = *wxWHITE_BRUSH;
3525 trgDc->SetBrush( brush );
3526 trgDc->DrawRectangle( 0, 0, m_prnX, m_prnY );
3565 double ccos = cos( m_reference_phi );
3566 double csin = sin( m_reference_phi );
3568 out_x = m_reference_x + ccos * x - csin * y;
3569 out_y = m_reference_y + csin * x + ccos * y;
3577 if( m_shape_xs.size()!=m_shape_ys.size() )
3580 "[mpMovableObject::ShapeUpdated] Error, m_shape_xs and m_shape_ys have different lengths!" ) );
3584 double ccos = cos( m_reference_phi );
3585 double csin = sin( m_reference_phi );
3587 m_trans_shape_xs.resize( m_shape_xs.size() );
3588 m_trans_shape_ys.resize( m_shape_xs.size() );
3590 std::vector<double>::iterator itXi, itXo;
3591 std::vector<double>::iterator itYi, itYo;
3593 m_bbox_min_x = 1e300;
3594 m_bbox_max_x = -1e300;
3595 m_bbox_min_y = 1e300;
3596 m_bbox_max_y = -1e300;
3598 for( itXo = m_trans_shape_xs.begin(),
3599 itYo = m_trans_shape_ys.begin(), itXi = m_shape_xs.begin(), itYi = m_shape_ys.begin();
3600 itXo!=m_trans_shape_xs.end(); itXo++, itYo++, itXi++, itYi++ )
3602 *itXo = m_reference_x + ccos * (*itXi) - csin * (*itYi);
3603 *itYo = m_reference_y + csin * (*itXi) + ccos * (*itYi);
3606 if( *itXo < m_bbox_min_x )
3607 m_bbox_min_x = *itXo;
3609 if( *itXo > m_bbox_max_x )
3610 m_bbox_max_x = *itXo;
3612 if( *itYo < m_bbox_min_y )
3613 m_bbox_min_y = *itYo;
3615 if( *itYo > m_bbox_max_y )
3616 m_bbox_max_y = *itYo;
3629 std::vector<double>::iterator itX = m_trans_shape_xs.begin();
3630 std::vector<double>::iterator itY = m_trans_shape_ys.begin();
3636 if( m_pen.GetWidth() <= 1 )
3638 while( itX!=m_trans_shape_xs.end() )
3640 dc.DrawPoint( w.
x2p( *(itX++) ), w.
y2p( *(itY++) ) );
3645 while( itX!=m_trans_shape_xs.end() )
3647 wxCoord cx = w.
x2p( *(itX++) );
3648 wxCoord cy = w.
y2p( *(itY++) );
3649 dc.DrawLine( cx, cy, cx, cy );
3655 wxCoord cx0 = 0, cy0 = 0;
3658 while( itX!=m_trans_shape_xs.end() )
3660 wxCoord cx = w.
x2p( *(itX++) );
3661 wxCoord cy = w.
y2p( *(itY++) );
3669 dc.DrawLine( cx0, cy0, cx, cy );
3674 if( !m_name.IsEmpty() && m_showName )
3676 dc.SetFont( m_font );
3679 dc.GetTextExtent( m_name, &tx, &ty );
3691 const int sx = w.
GetScrX() >> 1;
3692 const int sy = w.
GetScrY() >> 1;
3699 else if( (m_flags & mpALIGNMASK) ==
mpALIGN_NW )
3704 else if( (m_flags & mpALIGNMASK) ==
mpALIGN_SW )
3716 dc.DrawText( m_name, tx, ty );
3735 wxLogError( wxT(
"[mpCovarianceEllipse] Error: quantiles must be non-negative" ) );
return;
3740 wxLogError( wxT(
"[mpCovarianceEllipse] Error: cov(0,0) must be non-negative" ) );
return;
3745 wxLogError( wxT(
"[mpCovarianceEllipse] Error: cov(1,1) must be non-negative" ) );
return;
3748 m_shape_xs.resize( m_segments, 0 );
3749 m_shape_ys.resize( m_segments, 0 );
3753 double b = -m_cov_00 - m_cov_11;
3754 double c = m_cov_00 * m_cov_11 - m_cov_01 * m_cov_01;
3756 double D = b * b - 4 * c;
3760 wxLogError( wxT(
"[mpCovarianceEllipse] Error: cov is not positive definite" ) );
return;
3763 double eigenVal0 = 0.5 * ( -b + sqrt( D ) );
3764 double eigenVal1 = 0.5 * ( -b - sqrt( D ) );
3768 double eigenVec0_x, eigenVec0_y;
3769 double eigenVec1_x, eigenVec1_y;
3771 if( fabs( eigenVal0 - m_cov_00 )>1e-6 )
3773 double k1x = m_cov_01 / ( eigenVal0 - m_cov_00 );
3775 eigenVec0_x = eigenVec0_y * k1x;
3779 double k1y = m_cov_01 / ( eigenVal0 - m_cov_11 );
3781 eigenVec0_y = eigenVec0_x * k1y;
3784 if( fabs( eigenVal1 - m_cov_00 )>1e-6 )
3786 double k2x = m_cov_01 / ( eigenVal1 - m_cov_00 );
3788 eigenVec1_x = eigenVec1_y * k2x;
3792 double k2y = m_cov_01 / ( eigenVal1 - m_cov_11 );
3794 eigenVec1_y = eigenVec1_x * k2y;
3798 double len = sqrt( eigenVec0_x * eigenVec0_x + eigenVec0_y * eigenVec0_y );
3802 len = sqrt( eigenVec1_x * eigenVec1_x + eigenVec1_y * eigenVec1_y );
3808 eigenVal0 = sqrt( eigenVal0 );
3809 eigenVal1 = sqrt( eigenVal1 );
3812 double M_00 = eigenVec0_x * eigenVal0;
3813 double M_01 = eigenVec0_y * eigenVal0;
3815 double M_10 = eigenVec1_x * eigenVal1;
3816 double M_11 = eigenVec1_y * eigenVal1;
3820 double Aang = 6.283185308 / (m_segments - 1);
3823 for( i = 0, ang = 0; i<m_segments; i++, ang += Aang )
3825 double ccos = cos( ang );
3826 double csin = sin( ang );
3828 m_shape_xs[
i] = m_quantiles * (ccos * M_00 + csin * M_10 );
3829 m_shape_ys[
i] = m_quantiles * (ccos * M_01 + csin * M_11 );
3840 const std::vector<double>& points_ys,
3843 if( points_xs.size()!=points_ys.size() )
3846 "[mpPolygon] Error: points_xs and points_ys must have the same number of elements" ) );
3850 m_shape_xs = points_xs;
3851 m_shape_ys = points_ys;
3853 if( closedShape && points_xs.size() )
3855 m_shape_xs.push_back( points_xs[0] );
3856 m_shape_ys.push_back( points_ys[0] );
3878 wxLogError( wxT(
"[mpBitmapLayer] Assigned bitmap is not Ok()!" ) );
3894 if( m_visible && m_validImg )
3914 wxCoord x0 = w.
x2p( m_min_x );
3915 wxCoord y0 = w.
y2p( m_max_y );
3916 wxCoord x1 = w.
x2p( m_max_x );
3917 wxCoord y1 = w.
y2p( m_min_y );
3921 double screenPixelX = ( x1 - x0 ) / (
double) m_bitmap.GetWidth();
3922 double screenPixelY = ( y1 - y0 ) / (
double) m_bitmap.GetHeight();
3925 wxCoord borderMarginX = (wxCoord) (screenPixelX + 1);
3926 wxCoord borderMarginY = (wxCoord) (screenPixelY + 1);
3929 wxCoord dx0 = x0, dx1 = x1, dy0 = y0, dy1 = y1;
3932 dx0 = -borderMarginX;
3935 dy0 = -borderMarginY;
3938 dx1 = w.
GetScrX() + borderMarginX;
3941 dy1 = w.
GetScrY() + borderMarginY;
3944 wxCoord d_width = dx1 - dx0 + 1;
3945 wxCoord d_height = dy1 - dy0 + 1;
3948 wxCoord offset_x = (wxCoord) ( (dx0 - x0) / screenPixelX );
3949 wxCoord offset_y = (wxCoord) ( (dy0 - y0) / screenPixelY );
3952 wxCoord b_width = (wxCoord) ( (dx1 - dx0 + 1) / screenPixelX );
3953 wxCoord b_height = (wxCoord) ( (dy1 - dy0 + 1) / screenPixelY );
3955 #ifdef MATHPLOT_DO_LOGGING 3956 wxLogMessage(
"[mpBitmapLayer::Plot] screenPixel: x=%f y=%f d_width=%ix%i",
3961 wxLogMessage(
"[mpBitmapLayer::Plot] offset: x=%i y=%i bmpWidth=%ix%i",
3969 if( d_width>0 && d_height>0 )
3972 if( m_scaledBitmap.GetWidth()!=d_width
3973 || m_scaledBitmap.GetHeight()!=d_height
3974 || m_scaledBitmap_offset_x != offset_x
3975 || m_scaledBitmap_offset_y != offset_y )
3977 wxRect r( wxRect( offset_x, offset_y, b_width, b_height ) );
3986 if( r.width>m_bitmap.GetWidth() )
3987 r.width = m_bitmap.GetWidth();
3989 if( r.height>m_bitmap.GetHeight() )
3990 r.height = m_bitmap.GetHeight();
3992 m_scaledBitmap = wxBitmap(
3993 wxBitmap( m_bitmap ).GetSubBitmap( r ).ConvertToImage()
3994 .Scale( d_width, d_height ) );
3995 m_scaledBitmap_offset_x = offset_x;
3996 m_scaledBitmap_offset_y = offset_y;
4000 dc.DrawBitmap( m_scaledBitmap, dx0, dy0,
true );
4005 if( !m_name.IsEmpty() && m_showName )
4007 dc.SetFont( m_font );
4010 dc.GetTextExtent( m_name, &tx, &ty );
4022 const int sx = w.
GetScrX() >> 1;
4023 const int sy = w.
GetScrY() >> 1;
4030 else if( (m_flags & mpALIGNMASK) ==
mpALIGN_NW )
4035 else if( (m_flags & mpALIGNMASK) ==
mpALIGN_SW )
4047 dc.DrawText( m_name, tx, ty );
4065 m_scaleX->ExtendDataRange( GetMinX(), GetMaxX() );
4068 m_scaleY->ExtendDataRange( GetMinY(), GetMaxY() );
4074 return m_scaleX->TransformFromPlot( plotCoordX );
4080 return m_scaleY->TransformFromPlot( plotCoordY );
4086 return m_scaleX->TransformToPlot( x );
4092 return m_scaleY->TransformToPlot( y );
mpInfoLegend()
Default constructor.
virtual double TransformToPlot(double x) override
Layer plot handler.
void ZoomOut(const wxPoint ¢erPoint=wxDefaultPosition)
Zoom out current view and refresh display.
virtual void UpdateInfo(mpWindow &w, wxEvent &event) override
Updates the content of the info box.
void OnScrollThumbTrack(wxScrollWinEvent &event)
#define mpALIGN_LEFT
Aligns label to the left.
mpLayerType GetLayerType()
Get layer type: a Layer can be of different types: plot lines, axis, info boxes, etc, this method returns the right value.
virtual void getVisibleDataRange(mpWindow &w, double &minV, double &maxV) override
virtual void Plot(wxDC &dc, mpWindow &w) override
Plot method.
const wxString & GetName() const
Get layer name.
virtual bool Inside(wxPoint &point)
Checks whether a point is inside the info box rectangle.
#define mpALIGN_NW
Aligns label to north-west.
void OnLockAspect(wxCommandEvent &event)
double y2s(double y) const
mpLayer * GetLayer(int position)
virtual double TransformToPlot(double x) override
void GetBitmapCopy(wxImage &outBmp) const
Returns a copy of the current bitmap assigned to the layer.
mpInfoCoords()
Default constructor.
void RecalculateShape()
Called to update the m_shape_xs, m_shape_ys vectors, whenever a parameter changes.
class WXDLLIMPEXP_MATHPLOT mpFXYVector
virtual bool SetYView(double pos, double desiredMax, double desiredMin)
Applies new Y view coordinates depending on the settings.
void Rewind() override
Rewind value enumeration with mpFXY::GetNextXY.
double p2x(wxCoord pixelCoordX)
Converts mpWindow (screen) pixel coordinates into graph (floating point) coordinates, using current mpWindow position and scale.
void updateTickLabels(wxDC &dc, mpWindow &w)
virtual void Plot(wxDC &dc, mpWindow &w) override
Layer plot handler.
void OnScrollLineDown(wxScrollWinEvent &event)
void computeSlaveTicks(mpWindow &w)
bool DelLayer(mpLayer *layer, bool alsoDeleteObject=false, bool refreshDisplay=true)
Remove a plot layer from the canvas.
virtual void SetScale(mpScaleBase *scaleX, mpScaleBase *scaleY)
bool OnPrintPage(int page) override
Abstract base class providing plot and labeling functionality for functions F:X->Y.
void OnZoomOut(wxCommandEvent &event)
#define Y_BORDER_SEPARATION
void OnMouseMiddleDown(wxMouseEvent &event)
virtual double TransformToPlot(double x) override
void SetName(wxString name)
Set layer name.
std::vector< TickLabel > m_tickLabels
virtual void Plot(wxDC &dc, mpWindow &w) override
Layer plot handler.
Abstract base class providing plot and labeling functionality for functions F:Y->X.
const wxColour & GetAxesColour()
Get axes draw colour.
bool IsLayerVisible(const wxString &name)
Check whether a layer with given name is visible.
static int countDecimalDigits(double x, int maxDigits)
int GetScrY(void) const
Get current view's Y dimension in device context units.
#define mpALIGN_RIGHT
Aligns label to the right.
double s2x(double plotCoordX) const
void SetLayerVisible(const wxString &name, bool viewable)
Sets the visibility of a layer by its name.
double p2y(wxCoord pixelCoordY)
Converts mpWindow (screen) pixel coordinates into graph (floating point) coordinates, using current mpWindow position and scale.
void OnScrollLineUp(wxScrollWinEvent &event)
A class providing graphs functionality for a 2D plot (either continuous or a set of points)...
virtual void Plot(wxDC &dc, mpWindow &w) override
Plot method.
mpInfoLayer * IsInsideInfoLayer(wxPoint &point)
Check if a given point is inside the area of a mpInfoLayer and eventually returns its pointer...
void DoZoomInXCalc(const int staticXpixel)
bool AddLayer(mpLayer *layer, bool refreshDisplay=true)
Add a plot layer to the canvas.
void OnSize(wxSizeEvent &event)
bool GetNextXY(double &x, double &y) override
Get locus value for next N.
void ZoomInY()
Zoom in current view along Y and refresh display.
void ZoomOutX()
Zoom out current view along X and refresh display.
void ZoomOutY()
Zoom out current view along Y and refresh display.
void SetPen(wxPen pen)
Set layer pen.
void ZoomInX()
Zoom in current view along X and refresh display.
static const int delta[8][2]
double GetPosY(void) const
void OnZoomIn(wxCommandEvent &event)
~mpInfoCoords()
Default destructor.
virtual void Plot(wxDC &dc, mpWindow &w) override
Layer plot handler.
Abstract base class providing plot and labeling functionality for a locus plot F:N->X,Y.
#define X_BORDER_SEPARATION
void UpdateAll()
Refresh display.
void DoZoomInYCalc(const int staticYpixel)
void OnPaint(wxPaintEvent &event)
double GetDesiredXmax()
Returns the right-border layer coordinate that the user wants the mpWindow to show (it may be not exa...
#define mpALIGN_BORDER_TOP
Aligns X axis to top border.
virtual void Move(wxPoint delta)
Moves the layer rectangle of given pixel deltas.
wxCoord y2p(double y)
Converts graph (floating point) coordinates into mpWindow (screen) pixel coordinates, using current mpWindow position and scale.
virtual double GetMaxX()
Get inclusive right border of bounding box.
#define mpALIGN_BORDER_LEFT
Aligns Y axis to left border.
void computeLabelExtents(wxDC &dc, mpWindow &w)
Plot layer implementing a x-scale ruler.
virtual double TransformFromPlot(double xplot) override
virtual void recalculateTicks(wxDC &dc, mpWindow &w) override
void SetFont(wxFont &font)
Set layer font.
void SetVisible(bool show)
Sets layer visibility.
void Refresh()
Update the board display after modifying it bu a python script (note: it is automatically called by a...
void OnScrollPageUp(wxScrollWinEvent &event)
virtual void Plot(wxDC &dc, mpWindow &w) override
Plot given view of layer to the given device context.
void ZoomIn(const wxPoint ¢erPoint=wxDefaultPosition)
Zoom into current view and refresh display.
bool IsVisible()
Checks whether the layer is visible or not.
void OnScrollBottom(wxScrollWinEvent &event)
virtual int labelCount() const
virtual void UpdateInfo(mpWindow &w, wxEvent &event)
Updates the content of the info box.
void SetScaleX(double scaleX)
Set current view's X scale and refresh display.
Base class to create small rectangular info boxes mpInfoLayer is the base class to create a small rec...
void ZoomRect(wxPoint p0, wxPoint p1)
Zoom view fitting given coordinates to the window (p0 and p1 do not need to be in any specific order)...
double GetPosX(void) const
void OnMouseLeftRelease(wxMouseEvent &event)
void OnMouseMove(wxMouseEvent &event)
Plot layer implementing a y-scale ruler.
void ShapeUpdated()
Must be called by the descendent class after updating the shape (m_shape_xs/ys), or when the transfor...
virtual double GetMaxY()
Get inclusive top border of bounding box.
void SetMargins(int top, int right, int bottom, int left)
Set window margins, creating a blank area where some kinds of layers cannot draw. ...
void GetBoundingBox(double *bbox)
Returns the bounding box coordinates.
virtual void recalculateTicks(wxDC &dc, mpWindow &w) override
virtual double getLabelPos(int n)
#define mpALIGN_TOP
Aligns label to the top.
virtual ~mpInfoLayer()
Destructor.
void SetColourTheme(const wxColour &bgColour, const wxColour &drawColour, const wxColour &axesColour)
Set Color theme.
EVT_MIDDLE_DOWN(mpWindow::OnMouseMiddleDown) EVT_MOUSEWHEEL(mpWindow
void DelAllLayers(bool alsoDeleteObject, bool refreshDisplay=true)
Remove all layers from the plot.
mpInfoLayer()
Default constructor.
virtual void Plot(wxDC &dc, mpWindow &w) override
Layer plot handler.
#define mpALIGN_NE
Aligns label to north-east.
int GetScrX(void) const
Get current view's X dimension in device context units.
double GetScaleY(void) const
virtual void Plot(wxDC &dc, mpWindow &w) override
Layer plot handler.
virtual void UpdateInfo(mpWindow &w, wxEvent &event) override
Updates the content of the info box.
wxBitmap GetColourSquare(int side=16)
Get a small square bitmap filled with the colour of the pen used in the layer.
void OnCenter(wxCommandEvent &event)
mpLayer * GetLayerByName(const wxString &name)
double GetScaleX(void) const
unsigned int CountAllLayers()
Counts the number of plot layers, whether or not they have a bounding box.
bool HasPage(int page) override
void LockAspect(bool enable=TRUE)
Enable or disable X/Y scale aspect locking for the view.
void recalculateTicks(wxDC &dc, mpWindow &w) override
Layer plot handler.
virtual double TransformFromPlot(double xplot) override
bool m_drawOutsideMargins
void TranslatePoint(double x, double y, double &out_x, double &out_y)
A method for 2D translation and rotation, using the current transformation stored in m_reference_x...
virtual const wxString getLabel(int n)
#define mpALIGN_BORDER_BOTTOM
Aligns X axis to bottom border.
void Fit() override
Set view to fit global bounding box of all plot layers and refresh display.
void UpdateViewBoundary(wxCoord xnew, wxCoord ynew)
Update label positioning data.
const wxRect & GetRectangle()
Returns the current rectangle coordinates.
virtual double GetMinX()
Get inclusive left border of bounding box.
void SetMPScrollbars(bool status)
Enable/disable scrollbars.
virtual double GetMinY()
Get inclusive bottom border of bounding box.
void OnFit(wxCommandEvent &event)
virtual void UpdateReference()
Updates the rectangle reference point.
mpScaleXLog(const wxString &name=wxT("log(X)"), int flags=mpALIGN_CENTER, bool ticks=true, unsigned int type=mpX_NORMAL)
Full constructor.
void OnShowPopupMenu(wxMouseEvent &event)
wxCoord x2p(double x)
Converts graph (floating point) coordinates into mpWindow (screen) pixel coordinates, using current mpWindow position and scale.
void Clear()
Clears all the data, leaving the layer empty.
virtual void getVisibleDataRange(mpWindow &w, double &minV, double &maxV) override
double GetDesiredYmin()
Returns the bottom-border layer coordinate that the user wants the mpWindow to show (it may be not ex...
virtual void Plot(wxDC &dc, mpWindow &w) override
Plot given view of layer to the given device context.
double s2y(double plotCoordY) const
void SetBitmap(const wxImage &inBmp, double x, double y, double lx, double ly)
Change the bitmap associated with the layer (to update the screen, refresh the mpWindow).
#define mpSCROLL_NUM_PIXELS_PER_LINE
void DoScrollCalc(const int position, const int orientation)
virtual void Plot(wxDC &dc, mpWindow &w) override
Plot method.
mpPrintout(mpWindow *drawWindow, const wxChar *title=_T("wxMathPlot print output"))
~mpInfoLegend()
Default destructor.
virtual void Plot(wxDC &dc, mpWindow &w)=0
Plot given view of layer to the given device context.
virtual void SetData(const std::vector< double > &xs, const std::vector< double > &ys)
Changes the internal data: the set of points to draw.
const wxPen & GetPen() const
Get pen set for this layer.
virtual bool HasBBox()
Check whether this layer has a bounding box.
Plot layer implementing a text string.
virtual bool SetXView(double pos, double desiredMax, double desiredMin)
Applies new X view coordinates depending on the settings.
void OnMouseLeftDown(wxMouseEvent &event)
void DoZoomOutXCalc(const int staticXpixel)
Canvas for plotting mpLayer implementations.
double GetDesiredXmin()
Returns the left-border layer coordinate that the user wants the mpWindow to show (it may be not exac...
static bool GetLayer(MODEL_VRML &aModel, LAYER_NUM layer, VRML_LAYER **vlayer)
#define mpALIGN_BOTTOM
Aligns label to the bottom.
mpScaleX(const wxString &name=wxT("X"), int flags=mpALIGN_CENTER, bool ticks=true, unsigned int type=mpX_NORMAL)
Full constructor.
virtual bool UpdateBBox()
Recalculate global layer bounding box, and save it in m_minX,...
#define mpALIGN_CENTER
Aligns label to the center.
void setPoints(const std::vector< double > &points_xs, const std::vector< double > &points_ys, bool closedShape=true)
Set the points in the polygon.
unsigned int CountLayers()
Counts the number of plot layers, excluding axes or text: this is to count only the layers which have...
wxPoint GetPosition()
Returns the position of the upper left corner of the box (in pixels)
void OnScrollPageDown(wxScrollWinEvent &event)
void OnScrollTop(wxScrollWinEvent &event)
virtual double TransformFromPlot(double xplot) override
bool SaveScreenshot(const wxString &filename, wxBitmapType type=wxBITMAP_TYPE_BMP, wxSize imageSize=wxDefaultSize, bool fit=false)
Draw the window on a wxBitmap, then save it to a file.
void DoZoomOutYCalc(const int staticYpixel)
static double zoomIncrementalFactor
This value sets the zoom steps whenever the user clicks "Zoom in/out" or performs zoom with the mouse...
virtual void Plot(wxDC &dc, mpWindow &w) override
Layer plot handler.
wxSize GetSize()
Returns the size of the box (in pixels)
#define mpALIGN_SE
Aligns label to south-east.
Abstract base class providing plot and labeling functionality for functions F:Y->X.
double GetDesiredYmax()
Returns the top layer-border coordinate that the user wants the mpWindow to show (it may be not exact...
virtual double getTickPos(int n)
#define mpLEGEND_LINEWIDTH
void OnMouseWheel(wxMouseEvent &event)
#define mpALIGN_BORDER_RIGHT
Aligns Y axis to right border.
virtual void Plot(wxDC &dc, mpWindow &w) override
Text Layer plot handler.
double x2s(double x) const
#define mpALIGN_SW
Aligns label to south-west.