Graphic fast autofit for addPoint

git-svn-id: svn://db.shs.com.ru/libs@347 a8b55f48-bf90-11e4-a774-851b48703e85
This commit is contained in:
2018-01-18 14:11:48 +00:00
parent 7a3f3a928e
commit efca49fb72
3 changed files with 96 additions and 48 deletions

View File

@@ -94,8 +94,8 @@ Graphic::Graphic(QWidget * parent): QFrame(parent), line_x_min(this), line_x_max
mdm = 10.;
visible_time = -1.;
pause_phase = 0.;
selrect.setRect(0., 0., 1., 1.);
def_rect = selrect;
def_rect.setRect(0., 0., 1., 1.);
selrect = def_rect;
margins_.setRect(4, 4, 4, 4);
curaction = gaMove;
selbrush.setStyle(Qt::SolidPattern);
@@ -457,6 +457,7 @@ void Graphic::clear() {
graphics[i].polyline.clear();
graphics[i].polyline_pause.clear();
graphics[i].max_x = 0.;
graphics[i].cvrect = QRectF();
}
on_buttonAutofit_clicked();
}
@@ -487,6 +488,7 @@ void Graphic::setPaused(bool yes) {
graphics[i].polyline_pause = graphics[i].polyline;
graphics[i].polyline_pause.detach();
graphics[i].max_x_pause = graphics[i].max_x;
graphics[i].cvrect = QRectF();
}
timer_pause = startTimer(40);
}
@@ -498,6 +500,7 @@ void Graphic::setHistorySize(double val) {
for (int i = 0; i < graphics.size(); ++i) {
QPolygonF & pol(graphics[i].polyline);
if (pol.isEmpty() || history <= 0.) continue;
graphics[i].cvrect = QRectF();
x = pol.back().x() - history;
for (int j = pol.size() - 2; j >= 0 ; --j)
if (pol[j].x() < x) {
@@ -585,26 +588,37 @@ void Graphic::setButtonsPosition(Graphic::Alignment a) {
void Graphic::addPoint(const QPointF & p, int graphic, bool update_) {
if (graphic >= graphics.size() || graphic < 0) return;
if (graphics.at(graphic).polyline.size() == 0) graphics[graphic].max_x = p.x();
graphics[graphic].polyline << p;
if (graphics.at(graphic).max_x < p.x()) graphics[graphic].max_x = p.x();
GraphicType & t(graphics[graphic]);
if (!t.cvrect.isNull()) {
// if (graphics[graphic].cvrect.contains(p))
// graphics[graphic].cvrect = QRectF();
if (t.cvrect.top() < p.y()) t.cvrect.setTop(p.y());
if (t.cvrect.bottom() > p.y()) t.cvrect.setBottom(p.y());
if (t.cvrect.right() < p.x()) t.cvrect.setRight(p.x());
if (t.cvrect.left() > p.x()) t.cvrect.setLeft(p.x());
}
if (t.polyline.size() == 0) t.max_x = p.x();
t.polyline << p;
if (t.max_x < p.x()) t.max_x = p.x();
tick(graphic, true, update_);
}
void Graphic::setGraphicData(const QVector<QPointF> & g, int graphic, bool update_) {
if (graphic >= graphics.size() || graphic < 0) return;
graphics[graphic].polyline.clear();
graphics[graphic].polyline = g;
if (graphics.at(graphic).polyline.size() == 0) {
graphics[graphic].max_x = 0.;
GraphicType & t(graphics[graphic]);
t.cvrect = QRectF();
t.polyline.clear();
t.polyline = g;
if (t.polyline.size() == 0) {
t.max_x = 0.;
tick(graphic, false, update_);
return;
}
graphics[graphic].max_x = graphics.at(graphic).polyline[0].x();
for (int i = 1; i < graphics.at(graphic).polyline.size(); ++i)
if (graphics.at(graphic).max_x < graphics.at(graphic).polyline[i].x())
graphics[graphic].max_x = graphics.at(graphic).polyline[i].x();
t.max_x = t.polyline[0].x();
for (int i = 1; i < t.polyline.size(); ++i)
if (t.max_x < t.polyline[i].x())
t.max_x = t.polyline[i].x();
tick(graphic, false, update_);
}
@@ -694,7 +708,7 @@ void Graphic::setGraphicsCount(int arg, bool update) {
}
void Graphic::setHistogramData(const QVector<float> & g, int graphic) {
/*void Graphic::setHistogramData(const QVector<float> & g, int graphic) {
graphics[graphic].polyline.clear();
if (g.isEmpty()) {
return;
@@ -739,25 +753,29 @@ void Graphic::setHistogramData(const QVector<float> & g, int graphic) {
cpol << QPointF(range + min, 0.);
}
updateGraphics();
}
}*/
void Graphic::findGraphicsRect(double start_x, double end_x, double start_y, double end_y) {
double cx, cy, maxX, minX, maxY, minY, vx = DBL_MIN;
double cx, cy, maxX, minX, maxY, minY, vx;
bool isRangeX = (start_x != end_x), isRangeY = (start_y != end_y);
bool isEmpty = true, anyVisible = false, isTimeLimit = (visible_time > 0.) && !(isRangeX || isRangeY);
foreach (const GraphicType & t, graphics) {
const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline);
if (!pol.isEmpty()) {
isEmpty = false;
break;
}
}
if (isEmpty) {
grect = def_rect;
setRectToLines();
return;
}
// bool isEmpty = true;
bool fast = true, can_fast = (start_x == 0 && end_x == 0 && start_y == 0 && end_y == 0);
bool anyVisible = false, isTimeLimit = (visible_time > 0.) && !(isRangeX || isRangeY);
// foreach (const GraphicType & t, graphics) {
// const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline);
// if (!pol.isEmpty()) {
// isEmpty = false;
// break;
// }
// }
// if (isEmpty) {
// grect = def_rect;
// setRectToLines();
// return;
// }
// can_fast = false;
vx = DBL_MIN;
minY = minX = DBL_MAX;
maxY = maxX = -DBL_MAX;
foreach (const GraphicType & t, graphics) {
@@ -765,27 +783,50 @@ void Graphic::findGraphicsRect(double start_x, double end_x, double start_y, dou
if (vx < (pause_ ? t.max_x_pause : t.max_x)) vx = (pause_ ? t.max_x_pause : t.max_x);
}
vx -= visible_time;
foreach (const GraphicType & t, graphics) {
// qDebug() << "[Graphic]" << "can_fast" << can_fast;
for (int g = 0; g < graphics.size(); g++) {
GraphicType & t(graphics[g]);
if (!t.visible) continue;
const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline);
for (int i = 0; i < pol.size(); i++) {
cx = pol[i].x();
cy = pol[i].y();
if ((start_x > cx || end_x < cx) && isRangeX) continue;
if ((start_y > cy || end_y < cy) && isRangeY) continue;
if ((cx < vx) && isTimeLimit) continue;
if (maxY < cy) maxY = cy;
if (minY > cy) minY = cy;
if (maxX < cx) maxX = cx;
if (minX > cx) minX = cx;
if (pol.isEmpty()) continue;
bool f = true;
//qDebug() << "[Graphic]" << "cvrect:" << t.cvrect << t.cvrect.isNull();
if (t.cvrect.isNull() || !can_fast) {
for (int i = 0; i < pol.size(); i++) {
cx = pol[i].x();
cy = pol[i].y();
if ((start_x > cx || end_x < cx) && isRangeX) continue;
if ((start_y > cy || end_y < cy) && isRangeY) continue;
if ((cx < vx) && isTimeLimit) continue;
if (f) {
t.cvrect.setRect(cx, cy, 0, 0);
f = false;
} else {
if (t.cvrect.top() < cy) t.cvrect.setTop(cy);
if (t.cvrect.bottom() > cy) t.cvrect.setBottom(cy);
if (t.cvrect.right() < cx) t.cvrect.setRight(cx);
if (t.cvrect.left() > cx) t.cvrect.setLeft(cx);
}
fast = false;
}
if (f) continue;
//qDebug() << "[Graphic]" << "2 cvrect:" << t.cvrect;
}
if (!pol.isEmpty()) anyVisible = true;
anyVisible = true;
if (maxY < t.cvrect.top()) maxY = t.cvrect.top();
if (minY > t.cvrect.bottom()) minY = t.cvrect.bottom();
if (maxX < t.cvrect.right()) maxX = t.cvrect.right();
if (minX > t.cvrect.left()) minX = t.cvrect.left();
if (!can_fast) t.cvrect = QRectF();
}
if (!anyVisible) {
grect.setRect(0., 0., 1., 1.);
//qDebug() << "[Graphic]" << "empty autofit";
grect = def_rect;
setRectToLines();
return;
}
// if (fast) qDebug() << "[Graphic]" << "FAST autofit";
// else qDebug() << "[Graphic]" << "autofit";
if (maxX > limit_.right()) maxX = limit_.right();
if (minX > limit_.right()) minX = limit_.right();
if (minX < limit_.left()) minX = limit_.left();
@@ -796,8 +837,8 @@ void Graphic::findGraphicsRect(double start_x, double end_x, double start_y, dou
if (maxY < limit_.top()) maxY = limit_.top();
if (minX > maxX) qSwap<double>(minX, maxX);
if (minY > maxY) qSwap<double>(minY, maxY);
if (qAbs<double>(minX - maxX) < 1E-60) {minX -= 1E-20; maxX += 1E-20;}
if (qAbs<double>(minY - maxY) < 1E-60) {minY -= 1E-20; maxY += 1E-20;}
if (qAbs<double>(minX - maxX) < 1E-60) {minX -= defaultRect().width()/2; maxX += defaultRect().width()/2;}
if (qAbs<double>(minY - maxY) < 1E-60) {minY -= defaultRect().height()/2; maxY += defaultRect().height()/2;}
if (only_expand_x) {
if (minX > eminx) minX = eminx;
if (maxX < emaxx) maxX = emaxx;
@@ -1279,6 +1320,12 @@ void Graphic::tick(int index, bool slide, bool update_) {
if (history > 0.)
while (t.polyline.size() > 1) {
if (fabs(t.polyline.back().x() - t.polyline.front().x()) <= history) break;
if (!t.cvrect.isNull()) {
if (!t.cvrect.contains(t.polyline.first())) {
/// TODO: [Graphic] add smart remove for fast autofit
t.cvrect = QRectF();
}
}
t.polyline.pop_front();
}
}
@@ -1530,7 +1577,7 @@ QByteArray Graphic::save() {
void Graphic::load(QByteArray ba) {
if (ba.isEmpty()) return;
char ver = ba[0];
qDebug() << "load" << (int)ver;
//qDebug() << "load" << (int)ver;
switch(ver) {
case '2': {// version '2':
ba.remove(0, 1);

View File

@@ -195,8 +195,8 @@ public:
GraphicType graphic(int arg) {if (arg < 0 || arg >= graphics.size()) return GraphicType(); return graphics[arg];}
const QVector<GraphicType> & allGraphics() const {return graphics;}
void setAllGraphics(const QVector<GraphicType> & g, bool update = true) {graphics = g; if (update) updateLegend();}
void setHistogramData(const QVector<float> & g, int graphic);
void setHistogramData(const QVector<float> & g) {setHistogramData(g, curGraphic);}
// void setHistogramData(const QVector<float> & g, int graphic);
// void setHistogramData(const QVector<float> & g) {setHistogramData(g, curGraphic);}
double canvas2realX(double px) const;
double canvas2realY(double py) const;

View File

@@ -45,6 +45,7 @@ struct GraphicType {
QCheckBox * pb;
QIcon icon;
bool visible;
QRectF cvrect;
};
@@ -71,7 +72,7 @@ public:
protected:
void changeEvent(QEvent * e);
Ui::GraphicConf * ui;
private slots: