// SPDX-License-Identifier: LGPL-2.1-or-later /*************************************************************************** * Copyright (c) 2022 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library 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 Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include #include #include "Core/Evaluation.h" #include "Core/MeshKernel.h" #include #include "Writer3MF.h" using namespace MeshCore; Writer3MF::Writer3MF(std::ostream& str) : zip(str) { zip.putNextEntry("3D/3dmodel.model"); Initialize(zip); } Writer3MF::Writer3MF(const std::string& filename) : zip(filename) { zip.putNextEntry("3D/3dmodel.model"); Initialize(zip); } void Writer3MF::SetForceModel(bool model) { forceModel = model; } void Writer3MF::Initialize(std::ostream& str) { str << "\n" "\n" " FreeCAD\n"; str << Base::blanks(1) << "\n"; } void Writer3MF::Finish(std::ostream& str) { str << Base::blanks(1) << "\n"; str << Base::blanks(1) << "\n"; for (const auto& it : items) { str << Base::blanks(2) << it; } str << Base::blanks(1) << "\n"; str << "\n"; } bool Writer3MF::AddMesh(const MeshKernel& mesh, const Base::Matrix4D& mat) { int id = ++objectIndex; SaveBuildItem(id, mat); return SaveObject(zip, id, mesh); } void Writer3MF::AddResource(const Resource3MF& res) { resources.emplace_back(res); } bool Writer3MF::Save() { Finish(zip); zip.closeEntry(); zip.putNextEntry("_rels/.rels"); if (!SaveRels(zip)) { return false; } zip.closeEntry(); zip.putNextEntry("[Content_Types].xml"); if (!SaveContent(zip)) { return false; } zip.closeEntry(); for (const auto& it : resources) { zip.putNextEntry(it.fileNameInZip); zip.write(it.fileContent.data(), static_cast(it.fileContent.size())); zip.closeEntry(); } return true; } bool Writer3MF::SaveObject(std::ostream& str, int id, const MeshKernel& mesh) const { // NOLINTBEGIN(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers) const MeshPointArray& rPoints = mesh.GetPoints(); const MeshFacetArray& rFacets = mesh.GetFacets(); if (!str || str.bad()) { return false; } str << Base::blanks(2) << "\n"; str << Base::blanks(3) << "\n"; // vertices str << Base::blanks(4) << "\n"; std::size_t index = 0; for (auto it = rPoints.begin(); it != rPoints.end(); ++it, ++index) { str << Base::blanks(5) << "x << "\" y=\"" << it->y << "\" z=\"" << it->z << "\" />\n"; } str << Base::blanks(4) << "\n"; // facet indices str << Base::blanks(4) << "\n"; for (const auto& it : rFacets) { str << Base::blanks(5) << "\n"; } str << Base::blanks(4) << "\n"; str << Base::blanks(3) << "\n"; str << Base::blanks(2) << "\n"; // NOLINTEND(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers) return true; } std::string Writer3MF::GetType(const MeshKernel& mesh) const { bool isSolid = (forceModel || MeshEvalSolid(mesh).Evaluate()); return isSolid ? "model" : "surface"; } void Writer3MF::SaveBuildItem(int id, const Base::Matrix4D& mat) { std::stringstream str; str << "\n"; items.push_back(str.str()); } std::string Writer3MF::DumpMatrix(const Base::Matrix4D& mat) { // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) // The matrix representation in the specs is the transposed version of Matrix4D // This means that for the 3x3 sub-matrix the indices must be swapped // // 3D Manufacturing Format / Core Specification & Reference Guide v1.2.3 // Chapter: 3.3 3D Matrices (page 9) std::stringstream str; str << mat[0][0] << " " << mat[1][0] << " " << mat[2][0] << " " << mat[0][1] << " " << mat[1][1] << " " << mat[2][1] << " " << mat[0][2] << " " << mat[1][2] << " " << mat[2][2] << " " << mat[0][3] << " " << mat[1][3] << " " << mat[2][3]; return str.str(); // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) } bool Writer3MF::SaveRels(std::ostream& str) const { // NOLINTBEGIN(modernize-raw-string-literal) int ids = 1; str << "\n" << "\n" << " \n"; for (const auto& it : resources) { str << " \n"; } str << "\n"; return true; // NOLINTEND(modernize-raw-string-literal) } bool Writer3MF::SaveContent(std::ostream& str) const { str << "\n" << "\n" << " \n" << " \n"; for (const auto& it : resources) { str << " \n"; } str << ""; return true; }