src/layers/edittools.cpp

changeset 322
a39f454a3d7f
parent 320
af6633412a6c
child 323
3c09c937848c
--- 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();
 }

mercurial