virtual QwtText label(double fracDays) const { Time timeFromFracDays(fracDays-m_startDateTime.date().dayOfYear()-m_startDateTime.time().totalDays()); DateTime dateTime(m_startDateTime + timeFromFracDays); Date date = dateTime.date(); Time time = dateTime.time(); unsigned day = date.dayOfMonth(); unsigned month = openstudio::month(date.monthOfYear()); int hour = time.hours(); int minutes = time.minutes(); int seconds = time.seconds(); QString s; // zooming double currentDuration = scaleDiv().upperBound() - scaleDiv().lowerBound(); if (currentDuration < 1.0/24.0) // less than an hour { s.sprintf("%02d/%02d %02d:%02d:%02d", month, day, hour, minutes, seconds); } else if (currentDuration < 7.0) // less than a week { s.sprintf("%02d/%02d %02d:%02d", month, day, hour, minutes); } else // week or more { s.sprintf("%02d/%02d", month, day); } return s; }
void QwtPolarPlot::updateScale( int scaleId ) { if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount ) return; ScaleData &d = d_data->scaleData[scaleId]; double minValue = d.minValue; double maxValue = d.maxValue; double stepSize = d.stepSize; if ( scaleId == QwtPolar::ScaleRadius && d.doAutoScale ) { QwtDoubleInterval interval; const QwtPolarItemList& itmList = itemList(); for ( QwtPolarItemIterator it = itmList.begin(); it != itmList.end(); ++it ) { const QwtPolarItem *item = *it; if ( item->testItemAttribute( QwtPolarItem::AutoScale ) ) interval |= item->boundingInterval( scaleId ); } minValue = interval.minValue(); maxValue = interval.maxValue(); d.scaleEngine->autoScale( d.maxMajor, minValue, maxValue, stepSize ); d.scaleDiv.invalidate(); } if ( !d.scaleDiv.isValid() ) { d.scaleDiv = d.scaleEngine->divideScale( minValue, maxValue, d.maxMajor, d.maxMinor, stepSize ); } const QwtDoubleInterval interval = visibleInterval(); const QwtPolarItemList& itmList = itemList(); for ( QwtPolarItemIterator it = itmList.begin(); it != itmList.end(); ++it ) { QwtPolarItem *item = *it; item->updateScaleDiv( *scaleDiv( QwtPolar::Azimuth ), *scaleDiv( QwtPolar::Radius ), interval ); } }
/*! Calculate the minimum length that is needed to draw the scale \param font Font used for painting the labels \return Minimum length that is needed to draw the scale \sa extent() */ int QwtScaleDraw::minLength( const QFont &font ) const { int startDist, endDist; getBorderDistHint( font, startDist, endDist ); const QwtScaleDiv &sd = scaleDiv(); const uint minorCount = sd.ticks( QwtScaleDiv::MinorTick ).count() + sd.ticks( QwtScaleDiv::MediumTick ).count(); const uint majorCount = sd.ticks( QwtScaleDiv::MajorTick ).count(); int lengthForLabels = 0; if ( hasComponent( QwtAbstractScaleDraw::Labels ) ) lengthForLabels = minLabelDist( font ) * majorCount; int lengthForTicks = 0; if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ) { const double pw = qMax( 1, penWidth() ); // penwidth can be zero lengthForTicks = qCeil( ( majorCount + minorCount ) * ( pw + 1.0 ) ); } return startDist + endDist + qMax( lengthForLabels, lengthForTicks ); }
/*! \brief Calculate the bounding rect of the plot area The plot area depends on the zoom parameters. \param canvasRect Rectangle of the canvas \return Rectangle for displaying 100% of the plot */ QRectF QwtPolarPlot::plotRect( const QRectF &canvasRect ) const { const QwtScaleDiv *sd = scaleDiv( QwtPolar::Radius ); const QwtScaleEngine *se = scaleEngine( QwtPolar::Radius ); const int margin = plotMarginHint(); const QRectF cr = canvasRect; const int radius = qMin( cr.width(), cr.height() ) / 2 - margin; QwtScaleMap map; map.setTransformation( se->transformation() ); map.setPaintInterval( 0.0, radius / d_data->zoomFactor ); map.setScaleInterval( sd->lowerBound(), sd->upperBound() ); double v = map.s1(); if ( map.s1() <= map.s2() ) v += d_data->zoomPos.radius(); else v -= d_data->zoomPos.radius(); v = map.transform( v ); const QPointF off = QwtPointPolar( d_data->zoomPos.azimuth(), v ).toPoint(); QPointF center( cr.center().x(), cr.top() + margin + radius ); center -= QPointF( off.x(), -off.y() ); QRectF rect( 0, 0, 2 * map.p2(), 2 * map.p2() ); rect.moveCenter( center ); return rect; }
/*! Calculate the minimum length that is needed to draw the scale \param pen Pen that is used for painting backbone and ticks \param font Font used for painting the labels \sa extent() */ int QwtScaleDraw::minLength(const QPen &pen, const QFont &font) const { int startDist, endDist; getBorderDistHint(font, startDist, endDist); const QwtScaleDiv &sd = scaleDiv(); const uint minorCount = sd.ticks(QwtScaleDiv::MinorTick).count() + sd.ticks(QwtScaleDiv::MediumTick).count(); const uint majorCount = sd.ticks(QwtScaleDiv::MajorTick).count(); int lengthForLabels = 0; if ( hasComponent(QwtAbstractScaleDraw::Labels) ) { if ( majorCount >= 2 ) lengthForLabels = minLabelDist(font) * (majorCount - 1); } int lengthForTicks = 0; if ( hasComponent(QwtAbstractScaleDraw::Ticks) ) { const int pw = qwtMax( 1, pen.width() ); // penwidth can be zero lengthForTicks = 2 * (majorCount + minorCount) * pw; } return startDist + endDist + qwtMax(lengthForLabels, lengthForTicks); }
/*! Build a scale map The azimuth map translates between the scale values and angles from [0.0, 2 * PI[. The radial map translates scale values into the distance from the pole. \param scaleId Scale index \param radius Radius of the plot are in pixels \return Map for the scale on the canvas. With this map pixel coordinates can translated to plot coordinates and vice versa. \sa QwtScaleMap, transform(), invTransform() */ QwtScaleMap QwtPolarPlot::scaleMap( int scaleId, const double radius ) const { if ( scaleId < 0 || scaleId >= QwtPolar::ScaleCount ) return QwtScaleMap(); QwtScaleMap map; map.setTransformation( scaleEngine( scaleId )->transformation() ); const QwtScaleDiv *sd = scaleDiv( scaleId ); #if QWT_VERSION < 0x050200 map.setScaleInterval( sd->lBound(), sd->hBound() ); #else map.setScaleInterval( sd->lowerBound(), sd->upperBound() ); #endif if ( scaleId == QwtPolar::Azimuth ) { map.setPaintXInterval( d_data->azimuthOrigin, d_data->azimuthOrigin + M_2PI ); } else { map.setPaintXInterval( 0.0, radius ); } return map; }
/*! Calculate the extent of the scale The extent is the distance between the baseline to the outermost pixel of the scale draw. radius() + extent() is an upper limit for the radius of the bounding circle. \param font Font used for painting the labels \sa setMinimumExtent(), minimumExtent() \warning The implemented algo is not too smart and calculates only an upper limit, that might be a few pixels too large */ double QwtRoundScaleDraw::extent( const QFont &font ) const { double d = 0.0; if ( hasComponent( QwtAbstractScaleDraw::Labels ) ) { const QwtScaleDiv &sd = scaleDiv(); const QList<double> &ticks = sd.ticks( QwtScaleDiv::MajorTick ); for ( int i = 0; i < ticks.count(); i++ ) { const double value = ticks[i]; if ( !sd.contains( value ) ) continue; const QwtText label = tickLabel( font, value ); if ( label.isEmpty() ) continue; const double tval = scaleMap().transform( value ); if ( ( tval < d_data->startAngle + 360 * 16 ) && ( tval > d_data->startAngle - 360 * 16 ) ) { const double arc = tval / 16.0 / 360.0 * 2 * M_PI; const QSizeF sz = label.textSize( font ); const double off = qMax( sz.width(), sz.height() ); double x = off * qSin( arc ); double y = off * qCos( arc ); const double dist = qSqrt( x * x + y * y ); if ( dist > d ) d = dist; } } } if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ) { d += maxTickLength(); } if ( hasComponent( QwtAbstractScaleDraw::Backbone ) ) { const double pw = qMax( 1, penWidth() ); // penwidth can be zero d += pw; } if ( hasComponent( QwtAbstractScaleDraw::Labels ) && ( hasComponent( QwtAbstractScaleDraw::Ticks ) || hasComponent( QwtAbstractScaleDraw::Backbone ) ) ) { d += spacing(); } d = qMax( d, minimumExtent() ); return d; }
/*! \param font Font \return the maximum width of a label */ int QwtScaleDraw::maxLabelWidth(const QFont &font) const { int maxWidth = 0; const QwtValueList &ticks = scaleDiv().ticks(QwtScaleDiv::MajorTick); for (uint i = 0; i < (uint)ticks.count(); i++) { const double v = ticks[i]; if ( scaleDiv().contains(v) ) { const int w = labelSize(font, ticks[i]).width(); if ( w > maxWidth ) maxWidth = w; } } return maxWidth; }
/*! \param font Font \return the maximum height of a label */ int QwtScaleDraw::maxLabelHeight( const QFont &font ) const { double maxHeight = 0.0; const QList<double> &ticks = scaleDiv().ticks( QwtScaleDiv::MajorTick ); for ( int i = 0; i < ticks.count(); i++ ) { const double v = ticks[i]; if ( scaleDiv().contains( v ) ) { const double h = labelSize( font, ticks[i] ).height(); if ( h > maxHeight ) maxHeight = h; } } return qCeil( maxHeight ); }
/*! \param font Font \return the maximum width of a label */ int QwtScaleDraw::maxLabelWidth( const QFont &font ) const { double maxWidth = 0.0; const QList<double> &ticks = scaleDiv().ticks( QwtScaleDiv::MajorTick ); for ( int i = 0; i < ticks.count(); i++ ) { const double v = ticks[i]; if ( scaleDiv().contains( v ) ) { const double w = labelSize( font, ticks[i] ).width(); if ( w > maxWidth ) maxWidth = w; } } return qCeil( maxWidth ); }
/*! \param font Font \return the maximum height of a label */ int QwtScaleDraw::maxLabelHeight(const QFont &font) const { int maxHeight = 0; const QwtValueList &ticks = scaleDiv().ticks(QwtScaleDiv::MajorTick); for (uint i = 0; i < (uint)ticks.count(); i++) { const double v = ticks[i]; if ( scaleDiv().contains(v) ) { const int h = labelSize(font, ticks[i]).height(); if ( h > maxHeight ) maxHeight = h; } } return maxHeight; }
void ScaleDraw::drawTick(QPainter *p, double value, int len) const { int axis = this->axis(); ScaleEngine *sc_engine = (ScaleEngine *)d_plot->axisScaleEngine(axis); if (sc_engine->hasBreak()){ double dlb = sc_engine->axisBreakLeft(); double drb = sc_engine->axisBreakRight(); if ((dlb < value && drb > value) || ((axis == QwtPlot::yLeft || axis == QwtPlot::xBottom) && value == dlb) || ((axis == QwtPlot::yRight || axis == QwtPlot::xTop) && value == drb) || (sc_engine->testAttribute(QwtScaleEngine::Inverted) && (value == dlb || value == drb))) return; if (d_plot->isPrinting()){ QwtScaleMap scaleMap = map(); double val = scaleMap.transform(value); if (val >= scaleMap.transform(dlb) && val <= scaleMap.transform(drb)) return; } } QwtScaleDiv scDiv = scaleDiv(); QwtValueList majTicks = scDiv.ticks(QwtScaleDiv::MajorTick); if (majTicks.contains(value)){ if (d_majTicks == In || d_majTicks == None) return; switch (d_show_ticks_policy){ case ShowAll: break; case HideBegin: if (majTicks.first() == value) return; break; case HideEnd: if (majTicks.last() == value) return; break; case HideBeginEnd: if (majTicks.first() == value || majTicks.last() == value) return; break; } } QwtValueList medTicks = scDiv.ticks(QwtScaleDiv::MediumTick); if (medTicks.contains(value) && (d_minTicks == In || d_minTicks == None)) return; QwtValueList minTicks = scDiv.ticks(QwtScaleDiv::MinorTick); if (minTicks.contains(value) && (d_minTicks == In || d_minTicks == None)) return; QwtScaleDraw::drawTick(p, value, len); }
virtual void drawLabel( QPainter *painter, double val ) const { const int fh = painter->fontMetrics().height(); if ( length() < fh ) { const QList<double> ticks = scaleDiv().ticks( QwtScaleDiv::MajorTick ); if ( val != ticks.last() ) return; } else if ( length() < 3 * painter->fontMetrics().height() ) { const QList<double> ticks = scaleDiv().ticks( QwtScaleDiv::MajorTick ); if ( val != ticks.last() && val != ticks.first() ) return; } QwtScaleDraw::drawLabel( painter, val ); }
QwtText QwtTextScaleDraw::label(double value) const { const QwtScaleDiv scDiv = scaleDiv(); if (!scDiv.contains (value)) return QwtText(); QwtValueList lst = scDiv.ticks (QwtScaleDiv::MajorTick); lst.pop_front(); lst.pop_back(); int index = lst.indexOf(value); if (index >= 0 && index < (int)labels.count()) return QwtText(labels[index]); else return QwtText(); }
void ScaleDraw::drawTick(QPainter *p, double value, int len) const { QwtScaleDiv scDiv = scaleDiv(); QwtValueList majTicks = scDiv.ticks(QwtScaleDiv::MajorTick); if (majTicks.contains(value) && (d_majTicks == In || d_majTicks == None)) return; QwtValueList medTicks = scDiv.ticks(QwtScaleDiv::MediumTick); if (medTicks.contains(value) && (d_minTicks == In || d_minTicks == None)) return; QwtValueList minTicks = scDiv.ticks(QwtScaleDiv::MinorTick); if (minTicks.contains(value) && (d_minTicks == In || d_minTicks == None)) return; QwtScaleDraw::drawTick(p, value, len); }
/*! \brief Determine the minimum border distance This member function returns the minimum space needed to draw the mark labels at the scale's endpoints. \param font Font \param start Start border distance \param end End border distance */ void QwtScaleDraw::getBorderDistHint(const QFont &font, int &start, int &end ) const { start = 0; end = 0; if ( !hasComponent(QwtAbstractScaleDraw::Labels) ) return; const QwtValueList &ticks = scaleDiv().ticks(QwtScaleDiv::MajorTick); if ( ticks.count() == 0 ) return; QRect lr = labelRect(font, ticks[0]); // find the distance between tick and border int off = qwtAbs(map().transform(ticks[0]) - qRound(map().p1())); if ( orientation() == Qt::Vertical ) end = lr.bottom() + 1 - off; else start = -lr.left() - off; const int lastTick = ticks.count() - 1; lr = labelRect(font, ticks[lastTick]); // find the distance between tick and border off = qwtAbs(map().transform(ticks[lastTick]) - qRound(map().p2())); if ( orientation() == Qt::Vertical ) start = -lr.top() - off; else end = lr.right() + 1 - off; // if the distance between tick and border is larger // than half of the label width/height, we set to 0 if ( start < 0 ) start = 0; if ( end < 0 ) end = 0; }
AnalogGraph::AnalogGraph(QWidget *parent) : QwtPlot(parent), numberOfAnalogChannels_ (6) { plotLayout()->setAlignCanvasToScales(true); QwtText textLeft("Analog value"); QwtText textBottom("Analog channel"); QFont font; font.setPointSize(12); font.setFamily("Arial"); textLeft.setFont(font); textBottom.setFont(font); setAxisTitle(QwtPlot::yLeft, textLeft); setAxisTitle(QwtPlot::xBottom, textBottom); setAxisScale(QwtPlot::xBottom, 0, numberOfAnalogChannels_, 1); setAxisScale(QwtPlot::yLeft, 0, 1024, 200); QList<double> ticks[QwtScaleDiv::NTickTypes]; for (int i = 0; i <= numberOfAnalogChannels_; i++) { ticks[QwtScaleDiv::MajorTick] << i; } QwtScaleDiv scaleDiv( ticks[QwtScaleDiv::MajorTick].first(), ticks[QwtScaleDiv::MajorTick].last(), ticks ); setAxisScaleDiv(QwtPlot::xBottom, scaleDiv); populate(); replot(); // creating the legend items analogValuesLoader_ = new AnalogValuesLoader (numberOfAnalogChannels_); qRegisterMetaType < MyVector >("MyVector"); connect(analogValuesLoader_, SIGNAL(valuesChanged(const MyVector)), SLOT(redrawAnalogGraph(const MyVector))); analogValuesLoader_->start(); }
QwtScaleDiv Plot::yearScaleDiv() const { const int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; QList<double> ticks[QwtScaleDiv::NTickTypes]; QList<double> &mediumTicks = ticks[QwtScaleDiv::MediumTick]; mediumTicks += 0.0; for ( uint i = 0; i < sizeof( days ) / sizeof( days[0] ); i++ ) mediumTicks += mediumTicks.last() + days[i]; QList<double> &minorTicks = ticks[QwtScaleDiv::MinorTick]; for ( int i = 1; i <= 365; i += 7 ) minorTicks += i; QList<double> &majorTicks = ticks[QwtScaleDiv::MajorTick]; for ( int i = 0; i < 12; i++ ) majorTicks += i * 30 + 15; QwtScaleDiv scaleDiv( mediumTicks.first(), mediumTicks.last() + 1, ticks ); return scaleDiv; }
/*! \brief Calculate the bounding rect of the plot area The plot area depends on the zoom parameters. \param canvasRect Rectangle of the canvas \return Rectangle for displaying 100% of the plot */ QwtDoubleRect QwtPolarPlot::plotRect( const QRect &canvasRect ) const { const QwtScaleDiv *sd = scaleDiv( QwtPolar::Radius ); const QwtScaleEngine *se = scaleEngine( QwtPolar::Radius ); const int margin = plotMarginHint(); const QRect cr = canvasRect; const int radius = qwtMin( cr.width(), cr.height() ) / 2 - margin; QwtScaleMap map; map.setTransformation( se->transformation() ); map.setPaintXInterval( 0.0, radius / d_data->zoomFactor ); #if QWT_VERSION < 0x050200 map.setScaleInterval( sd->lBound(), sd->hBound() ); #else map.setScaleInterval( sd->lowerBound(), sd->upperBound() ); #endif double v = map.s1(); if ( map.s1() <= map.s2() ) v += d_data->zoomPos.radius(); else v -= d_data->zoomPos.radius(); v = map.xTransform( v ); const QwtDoublePoint off = QwtPolarPoint( d_data->zoomPos.azimuth(), v ).toPoint(); QwtDoublePoint center( cr.center().x(), cr.top() + margin + radius ); center -= QwtDoublePoint( off.x(), -off.y() ); QwtDoubleRect rect( 0, 0, 2 * map.p2(), 2 * map.p2() ); rect.moveCenter( center ); return rect; }
int QwtScaleDraw::minLabelDist( const QFont &font ) const { if ( !hasComponent( QwtAbstractScaleDraw::Labels ) ) return 0; const QList<double> &ticks = scaleDiv().ticks( QwtScaleDiv::MajorTick ); if ( ticks.isEmpty() ) return 0; const QFontMetrics fm( font ); const bool vertical = ( orientation() == Qt::Vertical ); QRectF bRect1; QRectF bRect2 = labelRect( font, ticks[0] ); if ( vertical ) { bRect2.setRect( -bRect2.bottom(), 0.0, bRect2.height(), bRect2.width() ); } double maxDist = 0.0; for ( int i = 1; i < ticks.count(); i++ ) { bRect1 = bRect2; bRect2 = labelRect( font, ticks[i] ); if ( vertical ) { bRect2.setRect( -bRect2.bottom(), 0.0, bRect2.height(), bRect2.width() ); } double dist = fm.leading(); // space between the labels if ( bRect1.right() > 0 ) dist += bRect1.right(); if ( bRect2.left() < 0 ) dist += -bRect2.left(); if ( dist > maxDist ) maxDist = dist; } double angle = qwtRadians( labelRotation() ); if ( vertical ) angle += M_PI / 2; const double sinA = qFastSin( angle ); // qreal -> double if ( qFuzzyCompare( sinA + 1.0, 1.0 ) ) return qCeil( maxDist ); const int fmHeight = fm.ascent() - 2; // The distance we need until there is // the height of the label font. This height is needed // for the neighbored label. double labelDist = fmHeight / qFastSin( angle ) * qFastCos( angle ); if ( labelDist < 0 ) labelDist = -labelDist; // For text orientations close to the scale orientation if ( labelDist > maxDist ) labelDist = maxDist; // For text orientations close to the opposite of the // scale orientation if ( labelDist < fmHeight ) labelDist = fmHeight; return qCeil( labelDist ); }
/*! Redraw the liquid in thermometer pipe. \param painter Painter \param pipeRect Bounding rectangle of the pipe without borders */ void QwtThermo::drawLiquid( QPainter *painter, const QRect &pipeRect ) const { painter->save(); painter->setClipRect( pipeRect, Qt::IntersectClip ); painter->setPen( Qt::NoPen ); const QwtScaleMap scaleMap = scaleDraw()->scaleMap(); QRect liquidRect = fillRect( pipeRect ); if ( d_data->colorMap != NULL ) { const QwtInterval interval = scaleDiv().interval().normalized(); // Because the positions of the ticks are rounded // we calculate the colors for the rounded tick values QVector<double> values = qwtTickList( scaleDraw()->scaleDiv() ); if ( scaleMap.isInverting() ) qSort( values.begin(), values.end(), qGreater<double>() ); else qSort( values.begin(), values.end(), qLess<double>() ); int from; if ( !values.isEmpty() ) { from = qRound( scaleMap.transform( values[0] ) ); qwtDrawLine( painter, from, d_data->colorMap->color( interval, values[0] ), pipeRect, liquidRect, d_data->orientation ); } for ( int i = 1; i < values.size(); i++ ) { const int to = qRound( scaleMap.transform( values[i] ) ); for ( int pos = from + 1; pos < to; pos++ ) { const double v = scaleMap.invTransform( pos ); qwtDrawLine( painter, pos, d_data->colorMap->color( interval, v ), pipeRect, liquidRect, d_data->orientation ); } qwtDrawLine( painter, to, d_data->colorMap->color( interval, values[i] ), pipeRect, liquidRect, d_data->orientation ); from = to; } } else { if ( !liquidRect.isEmpty() && d_data->alarmEnabled ) { const QRect r = alarmRect( liquidRect ); if ( !r.isEmpty() ) { painter->fillRect( r, palette().brush( QPalette::Highlight ) ); liquidRect = QRegion( liquidRect ).subtracted( r ).boundingRect(); } } painter->fillRect( liquidRect, palette().brush( QPalette::ButtonText ) ); } painter->restore(); }
int QwtScaleDraw::minLabelDist(const QFont &font) const { if ( !hasComponent(QwtAbstractScaleDraw::Labels) ) return 0; const QwtValueList &ticks = scaleDiv().ticks(QwtScaleDiv::MajorTick); if (ticks.count() == 0) return 0; const QFontMetrics fm(font); const bool vertical = (orientation() == Qt::Vertical); QRect bRect1; QRect bRect2 = labelRect(font, ticks[0]); if ( vertical ) { bRect2.setRect(-bRect2.bottom(), 0, bRect2.height(), bRect2.width()); } int maxDist = 0; for (uint i = 1; i < (uint)ticks.count(); i++ ) { bRect1 = bRect2; bRect2 = labelRect(font, ticks[i]); if ( vertical ) { bRect2.setRect(-bRect2.bottom(), 0, bRect2.height(), bRect2.width()); } int dist = fm.leading(); // space between the labels if ( bRect1.right() > 0 ) dist += bRect1.right(); if ( bRect2.left() < 0 ) dist += -bRect2.left(); if ( dist > maxDist ) maxDist = dist; } double angle = labelRotation() / 180.0 * M_PI; if ( vertical ) angle += M_PI / 2; if ( sin(angle) == 0.0 ) return maxDist; const int fmHeight = fm.ascent() - 2; // The distance we need until there is // the height of the label font. This height is needed // for the neighbour labal. int labelDist = (int)(fmHeight / sin(angle) * cos(angle)); if ( labelDist < 0 ) labelDist = -labelDist; // The cast above floored labelDist. We want to ceil. labelDist++; // For text orientations close to the scale orientation if ( labelDist > maxDist ) labelDist = maxDist; // For text orientations close to the opposite of the // scale orientation if ( labelDist < fmHeight ) labelDist = fmHeight; return labelDist; }
/*! Calculate the bounding interval of the radial scale that is visible on the canvas. */ QwtDoubleInterval QwtPolarPlot::visibleInterval() const { const QwtScaleDiv *sd = scaleDiv( QwtPolar::Radius ); const QwtDoubleRect cRect = canvas()->contentsRect(); const QwtDoubleRect pRect = plotRect( cRect.toRect() ); if ( cRect.contains( pRect.toRect() ) || !cRect.intersects( pRect ) ) { #if QWT_VERSION < 0x050200 return QwtDoubleInterval( sd->lBound(), sd->hBound() ); #else return QwtDoubleInterval( sd->lowerBound(), sd->upperBound() ); #endif } const QwtDoublePoint pole = pRect.center(); const QwtDoubleRect scaleRect = pRect & cRect; const QwtScaleMap map = scaleMap( QwtPolar::Radius ); double dmin = 0.0; double dmax = 0.0; if ( scaleRect.contains( pole ) ) { dmin = 0.0; QwtDoublePoint corners[4]; corners[0] = scaleRect.bottomRight(); corners[1] = scaleRect.topRight(); corners[2] = scaleRect.topLeft(); corners[3] = scaleRect.bottomLeft(); dmax = 0.0; for ( int i = 0; i < 4; i++ ) { const double dist = qwtDistance( pole, corners[i] ); if ( dist > dmax ) dmax = dist; } } else { if ( pole.x() < scaleRect.left() ) { if ( pole.y() < scaleRect.top() ) { dmin = qwtDistance( pole, scaleRect.topLeft() ); dmax = qwtDistance( pole, scaleRect.bottomRight() ); } else if ( pole.y() > scaleRect.bottom() ) { dmin = qwtDistance( pole, scaleRect.bottomLeft() ); dmax = qwtDistance( pole, scaleRect.topRight() ); } else { dmin = scaleRect.left() - pole.x(); dmax = qwtMax( qwtDistance( pole, scaleRect.bottomRight() ), qwtDistance( pole, scaleRect.topRight() ) ); } } else if ( pole.x() > scaleRect.right() ) { if ( pole.y() < scaleRect.top() ) { dmin = qwtDistance( pole, scaleRect.topRight() ); dmax = qwtDistance( pole, scaleRect.bottomLeft() ); } else if ( pole.y() > scaleRect.bottom() ) { dmin = qwtDistance( pole, scaleRect.bottomRight() ); dmax = qwtDistance( pole, scaleRect.topLeft() ); } else { dmin = pole.x() - scaleRect.right(); dmax = qwtMax( qwtDistance( pole, scaleRect.bottomLeft() ), qwtDistance( pole, scaleRect.topLeft() ) ); } } else if ( pole.y() < scaleRect.top() ) { dmin = scaleRect.top() - pole.y(); dmax = qwtMax( qwtDistance( pole, scaleRect.bottomLeft() ), qwtDistance( pole, scaleRect.bottomRight() ) ); } else if ( pole.y() > scaleRect.bottom() ) { dmin = pole.y() - scaleRect.bottom(); dmax = qwtMax( qwtDistance( pole, scaleRect.topLeft() ), qwtDistance( pole, scaleRect.topRight() ) ); } } const double radius = pRect.width() / 2.0; if ( dmax > radius ) dmax = radius; QwtDoubleInterval interval; interval.setMinValue( map.invTransform( dmin ) ); interval.setMaxValue( map.invTransform( dmax ) ); return interval; }
QwtText ScaleDraw::label(double value) const { switch (d_type){ case Numeric: { QLocale locale = ((Graph *)d_plot->parent())->multiLayer()->locale(); if (d_numeric_format == Superscripts){ QString txt = locale.toString(transformValue(value), 'e', d_prec); QStringList list = txt.split("e", QString::SkipEmptyParts); if (list[0].toDouble() == 0.0) return QString("0"); QString s = list[1]; int l = s.length(); QChar sign = s[0]; s.remove (sign); while (l>1 && s.startsWith ("0", false)){ s.remove ( 0, 1 ); l = s.length(); } if (sign == '-') s.prepend(sign); if (list[0] == "1") return QwtText("10<sup>" + s + "</sup>"); else return QwtText(list[0] + "x10<sup>" + s + "</sup>"); } else return QwtText(locale.toString(transformValue(value), d_fmt, d_prec)); break; } case Day: { int val = static_cast<int>(transformValue(value))%7; if (val < 0) val = 7 - abs(val); else if (val == 0) val = 7; QString day; switch(d_name_format){ case ShortName: day = QDate::shortDayName (val); break; case LongName: day = QDate::longDayName (val); break; case Initial: day = (QDate::shortDayName (val)).left(1); break; } return QwtText(day); break; } case Month: { int val = static_cast<int>(transformValue(value))%12; if (val < 0) val = 12 - abs(val); else if (val == 0) val = 12; QString day; switch(d_name_format){ case ShortName: day = QDate::shortMonthName (val); break; case LongName: day = QDate::longMonthName (val); break; case Initial: day = (QDate::shortMonthName (val)).left(1); break; } return QwtText(day); break; } case Time: return QwtText(d_date_time_origin.time().addMSecs((int)value).toString(d_format_info)); break; case Date: return QwtText(d_date_time_origin.addSecs((int)value).toString(d_format_info)); break; case ColHeader: case Text: { const QwtScaleDiv scDiv = scaleDiv(); if (!scDiv.contains (value)) return QwtText(); QwtValueList ticks = scDiv.ticks (QwtScaleDiv::MajorTick); double break_offset = 0; ScaleEngine *se = (ScaleEngine *)d_plot->axisScaleEngine(axis()); /*QwtScaleEngine *qwtsc_engine=d_plot->axisScaleEngine(axis()); ScaleEngine *se =dynamic_cast<ScaleEngine*>(qwtsc_engine); if(se!=NULL) {*/ bool inverted = se->testAttribute(QwtScaleEngine::Inverted); if(se->hasBreak()){ double lb = se->axisBreakLeft(); double rb = se->axisBreakRight(); if(inverted){ if (value <= lb){ int n_ticks = (int)ticks.count() - 1; double val0 = ticks[0]; double val1 = ticks[n_ticks]; for (int i = 1; i < n_ticks; i++){ double aux = ticks[i]; if(aux >= rb && val0 > aux){ val0 = aux; continue; } if(aux <= lb && val1 < aux) val1 = aux; } break_offset = fabs(val1 - val0); } } else { if (value >= rb){ double val0 = ticks[0]; for (int i = 1; i < (int)ticks.count(); i++){ double val = ticks[i]; if(val0 <= lb && val >= rb){ break_offset = fabs(val - val0); break; } val0 = val; } } } } double step = ticks[1] - ticks[0]; int index = static_cast<int>(ticks[0] + step*ticks.indexOf(value) - 1); int offset = abs((int)floor(break_offset/step)); if (offset) offset--; if (step > 0) index += offset; else index -= offset; if (index >= 0 && index < (int)d_text_labels.count()) return QwtText(d_text_labels[index]); else return QwtText(); //} break; } } return QwtText(); }
/*! \brief Determine the minimum border distance This member function returns the minimum space needed to draw the mark labels at the scale's endpoints. \param font Font \param start Start border distance \param end End border distance */ void QwtScaleDraw::getBorderDistHint( const QFont &font, int &start, int &end ) const { start = 0; end = 0; if ( !hasComponent( QwtAbstractScaleDraw::Labels ) ) return; const QList<double> &ticks = scaleDiv().ticks( QwtScaleDiv::MajorTick ); if ( ticks.count() == 0 ) return; // Find the ticks, that are mapped to the borders. // minTick is the tick, that is mapped to the top/left-most position // in widget coordinates. double minTick = ticks[0]; double minPos = map().transform( minTick ); double maxTick = minTick; double maxPos = minPos; for ( uint i = 1; i < ( uint )ticks.count(); i++ ) { const double tickPos = map().transform( ticks[i] ); if ( tickPos < minPos ) { minTick = ticks[i]; minPos = tickPos; } if ( tickPos > map().transform( maxTick ) ) { maxTick = ticks[i]; maxPos = tickPos; } } double e = 0.0; double s = 0.0; if ( orientation() == Qt::Vertical ) { s = -labelRect( font, minTick ).top(); s -= qAbs( minPos - qRound( map().p2() ) ); e = labelRect( font, maxTick ).bottom(); e -= qAbs( maxPos - map().p1() ); } else { s = -labelRect( font, minTick ).left(); s -= qAbs( minPos - map().p1() ); e = labelRect( font, maxTick ).right(); e -= qAbs( maxPos - map().p2() ); } if ( s < 0.0 ) s = 0.0; if ( e < 0.0 ) e = 0.0; start = qCeil( s ); end = qCeil( e ); }
QString ScaleDraw::labelString(double value) const { switch (d_type){ case Numeric: { QLocale locale = d_plot->locale(); if (d_plot->parent()) locale = d_plot->multiLayer()->locale(); if ((d_numeric_format == Superscripts)||(d_numeric_format == SuperscriptsGER)){ QString txt = locale.toString(transformValue(value), 'e', d_prec); QStringList list = txt.split("e", QString::SkipEmptyParts); if (list.isEmpty()) return QString::null; if (list[0].toDouble() == 0.0) return "0"; QString s = list[1]; int l = s.length(); QChar sign = s[0]; s.remove (sign); while (l>1 && s.startsWith ("0", false)){ s.remove ( 0, 1 ); l = s.length(); } if (sign == '-') s.prepend(sign); if (list[0] == "1") return "10<sup>" + s + "</sup>"; else { if (d_numeric_format == SuperscriptsGER) return list[0] + "·10<sup>" + s + "</sup>"; else return list[0] + QString(QChar(0x00D7)) + "10<sup>" + s + "</sup>"; } } else if (d_numeric_format == Engineering){ QString eng_suff; double new_value = value; if(fabs(new_value) >= 1e18){ eng_suff = 'E'; new_value /= 1e18; } else if(fabs(new_value) >= 1e15){ eng_suff = 'P'; new_value /= 1e15; } else if(fabs(new_value) >= 1e12){ eng_suff = 'T'; new_value /= 1e12; } else if(fabs(new_value) >= 1e9){ eng_suff = 'G'; new_value /= 1e9; } else if(fabs(new_value) >= 1e6){ eng_suff = 'M'; new_value /= 1e6; } else if(fabs(new_value) >= 1e3){ eng_suff = 'k'; new_value /= 1e3; } else if(fabs(new_value) >= 1){ eng_suff = ""; new_value /= 1.0; } else if(fabs(new_value) >= 1e-3){ eng_suff = 'm'; new_value /= 1e-3; } else if(fabs(new_value) >= 1e-6){ eng_suff = 'µ'; new_value /= 1e-6; } else if(fabs(new_value) >= 1e-9){ eng_suff = 'n'; new_value /= 1e-9; } else if(fabs(new_value) >= 1e-12){ eng_suff = 'p'; new_value /= 1e-12; } else if(fabs(new_value) >= 1e-15){ eng_suff = 'f'; new_value /= 1e-15; } else { eng_suff = 'a'; new_value /= 1e-18; } QString txt = locale.toString((new_value), 'f', d_prec); if(txt.contains(QRegExp("^0[\\.,]?0*$"))) return "0"; return txt + eng_suff; } else return locale.toString(transformValue(value), d_fmt, d_prec); break; } case Day: { int val = int(transformValue(value))%7; if (val < 0) val = 7 - abs(val); else if (val == 0) val = 7; QString day; switch(d_name_format){ case ShortName: day = QDate::shortDayName (val); break; case LongName: day = QDate::longDayName (val); break; case Initial: day = (QDate::shortDayName (val)).left(1); break; } return day; break; } case Month: { int val = int(transformValue(value))%12; if (val < 0) val = 12 - abs(val); else if (val == 0) val = 12; QString day; switch(d_name_format){ case ShortName: day = QDate::shortMonthName (val); break; case LongName: day = QDate::longMonthName (val); break; case Initial: day = (QDate::shortMonthName (val)).left(1); break; } return day; break; } case Time: { QTime time = Table::dateTime(value).time(); if (d_format_info == "M") return QString::number(60*time.hour() + time.minute()); else if (d_format_info == "S") return QString::number(3600*time.hour() + 60*time.minute() + time.second()); return time.toString(d_format_info); break; } case Date: return Table::dateTime(value).toString(d_format_info); break; case ColHeader: case Text: { const QwtScaleDiv scDiv = scaleDiv(); if (!scDiv.contains (value) || floor(value) < value) return QString::null; QwtValueList ticks = scDiv.ticks (QwtScaleDiv::MajorTick); double break_offset = 0; ScaleEngine *se = (ScaleEngine *)d_plot->axisScaleEngine(axis()); bool inverted = se->testAttribute(QwtScaleEngine::Inverted); if(se->hasBreak()){ double lb = se->axisBreakLeft(); double rb = se->axisBreakRight(); if(inverted){ if (value <= lb){ int n_ticks = (int)ticks.count() - 1; double val0 = ticks[0]; double val1 = ticks[n_ticks]; for (int i = 1; i < n_ticks; i++){ double aux = ticks[i]; if(aux >= rb && val0 > aux){ val0 = aux; continue; } if(aux <= lb && val1 < aux) val1 = aux; } break_offset = fabs(val1 - val0); } } else { if (value >= rb){ double val0 = ticks[0]; for (int i = 1; i < (int)ticks.count(); i++){ double val = ticks[i]; if(val0 <= lb && val >= rb){ break_offset = fabs(val - val0); break; } val0 = val; } } } } if (ticks.size() < 2) return QString::null; double step = ticks[1] - ticks[0]; int index = int(ticks[0] + step*ticks.indexOf(value) - 1); int offset = abs((int)floor(break_offset/step)); if (offset) offset--; if (step > 0) index += offset; else index -= offset; if (index >= 0 && index < (int)d_text_labels.count()) return d_text_labels[index]; else return QString::null; break; } } return QString::null; }
void ScaleDraw::drawLabel(QPainter *painter, double value) const { if (!d_plot) return; ScaleEngine *sc_engine = (ScaleEngine *)d_plot->axisScaleEngine(axis()); if (sc_engine->hasBreak() && sc_engine->axisBreakLeft() <= value && sc_engine->axisBreakRight() > value) return; QwtValueList majTicks = scaleDiv().ticks(QwtScaleDiv::MajorTick); if (majTicks.contains(value)){ switch (d_show_ticks_policy){ case ShowAll: break; case HideBegin: if (majTicks.first() == value) return; break; case HideEnd: if (majTicks.last() == value) return; break; case HideBeginEnd: if (majTicks.first() == value || majTicks.last() == value) return; break; } } QwtText lbl = tickLabel(painter->font(), value); if ( lbl.isEmpty() ) return; QPoint pos = labelPosition(value); QSize labelSize = lbl.textSize(painter->font()); if ( labelSize.height() % 2 ) labelSize.setHeight(labelSize.height() + 1); const QwtMetricsMap metricsMap = QwtPainter::metricsMap(); QwtPainter::resetMetricsMap(); labelSize = metricsMap.layoutToDevice(labelSize); pos = metricsMap.layoutToDevice(pos); painter->save(); painter->setMatrix(labelMatrix( pos, labelSize), true); if (d_selected) lbl.setBackgroundPen(QPen(Qt::blue)); else lbl.setBackgroundPen(QPen(Qt::NoPen)); lbl.setRenderFlags(labelAlignment()); lbl.draw (painter, QRect(QPoint(0, 0), labelSize) ); QwtPainter::setMetricsMap(metricsMap); // restore metrics map painter->restore(); }
void ScaleDraw::drawTick(QPainter *p, double value, int len) const { ScaleEngine *sc_engine = (ScaleEngine *)d_plot->axisScaleEngine(axis()); /*QwtScaleEngine *qwtsc_engine=d_plot->axisScaleEngine(axis()); ScaleEngine *sc_engine =dynamic_cast< ScaleEngine*>(qwtsc_engine); if(sc_engine!=NULL) {*/ if (sc_engine->hasBreak()){ int align = alignment(); bool invertedScale = sc_engine->testAttribute(QwtScaleEngine::Inverted); if (align == BottomScale || align == LeftScale){ if (invertedScale && sc_engine->axisBreakRight() == value) return; if (!invertedScale && sc_engine->axisBreakLeft() == value) return; } else { if (!invertedScale && sc_engine->axisBreakRight() == value) return; if (invertedScale && sc_engine->axisBreakLeft() == value) return; } } //} QwtScaleDiv scDiv = scaleDiv(); QwtValueList majTicks = scDiv.ticks(QwtScaleDiv::MajorTick); if (majTicks.contains(value) && (d_majTicks == In || d_majTicks == None)) return; QwtValueList medTicks = scDiv.ticks(QwtScaleDiv::MediumTick); if (medTicks.contains(value) && (d_minTicks == In || d_minTicks == None)) return; QwtValueList minTicks = scDiv.ticks(QwtScaleDiv::MinorTick); if (minTicks.contains(value) && (d_minTicks == In || d_minTicks == None)) return; QwtScaleDraw::drawTick(p, value, len); }