diff -r b179ab2f2c4e -r d68d1ce89d05 src/algorithms/geometry.cpp --- 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& 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 (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& objs) +{ + switch (static_cast(config::rotationPointType())) + { + case ObjectOrigin: + { + BoundingBox box; + + // Calculate center vertex + for (LDObject* obj : objs) + { + if (obj->hasMatrix()) + { + box << static_cast (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. *