# 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 = d.scaleWidget->title();
    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
    00128 void QwtPlot::setAxisScaleEngine(int axisId, QwtScaleEngine *scaleEngine)
    00129 {
    00130     if (axisValid(axisId) && scaleEngine != NULL )
    00131     {
    00132         AxisData &d = *d_axisData[axisId];
    00133
    00134         delete d.scaleEngine;
    00135         d.scaleEngine = scaleEngine;
    00136
    00137         d.scaleDiv.invalidate();
    00138
    00139         autoRefresh();
    00140     }
    00141 }
    00142
    00144 QwtScaleEngine *QwtPlot::axisScaleEngine(int axisId)
    00145 {
    00146     if (axisValid(axisId))
    00147         return d_axisData[axisId]->scaleEngine;
    00148     else
    00149         return NULL;
    00150 }
    00151
    00153 const QwtScaleEngine *QwtPlot::axisScaleEngine(int axisId) const
    00154 {
    00155     if (axisValid(axisId))
    00156         return d_axisData[axisId]->scaleEngine;
    00157     else
    00158         return NULL;
    00159 }
    00164 bool QwtPlot::axisAutoScale(int axisId) const
    00165 {
    00166     if (axisValid(axisId))
    00167         return d_axisData[axisId]->doAutoScale;
    00168     else
    00169         return false;
    00170
    00171 }
    00172
    00177 bool QwtPlot::axisEnabled(int axisId) const
    00178 {
    00179     if (axisValid(axisId))
    00180         return d_axisData[axisId]->isEnabled;
    00181     else
    00182         return false;
    00183 }
    00184
    00189 QFont QwtPlot::axisFont(int axisId) const
    00190 {
    00191     if (axisValid(axisId))
    00192         return axisWidget(axisId)->font();
    00193     else
    00194         return QFont();
    00195
    00196 }
    00197
    00203 int QwtPlot::axisMaxMajor(int axisId) const
    00204 {
    00205     if (axisValid(axisId))
    00206         return d_axisData[axisId]->maxMajor;
    00207     else
    00208         return 0;
    00209 }
    00210
    00216 int QwtPlot::axisMaxMinor(int axisId) const
    00217 {
    00218     if (axisValid(axisId))
    00219         return d_axisData[axisId]->maxMinor;
    00220     else
    00221         return 0;
    00222 }
    00223
    00235 const QwtScaleDiv *QwtPlot::axisScaleDiv(int axisId) const
    00236 {
    00237     if (!axisValid(axisId))
    00238         return NULL;
    00239
    00240     return &d_axisData[axisId]->scaleDiv;
    00241 }
    00242
    00254 QwtScaleDiv *QwtPlot::axisScaleDiv(int axisId)
    00255 {
    00256     if (!axisValid(axisId))
    00257         return NULL;
    00258
    00259     return &d_axisData[axisId]->scaleDiv;
    00260 }
    00261
    00268 const QwtScaleDraw *QwtPlot::axisScaleDraw(int axisId) const
    00269 {
    00270     if (!axisValid(axisId))
    00271         return NULL;
    00272
    00273     return axisWidget(axisId)->scaleDraw();
    00274 }
    00275
    00282 QwtScaleDraw *QwtPlot::axisScaleDraw(int axisId)
    00283 {
    00284     if (!axisValid(axisId))
    00285         return NULL;
    00286
    00287     return axisWidget(axisId)->scaleDraw();
    00288 }
    00289
    00300 double QwtPlot::axisStepSize(int axisId) const
    00301 {
    00302     if (!axisValid(axisId))
    00303         return 0;
    00304
    00305     return d_axisData[axisId]->stepSize;
    00306 }
    00307
    00312 QwtText QwtPlot::axisTitle(int axisId) const
    00313 {
    00314     if (axisValid(axisId))
    00315         return axisWidget(axisId)->title();
    00316     else
    00317         return QwtText();
    00318 }
    00319
    00332 void QwtPlot::enableAxis(int axisId, bool tf)
    00333 {
    00334     if (axisValid(axisId) && tf != d_axisData[axisId]->isEnabled)
    00335     {
    00336         d_axisData[axisId]->isEnabled = tf;
    00337         updateLayout();
    00338     }
    00339 }
    00340
    00349 double QwtPlot::invTransform(int axisId, int pos) const
    00350 {
    00351     if (axisValid(axisId))
    00352        return(canvasMap(axisId).invTransform(pos));
    00353     else
    00354        return 0.0;
    00355 }
    00356
    00357
    00365 int QwtPlot::transform(int axisId, double value) const
    00366 {
    00367     if (axisValid(axisId))
    00368        return(canvasMap(axisId).transform(value));
    00369     else
    00370        return 0;
    00371
    00372 }
    00373
    00381 void QwtPlot::setAxisFont(int axisId, const QFont &f)
    00382 {
    00383     if (axisValid(axisId))
    00384         axisWidget(axisId)->setFont(f);
    00385 }
    00386
    00396 void QwtPlot::setAxisAutoScale(int axisId)
    00397 {
    00398     if (axisValid(axisId) && !d_axisData[axisId]->doAutoScale )
    00399     {
    00400         d_axisData[axisId]->doAutoScale = true;
    00401         autoRefresh();
    00402     }
    00403 }
    00404
    00414 void QwtPlot::setAxisScale(int axisId, double min, double max, double stepSize)
    00415 {
    00416     if (axisValid(axisId))
    00417     {
    00418         AxisData &d = *d_axisData[axisId];
    00419
    00420         d.doAutoScale = false;
    00421         d.scaleDiv.invalidate();
    00422
    00423         d.minValue = min;
    00424         d.maxValue = max;
    00425         d.stepSize = stepSize;
    00426
    00427         autoRefresh();
    00428     }
    00429 }
    00430
    00437 void QwtPlot::setAxisScaleDiv(int axisId, const QwtScaleDiv &scaleDiv)
    00438 {
    00439     if (axisValid(axisId))
    00440     {
    00441         AxisData &d = *d_axisData[axisId];
    00442
    00443         d.doAutoScale = false;
    00444         d.scaleDiv = scaleDiv;
    00445
    00446         autoRefresh();
    00447     }
    00448 }
    00449
    00465 void QwtPlot::setAxisScaleDraw(int axisId, QwtScaleDraw *scaleDraw)
    00466 {
    00467     if (axisValid(axisId))
    00468     {
    00469         axisWidget(axisId)->setScaleDraw(scaleDraw);
    00470         autoRefresh();
    00471     }
    00472 }
    00473
    00480 #if QT_VERSION < 0x040000
    00481 void QwtPlot::setAxisLabelAlignment(int axisId, int alignment)
    00482 #else
    00483 void QwtPlot::setAxisLabelAlignment(int axisId, Qt::Alignment alignment)
    00484 #endif
    00485 {
    00486     if (axisValid(axisId))
    00487         axisWidget(axisId)->setLabelAlignment(alignment);
    00488 }
    00489
    00497 void QwtPlot::setAxisLabelRotation(int axisId, double rotation)
    00498 {
    00499     if (axisValid(axisId))
    00500         axisWidget(axisId)->setLabelRotation(rotation);
    00501 }
    00502
    00510 void QwtPlot::setAxisMaxMinor(int axisId, int maxMinor)
    00511 {
    00512     if (axisValid(axisId))
    00513     {
    00514         if ( maxMinor < 0 )
    00515             maxMinor = 0;
    00516         if ( maxMinor > 100 )
    00517             maxMinor = 100;
    00518
    00519         AxisData &d = *d_axisData[axisId];
    00520
    00521         if ( maxMinor != d.maxMinor )
    00522         {
    00523             d.maxMinor = maxMinor;
    00524             d.scaleDiv.invalidate();
    00525             autoRefresh();
    00526         }
    00527     }
    00528 }
    00529
    00537 void QwtPlot::setAxisMaxMajor(int axisId, int maxMajor)
    00538 {
    00539     if (axisValid(axisId))
    00540     {
    00541         if ( maxMajor < 1 )
    00542             maxMajor = 1;
    00543         if ( maxMajor > 1000 )
    00544             maxMajor = 10000;
    00545
    00546         AxisData &d = *d_axisData[axisId];
    00547         if ( maxMajor != d.maxMinor )
    00548         {
    00549             d.maxMajor = maxMajor;
    00550             d.scaleDiv.invalidate();
    00551             autoRefresh();
    00552         }
    00553     }
    00554 }
    00555
    00561 void QwtPlot::setAxisTitle(int axisId, const QString &title)
    00562 {
    00563     if (axisValid(axisId))
    00564         axisWidget(axisId)->setTitle(title);
    00565 }
    00566
    00572 void QwtPlot::setAxisTitle(int axisId, const QwtText &title)
    00573 {
    00574     if (axisValid(axisId))
    00575         axisWidget(axisId)->setTitle(title);
    00576 }
    00577
    00579 void QwtPlot::updateAxes()
    00580 {
    00581     // Find bounding interval of the item data
    00582     // for all axes, where autoscaling is enabled
    00583
    00584     QwtDoubleInterval intv[axisCnt];
    00585
    00586     const QwtPlotItemList& itmList = itemList();
    00587
    00588     QwtPlotItemIterator it;
    00589     for ( it = itmList.begin(); it != itmList.end(); ++it )
    00590     {
    00591         const QwtPlotItem *item = *it;
    00592
    00593         if ( !item->testItemAttribute(QwtPlotItem::AutoScale) )
    00594             continue;
    00595
    00596         if ( axisAutoScale(item->xAxis()) || axisAutoScale(item->yAxis()) )
    00597         {
    00598             const QwtDoubleRect rect = item->boundingRect();
    00599             intv[item->xAxis()] |= QwtDoubleInterval(rect.left(), rect.right());
    00600             intv[item->yAxis()] |= QwtDoubleInterval(rect.top(), rect.bottom());
    00601         }
    00602     }
    00603
    00604     // Adjust scales
    00605
    00606     for (int axisId = 0; axisId < axisCnt; axisId++)
    00607     {
    00608         AxisData &d = *d_axisData[axisId];
    00609
    00610         double minValue = d.minValue;
    00611         double maxValue = d.maxValue;
    00612         double stepSize = d.stepSize;
    00613
    00614         if ( d.doAutoScale && intv[axisId].isValid() )
    00615         {
    00616             d.scaleDiv.invalidate();
    00617
    00618             minValue = intv[axisId].minValue();
    00619             maxValue = intv[axisId].maxValue();
    00620
    00621             d.scaleEngine->autoScale(d.maxMajor,
    00622                 minValue, maxValue, stepSize);
    00623         }
    00624         if ( !d.scaleDiv.isValid() )
    00625         {
    00626             d.scaleDiv = d.scaleEngine->divideScale(
    00627                 minValue, maxValue,
    00628                 d.maxMajor, d.maxMinor, stepSize);
    00629         }
    00630
    00631         QwtScaleWidget *scaleWidget = axisWidget(axisId);
    00632         scaleWidget->setScaleDiv(
    00633             d.scaleEngine->transformation(), d.scaleDiv);
    00634
    00635         int startDist, endDist;
    00636         scaleWidget->getBorderDistHint(startDist, endDist);
    00637         scaleWidget->setBorderDist(startDist, endDist);
    00638     }
    00639
    00640     for ( it = itmList.begin(); it != itmList.end(); ++it )
    00641     {
    00642         QwtPlotItem *item = *it;
    00643         item->updateScaleDiv( *axisScaleDiv(item->xAxis()),
    00644             *axisScaleDiv(item->yAxis()));
    00645     }
    00646 }
    00647