# HG changeset patch # User Teemu Piippo # Date 1521449833 -7200 # Node ID 4a4e9fb9da76dc3145e568be2d69215401b52a2c # Parent 609b75b026c4c3313b1c28a5e0b9fd08452c20b8 moved inverting code into a new file diff -r 609b75b026c4 -r 4a4e9fb9da76 CMakeLists.txt --- a/CMakeLists.txt Sun Mar 18 23:31:15 2018 +0200 +++ b/CMakeLists.txt Mon Mar 19 10:57:13 2018 +0200 @@ -57,6 +57,7 @@ src/serializer.cpp src/ringFinder.cpp src/version.cpp + src/algorithms/invert.cpp src/dialogs/colorselector.cpp src/dialogs/configdialog.cpp src/dialogs/externalprogrampathdialog.cpp @@ -128,6 +129,7 @@ src/ringFinder.h src/serializer.h src/transform.h + src/algorithms/invert.h src/dialogs/colorselector.h src/dialogs/configdialog.h src/dialogs/externalprogrampathdialog.h diff -r 609b75b026c4 -r 4a4e9fb9da76 src/algorithms/invert.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/algorithms/invert.cpp Mon Mar 19 10:57:13 2018 +0200 @@ -0,0 +1,121 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 - 2017 Teemu Piippo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "../linetypes/modelobject.h" +#include "../lddocument.h" + +/* + * Returns whether or not the document is flat. + * If it is flat, the result is stored in *axis. + */ +bool isflat(Model* model, Axis* axis) +{ + QVector axisSet = {X, Y, Z}; + + for (LDObject* subfileObject : model->objects()) + { + for (int i = 0; i < subfileObject->numVertices(); ++i) + { + Vertex const& v_i = subfileObject->vertex(i); + + if (not qFuzzyCompare(v_i.x(), 0.f)) + axisSet.removeOne(X); + + if (not qFuzzyCompare(v_i.y(), 0.f)) + axisSet.removeOne(Y); + + if (not qFuzzyCompare(v_i.z(), 0.f)) + axisSet.removeOne(Z); + } + + if (axisSet.isEmpty()) + break; + } + + if (axisSet.size() == 1) + { + *axis = axisSet[0]; + return true; + } + else + { + return false; + } +} + +/* + * Returns a matrix that causes a flip on the given axis. + */ +Matrix flipmatrix(Axis axis) +{ + Matrix result = Matrix::identity; + + switch (axis) + { + case X: + result(0, 0) = -1; + break; + + case Y: + result(1, 1) = -1; + break; + + case Z: + result(2, 2) = -1; + break; + } + + return result; +} + +/* + * Inverts an LDObject so that its winding is changed. + */ +void invert(LDObject* obj, DocumentManager* context) +{ + if (obj->numPolygonVertices() > 0) + { + QVector vertices; + + for (int i = 0; i < obj->numPolygonVertices(); i += 1) + vertices.append(obj->vertex(i)); + + for (int i = 0; i < vertices.size(); i += 1) + obj->setVertex(i, vertices[vertices.size() - 1 - i]); + } + else if (obj->type() == LDObjectType::SubfileReference) + { + // Check whether subfile is flat. If it is, flip it on the axis on which it is flat. + Model model {context}; + LDSubfileReference* reference = static_cast(obj); + reference->fileInfo(context)->inlineContents(model, true, false); + Axis flatAxis; + + if (isflat(&model, &flatAxis)) + { + reference->setTransformationMatrix( + reference->transformationMatrix() * flipmatrix(flatAxis) + ); + } + else + { + // Subfile is not flat. Resort to invertnext. + reference->setInverted(not reference->isInverted()); + } + } +} diff -r 609b75b026c4 -r 4a4e9fb9da76 src/algorithms/invert.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/algorithms/invert.h Mon Mar 19 10:57:13 2018 +0200 @@ -0,0 +1,24 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 - 2017 Teemu Piippo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include "../main.h" + +bool isflat(class Model* model, Axis* axis); +Matrix flipmatrix(Axis axis); +void invert(LDObject* obj, class DocumentManager* context); diff -r 609b75b026c4 -r 4a4e9fb9da76 src/toolsets/basictoolset.cpp --- a/src/toolsets/basictoolset.cpp Sun Mar 18 23:31:15 2018 +0200 +++ b/src/toolsets/basictoolset.cpp Mon Mar 19 10:57:13 2018 +0200 @@ -37,6 +37,7 @@ #include "../grid.h" #include "../parser.h" #include "../widgets/vertexobjecteditor.h" +#include "../algorithms/invert.h" #include "basictoolset.h" #include "guiutilities.h" @@ -228,70 +229,8 @@ void BasicToolset::invert() { - for (LDObject* obj : selectedObjects()) - { - if (obj->numPolygonVertices() > 0) - { - QVector vertices; - - for (int i = 0; i < obj->numPolygonVertices(); i += 1) - vertices.append(obj->vertex(i)); - - for (int i = 0; i < vertices.size(); i += 1) - obj->setVertex(i, vertices[vertices.size() - 1 - i]); - } - else if (obj->type() == LDObjectType::SubfileReference) - { - // Check whether subfile is flat - int axisSet = (1 << X) | (1 << Y) | (1 << Z); - Model model {currentDocument()->documentManager()}; - LDSubfileReference* reference = static_cast(obj); - reference->fileInfo(m_documents)->inlineContents(model, true, false); - - for (LDObject* subobj : model.objects()) - { - for (int i = 0; i < subobj->numVertices(); ++i) - { - Vertex const& vrt = subobj->vertex (i); - - if (axisSet & (1 << X) and vrt.x() != 0.0) - axisSet &= ~(1 << X); - - if (axisSet & (1 << Y) and vrt.y() != 0.0) - axisSet &= ~(1 << Y); - - if (axisSet & (1 << Z) and vrt.z() != 0.0) - axisSet &= ~(1 << Z); - } - - if (axisSet == 0) - break; - } - - if (axisSet != 0) - { - // Subfile has all vertices zero on one specific plane, so it is flat. - // Let's flip it. - Matrix matrixModifier = Matrix::identity; - - if (axisSet & (1 << X)) - matrixModifier(0, 0) = -1; - - if (axisSet & (1 << Y)) - matrixModifier(1, 1) = -1; - - if (axisSet & (1 << Z)) - matrixModifier(2, 2) = -1; - - reference->setTransformationMatrix(reference->transformationMatrix() * matrixModifier); - } - else - { - // Subfile is not flat. Resort to invertnext. - reference->setInverted(not reference->isInverted()); - } - } - } + for (LDObject* object : selectedObjects()) + ::invert(object, m_documents); } template