Draw tool now renders the winding of the new polygon

Sat, 05 Mar 2022 16:57:28 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Sat, 05 Mar 2022 16:57:28 +0200
changeset 168
24590af32ad6
parent 167
c1ff4f107569
child 169
6da096930534

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;

mercurial