src/linetypes/circularprimitive.cpp

changeset 1398
1c70d3447d20
parent 1394
8d9d0532b3df
child 1399
f52ea4078f5d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/linetypes/circularprimitive.cpp	Sun Jun 10 16:50:14 2018 +0300
@@ -0,0 +1,187 @@
+#include "../algorithms/geometry.h"
+#include "../glShared.h"
+#include "../model.h"
+#include "../algorithms/invert.h"
+#include "circularprimitive.h"
+#include "quadrilateral.h"
+#include "primitives.h"
+
+QString LDCircularPrimitive::buildFilename() const
+{
+	int numerator = this->m_segments;
+	int denominator = this->m_divisions;
+	QString prefix;
+
+	if (m_divisions != MediumResolution)
+		prefix = QString::number(m_divisions) + '\\';
+
+	simplify(numerator, denominator);
+
+	switch (m_type)
+	{
+	case PrimitiveModel::Cylinder:
+		return format("%1%2-%3cyli.dat", prefix, numerator, denominator);
+
+	case PrimitiveModel::Circle:
+		return format("%1%2-%3edge.dat", prefix, numerator, denominator);
+
+	default:
+		Q_ASSERT(false);
+		return "";
+	}
+}
+
+LDCircularPrimitive::LDCircularPrimitive(
+	PrimitiveModel::Type type,
+	int segments,
+	int divisions,
+	const Matrix& transformationMatrix,
+	const Vertex& position
+) :
+	LDMatrixObject {transformationMatrix, position},
+	m_type {type},
+	m_segments {segments},
+	m_divisions {divisions} {}
+
+LDObjectType LDCircularPrimitive::type() const
+{
+	return SubclassType;
+}
+
+QString LDCircularPrimitive::asText() const
+{
+	return LDSubfileReference(buildFilename(), transformationMatrix(), position()).asText();
+}
+
+void LDCircularPrimitive::getVertices(DocumentManager* /* context */, QSet<Vertex>& vertices) const
+{
+	int endSegment = (m_segments == m_divisions) ? m_segments : m_segments + 1;
+
+	for (int i = 0; i < endSegment; i += 1)
+	{
+		QPointF point2d = pointOnLDrawCircumference(i, m_divisions);
+
+		for (double y_value : {0.0, 1.0})
+		{
+			Vertex vertex {point2d.x(), y_value, point2d.y()};
+			vertex.transform(transformationMatrix(), position());
+			vertices.insert(vertex);
+		}
+	}
+}
+
+bool LDCircularPrimitive::isRasterizable() const { return true; }
+
+void LDCircularPrimitive::rasterize(
+	DocumentManager* context,
+	Winding /* parentWinding */,
+	Model& model,
+	bool /* deep */,
+	bool /* render */
+) {
+	Model cylinderBody {context};
+	buildPrimitiveBody(cylinderBody);
+
+	for (LDObject* object : cylinderBody.objects())
+	{
+		for (int i = 0; i < object->numVertices(); i += 1)
+		{
+			Vertex vertex = object->vertex(i);
+			vertex.transform(transformationMatrix(), position());
+			object->setVertex(i, vertex);
+		}
+	}
+
+	model.merge(cylinderBody);
+}
+
+QVector<LDPolygon> LDCircularPrimitive::rasterizePolygons(DocumentManager* context, Winding winding)
+{
+	Model cylinderBody {context};
+	buildPrimitiveBody(cylinderBody);
+	QVector<LDPolygon> result;
+	bool cachedShouldInvert = shouldInvert(winding, context);
+
+	for (LDObject* object : cylinderBody.objects())
+	{
+		for (int i = 0; i < object->numVertices(); i += 1)
+		{
+			Vertex vertex = object->vertex(i);
+			vertex.transform(transformationMatrix(), position());
+			object->setVertex(i, vertex);
+		}
+
+		LDPolygon* polygon = object->getPolygon();
+
+		if (polygon)
+		{
+			if (cachedShouldInvert)
+				invertPolygon(*polygon);
+
+			result.append(*polygon);
+		}
+
+		delete polygon;
+	}
+
+	return result;
+}
+
+void LDCircularPrimitive::buildPrimitiveBody(Model& model) const
+{
+	PrimitiveModel primitive;
+	primitive.type = m_type;
+	primitive.segments = m_segments;
+	primitive.divisions = m_divisions;
+	primitive.ringNumber = 0;
+	primitive.generateBody(model);
+}
+
+QString LDCircularPrimitive::objectListText() const
+{
+	QString result = format(
+		"%1 %2 %3, (",
+		PrimitiveModel::typeName(m_type),
+		m_segments / m_divisions,
+		position().toString(true)
+	);
+
+	for (int i = 0; i < 9; ++i)
+		result += format("%1%2", transformationMatrix().value(i), (i != 8) ? " " : "");
+
+	result += ')';
+	return result;
+}
+
+int LDCircularPrimitive::triangleCount(DocumentManager*) const
+{
+	switch (m_type)
+	{
+	case PrimitiveModel::Ring:
+	case PrimitiveModel::Cone:
+		throw std::logic_error("Bad primitive type to LDCircularPrimitive");
+
+	case PrimitiveModel::Cylinder:
+		return 2 * m_segments;
+
+	case PrimitiveModel::Disc:
+	case PrimitiveModel::DiscNegative:
+		return m_segments;
+
+	case PrimitiveModel::Circle:
+		return 0;
+	}
+
+	return 0;
+}
+
+QString LDCircularPrimitive::typeName() const
+{
+	return "circular-primitive";
+}
+
+void LDCircularPrimitive::serialize(class Serializer& serializer)
+{
+	LDMatrixObject::serialize(serializer);
+	serializer << m_segments << m_divisions;
+}

mercurial