Edit tools: get rid of the preview polygon and render the result-to-be

Tue, 14 Jun 2022 23:04:49 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Tue, 14 Jun 2022 23:04:49 +0300
changeset 222
72b456f2f3c2
parent 221
e28f89b8ccdf
child 223
ce81db996275

Edit tools: get rid of the preview polygon and render the result-to-be

src/document.cpp file | annotate | diff | comparison | revisions
src/document.h file | annotate | diff | comparison | revisions
--- a/src/document.cpp	Tue Jun 14 22:31:39 2022 +0300
+++ b/src/document.cpp	Tue Jun 14 23:04:49 2022 +0300
@@ -70,8 +70,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->updatePreviewPolygon();
 }
 
 static QVector<QPointF> convertWorldPointsToScreenPoints(
@@ -119,6 +119,24 @@
 	painter->drawPolygon(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
 }
 
+static opt<std::vector<glm::vec3>> modelActionPoints(const ModelAction& action)
+{
+	opt<std::vector<glm::vec3>> result;
+	if (const AppendToModel* append = std::get_if<AppendToModel>(&action)) {
+		const ModelElement& newElement = append->newElement;
+		if (const LineSegment* seg = std::get_if<Colored<LineSegment>>(&newElement)) {
+			result = {seg->p1, seg->p2};
+		}
+		else if (const Triangle* tri = std::get_if<Colored<Triangle>>(&newElement)) {
+			result = {tri->p1, tri->p2, tri->p3};
+		}
+		else if (const Quadrilateral* quad = std::get_if<Colored<Quadrilateral>>(&newElement)) {
+			result = {quad->p1, quad->p2, quad->p3, quad->p4};
+		}
+	}
+	return result;
+}
+
 void EditTools::overpaint(QPainter* painter)
 {
 	struct Pens
@@ -151,26 +169,24 @@
 	case SelectMode:
 		break;
 	case DrawMode:
-		{
-			painter->setPen(this->isconcave ? pens.badPolygonPen : pens.polygonPen);
-			if (this->previewPolygon.size() > 2 and not this->isconcave)
-			{
-				if (worldPolygonWinding(this->previewPolygon, this->renderer) == Winding::Clockwise) {
+		painter->setPen(this->isconcave ? pens.badPolygonPen : pens.polygonPen);
+		for (const ModelAction& action : this->actions()) {
+			const opt<std::vector<glm::vec3>> points = modelActionPoints(action);
+			if (points.has_value()) {
+				if (worldPolygonWinding(*points, this->renderer) == Winding::Clockwise) {
 					painter->setBrush(pens.greenPolygonBrush);
 				}
 				else {
 					painter->setBrush(pens.redPolygonBrush);
 				}
-				drawWorldPolygon(painter, this->previewPolygon, this->renderer);
-			}
-			else {
-				drawWorldPolyline(painter, this->previewPolygon, this->renderer);
+				drawWorldPolygon(painter, *points, this->renderer);
 			}
-			painter->setBrush(pens.pointBrush);
-			painter->setPen(pens.pointPen);
-			for (const glm::vec3& point : this->polygon) {
-				drawWorldPoint(painter, point, this->renderer);
-			}
+		}
+		//drawWorldPolyline(painter, this->previewPolygon, this->renderer);
+		painter->setBrush(pens.pointBrush);
+		painter->setPen(pens.pointPen);
+		for (const glm::vec3& point : this->polygon) {
+			drawWorldPoint(painter, point, this->renderer);
 		}
 		break;
 	}
@@ -187,29 +203,24 @@
 
 void EditTools::updatePreviewPolygon()
 {
-	this->previewPolygon = this->polygon;
-	if (this->worldPosition.has_value()) {
-		this->previewPolygon.resize(this->polygon.size() + 1);
-		this->previewPolygon.back() = *this->worldPosition;
-	}
-	if (this->previewPolygon.size() > 2)
-	{
-		this->isconcave = not isConvex(this->previewPolygon);
+	if (this->polygon.size() > 2) {
+		this->isconcave = not isConvex(this->polygon);
 	}
 }
 
 void EditTools::removeLastPoint()
 {
-	if (this->polygon.size() > 0)
-	{
+	if (this->polygon.size() > 1) {
 		this->polygon.erase(this->polygon.end() - 1);
-		this->updatePreviewPolygon();
 	}
 }
 
-bool isCloseToExistingPoints(const std::vector<glm::vec3>& points, const glm::vec3 &pos)
+template<typename T>
+bool isCloseToExistingPoints(T begin, T end, const glm::vec3 &pos)
 {
-	return any(points, std::bind(isclose, std::placeholders::_1, pos));
+	return std::any_of(begin, end, [&pos](const glm::vec3& p){
+		return isclose(pos, p);
+	});
 }
 
 EditingMode EditTools::currentEditingMode() const
@@ -228,7 +239,7 @@
 		break;
 	case DrawMode:
 		if (event->button() == Qt::LeftButton and this->worldPosition.has_value()) {
-			if (isCloseToExistingPoints(this->polygon, *this->worldPosition)) {
+			if (isCloseToExistingPoints(this->polygon.begin(), this->polygon.end() - 1, *this->worldPosition)) {
 				this->closeShape();
 			}
 			else {
@@ -238,21 +249,22 @@
 		}
 		else if (true
 			and event->button() == Qt::RightButton
-			and this->polygon.size() > 0
+			and this->polygon.size() > 1
 		) {
-			this->polygon.erase(this->polygon.end() - 1);
+			this->removeLastPoint();
 			updatePreviewPolygon();
 		}
 		break;
 	}
 }
 
-void EditTools::closeShape()
+const std::vector<ModelAction> EditTools::actions() const
 {
+	std::vector<ModelAction> result;
 	if (this->polygon.size() >= 2 and this->polygon.size() <= 4) {
 		switch (this->polygon.size()) {
 		case 2:
-			Q_EMIT this->modelAction(AppendToModel{
+			result.push_back(AppendToModel{
 				.newElement = Colored<LineSegment>{
 					LineSegment{
 						.p1 = this->polygon[0],
@@ -263,7 +275,7 @@
 			});
 			break;
 		case 3:
-			Q_EMIT this->modelAction(AppendToModel{
+			result.push_back(AppendToModel{
 				.newElement = Colored<Triangle>{
 					Triangle{
 						.p1 = this->polygon[0],
@@ -275,7 +287,7 @@
 			});
 			break;
 		case 4:
-			Q_EMIT this->modelAction(AppendToModel{
+			result.push_back(AppendToModel{
 				.newElement = Colored<Quadrilateral>{
 					Quadrilateral{
 						.p1 = this->polygon[0],
@@ -289,6 +301,14 @@
 			break;
 		}
 	}
+	return result;
+}
+
+void EditTools::closeShape()
+{
+	for (const ModelAction& action : this->actions()) {
+		Q_EMIT this->modelAction(action);
+	}
 	this->polygon.clear();
 	this->updatePreviewPolygon();
 }
--- a/src/document.h	Tue Jun 14 22:31:39 2022 +0300
+++ b/src/document.h	Tue Jun 14 23:04:49 2022 +0300
@@ -49,9 +49,7 @@
 class EditTools final : public QObject, public RenderLayer
 {
 	Q_OBJECT
-	std::vector<glm::vec3> polygon;
-	std::vector<glm::vec3> previewPolygon;
-	glm::vec3 previewPoint;
+	std::vector<glm::vec3> polygon = {{0, 0, 0}};
 	bool isconcave = false;
 	EditingMode mode = SelectMode;
 	glm::mat4 mvpMatrix;
@@ -76,6 +74,7 @@
 	void mouseClick(const QMouseEvent* event) override;
 	void overpaint(QPainter* painter) override;
 private:
+	const std::vector<ModelAction> actions() const;
 	void closeShape();
 	void updatePreviewPolygon();
 	void removeLastPoint();

mercurial