# HG changeset patch # User Teemu Piippo # Date 1646492248 -7200 # Node ID 24590af32ad6f32770240d6517295084579f066d # Parent c1ff4f107569ce580469615667ab6b11240448b3 Draw tool now renders the winding of the new polygon diff -r c1ff4f107569 -r 24590af32ad6 src/geometry.cpp --- 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; +} diff -r c1ff4f107569 -r 24590af32ad6 src/geometry.h --- 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 #include "basics.h" namespace geom @@ -94,6 +95,7 @@ LineSegment2D left(const QRectF& rectangle); LineSegment2D right(const QRectF& rectangle); bool isConvex(const std::vector& polygon); + Winding winding(const QPolygonF& polygon); struct ScalingExtract { glm::vec3 scaling; diff -r c1ff4f107569 -r 24590af32ad6 src/tools/drawtool.cpp --- 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 diff -r c1ff4f107569 -r 24590af32ad6 src/ui/canvas.cpp --- 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 &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 Canvas::convertWorldPointsToScreenPoints(const std::vector &worldPoints) +QVector Canvas::convertWorldPointsToScreenPoints(const std::vector &worldPoints) const { QVector points2d; points2d.reserve(worldPoints.size()); diff -r c1ff4f107569 -r 24590af32ad6 src/ui/canvas.h --- 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& points); void drawWorldPolygon(QPainter* painter, const std::vector& points); + Winding worldPolygonWinding(const std::vector& points) const; const std::optional& 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 convertWorldPointsToScreenPoints(const std::vector& worldPoints); + QVector convertWorldPointsToScreenPoints(const std::vector& worldPoints) const; Q_SLOT void updateCanvasRenderPreferences(); std::optional gridProgram; std::optional axesProgram;