src/algorithms/geometry.cpp

changeset 1328
d68d1ce89d05
parent 1326
69a90bd2dba2
child 1403
7a2d84112983
--- a/src/algorithms/geometry.cpp	Sat Mar 24 12:58:01 2018 +0200
+++ b/src/algorithms/geometry.cpp	Sat Mar 24 13:03:02 2018 +0200
@@ -17,6 +17,8 @@
  */
 
 #include "geometry.h"
+#include "../linetypes/modelobject.h"
+#include "../types/boundingbox.h"
 
 /*
  * LDraw uses 4 points of precision for sin and cos values. Primitives must be generated
@@ -66,6 +68,100 @@
 	return lines;
 }
 
+
+void rotateVertex(Vertex& vertex, const Vertex& rotationPoint, const Matrix& transformationMatrix)
+{
+	vertex -= rotationPoint.toVector();
+	vertex.transform (transformationMatrix, {0, 0, 0});
+	vertex += rotationPoint.toVector();
+}
+
+
+void rotateObjects(int l, int m, int n, double angle, const QVector<LDObject*>& objects)
+{
+	Vertex rotationPoint = getRotationPoint (objects);
+	double cosAngle = cos(angle);
+	double sinAngle = sin(angle);
+
+	// ref: http://en.wikipedia.org/wiki/Transformation_matrix#Rotation_2
+	Matrix transformationMatrix (
+	{
+		(l * l * (1 - cosAngle)) + cosAngle,
+		(m * l * (1 - cosAngle)) - (n * sinAngle),
+		(n * l * (1 - cosAngle)) + (m * sinAngle),
+
+		(l * m * (1 - cosAngle)) + (n * sinAngle),
+		(m * m * (1 - cosAngle)) + cosAngle,
+		(n * m * (1 - cosAngle)) - (l * sinAngle),
+
+		(l * n * (1 - cosAngle)) - (m * sinAngle),
+		(m * n * (1 - cosAngle)) + (l * sinAngle),
+		(n * n * (1 - cosAngle)) + cosAngle
+	});
+
+	// Apply the above matrix to everything
+	for (LDObject* obj : objects)
+	{
+		if (obj->numVertices())
+		{
+			for (int i = 0; i < obj->numVertices(); ++i)
+			{
+				Vertex v = obj->vertex (i);
+				rotateVertex(v, rotationPoint, transformationMatrix);
+				obj->setVertex (i, v);
+			}
+		}
+		else if (obj->hasMatrix())
+		{
+			LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (obj);
+
+			// Transform the position
+			Vertex v = mo->position();
+			rotateVertex(v, rotationPoint, transformationMatrix);
+			mo->setPosition (v);
+
+			// Transform the matrix
+			mo->setTransformationMatrix(transformationMatrix * mo->transformationMatrix());
+		}
+	}
+}
+
+
+Vertex getRotationPoint(const QVector<LDObject*>& objs)
+{
+	switch (static_cast<RotationPoint>(config::rotationPointType()))
+	{
+	case ObjectOrigin:
+		{
+			BoundingBox box;
+
+			// Calculate center vertex
+			for (LDObject* obj : objs)
+			{
+				if (obj->hasMatrix())
+				{
+					box << static_cast<LDMatrixObject*> (obj)->position();
+				}
+				else
+				{
+					for (int i = 0; i < obj->numVertices(); ++i)
+						box << obj->vertex(i);
+				}
+			}
+
+			return box.center();
+		}
+
+	case WorldOrigin:
+		return Vertex();
+
+	case CustomPoint:
+		return config::customRotationPoint();
+	}
+
+	return Vertex();
+}
+
 /*
  * Computes the shortest distance from a point to a rectangle.
  *

mercurial