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.; mdm = 10.;
visible_time = -1.; visible_time = -1.;
pause_phase = 0.; pause_phase = 0.;
selrect.setRect(0., 0., 1., 1.); def_rect.setRect(0., 0., 1., 1.);
def_rect = selrect; selrect = def_rect;
margins_.setRect(4, 4, 4, 4); margins_.setRect(4, 4, 4, 4);
curaction = gaMove; curaction = gaMove;
selbrush.setStyle(Qt::SolidPattern); selbrush.setStyle(Qt::SolidPattern);
@@ -457,6 +457,7 @@ void Graphic::clear() {
graphics[i].polyline.clear(); graphics[i].polyline.clear();
graphics[i].polyline_pause.clear(); graphics[i].polyline_pause.clear();
graphics[i].max_x = 0.; graphics[i].max_x = 0.;
graphics[i].cvrect = QRectF();
} }
on_buttonAutofit_clicked(); on_buttonAutofit_clicked();
} }
@@ -487,6 +488,7 @@ void Graphic::setPaused(bool yes) {
graphics[i].polyline_pause = graphics[i].polyline; graphics[i].polyline_pause = graphics[i].polyline;
graphics[i].polyline_pause.detach(); graphics[i].polyline_pause.detach();
graphics[i].max_x_pause = graphics[i].max_x; graphics[i].max_x_pause = graphics[i].max_x;
graphics[i].cvrect = QRectF();
} }
timer_pause = startTimer(40); timer_pause = startTimer(40);
} }
@@ -498,6 +500,7 @@ void Graphic::setHistorySize(double val) {
for (int i = 0; i < graphics.size(); ++i) { for (int i = 0; i < graphics.size(); ++i) {
QPolygonF & pol(graphics[i].polyline); QPolygonF & pol(graphics[i].polyline);
if (pol.isEmpty() || history <= 0.) continue; if (pol.isEmpty() || history <= 0.) continue;
graphics[i].cvrect = QRectF();
x = pol.back().x() - history; x = pol.back().x() - history;
for (int j = pol.size() - 2; j >= 0 ; --j) for (int j = pol.size() - 2; j >= 0 ; --j)
if (pol[j].x() < x) { 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_) { void Graphic::addPoint(const QPointF & p, int graphic, bool update_) {
if (graphic >= graphics.size() || graphic < 0) return; if (graphic >= graphics.size() || graphic < 0) return;
if (graphics.at(graphic).polyline.size() == 0) graphics[graphic].max_x = p.x(); GraphicType & t(graphics[graphic]);
graphics[graphic].polyline << p; if (!t.cvrect.isNull()) {
if (graphics.at(graphic).max_x < p.x()) graphics[graphic].max_x = p.x(); // 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_); tick(graphic, true, update_);
} }
void Graphic::setGraphicData(const QVector<QPointF> & g, int graphic, bool update_) { void Graphic::setGraphicData(const QVector<QPointF> & g, int graphic, bool update_) {
if (graphic >= graphics.size() || graphic < 0) return; if (graphic >= graphics.size() || graphic < 0) return;
graphics[graphic].polyline.clear(); GraphicType & t(graphics[graphic]);
graphics[graphic].polyline = g; t.cvrect = QRectF();
if (graphics.at(graphic).polyline.size() == 0) { t.polyline.clear();
graphics[graphic].max_x = 0.; t.polyline = g;
if (t.polyline.size() == 0) {
t.max_x = 0.;
tick(graphic, false, update_); tick(graphic, false, update_);
return; return;
} }
graphics[graphic].max_x = graphics.at(graphic).polyline[0].x(); t.max_x = t.polyline[0].x();
for (int i = 1; i < graphics.at(graphic).polyline.size(); ++i) for (int i = 1; i < t.polyline.size(); ++i)
if (graphics.at(graphic).max_x < graphics.at(graphic).polyline[i].x()) if (t.max_x < t.polyline[i].x())
graphics[graphic].max_x = graphics.at(graphic).polyline[i].x(); t.max_x = t.polyline[i].x();
tick(graphic, false, update_); 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(); graphics[graphic].polyline.clear();
if (g.isEmpty()) { if (g.isEmpty()) {
return; return;
@@ -739,25 +753,29 @@ void Graphic::setHistogramData(const QVector<float> & g, int graphic) {
cpol << QPointF(range + min, 0.); cpol << QPointF(range + min, 0.);
} }
updateGraphics(); updateGraphics();
} }*/
void Graphic::findGraphicsRect(double start_x, double end_x, double start_y, double end_y) { 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 isRangeX = (start_x != end_x), isRangeY = (start_y != end_y);
bool isEmpty = true, anyVisible = false, isTimeLimit = (visible_time > 0.) && !(isRangeX || isRangeY); // bool isEmpty = true;
foreach (const GraphicType & t, graphics) { bool fast = true, can_fast = (start_x == 0 && end_x == 0 && start_y == 0 && end_y == 0);
const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline); bool anyVisible = false, isTimeLimit = (visible_time > 0.) && !(isRangeX || isRangeY);
if (!pol.isEmpty()) { // foreach (const GraphicType & t, graphics) {
isEmpty = false; // const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline);
break; // if (!pol.isEmpty()) {
} // isEmpty = false;
} // break;
if (isEmpty) { // }
grect = def_rect; // }
setRectToLines(); // if (isEmpty) {
return; // grect = def_rect;
} // setRectToLines();
// return;
// }
// can_fast = false;
vx = DBL_MIN;
minY = minX = DBL_MAX; minY = minX = DBL_MAX;
maxY = maxX = -DBL_MAX; maxY = maxX = -DBL_MAX;
foreach (const GraphicType & t, graphics) { 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); if (vx < (pause_ ? t.max_x_pause : t.max_x)) vx = (pause_ ? t.max_x_pause : t.max_x);
} }
vx -= visible_time; 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; if (!t.visible) continue;
const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline); const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline);
for (int i = 0; i < pol.size(); i++) { if (pol.isEmpty()) continue;
cx = pol[i].x(); bool f = true;
cy = pol[i].y(); //qDebug() << "[Graphic]" << "cvrect:" << t.cvrect << t.cvrect.isNull();
if ((start_x > cx || end_x < cx) && isRangeX) continue; if (t.cvrect.isNull() || !can_fast) {
if ((start_y > cy || end_y < cy) && isRangeY) continue; for (int i = 0; i < pol.size(); i++) {
if ((cx < vx) && isTimeLimit) continue; cx = pol[i].x();
if (maxY < cy) maxY = cy; cy = pol[i].y();
if (minY > cy) minY = cy; if ((start_x > cx || end_x < cx) && isRangeX) continue;
if (maxX < cx) maxX = cx; if ((start_y > cy || end_y < cy) && isRangeY) continue;
if (minX > cx) minX = cx; 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) { if (!anyVisible) {
grect.setRect(0., 0., 1., 1.); //qDebug() << "[Graphic]" << "empty autofit";
grect = def_rect;
setRectToLines(); setRectToLines();
return; return;
} }
// if (fast) qDebug() << "[Graphic]" << "FAST autofit";
// else qDebug() << "[Graphic]" << "autofit";
if (maxX > limit_.right()) maxX = limit_.right(); if (maxX > limit_.right()) maxX = limit_.right();
if (minX > limit_.right()) minX = limit_.right(); if (minX > limit_.right()) minX = limit_.right();
if (minX < limit_.left()) minX = limit_.left(); 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 (maxY < limit_.top()) maxY = limit_.top();
if (minX > maxX) qSwap<double>(minX, maxX); if (minX > maxX) qSwap<double>(minX, maxX);
if (minY > maxY) qSwap<double>(minY, maxY); if (minY > maxY) qSwap<double>(minY, maxY);
if (qAbs<double>(minX - maxX) < 1E-60) {minX -= 1E-20; maxX += 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 -= 1E-20; maxY += 1E-20;} if (qAbs<double>(minY - maxY) < 1E-60) {minY -= defaultRect().height()/2; maxY += defaultRect().height()/2;}
if (only_expand_x) { if (only_expand_x) {
if (minX > eminx) minX = eminx; if (minX > eminx) minX = eminx;
if (maxX < emaxx) maxX = emaxx; if (maxX < emaxx) maxX = emaxx;
@@ -1279,6 +1320,12 @@ void Graphic::tick(int index, bool slide, bool update_) {
if (history > 0.) if (history > 0.)
while (t.polyline.size() > 1) { while (t.polyline.size() > 1) {
if (fabs(t.polyline.back().x() - t.polyline.front().x()) <= history) break; 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(); t.polyline.pop_front();
} }
} }
@@ -1530,7 +1577,7 @@ QByteArray Graphic::save() {
void Graphic::load(QByteArray ba) { void Graphic::load(QByteArray ba) {
if (ba.isEmpty()) return; if (ba.isEmpty()) return;
char ver = ba[0]; char ver = ba[0];
qDebug() << "load" << (int)ver; //qDebug() << "load" << (int)ver;
switch(ver) { switch(ver) {
case '2': {// version '2': case '2': {// version '2':
ba.remove(0, 1); 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];} GraphicType graphic(int arg) {if (arg < 0 || arg >= graphics.size()) return GraphicType(); return graphics[arg];}
const QVector<GraphicType> & allGraphics() const {return graphics;} const QVector<GraphicType> & allGraphics() const {return graphics;}
void setAllGraphics(const QVector<GraphicType> & g, bool update = true) {graphics = g; if (update) updateLegend();} 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, int graphic);
void setHistogramData(const QVector<float> & g) {setHistogramData(g, curGraphic);} // void setHistogramData(const QVector<float> & g) {setHistogramData(g, curGraphic);}
double canvas2realX(double px) const; double canvas2realX(double px) const;
double canvas2realY(double py) const; double canvas2realY(double py) const;

View File

@@ -45,6 +45,7 @@ struct GraphicType {
QCheckBox * pb; QCheckBox * pb;
QIcon icon; QIcon icon;
bool visible; bool visible;
QRectF cvrect;
}; };