Show concave polygons as red while drawing

Fri, 27 Aug 2021 00:55:32 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Fri, 27 Aug 2021 00:55:32 +0300
changeset 122
b54b350dff5d
parent 121
000781318c36
child 123
e3fe3617b631

Show concave polygons as red while drawing

src/geometry.cpp file | annotate | diff | comparison | revisions
src/geometry.h file | annotate | diff | comparison | revisions
src/maths.h file | annotate | diff | comparison | revisions
src/tools/drawtool.cpp file | annotate | diff | comparison | revisions
src/tools/drawtool.h file | annotate | diff | comparison | revisions
--- a/src/geometry.cpp	Fri Jul 30 01:28:39 2021 +0300
+++ b/src/geometry.cpp	Fri Aug 27 00:55:32 2021 +0300
@@ -1,5 +1,7 @@
 #include <glm/gtc/matrix_transform.hpp>
 #include "geometry.h"
+#include "ring.h"
+#include "maths.h"
 
 /**
  * @brief Computes line-plane intersection
@@ -196,3 +198,24 @@
 		glm::vec2{rectangle.right(), rectangle.bottom()}
 	};
 }
+
+bool geom::convex(const std::vector<glm::vec3>& polygon)
+{
+	const int n = polygon.size();
+	auto polygonRing = iter::ring(polygon, n);
+	std::vector<glm::vec3> crosses;
+	crosses.resize(n);
+	for (int i = 0; i < n; i += 1)
+	{
+		crosses[i] = glm::cross(polygonRing[i - 1] - polygonRing[i], polygonRing[i + 1] - polygonRing[i]);
+	}
+	for (int i = 0; i < n - 1; i += 1)
+	{
+		const float dotp = glm::dot(crosses[0], crosses[i + 1]);
+		if (dotp < 0 or qFuzzyIsNull(dotp))
+		{
+			return false;
+		}
+	}
+	return true;
+}
--- a/src/geometry.h	Fri Jul 30 01:28:39 2021 +0300
+++ b/src/geometry.h	Fri Aug 27 00:55:32 2021 +0300
@@ -93,6 +93,7 @@
 	LineSegment2D bottom(const QRectF& rectangle);
 	LineSegment2D left(const QRectF& rectangle);
 	LineSegment2D right(const QRectF& rectangle);
+	bool convex(const std::vector<glm::vec3>& polygon);
 	struct ScalingExtract
 	{
 		glm::vec3 scaling;
--- a/src/maths.h	Fri Jul 30 01:28:39 2021 +0300
+++ b/src/maths.h	Fri Aug 27 00:55:32 2021 +0300
@@ -72,7 +72,32 @@
 	}
 	constexpr double infinity = std::numeric_limits<double>::infinity();
 	constexpr long double pi = M_PIl;
-
+	// Returns the minimum value of a container
+	template<typename T>
+	inline auto nmin(T&& values)
+	{
+		auto it = std::begin(values);
+		auto result_p = it;
+		for (++it; it != std::end(values); ++it)
+		{
+			if (*it < *result_p)
+				result_p = it;
+		}
+		return *result_p;
+	}
+	// Returns the maximum value of a container
+	template<typename T>
+	inline auto nmax(T&& values)
+	{
+		auto it = std::begin(values);
+		auto result_p = it;
+		for (++it; it != std::end(values); ++it)
+		{
+			if (*it > *result_p)
+				result_p = it;
+		}
+		return *result_p;
+	}
 	/*
 	 * Returns the empty sum. (recursion base)
 	 */
--- a/src/tools/drawtool.cpp	Fri Jul 30 01:28:39 2021 +0300
+++ b/src/tools/drawtool.cpp	Fri Aug 27 00:55:32 2021 +0300
@@ -10,6 +10,7 @@
 static const QPen polygonPen = {QBrush{Qt::black}, 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}};
 
 DrawTool::DrawTool(QObject* parent) :
 	BaseTool{parent} {}
@@ -83,6 +84,10 @@
 {
 	this->previewPolygon.resize(this->polygon.size() + 1);
 	this->previewPolygon.back() = this->previewPoint;
+	if (this->previewPolygon.size() > 2)
+	{
+		this->isconcave = not geom::convex(this->previewPolygon);
+	}
 }
 
 void DrawTool::reset()
@@ -92,7 +97,7 @@
 
 void DrawTool::overpaint(Canvas* canvas, QPainter* painter) const
 {
-	painter->setBrush(::polygonBrush);
+	painter->setBrush(this->isconcave ? ::badPolygonBrush : ::polygonBrush);
 	painter->setPen(::polygonPen);
 	canvas->drawWorldPolygon(painter, this->previewPolygon);
 	painter->setBrush(::pointBrush);
--- a/src/tools/drawtool.h	Fri Jul 30 01:28:39 2021 +0300
+++ b/src/tools/drawtool.h	Fri Aug 27 00:55:32 2021 +0300
@@ -19,5 +19,6 @@
 	std::vector<glm::vec3> polygon;
 	std::vector<glm::vec3> previewPolygon;
 	glm::vec3 previewPoint;
+	bool isconcave = false;
 	void updatePreviewPolygon();
 };

mercurial