# HG changeset patch # User Teemu Piippo # Date 1656868714 -10800 # Node ID a39f454a3d7fa7ee1043434d76bd2134963c3367 # Parent 180072db4a834184d25d1a78efc7dc114220302c Reduce edittools.cpp further diff -r 180072db4a83 -r a39f454a3d7f CMakeLists.txt --- a/CMakeLists.txt Sun Jul 03 15:59:22 2022 +0300 +++ b/CMakeLists.txt Sun Jul 03 20:18:34 2022 +0300 @@ -68,6 +68,7 @@ src/geometry.cpp src/ldrawalgorithm.cpp src/libraries.cpp + src/inputvertices.cpp src/invert.cpp src/main.cpp src/messagelog.cpp @@ -99,6 +100,7 @@ src/colors.h src/documentmanager.h src/geometry.h + src/inputvertices.h src/invert.h src/ldrawalgorithm.h src/libraries.h diff -r 180072db4a83 -r a39f454a3d7f src/geometry.h --- a/src/geometry.h Sun Jul 03 15:59:22 2022 +0300 +++ b/src/geometry.h Sun Jul 03 20:18:34 2022 +0300 @@ -221,3 +221,8 @@ } return result; } + +constexpr QPointF vecToQPoint(const glm::vec2& a) +{ + return {a.x, a.y}; +} diff -r 180072db4a83 -r a39f454a3d7f src/gl/partrenderer.h --- a/src/gl/partrenderer.h Sun Jul 03 15:59:22 2022 +0300 +++ b/src/gl/partrenderer.h Sun Jul 03 20:18:34 2022 +0300 @@ -72,3 +72,48 @@ void renderVao(const gl::ArrayClass arrayClass); void checkForGLErrors(); }; + +inline QVector convertWorldPointsToScreenPoints( + const std::vector &worldPoints, + const PartRenderer* renderer) +{ + QVector points2d; + points2d.reserve(static_cast(worldPoints.size())); + for (const glm::vec3& point : worldPoints) + { + points2d.push_back(renderer->modelToScreenCoordinates(point)); + } + return points2d; +} + +inline Winding worldPolygonWinding( + const std::vector &points, + const PartRenderer* renderer) +{ + return winding(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)}); +} + +inline void drawWorldPoint( + QPainter* painter, + const glm::vec3& worldPoint, + const PartRenderer* renderer) +{ + const QPointF center = renderer->modelToScreenCoordinates(worldPoint); + painter->drawEllipse(inscribe(CircleF{center, 5})); +} + +inline void drawWorldPolyline( + QPainter *painter, + const std::vector &points, + const PartRenderer* renderer) +{ + painter->drawPolyline(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)}); +} + +inline void drawWorldPolygon( + QPainter* painter, + const std::vector &points, + const PartRenderer* renderer) +{ + painter->drawPolygon(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)}); +} diff -r 180072db4a83 -r a39f454a3d7f src/inputvertices.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/inputvertices.cpp Sun Jul 03 20:18:34 2022 +0300 @@ -0,0 +1,43 @@ +#include "src/inputvertices.h" + +bool InputVertices::currentPointOnExistingPoint() const +{ + const glm::vec3& pos = this->polygon.back(); + return std::any_of( + this->polygon.begin(), + this->polygon.end() - 1, + [&pos](const glm::vec3& p){return isclose(pos, p);}); +} + +std::size_t InputVertices::calcNumPoints() const +{ + std::size_t result = this->polygon.size(); + if (this->currentPointOnExistingPoint()) { + result -= 1; + } + return result; +} + +void InputVertices::updateCurrentPoint(const glm::vec3& p) +{ + this->polygon.back() = p; + this->numpoints = this->calcNumPoints(); +} + +void InputVertices::removeLastPoint() +{ + if (this->polygon.size() > 1) { + this->polygon.erase(this->polygon.end() - 2); + this->numpoints = this->calcNumPoints(); + } +} + +void InputVertices::finishCurrentPoint() +{ + this->polygon.push_back(this->polygon.back()); +} + +void InputVertices::clear() +{ + *this = {}; +} diff -r 180072db4a83 -r a39f454a3d7f src/inputvertices.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/inputvertices.h Sun Jul 03 20:18:34 2022 +0300 @@ -0,0 +1,39 @@ +#pragma once +#include "src/basics.h" + +class InputVertices +{ + std::vector polygon = {origin}; + std::size_t numpoints = 1; +public: + bool currentPointOnExistingPoint() const; + std::size_t calcNumPoints() const; + void updateCurrentPoint(const glm::vec3& p); + void removeLastPoint(); + void finishCurrentPoint(); + void clear(); + const glm::vec3& operator[](std::size_t i) const + { + return this->polygon[i]; + } + std::size_t bufferSize() const + { + return this->polygon.size(); + } + std::size_t polygonSize() const + { + return this->numpoints; + } + auto begin() const + { + return std::begin(this->polygon); + } + auto end() const + { + return std::end(this->polygon); + } + auto polygonEnd() const + { + return std::begin(this->polygon) + static_cast(this->numpoints); + } +}; diff -r 180072db4a83 -r a39f454a3d7f src/layers/edittools.cpp --- a/src/layers/edittools.cpp Sun Jul 03 15:59:22 2022 +0300 +++ b/src/layers/edittools.cpp Sun Jul 03 20:18:34 2022 +0300 @@ -88,54 +88,8 @@ // And finally transform it back to grid coordinates by transforming it with the // grid matrix. this->worldPosition = this->gridMatrix * glm::vec4{*this->worldPosition, 1}; - this->polygon.back() = *this->worldPosition; - this->numpoints = this->calcNumPoints(); - } -} - -static QVector convertWorldPointsToScreenPoints( - const std::vector &worldPoints, - const PartRenderer* renderer) -{ - QVector points2d; - points2d.reserve(static_cast(worldPoints.size())); - for (const glm::vec3& point : worldPoints) - { - points2d.push_back(renderer->modelToScreenCoordinates(point)); + this->inputPolygon.updateCurrentPoint(*this->worldPosition); } - return points2d; -} - -static Winding worldPolygonWinding( - const std::vector &points, - const PartRenderer* renderer) -{ - return winding(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)}); -} - -static void drawWorldPoint( - QPainter* painter, - const glm::vec3& worldPoint, - const PartRenderer* renderer) -{ - const QPointF center = renderer->modelToScreenCoordinates(worldPoint); - painter->drawEllipse(inscribe(CircleF{center, 5})); -} - -static void drawWorldPolyline( - QPainter *painter, - const std::vector &points, - const PartRenderer* renderer) -{ - painter->drawPolyline(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)}); -} - -static void drawWorldPolygon( - QPainter* painter, - const std::vector &points, - const PartRenderer* renderer) -{ - painter->drawPolygon(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)}); } //! \brief Conversion function from PlainPolygonElement to ModelElement @@ -183,7 +137,6 @@ const QPen pointPen; const QPen textPen; const QPen polygonPen; - const QPen badPolygonPen; const QBrush greenPolygonBrush; const QBrush redPolygonBrush; }; @@ -240,11 +193,6 @@ } } -constexpr QPointF vecToQPoint(const glm::vec2& a) -{ - return {a.x, a.y}; -} - void EditTools::renderPreview(QPainter* painter, const void* pensptr) { const Pens& pens = *reinterpret_cast(pensptr); @@ -267,11 +215,11 @@ } painter->setBrush(pens.pointBrush); painter->setPen(pens.pointPen); - for (const glm::vec3& point : this->polygon) { + for (const glm::vec3& point : this->inputPolygon) { drawWorldPoint(painter, point, this->renderer); } - if (this->mode == CircleMode and this->polygon.size() >= 2) { - const glm::vec3 circleOrigin = this->polygon[0]; + if (this->mode == CircleMode and this->inputPolygon.polygonSize() >= 2) { + const glm::vec3 circleOrigin = this->inputPolygon[0]; const QPointF originScreen = this->renderer->modelToScreenCoordinates(circleOrigin); const auto extremity = [this, &originScreen](const glm::vec3& p){ const QPointF s2 = this->renderer->modelToScreenCoordinates(p); @@ -287,25 +235,25 @@ }; const glm::vec3 zvec = this->gridMatrix[2]; { - const glm::vec2 p1 = extremity(this->polygon[0] + zvec); - const glm::vec2 p2 = extremity(this->polygon[0] - zvec); + const glm::vec2 p1 = extremity(this->inputPolygon[0] + zvec); + const glm::vec2 p2 = extremity(this->inputPolygon[0] - zvec); const glm::vec2 lateral = glm::normalize(glm::mat2{{0, 1}, {-1, 0}} * (p2 - p1)); painter->setPen(QPen{Qt::white, 3}); painter->drawLine(vecToQPoint(p1), vecToQPoint(p2)); constexpr float notchsize = 40.0f; for (int a = -30; a <= 30; ++a) { - const glm::vec3 notch = this->polygon[0] + static_cast(a) * zvec; + const glm::vec3 notch = this->inputPolygon[0] + static_cast(a) * zvec; const QPointF s_notchcenter = this->renderer->modelToScreenCoordinates(notch); const QPointF notch_s1 = s_notchcenter + notchsize * 0.5f * vecToQPoint(lateral); const QPointF notch_s2 = s_notchcenter - notchsize * 0.5f * vecToQPoint(lateral); painter->drawLine(notch_s1, notch_s2); } } - if (this->polygon.size() >= 3) { + if (this->inputPolygon.polygonSize() >= 3) { const opt height = this->cylinderHeight(); if (height.has_value()) { const glm::vec3 heightvec = height.value_or(0) * zvec; - const glm::vec3 p = this->polygon[1] + 0.5f * heightvec; + const glm::vec3 p = this->inputPolygon[1] + 0.5f * heightvec; QFont font{}; font.setBold(true); drawBorderedText(painter, this->renderer->modelToScreenCoordinates(p), font, QString::number(*height)); @@ -314,50 +262,20 @@ } } -void EditTools::removeLastPoint() -{ - if (this->polygon.size() > 1) { - this->polygon.erase(this->polygon.end() - 2); - this->numpoints = this->calcNumPoints(); - } -} - -bool EditTools::isCloseToExistingPoints() const -{ - if (this->worldPosition.has_value()) { - const glm::vec3& pos = *this->worldPosition; - return std::any_of(this->polygon.begin(), this->polygon.end() - 1, [&pos](const glm::vec3& p){ - return isclose(pos, p); - }); - } - else { - return false; - } -} - -std::size_t EditTools::calcNumPoints() const -{ - std::size_t result = this->polygon.size(); - if (this->isCloseToExistingPoints()) { - result -= 1; - } - return result; -} - opt EditTools::cylinderHeight() const { - if (this->polygon.size() < 3) { + if (this->inputPolygon.bufferSize() < 3) { return {}; } else { const Plane plane{ .normal = glm::normalize(this->renderer->cameraVector(this->localPosition)), - .anchor = this->polygon[0], + .anchor = this->inputPolygon[0], }; const opt p = this->renderer->screenToModelCoordinates(this->localPosition, plane); if (p.has_value()) { const glm::vec3 heightvec = glm::normalize(glm::vec3{gridMatrix[2]}); - return std::round(glm::dot(*p - polygon[0], heightvec)); + return std::round(glm::dot(*p - this->inputPolygon[0], heightvec)); } else { return {}; @@ -381,27 +299,27 @@ break; case DrawMode: if (event->button() == Qt::LeftButton and this->worldPosition.has_value()) { - if (isCloseToExistingPoints()) { + if (this->inputPolygon.currentPointOnExistingPoint()) { this->closeShape(); } else { - this->polygon.push_back(*this->worldPosition); + this->inputPolygon.finishCurrentPoint(); } } break; case CircleMode: if (event->button() == Qt::LeftButton) { - if (this->polygon.size() == 3) { + if (this->inputPolygon.bufferSize() == 3) { this->closeShape(); } else if (this->worldPosition.has_value()) { - this->polygon.push_back(*this->worldPosition); + this->inputPolygon.finishCurrentPoint(); } } break; } - if (event->button() == Qt::RightButton and this->polygon.size() > 1) { - this->removeLastPoint(); + if (event->button() == Qt::RightButton) { + this->inputPolygon.removeLastPoint(); } } @@ -409,14 +327,14 @@ const std::vector EditTools::circleModeActions() const { std::vector result; - if (this->numpoints >= 2) { - const glm::vec3 x = polygon[1] - polygon[0]; + if (this->inputPolygon.polygonSize() >= 2) { + const glm::vec3 x = this->inputPolygon[1] - this->inputPolygon[0]; const opt cyliheight = this->cylinderHeight().value_or(1); glm::mat4 transform{ glm::vec4{x, 0}, *cyliheight * this->gridMatrix[2], glm::vec4{glm::cross(glm::vec3{-this->gridMatrix[2]}, x), 0}, - glm::vec4{this->polygon[0], 1}, + glm::vec4{this->inputPolygon[0], 1}, }; Colored circ{ CircularPrimitive{ @@ -434,13 +352,13 @@ const std::vector EditTools::drawModeActions() const { std::vector result; - if (this->numpoints == 2) { - result.push_back(AppendToModel{edge(this->polygon[0], this->polygon[1])}); + if (this->inputPolygon.polygonSize() == 2) { + result.push_back(AppendToModel{edge(this->inputPolygon[0], this->inputPolygon[1])}); } - else if (this->numpoints > 2) { + else if (this->inputPolygon.polygonSize() > 2) { for (const PlainPolygonElement& poly : polygonize( - this->polygon.begin(), - this->polygon.begin() + static_cast(this->numpoints)) + this->inputPolygon.begin(), + this->inputPolygon.polygonEnd()) ) { result.push_back(AppendToModel{ .newElement = elementFromPolygonAndColor(poly, MAIN_COLOR), @@ -467,6 +385,5 @@ for (const ModelAction& action : this->modelActions()) { Q_EMIT this->modelAction(action); } - this->polygon.clear(); - this->polygon.push_back(this->worldPosition.value_or(glm::vec3{0, 0, 0})); + this->inputPolygon.clear(); } diff -r 180072db4a83 -r a39f454a3d7f src/layers/edittools.h --- a/src/layers/edittools.h Sun Jul 03 15:59:22 2022 +0300 +++ b/src/layers/edittools.h Sun Jul 03 20:18:34 2022 +0300 @@ -23,6 +23,7 @@ #include "src/model.h" #include "src/vertexmap.h" #include "src/gl/common.h" +#include "src/inputvertices.h" enum EditingMode { @@ -38,8 +39,7 @@ class EditTools final : public QObject, public RenderLayer { Q_OBJECT - std::vector polygon = {{0, 0, 0}}; - std::size_t numpoints = 1; + InputVertices inputPolygon; EditingMode mode = SelectMode; glm::mat4 mvpMatrix; glm::mat4 gridMatrix{1}; @@ -76,8 +76,5 @@ bool usePolygon() const; void closeShape(); void renderPreview(QPainter* painter, const void* pensptr); - void removeLastPoint(); - [[nodiscard]] bool isCloseToExistingPoints() const; - [[nodiscard]] std::size_t calcNumPoints() const; [[nodiscard]] opt cylinderHeight() const; };