Mon, 09 Mar 2020 22:12:50 +0200
finished splitQuadrilateral theoretically (untested)
/* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 - 2020 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 <http://www.gnu.org/licenses/>. */ #include "modeleditcontext.h" Model::EditContext::EditContext(Model& model) : storedModel{model} { } ldraw::id_t Model::EditContext::append(std::unique_ptr<ldraw::Object>&& object) { const ldraw::id_t id = object->id; this->model().objectsById[id] = object.get(); this->model().append(std::move(object)); return id; } void Model::EditContext::remove(int position) { this->model().remove(position); } void Model::EditContext::setObjectProperty( ldraw::id_t id, ldraw::Property property, const QVariant& value) { ldraw::Object* object = this->model().objectAt(id); if (object != nullptr) { object->setProperty(property, value); } } void Model::EditContext::invertObject(ldraw::id_t id) { auto it = this->model().objectsById.find(id); if (it != this->model().objectsById.end()) { ldraw::Object* object = it->second; object->invert(); } } Model& Model::EditContext::model() { return this->storedModel; } namespace { using PropertyTriplet = std::tuple<ldraw::Property, ldraw::Property, ldraw::Property>; } static std::array<PropertyTriplet, 2> diagonalToPointProperties(ldraw::Diagonal diagonal) { std::array<PropertyTriplet, 2> result; switch (diagonal) { case ldraw::Diagonal::Diagonal_13: result = { std::make_tuple(ldraw::Property::Point1, ldraw::Property::Point2, ldraw::Property::Point3), std::make_tuple(ldraw::Property::Point1, ldraw::Property::Point3, ldraw::Property::Point4) }; break; case ldraw::Diagonal::Diagonal_24: result = { std::make_tuple(ldraw::Property::Point1, ldraw::Property::Point2, ldraw::Property::Point4), std::make_tuple(ldraw::Property::Point2, ldraw::Property::Point3, ldraw::Property::Point4) }; break; } return result; } auto ldraw::splitQuadrilateral( Model::EditContext& editor, ldraw::quadrilateralid_t quadrilateral_id, ldraw::Diagonal splitType ) -> std::optional<std::pair<ldraw::triangleid_t, ldraw::triangleid_t>> { std::optional<std::pair<ldraw::triangleid_t, ldraw::triangleid_t>> result; QModelIndex index; const ldraw::Quadrilateral* quadrilateral = editor.model().get(quadrilateral_id, &index); if (quadrilateral != nullptr) { Q_ASSERT(index.isValid()); int position = index.row(); editor.remove(position); std::vector<ldraw::triangleid_t> triangles; triangles.reserve(2); const std::array<PropertyTriplet, 2> split = diagonalToPointProperties(splitType); for (const PropertyTriplet& properties : split) { const ldraw::triangleid_t triangle = editor.insert<ldraw::Triangle>( position, quadrilateral->getProperty(std::get<0>(properties)).value<glm::vec3>(), quadrilateral->getProperty(std::get<1>(properties)).value<glm::vec3>(), quadrilateral->getProperty(std::get<2>(properties)).value<glm::vec3>(), ldraw::Color{quadrilateral->getProperty(ldraw::Property::Color).toInt()}); triangles.push_back(triangle); position += 1; } result = {triangles[0], triangles[1]}; } return result; }