From b14a48da6eb319a198e91ca53d7185e9d53ee5d6 Mon Sep 17 00:00:00 2001 From: peri4 Date: Thu, 11 Mar 2021 00:25:36 +0300 Subject: [PATCH] version 2.1.0_beta Graphic first LOD optimization try, now works only on setGraphicData --- CMakeLists.txt | 4 +- libs/graphic/graphic.cpp | 106 ++++++++++++++++++++++++++++-------- libs/graphic/graphic.h | 7 ++- libs/graphic/graphic.ui | 5 +- libs/graphic/graphic_conf.h | 2 + 5 files changed, 94 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3414dad..43884bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(qad) set(qad_MAJOR 2) -set(qad_MINOR 0) +set(qad_MINOR 1) set(qad_REVISION 0) -set(qad_SUFFIX alpha) +set(qad_SUFFIX beta) set(qad_COMPANY SHS) set(qad_DOMAIN org.SHS) diff --git a/libs/graphic/graphic.cpp b/libs/graphic/graphic.cpp index 0ead8d8..c18e689 100644 --- a/libs/graphic/graphic.cpp +++ b/libs/graphic/graphic.cpp @@ -117,7 +117,7 @@ Graphic::Graphic(QWidget * parent): QFrame(parent), canvas(0), line_x_min(this), icon_pause_f = QImage(":/icons/pause-front.png"); aupdate = grid = isFit = navigation = true; aalias = bufferActive = isOGL = cancel = guides = hasLblX = hasLblY = isHover = false; - pause_ = only_expand_x = only_expand_y = false; + pause_ = only_expand_x = only_expand_y = m_LODOptimization = false; limit_.setCoords(-DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX); eminx = eminy = DBL_MAX; emaxx = emaxy = DBL_MIN; @@ -150,6 +150,7 @@ Graphic::Graphic(QWidget * parent): QFrame(parent), canvas(0), line_x_min(this), setButtonsPosition(Graphic::Left); setAntialiasing(false); setCaption(""); + setBorderInputsVisible(false); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); ui->layoutButtons->update(); updateLegend(); @@ -583,6 +584,8 @@ void Graphic::clear() { for (int i = 0; i < graphics.size(); ++i) { graphics[i].polyline.clear(); graphics[i].polyline_pause.clear(); + graphics[i]._lod.clear(); + graphics[i]._lod_pause.clear(); graphics[i].max_x = 0.; graphics[i].cvrect = QRectF(); } @@ -613,6 +616,8 @@ void Graphic::setPaused(bool yes) { for (int i = 0; i < graphics.size(); ++i) { graphics[i].polyline_pause = graphics[i].polyline; graphics[i].polyline_pause.detach(); + graphics[i]._lod_pause = graphics[i]._lod; + graphics[i]._lod_pause.detach(); graphics[i].max_x_pause = graphics[i].max_x; } timer_pause = startTimer(40); @@ -1183,7 +1188,8 @@ void Graphic::drawGraphics() { ui->status->setText(tr("Cursor: ") + pointCoords(canvas2real(QPointF(curpos)))); QPointF srp = -selrect.topLeft(); double sclx, scly, wid = canvas->width(), hei = canvas->height(); - sclx = (wid - gridborder.x() - margins_.left() - margins_.width()) / selrect.width(); + int cwid = (wid - gridborder.x() - margins_.left() - margins_.width()); + sclx = cwid / selrect.width(); scly = (hei - gridborder.y() - margins_.top() - margins_.height()) / selrect.height(); painter->setClipping(true); painter->setClipRect(QRect(gridborder.x(), 0, wid - gridborder.x(), hei - gridborder.y())); @@ -1197,27 +1203,36 @@ void Graphic::drawGraphics() { QPen pen; for (int i = 0; i < graphics.size(); ++i) { GraphicType & t(graphics[i]); - QPolygonF & rpol(pause_ ? t.polyline_pause : t.polyline); - if (t.visible && !rpol.isEmpty()) { - pen = t.pen; - if (qRound(pen.widthF()) == pen.widthF()) pen.setWidth(pen.width()*thick); - else pen.setWidthF(pen.widthF()*thick); - pen.setCosmetic(true); - if (t.lines) { - painter->setPen(pen); - if (t.fill) { - cpol = rpol; - painter->setBrush(t.fill_color); - painter->drawPolygon(mat.map(cpol)); - } else - painter->drawPolyline(mat.map(rpol)); - } - if (t.points) { - if (qRound(t.pointWidth) == t.pointWidth) pen.setWidth(qRound(t.pointWidth*thick)); - else pen.setWidthF(t.pointWidth*thick); - painter->setPen(pen); - painter->drawPoints(mat.map(rpol)); - } + QPolygonF & src_pol(pause_ ? t.polyline_pause : t.polyline); + if (!t.visible || src_pol.isEmpty()) continue; + QVector & src_lod(pause_ ? t._lod_pause : t._lod); + int lod = 0; + if (m_LODOptimization) { + int gpcnt = src_pol.size(); + qreal range = src_pol.back().x() - src_pol.front().x(); + qreal ppp = (gpcnt * selrect.width() / qMax(range, 1.E-9) / cwid); + lod = qBound(0, qFloor(log2(ppp) - 2), src_lod.size()); + //qDebug() << "draw lod" << lod; + } + QPolygonF & rpol(lod == 0 ? src_pol : src_lod[lod - 1]); + pen = t.pen; + if (qRound(pen.widthF()) == pen.widthF()) pen.setWidth(pen.width()*thick); + else pen.setWidthF(pen.widthF()*thick); + pen.setCosmetic(true); + if (t.lines) { + painter->setPen(pen); + if (t.fill) { + cpol = rpol; + painter->setBrush(t.fill_color); + painter->drawPolygon(mat.map(cpol)); + } else + painter->drawPolyline(mat.map(rpol)); + } + if (t.points) { + if (qRound(t.pointWidth) == t.pointWidth) pen.setWidth(qRound(t.pointWidth*thick)); + else pen.setWidthF(t.pointWidth*thick); + painter->setPen(pen); + painter->drawPoints(mat.map(rpol)); } } painter->setWorldMatrixEnabled(true); @@ -1524,6 +1539,8 @@ void Graphic::tick(int index, bool slide, bool update_) { } t.polyline.pop_front(); } + } else { + calcLOD(index); } if (!update_) { if (isFit) findGraphicsRect(); @@ -1538,6 +1555,49 @@ void Graphic::tick(int index, bool slide, bool update_) { } +void Graphic::calcLOD(int index) { + if (!m_LODOptimization) return; + GraphicType & t(graphics[index]); + t._lod.clear(); + int pcnt = t.polyline.size(); + //qDebug() << "calcLOD" << index; + while (pcnt >= 10) { + QPolygonF & pl(t._lod.isEmpty() ? t.polyline : t._lod.back()); + t._lod.append(QPolygonF()); + QPolygonF & cl(t._lod.back()); + cl << pl.front(); + int qcnt = (pl.size() + 1) / 4; + pcnt = qcnt * 2 + 2; + int pc = 4; + qreal mx[2] = {0., 0.}, my[2] = {0., 0.}, my_x[2] = {0., 0.}, px, py; + for (int i = 0; i < qcnt; ++i) { + int j = i*4 + 1; + if (i == qcnt - 1) pc = pl.size() - j - 1; + mx[0] = mx[1] = my_x[0] = my_x[1] = pl[j].x(); my[0] = my[1] = pl[j].y(); + for (int k = 1; k < pc; ++k) { + px = pl[j + k].x(); py = pl[j + k].y(); + mx[0] = qMin(mx[0], px); mx[1] = qMax(mx[1], px); + if (my[0] > py) { + my[0] = py; + my_x[0] = px; + } + if (my[1] < py) { + my[1] = py; + my_x[1] = px; + } + } + qreal dx =(mx[1] - mx[0]) / 4., cx = (mx[1] + mx[0]) / 2.; + if (my_x[1] >= my_x[0]) + cl << QPointF(cx - dx, my[0]) << QPointF(cx + dx, my[1]); + else + cl << QPointF(cx - dx, my[1]) << QPointF(cx + dx, my[0]); + } + cl << pl.back(); + //qDebug() << "lod" << t._lod.size() << "->" << cl.size(); + } +} + + void Graphic::on_graphic_buttonAutofit_clicked() { isFit = true; bool isEmpty = true; diff --git a/libs/graphic/graphic.h b/libs/graphic/graphic.h index 64ececc..de6f86f 100644 --- a/libs/graphic/graphic.h +++ b/libs/graphic/graphic.h @@ -97,6 +97,7 @@ class QAD_GRAPHIC_EXPORT Graphic: public QFrame Q_PROPERTY(bool onlyExpandY READ onlyExpandY WRITE setOnlyExpandY) Q_PROPERTY(bool onlyExpandX READ onlyExpandX WRITE setOnlyExpandX) Q_PROPERTY(bool gesturesNavigation READ gesturesNavigation WRITE setGesturesNavigation) + Q_PROPERTY(bool LODOptimization READ LODOptimization WRITE setLODOptimization) Q_PROPERTY(double historySize READ historySize WRITE setHistorySize) Q_PROPERTY(double maxVisibleTime READ maxVisibleTime WRITE setMaxVisibleTime) Q_PROPERTY(double autoXIncrement READ autoXIncrement WRITE setAutoXIncrement) @@ -181,6 +182,7 @@ public: bool onlyExpandY() const {return only_expand_y;} bool onlyExpandX() const {return only_expand_x;} bool gesturesNavigation() const {return gestures;} + bool LODOptimization() const {return m_LODOptimization;} bool isAutofitted() const {return isFit;} int currentGraphic() const {return curGraphic;} int currentTraceGraphic() const {return curTrace;} @@ -262,6 +264,7 @@ public slots: void setSelectionPen(const QPen & pen) {selpen = pen;} void setSelectionBrush(const QBrush & brush) {selbrush = brush;} void setNavigationEnabled(bool on) {navigation = on;} + void setLODOptimization(bool yes) {m_LODOptimization = yes;} void setOpenGL(bool on); void setAntialiasing(bool enabled); void setAutoUpdate(bool enabled) {aupdate = enabled;} @@ -331,6 +334,7 @@ public slots: void zoomOut() {zoom(1.2);} void fullscreen(); + protected: virtual void changeEvent(QEvent * e); virtual void resizeEvent(QResizeEvent * ); @@ -345,6 +349,7 @@ protected: void setCurrentAction(GraphicAction action); void findGraphicsRect(double start_x = 0., double end_x = 0., double start_y = 0., double end_y = 0.); void tick(int index, bool slide = true, bool update = true); + void calcLOD(int index); void repaintCanvas(bool force = false) {if (tm.elapsed() < min_repaint_int && !force) return; tm.restart(); canvas->update();} void drawGraphics(); void drawGrid(); @@ -401,7 +406,7 @@ protected: double gridx, gridy, history, visible_time, inc_x, grid_numbers_x, grid_numbers_y, LN10; double eminx, eminy, emaxx, emaxy, pause_phase, gesture_angle; int lastw, lasth, min_repaint_int, timer_pause, thick; - bool aalias, aupdate, grid, guides, isFit, isOGL, isHover, bufferActive, cancel, pause_, gestures; + bool aalias, aupdate, grid, guides, isFit, isOGL, isHover, bufferActive, cancel, pause_, gestures, m_LODOptimization; bool hasLblX, hasLblY, navigation, only_expand_y, only_expand_x, is_lines_update, leg_update, visible_update, fullscr, need_mouse_pan; protected slots: diff --git a/libs/graphic/graphic.ui b/libs/graphic/graphic.ui index 7a3f710..db27bb1 100644 --- a/libs/graphic/graphic.ui +++ b/libs/graphic/graphic.ui @@ -49,7 +49,7 @@ -10 0 - 33 + 35 420 @@ -122,9 +122,6 @@ true - - true - diff --git a/libs/graphic/graphic_conf.h b/libs/graphic/graphic_conf.h index b88b3a7..b0014d6 100644 --- a/libs/graphic/graphic_conf.h +++ b/libs/graphic/graphic_conf.h @@ -54,6 +54,8 @@ struct QAD_GRAPHIC_EXPORT GraphicType { QString name; QPolygonF polyline; QPolygonF polyline_pause; + QVector _lod; + QVector _lod_pause; QPen pen; QColor fill_color; bool lines;