added support for open/closed cylinders in LDCircularPrimitive

Sun, 17 Jun 2018 17:07:29 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Sun, 17 Jun 2018 17:07:29 +0300
changeset 1407
22bc5862cb56
parent 1406
37fffb682d2f
child 1408
0d6162662040

added support for open/closed cylinders in LDCircularPrimitive

src/dialogs/circularprimitiveeditor.cpp file | annotate | diff | comparison | revisions
src/dialogs/circularprimitiveeditor.ui file | annotate | diff | comparison | revisions
src/linetypes/circularprimitive.cpp file | annotate | diff | comparison | revisions
src/linetypes/circularprimitive.h file | annotate | diff | comparison | revisions
src/parser.cpp file | annotate | diff | comparison | revisions
src/primitives.cpp file | annotate | diff | comparison | revisions
src/primitives.h file | annotate | diff | comparison | revisions
src/types/vertex.cpp file | annotate | diff | comparison | revisions
--- a/src/dialogs/circularprimitiveeditor.cpp	Sun Jun 17 16:13:24 2018 +0300
+++ b/src/dialogs/circularprimitiveeditor.cpp	Sun Jun 17 17:07:29 2018 +0300
@@ -40,6 +40,8 @@
 	MAP_RADIO_BUTTON(cylinder, Cylinder),
 	MAP_RADIO_BUTTON(disc, Disc),
 	MAP_RADIO_BUTTON(discNegative, DiscNegative),
+	MAP_RADIO_BUTTON(cylinderClosed, CylinderClosed),
+	MAP_RADIO_BUTTON(cylinderOpen, CylinderOpen),
 #undef MAP_RADIO_BUTTON
 };
 
--- a/src/dialogs/circularprimitiveeditor.ui	Sun Jun 17 16:13:24 2018 +0300
+++ b/src/dialogs/circularprimitiveeditor.ui	Sun Jun 17 17:07:29 2018 +0300
@@ -73,32 +73,46 @@
      <property name="title">
       <string>Type</string>
      </property>
-     <layout class="QFormLayout" name="formLayout">
-      <item row="3" column="0">
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="QRadioButton" name="circle">
+        <property name="text">
+         <string>Circle</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QRadioButton" name="cylinder">
+        <property name="text">
+         <string>C&amp;ylinder</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="2">
+       <widget class="QRadioButton" name="cylinderClosed">
+        <property name="text">
+         <string>Closed cylinder</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
        <widget class="QRadioButton" name="disc">
         <property name="text">
          <string>Disc</string>
         </property>
        </widget>
       </item>
-      <item row="3" column="1">
+      <item row="1" column="1">
        <widget class="QRadioButton" name="discNegative">
         <property name="text">
          <string>Disc negati&amp;ve</string>
         </property>
        </widget>
       </item>
-      <item row="2" column="0">
-       <widget class="QRadioButton" name="circle">
+      <item row="1" column="2">
+       <widget class="QRadioButton" name="cylinderOpen">
         <property name="text">
-         <string>Circle</string>
-        </property>
-       </widget>
-      </item>
-      <item row="2" column="1">
-       <widget class="QRadioButton" name="cylinder">
-        <property name="text">
-         <string>C&amp;ylinder</string>
+         <string>Open cylinder</string>
         </property>
        </widget>
       </item>
--- a/src/linetypes/circularprimitive.cpp	Sun Jun 17 16:13:24 2018 +0300
+++ b/src/linetypes/circularprimitive.cpp	Sun Jun 17 17:07:29 2018 +0300
@@ -76,7 +76,7 @@
 	bool /* render */
 ) {
 	Model cylinderBody {context};
-	buildPrimitiveBody(cylinderBody);
+	buildPrimitiveBody(cylinderBody, false);
 
 	for (LDObject* object : cylinderBody.objects())
 	{
@@ -94,7 +94,7 @@
 QVector<LDPolygon> LDCircularPrimitive::rasterizePolygons(DocumentManager* context, Winding winding)
 {
 	Model cylinderBody {context};
-	buildPrimitiveBody(cylinderBody);
+	buildPrimitiveBody(cylinderBody, true);
 	QVector<LDPolygon> result;
 	bool cachedShouldInvert = shouldInvert(winding, context);
 
@@ -121,14 +121,14 @@
 	return result;
 }
 
-void LDCircularPrimitive::buildPrimitiveBody(Model& model) const
+void LDCircularPrimitive::buildPrimitiveBody(Model& model, bool deep) const
 {
 	PrimitiveModel primitive;
 	primitive.type = m_type;
 	primitive.segments = m_segments;
 	primitive.divisions = m_divisions;
 	primitive.ringNumber = 0;
-	primitive.generateBody(model);
+	primitive.generateBody(model, deep);
 }
 
 QString LDCircularPrimitive::stem() const
@@ -147,6 +147,12 @@
 	case PrimitiveModel::DiscNegative:
 		return "ndis";
 
+	case PrimitiveModel::CylinderClosed:
+		return "cylc";
+
+	case PrimitiveModel::CylinderOpen:
+		return "cylo";
+
 	default:
 		throw std::logic_error("Bad primitive type to LDCircularPrimitive");
 	}
@@ -218,6 +224,8 @@
 		throw std::logic_error("Bad primitive type to LDCircularPrimitive");
 
 	case PrimitiveModel::Cylinder:
+	case PrimitiveModel::CylinderClosed:
+	case PrimitiveModel::CylinderOpen:
 		return 2 * m_segments;
 
 	case PrimitiveModel::Disc:
@@ -250,6 +258,12 @@
 
 	case PrimitiveModel::Circle:
 		return "circle";
+
+	case PrimitiveModel::CylinderClosed:
+		return "cylinder-closed";
+
+	case PrimitiveModel::CylinderOpen:
+		return "cylinder-open";
 	}
 
 	return "";
--- a/src/linetypes/circularprimitive.h	Sun Jun 17 16:13:24 2018 +0300
+++ b/src/linetypes/circularprimitive.h	Sun Jun 17 17:07:29 2018 +0300
@@ -40,7 +40,7 @@
 
 private:
 	QString buildFilename() const;
-	void buildPrimitiveBody(Model& model) const;
+	void buildPrimitiveBody(Model& model, bool newParameter = false) const;
 	QString stem() const;
 
 	PrimitiveModel::Type m_type = PrimitiveModel::Circle;
--- a/src/parser.cpp	Sun Jun 17 16:13:24 2018 +0300
+++ b/src/parser.cpp	Sun Jun 17 17:07:29 2018 +0300
@@ -391,7 +391,9 @@
 					matrix(i / 3, i % 3) = tokens[i + 5].toDouble(); // 5 - 13
 
 				matrix.optimize();
-				static const QRegExp circularPrimitiveRegexp {R"((?:(\d+)\\)?(\d+)-(\d+)(cyli|edge|disc|ndis)\.dat)"};
+				static const QRegExp circularPrimitiveRegexp {
+					R"((?:(\d+)\\)?(\d+)-(\d+)(cyli|edge|disc|ndis|cylc|cylo)\.dat)"
+				};
 				LDObject* obj;
 
 				if (circularPrimitiveRegexp.exactMatch(referenceName))
@@ -413,6 +415,10 @@
 						type = PrimitiveModel::Disc;
 					else if (stem == "ndis")
 						type = PrimitiveModel::DiscNegative;
+					else if (stem == "cylc")
+						type = PrimitiveModel::CylinderClosed;
+					else if (stem == "cylo")
+						type = PrimitiveModel::CylinderOpen;
 
 					obj = model.emplaceAt<LDCircularPrimitive>(
 						position,
--- a/src/primitives.cpp	Sun Jun 17 16:13:24 2018 +0300
+++ b/src/primitives.cpp	Sun Jun 17 17:07:29 2018 +0300
@@ -32,6 +32,7 @@
 #include "linetypes/empty.h"
 #include "linetypes/quadrilateral.h"
 #include "linetypes/triangle.h"
+#include "linetypes/circularprimitive.h"
 
 PrimitiveManager::PrimitiveManager(QObject* parent) :
 	QAbstractItemModel {parent},
@@ -265,7 +266,6 @@
 
 void PrimitiveModel::generateCylinder(Model& model, Winding winding) const
 {
-	Q_ASSERT(this->type == Cylinder);
 	auto circle = makeCircle(this->segments, this->divisions, 1);
 	bool useTangents = (this->segments != this->divisions);
 
@@ -328,7 +328,7 @@
 /*
  * Builds a circle primitive.
  */
-void PrimitiveModel::generateCircle(Model& model) const
+void PrimitiveModel::generateCircle(Model& model, const QMatrix4x4& matrix) const
 {
 	QVector<QLineF> circle = makeCircle(segments, divisions, 1);
 
@@ -340,13 +340,41 @@
 		double z1 = circle[i].y2();
 
 		LDEdgeLine* line = model.emplace<LDEdgeLine>();
-		line->setVertex(0, Vertex {x0, 0.0f, z0});
-		line->setVertex(1, Vertex {x1, 0.0f, z1});
+		line->setVertex(0, Vertex {x0, 0.0f, z0}.transformed(matrix));
+		line->setVertex(1, Vertex {x1, 0.0f, z1}.transformed(matrix));
 		line->setColor(EdgeColor);
 	}
 }
 
-void PrimitiveModel::generateBody(Model& model) const
+void PrimitiveModel::generateDisc(Model& model) const
+{
+	QVector<QLineF> circle = makeCircle(segments, divisions, 1);
+
+	for (int i = 0; i < segments; ++i)
+	{
+		LDTriangle* segment = model.emplace<LDTriangle>();
+		segment->setColor(MainColor);
+		segment->setVertex(0, {circle[i].x1(), 0.0, circle[i].y1()});
+		segment->setVertex(1, {circle[i].x2(), 0.0, circle[i].y2()});
+		segment->setVertex(2, {0.0, 0.0, 0.0});
+	}
+}
+
+void PrimitiveModel::generateDiscNegative(Model& model) const
+{
+	QVector<QLineF> circle = makeCircle(segments, divisions, 1);
+
+	for (int i = 0; i < segments; ++i)
+	{
+		LDTriangle* segment = model.emplace<LDTriangle>();
+		segment->setColor(MainColor);
+		segment->setVertex(0, {(circle[i].x1() >= 0.0) ? 1.0 : -1.0, 0.0, (circle[i].y1() >= 0.0) ? 1.0 : -1.0});
+		segment->setVertex(1, {circle[i].x2(), 0.0, circle[i].y2()});
+		segment->setVertex(2, {circle[i].x1(), 0.0, circle[i].y1()});
+	}
+}
+
+void PrimitiveModel::generateBody(Model& model, bool deep) const
 {
 	switch (type)
 	{
@@ -358,6 +386,39 @@
 		generateCircle(model);
 		return;
 
+	case Disc:
+		generateDisc(model);
+		return;
+
+	case DiscNegative:
+		generateDiscNegative(model);
+		return;
+
+	case CylinderClosed:
+		if (deep)
+			generateDisc(model);
+		else
+			model.emplace<LDCircularPrimitive>(Disc, segments, divisions, QMatrix4x4 {});
+	case CylinderOpen:
+		{
+			QMatrix4x4 endCircleMatrix;
+			endCircleMatrix.translate(0, 1, 0);
+
+			if (deep)
+			{
+				generateCylinder(model);
+				generateCircle(model);
+				generateCircle(model, endCircleMatrix);
+			}
+			else
+			{
+				model.emplace<LDCircularPrimitive>(Cylinder, segments, divisions, QMatrix4x4 {});
+				model.emplace<LDCircularPrimitive>(Circle, segments, divisions, QMatrix4x4 {});
+				model.emplace<LDCircularPrimitive>(Circle, segments, divisions, endCircleMatrix);
+			}
+		}
+		return;
+
 	default:
 		break;
 	}
@@ -414,35 +475,10 @@
 
 		case Disc:
 		case DiscNegative:
-			{
-				double x2, z2;
-
-				if (type == Disc)
-				{
-					x2 = z2 = 0.0;
-				}
-				else
-				{
-					x2 = (x0 >= 0.0) ? 1.0 : -1.0;
-					z2 = (z0 >= 0.0) ? 1.0 : -1.0;
-				}
-
-				Vertex v0 = {x0, 0.0, z0};
-				Vertex v1 = {x1, 0.0, z1};
-				Vertex v2 = {x2, 0.0, z2};
-
-				// Disc negatives need to go the other way around, otherwise
-				// they'll end up upside-down.
-				LDTriangle* segment = model.emplace<LDTriangle>();
-				segment->setColor(MainColor);
-				segment->setVertex(type == Disc ? 0 : 2, v0);
-				segment->setVertex(1, v1);
-				segment->setVertex(type == Disc ? 2 : 0, v2);
-			}
-			break;
-
 		case Circle:
 		case Cylinder:
+		case CylinderClosed:
+		case CylinderOpen:
 			break;
 		}
 	}
@@ -484,7 +520,17 @@
 QString PrimitiveModel::typeName(PrimitiveModel::Type type)
 {
 	// Not translated as primitives are in English.
-	const char* names[] = {"Circle", "Cylinder", "Disc", "Disc Negative", "Ring", "Cone"};
+	const char* names[] =
+	{
+		"Circle",
+		"Cylinder",
+		"Disc",
+		"Disc Negative",
+		"Ring",
+		"Cone",
+		"Cylinder Closed",
+		"Cylinder Open"
+	};
 
 	if (type >= 0 and type < countof(names))
 		return names[type];
--- a/src/primitives.h	Sun Jun 17 16:13:24 2018 +0300
+++ b/src/primitives.h	Sun Jun 17 17:07:29 2018 +0300
@@ -50,17 +50,23 @@
 		DiscNegative,
 		Ring,
 		Cone,
+		CylinderClosed,
+		CylinderOpen,
 	} type;
 	int segments;
 	int divisions;
 	int ringNumber;
 
 	QString typeName() const;
-	void generateBody(Model& model) const;
+	void generateBody(Model& model, bool deep = false) const;
 	void generateCylinder(Model& model, Winding winding = CounterClockwise) const;
-	void generateCircle(Model& model) const;
+	void generateCircle(Model& model, const QMatrix4x4& matrix = {}) const;
 	static QString typeName(Type type);
 	QString makeFileName(FilenameStyle style) const;
+	void generateDisc(Model& model) const;
+
+private:
+	void generateDiscNegative(Model& model) const;
 };
 
 Q_DECLARE_METATYPE(PrimitiveModel::Type)
--- a/src/types/vertex.cpp	Sun Jun 17 16:13:24 2018 +0300
+++ b/src/types/vertex.cpp	Sun Jun 17 17:07:29 2018 +0300
@@ -200,13 +200,16 @@
 	return {
 		matrix(0, 0) * this->x
 			+ matrix(0, 1) * this->y
-			+ matrix(0, 2) * this->z,
+			+ matrix(0, 2) * this->z
+			+ matrix(0, 3),
 		matrix(1, 0) * this->x
 			+ matrix(1, 1) * this->y
-			+ matrix(1, 2) * this->z,
+			+ matrix(1, 2) * this->z
+			+ matrix(1, 3),
 		matrix(2, 0) * this->x
 			+ matrix(2, 1) * this->y
-			+ matrix(2, 2) * this->z,
+			+ matrix(2, 2) * this->z
+			+ matrix(2, 3),
 	};
 }
 

mercurial