diff --git a/src/ifcgeom/ConversionResult.cpp b/src/ifcgeom/ConversionResult.cpp index 6be2736742..96ab62f428 100644 --- a/src/ifcgeom/ConversionResult.cpp +++ b/src/ifcgeom/ConversionResult.cpp @@ -7,7 +7,7 @@ IfcGeom::Representation::Triangulation * IfcGeom::ConversionResultShape::Triangu { auto t = IfcGeom::Representation::Triangulation::empty(settings); static ifcopenshell::geometry::taxonomy::matrix4 iden; - Triangulate(settings, iden, t, -1); + Triangulate(settings, iden, t, -1, -1); return t; } diff --git a/src/ifcgeom/ConversionResult.h b/src/ifcgeom/ConversionResult.h index 487a23699f..281b1b3ed2 100644 --- a/src/ifcgeom/ConversionResult.h +++ b/src/ifcgeom/ConversionResult.h @@ -214,7 +214,7 @@ namespace IfcGeom { class IFC_GEOM_API ConversionResultShape { public: - virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, Representation::Triangulation* t, int surface_style_id) const = 0; + virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, Representation::Triangulation* t, int item_id, int surface_style_id) const = 0; IfcGeom::Representation::Triangulation* Triangulate(const ifcopenshell::geometry::Settings& settings) const; virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const = 0; diff --git a/src/ifcgeom/IfcGeomRepresentation.cpp b/src/ifcgeom/IfcGeomRepresentation.cpp index 54ec30ea7f..e878e9dfd5 100644 --- a/src/ifcgeom/IfcGeomRepresentation.cpp +++ b/src/ifcgeom/IfcGeomRepresentation.cpp @@ -354,7 +354,7 @@ IfcGeom::Representation::Triangulation::Triangulation(const BRep& shape_model) } } - iit->Shape()->Triangulate(settings(), *iit->Placement(), this, surface_style_id); + iit->Shape()->Triangulate(settings(), *iit->Placement(), this, iit->ItemId(), surface_style_id); } } @@ -389,7 +389,7 @@ std::vector IfcGeom::Representation::Triangulation::box_project_uvs(cons return uvs; } -int IfcGeom::Representation::Triangulation::addVertex(int material_index, double pX, double pY, double pZ) { +int IfcGeom::Representation::Triangulation::addVertex(int item_id, int material_index, double pX, double pY, double pZ) { const bool convert = settings().get().get(); auto unit_magnitude = settings().get().get(); const double X = convert ? (pX /unit_magnitude) : pX; @@ -397,7 +397,7 @@ int IfcGeom::Representation::Triangulation::addVertex(int material_index, double const double Z = convert ? (pZ /unit_magnitude) : pZ; int i = (int)_verts.size() / 3; if (settings().get().get()) { - const VertexKey key = std::make_pair(material_index, std::make_pair(X, std::make_pair(Y, Z))); + const VertexKey key = std::make_tuple(item_index, material_index, X, Y, Z); typename VertexKeyMap::const_iterator it = welds.find(key); if (it != welds.end()) return it->second; i = (int)(welds.size() + weld_offset_); diff --git a/src/ifcgeom/IfcGeomRepresentation.h b/src/ifcgeom/IfcGeomRepresentation.h index b0c5bbb12e..5250603bea 100644 --- a/src/ifcgeom/IfcGeomRepresentation.h +++ b/src/ifcgeom/IfcGeomRepresentation.h @@ -96,10 +96,8 @@ namespace IfcGeom { class Triangulation : public Representation { private: - // A nested pair of floats and a material index to be able to store an XYZ coordinate in a map. - // TODO: Make this a std::tuple when compilers add support for that. - typedef typename std::pair > Coordinate; - typedef typename std::pair VertexKey; + // A tuple of to store as a key in a map. + typedef typename std::tuple VertexKey; typedef std::map VertexKeyMap; typedef std::pair Edge; @@ -111,6 +109,7 @@ namespace IfcGeom { std::vector uvs_; std::vector _material_ids; std::vector _materials; + std::vector _item_ids; size_t weld_offset_; VertexKeyMap welds; @@ -129,6 +128,7 @@ namespace IfcGeom { const std::vector& uvs() const { return uvs_; } const std::vector& material_ids() const { return _material_ids; } const std::vector& materials() const { return _materials; } + const std::vector& item_ids() const { return _item_ids; } Triangulation(const BRep& shape_model); @@ -142,7 +142,8 @@ namespace IfcGeom { const std::vector& normals, const std::vector& uvs, const std::vector& material_ids, - const std::vector& materials + const std::vector& materials, + const std::vector& item_ids ) : Representation(settings, entity) , id_(id) @@ -153,6 +154,7 @@ namespace IfcGeom { , uvs_(uvs) , _material_ids(material_ids) , _materials(materials) + , _item_ids(item_ids) {} virtual ~Triangulation() {} @@ -164,7 +166,7 @@ namespace IfcGeom { static Triangulation* empty(const ifcopenshell::geometry::Settings& settings) { return new Triangulation(settings, ""); } /// Welds vertices that belong to different faces - int addVertex(int material_index, double X, double Y, double Z); + int addVertex(int item_index, int material_index, double X, double Y, double Z); void addNormal(double X, double Y, double Z) { _normals.push_back(X); @@ -172,11 +174,12 @@ namespace IfcGeom { _normals.push_back(Z); } - void addFace(int style, int i0, int i1, int i2) { + void addFace(int item_id, int style, int i0, int i1, int i2) { _faces.push_back(i0); _faces.push_back(i1); _faces.push_back(i2); + _item_ids.push_back(item_id); _material_ids.push_back(style); } diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 1cb9b301c7..70b10e83d4 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -57,7 +57,7 @@ void ifcopenshell::geometry::CgalShape::to_nef() const { } #endif -void ifcopenshell::geometry::CgalShape::Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const { +void ifcopenshell::geometry::CgalShape::Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const { // Copy is made because triangulate_faces() obviously does not accept a const argument // ... also becuase of transforming the vertex positions, right? cgal_shape_t s = *this; @@ -152,6 +152,7 @@ void ifcopenshell::geometry::CgalShape::Triangulate(ifcopenshell::geometry::Sett auto it = welds.find(pn); if (it == welds.end()) { vidx = t->addVertex( + item_id, surface_style_id, CGAL::to_double(current_halfedge->vertex()->point().cartesian(0)), CGAL::to_double(current_halfedge->vertex()->point().cartesian(1)), @@ -174,7 +175,7 @@ void ifcopenshell::geometry::CgalShape::Triangulate(ifcopenshell::geometry::Sett ++current_halfedge; } while (current_halfedge != face->facet_begin()); - t->addFace(surface_style_id, vertexidx[0], vertexidx[1], vertexidx[2]); + t->addFace(item_id, surface_style_id, vertexidx[0], vertexidx[1], vertexidx[2]); ++num_faces; } @@ -547,7 +548,7 @@ void ifcopenshell::geometry::CgalShape::map(const std::vectorNode(i).Transformed(loc).XYZ()); taxonomy_transform(place.components_, *coords.rbegin()); const gp_XYZ& last = *coords.rbegin(); - dict[i] = t->addVertex(surface_style_id, last.X(), last.Y(), last.Z()); + dict[i] = t->addVertex(item_id, surface_style_id, last.X(), last.Y(), last.Z()); if (calculate_normals) { const gp_Pnt2d& uv = tri->UVNode(i); @@ -140,7 +140,7 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(ifcopenshell::geometr _normals.push_back((float)normal.Z()); */ - t->addFace(surface_style_id, dict[n1], dict[n2], dict[n3]); + t->addFace(item_id, surface_style_id, dict[n1], dict[n2], dict[n3]); t->addEdge(dict[n1], dict[n2], edgecount, edges_temp); t->addEdge(dict[n2], dict[n3], edgecount, edges_temp); @@ -208,8 +208,8 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(ifcopenshell::geometr taxonomy_transform(place.components_, p3); taxonomy_transform(place.components_, p); - int left = t->addVertex(surface_style_id, p2.X(), p2.Y(), p2.Z()); - int right = t->addVertex(surface_style_id, p3.X(), p3.Y(), p3.Z()); + int left = t->addVertex(item_id, surface_style_id, p2.X(), p2.Y(), p2.Z()); + int right = t->addVertex(item_id, surface_style_id, p3.X(), p3.Y(), p3.Z()); segments.push_back(std::make_pair(left, current)); segments.push_back(std::make_pair(right, current)); diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h index 4b4e224a3b..7a70d05c68 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h @@ -50,7 +50,7 @@ namespace ifcopenshell { const TopoDS_Shape& shape() const { return shape_; } operator const TopoDS_Shape& () { return shape_; } - virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const; + virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const; virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const; virtual IfcGeom::ConversionResultShape* clone() const { diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index 6c92ec3e43..46e42f8afc 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -295,16 +295,9 @@ struct ShapeRTTI : public boost::static_visitor edges = property(edges) material_ids = property(material_ids) materials = property(materials) - %} -}; - -// Specialized accessors follow later, for otherwise property definitions -// would appear before templated getter functions are defined. -%extend IfcGeom::Representation::Triangulation { - %pythoncode %{ - # Hide the getters with read-only property implementations verts = property(verts) normals = property(normals) + item_ids = property(item_ids) %} }; diff --git a/src/serializers/HdfSerializer.cpp b/src/serializers/HdfSerializer.cpp index 4bcdfb4b5e..6d380ce607 100644 --- a/src/serializers/HdfSerializer.cpp +++ b/src/serializers/HdfSerializer.cpp @@ -396,6 +396,7 @@ IfcGeom::Element* HdfSerializer::read(IfcParse::IfcFile& f, const std::string& g auto normals = read_dataset(meshGroup, DATASET_NAME_NORMALS); auto uvcoords = read_dataset(meshGroup, DATASET_NAME_UVCOORDS); auto material_ids = read_dataset(meshGroup, DATASET_NAME_MATERIAL_IDS); + auto item_ids = read_dataset(meshGroup, DATASET_NAME_ITEM_IDS); std::vector surface_styles; @@ -431,7 +432,8 @@ IfcGeom::Element* HdfSerializer::read(IfcParse::IfcFile& f, const std::string& g normals, uvcoords, material_ids, - surface_style_ptrs + surface_style_ptrs, + item_ids )); triangulation_cache_.insert({ representation_id_str, triangulation_geometry }); @@ -664,6 +666,7 @@ void HdfSerializer::write(const IfcGeom::TriangulationElement* o) { write_dataset(meshGroup, DATASET_NAME_NORMALS, mesh.normals(), 2); write_dataset(meshGroup, DATASET_NAME_UVCOORDS, mesh.uvs(), 2); write_dataset(meshGroup, DATASET_NAME_MATERIAL_IDS, mesh.material_ids(), 1); + write_dataset(meshGroup, DATASET_NAME_ITEM_IDS, mesh.item_ids(), 1); { auto& ts = mesh.materials(); @@ -690,6 +693,7 @@ const H5std_string HdfSerializer::DATASET_NAME_NORMALS = "normals"; const H5std_string HdfSerializer::DATASET_NAME_INDICES = "indices"; const H5std_string HdfSerializer::DATASET_NAME_EDGES = "edges"; const H5std_string HdfSerializer::DATASET_NAME_MATERIAL_IDS = "material_ids"; +const H5std_string HdfSerializer::DATASET_NAME_ITEM_IDS = "item_ids"; const H5std_string HdfSerializer::DATASET_NAME_MATERIALS = "materials"; const H5std_string HdfSerializer::DATASET_NAME_OCCT = "brep"; const H5std_string HdfSerializer::DATASET_NAME_PLACEMENT = "placement"; diff --git a/src/serializers/HdfSerializer.h b/src/serializers/HdfSerializer.h index d6fdcffe87..db1c838994 100644 --- a/src/serializers/HdfSerializer.h +++ b/src/serializers/HdfSerializer.h @@ -46,6 +46,7 @@ private: static const H5std_string DATASET_NAME_INDICES; static const H5std_string DATASET_NAME_EDGES; static const H5std_string DATASET_NAME_MATERIAL_IDS; + static const H5std_string DATASET_NAME_ITEM_IDS; static const H5std_string DATASET_NAME_MATERIALS; static const H5std_string DATASET_NAME_OCCT; static const H5std_string DATASET_NAME_PLACEMENT;