Fri, 27 Aug 2021 00:55:32 +0300
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);