most files - check if this is all we need
This commit is contained in:
722
seaplot.cpp
Normal file
722
seaplot.cpp
Normal file
@ -0,0 +1,722 @@
|
||||
#include "seaplot.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <qfont.h>
|
||||
#include <qgrid.h>
|
||||
#include <qtooltip.h>
|
||||
#include <qwt_plot_layout.h>
|
||||
#include <qwt_scale.h>
|
||||
#include "utils.h"
|
||||
|
||||
#define SEA_RESOLUTION 0.00005 /* chagned from 0.0005 for Amy, July 2020 */
|
||||
|
||||
LegendButton::LegendButton(QWidget *parent, SeaPlot *plot, SeaCurve *crv) : QwtLegendButton(parent) {
|
||||
this->plot = plot;
|
||||
this->crv = crv;
|
||||
connect(this, SIGNAL(clicked()), this, SLOT(legendClicked()));
|
||||
connect(&clickTimer, SIGNAL(timeout()), this, SLOT(handleClickTimer()));
|
||||
label = new FlatButton(crv->title(), parent);
|
||||
setFixedHeight(label->sizeHint().height());
|
||||
setFixedWidth(16);
|
||||
connect(label, SIGNAL(clicked()), this, SLOT(legendClicked()));
|
||||
connect(label, SIGNAL(mousePressed()), this, SLOT(mousePressed()));
|
||||
};
|
||||
|
||||
void LegendButton::init(SeaPlot *plot, SeaCurve *crv) {
|
||||
this->plot = plot;
|
||||
this->crv = crv;
|
||||
};
|
||||
|
||||
void LegendButton::mousePressed() {
|
||||
clickDone = false;
|
||||
clickTimer.stop();
|
||||
clickTimer.start(300);
|
||||
}
|
||||
|
||||
void LegendButton::handleClickTimer() {
|
||||
if (!clickDone) {
|
||||
clickTimer.stop();
|
||||
clickDone = true;
|
||||
longClick();
|
||||
}
|
||||
}
|
||||
|
||||
void LegendButton::legendClicked() {
|
||||
if (!clickDone) {
|
||||
clickDone = true;
|
||||
clickTimer.stop();
|
||||
plot->switchBold(crv);
|
||||
}
|
||||
};
|
||||
|
||||
void LegendButton::longClick() {
|
||||
plot->setOneBold(crv);
|
||||
};
|
||||
|
||||
|
||||
void LegendButton::mousePressEvent(QMouseEvent *e) {
|
||||
mousePressed();
|
||||
QwtLegendButton::mousePressEvent(e);
|
||||
}
|
||||
|
||||
void LegendButton::setTitle(const QString &title) {
|
||||
label->setText(title);
|
||||
}
|
||||
|
||||
class TimeScaleDraw: public QwtScaleDraw {
|
||||
public:
|
||||
TimeScaleDraw(SeaSet *set) : QwtScaleDraw() {
|
||||
this->set = set;
|
||||
}
|
||||
virtual QString label(double v) const {
|
||||
QTime time;
|
||||
QwtScaleDiv div = scaleDiv();
|
||||
double step = div.majStep();
|
||||
int itic0 = lround(div.lBound() / step + 0.5001);
|
||||
int itic1 = lround(div.hBound() / step - 0.5001);
|
||||
int itic = lround(v / step);;
|
||||
int m;
|
||||
|
||||
if (step < 23*3600) {
|
||||
m = 2;
|
||||
if (step > 59 && step < 121) {
|
||||
m = 5;
|
||||
} else if (lround(step) == 600) {
|
||||
m = 3;
|
||||
}
|
||||
} else {
|
||||
m = (itic1 - itic0) / 5 + 1;
|
||||
}
|
||||
time.setHMS(0,0,0);
|
||||
itic0 = lround(div.lBound() / step / m + 0.5001);
|
||||
itic1 = lround(div.hBound() / step / m - 0.5001);
|
||||
if (itic1 - itic0 > 1 && v > div.hBound() - step) {
|
||||
return ""; //do not show last label
|
||||
} else if (itic % m == 0) {
|
||||
if (step < 3599) {
|
||||
return time.addSecs(lround(v)).toString("hh:mm");
|
||||
} else if (lround(v/3600) % 24 == 0) {
|
||||
return set->dateLabel(lround(v/(24*3600)));
|
||||
} else {
|
||||
return time.addSecs(lround(v)).toString("hh").append("h");
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
SeaSet *set;
|
||||
};
|
||||
|
||||
class YScaleDraw: public QwtScaleDraw {
|
||||
public:
|
||||
YScaleDraw(SeaSet *set) : QwtScaleDraw() {
|
||||
this->set = set;
|
||||
}
|
||||
virtual int maxLabelWidth(const QFontMetrics &fm) const {
|
||||
return set->leftLabelWidth(QwtScaleDraw::maxLabelWidth(fm));
|
||||
}
|
||||
SeaSet *set;
|
||||
};
|
||||
|
||||
class SeaZoomer: public QwtPlotZoomer {
|
||||
friend class SeaPlot;
|
||||
public:
|
||||
SeaZoomer(SeaPlot *p) :
|
||||
QwtPlotZoomer(QwtPlot::xBottom, QwtPlot::yLeft,
|
||||
QwtPicker::DragSelection, QwtPicker::AlwaysOff,
|
||||
p->canvas()) {
|
||||
yAuto = true;
|
||||
displayMarker = false;
|
||||
pl = p;
|
||||
doZoom = false;
|
||||
};
|
||||
SeaPlot *pl;
|
||||
bool yAuto;
|
||||
bool setMark;
|
||||
bool displayMarker;
|
||||
bool track;
|
||||
bool doZoom;
|
||||
int xp, yp;
|
||||
QTime t;
|
||||
|
||||
protected:
|
||||
QwtDoubleSize minZoomSize() const {
|
||||
const QwtScaleDiv *scy = pl->axisScale(QwtPlot::yLeft);
|
||||
double hei = fabs(scy->hBound() + scy->lBound()) * SEA_RESOLUTION;
|
||||
return QwtDoubleSize(60., hei);
|
||||
};
|
||||
|
||||
void rescale() {
|
||||
QwtDoubleRect r = zoomRect();
|
||||
if (doZoom && r != scaleRect()) {
|
||||
pl->zoomTo(scaleRect(), r);
|
||||
}
|
||||
}
|
||||
|
||||
void enableMarker() {
|
||||
if (!displayMarker) {
|
||||
QWidget *parent = parentWidget();
|
||||
track = parent->hasMouseTracking();
|
||||
parent->setMouseTracking(true);
|
||||
displayMarker = true;
|
||||
}
|
||||
}
|
||||
|
||||
void disableMarker() {
|
||||
if (displayMarker) {
|
||||
QWidget *parent = parentWidget();
|
||||
displayMarker = false;
|
||||
parent->setMouseTracking(track);
|
||||
}
|
||||
}
|
||||
|
||||
void widgetMousePressEvent(QMouseEvent *e) {
|
||||
//printf("*** mousePress %d %d\n", e->x(), e->y());
|
||||
xp = e->x();
|
||||
yp = e->y();
|
||||
if (pl->set->markerFix) {
|
||||
setMark = true;
|
||||
} else {
|
||||
setMark = !pl->set->markerWasOn;
|
||||
}
|
||||
pl->set->markerFix = false;
|
||||
t.start();
|
||||
QwtPlotZoomer::widgetMousePressEvent(e);
|
||||
}
|
||||
|
||||
void widgetMouseReleaseEvent(QMouseEvent *e) {
|
||||
//printf("*** mouseRelease %d %d %d\n", e->x(), e->y(), t.elapsed());
|
||||
// mechanism for avoiding unintended zooms:
|
||||
// do not allow if the rectangle is too small
|
||||
// or if the mouse was pressed for less than 200 ms
|
||||
doZoom = abs(e->x() - xp) + abs(e->y() - yp) > 2 && t.elapsed() > 200;
|
||||
QwtPlotZoomer::widgetMouseReleaseEvent(e);
|
||||
if (!doZoom && !displayMarker && setMark) {
|
||||
QwtDoublePoint p = invTransform(e->pos());
|
||||
pl->set->setMarker(p.x());
|
||||
}
|
||||
}
|
||||
|
||||
void widgetMouseDoubleClickEvent(QMouseEvent *e) {
|
||||
//printf("*** mouseDoubleClick %d %d %d\n", e->x(), e->y(), t.elapsed());
|
||||
setMark = true;
|
||||
pl->set->markerFix = true;
|
||||
QwtDoublePoint at =invTransform(e->pos());
|
||||
//pl->set->gotoTime(at.x(), FALSE);
|
||||
}
|
||||
|
||||
void widgetMouseMoveEvent(QMouseEvent *e) {
|
||||
if (displayMarker) {
|
||||
QwtDoublePoint p = invTransform(e->pos());
|
||||
if (!pl->set->markerFix) {
|
||||
pl->set->setMarker(p.x());
|
||||
pl->set->gotoTime(p.x(), TRUE);
|
||||
}
|
||||
} else {
|
||||
QwtPlotZoomer::widgetMouseMoveEvent(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SeaCurve::SeaCurve(QwtPlot *parent, const QString &title) : QwtPlotCurve(parent, title) {
|
||||
leg = NULL;
|
||||
iColor = -1;
|
||||
};
|
||||
|
||||
void SeaCurve::draw(QPainter *p, const QwtDiMap &xMap, const QwtDiMap &yMap,
|
||||
int from, int to) {
|
||||
int i, start;
|
||||
double ylowlim;
|
||||
|
||||
if (leg->plot->logarithmic) {
|
||||
ylowlim = 1e-30;
|
||||
} else {
|
||||
ylowlim = DATA_UNDEF;
|
||||
}
|
||||
start = -1;
|
||||
if (to < 0) {
|
||||
to = dataSize() - 1;
|
||||
if (to < 0) return;
|
||||
}
|
||||
for (i=from; i<=to; i++) {
|
||||
if (i > 0 && y(i) <= ylowlim) { /* undefined value */
|
||||
if (start >= 0) {
|
||||
QwtPlotCurve::draw(p, xMap, yMap, start, i-1);
|
||||
start = -1;
|
||||
}
|
||||
} else {
|
||||
if (start < 0) start = i;
|
||||
}
|
||||
}
|
||||
if (start >= 0) {
|
||||
QwtPlotCurve::draw(p, xMap, yMap, start, to);
|
||||
}
|
||||
};
|
||||
|
||||
void SeaCurve::setPen(const QPen &p) {
|
||||
QwtCurve::setPen(p);
|
||||
if (leg) leg->setCurvePen(p);
|
||||
};
|
||||
|
||||
void SeaCurve::setTitle(const QString &t) {
|
||||
QwtCurve::setTitle(t);
|
||||
if (leg) leg->setTitle(t);
|
||||
};
|
||||
|
||||
void SeaCurve::yBounds(double from, double to, double &ymin, double &ymax) {
|
||||
int i, n = dataSize();
|
||||
double y1, y2;
|
||||
double ya, yb, yc, yd, yi;
|
||||
int k, n1, n2, nn;
|
||||
bool done;
|
||||
double ylowlim;
|
||||
|
||||
// implementing a mechanism to ignore spikes:
|
||||
// after the first pass, the whole range is divided into 3 ranges.
|
||||
// in the next pass, only the points in the middle range are taken into account
|
||||
// for minimum and maximum, the others are counted only. When the number of points
|
||||
// in the upper or in the lower part are less than 2 %, the range is reduced by
|
||||
// the upper and/or the lower part and a next pass is done
|
||||
|
||||
if (leg->plot->logarithmic) {
|
||||
ylowlim = 1e-30;
|
||||
} else {
|
||||
ylowlim = DATA_UNDEF;
|
||||
}
|
||||
y1 = 1e30;
|
||||
y2 = -1e30;
|
||||
ya = -1e30;
|
||||
yb = -1e30;
|
||||
yc = 1e30;
|
||||
yd = 1e30;
|
||||
k = 0;
|
||||
yi = 1e30;
|
||||
while (1) {
|
||||
n1 = 0;
|
||||
n2 = 0;
|
||||
nn = 0;
|
||||
for (i=0; i<n; i++) {
|
||||
if (x(i)>= from) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; i<n; i++) {
|
||||
if (x(i) > to) {
|
||||
break;
|
||||
}
|
||||
yi = y(i);
|
||||
if (yi > ylowlim) { // and therefore yi != DATA_UNDEF
|
||||
if (yi < yb) {
|
||||
n1++;
|
||||
} else if (yi > yc) {
|
||||
n2++;
|
||||
} else {
|
||||
nn++;
|
||||
if (yi > y2) {
|
||||
y2 = yi;
|
||||
}
|
||||
if (yi < y1) {
|
||||
y1 = yi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == n && yi > ylowlim) {
|
||||
if (yi < y1) y1 = yi;
|
||||
if (yi > y2) y2 = yi;
|
||||
}
|
||||
if (k == 0) {
|
||||
ya = y1;
|
||||
yd = y2;
|
||||
} else {
|
||||
done = true;
|
||||
if (n1 * 49 < nn + n2 && y1 >= yb) {
|
||||
ya = y1;
|
||||
done = false;
|
||||
}
|
||||
if (n2 * 49 < nn + n1 && y2 <= yc) {
|
||||
yd = y2;
|
||||
done = false;
|
||||
}
|
||||
if (done || k > 20 || ya == yd) {
|
||||
break;
|
||||
}
|
||||
//printf("%s %d %d %d %d %f %f\n", data->label.latin1(), k, n1, n2, nn, ya, yd);
|
||||
}
|
||||
k++;
|
||||
yb = ya + (yd - ya) / 3;
|
||||
yc = yd - (yd - ya) / 3;
|
||||
y1 = yc;
|
||||
y2 = yb;
|
||||
}
|
||||
if (yi < 0.9e30) {
|
||||
ymin = QMIN(ymin, ya);
|
||||
ymax = QMAX(ymax, yd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void SeaCurve::changeBold() {
|
||||
int i;
|
||||
if (iColor == -1) {
|
||||
i = Convert2ColorIndex("black");
|
||||
} else {
|
||||
i = iColor;
|
||||
}
|
||||
leg->plot->set->saveBoldState(data);
|
||||
if (data->bold) {
|
||||
setPen(thisPen(i, 0));
|
||||
QToolTip::add(leg, "hide curve (long click: show this curve only)");
|
||||
QToolTip::add(leg->label, "hide curve (long click: show this curve only)");
|
||||
} else {
|
||||
setPen(thisPen(i, 1));
|
||||
QToolTip::add(leg, "show curve (long click: this curve only)");
|
||||
QToolTip::add(leg->label, "show curve (long click: this curve only)");
|
||||
}
|
||||
}
|
||||
|
||||
SeaPlot::SeaPlot(QWidget *p, SeaSet *set, const QString &name) : QwtPlot(p, name) {
|
||||
QTime now(QTime::currentTime());
|
||||
QTime midnight(0,0,0);
|
||||
double dnow;
|
||||
|
||||
//setAutoLegend( TRUE );
|
||||
//setLegendPosition( QwtPlot::Left , 0.5);
|
||||
this->set = set;
|
||||
|
||||
dnow = midnight.secsTo(now);
|
||||
setAxisScale(QwtPlot::xBottom, dnow-1800, dnow+600, 300.0);
|
||||
setAxisScale(QwtPlot::yLeft, 0.0, 0.9999);
|
||||
setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw(set));
|
||||
setAxisScaleDraw(QwtPlot::yLeft, new YScaleDraw(set));
|
||||
setAxisLabelFormat(QwtPlot::yLeft, 'g', 5);
|
||||
zoom = new SeaZoomer(this);
|
||||
zoom->setRubberBand(QwtPlotZoomer::RectRubberBand);
|
||||
zoom->setRubberBandPen(QPen(Qt::red));
|
||||
plotLayout()->setCanvasMargin(0, SeaPlot::yLeft);
|
||||
plotLayout()->setCanvasMargin(0, SeaPlot::yRight);
|
||||
canvas()->setPaletteBackgroundColor(QColor(238,238,238));
|
||||
setGridPen(QPen(QColor(221, 221, 221), 1));
|
||||
logarithmic = false;
|
||||
removeAll();
|
||||
};
|
||||
|
||||
void SeaPlot::removeAll() {
|
||||
tag = "";
|
||||
removeCurves();
|
||||
marker = insertCurve("Marker");
|
||||
// setCurvePen(marker, QPen(Qt::white, 3));
|
||||
setCurvePen(marker, QPen(Qt::black, 1));
|
||||
}
|
||||
|
||||
void SeaPlot::setMarker(double x) {
|
||||
const QwtScaleDiv *s = axisScale(yLeft);
|
||||
double xval[2], yval[2], h;
|
||||
SeaCurve *crv;
|
||||
QwtPlotCurveIterator itc = curveIterator();
|
||||
|
||||
if (x == DATA_UNDEF) {
|
||||
zoom->disableMarker();
|
||||
xval[0] = DATA_UNDEF;
|
||||
xval[1] = DATA_UNDEF;
|
||||
} else {
|
||||
zoom->enableMarker();
|
||||
xval[0] = x;
|
||||
xval[1] = x;
|
||||
}
|
||||
h = s->hBound() - s->lBound();
|
||||
if (logarithmic) {
|
||||
yval[0] = s->lBound() * 0.5;
|
||||
} else {
|
||||
yval[0] = s->lBound() - h;
|
||||
}
|
||||
yval[1] = s->hBound() + h;
|
||||
setCurveData(marker, xval, yval, 2);
|
||||
|
||||
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
|
||||
crv = dynamic_cast<SeaCurve *>(c);
|
||||
if (crv) {
|
||||
crv->data->showValueAt(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SeaPlot::refresh() {
|
||||
const QwtScaleDiv *s = axisScale(xBottom);
|
||||
replotRange(s->lBound(), s->hBound(), s->majStep());
|
||||
};
|
||||
|
||||
void SeaPlot::autoColors() {
|
||||
SeaCurve *crv;
|
||||
QwtPlotCurveIterator itc = curveIterator();
|
||||
int i;
|
||||
|
||||
usedColors.fill(false, N_SEACOLORS);
|
||||
usedColors.setBit(0); // do not use white
|
||||
|
||||
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
|
||||
crv = dynamic_cast<SeaCurve *>(c);
|
||||
if (crv) {
|
||||
if (crv->iColor >= 0 && crv->iColor < N_SEACOLORS) {
|
||||
usedColors.setBit(crv->iColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i=0;
|
||||
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
|
||||
crv = dynamic_cast<SeaCurve *>(c);
|
||||
if (crv) {
|
||||
if (crv->iColor < 0) {
|
||||
while (i < N_SEACOLORS && usedColors.at(i)) {
|
||||
i++;
|
||||
}
|
||||
if (i >= N_SEACOLORS) {
|
||||
crv->iColor = Convert2ColorIndex("black");
|
||||
} else {
|
||||
crv->iColor = i;
|
||||
usedColors.setBit(i);
|
||||
crv->changeBold();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LegendButton *SeaPlot::putCurve(SeaData *d, QWidget *parent, LegendButton *legButton) {
|
||||
SeaCurve *crv = new SeaCurve(this, d->label);
|
||||
|
||||
d->plot = this;
|
||||
d->key = insertCurve(crv);
|
||||
|
||||
if (legButton) {
|
||||
legButton->init(this, crv);
|
||||
} else {
|
||||
legButton = new LegendButton(parent, this, crv);
|
||||
}
|
||||
legButton->setTitle(d->label);
|
||||
|
||||
//QFont myfont(legButton->font());
|
||||
//myfont.setPointSize(12);
|
||||
//legButton->setFont(myfont);
|
||||
//legButton->setFixedHeight(legButton->fontMetrics().height()+2);
|
||||
|
||||
crv->leg = legButton;
|
||||
//crv->leg->setTitle(crv->title());
|
||||
//crv->leg->setTitle("");
|
||||
//if (d->style >= 0 && d->style <= N_SEACOLORS) {
|
||||
if (d->style >= 0) {
|
||||
crv->iColor = d->style;
|
||||
crv->autoColor = false;
|
||||
} else {
|
||||
crv->iColor = -1;
|
||||
crv->autoColor = true;
|
||||
}
|
||||
crv->data = d;
|
||||
crv->changeBold();
|
||||
crv->setStyle(QwtCurve::Lines);
|
||||
d->modified = true;
|
||||
d->update();
|
||||
return legButton;
|
||||
}
|
||||
|
||||
void SeaPlot::showAgain() {
|
||||
SeaCurve *crv;
|
||||
QwtPlotCurveIterator itc = curveIterator();
|
||||
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
|
||||
crv = dynamic_cast<SeaCurve *>(c);
|
||||
if (crv) {
|
||||
crv->data->bold = true;
|
||||
crv->changeBold();
|
||||
}
|
||||
}
|
||||
autoColors();
|
||||
//refresh();
|
||||
set->replotAnyway();
|
||||
}
|
||||
|
||||
bool SeaPlot::toggleLinLog() {
|
||||
logarithmic = ! logarithmic;
|
||||
if (logarithmic) {
|
||||
setAxisOptions(QwtPlot::yLeft, QwtAutoScale::Logarithmic);
|
||||
} else {
|
||||
setAxisOptions(QwtPlot::yLeft, QwtAutoScale::None);
|
||||
}
|
||||
refresh();
|
||||
return logarithmic;
|
||||
}
|
||||
|
||||
void SeaPlot::zoomMax() {
|
||||
autoZoom(true);
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SeaPlot::autoZoom(bool on) {
|
||||
zoom->yAuto = on;
|
||||
setAutoOff(!on);
|
||||
}
|
||||
|
||||
void SeaPlot::undoZoom(QwtDoubleRect &r) {
|
||||
setAxisScale(QwtPlot::yLeft, r.y1(), r.y2());
|
||||
zoom->setZoomBase();
|
||||
}
|
||||
|
||||
void SeaPlot::zoomTo(QwtDoubleRect old, QwtDoubleRect &r) {
|
||||
set->saveRange(this, old, zoom->yAuto);
|
||||
autoZoom(false);
|
||||
setAxisScale(QwtPlot::yLeft, r.y1(), r.y2());
|
||||
set->rescale(r.x1(), r.x2());
|
||||
zoom->setZoomBase();
|
||||
}
|
||||
|
||||
void SeaPlot::zoomOut() {
|
||||
QwtDoubleRect r = zoom->zoomRect();
|
||||
QwtDoubleRect old= zoom->scaleRect();
|
||||
|
||||
set->saveRange(this, old, zoom->yAuto);
|
||||
if (logarithmic) {
|
||||
double h = log(r.y2()) - log(r.y1());
|
||||
r.setY2(exp(log(r.y2()) + h / 2));
|
||||
r.setY1(exp(log(r.y1()) - h / 2));
|
||||
} else {
|
||||
double h = r.y2() - r.y1();
|
||||
r.setY2(r.y2() + h / 2);
|
||||
r.setY1(r.y1() - h / 2);
|
||||
}
|
||||
zoom->setZoomBase(r);
|
||||
zoom->zoom(0);
|
||||
autoZoom(false);
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SeaPlot::shiftUp() {
|
||||
QwtDoubleRect r = zoom->zoomRect();
|
||||
double h = (r.y2() - r.y1()) * 0.5;
|
||||
QwtDoubleRect old= zoom->scaleRect();
|
||||
|
||||
set->saveRange(this, old, zoom->yAuto);
|
||||
r.setY2(r.y2() + h);
|
||||
r.setY1(r.y1() + h);
|
||||
zoom->setZoomBase(r);
|
||||
zoom->zoom(r);
|
||||
zoom->setZoomBase();
|
||||
zoom->zoom(0);
|
||||
autoZoom(false);
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SeaPlot::shiftDown() {
|
||||
QwtDoubleRect r = zoom->zoomRect();
|
||||
double h = (r.y2() - r.y1()) * 0.5;
|
||||
QwtDoubleRect old= zoom->scaleRect();
|
||||
|
||||
set->saveRange(this, old, zoom->yAuto);
|
||||
r.setY2(r.y2() - h);
|
||||
r.setY1(r.y1() - h);
|
||||
zoom->setZoomBase(r);
|
||||
zoom->zoom(r);
|
||||
zoom->setZoomBase();
|
||||
zoom->zoom(0);
|
||||
autoZoom(false);
|
||||
refresh();
|
||||
}
|
||||
|
||||
int SeaPlot::replotRange(double from, double to, double tick) {
|
||||
SeaCurve *crv;
|
||||
QwtDoubleRect r;
|
||||
double ymin, ymax, yminA, ymaxA, y0, res;
|
||||
int result;
|
||||
bool nobold;
|
||||
|
||||
result = 1;
|
||||
ymin = 1e30;
|
||||
ymax = -1e30;
|
||||
yminA = ymin;
|
||||
ymaxA = ymax;
|
||||
nobold = true;
|
||||
QwtPlotCurveIterator itc = curveIterator();
|
||||
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
|
||||
crv = dynamic_cast<SeaCurve *>(c);
|
||||
if (crv) {
|
||||
crv->yBounds(from, to, yminA, ymaxA);
|
||||
if (crv->data->bold) {
|
||||
crv->yBounds(from, to, ymin, ymax);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ymin > ymax) {
|
||||
ymin = yminA;
|
||||
ymax = ymaxA;
|
||||
if (ymin > ymax) {
|
||||
ymin = 0;
|
||||
ymax = 1;
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
r = zoom->zoomRect();
|
||||
if (zoom->yAuto) {
|
||||
res = 0.1;
|
||||
} else {
|
||||
ymin = r.y1();
|
||||
ymax = r.y2();
|
||||
res = SEA_RESOLUTION;
|
||||
}
|
||||
if (logarithmic) {
|
||||
if (ymax <= 0) {
|
||||
ymax = ymaxA;
|
||||
ymin = yminA;
|
||||
} else if (ymin <= 0) {
|
||||
ymin = QMIN(ymax, yminA);
|
||||
}
|
||||
y0 = (log(ymin) + log(ymax)) / 2;
|
||||
if ((log(ymax) - log(ymin)) < res) {
|
||||
ymin = exp(y0 - res * 0.4999);
|
||||
ymax = exp(y0 + res * 0.5);
|
||||
}
|
||||
} else {
|
||||
y0 = (ymin + ymax) / 2;
|
||||
if ((ymax - ymin) < y0 * res) {
|
||||
ymin = y0 * (1 - res * 0.4999);
|
||||
ymax = y0 * (1 + res * 0.5);
|
||||
}
|
||||
}
|
||||
setAxisMaxMinor(QwtPlot::xBottom, 0);
|
||||
setAxisScale(QwtPlot::xBottom, from, to, tick);
|
||||
setAxisScale(QwtPlot::yLeft, ymin, ymax);
|
||||
replot();
|
||||
if (zoom->zoomRectIndex() == 0) {
|
||||
zoom->setZoomBase();
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
int SeaPlot::replotRange() {
|
||||
const QwtScaleDiv *scx = axisScale(QwtPlot::xBottom);
|
||||
return replotRange(scx->lBound(), scx->hBound(), scx->majStep());
|
||||
};
|
||||
|
||||
void SeaPlot::switchBold(SeaCurve *crv) {
|
||||
crv->data->bold = !crv->data->bold;
|
||||
crv->changeBold();
|
||||
crv->leg->update();
|
||||
set->replotAnyway();
|
||||
set->updateCurveList();
|
||||
}
|
||||
|
||||
void SeaPlot::setOneBold(SeaCurve *selectedCrv) {
|
||||
QwtPlotCurveIterator itc = curveIterator();
|
||||
SeaCurve *crv;
|
||||
|
||||
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
|
||||
crv = dynamic_cast<SeaCurve *>(c);
|
||||
if (crv) { // omit Marker
|
||||
crv->data->bold = crv == selectedCrv;
|
||||
crv->changeBold();
|
||||
crv->leg->update();
|
||||
}
|
||||
}
|
||||
autoZoom(true);
|
||||
set->replotAnyway();
|
||||
set->updateCurveList();
|
||||
}
|
||||
|
Reference in New Issue
Block a user