src/document.cpp

changeset 232
8efa3a33172e
parent 228
948867719906
child 244
065db0753f05
--- a/src/document.cpp	Wed Jun 15 19:47:02 2022 +0300
+++ b/src/document.cpp	Mon Jun 20 02:04:51 2022 +0300
@@ -23,6 +23,7 @@
 #include "model.h"
 #include "ui/objecteditor.h"
 #include "gl/partrenderer.h"
+#include "circularprimitive.h"
 
 // Make mapbox::earcut work with glm::vec3
 namespace mapbox {
@@ -63,6 +64,11 @@
 	});
 }
 
+void EditTools::setCircleToolOptions(const CircleToolOptions& options)
+{
+	this->circleToolOptions = options;
+}
+
 void EditTools::mvpMatrixChanged(const glm::mat4& matrix)
 {
 	this->mvpMatrix = matrix;
@@ -138,19 +144,25 @@
 	painter->drawPolygon(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
 }
 
-static opt<std::vector<glm::vec3>> modelActionPoints(const ModelAction& action)
+static std::vector<std::vector<glm::vec3>> modelActionPoints(const ModelAction& action)
 {
-	opt<std::vector<glm::vec3>> result;
+	std::vector<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};
+			result.push_back({seg->p1, seg->p2});
 		}
 		else if (const Triangle* tri = std::get_if<Colored<Triangle>>(&newElement)) {
-			result = {tri->p1, tri->p2, tri->p3};
+			result.push_back({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};
+			result.push_back({quad->p1, quad->p2, quad->p3, quad->p4});
+		}
+		else if (const CircularPrimitive* circ = std::get_if<Colored<CircularPrimitive>>(&newElement)) {
+			rasterize(*circ, [&](const ModelElement& element){
+				const auto& subpoints = modelActionPoints(AppendToModel{element});
+				std::copy(subpoints.begin(), subpoints.end(), std::back_inserter(result));
+			});
 		}
 	}
 	return result;
@@ -199,23 +211,36 @@
 	}
 }
 
+const std::vector<ModelAction> EditTools::modelActions() const
+{
+	switch(this->mode) {
+	case SelectMode:
+		return {};
+	case DrawMode:
+		return drawModeActions();
+	case CircleMode:
+		return circleModeActions();
+	}
+}
+
 void EditTools::renderPreview(QPainter* painter, const void* pensptr)
 {
 	const Pens& pens = *reinterpret_cast<const Pens*>(pensptr);
 	painter->setPen(pens.polygonPen);
-	for (const ModelAction& action : this->actions()) {
-		const std::vector<glm::vec3> points = modelActionPoints(action).value_or(std::vector<glm::vec3>{});
-		if (points.size() == 2) {
-			drawWorldPolyline(painter, points, renderer);
-		}
-		else {
-			if (worldPolygonWinding(points, this->renderer) == Winding::Clockwise) {
-				painter->setBrush(pens.greenPolygonBrush);
+	for (const ModelAction& action : this->modelActions()) {
+		for (const std::vector<glm::vec3>& points : modelActionPoints(action)) {
+			if (points.size() == 2) {
+				drawWorldPolyline(painter, points, renderer);
 			}
 			else {
-				painter->setBrush(pens.redPolygonBrush);
+				if (worldPolygonWinding(points, this->renderer) == Winding::Clockwise) {
+					painter->setBrush(pens.greenPolygonBrush);
+				}
+				else {
+					painter->setBrush(pens.redPolygonBrush);
+				}
+				drawWorldPolygon(painter, points, this->renderer);
 			}
-			drawWorldPolygon(painter, points, this->renderer);
 		}
 	}
 	painter->setBrush(pens.pointBrush);
@@ -268,39 +293,21 @@
 				this->polygon.push_back(*this->worldPosition);
 			}
 		}
-		else if (true
-			and event->button() == Qt::RightButton
-			and this->polygon.size() > 1
-		) {
-			this->removeLastPoint();
+		break;
+	case CircleMode:
+		if (event->button() == Qt::LeftButton and this->worldPosition.has_value()) {
+			if (this->polygon.size() == 2) {
+				this->closeShape();
+			}
+			else {
+				this->polygon.push_back(*this->worldPosition);
+			}
 		}
 		break;
 	}
-}
-
-constexpr float distancesquared(const glm::vec3& p1, const glm::vec3& p2)
-{
-	const float dx = p2.x - p1.x;
-	const float dy = p2.y - p1.y;
-	const float dz = p2.z - p1.z;
-	return (dx * dx) + (dy * dy) + (dz * dz);
-}
-
-inline float area(const Quadrilateral& q)
-{
-	return 0.5 * (
-		glm::length(glm::cross(q.p2 - q.p1, q.p3 - q.p1)) +
-		glm::length(glm::cross(q.p3 - q.p2, q.p4 - q.p2))
-	);
-}
-
-inline float energy(const Quadrilateral& q)
-{
-	const float L2 = distancesquared(q.p1, q.p2)
-		+ distancesquared(q.p2, q.p3)
-		+ distancesquared(q.p3, q.p4)
-		+ distancesquared(q.p4, q.p1);
-	return 1 - 6.928203230275509 * area(q) / L2;
+	if (event->button() == Qt::RightButton and this->polygon.size() > 1) {
+		this->removeLastPoint();
+	}
 }
 
 struct MergedTriangles
@@ -365,7 +372,32 @@
 	return result;
 }
 
-const std::vector<ModelAction> EditTools::actions() const
+
+const std::vector<ModelAction> EditTools::circleModeActions() const
+{
+	std::vector<ModelAction> result;
+	if (this->numpoints == 2) {
+		const glm::vec3 x = polygon[1] - polygon[0];
+		glm::mat4 transform{
+			glm::vec4{x, 0},
+			this->gridMatrix[2],
+			glm::vec4{glm::cross(glm::vec3{-this->gridMatrix[2]}, x), 0},
+			glm::vec4{this->polygon[0], 1},
+		};
+		Colored<CircularPrimitive> circ{
+			CircularPrimitive{
+				.type = this->circleToolOptions.type,
+				.fraction = this->circleToolOptions.fraction,
+				.transformation = transform,
+			},
+			MAIN_COLOR
+		};
+		result.push_back(AppendToModel{.newElement = circ});
+	}
+	return result;
+}
+
+const std::vector<ModelAction> EditTools::drawModeActions() const
 {
 	std::vector<ModelAction> result;
 	if (this->numpoints == 2) {
@@ -415,7 +447,7 @@
 
 void EditTools::closeShape()
 {
-	for (const ModelAction& action : this->actions()) {
+	for (const ModelAction& action : this->modelActions()) {
 		Q_EMIT this->modelAction(action);
 	}
 	this->polygon.clear();

mercurial