mirror of https://github.com/CGAL/cgal
Write a 3mf wrapper
This commit is contained in:
parent
934544dbde
commit
a36c7fe39b
|
|
@ -0,0 +1,186 @@
|
||||||
|
#ifndef READ_3MF_H
|
||||||
|
#define READ_3MF_H
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "Model/COM/NMR_DLLInterfaces.h"
|
||||||
|
namespace CGAL{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief read_soups_from_3mf extracts ranges of points and triangles from the
|
||||||
|
* `MeshObject`s contained in `file_name`
|
||||||
|
* \tparam PointRanges a model of the concepts `RandomAccessContainer` and
|
||||||
|
* `BackInsertionSequence` whose `value type` is
|
||||||
|
* a model of the concepts `RandomAccessContainer` and `BackInsertionSequence`
|
||||||
|
* whose `value type` is the point type.
|
||||||
|
* \tparam PolygonRanges a model of the concept `RandomAccessContainer` whose
|
||||||
|
* `value_type` is a model of the concept `RandomAccessContainer`
|
||||||
|
* whose `value_type` is a model of the concept `RandomAccessContainer` whose
|
||||||
|
* `value_type` is std::size_t.
|
||||||
|
* \param file_name the name of the 3mf file to read.
|
||||||
|
* \param all_points a `PointRanges` that will contain the points of the meshes
|
||||||
|
* in `file_name`.
|
||||||
|
* Each of these meshes will add a range of its points.
|
||||||
|
* \param all_polygons a `PolygonRanges` that will contain the triangles of the
|
||||||
|
* meshes in `file_name`.
|
||||||
|
* Each of these meshes will add a range of its triangles. A `triangle` of
|
||||||
|
* all_polygons[i] contains the indices of its points in all_points[i].
|
||||||
|
* \param names will contain the name of each mesh in `file_name` if any.
|
||||||
|
* If the i'th mesh has no name, it will be called "Unknown Mesh" in names.
|
||||||
|
* \return the number of meshes processed in `file_name`.
|
||||||
|
*/
|
||||||
|
template<typename PointRanges, typename PolygonRanges>
|
||||||
|
int read_soups_from_3mf(const std::string& file_name, PointRanges& all_points,
|
||||||
|
PolygonRanges& all_polygons, std::vector<std::string>& names)
|
||||||
|
{
|
||||||
|
typedef typename PointRanges::value_type PointRange;
|
||||||
|
typedef typename PointRange::value_type Point_3;
|
||||||
|
typedef typename PolygonRanges::value_type PolygonRange;
|
||||||
|
typedef typename PolygonRange::value_type Polygon;
|
||||||
|
DWORD nInterfaceVersionMajor, nInterfaceVersionMinor, nInterfaceVersionMicro, nbVertices, nbPolygons;
|
||||||
|
HRESULT hResult;
|
||||||
|
NMR::PLib3MFModel * pModel;
|
||||||
|
NMR::PLib3MFModelReader * pReader;
|
||||||
|
// Extract Extension of filename
|
||||||
|
std::string sReaderName("3mf");
|
||||||
|
|
||||||
|
hResult = NMR::lib3mf_getinterfaceversion(&nInterfaceVersionMajor, &nInterfaceVersionMinor, &nInterfaceVersionMicro);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not get 3MF Library version: " << std::hex << hResult << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Model Instance
|
||||||
|
hResult = NMR::lib3mf_createmodel(&pModel);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not create model: " << std::hex << hResult << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Model Reader
|
||||||
|
hResult = NMR::lib3mf_model_queryreader(pModel, sReaderName.c_str(), &pReader);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not create model reader: " << std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import Model from File
|
||||||
|
hResult = NMR::lib3mf_reader_readfromfileutf8(pReader, file_name.c_str());
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not parse file: " << std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_release(pReader);
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release Model Reader
|
||||||
|
NMR::lib3mf_release(pReader);
|
||||||
|
|
||||||
|
//Iterate Model
|
||||||
|
|
||||||
|
BOOL pbHasNext;
|
||||||
|
NMR::PLib3MFModelResourceIterator * pResourceIterator;
|
||||||
|
|
||||||
|
hResult = NMR::lib3mf_model_getobjects(pModel, &pResourceIterator);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not get object: " << std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
hResult = NMR::lib3mf_resourceiterator_movenext(pResourceIterator, &pbHasNext);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not get next object: " << std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_release(pResourceIterator);
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
while (pbHasNext) {
|
||||||
|
NMR::PLib3MFModelResource * pResource;
|
||||||
|
NMR::PLib3MFModelMeshObject * pMeshObject;
|
||||||
|
NMR::PLib3MFModelComponentsObject * pComponentsObject;
|
||||||
|
NMR::ModelResourceID ResourceID;
|
||||||
|
|
||||||
|
// get current resource
|
||||||
|
hResult = NMR::lib3mf_resourceiterator_getcurrent(pResourceIterator, &pResource);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not get resource: " << std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_release(pResourceIterator);
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get resource ID
|
||||||
|
hResult = NMR::lib3mf_resource_getresourceid(pResource, &ResourceID);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not get resource id: " << std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_release(pResource);
|
||||||
|
NMR::lib3mf_release(pResourceIterator);
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query mesh interface
|
||||||
|
BOOL bIsMeshObject;
|
||||||
|
hResult = NMR::lib3mf_object_ismeshobject(pResource, &bIsMeshObject);
|
||||||
|
if ((hResult == LIB3MF_OK) && (bIsMeshObject)) {
|
||||||
|
std::cout << "------------------------------------------------------" << std::endl;
|
||||||
|
std::cout << "mesh object #" << ResourceID << ": " << std::endl;
|
||||||
|
|
||||||
|
pMeshObject = pResource;
|
||||||
|
NMR::lib3mf_meshobject_getvertexcount(pMeshObject, &nbVertices);
|
||||||
|
NMR::lib3mf_meshobject_gettrianglecount(pMeshObject, &nbPolygons);
|
||||||
|
PointRange points (nbVertices);
|
||||||
|
PolygonRange triangles(nbPolygons);
|
||||||
|
DWORD nNeededChars;
|
||||||
|
std::vector<char> pBuffer;
|
||||||
|
// Retrieve Mesh Name Length
|
||||||
|
hResult = NMR::lib3mf_object_getnameutf8(pMeshObject, NULL, 0, &nNeededChars);
|
||||||
|
if (hResult != LIB3MF_OK)
|
||||||
|
return hResult;
|
||||||
|
|
||||||
|
// Retrieve Mesh Name
|
||||||
|
if (nNeededChars > 0) {
|
||||||
|
pBuffer.resize(nNeededChars + 1);
|
||||||
|
hResult = NMR::lib3mf_object_getnameutf8(pMeshObject, &pBuffer[0], nNeededChars + 1, NULL);
|
||||||
|
pBuffer[nNeededChars] = 0;
|
||||||
|
names.push_back(std::string(&pBuffer[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
names.push_back(std::string("Unknown Mesh"));
|
||||||
|
for(DWORD vid = 0; vid < nbVertices; ++vid)
|
||||||
|
{
|
||||||
|
NMR::MODELMESHVERTEX pVertex;
|
||||||
|
NMR::lib3mf_meshobject_getvertex(pMeshObject, vid, &pVertex);
|
||||||
|
points[vid] =
|
||||||
|
Point_3(pVertex.m_fPosition[0],
|
||||||
|
pVertex.m_fPosition[1],
|
||||||
|
pVertex.m_fPosition[2]);
|
||||||
|
}
|
||||||
|
for(DWORD pid = 0; pid < nbPolygons; ++pid)
|
||||||
|
{
|
||||||
|
NMR::MODELMESHTRIANGLE pTriangle;
|
||||||
|
NMR::lib3mf_meshobject_gettriangle(pMeshObject, pid, &pTriangle);
|
||||||
|
Polygon triangle(3);
|
||||||
|
for(DWORD i = 0; i< 3; ++i)
|
||||||
|
triangle[i] = pTriangle.m_nIndices[i];
|
||||||
|
triangles[pid] = triangle;
|
||||||
|
}
|
||||||
|
all_points.push_back(points);
|
||||||
|
all_polygons.push_back(triangles);
|
||||||
|
}
|
||||||
|
// free instances
|
||||||
|
NMR::lib3mf_release(pResource);
|
||||||
|
hResult = NMR::lib3mf_resourceiterator_movenext(pResourceIterator, &pbHasNext);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not get next object: " << std::hex << hResult << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return all_points.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
}//end CGAL
|
||||||
|
|
||||||
|
#endif // READ_3MF_H
|
||||||
|
|
||||||
|
|
@ -0,0 +1,303 @@
|
||||||
|
// Copyright (c) 2019 Geometry Factory
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 3 of the License,
|
||||||
|
// or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0+
|
||||||
|
//
|
||||||
|
// Author(s) : Maxime Gimeno
|
||||||
|
|
||||||
|
#ifndef WRITE_3MF_H
|
||||||
|
#define WRITE_3MF_H
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "Model/COM/NMR_DLLInterfaces.h"
|
||||||
|
namespace CGAL{
|
||||||
|
namespace tmf_internal{
|
||||||
|
// Utility functions to create vertices and triangles
|
||||||
|
NMR::MODELMESHVERTEX fnCreateVertex(float x, float y, float z)
|
||||||
|
{
|
||||||
|
NMR::MODELMESHVERTEX result;
|
||||||
|
result.m_fPosition[0] = x;
|
||||||
|
result.m_fPosition[1] = y;
|
||||||
|
result.m_fPosition[2] = z;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
NMR::MODELMESHTRIANGLE fnCreateTriangle(int v0, int v1, int v2)
|
||||||
|
{
|
||||||
|
NMR::MODELMESHTRIANGLE result;
|
||||||
|
result.m_nIndices[0] = v0;
|
||||||
|
result.m_nIndices[1] = v1;
|
||||||
|
result.m_nIndices[2] = v2;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //end internal
|
||||||
|
|
||||||
|
bool add_build_item(NMR::PLib3MFModel * pModel,
|
||||||
|
NMR::PLib3MFModelMeshObject* pMeshObject)
|
||||||
|
{
|
||||||
|
HRESULT hResult;
|
||||||
|
DWORD nErrorMessage;
|
||||||
|
LPCSTR pszErrorMessage;
|
||||||
|
// Add Build Item for Mesh
|
||||||
|
NMR::PLib3MFModelBuildItem * pBuildItem;
|
||||||
|
hResult = NMR::lib3mf_model_addbuilditem(pModel, pMeshObject, NULL, &pBuildItem);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not create build item: "
|
||||||
|
<< std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_getlasterror(pModel, &nErrorMessage, &pszErrorMessage);
|
||||||
|
std::cout << "error #" << std::hex << nErrorMessage
|
||||||
|
<< ": " << pszErrorMessage << std::endl;
|
||||||
|
NMR::lib3mf_release(pMeshObject);
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Release BuildItem and Mesh
|
||||||
|
NMR::lib3mf_release(pMeshObject);
|
||||||
|
NMR::lib3mf_release(pBuildItem);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool export_model_to_file(const std::string& file_name,
|
||||||
|
NMR::PLib3MFModel * pModel)
|
||||||
|
{
|
||||||
|
HRESULT hResult;
|
||||||
|
DWORD nErrorMessage;
|
||||||
|
LPCSTR pszErrorMessage;
|
||||||
|
// Output mesh as 3MF
|
||||||
|
// Create Model Writer for 3MF
|
||||||
|
NMR::PLib3MFModelWriter * p3MFWriter;
|
||||||
|
hResult = NMR::lib3mf_model_querywriter(pModel, "3mf", &p3MFWriter);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not create model reader: "
|
||||||
|
<< std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_getlasterror(pModel, &nErrorMessage, &pszErrorMessage);
|
||||||
|
std::cout << "error #" << std::hex << nErrorMessage
|
||||||
|
<< ": " << pszErrorMessage << std::endl;
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Export Model into File
|
||||||
|
hResult = NMR::lib3mf_writer_writetofileutf8(p3MFWriter, file_name.c_str());
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not write file: " << std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_getlasterror(p3MFWriter, &nErrorMessage, &pszErrorMessage);
|
||||||
|
std::cout << "error #" << std::hex << nErrorMessage << ": "
|
||||||
|
<< pszErrorMessage << std::endl;
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
NMR::lib3mf_release(p3MFWriter);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release Model Writer
|
||||||
|
NMR::lib3mf_release(p3MFWriter);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename PointRange, typename PolygonRange>
|
||||||
|
bool write_mesh_to_model( const PointRange& points,
|
||||||
|
const PolygonRange& polygons,
|
||||||
|
const std::string& name,
|
||||||
|
NMR::PLib3MFModelMeshObject** pMeshObject,
|
||||||
|
NMR::PLib3MFModel * pModel
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DWORD nErrorMessage;
|
||||||
|
LPCSTR pszErrorMessage;
|
||||||
|
HRESULT hResult;
|
||||||
|
// Create mesh structure
|
||||||
|
std::vector<NMR::MODELMESHVERTEX> pVertices;
|
||||||
|
std::vector<NMR::MODELMESHTRIANGLE> pTriangles;
|
||||||
|
// Create Mesh Object
|
||||||
|
hResult = NMR::lib3mf_model_addmeshobject(pModel, pMeshObject);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not add mesh object: " << std::hex
|
||||||
|
<< hResult << std::endl;
|
||||||
|
NMR::lib3mf_getlasterror(pModel, &nErrorMessage, &pszErrorMessage);
|
||||||
|
std::cout << "error #" << std::hex << nErrorMessage << ": "
|
||||||
|
<< pszErrorMessage << std::endl;
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for( auto point : points)
|
||||||
|
{
|
||||||
|
pVertices.push_back(tmf_internal::fnCreateVertex(point.x(), point.y(), point.z()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto triangle : polygons)
|
||||||
|
{
|
||||||
|
pTriangles.push_back(tmf_internal::fnCreateTriangle(triangle[0], triangle[1], triangle[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
hResult = NMR::lib3mf_meshobject_setgeometry(*pMeshObject, pVertices.data(),
|
||||||
|
pVertices.size(), pTriangles.data(),
|
||||||
|
pTriangles.size());
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not set mesh geometry: "
|
||||||
|
<< std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
|
||||||
|
std::cout << "error #" << std::hex << nErrorMessage
|
||||||
|
<< ": " << pszErrorMessage << std::endl;
|
||||||
|
NMR::lib3mf_release(*pMeshObject);
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Set name
|
||||||
|
hResult = NMR::lib3mf_object_setnameutf8(*pMeshObject, name.c_str());
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not set object name: " << std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
|
||||||
|
std::cout << "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
|
||||||
|
NMR::lib3mf_release(*pMeshObject);
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//remember that it adds 3 demmy vertices in the beginning, and a dummy triangle to be ignored.
|
||||||
|
template<typename PointRange>
|
||||||
|
bool write_points(const PointRange& points,
|
||||||
|
const std::string& name,
|
||||||
|
NMR::PLib3MFModelMeshObject** pMeshObject,
|
||||||
|
NMR::PLib3MFModel * pModel
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DWORD nErrorMessage;
|
||||||
|
LPCSTR pszErrorMessage;
|
||||||
|
HRESULT hResult;
|
||||||
|
// Create mesh structure
|
||||||
|
std::vector<NMR::MODELMESHVERTEX> pVertices;
|
||||||
|
// Create Mesh Object
|
||||||
|
hResult = NMR::lib3mf_model_addmeshobject(pModel, pMeshObject);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not add mesh object: " << std::hex
|
||||||
|
<< hResult << std::endl;
|
||||||
|
NMR::lib3mf_getlasterror(pModel, &nErrorMessage, &pszErrorMessage);
|
||||||
|
std::cout << "error #" << std::hex << nErrorMessage << ": "
|
||||||
|
<< pszErrorMessage << std::endl;
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//add 3 demmy vertices to be sure to have a valid triangle and accept point sets with less than 3 vertices.
|
||||||
|
for(int i = 0; i< 3; ++i)
|
||||||
|
pVertices.push_back(tmf_internal::fnCreateVertex(0,0,0));
|
||||||
|
for( auto point : points)
|
||||||
|
{
|
||||||
|
pVertices.push_back(tmf_internal::fnCreateVertex(point.x(), point.y(), point.z()));
|
||||||
|
}
|
||||||
|
NMR::MODELMESHTRIANGLE dummy_triangle = tmf_internal::fnCreateTriangle(0,1,2); //add a triangle to avoid lib error.
|
||||||
|
hResult = NMR::lib3mf_meshobject_setgeometry(*pMeshObject, pVertices.data(),
|
||||||
|
pVertices.size(), &dummy_triangle, 1);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not set mesh geometry: "
|
||||||
|
<< std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
|
||||||
|
std::cout << "error #" << std::hex << nErrorMessage
|
||||||
|
<< ": " << pszErrorMessage << std::endl;
|
||||||
|
NMR::lib3mf_release(*pMeshObject);
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Set name
|
||||||
|
hResult = NMR::lib3mf_object_setnameutf8(*pMeshObject, name.c_str());
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not set object name: " << std::hex << hResult << std::endl;
|
||||||
|
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
|
||||||
|
std::cout << "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
|
||||||
|
NMR::lib3mf_release(*pMeshObject);
|
||||||
|
NMR::lib3mf_release(pModel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename PointRange>
|
||||||
|
bool write_point_cloud_to_model(const PointRange& points,
|
||||||
|
const std::string& name,
|
||||||
|
NMR::PLib3MFModelMeshObject** pMeshObject,
|
||||||
|
NMR::PLib3MFModel * pModel
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::string pc_name = name;
|
||||||
|
pc_name.append("_cgal_pc");
|
||||||
|
write_points(points, pc_name, pMeshObject, pModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename PointRange>
|
||||||
|
bool write_polyline_to_model(const PointRange& points,
|
||||||
|
const std::string& name,
|
||||||
|
NMR::PLib3MFModelMeshObject** pMeshObject,
|
||||||
|
NMR::PLib3MFModel * pModel
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::string pc_name = name;
|
||||||
|
pc_name.append("_cgal_pl");
|
||||||
|
write_points(points, pc_name, pMeshObject, pModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief write_soups_to_3mf will write the polygon soups in all_points and
|
||||||
|
* all_polygons in `file_name`, in the 3mf format.
|
||||||
|
* \tparam PointRanges a model of the concepts `RandomAccessContainer` and
|
||||||
|
* `BackInsertionSequence` whose `value type` is
|
||||||
|
* a model of the concepts `RandomAccessContainer` and `BackInsertionSequence`
|
||||||
|
* whose `value type` is the point type.
|
||||||
|
* \tparam PolygonRanges a model of the concept `RandomAccessContainer` whose
|
||||||
|
* `value_type` is a model of the concept `RandomAccessContainer`
|
||||||
|
* whose `value_type` is a model of the concept `RandomAccessContainer` whose
|
||||||
|
* `value_type` is std::size_t.
|
||||||
|
* \param file_name the name of the 3mf file to write.
|
||||||
|
* \param all_points a `PointRanges` that contains the points of the soups
|
||||||
|
* to write.
|
||||||
|
* \param all_polygons a `PolygonRanges` that contains the triangles of the
|
||||||
|
* soups in `file_name`.
|
||||||
|
* \param names will contains the name of each mesh in `file_name`.
|
||||||
|
* \return `true` if the writing is successful, `false` otherwise.
|
||||||
|
*/
|
||||||
|
template<typename PointRanges, typename PolygonRanges>
|
||||||
|
bool write_soups_to_3mf(const std::string& file_name,
|
||||||
|
const PointRanges& all_points,
|
||||||
|
const PolygonRanges& all_polygons,
|
||||||
|
const std::vector<std::string>& names)
|
||||||
|
{
|
||||||
|
DWORD nErrorMessage;
|
||||||
|
LPCSTR pszErrorMessage;
|
||||||
|
HRESULT hResult;
|
||||||
|
|
||||||
|
// Create Model Instance
|
||||||
|
NMR::PLib3MFModel * pModel;
|
||||||
|
hResult = NMR::lib3mf_createmodel(&pModel);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not create model: " << std::hex << hResult << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for(std::size_t id = 0; id < all_points.size(); ++id)
|
||||||
|
{
|
||||||
|
NMR::PLib3MFModelMeshObject* pMeshObject;
|
||||||
|
std::string name;
|
||||||
|
if(names.size() > id
|
||||||
|
&& ! names[id].empty())
|
||||||
|
{
|
||||||
|
name=names[id];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
name = std::string("");
|
||||||
|
write_mesh_to_model(all_points[id], all_polygons[id], name, &pMeshObject, pModel);
|
||||||
|
//write_mesh_object_to_model(pModel, pMeshObject);
|
||||||
|
}
|
||||||
|
return export_model_to_file(file_name, pModel);
|
||||||
|
}
|
||||||
|
}//end CGAL
|
||||||
|
#endif // WRITE_3MF_H
|
||||||
|
|
@ -7,13 +7,49 @@ project( Stream_support_Tests )
|
||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
|
|
||||||
find_package(CGAL QUIET)
|
find_package(CGAL QUIET)
|
||||||
|
|
||||||
if ( CGAL_FOUND )
|
if ( CGAL_FOUND )
|
||||||
|
set(3MF_INCLUDE_DIR "" CACHE PATH "Path to lib3MF headers")
|
||||||
|
set(3MF_LIBRARY_DIR "" CACHE PATH "Path to lib3MF library files")
|
||||||
|
if(IS_DIRECTORY "${3MF_INCLUDE_DIR}/Common")
|
||||||
|
set(3MF_FOUND true)
|
||||||
|
endif()
|
||||||
|
|
||||||
# create a target per cppfile
|
# create a target per cppfile
|
||||||
file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
|
file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
|
||||||
foreach(cppfile ${cppfiles})
|
foreach(cppfile ${cppfiles})
|
||||||
create_single_source_cgal_program( "${cppfile}" )
|
if ( "${cppfile}" STREQUAL "test_3mf_to_sm.cpp" )
|
||||||
|
|
||||||
|
if(3MF_FOUND)
|
||||||
|
if (WIN32)
|
||||||
|
set(LSUFFIX "dll")
|
||||||
|
set(LSUFFIXOUT ".dll")
|
||||||
|
elseif(UNIX AND NOT APPLE)
|
||||||
|
set(LSUFFIX "so")
|
||||||
|
set(LSUFFIXOUT ".so.1")
|
||||||
|
else()
|
||||||
|
set(LSUFFIX "dylib")
|
||||||
|
set(LSUFFIXOUT ".1.dylib")
|
||||||
|
endif()
|
||||||
|
include_directories(${3MF_INCLUDE_DIR})
|
||||||
|
link_directories(${3MF_LIBRARY_DIR})
|
||||||
|
create_single_source_cgal_program( "${cppfile}" )
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
target_link_libraries(test_3mf_to_sm PRIVATE lib3MF)
|
||||||
|
else()
|
||||||
|
# Unix prefixes the name of the library with "lib" anyway
|
||||||
|
target_link_libraries(test_3mf_to_sm PRIVATE 3MF)
|
||||||
|
if(APPLE)
|
||||||
|
target_link_directories(test_3mf_to_sm PRIVATE ${3MF_LIBRARY_DIR}/..)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(STATUS "NOTICE: This program requires the lib3MF library, and will not be compiled.")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
create_single_source_cgal_program( "${cppfile}" )
|
||||||
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
else()
|
else()
|
||||||
|
|
@ -22,3 +58,4 @@ else()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,147 @@
|
||||||
|
//needed by functions
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "Model/COM/NMR_DLLInterfaces.h"
|
||||||
|
//needed by example
|
||||||
|
#include <CGAL/boost/graph/helpers.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <CGAL/Surface_mesh.h>
|
||||||
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
|
||||||
|
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <CGAL/IO/read_3mf.h>
|
||||||
|
#include <CGAL/IO/write_3mf.h>
|
||||||
|
// Use NMR namespace for the interfaces
|
||||||
|
using namespace NMR;
|
||||||
|
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||||
|
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||||
|
|
||||||
|
typedef Kernel::Point_3 Point_3;
|
||||||
|
typedef CGAL::Surface_mesh<Point_3> Mesh;
|
||||||
|
typedef std::vector<Point_3> PointRange;
|
||||||
|
typedef std::vector<std::size_t> Polygon;
|
||||||
|
typedef std::vector<Polygon> PolygonRange;
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
/* if( argc != 2)
|
||||||
|
{
|
||||||
|
std::cerr<<"please give an input 3mf file.";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::vector<PointRange> all_points;
|
||||||
|
std::vector<PolygonRange> all_polygons;
|
||||||
|
std::vector<std::string> names;
|
||||||
|
std::size_t nb_meshes =
|
||||||
|
CGAL::read_soups_from_3mf(argv[1], all_points, all_polygons, names);
|
||||||
|
if(nb_meshes <0)
|
||||||
|
return 1;
|
||||||
|
for(std::size_t i = 0; i< nb_meshes; ++i)
|
||||||
|
{
|
||||||
|
PolygonRange triangles = all_polygons[i];
|
||||||
|
PointRange points = all_points[i];
|
||||||
|
bool ok = true;
|
||||||
|
if(!PMP::is_polygon_soup_a_polygon_mesh(triangles))
|
||||||
|
ok = PMP::orient_polygon_soup(points, triangles);
|
||||||
|
if(!ok)
|
||||||
|
{
|
||||||
|
std::cerr<<"Object is not orientable. Skipped."<<std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Mesh mesh;
|
||||||
|
PMP::polygon_soup_to_polygon_mesh(points, triangles, mesh);
|
||||||
|
std::cout<<names[i]<<" is valid: "<<mesh.is_valid()<<std::endl;
|
||||||
|
std::string outputName("output");
|
||||||
|
outputName.append(std::to_string(i));
|
||||||
|
outputName.append(".off");
|
||||||
|
std::ofstream ofs(outputName);
|
||||||
|
ofs << mesh;
|
||||||
|
ofs.close();
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
Mesh sphere, tube;
|
||||||
|
CGAL::make_icosahedron<Mesh, Point_3>(sphere);
|
||||||
|
CGAL::make_regular_prism(10, tube, Point_3(0,-10,0), 10);
|
||||||
|
/*
|
||||||
|
all_points.clear();
|
||||||
|
all_polygons.clear();
|
||||||
|
names.clear();
|
||||||
|
*/
|
||||||
|
PointRange points;
|
||||||
|
//PolygonRange triangles;
|
||||||
|
typedef boost::property_map<Mesh, boost::vertex_point_t>::type VPMap;
|
||||||
|
VPMap vpm = get(boost::vertex_point, sphere);
|
||||||
|
std::unordered_map<boost::graph_traits<Mesh>::vertex_descriptor,
|
||||||
|
std::size_t> vertex_id_map;
|
||||||
|
std::size_t i = 0;
|
||||||
|
for(auto v : sphere.vertices())
|
||||||
|
{
|
||||||
|
points.push_back(get(vpm, v));
|
||||||
|
vertex_id_map[v] = i++;
|
||||||
|
}
|
||||||
|
//all_points.push_back(points);
|
||||||
|
/*for(auto f : sphere.faces())
|
||||||
|
{
|
||||||
|
Polygon triangle;
|
||||||
|
for(auto vert : CGAL::vertices_around_face(halfedge(f, sphere), sphere))
|
||||||
|
{
|
||||||
|
triangle.push_back(vertex_id_map[vert]);
|
||||||
|
}
|
||||||
|
triangles.push_back(triangle);
|
||||||
|
}
|
||||||
|
all_polygons.push_back(triangles);
|
||||||
|
points.clear();
|
||||||
|
triangles.clear();
|
||||||
|
vertex_id_map.clear();
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
vpm = get(boost::vertex_point, tube);
|
||||||
|
for(auto v : tube.vertices())
|
||||||
|
{
|
||||||
|
points.push_back(get(vpm, v));
|
||||||
|
vertex_id_map[v] = i++;
|
||||||
|
}
|
||||||
|
all_points.push_back(points);
|
||||||
|
for(auto f : tube.faces())
|
||||||
|
{
|
||||||
|
Polygon triangle;
|
||||||
|
for(auto vert : CGAL::vertices_around_face(halfedge(f, tube), tube))
|
||||||
|
{
|
||||||
|
triangle.push_back(vertex_id_map[vert]);
|
||||||
|
}
|
||||||
|
triangles.push_back(triangle);
|
||||||
|
}
|
||||||
|
all_polygons.push_back(triangles);
|
||||||
|
names.push_back(std::string("sphere"));
|
||||||
|
names.push_back(std::string("tube"));
|
||||||
|
if(!CGAL::write_soups_to_3mf("micro.3mf", all_points, all_polygons, names)){
|
||||||
|
std::cerr<<"an error has occured in final writing."<<std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
DWORD nErrorMessage;
|
||||||
|
LPCSTR pszErrorMessage;
|
||||||
|
HRESULT hResult;
|
||||||
|
NMR::PLib3MFModel * pModel;
|
||||||
|
hResult = NMR::lib3mf_createmodel(&pModel);
|
||||||
|
if (hResult != LIB3MF_OK) {
|
||||||
|
std::cout << "could not create model: " << std::hex << hResult << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NMR::PLib3MFModelMeshObject* pMeshObject;
|
||||||
|
|
||||||
|
DWORD nv;
|
||||||
|
CGAL::write_point_cloud_to_model(points,"point_set", &pMeshObject, pModel);
|
||||||
|
hResult = lib3mf_meshobject_getvertexcount(pMeshObject, &nv);
|
||||||
|
std::cout<<nv<<" vertices."<<std::endl;
|
||||||
|
lib3mf_release(pMeshObject);
|
||||||
|
CGAL::write_polyline_to_model(points,"polyline", &pMeshObject, pModel);
|
||||||
|
hResult = lib3mf_meshobject_getvertexcount(pMeshObject, &nv);
|
||||||
|
std::cout<<nv<<" vertices."<<std::endl;
|
||||||
|
std::cout<<"OK."<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in New Issue