Sat, 05 Mar 2022 16:57:28 +0200
Draw tool now renders the winding of the new polygon
src/geometry.cpp | file | annotate | diff | comparison | revisions | |
src/geometry.h | file | annotate | diff | comparison | revisions | |
src/tools/drawtool.cpp | file | annotate | diff | comparison | revisions | |
src/ui/canvas.cpp | file | annotate | diff | comparison | revisions | |
src/ui/canvas.h | file | annotate | diff | comparison | revisions |
--- a/src/geometry.cpp Sat Mar 05 15:40:43 2022 +0200 +++ b/src/geometry.cpp Sat Mar 05 16:57:28 2022 +0200 @@ -217,3 +217,21 @@ return glm::dot(crosses[0], vector) < 1e-6; }); } + +/** + * @brief Determines the winding of a 2d polygon + * @param polygon + * @return winding + */ +Winding geom::winding(const QPolygonF &polygon) +{ + // based on https://stackoverflow.com/a/1165943 + double sum = 0.0; + for (int i = 0; i < polygon.size(); i += 1) + { + const QPointF& p1 = polygon[i]; + const QPointF& p2 = polygon[(i + 1) % polygon.size()]; + sum += (p2.x() - p1.x()) * (p2.y() + p1.y()); + } + return (sum < 0) ? Winding::Anticlockwise : Winding::Clockwise; +}
--- a/src/geometry.h Sat Mar 05 15:40:43 2022 +0200 +++ b/src/geometry.h Sat Mar 05 16:57:28 2022 +0200 @@ -1,4 +1,5 @@ #pragma once +#include <QPolygonF> #include "basics.h" namespace geom @@ -94,6 +95,7 @@ LineSegment2D left(const QRectF& rectangle); LineSegment2D right(const QRectF& rectangle); bool isConvex(const std::vector<glm::vec3>& polygon); + Winding winding(const QPolygonF& polygon); struct ScalingExtract { glm::vec3 scaling;
--- a/src/tools/drawtool.cpp Sat Mar 05 15:40:43 2022 +0200 +++ b/src/tools/drawtool.cpp Sat Mar 05 16:57:28 2022 +0200 @@ -8,9 +8,10 @@ static const QBrush pointBrush = {Qt::white}; static const QPen polygonPen = {QBrush{Qt::black}, 2.0, Qt::DashLine}; +static const QPen badPolygonPen = {QBrush{Qt::red}, 2.0, Qt::DashLine}; static const QPen pointPen = {QBrush{Qt::black}, 2.0}; -static const QBrush polygonBrush = {QColor{64, 255, 128, 192}}; -static const QBrush badPolygonBrush = {QColor{255, 96, 96, 192}}; +static const QBrush greenPolygonBrush = {QColor{64, 255, 128, 192}}; +static const QBrush redPolygonBrush = {QColor{255, 96, 96, 192}}; DrawTool::DrawTool(Document* document) : BaseTool{document} @@ -114,10 +115,17 @@ void DrawTool::overpaint(Canvas* canvas, QPainter* painter) const { - painter->setBrush(this->isconcave ? ::badPolygonBrush : ::polygonBrush); - painter->setPen(::polygonPen); - if (this->previewPolygon.size() > 2) + painter->setPen(this->isconcave ? ::badPolygonPen : ::polygonPen); + if (this->previewPolygon.size() > 2 and not this->isconcave) { + if (canvas->worldPolygonWinding(this->previewPolygon) == Winding::Clockwise) + { + painter->setBrush(::greenPolygonBrush); + } + else + { + painter->setBrush(::redPolygonBrush); + } canvas->drawWorldPolygon(painter, this->previewPolygon); } else
--- a/src/ui/canvas.cpp Sat Mar 05 15:40:43 2022 +0200 +++ b/src/ui/canvas.cpp Sat Mar 05 16:57:28 2022 +0200 @@ -240,6 +240,11 @@ painter->drawPolygon(QPolygonF{this->convertWorldPointsToScreenPoints(points)}); } +Winding Canvas::worldPolygonWinding(const std::vector<glm::vec3> &points) const +{ + return geom::winding(QPolygonF{this->convertWorldPointsToScreenPoints(points)}); +} + /** * @brief Gets the current position of the cursor in the model * @return 3D vector @@ -326,7 +331,7 @@ return std::abs(dot) < threshold; } -QVector<QPointF> Canvas::convertWorldPointsToScreenPoints(const std::vector<glm::vec3> &worldPoints) +QVector<QPointF> Canvas::convertWorldPointsToScreenPoints(const std::vector<glm::vec3> &worldPoints) const { QVector<QPointF> points2d; points2d.reserve(worldPoints.size());
--- a/src/ui/canvas.h Sat Mar 05 15:40:43 2022 +0200 +++ b/src/ui/canvas.h Sat Mar 05 16:57:28 2022 +0200 @@ -23,6 +23,7 @@ void drawWorldPoint(QPainter* painter, const glm::vec3& worldPoint) const; void drawWorldPolyline(QPainter* painter, const std::vector<glm::vec3>& points); void drawWorldPolygon(QPainter* painter, const std::vector<glm::vec3>& points); + Winding worldPolygonWinding(const std::vector<glm::vec3>& points) const; const std::optional<glm::vec3>& getWorldPosition() const; void adjustGridToView(); public Q_SLOTS: @@ -43,7 +44,7 @@ void setGridMatrix(const glm::mat4 &newMatrix); glm::vec3 cameraVector() const; bool isGridPerpendicularToScreen(float threshold) const; - QVector<QPointF> convertWorldPointsToScreenPoints(const std::vector<glm::vec3>& worldPoints); + QVector<QPointF> convertWorldPointsToScreenPoints(const std::vector<glm::vec3>& worldPoints) const; Q_SLOT void updateCanvasRenderPreferences(); std::optional<GridProgram> gridProgram; std::optional<AxesProgram> axesProgram;