# qwt_plot_axis.cpp

    00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
    00002  * Qwt Widget Library
    00003  * Copyright (C) 1997   Josef Wilgen
    00004  * Copyright (C) 2002   Uwe Rathmann
    00005  *
    00006  * This library is free software; you can redistribute it and/or
    00007  * modify it under the terms of the Qwt License, Version 1.0
    00008  *****************************************************************************/
    00009
    00010 #include "qwt_plot.h"
    00011 #include "qwt_math.h"
    00012 #include "qwt_scale_widget.h"
    00013 #include "qwt_scale_div.h"
    00014 #include "qwt_scale_engine.h"
    00015
    00016 class QwtPlot::AxisData
    00017 {
    00018 public:
    00019     bool isEnabled;
    00020     bool doAutoScale;
    00021
    00022     double minValue;
    00023     double maxValue;
    00024     double stepSize;
    00025
    00026     int maxMajor;
    00027     int maxMinor;
    00028
    00029     QwtScaleDiv scaleDiv;
    00030     QwtScaleEngine *scaleEngine;
    00031     QwtScaleWidget *scaleWidget;
    00032 };
    00033
    00035 void QwtPlot::initAxesData()
    00036 {
    00037     int axisId;
    00038
    00039     for( axisId = 0; axisId < axisCnt; axisId++)
    00040         d_axisData[axisId] = new AxisData;
    00041
    00042     d_axisData[yLeft]->scaleWidget =
    00043         new QwtScaleWidget(QwtScaleDraw::LeftScale, this);
    00044     d_axisData[yRight]->scaleWidget =
    00045         new QwtScaleWidget(QwtScaleDraw::RightScale, this);
    00046     d_axisData[xTop]->scaleWidget =
    00047         new QwtScaleWidget(QwtScaleDraw::TopScale, this);
    00048     d_axisData[xBottom]->scaleWidget =
    00049         new QwtScaleWidget(QwtScaleDraw::BottomScale, this);
    00050
    00051
    00052     QFont fscl(fontInfo().family(), 10);
    00053     QFont fttl(fontInfo().family(), 12, QFont::Bold);
    00054
    00055     for(axisId = 0; axisId < axisCnt; axisId++)
    00056     {
    00057         AxisData &d = *d_axisData[axisId];
    00058
    00059         d.scaleWidget->setFont(fscl);
    00060         d.scaleWidget->setMargin(2);
    00061
    00062         QwtText text;
    00063         text.setFont(fttl);
    00064         d.scaleWidget->setTitle(text);
    00065
    00066         d.doAutoScale = true;
    00067
    00068         d.minValue = 0.0;
    00069         d.maxValue = 1000.0;
    00070         d.stepSize = 0.0;
    00071
    00072         d.maxMinor = 5;
    00073         d.maxMajor = 8;
    00074
    00075         d.scaleEngine = new QwtLinearScaleEngine;
    00076
    00077         d.scaleDiv.invalidate();
    00078     }
    00079
    00080     d_axisData[yLeft]->isEnabled = true;
    00081     d_axisData[yRight]->isEnabled = false;
    00082     d_axisData[xBottom]->isEnabled = true;
    00083     d_axisData[xTop]->isEnabled = false;
    00084 }
    00085
    00086 void QwtPlot::deleteAxesData()
    00087 {
    00088     for( int axisId = 0; axisId < axisCnt; axisId++)
    00089     {
    00090         delete d_axisData[axisId]->scaleEngine;
    00091         delete d_axisData[axisId];
    00092         d_axisData[axisId] = NULL;
    00093     }
    00094 }
    00095
    00100 const QwtScaleWidget *QwtPlot::axisWidget(int axisId) const
    00101 {
    00102     if (axisValid(axisId))
    00103         return d_axisData[axisId]->scaleWidget;
    00104
    00105     return NULL;
    00106 }
    00107
    00112 QwtScaleWidget *QwtPlot::axisWidget(int axisId)
    00113 {
    00114     if (axisValid(axisId))
    00115         return d_axisData[axisId]->scaleWidget;
    00116
    00117     return NULL;
    00118 }
    00119
    00120 void QwtPlot::setAxisScaleEngine(int axisId, QwtScaleEngine *scaleEngine)
    00121 {
    00122     if (axisValid(axisId) && scaleEngine != NULL )
    00123     {
    00124         AxisData &d = *d_axisData[axisId];
    00125
    00126         delete d.scaleEngine;
    00127         d.scaleEngine = scaleEngine;
    00128
    00129         d.scaleDiv.invalidate();
    00130
    00131         autoRefresh();
    00132     }
    00133 }
    00134
    00135 QwtScaleEngine *QwtPlot::axisScaleEngine(int axisId)
    00136 {
    00137     if (axisValid(axisId))
    00138         return d_axisData[axisId]->scaleEngine;
    00139     else
    00140         return NULL;
    00141 }
    00142
    00143 const QwtScaleEngine *QwtPlot::axisScaleEngine(int axisId) const
    00144 {
    00145     if (axisValid(axisId))
    00146         return d_axisData[axisId]->scaleEngine;
    00147     else
    00148         return NULL;
    00149 }
    00154 bool QwtPlot::axisAutoScale(int axisId) const
    00155 {
    00156     if (axisValid(axisId))
    00157         return d_axisData[axisId]->doAutoScale;
    00158     else
    00159         return false;
    00160
    00161 }
    00162
    00167 bool QwtPlot::axisEnabled(int axisId) const
    00168 {
    00169     if (axisValid(axisId))
    00170         return d_axisData[axisId]->isEnabled;
    00171     else
    00172         return false;
    00173 }
    00174
    00179 QFont QwtPlot::axisFont(int axisId) const
    00180 {
    00181     if (axisValid(axisId))
    00182         return axisWidget(axisId)->font();
    00183     else
    00184         return QFont();
    00185
    00186 }
    00187
    00192 int QwtPlot::axisMaxMajor(int axisId) const
    00193 {
    00194     if (axisValid(axisId))
    00195         return d_axisData[axisId]->maxMajor;
    00196     else
    00197         return 0;
    00198 }
    00199
    00204 int QwtPlot::axisMaxMinor(int axisId) const
    00205 {
    00206     if (axisValid(axisId))
    00207         return d_axisData[axisId]->maxMinor;
    00208     else
    00209         return 0;
    00210 }
    00211
    00223 const QwtScaleDiv *QwtPlot::axisScaleDiv(int axisId) const
    00224 {
    00225     if (!axisValid(axisId))
    00226         return NULL;
    00227
    00228     return &d_axisData[axisId]->scaleDiv;
    00229 }
    00230
    00242 QwtScaleDiv *QwtPlot::axisScaleDiv(int axisId)
    00243 {
    00244     if (!axisValid(axisId))
    00245         return NULL;
    00246
    00247     return &d_axisData[axisId]->scaleDiv;
    00248 }
    00249
    00256 const QwtScaleDraw *QwtPlot::axisScaleDraw(int axisId) const
    00257 {
    00258     if (!axisValid(axisId))
    00259         return NULL;
    00260
    00261     return axisWidget(axisId)->scaleDraw();
    00262 }
    00263
    00270 QwtScaleDraw *QwtPlot::axisScaleDraw(int axisId)
    00271 {
    00272     if (!axisValid(axisId))
    00273         return NULL;
    00274
    00275     return axisWidget(axisId)->scaleDraw();
    00276 }
    00277
    00282 QwtText QwtPlot::axisTitle(int axisId) const
    00283 {
    00284     if (axisValid(axisId))
    00285         return axisWidget(axisId)->title();
    00286     else
    00287         return QwtText();
    00288 }
    00289
    00302 void QwtPlot::enableAxis(int axisId, bool tf)
    00303 {
    00304     if (axisValid(axisId) && tf != d_axisData[axisId]->isEnabled)
    00305     {
    00306         d_axisData[axisId]->isEnabled = tf;
    00307         updateLayout();
    00308     }
    00309 }
    00310
    00319 double QwtPlot::invTransform(int axisId, int pos) const
    00320 {
    00321     if (axisValid(axisId))
    00322        return(canvasMap(axisId).invTransform(pos));
    00323     else
    00324        return 0.0;
    00325 }
    00326
    00327
    00335 int QwtPlot::transform(int axisId, double value) const
    00336 {
    00337     if (axisValid(axisId))
    00338        return(canvasMap(axisId).transform(value));
    00339     else
    00340        return 0;
    00341
    00342 }
    00343
    00351 void QwtPlot::setAxisFont(int axisId, const QFont &f)
    00352 {
    00353     if (axisValid(axisId))
    00354         axisWidget(axisId)->setFont(f);
    00355 }
    00356
    00366 void QwtPlot::setAxisAutoScale(int axisId)
    00367 {
    00368     if (axisValid(axisId) && !d_axisData[axisId]->doAutoScale )
    00369     {
    00370         d_axisData[axisId]->doAutoScale = true;
    00371         autoRefresh();
    00372     }
    00373 }
    00374
    00384 void QwtPlot::setAxisScale(int axisId, double min, double max, double stepSize)
    00385 {
    00386     if (axisValid(axisId))
    00387     {
    00388         AxisData &d = *d_axisData[axisId];
    00389
    00390         d.doAutoScale = false;
    00391         d.scaleDiv.invalidate();
    00392
    00393         d.minValue = min;
    00394         d.maxValue = max;
    00395         d.stepSize = stepSize;
    00396
    00397         autoRefresh();
    00398     }
    00399 }
    00400
    00407 void QwtPlot::setAxisScaleDiv(int axisId, const QwtScaleDiv &scaleDiv)
    00408 {
    00409     if (axisValid(axisId))
    00410     {
    00411         AxisData &d = *d_axisData[axisId];
    00412
    00413         d.doAutoScale = false;
    00414         d.scaleDiv = scaleDiv;
    00415
    00416         autoRefresh();
    00417     }
    00418 }
    00419
    00435 void QwtPlot::setAxisScaleDraw(int axisId, QwtScaleDraw *scaleDraw)
    00436 {
    00437     if (axisValid(axisId))
    00438     {
    00439         axisWidget(axisId)->setScaleDraw(scaleDraw);
    00440         autoRefresh();
    00441     }
    00442 }
    00443
    00450 #if QT_VERSION < 0x040000
    00451 void QwtPlot::setAxisLabelAlignment(int axisId, int alignment)
    00452 #else
    00453 void QwtPlot::setAxisLabelAlignment(int axisId, Qt::Alignment alignment)
    00454 #endif
    00455 {
    00456     if (axisValid(axisId))
    00457         axisWidget(axisId)->setLabelAlignment(alignment);
    00458 }
    00459
    00467 void QwtPlot::setAxisLabelRotation(int axisId, double rotation)
    00468 {
    00469     if (axisValid(axisId))
    00470         axisWidget(axisId)->setLabelRotation(rotation);
    00471 }
    00472
    00479 void QwtPlot::setAxisMaxMinor(int axisId, int maxMinor)
    00480 {
    00481     if (axisValid(axisId))
    00482     {
    00483         if ( maxMinor < 0 )
    00484             maxMinor = 0;
    00485         if ( maxMinor > 100 )
    00486             maxMinor = 100;
    00487
    00488         AxisData &d = *d_axisData[axisId];
    00489
    00490         if ( maxMinor != d.maxMinor )
    00491         {
    00492             d.maxMinor = maxMinor;
    00493             d.scaleDiv.invalidate();
    00494             autoRefresh();
    00495         }
    00496     }
    00497 }
    00498
    00505 void QwtPlot::setAxisMaxMajor(int axisId, int maxMajor)
    00506 {
    00507     if (axisValid(axisId))
    00508     {
    00509         if ( maxMajor < 1 )
    00510             maxMajor = 1;
    00511         if ( maxMajor > 1000 )
    00512             maxMajor = 10000;
    00513
    00514         AxisData &d = *d_axisData[axisId];
    00515         if ( maxMajor != d.maxMinor )
    00516         {
    00517             d.maxMajor = maxMajor;
    00518             d.scaleDiv.invalidate();
    00519             autoRefresh();
    00520         }
    00521     }
    00522 }
    00523
    00529 void QwtPlot::setAxisTitle(int axisId, const QString &title)
    00530 {
    00531     if (axisValid(axisId))
    00532         axisWidget(axisId)->setTitle(title);
    00533 }
    00534
    00540 void QwtPlot::setAxisTitle(int axisId, const QwtText &title)
    00541 {
    00542     if (axisValid(axisId))
    00543         axisWidget(axisId)->setTitle(title);
    00544 }
    00545
    00547 void QwtPlot::updateAxes()
    00548 {
    00549     // Find bounding interval of the item data
    00550     // for all axes, where autoscaling is enabled
    00551
    00552     QwtDoubleInterval intv[axisCnt];
    00553
    00554     const QwtPlotItemList& itmList = itemList();
    00555
    00556     QwtPlotItemIterator it;
    00557     for ( it = itmList.begin(); it != itmList.end(); ++it )
    00558     {
    00559         const QwtPlotItem *item = *it;
    00560
    00561         if ( !item->testItemAttribute(QwtPlotItem::AutoScale) )
    00562             continue;
    00563
    00564         if ( axisAutoScale(item->xAxis()) || axisAutoScale(item->yAxis()) )
    00565         {
    00566             const QwtDoubleRect rect = item->boundingRect();
    00567             intv[item->xAxis()] |= QwtDoubleInterval(rect.left(), rect.right());
    00568             intv[item->yAxis()] |= QwtDoubleInterval(rect.top(), rect.bottom());
    00569         }
    00570     }
    00571
    00572     // Adjust scales
    00573
    00574     for (int axisId = 0; axisId < axisCnt; axisId++)
    00575     {
    00576         AxisData &d = *d_axisData[axisId];
    00577
    00578         double minValue = d.minValue;
    00579         double maxValue = d.maxValue;
    00580         double stepSize = d.stepSize;
    00581
    00582         if ( d.doAutoScale && intv[axisId].isValid() )
    00583         {
    00584             d.scaleDiv.invalidate();
    00585
    00586             minValue = intv[axisId].minValue();
    00587             maxValue = intv[axisId].maxValue();
    00588
    00589             d.scaleEngine->autoScale(d.maxMajor,
    00590                 minValue, maxValue, stepSize);
    00591         }
    00592         if ( !d.scaleDiv.isValid() )
    00593         {
    00594             d.scaleDiv = d.scaleEngine->divideScale(
    00595                 minValue, maxValue,
    00596                 d.maxMajor, d.maxMinor, stepSize);
    00597         }
    00598
    00599         QwtScaleWidget *scaleWidget = axisWidget(axisId);
    00600         scaleWidget->setScaleDiv(
    00601             d.scaleEngine->transformation(), d.scaleDiv);
    00602
    00603         int startDist, endDist;
    00604         scaleWidget->getBorderDistHint(startDist, endDist);
    00605         scaleWidget->setBorderDist(startDist, endDist);
    00606     }
    00607
    00608     for ( it = itmList.begin(); it != itmList.end(); ++it )
    00609     {
    00610         QwtPlotItem *item = *it;
    00611         item->updateScaleDiv( *axisScaleDiv(item->xAxis()),
    00612             *axisScaleDiv(item->yAxis()));
    00613     }
    00614 }
    00615