⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qwt_scldraw.cpp

📁 软件无线电的平台
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997   Josef Wilgen * Copyright (C) 2002   Uwe Rathmann *  * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/// vim: expandtab#include <qpainter.h>#include "qwt_math.h"#include "qwt_painter.h"#include "qwt_scldraw.h"#include "qwt_layout_metrics.h"static const double step_eps = 1.0e-6;/*!  \brief Constructor  The range of the scale is initialized to [0, 100],  the angle range is set to [-135, 135], the geometry  is initialized such that the origin is at (0,0), the  length is 100, and the orientation is QwtScaleDraw::Bottom.*/QwtScaleDraw::QwtScaleDraw():    d_options(Backbone),    d_hpad(4),    d_vpad(4),    d_medLen(6),    d_majLen(8),    d_minLen(4),    d_minAngle(-135 * 16),    d_maxAngle(135 * 16),    d_fmt('g'),    d_prec(4),    d_fieldwidth(0),    d_labelAlignment(0),    d_labelRotation(0.0){    setGeometry(0,0,100,Bottom);    setScale(0,100,0,0,10);}//! DestructorQwtScaleDraw::~QwtScaleDraw(){}void QwtScaleDraw::setOptions(int opt){    d_options = opt;}int QwtScaleDraw::options() const{    return d_options;}/*!  \brief Adjust the range of the scale  If step == 0.0, the step width is calculated automatically  dependent on the maximal number of scale ticks.  \param x1 Value at the left/low endpoint of the scale  \param x2 Value at the right/high endpoint of the scale  \param maxMajIntv Max. number of major step intervals  \param maxMinIntv Max. number of minor step intervals  \param step Step size (default : 0.0)  \param logscale Logarithmic scale (default : 0)*/void QwtScaleDraw::setScale(double x1, double x2, int maxMajIntv,                            int maxMinIntv, double step, int logscale){    d_scldiv.rebuild( x1, x2, maxMajIntv, maxMinIntv, logscale, step, FALSE );    setDblRange( d_scldiv.lBound(), d_scldiv.hBound(), d_scldiv.logScale());}/*!  \brief Change the scale division  \param sd new scale division*/void QwtScaleDraw::setScale(const QwtScaleDiv &sd){    d_scldiv = sd;    setDblRange(d_scldiv.lBound(),d_scldiv.hBound(),d_scldiv.logScale());}/*!  \brief Draw the scale  \param p the painter*/void QwtScaleDraw::draw(QPainter *p) const{    uint i;    for (i=0; i< d_scldiv.majCnt(); i++)    {        const double val = d_scldiv.majMark(i);        drawTick(p, val, d_majLen);        drawLabel(p, val);    }    if (d_scldiv.logScale())    {        for (i=0; i< d_scldiv.minCnt(); i++)            drawTick(p, d_scldiv.minMark(i), d_minLen);    }    else    {        const int kmax = d_scldiv.majCnt() - 1;        if (kmax > 0)         {            double majTick = d_scldiv.majMark(0);            double hval = majTick - 0.5 * d_scldiv.majStep();            int k = 0;            for (i=0; i< d_scldiv.minCnt(); i++)            {                const double val = d_scldiv.minMark(i);                if  (val > majTick)                {                    if (k < kmax)                    {                        k++;                        majTick = d_scldiv.majMark(k);                    }                    else                    {                        majTick += d_scldiv.majMark(kmax) + d_scldiv.majStep();                    }                    hval = majTick - 0.5 * d_scldiv.majStep();                }                if (qwtAbs(val-hval) < step_eps * d_scldiv.majStep())                    drawTick(p, val, d_medLen);                else                    drawTick(p, val, d_minLen);            }        }    }    if ( options() & Backbone )        drawBackbone(p);}//! Draws a single scale tickvoid QwtScaleDraw::drawTick(QPainter *p, double val, int len) const{    if ( len <= 0 )        return;    const int tval = transform(val);    switch(d_orient)    {        case Left:            QwtPainter::drawLine(p, d_xorg, tval, d_xorg - len, tval);            break;        case Right:            QwtPainter::drawLine(p, d_xorg, tval, d_xorg + len, tval);            break;        case Bottom:             QwtPainter::drawLine(p, tval, d_yorg, tval, d_yorg + len);            break;        case Top:            QwtPainter::drawLine(p, tval, d_yorg, tval, d_yorg - len);            break;        case Round:            if ((tval <= d_minAngle + 359 * 16)                 || (tval >= d_minAngle - 359 * 16))            {                const double arc = double(tval) / 16.0 * M_PI / 180.0;                const int x1 = qwtInt(d_xCenter + sin(arc) * d_radius);                const int x2 = qwtInt(d_xCenter + sin(arc)                     * (d_radius + double(len)));                const int y1 = qwtInt(d_yCenter - cos(arc) * d_radius);                const int y2 = qwtInt(d_yCenter - cos(arc)                     * (d_radius + double(len)));                QwtPainter::drawLine(p, x1, y1, x2, y2);            }            break;    }}//! Draws the number label for a major scale tickvoid QwtScaleDraw::drawLabel(QPainter *p, double val) const{    QPoint pos;    int alignment;    double rotation;    labelPlacement(QFontMetrics(p->font()), val, pos, alignment, rotation);    if ( alignment )    {        const QString txt = label(val);        if ( !txt.isEmpty() )        {            QWMatrix m = labelWorldMatrix(QFontMetrics(p->font()),                pos, alignment, rotation, txt);            p->save();#ifndef QT_NO_TRANSFORMATIONS            p->setWorldMatrix(m, TRUE);#else            p->translate(m.dx(), m.dy());#endif            QwtPainter::drawText(p, 0, 0, txt);            p->restore();        }    }}//! Find position, alignment and rotation of the labelvoid QwtScaleDraw::labelPlacement( const QFontMetrics &fm, double val,     QPoint &pos, int &alignment, double &rotation) const{    // correct rounding errors if val = 0    if ((!d_scldiv.logScale())         && (qwtAbs(val) < qwtAbs(step_eps * d_scldiv.majStep())))    {       val = 0.0;    }        const int tval = transform(val);    int x = 0;    int y = 0;    int align = 0;    switch(d_orient)    {        case Right:        {            x = d_xorg + d_majLen + d_hpad + 1;            y = tval;            align = d_labelAlignment;            if ( align == 0 )                align = Qt::AlignRight | Qt::AlignVCenter;            break;        }        case Left:        {            x = d_xorg - d_majLen - d_hpad - 1;            y = tval;            align = d_labelAlignment;            if ( align == 0 )                align = Qt::AlignLeft | Qt::AlignVCenter;            break;        }        case Bottom:        {            x = tval;            y = d_yorg + d_majLen + d_vpad + 1;            align = d_labelAlignment;            if ( align == 0 )                align = Qt::AlignHCenter | Qt::AlignBottom;            break;        }        case Top:        {            x = tval;            y = d_yorg - d_majLen - d_vpad - 1;            align = d_labelAlignment;            if ( align == 0 )                align = Qt::AlignHCenter | Qt::AlignTop;            break;        }        case Round:        {            if ((tval > d_minAngle + 359 * 16)                 || (tval < d_minAngle - 359 * 16))            {               break;            }                        const int fmh = fm.ascent() - 2;             const double arc = tval / 16.0 / 360.0 * 2 * M_PI;            const double radius = d_radius + d_majLen + d_vpad;            // First we find the point on a circle enlarged            // by half of the font height.            double xOffset = ( radius + fmh / 2 ) * sin(arc);             double yOffset = ( radius + fmh / 2 ) * cos(arc);            if ( qwtInt(xOffset) != 0 )             {                // The centered label might cut the circle                 // with distance: d_radius + d_majLen + d_vpad                // We align the label to the circle by moving                // the x-coordinate, because we have only                // horizontal labels here.                const int fmw = fm.width(label(val));                const double circleX = radius * sin(arc);                 if ( xOffset < 0 )                    xOffset = circleX - fmw / 2; // left                else                    xOffset = circleX + fmw / 2; // right            }            x = qwtInt(d_xCenter + xOffset);            y = qwtInt(d_yCenter - yOffset);            align = Qt::AlignHCenter | Qt::AlignVCenter;            break;        }    }    pos = QPoint(x, y);    alignment = align;    rotation = d_labelRotation;}//! Return the world matrix for painting the label QWMatrix QwtScaleDraw::labelWorldMatrix(const QFontMetrics &fm,    const QPoint &pos, int alignment, double rotation,     const QString &txt) const{    const int w = fm.boundingRect(0, 0,         QCOORD_MAX, QCOORD_MAX, 0, txt).width() - 2;    const int h = fm.ascent() - 2;        int x, y;    if ( alignment & Qt::AlignLeft )        x = -w;    else if ( alignment & Qt::AlignRight )        x = 0 - w % 2;    else // Qt::AlignHCenter        x = -(w / 2);            if ( alignment & Qt::AlignTop )        y = 0;    else if ( alignment & Qt::AlignBottom )        y = h - 1;    else // Qt::AlignVCenter        y = h / 2;        QWMatrix m;    m.translate(pos.x(), pos.y());    m.rotate(rotation);    m.translate(x, y);    return m;}//! Draws the baseline of the scalevoid QwtScaleDraw::drawBackbone(QPainter *p) const{    const int bw2 = p->pen().width() / 2;        switch(d_orient)    {        case Left:            QwtPainter::drawLine(p, d_xorg - bw2,                 d_yorg, d_xorg - bw2, d_yorg + d_len - 1);            break;        case Right:            QwtPainter::drawLine(p, d_xorg + bw2,                 d_yorg, d_xorg + bw2, d_yorg + d_len - 1);            break;        case Top:            QwtPainter::drawLine(p, d_xorg, d_yorg - bw2,                 d_xorg + d_len - 1, d_yorg - bw2);            break;        case Bottom:            QwtPainter::drawLine(p, d_xorg, d_yorg + bw2,                 d_xorg + d_len - 1, d_yorg + bw2);            break;        case Round:        {            const int a1 = qwtMin(i1(), i2()) - 90 * 16;             const int a2 = qwtMax(i1(), i2()) - 90 * 16;                         p->drawArc(d_xorg, d_yorg, d_len, d_len,                -a2, a2 - a1 + 1);           // counterclockwise            break;        }    }}/*!  \brief Specify the geometry of the scale  The parameters xorigin, yorigin and length have different meanings,  dependent on the  orientation:  <dl>  <dt>QwtScaleDraw::Left  <dd>The origin is the topmost point of the      baseline. The baseline is a vertical line with the      specified length. Scale marks and labels are drawn      at the left of the baseline.  <dt>QwtScaleDraw::Right  <dd>The origin is the topmost point of the      baseline. The baseline is a vertical line with the      specified length. Scale marks and labels are drawn      at the right of the baseline.  <dt>QwtScaleDraw::Top  <dd>The origin is the leftmost point of the      baseline. The baseline is a horizontal line with the      specified length. Scale marks and labels are drawn      above the baseline.  <dt>QwtScaleDraw::Bottom  <dd>The origin is the leftmost point of the      baseline. The baseline is a horizontal line with the      specified length. Scale marks and labels are drawn      below the baseline.  <dt>QwtScaleDraw::Round  <dd>The origin is the top left corner of the      bounding rectangle of the baseline circle. The baseline      is the segment of a circle with a diameter of the specified length.      Scale marks and labels are drawn outside the baseline      circle.</dl>  \param xorigin x coordinate of the origin  \param yorigin y coordinate of the origin  \param length length or diameter of the scale, excluding border distance  \param o The orientation*/void QwtScaleDraw::setGeometry(int xorigin, int yorigin,     int length, Orientation o){    static int minLen = 10;    d_xorg = xorigin;    d_yorg = yorigin;    d_radius = double(length) * 0.5;    d_xCenter = double(xorigin) + double(length) * 0.5;    d_yCenter = double(yorigin) + double(length) * 0.5;        if (length > minLen)       d_len = length;    else       d_len = minLen;        d_orient = o;        switch(d_orient)    {        case Left:        case Right:            setIntRange(d_yorg + d_len - 1, d_yorg);            break;        case Round:            setIntRange(d_minAngle, d_maxAngle);            break;        case Top:        case Bottom:            setIntRange(d_xorg, d_xorg + d_len - 1);            break;    }}/*!  \param pen pen  \param fm font metrics  \return the maximum width of the scale */int QwtScaleDraw::maxWidth(const QPen &pen, const QFontMetrics &fm) const{    int w = 0;    switch (d_orient)    {        case Left:        case Right:            w += pen.width() + d_majLen + d_hpad + maxLabelWidth(fm);            break;        case Round:            w += pen.width() + d_majLen + d_vpad + maxLabelWidth(fm);            break;        case Top:        case Bottom:            w = d_len + maxLabelWidth(fm);            break;    }    return w;}/*!  \param pen pen  \param fm font metrics  \return the maximum height of the scale*/int QwtScaleDraw::maxHeight(const QPen &pen, const QFontMetrics &fm) const {    int h = 0;        switch (d_orient)    {        case Top:        case Bottom:            h = pen.width() + d_vpad + d_majLen + maxLabelHeight(fm);            break;        case Left:        case Right:            h = d_len + maxLabelHeight(fm);            break;        case Round:            h = d_vpad + d_majLen;            if ( maxLabelHeight(fm) > 0 )                h += fm.ascent() - 2;            break;    }        return h;}/*!  Rotate all labels. 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -