Reduce edittools.cpp further

Sun, 03 Jul 2022 20:18:34 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Sun, 03 Jul 2022 20:18:34 +0300
changeset 322
a39f454a3d7f
parent 321
180072db4a83
child 323
3c09c937848c

Reduce edittools.cpp further

CMakeLists.txt file | annotate | diff | comparison | revisions
src/geometry.h file | annotate | diff | comparison | revisions
src/gl/partrenderer.h file | annotate | diff | comparison | revisions
src/inputvertices.cpp file | annotate | diff | comparison | revisions
src/inputvertices.h file | annotate | diff | comparison | revisions
src/layers/edittools.cpp file | annotate | diff | comparison | revisions
src/layers/edittools.h file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Sun Jul 03 15:59:22 2022 +0300
+++ b/CMakeLists.txt	Sun Jul 03 20:18:34 2022 +0300
@@ -68,6 +68,7 @@
 	src/geometry.cpp
 	src/ldrawalgorithm.cpp
 	src/libraries.cpp
+	src/inputvertices.cpp
 	src/invert.cpp
 	src/main.cpp
 	src/messagelog.cpp
@@ -99,6 +100,7 @@
 	src/colors.h
 	src/documentmanager.h
 	src/geometry.h
+	src/inputvertices.h
 	src/invert.h
 	src/ldrawalgorithm.h
 	src/libraries.h
--- a/src/geometry.h	Sun Jul 03 15:59:22 2022 +0300
+++ b/src/geometry.h	Sun Jul 03 20:18:34 2022 +0300
@@ -221,3 +221,8 @@
 	}
 	return result;
 }
+
+constexpr QPointF vecToQPoint(const glm::vec2& a)
+{
+	return {a.x, a.y};
+}
--- a/src/gl/partrenderer.h	Sun Jul 03 15:59:22 2022 +0300
+++ b/src/gl/partrenderer.h	Sun Jul 03 20:18:34 2022 +0300
@@ -72,3 +72,48 @@
 	void renderVao(const gl::ArrayClass arrayClass);
 	void checkForGLErrors();
 };
+
+inline QVector<QPointF> convertWorldPointsToScreenPoints(
+	const std::vector<glm::vec3> &worldPoints,
+	const PartRenderer* renderer)
+{
+	QVector<QPointF> points2d;
+	points2d.reserve(static_cast<int>(worldPoints.size()));
+	for (const glm::vec3& point : worldPoints)
+	{
+		points2d.push_back(renderer->modelToScreenCoordinates(point));
+	}
+	return points2d;
+}
+
+inline Winding worldPolygonWinding(
+	const std::vector<glm::vec3> &points,
+	const PartRenderer* renderer)
+{
+	return winding(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
+}
+
+inline void drawWorldPoint(
+	QPainter* painter,
+	const glm::vec3& worldPoint,
+	const PartRenderer* renderer)
+{
+	const QPointF center = renderer->modelToScreenCoordinates(worldPoint);
+	painter->drawEllipse(inscribe(CircleF{center, 5}));
+}
+
+inline void drawWorldPolyline(
+	QPainter *painter,
+	const std::vector<glm::vec3> &points,
+	const PartRenderer* renderer)
+{
+	painter->drawPolyline(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
+}
+
+inline void drawWorldPolygon(
+	QPainter* painter,
+	const std::vector<glm::vec3> &points,
+	const PartRenderer* renderer)
+{
+	painter->drawPolygon(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/inputvertices.cpp	Sun Jul 03 20:18:34 2022 +0300
@@ -0,0 +1,43 @@
+#include "src/inputvertices.h"
+
+bool InputVertices::currentPointOnExistingPoint() const
+{
+	const glm::vec3& pos = this->polygon.back();
+	return std::any_of(
+		this->polygon.begin(),
+		this->polygon.end() - 1,
+		[&pos](const glm::vec3& p){return isclose(pos, p);});
+}
+
+std::size_t InputVertices::calcNumPoints() const
+{
+	std::size_t result = this->polygon.size();
+	if (this->currentPointOnExistingPoint()) {
+		result -= 1;
+	}
+	return result;
+}
+
+void InputVertices::updateCurrentPoint(const glm::vec3& p)
+{
+	this->polygon.back() = p;
+	this->numpoints = this->calcNumPoints();
+}
+
+void InputVertices::removeLastPoint()
+{
+	if (this->polygon.size() > 1) {
+		this->polygon.erase(this->polygon.end() - 2);
+		this->numpoints = this->calcNumPoints();
+	}
+}
+
+void InputVertices::finishCurrentPoint()
+{
+	this->polygon.push_back(this->polygon.back());
+}
+
+void InputVertices::clear()
+{
+	*this = {};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/inputvertices.h	Sun Jul 03 20:18:34 2022 +0300
@@ -0,0 +1,39 @@
+#pragma once
+#include "src/basics.h"
+
+class InputVertices
+{
+	std::vector<glm::vec3> polygon = {origin};
+	std::size_t numpoints = 1;
+public:
+	bool currentPointOnExistingPoint() const;
+	std::size_t calcNumPoints() const;
+	void updateCurrentPoint(const glm::vec3& p);
+	void removeLastPoint();
+	void finishCurrentPoint();
+	void clear();
+	const glm::vec3& operator[](std::size_t i) const
+	{
+		return this->polygon[i];
+	}
+	std::size_t bufferSize() const
+	{
+		return this->polygon.size();
+	}
+	std::size_t polygonSize() const
+	{
+		return this->numpoints;
+	}
+	auto begin() const
+	{
+		return std::begin(this->polygon);
+	}
+	auto end() const
+	{
+		return std::end(this->polygon);
+	}
+	auto polygonEnd() const
+	{
+		return std::begin(this->polygon) + static_cast<long int>(this->numpoints);
+	}
+};
--- a/src/layers/edittools.cpp	Sun Jul 03 15:59:22 2022 +0300
+++ b/src/layers/edittools.cpp	Sun Jul 03 20:18:34 2022 +0300
@@ -88,54 +88,8 @@
 		// And finally transform it back to grid coordinates by transforming it with the
 		// grid matrix.
 		this->worldPosition = this->gridMatrix * glm::vec4{*this->worldPosition, 1};
-		this->polygon.back() = *this->worldPosition;
-		this->numpoints = this->calcNumPoints();
-	}
-}
-
-static QVector<QPointF> convertWorldPointsToScreenPoints(
-	const std::vector<glm::vec3> &worldPoints,
-	const PartRenderer* renderer)
-{
-	QVector<QPointF> points2d;
-	points2d.reserve(static_cast<int>(worldPoints.size()));
-	for (const glm::vec3& point : worldPoints)
-	{
-		points2d.push_back(renderer->modelToScreenCoordinates(point));
+		this->inputPolygon.updateCurrentPoint(*this->worldPosition);
 	}
-	return points2d;
-}
-
-static Winding worldPolygonWinding(
-	const std::vector<glm::vec3> &points,
-	const PartRenderer* renderer)
-{
-	return winding(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
-}
-
-static void drawWorldPoint(
-	QPainter* painter,
-	const glm::vec3& worldPoint,
-	const PartRenderer* renderer)
-{
-	const QPointF center = renderer->modelToScreenCoordinates(worldPoint);
-	painter->drawEllipse(inscribe(CircleF{center, 5}));
-}
-
-static void drawWorldPolyline(
-	QPainter *painter,
-	const std::vector<glm::vec3> &points,
-	const PartRenderer* renderer)
-{
-	painter->drawPolyline(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
-}
-
-static void drawWorldPolygon(
-	QPainter* painter,
-	const std::vector<glm::vec3> &points,
-	const PartRenderer* renderer)
-{
-	painter->drawPolygon(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
 }
 
 //! \brief Conversion function from PlainPolygonElement to ModelElement
@@ -183,7 +137,6 @@
 	const QPen pointPen;
 	const QPen textPen;
 	const QPen polygonPen;
-	const QPen badPolygonPen;
 	const QBrush greenPolygonBrush;
 	const QBrush redPolygonBrush;
 };
@@ -240,11 +193,6 @@
 	}
 }
 
-constexpr QPointF vecToQPoint(const glm::vec2& a)
-{
-	return {a.x, a.y};
-}
-
 void EditTools::renderPreview(QPainter* painter, const void* pensptr)
 {
 	const Pens& pens = *reinterpret_cast<const Pens*>(pensptr);
@@ -267,11 +215,11 @@
 	}
 	painter->setBrush(pens.pointBrush);
 	painter->setPen(pens.pointPen);
-	for (const glm::vec3& point : this->polygon) {
+	for (const glm::vec3& point : this->inputPolygon) {
 		drawWorldPoint(painter, point, this->renderer);
 	}
-	if (this->mode == CircleMode and this->polygon.size() >= 2) {
-		const glm::vec3 circleOrigin = this->polygon[0];
+	if (this->mode == CircleMode and this->inputPolygon.polygonSize() >= 2) {
+		const glm::vec3 circleOrigin = this->inputPolygon[0];
 		const QPointF originScreen = this->renderer->modelToScreenCoordinates(circleOrigin);
 		const auto extremity = [this, &originScreen](const glm::vec3& p){
 			const QPointF s2 = this->renderer->modelToScreenCoordinates(p);
@@ -287,25 +235,25 @@
 		};
 		const glm::vec3 zvec = this->gridMatrix[2];
 		{
-			const glm::vec2 p1 = extremity(this->polygon[0] + zvec);
-			const glm::vec2 p2 = extremity(this->polygon[0] - zvec);
+			const glm::vec2 p1 = extremity(this->inputPolygon[0] + zvec);
+			const glm::vec2 p2 = extremity(this->inputPolygon[0] - zvec);
 			const glm::vec2 lateral = glm::normalize(glm::mat2{{0, 1}, {-1, 0}} * (p2 - p1));
 			painter->setPen(QPen{Qt::white, 3});
 			painter->drawLine(vecToQPoint(p1), vecToQPoint(p2));
 			constexpr float notchsize = 40.0f;
 			for (int a = -30; a <= 30; ++a) {
-				const glm::vec3 notch = this->polygon[0] + static_cast<float>(a) * zvec;
+				const glm::vec3 notch = this->inputPolygon[0] + static_cast<float>(a) * zvec;
 				const QPointF s_notchcenter = this->renderer->modelToScreenCoordinates(notch);
 				const QPointF notch_s1 = s_notchcenter + notchsize * 0.5f * vecToQPoint(lateral);
 				const QPointF notch_s2 = s_notchcenter - notchsize * 0.5f * vecToQPoint(lateral);
 				painter->drawLine(notch_s1, notch_s2);
 			}
 		}
-		if (this->polygon.size() >= 3) {
+		if (this->inputPolygon.polygonSize() >= 3) {
 			const opt<float> height = this->cylinderHeight();
 			if (height.has_value()) {
 				const glm::vec3 heightvec = height.value_or(0) * zvec;
-				const glm::vec3 p = this->polygon[1] + 0.5f * heightvec;
+				const glm::vec3 p = this->inputPolygon[1] + 0.5f * heightvec;
 				QFont font{};
 				font.setBold(true);
 				drawBorderedText(painter, this->renderer->modelToScreenCoordinates(p), font, QString::number(*height));
@@ -314,50 +262,20 @@
 	}
 }
 
-void EditTools::removeLastPoint()
-{
-	if (this->polygon.size() > 1) {
-		this->polygon.erase(this->polygon.end() - 2);
-		this->numpoints = this->calcNumPoints();
-	}
-}
-
-bool EditTools::isCloseToExistingPoints() const
-{
-	if (this->worldPosition.has_value()) {
-		const glm::vec3& pos = *this->worldPosition;
-		return std::any_of(this->polygon.begin(), this->polygon.end() - 1, [&pos](const glm::vec3& p){
-			return isclose(pos, p);
-		});
-	}
-	else {
-		return false;
-	}
-}
-
-std::size_t EditTools::calcNumPoints() const
-{
-	std::size_t result = this->polygon.size();
-	if (this->isCloseToExistingPoints()) {
-		result -= 1;
-	}
-	return result;
-}
-
 opt<float> EditTools::cylinderHeight() const
 {
-	if (this->polygon.size() < 3) {
+	if (this->inputPolygon.bufferSize() < 3) {
 		return {};
 	}
 	else {
 		const Plane plane{
 			.normal = glm::normalize(this->renderer->cameraVector(this->localPosition)),
-			.anchor = this->polygon[0],
+			.anchor = this->inputPolygon[0],
 		};
 		const opt<glm::vec3> p = this->renderer->screenToModelCoordinates(this->localPosition, plane);
 		if (p.has_value()) {
 			const glm::vec3 heightvec = glm::normalize(glm::vec3{gridMatrix[2]});
-			return std::round(glm::dot(*p - polygon[0], heightvec));
+			return std::round(glm::dot(*p - this->inputPolygon[0], heightvec));
 		}
 		else {
 			return {};
@@ -381,27 +299,27 @@
 		break;
 	case DrawMode:
 		if (event->button() == Qt::LeftButton and this->worldPosition.has_value()) {
-			if (isCloseToExistingPoints()) {
+			if (this->inputPolygon.currentPointOnExistingPoint()) {
 				this->closeShape();
 			}
 			else {
-				this->polygon.push_back(*this->worldPosition);
+				this->inputPolygon.finishCurrentPoint();
 			}
 		}
 		break;
 	case CircleMode:
 		if (event->button() == Qt::LeftButton) {
-			if (this->polygon.size() == 3) {
+			if (this->inputPolygon.bufferSize() == 3) {
 				this->closeShape();
 			}
 			else if (this->worldPosition.has_value()) {
-				this->polygon.push_back(*this->worldPosition);
+				this->inputPolygon.finishCurrentPoint();
 			}
 		}
 		break;
 	}
-	if (event->button() == Qt::RightButton and this->polygon.size() > 1) {
-		this->removeLastPoint();
+	if (event->button() == Qt::RightButton) {
+		this->inputPolygon.removeLastPoint();
 	}
 }
 
@@ -409,14 +327,14 @@
 const std::vector<ModelAction> EditTools::circleModeActions() const
 {
 	std::vector<ModelAction> result;
-	if (this->numpoints >= 2) {
-		const glm::vec3 x = polygon[1] - polygon[0];
+	if (this->inputPolygon.polygonSize() >= 2) {
+		const glm::vec3 x = this->inputPolygon[1] - this->inputPolygon[0];
 		const opt<float> cyliheight = this->cylinderHeight().value_or(1);
 		glm::mat4 transform{
 			glm::vec4{x, 0},
 			*cyliheight * this->gridMatrix[2],
 			glm::vec4{glm::cross(glm::vec3{-this->gridMatrix[2]}, x), 0},
-			glm::vec4{this->polygon[0], 1},
+			glm::vec4{this->inputPolygon[0], 1},
 		};
 		Colored<CircularPrimitive> circ{
 			CircularPrimitive{
@@ -434,13 +352,13 @@
 const std::vector<ModelAction> EditTools::drawModeActions() const
 {
 	std::vector<ModelAction> result;
-	if (this->numpoints == 2) {
-		result.push_back(AppendToModel{edge(this->polygon[0], this->polygon[1])});
+	if (this->inputPolygon.polygonSize() == 2) {
+		result.push_back(AppendToModel{edge(this->inputPolygon[0], this->inputPolygon[1])});
 	}
-	else if (this->numpoints > 2) {
+	else if (this->inputPolygon.polygonSize() > 2) {
 		for (const PlainPolygonElement& poly : polygonize(
-			this->polygon.begin(),
-			this->polygon.begin() + static_cast<long>(this->numpoints))
+			this->inputPolygon.begin(),
+			this->inputPolygon.polygonEnd())
 		) {
 			result.push_back(AppendToModel{
 				.newElement = elementFromPolygonAndColor(poly, MAIN_COLOR),
@@ -467,6 +385,5 @@
 	for (const ModelAction& action : this->modelActions()) {
 		Q_EMIT this->modelAction(action);
 	}
-	this->polygon.clear();
-	this->polygon.push_back(this->worldPosition.value_or(glm::vec3{0, 0, 0}));
+	this->inputPolygon.clear();
 }
--- a/src/layers/edittools.h	Sun Jul 03 15:59:22 2022 +0300
+++ b/src/layers/edittools.h	Sun Jul 03 20:18:34 2022 +0300
@@ -23,6 +23,7 @@
 #include "src/model.h"
 #include "src/vertexmap.h"
 #include "src/gl/common.h"
+#include "src/inputvertices.h"
 
 enum EditingMode
 {
@@ -38,8 +39,7 @@
 class EditTools final : public QObject, public RenderLayer
 {
 	Q_OBJECT
-	std::vector<glm::vec3> polygon = {{0, 0, 0}};
-	std::size_t numpoints = 1;
+	InputVertices inputPolygon;
 	EditingMode mode = SelectMode;
 	glm::mat4 mvpMatrix;
 	glm::mat4 gridMatrix{1};
@@ -76,8 +76,5 @@
 	bool usePolygon() const;
 	void closeShape();
 	void renderPreview(QPainter* painter, const void* pensptr);
-	void removeLastPoint();
-	[[nodiscard]] bool isCloseToExistingPoints() const;
-	[[nodiscard]] std::size_t calcNumPoints() const;
 	[[nodiscard]] opt<float> cylinderHeight() const;
 };

mercurial