FreeCAD

Форк
0
/
Reader3MF.cpp 
332 строки · 12.1 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2022 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
#include <boost/tokenizer.hpp>
26
#include <memory>
27
#include <ostream>
28
#include <sstream>
29
#include <xercesc/dom/DOM.hpp>
30
#include <xercesc/parsers/XercesDOMParser.hpp>
31
#endif
32

33
#include "Core/MeshIO.h"
34
#include "Core/MeshKernel.h"
35
#include <Base/InputSource.h>
36
#include <Base/XMLTools.h>
37
#include <Base/ZipHeader.h>
38
#include <zipios++/zipfile.h>
39

40
#include "Reader3MF.h"
41

42

43
using namespace MeshCore;
44
XERCES_CPP_NAMESPACE_USE
45

46
Reader3MF::Reader3MF(std::istream& str)
47
{
48
    zipios::ZipHeader zipHeader(str);
49
    if (zipHeader.isValid()) {
50
        zip.reset(zipHeader.getInputStream("3D/3dmodel.model"));
51
    }
52
}
53

54
Reader3MF::Reader3MF(const std::string& filename)
55
{
56
    zipios::ZipFile zipFile(filename);
57
    if (zipFile.isValid()) {
58
        zip.reset(zipFile.getInputStream("3D/3dmodel.model"));
59
    }
60
}
61

62
std::vector<int> Reader3MF::GetMeshIds() const
63
{
64
    std::vector<int> ids;
65
    ids.reserve(meshes.size());
66
    for (const auto& it : meshes) {
67
        ids.emplace_back(it.first);
68
    }
69

70
    return ids;
71
}
72

73
bool Reader3MF::Load()
74
{
75
    try {
76
        if (!zip) {
77
            return false;
78
        }
79
        return LoadModel(*zip);
80
    }
81
    catch (const std::exception&) {
82
        return false;
83
    }
84
}
85

86
bool Reader3MF::LoadModel(std::istream& str)
87
{
88
    try {
89
        std::unique_ptr<XercesDOMParser> parser(new XercesDOMParser);
90
        parser->setValidationScheme(XercesDOMParser::Val_Auto);
91
        parser->setDoNamespaces(false);
92
        parser->setDoSchema(false);
93
        parser->setValidationSchemaFullChecking(false);
94
        parser->setCreateEntityReferenceNodes(false);
95

96
        Base::StdInputSource inputSource(str, "3dmodel.model");
97
        parser->parse(inputSource);
98
        std::unique_ptr<DOMDocument> xmlDocument(parser->adoptDocument());
99
        return LoadModel(*xmlDocument);
100
    }
101
    catch (const XMLException&) {
102
        return false;
103
    }
104
    catch (const DOMException&) {
105
        return false;
106
    }
107
}
108

109
bool Reader3MF::LoadModel(DOMDocument& xmlDocument)
110
{
111
    DOMNodeList* nodes = xmlDocument.getElementsByTagName(XStr("model").unicodeForm());
112
    for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
113
        DOMNode* node = nodes->item(i);
114
        if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
115
            bool resource = LoadResources(static_cast<DOMElement*>(node)->getElementsByTagName(
116
                XStr("resources").unicodeForm()));
117
            bool build = LoadBuild(
118
                static_cast<DOMElement*>(node)->getElementsByTagName(XStr("build").unicodeForm()));
119
            return (resource && build);
120
        }
121
    }
122

123
    return false;
124
}
125

126
bool Reader3MF::LoadResources(DOMNodeList* nodes)
127
{
128
    if (!nodes) {
129
        return false;
130
    }
131

132
    for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
133
        DOMNode* node = nodes->item(i);
134
        if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
135
            DOMNodeList* objectList =
136
                static_cast<DOMElement*>(node)->getElementsByTagName(XStr("object").unicodeForm());
137
            return LoadObjects(objectList);
138
        }
139
    }
140

141
    return false;
142
}
143

144
bool Reader3MF::LoadBuild(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
145
{
146
    if (!nodes) {
147
        return false;
148
    }
149

150
    for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
151
        DOMNode* node = nodes->item(i);
152
        if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
153
            DOMNodeList* objectList =
154
                static_cast<DOMElement*>(node)->getElementsByTagName(XStr("item").unicodeForm());
155
            return LoadItems(objectList);
156
        }
157
    }
158

159
    return false;
160
}
161

162
bool Reader3MF::LoadItems(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
163
{
164
    const std::size_t numEntries = 12;
165
    if (!nodes) {
166
        return false;
167
    }
168

169
    for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
170
        DOMNode* itemNode = nodes->item(i);
171
        DOMNode* idAttr = itemNode->getAttributes()->getNamedItem(XStr("objectid").unicodeForm());
172
        if (idAttr) {
173
            std::string id = StrX(idAttr->getNodeValue()).c_str();
174
            int idValue = std::stoi(id);
175
            Base::Matrix4D mat;
176

177
            DOMNode* transformAttr =
178
                itemNode->getAttributes()->getNamedItem(XStr("transform").unicodeForm());
179
            if (transformAttr) {
180
                std::string transform = StrX(transformAttr->getNodeValue()).c_str();
181
                boost::char_separator<char> sep(" ,");
182
                boost::tokenizer<boost::char_separator<char>> tokens(transform, sep);
183
                std::vector<std::string> token_results;
184
                token_results.assign(tokens.begin(), tokens.end());
185
                if (token_results.size() == numEntries) {
186
                    mat[0][0] = std::stod(token_results[0]);
187
                    mat[1][0] = std::stod(token_results[1]);
188
                    mat[2][0] = std::stod(token_results[2]);
189
                    mat[0][1] = std::stod(token_results[3]);
190
                    mat[1][1] = std::stod(token_results[4]);
191
                    mat[2][1] = std::stod(token_results[5]);
192
                    mat[0][2] = std::stod(token_results[6]);
193
                    mat[1][2] = std::stod(token_results[7]);
194
                    mat[2][2] = std::stod(token_results[8]);
195
                    mat[0][3] = std::stod(token_results[9]);
196
                    mat[1][3] = std::stod(token_results[10]);
197
                    mat[2][3] = std::stod(token_results[11]);
198

199
                    try {
200
                        meshes.at(idValue).second = mat;
201
                    }
202
                    catch (const std::exception&) {
203
                    }
204
                }
205
            }
206
        }
207
    }
208

209
    return true;
210
}
211

212
bool Reader3MF::LoadObjects(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
213
{
214
    if (!nodes) {
215
        return false;
216
    }
217

218
    for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
219
        DOMNode* objectNode = nodes->item(i);
220
        if (objectNode->getNodeType() == DOMNode::ELEMENT_NODE) {
221
            DOMNode* idAttr = objectNode->getAttributes()->getNamedItem(XStr("id").unicodeForm());
222
            if (idAttr) {
223
                int id = std::stoi(StrX(idAttr->getNodeValue()).c_str());
224
                DOMNodeList* meshList = static_cast<DOMElement*>(objectNode)
225
                                            ->getElementsByTagName(XStr("mesh").unicodeForm());
226
                LoadMesh(meshList, id);
227
            }
228
        }
229
    }
230

231
    return (!meshes.empty());
232
}
233

234
void Reader3MF::LoadMesh(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes, int id)
235
{
236
    if (!nodes) {
237
        return;
238
    }
239

240
    for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
241
        DOMNode* node = nodes->item(i);
242
        if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
243
            MeshPointArray points;
244
            MeshFacetArray facets;
245
            LoadVertices(static_cast<DOMElement*>(node)->getElementsByTagName(
246
                             XStr("vertices").unicodeForm()),
247
                         points);
248
            LoadTriangles(static_cast<DOMElement*>(node)->getElementsByTagName(
249
                              XStr("triangles").unicodeForm()),
250
                          facets);
251

252
            MeshCleanup meshCleanup(points, facets);
253
            meshCleanup.RemoveInvalids();
254
            MeshPointFacetAdjacency meshAdj(points.size(), facets);
255
            meshAdj.SetFacetNeighbourhood();
256

257
            MeshKernel kernel;
258
            kernel.Adopt(points, facets);
259
            meshes.emplace(id, std::make_pair(kernel, Base::Matrix4D()));
260
        }
261
    }
262
}
263

264
void Reader3MF::LoadVertices(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes,
265
                             MeshPointArray& points)
266
{
267
    if (!nodes) {
268
        return;
269
    }
270

271
    for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
272
        DOMNode* node = nodes->item(i);
273
        if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
274
            DOMNodeList* vertexList =
275
                static_cast<DOMElement*>(node)->getElementsByTagName(XStr("vertex").unicodeForm());
276
            if (vertexList) {
277
                XMLSize_t numVertices = vertexList->getLength();
278
                points.reserve(numVertices);
279
                for (XMLSize_t j = 0; j < numVertices; j++) {
280
                    DOMNode* vertexNode = vertexList->item(j);
281
                    DOMNamedNodeMap* attr = vertexNode->getAttributes();
282
                    if (attr) {
283
                        DOMNode* xAttr = attr->getNamedItem(XStr("x").unicodeForm());
284
                        DOMNode* yAttr = attr->getNamedItem(XStr("y").unicodeForm());
285
                        DOMNode* zAttr = attr->getNamedItem(XStr("z").unicodeForm());
286
                        if (xAttr && yAttr && zAttr) {
287
                            float x = std::stof(StrX(xAttr->getNodeValue()).c_str());
288
                            float y = std::stof(StrX(yAttr->getNodeValue()).c_str());
289
                            float z = std::stof(StrX(zAttr->getNodeValue()).c_str());
290
                            points.emplace_back(x, y, z);
291
                        }
292
                    }
293
                }
294
            }
295
        }
296
    }
297
}
298

299
void Reader3MF::LoadTriangles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes,
300
                              MeshFacetArray& facets)
301
{
302
    if (!nodes) {
303
        return;
304
    }
305

306
    for (XMLSize_t i = 0; i < nodes->getLength(); i++) {
307
        DOMNode* node = nodes->item(i);
308
        if (node->getNodeType() == DOMNode::ELEMENT_NODE) {
309
            DOMNodeList* triangleList = static_cast<DOMElement*>(node)->getElementsByTagName(
310
                XStr("triangle").unicodeForm());
311
            if (triangleList) {
312
                XMLSize_t numTriangles = triangleList->getLength();
313
                facets.reserve(numTriangles);
314
                for (XMLSize_t j = 0; j < numTriangles; j++) {
315
                    DOMNode* triangleNode = triangleList->item(j);
316
                    DOMNamedNodeMap* attr = triangleNode->getAttributes();
317
                    if (attr) {
318
                        DOMNode* v1Attr = attr->getNamedItem(XStr("v1").unicodeForm());
319
                        DOMNode* v2Attr = attr->getNamedItem(XStr("v2").unicodeForm());
320
                        DOMNode* v3Attr = attr->getNamedItem(XStr("v3").unicodeForm());
321
                        if (v1Attr && v2Attr && v3Attr) {
322
                            PointIndex v1 = std::stoul(StrX(v1Attr->getNodeValue()).c_str());
323
                            PointIndex v2 = std::stoul(StrX(v2Attr->getNodeValue()).c_str());
324
                            PointIndex v3 = std::stoul(StrX(v3Attr->getNodeValue()).c_str());
325
                            facets.emplace_back(v1, v2, v3);
326
                        }
327
                    }
328
                }
329
            }
330
        }
331
    }
332
}
333

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.