--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/linetypes/compoundobject.cpp Tue Mar 15 18:52:48 2022 +0200 @@ -0,0 +1,115 @@ +#include "compoundobject.h" +#include "documentmanager.h" +#include "invert.h" +#include "polygoncache.h" + +ldraw::CompoundObject::CompoundObject +( + const glm::mat4& transformation, + const Color color +) : + ColoredObject{color}, + transformation{transformation} +{ +} + +QVariant ldraw::CompoundObject::getProperty(Property property) const +{ + switch (property) + { + case Property::Transformation: + return QVariant::fromValue(this->transformation); + case Property::IsInverted: + return this->isInverted; + default: + return ColoredObject::getProperty(property); + } +} + +void ldraw::CompoundObject::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) +{ + LDRAW_OBJECT_HANDLE_SET_PROPERTY(Transformation, {this->transformation = value;}); + LDRAW_OBJECT_HANDLE_SET_PROPERTY(IsInverted, {this->isInverted = value;}); + ldraw::ColoredObject::setProperty(result, pair); +} + +glm::vec3 ldraw::CompoundObject::position() const +{ + return this->transformation[3]; +} + +void ldraw::CompoundObject::invert(GetPolygonsContext *context) +{ + const std::optional<Axis> flatDimension = context ? this->flatDimension(context) : std::optional<Axis>{}; + if (flatDimension.has_value()) + { + glm::mat4 matrix = glm::identity<glm::mat4>(); + matrix[*flatDimension][*flatDimension] = -1.0f; + this->transformation *= matrix; + } + else + { + this->isInverted = not this->isInverted; + } +} + + +QDataStream& ldraw::CompoundObject::serialize(QDataStream &stream) const +{ + return ColoredObject::serialize(stream) << this->transformation << this->isInverted; +} + +QDataStream& ldraw::CompoundObject::deserialize(QDataStream &stream) +{ + return ColoredObject::deserialize(stream) >> this->transformation >> this->isInverted; +} + +/** + * @brief Finds out in which dimension the object is flat in. In that dimension all vertices have a value of 0. + * If the object is not flat, this does not return a value. + * @param model Model to find out flatness of + * @param documents Where to look for subfiles + * @returns dimension the model is flat in, if such dimension exists, no value otherwise. + */ +std::optional<Axis> ldraw::CompoundObject::flatDimension(GetPolygonsContext *context) const +{ + // The dimensions that this model is potentially flat in. + QVector<Axis> dimensions = {X, Y, Z}; + std::vector<gl::Polygon> polygons; + this->getPolygons(polygons, context); + for (const gl::Polygon& polygon : polygons) + { + for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1) + { + const glm::vec3& v_i = polygon.vertices[i]; + if (not qFuzzyCompare(v_i.x, 0.0f)) + { + dimensions.removeOne(X); + } + if (not qFuzzyCompare(v_i.y, 0.0f)) + { + dimensions.removeOne(Y); + } + if (not qFuzzyCompare(v_i.z, 0.0f)) + { + dimensions.removeOne(Z); + } + } + // If there are no more dimensions left, we can exit the loop. + if (dimensions.isEmpty()) + { + break; + } + } + if (dimensions.size() == 1) + { + // The model is flat in one dimension, return that. + // If the model is flat in two or three dimensions, it's not really a valid model. + return dimensions[0]; + } + else + { + // The model is not flat. + return {}; + } +}