/*! \brief No docs Description \param x ??? \param align \todo Documentation */ void QwtDoubleRange::setNewValue(double x, bool align) { double vmin,vmax; d_prevValue = d_value; vmin = qwtMin(d_minValue, d_maxValue); vmax = qwtMax(d_minValue, d_maxValue); // // Range check // if (x < vmin) { if ((d_periodic) && (vmin != vmax)) d_value = x + ::ceil( (vmin - x) / (vmax - vmin ) ) * (vmax - vmin); else d_value = vmin; } else if (x > vmax) { if ((d_periodic) && (vmin != vmax)) d_value = x - ::ceil( ( x - vmax) / (vmax - vmin )) * (vmax - vmin); else d_value = vmax; } else d_value = x; d_exactPrevValue = d_exactValue; d_exactValue = d_value; // align to grid if (align) { if (d_step != 0.0) { d_value = d_minValue + qwtRound((d_value - d_minValue) / d_step) * d_step; } else d_value = d_minValue; // correct rounding error at the border if (fabs(d_value - d_maxValue) < MinEps * qwtAbs(d_step)) d_value = d_maxValue; // correct rounding error if value = 0 if (::fabs(d_value) < MinEps * qwtAbs(d_step)) d_value = 0.0; } if (!d_isValid || d_prevValue != d_value) { d_isValid = true; valueChange(); } }
int ScalePicker::maxLabelWidth(const QwtScale *scale) const { QFontMetrics fm(scale->font()); const QwtScaleDraw * scaleDraw=scale->scaleDraw (); const QwtScaleDiv scaleDiv=scaleDraw->scaleDiv(); const double step_eps = 1.0e-6; int maxWidth = 0; for (uint i = 0; i < scaleDiv.majCnt(); i++) { double val = scaleDiv.majMark(i); // correct rounding errors if val = 0 if ((!scaleDiv.logScale()) && (qwtAbs(val) < step_eps * qwtAbs(scaleDiv.majStep()))) { val = 0.0; } const int w = fm.boundingRect(scaleDraw->label(val)).width(); if ( w > maxWidth ) maxWidth = w; } return maxWidth; }
QList<QwtDoublePoint> QwtCircleClipper::cuttingPoints( Edge edge, const QwtDoublePoint &pos, double radius) const { QList<QwtDoublePoint> points; if ( edge == Left || edge == Right ) { const double x = (edge == Left) ? left() : right(); if ( qwtAbs(pos.x() - x) < radius ) { const double off = ::sqrt(qwtSqr(radius) - qwtSqr(pos.x() - x)); const double y1 = pos.y() + off; if ( y1 >= top() && y1 <= bottom() ) points += QwtDoublePoint(x, y1); const double y2 = pos.y() - off; if ( y2 >= top() && y2 <= bottom() ) points += QwtDoublePoint(x, y2); } } else { const double y = (edge == Top) ? top() : bottom(); if ( qwtAbs(pos.y() - y) < radius ) { const double off = ::sqrt(qwtSqr(radius) - qwtSqr(pos.y() - y)); const double x1 = pos.x() + off; if ( x1 >= left() && x1 <= right() ) points += QwtDoublePoint(x1, y); const double x2 = pos.x() - off; if ( x2 >= left() && x2 <= right() ) points += QwtDoublePoint(x2, y); } } return points; }
bool QwtPlotPicker::end(bool ok) { ok = QwtPicker::end(ok); if ( !ok ) return false; QwtPlot *plot = QwtPlotPicker::plot(); if ( !plot ) return false; const QwtPolygon &pa = selection(); if ( pa.count() == 0 ) return false; if ( selectionFlags() & PointSelection ) { const QwtDoublePoint pos = invTransform(pa[0]); emit selected(pos); } else if ( (selectionFlags() & RectSelection) && pa.count() >= 2 ) { QPoint p1 = pa[0]; QPoint p2 = pa[int(pa.count() - 1)]; if ( selectionFlags() & CenterToCorner ) { p1.setX(p1.x() - (p2.x() - p1.x())); p1.setY(p1.y() - (p2.y() - p1.y())); } else if ( selectionFlags() & CenterToRadius ) { const int radius = qwtMax(qwtAbs(p2.x() - p1.x()), qwtAbs(p2.y() - p1.y())); p2.setX(p1.x() + radius); p2.setY(p1.y() + radius); p1.setX(p1.x() - radius); p1.setY(p1.y() - radius); } emit selected(invTransform(QRect(p1, p2)).normalized()); } else { QwtArray<QwtDoublePoint> dpa(pa.count()); for ( int i = 0; i < int(pa.count()); i++ ) dpa[i] = invTransform(pa[i]); emit selected(dpa); } return true; }
/*! Zoom in/out the axes scales \param factor A value < 1.0 zooms in, a value > 1.0 zooms out. */ void QwtPlotMagnifier::rescale(double factor) { factor = qwtAbs(factor); if ( factor == 1.0 || factor == 0.0 ) return; bool doReplot = false; QwtPlot* plt = plot(); const bool autoReplot = plt->autoReplot(); plt->setAutoReplot(false); for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { const QwtScaleDiv *scaleDiv = plt->axisScaleDiv(axisId); if ( isAxisEnabled(axisId) && scaleDiv->isValid() ) { const double center = scaleDiv->lowerBound() + scaleDiv->range() / 2; const double width_2 = scaleDiv->range() / 2 * factor; plt->setAxisScale(axisId, center - width_2, center + width_2); doReplot = true; } } plt->setAutoReplot(autoReplot); if ( doReplot ) plt->replot(); }
/*! Zoom in/out the zoomed area \param factor A value < 1.0 zooms in, a value > 1.0 zooms out. */ void QwtPolarMagnifier::rescale( double factor ) { factor = qwtAbs( factor ); if ( factor == 1.0 || factor == 0.0 ) return; QwtPolarPlot* plt = plot(); if ( plt == NULL ) return; QwtPolarPoint zoomPos; double newZoomFactor = plt->zoomFactor() * factor; if ( newZoomFactor >= 1.0 ) newZoomFactor = 1.0; else zoomPos = plt->zoomPos(); const bool autoReplot = plt->autoReplot(); plt->setAutoReplot( false ); plt->zoom( zoomPos, newZoomFactor ); plt->setAutoReplot( autoReplot ); plt->replot(); }
/*! \brief Calculate a scale division \param x1 First interval limit \param x2 Second interval limit \param maxMajSteps Maximum for the number of major steps \param maxMinSteps Maximum number of minor steps \param stepSize Step size. If stepSize == 0, the scaleEngine calculates one. \sa QwtScaleEngine::stepSize(), QwtScaleEngine::subDivide() */ QwtScaleDiv QwtLinearScaleEngine::divideScale(double x1, double x2, int maxMajSteps, int maxMinSteps, double stepSize) const { QwtDoubleInterval interval = QwtDoubleInterval(x1, x2).normalized(); if (interval.width() <= 0 ) return QwtScaleDiv(); stepSize = qwtAbs(stepSize); if ( stepSize == 0.0 ) { if ( maxMajSteps < 1 ) maxMajSteps = 1; stepSize = divideInterval(interval.width(), maxMajSteps); } QwtScaleDiv scaleDiv; if ( stepSize != 0.0 ) { QwtValueList ticks[QwtScaleDiv::NTickTypes]; buildTicks(interval, stepSize, maxMinSteps, ticks); scaleDiv = QwtScaleDiv(interval, ticks); } if ( x1 > x2 ) scaleDiv.invert(); return scaleDiv; }
void QwtPlotMagnifier::widgetWheelEvent(QWheelEvent *we) { #if QT_VERSION < 0x040000 if ( (we->state() & Qt::KeyButtonMask) != (d_data->wheelButtonState & Qt::KeyButtonMask) ) #else if ( (we->modifiers() & Qt::KeyboardModifierMask) != (int)(d_data->wheelButtonState & Qt::KeyboardModifierMask) ) #endif { return; } if ( d_data->wheelFactor != 0.0 ) { /* A positive delta indicates that the wheel was rotated forwards away from the user; a negative value indicates that the wheel was rotated backwards toward the user. Most mouse types work in steps of 15 degrees, in which case the delta value is a multiple of 120 (== 15 * 8). */ double f = ::pow(d_data->wheelFactor, qwtAbs(we->delta() / 120)); if ( we->delta() > 0 ) f = 1 / f; rescale(f); } }
/*! \brief Specify range and step size \param vmin lower boundary of the interval \param vmax higher boundary of the interval \param vstep step width \param pageSize page size in steps \warning \li A change of the range changes the value if it lies outside the new range. The current value will *not* be adjusted to the new step raster. \li vmax < vmin is allowed. \li If the step size is left out or set to zero, it will be set to 1/100 of the interval length. \li If the step size has an absurd value, it will be corrected to a better one. */ void QwtDoubleRange::setRange(double vmin, double vmax, double vstep, int pageSize) { bool rchg = ((d_maxValue != vmax) || (d_minValue != vmin)); if (rchg) { d_minValue = vmin; d_maxValue = vmax; } // // look if the step width has an acceptable // value or otherwise change it. // setStep(vstep); // // limit page size // d_pageSize = qwtLim(pageSize,0, int(qwtAbs((d_maxValue - d_minValue) / d_step))); // // If the value lies out of the range, it // will be changed. Note that it will not be adjusted to // the new step width. setNewValue(d_value, false); // call notifier after the step width has been // adjusted. if (rchg) rangeChange(); }
void QwtLinearColorMap::ColorStops::insert(double pos, const QColor &color) { // Lookups need to be very fast, insertions are not so important. // Anyway, a balanced tree is what we need here. TODO ... if ( pos < 0.0 || pos > 1.0 ) return; int index; if ( _stops.size() == 0 ) { index = 0; #if QT_VERSION < 0x040000 _stops.resize(1, QGArray::SpeedOptim); #else _stops.resize(1); #endif } else { index = findUpper(pos); if ( index == (int)_stops.size() || qwtAbs(_stops[index].pos - pos) >= 0.001 ) { #if QT_VERSION < 0x040000 _stops.resize(_stops.size() + 1, QGArray::SpeedOptim); #else _stops.resize(_stops.size() + 1); #endif for ( int i = _stops.size() - 1; i > index; i-- ) _stops[i] = _stops[i-1]; } } _stops[index] = ColorStop(pos, color); }
void QwtLinearScaleEngine::buildMinorTicks( const QwtValueList& majorTicks, int maxMinSteps, double stepSize, QwtValueList &minorTicks, QwtValueList &mediumTicks) const { double minStep = divideInterval(stepSize, maxMinSteps); if (minStep == 0.0) return; // # ticks per interval int numTicks = (int)::ceil(qwtAbs(stepSize / minStep)) - 1; // Do the minor steps fit into the interval? if ( QwtScaleArithmetic::compareEps((numTicks + 1) * qwtAbs(minStep), qwtAbs(stepSize), stepSize) > 0) { numTicks = 1; minStep = stepSize * 0.5; } int medIndex = -1; if ( numTicks % 2 ) medIndex = numTicks / 2; // calculate minor ticks for (int i = 0; i < (int)majorTicks.count(); i++) { double val = majorTicks[i]; for (int k = 0; k < numTicks; k++) { val += minStep; double alignedValue = val; if (QwtScaleArithmetic::compareEps(val, 0.0, stepSize) == 0) alignedValue = 0.0; if ( k == medIndex ) mediumTicks += alignedValue; else minorTicks += alignedValue; } } }
/*! \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; }
QwtDoubleInterval QwtScaleEngine::buildInterval(double v) const { #if 1 const double delta = (v == 0.0) ? 0.5 : qwtAbs(0.5 * v); return QwtDoubleInterval(v - delta, v + delta); #else if ( v == 0.0 ) return QwtDoubleInterval(-0.5, 0.5); return QwtDoubleInterval(0.5 * v, 1.5 * v); #endif }
/*! \brief Calculate a scale division \param x1 First interval limit \param x2 Second interval limit \param maxMajSteps Maximum for the number of major steps \param maxMinSteps Maximum number of minor steps \param stepSize Step size. If stepSize == 0, the scaleEngine calculates one. \sa QwtScaleEngine::stepSize, LogTimeScaleEngine::subDivide */ QwtScaleDiv LogTimeScaleEngine::divideScale(double x1, double x2, int maxMajSteps, int maxMinSteps, double stepSize) const { QwtDoubleInterval interval = QwtDoubleInterval(x1, x2).normalized(); interval = interval.limited(LOG_MIN, LOG_MAX); if (interval.width() <= 0 ) return QwtScaleDiv(); if (interval.maxValue() / interval.minValue() < 10.0) { // scale width is less than one decade -> build linear scale QwtLinearScaleEngine linearScaler; linearScaler.setAttributes(attributes()); linearScaler.setReference(reference()); linearScaler.setMargins( #if (QWT_VERSION >= 0x050200) lowerMargin(), upperMargin() #else loMargin(), hiMargin() #endif ); return linearScaler.divideScale(x1, x2, maxMajSteps, maxMinSteps, stepSize); } stepSize = qwtAbs(stepSize); if ( stepSize == 0.0 ) { if ( maxMajSteps < 1 ) maxMajSteps = 1; stepSize = divideInterval(log10(interval).width(), maxMajSteps); if ( stepSize < 1.0 ) stepSize = 1.0; // major step must be >= 1 decade } QwtScaleDiv scaleDiv; if ( stepSize != 0.0 ) { QwtValueList ticks[QwtScaleDiv::NTickTypes]; buildTicks(interval, stepSize, maxMinSteps, ticks); scaleDiv = QwtScaleDiv(interval, ticks); } if ( x1 > x2 ) scaleDiv.invert(); return scaleDiv; }
/*! \brief Compare 2 values, relative to an interval Values are "equal", when : \f$\cdot value2 - value1 <= abs(intervalSize * 10e^{-6})\f$ \param value1 First value to compare \param value2 Second value to compare \param intervalSize interval size \return 0: if equal, -1: if value2 > value1, 1: if value1 > value2 */ int QwtScaleArithmetic::compareEps(double value1, double value2, double intervalSize) { const double eps = qwtAbs(_eps * intervalSize); if ( value2 - value1 > eps ) return -1; if ( value1 - value2 > eps ) return 1; return 0; }
static bool limRange(double &val, double v1, double v2, double eps_rel = 0.0, double eps_abs = 0.0) { bool rv = true; double vmin = qwtMin(v1, v2); double vmax = qwtMax(v1, v2); double delta_min = qwtMax(qwtAbs(eps_rel * vmin), qwtAbs(eps_abs)); double delta_max = qwtMax(qwtAbs(eps_rel * vmax), qwtAbs(eps_abs)); if (val < vmin) { if (val < vmin - delta_min) rv = false; val = vmin; } else if (val > vmax) { if (val > vmax + delta_max) rv = false; val = vmax; } return rv; }
/*! \brief Translate and in/decrease the zoom factor In zoom mode the zoom position is in the center of the canvas. The radius of the circle depends on the size of the plot canvas, that is divided by the zoom factor. Thus a factor < 1.0 zoom in. Setting an invalid zoom position disables zooming. \param zoomPos Center of the translation \param zoomFactor Zoom factor \sa unzoom(), zoomPos(), zoomFactor() */ void QwtPolarPlot::zoom( const QwtPolarPoint &zoomPos, double zoomFactor ) { zoomFactor = qwtAbs( zoomFactor ); if ( zoomPos != d_data->zoomPos || zoomFactor != d_data->zoomFactor ) { d_data->zoomPos = zoomPos; d_data->zoomFactor = zoomFactor; #if 1 updateLayout(); #endif autoRefresh(); } }
/*! \brief Calculate a scale division \param x1 First interval limit \param x2 Second interval limit \param maxMajSteps Maximum for the number of major steps \param maxMinSteps Maximum number of minor steps \param stepSize Step size. If stepSize == 0, the scaleEngine calculates one. */ QwtScaleDiv Log2ScaleEngine::divideScale(double x1, double x2, int maxMajSteps, int maxMinSteps, double stepSize) const { QwtDoubleInterval interval = QwtDoubleInterval(x1, x2).normalized(); interval = interval.limited(LOG_MIN, LOG_MAX); if (interval.width() <= 0 ) return QwtScaleDiv(); if (interval.maxValue() / interval.minValue() < 2){ // scale width is less than 2 -> build linear scale QwtLinearScaleEngine linearScaler; linearScaler.setAttributes(attributes()); linearScaler.setReference(reference()); linearScaler.setMargins(lowerMargin(), upperMargin()); return linearScaler.divideScale(x1, x2, maxMajSteps, maxMinSteps, stepSize); } stepSize = qwtAbs(stepSize); if ( stepSize == 0.0 ){ if ( maxMajSteps < 1 ) maxMajSteps = 1; stepSize = ceil(log2(interval).width()/double(maxMajSteps)); } QwtScaleDiv scaleDiv; if ( stepSize != 0.0 ){ QwtValueList ticks[QwtScaleDiv::NTickTypes]; buildTicks(interval, stepSize, maxMinSteps, ticks); scaleDiv = QwtScaleDiv(interval, ticks); } if ( x1 > x2 ) scaleDiv.invert(); return scaleDiv; }
QPoint QwtRect::intersectEdge(const QPoint &p1, const QPoint &p2, Edge edge ) const { int x=0, y=0; double m = 0; const double dy = p2.y() - p1.y(); const double dx = p2.x() - p1.x(); switch ( edge ) { case Left: x = left(); m = double(qwtAbs(p1.x() - x)) / qwtAbs(dx); y = p1.y() + int(dy * m); break; case Top: y = top(); m = double(qwtAbs(p1.y() - y)) / qwtAbs(dy); x = p1.x() + int(dx * m); break; case Right: x = right(); m = double(qwtAbs(p1.x() - x)) / qwtAbs(dx); y = p1.y() + int(dy * m); break; case Bottom: y = bottom(); m = double(qwtAbs(p1.y() - y)) / qwtAbs(dy); x = p1.x() + int(dx * m); break; default: break; } return QPoint(x,y); }
double QwtCircleClipper::toAngle( const QwtDoublePoint &from, const QwtDoublePoint &to) const { if ( from.x() == to.x() ) return from.y() <= to.y() ? M_PI / 2.0 : 3 * M_PI / 2.0; const double m = qwtAbs((to.y() - from.y()) / (to.x() - from.x()) ); double angle = ::atan(m); if ( to.x() > from.x() ) { if ( to.y() > from.y() ) angle = 2 * M_PI - angle; } else { if ( to.y() > from.y() ) angle = M_PI + angle; else angle = M_PI - angle; } return angle; }
/*! \brief build a logarithmic scale */ void QwtAutoScale::buildLogScale () { if (!d_autoScale) return; double minval = d_minValue; // the calculation of scale divisions double maxval = d_maxValue; // is based on the input data. if (d_loMargin > 0.0) minval /= pow(10.0, d_loMargin); if (d_hiMargin > 0.0) maxval *= pow(10.0, d_hiMargin); if (d_scaleOpt & Symmetric) { const double delta = qwtMax(maxval / d_lref, d_lref / minval); maxval = d_lref * delta; minval = d_lref / delta; } else if (d_scaleOpt & IncludeRef) { if (maxval < d_lref) maxval = d_lref; else if (minval > d_lref) minval = d_lref; } const double ticks = (d_maxMajor > 0) ? double(d_maxMajor) : 1; setRange(minval, maxval); // decades included in the interval const double decades = qwtAbs(log10 (d_scaleMax / d_scaleMin)); // calculate step size in decades double step; if ((decades > 1.0) && (decades > ticks)) { double ipart; // One interval contains more than one decade. // The number of decades in an interval is adjusted // to be a multiple of 2,3,5, or 10. double fpart = modf (log10 (ceil (decades * 0.999999 / ticks)), &ipart); if (fpart < MinEps) fpart = 1.0; else if ((fpart - LOG10_2) < MinEps) fpart = 2.0; else if ((fpart - LOG10_3) < MinEps) fpart = 3.0; else if ((fpart - LOG10_5) < MinEps) fpart = 5.0; else fpart = 10.0; step = pow (10.0, ipart) * fpart; } else // The minimal step size is one decade. { step = 1.0; } if (!(d_scaleOpt & Floating)) { d_scaleMin = pow (10.0, step * floor ((log10(d_scaleMin) + MinEps * step) / step)); d_scaleMax = pow (10.0, step * ceil ((log10(d_scaleMax) - MinEps * step) / step)); } if (d_scaleOpt & Inverted) { step = -step; d_scldiv.rebuild(d_scaleMax, d_scaleMin, d_maxMajor, d_maxMinor, TRUE, step, FALSE); } else { d_scldiv.rebuild(d_scaleMin, d_scaleMax, d_maxMajor, d_maxMinor, TRUE, step, TRUE); } }
/*! Draw the Wheel's background gradient \param painter Painter \param r Bounding rectangle */ void QwtWheel::drawWheelBackground(QPainter *painter, const QRect &r ) { painter->save(); // // initialize pens // #if QT_VERSION < 0x040000 const QColor light = colorGroup().light(); const QColor dark = colorGroup().dark(); #else const QColor light = palette().color(QPalette::Light); const QColor dark = palette().color(QPalette::Dark); #endif QPen lightPen; lightPen.setColor(light); lightPen.setWidth(d_data->intBorder); QPen darkPen; darkPen.setColor(dark); darkPen.setWidth(d_data->intBorder); setColorArray(); // // initialize auxiliary variables // const int nFields = NUM_COLORS * 13 / 10; const int hiPos = nFields - NUM_COLORS + 1; if ( orientation() == Qt::Horizontal ) { const int rx = r.x(); int ry = r.y() + d_data->intBorder; const int rh = r.height() - 2* d_data->intBorder; const int rw = r.width(); // // draw shaded background // int x1 = rx; for (int i = 1; i < nFields; i++ ) { const int x2 = rx + (rw * i) / nFields; painter->fillRect(x1, ry, x2-x1 + 1 ,rh, d_data->colors[qwtAbs(i-hiPos)]); x1 = x2 + 1; } painter->fillRect(x1, ry, rw - (x1 - rx), rh, d_data->colors[NUM_COLORS - 1]); // // draw internal border // painter->setPen(lightPen); ry = r.y() + d_data->intBorder / 2; painter->drawLine(r.x(), ry, r.x() + r.width() , ry); painter->setPen(darkPen); ry = r.y() + r.height() - (d_data->intBorder - d_data->intBorder / 2); painter->drawLine(r.x(), ry , r.x() + r.width(), ry); } else // Qt::Vertical { int rx = r.x() + d_data->intBorder; const int ry = r.y(); const int rh = r.height(); const int rw = r.width() - 2 * d_data->intBorder; // // draw shaded background // int y1 = ry; for ( int i = 1; i < nFields; i++ ) { const int y2 = ry + (rh * i) / nFields; painter->fillRect(rx, y1, rw, y2-y1 + 1, d_data->colors[qwtAbs(i-hiPos)]); y1 = y2 + 1; } painter->fillRect(rx, y1, rw, rh - (y1 - ry), d_data->colors[NUM_COLORS - 1]); // // draw internal borders // painter->setPen(lightPen); rx = r.x() + d_data->intBorder / 2; painter->drawLine(rx, r.y(), rx, r.y() + r.height()); painter->setPen(darkPen); rx = r.x() + r.width() - (d_data->intBorder - d_data->intBorder / 2); painter->drawLine(rx, r.y(), rx , r.y() + r.height()); } painter->restore(); }
/*! \brief Build a linear scale */ void QwtAutoScale::buildLinScale () { double delta; const double ticks = double (d_maxMajor); // // If in Autoscale Mode, adjust minval and maxval according to // the active scale options, and add the margins // if (!d_autoScale) return; double minval = d_minValue; // scale boundaries are based on the double maxval = d_maxValue; // data. // // add / subtract margins // if (d_loMargin > 0.0) minval -= d_loMargin; if (d_hiMargin > 0.0) maxval += d_hiMargin; // // Correct minval / maxval according to the scale options // if (d_scaleOpt & Symmetric) { delta = qwtMax(qwtAbs(d_ref - maxval), qwtAbs(d_ref - minval)); maxval = d_ref + delta; minval = d_ref - delta; } else if (d_scaleOpt & IncludeRef) { if (maxval < d_ref) maxval = d_ref; else if (minval > d_ref) minval = d_ref; } // // first approximation of d_scaleMin and d_scaleMax // setRange(minval, maxval); delta = d_scaleMax - d_scaleMin; // dec := maximal power of ten which fits into the interval // [d_scaleMin,d_scaleMax] const double dec = pow (10.0, floor (log10 (delta))); // // The following magic line calculates the step size such that // - The number of subintervals will not exceed the maximum // as specified by the user // - The step size fits {1,2,5}*10^n with a natural number n // double step = qwtCeil125(delta * 0.999999 / dec / ticks) * dec; // // determine he final values of scaleMin and scaleMax // if (! (d_scaleOpt & Floating) ) { // adjust of d_scaleMin and d_scaleMax such that both are integer // multiples of the step size. d_scaleMin = step * floor ((d_scaleMin + MinEps * step) / step); d_scaleMax = step * ceil ((d_scaleMax - MinEps * step) / step); } if (d_scaleOpt & Inverted) { step = -step; d_scldiv.rebuild(d_scaleMax, d_scaleMin, d_maxMajor, d_maxMinor, FALSE, step, FALSE); } else { d_scldiv.rebuild(d_scaleMin, d_scaleMax, d_maxMajor, d_maxMinor, FALSE, step, TRUE); } }
/*! \return the step size \sa setStep(), setRange() */ double QwtDoubleRange::step() const { return qwtAbs(d_step); }
/*! \brief Redraw the wheel \param painter painter \param r contents rectangle */ void QwtWheel::drawWheel( QPainter *painter, const QRect &r ) { // // draw background gradient // drawWheelBackground( painter, r ); if ( maxValue() == minValue() || d_data->totalAngle == 0.0 ) return; #if QT_VERSION < 0x040000 const QColor light = colorGroup().light(); const QColor dark = colorGroup().dark(); #else const QColor light = palette().color(QPalette::Light); const QColor dark = palette().color(QPalette::Dark); #endif const double sign = (minValue() < maxValue()) ? 1.0 : -1.0; double cnvFactor = qwtAbs(d_data->totalAngle / (maxValue() - minValue())); const double halfIntv = 0.5 * d_data->viewAngle / cnvFactor; const double loValue = value() - halfIntv; const double hiValue = value() + halfIntv; const double tickWidth = 360.0 / double(d_data->tickCnt) / cnvFactor; const double sinArc = sin(d_data->viewAngle * M_PI / 360.0); cnvFactor *= M_PI / 180.0; // // draw grooves // if ( orientation() == Qt::Horizontal ) { const double halfSize = double(r.width()) * 0.5; int l1 = r.y() + d_data->intBorder; int l2 = r.y() + r.height() - d_data->intBorder - 1; // draw one point over the border if border > 1 if ( d_data->intBorder > 1 ) { l1 --; l2 ++; } const int maxpos = r.x() + r.width() - 2; const int minpos = r.x() + 2; // // draw tick marks // for ( double tickValue = ceil(loValue / tickWidth) * tickWidth; tickValue < hiValue; tickValue += tickWidth ) { // // calculate position // const int tickPos = r.x() + r.width() - int( halfSize * (sinArc + sign * sin((tickValue - value()) * cnvFactor)) / sinArc); // // draw vertical line // if ( (tickPos <= maxpos) && (tickPos > minpos) ) { painter->setPen(dark); painter->drawLine(tickPos -1 , l1, tickPos - 1, l2 ); painter->setPen(light); painter->drawLine(tickPos, l1, tickPos, l2); } } } else if ( orientation() == Qt::Vertical ) { const double halfSize = double(r.height()) * 0.5; int l1 = r.x() + d_data->intBorder; int l2 = r.x() + r.width() - d_data->intBorder - 1; if ( d_data->intBorder > 1 ) { l1--; l2++; } const int maxpos = r.y() + r.height() - 2; const int minpos = r.y() + 2; // // draw tick marks // for ( double tickValue = ceil(loValue / tickWidth) * tickWidth; tickValue < hiValue; tickValue += tickWidth ) { // // calculate position // const int tickPos = r.y() + int( halfSize * (sinArc + sign * sin((tickValue - value()) * cnvFactor)) / sinArc); // // draw horizontal line // if ( (tickPos <= maxpos) && (tickPos > minpos) ) { painter->setPen(dark); painter->drawLine(l1, tickPos - 1 ,l2, tickPos - 1); painter->setPen(light); painter->drawLine(l1, tickPos, l2, tickPos); } } } }
void QwtPicker::drawRubberBand(QPainter *painter) const { if ( !isActive() || rubberBand() == NoRubberBand || rubberBandPen().style() == Qt::NoPen ) { return; } const QRect &pRect = pickRect(); const SelectedPoints &pa = d_data->selection; if ( selectionFlags() & PointSelection ) { if ( pa.count() < 1 ) return; const QPoint pos = pa[0]; switch(rubberBand()) { case VLineRubberBand: QwtPainter::drawLine(painter, pos.x(), pRect.top(), pos.x(), pRect.bottom()); break; case HLineRubberBand: QwtPainter::drawLine(painter, pRect.left(), pos.y(), pRect.right(), pos.y()); break; case CrossRubberBand: QwtPainter::drawLine(painter, pos.x(), pRect.top(), pos.x(), pRect.bottom()); QwtPainter::drawLine(painter, pRect.left(), pos.y(), pRect.right(), pos.y()); break; default: break; } } else if ( selectionFlags() & RectSelection ) { if ( pa.count() < 2 ) return; QPoint p1 = pa[0]; QPoint p2 = pa[int(pa.count() - 1)]; if ( selectionFlags() & CenterToCorner ) { p1.setX(p1.x() - (p2.x() - p1.x())); p1.setY(p1.y() - (p2.y() - p1.y())); } else if ( selectionFlags() & CenterToRadius ) { const int radius = qwtMax(qwtAbs(p2.x() - p1.x()), qwtAbs(p2.y() - p1.y())); p2.setX(p1.x() + radius); p2.setY(p1.y() + radius); p1.setX(p1.x() - radius); p1.setY(p1.y() - radius); } #if QT_VERSION < 0x040000 const QRect rect = QRect(p1, p2).normalize(); #else const QRect rect = QRect(p1, p2).normalized(); #endif switch(rubberBand()) { case EllipseRubberBand: QwtPainter::drawEllipse(painter, rect); break; case RectRubberBand: QwtPainter::drawRect(painter, rect); break; default: break; } } else if ( selectionFlags() & PolygonSelection ) { if ( rubberBand() == PolygonRubberBand ) painter->drawPolyline(pa); } }
static inline bool isClose( double value1, double value2 ) { return qwtAbs( value1 - value2 ) < DBL_EPSILON; }
QwtDoubleInterval QwtScaleEngine::buildInterval(double v) const { const double delta = (v == 0.0) ? 0.5 : qwtAbs(0.5 * v); return QwtDoubleInterval(v - delta, v + delta); }
QwtValueList QwtLog10ScaleEngine::buildMinorTicks( const QwtValueList &majorTicks, int maxMinSteps, double stepSize) const { if (stepSize < 1.1) // major step width is one decade { if ( maxMinSteps < 1 ) return QwtValueList(); int k0, kstep, kmax; if (maxMinSteps >= 8) { k0 = 2; kmax = 9; kstep = 1; } else if (maxMinSteps >= 4) { k0 = 2; kmax = 8; kstep = 2; } else if (maxMinSteps >= 2) { k0 = 2; kmax = 5; kstep = 3; } else { k0 = 5; kmax = 5; kstep = 1; } QwtValueList minorTicks; for (int i = 0; i < (int)majorTicks.count(); i++) { const double v = majorTicks[i]; for (int k = k0; k<= kmax; k+=kstep) minorTicks += v * double(k); } return minorTicks; } else // major step > one decade { double minStep = divideInterval(stepSize, maxMinSteps); if ( minStep == 0.0 ) return QwtValueList(); if ( minStep < 1.0 ) minStep = 1.0; // # subticks per interval int nMin = qRound(stepSize / minStep) - 1; // Do the minor steps fit into the interval? if ( QwtScaleArithmetic::compareEps((nMin + 1) * minStep, qwtAbs(stepSize), stepSize) > 0) { nMin = 0; } if (nMin < 1) return QwtValueList(); // no subticks // substep factor = 10^substeps const double minFactor = qwtMax(pow(10.0, minStep), 10.0); QwtValueList minorTicks; for (int i = 0; i < (int)majorTicks.count(); i++) { double val = majorTicks[i]; for (int k=0; k< nMin; k++) { val *= minFactor; minorTicks += val; } } return minorTicks; } }
bool ScaleDiv::buildLogDiv(int maxMajSteps, int maxMinSteps, double majStep) { double firstTick, lastTick; double lFirst, lLast; double val, sval, minStep, minFactor; int nMaj, nMin, minSize, i, k, k0, kstep, kmax, i0; int rv = true; double width; QVector<double> buffer; // Parameter range check maxMajSteps = qwtMax(1, qwtAbs(maxMajSteps)); maxMinSteps = qwtMax(0, qwtAbs(maxMinSteps)); majStep = qwtAbs(majStep); // boundary check limRange(d_hBound, LOG_MIN, LOG_MAX); limRange(d_lBound, LOG_MIN, LOG_MAX); // reset vectors d_minMarks.resize(0); d_majMarks.resize(0); if (d_lBound == d_hBound) return true; // scale width in decades width = log10(d_hBound) - log10(d_lBound); // scale width is less than one decade -> build linear scale if (width < 1.0) { rv = buildLinDiv(maxMajSteps, maxMinSteps, 0.0); // convert step width to decades if (d_majStep > 0) d_majStep = log10(d_majStep); return rv; } // // Set up major scale divisions // if (majStep == 0.0) d_majStep = qwtCeil125(width * 0.999999 / double(maxMajSteps)); else d_majStep = majStep; // major step must be >= 1 decade d_majStep = qwtMax(d_majStep, 1.0); lFirst = ceil((log10(d_lBound) - step_eps * d_majStep) / d_majStep) * d_majStep; lLast = floor((log10(d_hBound) + step_eps * d_majStep) / d_majStep) * d_majStep; firstTick = pow(10.0, lFirst); lastTick = pow(10.0, lLast); nMaj = qwtMin(10000, int(rint(qwtAbs(lLast - lFirst) / d_majStep)) + 1); d_majMarks.resize(nMaj); qwtLogSpace(d_majMarks.data(), d_majMarks.size(), firstTick, lastTick); // // Set up minor scale divisions // if ((d_majMarks.size() < 1) || (maxMinSteps < 1)) return true; // no minor marks if (d_majStep < 1.1) // major step width is one decade { if (maxMinSteps >= 8) { k0 = 2; kmax = 9; kstep = 1; minSize = (d_majMarks.size() + 1) * 8; } else if (maxMinSteps >= 4) { k0 = 2; kmax = 8; kstep = 2; minSize = (d_majMarks.size() + 1) * 4; } else if (maxMinSteps >= 2) { k0 = 2; kmax = 5; kstep = 3; minSize = (d_majMarks.size() + 1) * 2; } else { k0 = 5; kmax = 5; kstep = 1; minSize = (d_majMarks.size() + 1); } // resize buffer to the max. possible number of minor marks buffer.resize(minSize); // Are there minor ticks below the first major tick? if (d_lBound < firstTick) i0 = -1; else i0 = 0; minSize = 0; for (i = i0; i < (int) d_majMarks.size(); i++) { if (i >= 0) val = d_majMarks[i]; else val = d_majMarks[0] / pow(10.0, d_majStep); for (k = k0; k <= kmax; k += kstep) { sval = val * double(k); if (limRange(sval, d_lBound, d_hBound, border_eps)) { buffer[minSize] = sval; minSize++; } } } // copy values into the minMarks array //d_minMarks.duplicate(buffer.data(), minSize); d_minMarks.resize(minSize); qCopy(buffer.data(), buffer.data() + minSize, d_minMarks.begin()); } else // major step > one decade { // substep width in decades, at least one decade minStep = qwtCeil125((d_majStep - step_eps * (d_majStep / double(maxMinSteps))) / double(maxMinSteps)); minStep = qwtMax(1.0, minStep); // # subticks per interval nMin = int(rint(d_majStep / minStep)) - 1; // Do the minor steps fit into the interval? if (qwtAbs(double(nMin + 1) * minStep - d_majStep) > step_eps * d_majStep) nMin = 0; if (nMin < 1) return true; // no subticks // resize buffer to max. possible number of subticks buffer.resize((d_majMarks.size() + 1) * nMin); // substep factor = 10^substeps minFactor = qwtMax(pow(10, minStep), 10.0); // Are there minor ticks below the first major tick? if (d_lBound < firstTick) i0 = -1; else i0 = 0; minSize = 0; for (i = i0; i < (int) d_majMarks.size(); i++) { if (i >= 0) val = d_majMarks[i]; else val = firstTick / pow(10.0, d_majStep); for (k = 0; k < nMin; k++) { sval = (val *= minFactor); if (limRange(sval, d_lBound, d_hBound, border_eps)) { buffer[minSize] = sval; minSize++; } } } //d_minMarks.duplicate(buffer.data(), minSize); d_minMarks.resize(minSize); qCopy(buffer.data(), buffer.data() + minSize, d_minMarks.begin()); } return rv; }