X-Git-Url: http://git.kpe.io/?p=ctsim.git;a=blobdiff_plain;f=libctgraphics%2Fezplot.cpp;h=72f7e5149fbbfdbc9ff0ea53b4b5ed810db6e397;hp=c00953554e2c087436a2e4092c0ef0df7885280c;hb=df761d2b3cac3d347f4ef0f9f69e88d3bb66b2fa;hpb=2a3686d3bd1f690d318b81766c261da785cf9b57 diff --git a/libctgraphics/ezplot.cpp b/libctgraphics/ezplot.cpp index c009535..72f7e51 100644 --- a/libctgraphics/ezplot.cpp +++ b/libctgraphics/ezplot.cpp @@ -6,7 +6,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ezplot.cpp,v 1.21 2000/12/23 18:12:35 kevin Exp $ +** $Id: ezplot.cpp,v 1.25 2000/12/27 20:09:19 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -35,8 +35,8 @@ static const int MAXNUMFMT = 15; // maximum length of a numeric format static const int DEF_CURVE_CLR = C_RED; -EZPlotCurve::EZPlotCurve (const double* xData, const double* yData, int n, int color, int linestyle, int symbol, int symfreq, const std::string& legend) -: x(NULL), y(NULL), m_sLegend (legend) +EZPlotCurve::EZPlotCurve (const double* xData, const double* yData, int n) +: x(NULL), y(NULL) { x = new double [n]; y = new double [n]; @@ -46,10 +46,6 @@ EZPlotCurve::EZPlotCurve (const double* xData, const double* yData, int n, int c memcpy (y, yData, copyCount); m_iPointCount = n; - m_iColor = color; - m_iLineStyle = linestyle; - m_iSymbol = symbol; - m_iSymbolFreq = symfreq; } EZPlotCurve::~EZPlotCurve () @@ -117,7 +113,7 @@ EZPlot::addCurve (const double x[], const double y[], int num) if (num < 1) return; - EZPlotCurve* pCurve = new EZPlotCurve (x, y, num, o_color, o_linestyle, o_symbol, o_symfreq, c_legend); + EZPlotCurve* pCurve = new EZPlotCurve (x, y, num); m_vecCurves.push_back (pCurve); } @@ -141,7 +137,22 @@ EZPlot::clearCurves () EZPlot::EZPlot (SGP& sgp) : rSGP (sgp) { - initPlotSettings(); + initKeywords(); + m_pol.addSkipWord ("please"); + m_pol.addSkipWord ("use"); + m_pol.addSkipWord ("are"); + m_pol.addSkipWord ("and"); + m_pol.addSkipWord ("is"); + m_pol.addSkipWord ("the"); + m_pol.addSkipWord ("equals"); + m_pol.addSkipChar ('='); + + m_pol.usefile (POL::P_USE_STR,""); + m_pol.set_inputline ("!eoc ,"); + m_pol.reader (); + m_pol.closefile (); + + initPlotSettings(); } void @@ -149,11 +160,12 @@ EZPlot::initPlotSettings () { charheight = rSGP.getCharHeight(); charwidth = rSGP.getCharWidth(); - + + m_iCurrentCurve = -1; + c_xlabel = ""; c_ylabel = ""; c_title = ""; - c_legend = ""; o_xporigin = 0.0; o_yporigin = 0.0; @@ -195,14 +207,125 @@ EZPlot::initPlotSettings () s_textsize = FALSE; clr_axis = C_BLACK; // set fixed colors - clr_title = C_CYAN; - clr_label = C_CYAN; - clr_legend = C_RED; + clr_title = C_RED; + clr_label = C_BLUE; + clr_legend = C_CYAN; clr_number = C_GREEN; clr_grid = C_LTGRAY; } - +void +EZPlot::setColor (unsigned int iCurve, int iColor) +{ + if (m_veciColor.size() <= iCurve) { + m_veciColor.resize ((m_iCurrentCurve + 1) * 2); + m_vecbColorSet.resize ((m_iCurrentCurve + 1) * 2); + } + m_veciColor [iCurve] = iColor; + m_vecbColorSet [iCurve] = true; +} + +void +EZPlot::setSymbol (unsigned int iCurve, int iSymbol) +{ + if (m_veciSymbol.size() <= iCurve) { + m_veciSymbol.resize ((m_iCurrentCurve + 1) * 2); + m_vecbSymbolSet.resize ((m_iCurrentCurve + 1) * 2); + } + m_veciSymbol [iCurve] = iSymbol; + m_vecbSymbolSet [iCurve] = true; +} + +void +EZPlot::setSymbolFreq (unsigned int iCurve, int iSymbolFreq) +{ + if (m_veciSymbolFreq.size() <= iCurve) { + m_veciSymbolFreq.resize ((m_iCurrentCurve + 1) * 2); + m_vecbSymbolFreqSet.resize ((m_iCurrentCurve + 1) * 2); + } + m_veciSymbolFreq [iCurve] = iSymbolFreq; + m_vecbSymbolFreqSet [iCurve] = true; +} + +void +EZPlot::setLinestyle (unsigned int iCurve, int iLinestyle) +{ + if (m_veciLinestyle.size() <= iCurve) { + m_veciLinestyle.resize ((m_iCurrentCurve + 1) * 2); + m_vecbLinestyleSet.resize ((m_iCurrentCurve + 1) * 2); + } + m_veciLinestyle [iCurve] = iLinestyle; + m_vecbLinestyleSet [iCurve] = true; +} + +void +EZPlot::setLegend (unsigned int iCurve, const std::string& strLegend) +{ + if (m_vecsLegend.size() <= iCurve) { + m_vecsLegend.resize ((m_iCurrentCurve + 1) * 2); + m_vecbLegendSet.resize ((m_iCurrentCurve + 1) * 2); + } + m_vecsLegend [iCurve] = strLegend; + m_vecbLegendSet [iCurve] = true; +} + +void +EZPlot::setLegend (unsigned int iCurve, const char* const pszLegend) +{ + if (m_vecsLegend.size() <= iCurve) { + m_vecsLegend.resize ((m_iCurrentCurve + 1) * 2); + m_vecbLegendSet.resize ((m_iCurrentCurve + 1) * 2); + } + m_vecsLegend [iCurve] = pszLegend; + m_vecbLegendSet [iCurve] = true; +} + +int +EZPlot::getColor (unsigned int iCurve) const +{ + if (m_veciColor.size() > iCurve && m_vecbColorSet[iCurve]) + return m_veciColor[iCurve]; + else + return o_color; +} + +int +EZPlot::getSymbol (unsigned int iCurve) const +{ + if (m_veciSymbol.size() > iCurve && m_vecbSymbolSet[iCurve]) + return m_veciSymbol[iCurve]; + else + return o_symbol; +} + +int +EZPlot::getSymbolFreq (unsigned int iCurve) const +{ + if (m_veciSymbolFreq.size() > iCurve && m_vecbSymbolFreqSet[iCurve]) + return m_veciSymbolFreq[iCurve]; + else + return o_symfreq; +} + +int +EZPlot::getLinestyle (unsigned int iCurve) const +{ + if (m_veciLinestyle.size() > iCurve && m_vecbLinestyleSet[iCurve]) + return m_veciLinestyle[iCurve]; + else + return o_linestyle; +} + +const std::string* +EZPlot::getLegend (unsigned int iCurve) const +{ + if (m_vecsLegend.size() > iCurve && m_vecbLegendSet[iCurve]) + return &m_vecsLegend[iCurve]; + else + return NULL; +} + + /* NAME * plot Plots all curves collected by addCurves () * @@ -219,41 +342,34 @@ EZPlot::initPlotSettings () void EZPlot::plot () { -#if 0 - wxFont* myFont = new wxFont (12, wxMODERN, wxNORMAL, wxNORMAL); - rSGP.getDriver().idWX()->SetFont (*myFont); -#endif if (m_vecCurves.size() <= 0) return; rSGP.setWindow (0., 0., 1., 1.); - if (s_textsize == TRUE) { - charheight = v_textsize; - charwidth = rSGP.getCharWidth(); - } else { - charheight = rSGP.getCharHeight(); - charwidth = rSGP.getCharWidth(); - } - - const EZPlotCurve& firstCurve = *m_vecCurves[0]; + if (s_textsize == TRUE) + rSGP.setTextPointSize (v_textsize); + charheight = rSGP.getCharHeight(); + charwidth = rSGP.getCharWidth(); + + const EZPlotCurve& firstCurve = *m_vecCurves[0]; double xmin = firstCurve.x[0]; // extent of curves in world coord double xmax = xmin; double ymin = firstCurve.y[0]; - double ymax = ymin; - - for (EZPlotCurveConstIterator iterCurve = m_vecCurves.begin(); iterCurve != m_vecCurves.end(); iterCurve++) { - const EZPlotCurve& curve = **iterCurve; + double ymax = ymin; + unsigned int iCurve; + for (iCurve = 0; iCurve < m_vecCurves.size(); iCurve++) { + const EZPlotCurve* const pCurve = m_vecCurves [iCurve]; - for (int ip = 0; ip < curve.m_iPointCount; ip++) { - if (curve.x[ip] > xmax) - xmax = curve.x[ip]; - else if (curve.x[ip] < xmin) - xmin = curve.x[ip]; - if (curve.y[ip] > ymax) - ymax = curve.y[ip]; - else if (curve.y[ip] < ymin) - ymin = curve.y[ip]; + for (int ip = 0; ip < pCurve->m_iPointCount; ip++) { + if (pCurve->x[ip] > xmax) + xmax = pCurve->x[ip]; + else if (pCurve->x[ip] < xmin) + xmin = pCurve->x[ip]; + if (pCurve->y[ip] > ymax) + ymax = pCurve->y[ip]; + else if (pCurve->y[ip] < ymin) + ymin = pCurve->y[ip]; } } @@ -338,20 +454,22 @@ EZPlot::plot () ya_max = yp_max; // adjust frame for title + title_row = ya_max;; if (c_title.length() > 0) - ya_max -= 2 * charheight; - title_row = ya_max + 2 * charheight; - + ya_max -= 2 * charheight; + // calculate legend box boundaries int max_leg = 0; // longest legend in characters - int num_leg = 0; // number of legend titles - for (EZPlotCurveConstIterator iterCurve2 = m_vecCurves.begin(); iterCurve2 != m_vecCurves.end(); iterCurve2++) { - const EZPlotCurve& curve = **iterCurve2; - int nLegend = curve.m_sLegend.length(); - if (nLegend > 0) { - ++num_leg; - if (nLegend > max_leg) - nLegend = max_leg; + int num_leg = 0; // number of legend titles + for (iCurve = 0; iCurve < m_vecCurves.size(); iCurve++) { + const std::string* pstrLegend = getLegend (iCurve); + if (pstrLegend && pstrLegend->length() > 0) { + int nLegend = pstrLegend->length(); + if (nLegend > 0) { + ++num_leg; + if (nLegend > max_leg) + nLegend = max_leg; + } } } @@ -378,31 +496,32 @@ EZPlot::plot () rSGP.setColor (clr_legend); rSGP.drawRect (xl_min, yl_min, xl_max, yl_max); - int iLegend = 0; // current legend position - for (EZPlotCurveIterator iterCurve = m_vecCurves.begin(); iterCurve != m_vecCurves.end(); iterCurve++) { - const EZPlotCurve& curve = **iterCurve; - - if (curve.m_sLegend.length() == 0) + int iLegend = 0; // current legend position + for (iCurve = 0; iCurve < m_vecCurves.size(); iCurve++) { + const std::string* pstrLegend = getLegend (iCurve); + if (! pstrLegend || pstrLegend->length() == 0) continue; double xmin = xl_min + 1.0 * charwidth; double xmax = xl_max - 1.0 * charwidth; double y = yl_max - (2.0 + iLegend * 3) * charheight; - rSGP.moveAbs (xmin, y + 0.5 * charheight); - rSGP.drawText (curve.m_sLegend); - rSGP.setColor (curve.m_iColor); - if (curve.m_iLineStyle != SGP::LS_NOLINE) { - rSGP.setLineStyle (curve.m_iLineStyle); + rSGP.moveAbs (xmin, y + 0.5 * charheight); + rSGP.drawText (pstrLegend->c_str()); + rSGP.setColor (getColor (iCurve)); + int iLS = getLinestyle (iCurve); + if (iLS != SGP::LS_NOLINE) { + rSGP.setLineStyle (iLS); rSGP.moveAbs (xmin, y); rSGP.lineAbs (xmax, y); - } - if (curve.m_iSymbol > 0) { + } + int iSymbol = getSymbol (iCurve); + if (iSymbol > 0) { double xinc = (xmax - xmin) / (5 - 1); rSGP.setLineStyle (SGP::LS_SOLID); for (int j = 0; j < 5; j++) { rSGP.moveAbs (xmin + j * xinc, y); - symbol(curve.m_iSymbol, 0.5 * charwidth, 0.5 * charheight); + symbol(iSymbol, 0.5 * charwidth, 0.5 * charheight); } } ++iLegend; // move to next legend position @@ -417,13 +536,20 @@ EZPlot::plot () // X-Label if (c_xlabel.length() > 0) - ya_min += 3.0 * charheight; + ya_min += 1.5 * charheight; xlbl_row = xp_min; // put x-label on bottom of plot frame // Y-Label - if (c_ylabel.length() > 0) - xa_min += 3.0 * charwidth; // reverse rSGP.setTextSize because writing text sideways - ylbl_col = xp_min + 2 * charwidth; + if (c_ylabel.length() > 0) { + rSGP.setTextAngle (HALFPI); + rSGP.setTextSize (1.5 * charheight); + double xExtent, yExtent; + rSGP.getTextExtent (c_ylabel.c_str(), &xExtent, &yExtent); + rSGP.setTextSize (charheight); + xa_min += xExtent; + rSGP.setTextAngle (0.0); + } + ylbl_col = xp_min; /*------------------------------*/ /* adjust frame for tick labels */ @@ -433,17 +559,19 @@ EZPlot::plot () if (o_xaxis == NOAXIS || o_xtlabel == FALSE) xtl_ofs = 0.0; else if (o_xticks == BELOW) - xtl_ofs = -1.5 * charheight; // kr + xtl_ofs = -0.5 * charheight; else if (o_xticks == ABOVE) - xtl_ofs = 1.5 * charheight; + xtl_ofs = 0.5 * charheight; if (o_yaxis == NOAXIS || o_ytlabel == FALSE) ytl_ofs = 0.0; else if (o_yticks == LEFT) - ytl_ofs = -(1 + y_fldwid) * charwidth; + ytl_ofs = -(2 + y_fldwid) * charwidth; else if (o_yticks == RIGHT) ytl_ofs = 1.5 * charwidth; + xa_max -= 0.7 * x_fldwid * charwidth; // make room for last x tick label + xt_min = xa_min; yt_min = ya_min; xt_max = xa_max; @@ -452,18 +580,18 @@ EZPlot::plot () // see if need to shrink axis extents and/or tick extents if (xtl_ofs != 0.0 && s_ycross == FALSE) { if (o_xticks == BELOW) { - ya_min += 2.5 * charheight; + ya_min += 1.5 * charheight; yt_min = ya_min; } else if (o_xticks == ABOVE) { ya_min += 0.0; - yt_min = ya_min + 2.5 * charheight; + yt_min = ya_min + 1.5 * charheight; } } else // noaxis, no t-labels, or user set cross yt_min = ya_min; if (ytl_ofs != 0.0 && s_xcross == FALSE) { if (o_yticks == LEFT) { - xa_min += (1 + y_fldwid) * charwidth; + xa_min += (2 + y_fldwid) * charwidth; xt_min = xa_min; } else if (o_yticks == RIGHT) { xa_min += 0.0; @@ -471,7 +599,7 @@ EZPlot::plot () } } else xt_min = xa_min; - + // decrease size of graph, if necessary, to accommadate space // between axis boundary and boundary of ticks double x_added_ticks = 0; // number of tick spaces added to axis @@ -531,20 +659,21 @@ EZPlot::plot () double clipRect[4]; clipRect[0] = xgn_min; clipRect[1] = ygn_min; clipRect[2] = xgn_max; clipRect[3] = ygn_max; - - for (EZPlotCurveIterator iterCurve3 = m_vecCurves.begin(); iterCurve3 != m_vecCurves.end(); iterCurve3++) { - const EZPlotCurve& curve = **iterCurve3; - - rSGP.setColor (curve.m_iColor); + + for (iCurve = 0; iCurve < m_vecCurves.size(); iCurve++) { + const EZPlotCurve* const pCurve = m_vecCurves [iCurve]; - bool bOutside = false; - if (curve.m_iLineStyle != SGP::LS_NOLINE) { - rSGP.setLineStyle (curve.m_iLineStyle); - double x1 = convertWorldToNDC_X (curve.x[0]); - double y1 = convertWorldToNDC_Y (curve.y[0]); - for (int i = 1; i < curve.m_iPointCount; i++) { - double x2 = convertWorldToNDC_X (curve.x[i]); - double y2 = convertWorldToNDC_Y (curve.y[i]); + rSGP.setColor (getColor (iCurve)); + int iSym = getSymbol (iCurve); + int iLS = getLinestyle (iCurve); + + if (iLS != SGP::LS_NOLINE) { + rSGP.setLineStyle (iLS); + double x1 = convertWorldToNDC_X (pCurve->x[0]); + double y1 = convertWorldToNDC_Y (pCurve->y[0]); + for (int i = 1; i < pCurve->m_iPointCount; i++) { + double x2 = convertWorldToNDC_X (pCurve->x[i]); + double y2 = convertWorldToNDC_Y (pCurve->y[i]); double x2Clip = x2; double y2Clip = y2; if (clip_rect (x1, y1, x2Clip, y2Clip, clipRect)) { @@ -555,19 +684,20 @@ EZPlot::plot () y1 = y2; } } - if (curve.m_iSymbol > 0) { + if (iSym > 0) { + int iSymFreq = getSymbolFreq (iCurve); rSGP.setLineStyle (SGP::LS_SOLID); - double x = convertWorldToNDC_X (curve.x[0]); - double y = convertWorldToNDC_Y (curve.y[0]); + double x = convertWorldToNDC_X (pCurve->x[0]); + double y = convertWorldToNDC_Y (pCurve->y[0]); rSGP.moveAbs (x, y); - symbol (curve.m_iSymbol, symwidth, symheight); - for (int i = 1; i < curve.m_iPointCount; i++) - if (i % curve.m_iSymbolFreq == 0 || i == curve.m_iPointCount - 1) { - x = convertWorldToNDC_X (curve.x[i]); - y = convertWorldToNDC_Y (curve.y[i]); + symbol (iSym, symwidth, symheight); + for (int i = 1; i < pCurve->m_iPointCount; i++) + if (i % iSymFreq == 0 || i == pCurve->m_iPointCount - 1) { + x = convertWorldToNDC_X (pCurve->x[i]); + y = convertWorldToNDC_Y (pCurve->y[i]); if (y >= ygn_min && y <= ygn_max) { rSGP.moveAbs (x, y); - symbol (curve.m_iSymbol, symwidth, symheight); + symbol (iSym, symwidth, symheight); } } } @@ -600,9 +730,9 @@ EZPlot::drawAxes() rSGP.setTextColor (1, -1); if (o_xticks == ABOVE) - xticklen = charheight; + xticklen = 0.5 * charheight; else if (o_xticks == BELOW) - xticklen = -charheight; + xticklen = -0.5 * charheight; if (o_yticks == RIGHT) yticklen = charwidth; @@ -670,9 +800,11 @@ EZPlot::drawAxes() rSGP.lineAbs (xt_min + xn_tickinc * i, ya_min); } } - rSGP.moveAbs (xa_min + (xa_max-xa_min)/2 - c_xlabel.length()*charwidth * 1.5, xlbl_row + charheight * 1.5); rSGP.setTextSize (charheight * 1.5); - rSGP.setTextColor (clr_label, -1); + rSGP.setTextColor (clr_label, -1); + double wText, hText; + rSGP.getTextExtent (c_xlabel.c_str(), &wText, &hText); + rSGP.moveAbs (xa_min + (xa_max-xa_min)/2 - wText / 2, xlbl_row + charheight * 1.5); rSGP.drawText (c_xlabel); rSGP.setTextSize (charheight); minorinc = xn_tickinc / (o_xminortick + 1); @@ -735,12 +867,14 @@ EZPlot::drawAxes() rSGP.moveAbs (xa_max, y); rSGP.lineAbs (xa_min, y); } - } - rSGP.moveAbs (ylbl_col, ya_min + (ya_max-ya_min)/2 - c_ylabel.length()*charheight*1.5); - rSGP.getDriver().idWX()->SetFont(*wxSWISS_FONT); + } rSGP.setTextAngle (HALFPI); rSGP.setTextSize (1.5 * charheight); - rSGP.setTextColor (clr_label, -1); + rSGP.setTextColor (clr_label, -1); + double xExtent, yExtent; + rSGP.getTextExtent (c_ylabel.c_str(), &xExtent, &yExtent); + rSGP.moveAbs (ylbl_col, ya_min + (ya_max-ya_min)/2 - yExtent / 2); + rSGP.drawText (c_ylabel); rSGP.setTextAngle (0.0); rSGP.setTextSize (charheight); minorinc = yn_tickinc / (o_yminortick + 1); @@ -767,8 +901,8 @@ EZPlot::drawAxes() axis_near = TRUE; } if (o_ytlabel == TRUE && axis_near == FALSE) { - snprintf (str, sizeof(str), y_numfmt, ygw_min + yw_tickinc * i); - rSGP.moveAbs (yaxispos + ytl_ofs, y + 0.5 * charheight); + snprintf (str, sizeof(str), y_numfmt, ygw_min + yw_tickinc * i); + rSGP.moveAbs (yaxispos + ytl_ofs, y + 0.5 * charheight); rSGP.setTextColor (clr_number, -1); rSGP.drawText (str); }