23
#include "PreCompiled.h"
25
#include <boost/tokenizer.hpp>
29
#include <xercesc/dom/DOM.hpp>
30
#include <xercesc/parsers/XercesDOMParser.hpp>
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>
43
using namespace MeshCore;
44
XERCES_CPP_NAMESPACE_USE
46
Reader3MF::Reader3MF(std::istream& str)
48
zipios::ZipHeader zipHeader(str);
49
if (zipHeader.isValid()) {
50
zip.reset(zipHeader.getInputStream("3D/3dmodel.model"));
54
Reader3MF::Reader3MF(const std::string& filename)
56
zipios::ZipFile zipFile(filename);
57
if (zipFile.isValid()) {
58
zip.reset(zipFile.getInputStream("3D/3dmodel.model"));
62
std::vector<int> Reader3MF::GetMeshIds() const
65
ids.reserve(meshes.size());
66
for (const auto& it : meshes) {
67
ids.emplace_back(it.first);
79
return LoadModel(*zip);
81
catch (const std::exception&) {
86
bool Reader3MF::LoadModel(std::istream& str)
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);
96
Base::StdInputSource inputSource(str, "3dmodel.model");
97
parser->parse(inputSource);
98
std::unique_ptr<DOMDocument> xmlDocument(parser->adoptDocument());
99
return LoadModel(*xmlDocument);
101
catch (const XMLException&) {
104
catch (const DOMException&) {
109
bool Reader3MF::LoadModel(DOMDocument& xmlDocument)
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);
126
bool Reader3MF::LoadResources(DOMNodeList* nodes)
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);
144
bool Reader3MF::LoadBuild(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
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);
162
bool Reader3MF::LoadItems(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
164
const std::size_t numEntries = 12;
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());
173
std::string id = StrX(idAttr->getNodeValue()).c_str();
174
int idValue = std::stoi(id);
177
DOMNode* transformAttr =
178
itemNode->getAttributes()->getNamedItem(XStr("transform").unicodeForm());
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]);
200
meshes.at(idValue).second = mat;
202
catch (const std::exception&) {
212
bool Reader3MF::LoadObjects(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes)
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());
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);
231
return (!meshes.empty());
234
void Reader3MF::LoadMesh(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes, int id)
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()),
248
LoadTriangles(static_cast<DOMElement*>(node)->getElementsByTagName(
249
XStr("triangles").unicodeForm()),
252
MeshCleanup meshCleanup(points, facets);
253
meshCleanup.RemoveInvalids();
254
MeshPointFacetAdjacency meshAdj(points.size(), facets);
255
meshAdj.SetFacetNeighbourhood();
258
kernel.Adopt(points, facets);
259
meshes.emplace(id, std::make_pair(kernel, Base::Matrix4D()));
264
void Reader3MF::LoadVertices(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes,
265
MeshPointArray& points)
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());
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();
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);
299
void Reader3MF::LoadTriangles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes,
300
MeshFacetArray& facets)
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());
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();
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);