diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index e2da8ecd97..81fd474622 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -2,5 +2,182 @@ #include "CgalConversionResult.h" void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const { - throw std::runtime_error("Not implemented Triangulate()"); + cgal_shape_t s = shape_; + const cgal_placement_t& trsf = dynamic_cast(place)->trsf(); + + // Triangulate the shape and compute the normals + std::map vertex_normals; + boost::associative_property_map> vertex_normals_map(vertex_normals); + std::map face_normals; + boost::associative_property_map> face_normals_map(face_normals); + try { + CGAL::Polygon_mesh_processing::triangulate_faces(s); + CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); + } catch (...) { + + // TODO: Catch outside + // Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape:",ifc_file->entityById(_id)->entity); + Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape"); + return; + } + + // Iterates over the faces of the shape + int num_faces = 0, num_vertices = 0; +// TopExp_Explorer exp; + for (auto &face: faces(s)) { + CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin(); + do { + t->addVertex(surface_style_id, + CGAL::to_double(current_halfedge->vertex()->point().cartesian(0)), + CGAL::to_double(current_halfedge->vertex()->point().cartesian(1)), + CGAL::to_double(current_halfedge->vertex()->point().cartesian(2))); + for (int i = 0; i < 3; ++i) t->normals().push_back(CGAL::to_double(face_normals_map[face].cartesian(i))); + t->faces().push_back(num_vertices); + ++num_vertices; + ++current_halfedge; + } while (current_halfedge != face->facet_begin()); + t->material_ids().push_back(surface_style_id); + ++num_faces; + +// TopLoc_Location loc; +// Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face, loc); +// +// if (!tri.IsNull()) { +// +// // A 3x3 matrix to rotate the vertex normals +// const gp_Mat rotation_matrix = trsf.VectorialPart(); +// +// // Keep track of the number of times an edge is used +// // Manifold edges (i.e. edges used twice) are deemed invisible +// std::map, int> edgecount; +// std::vector > edges_temp; +// +// const TColgp_Array1OfPnt& nodes = tri->Nodes(); +// const TColgp_Array1OfPnt2d& uvs = tri->UVNodes(); +// std::vector coords; +// BRepGProp_Face prop(face); +// std::map dict; +// +// // Vertex normals are only calculated if vertices are not welded and calculation is not disable explicitly. +// const bool calculate_normals = !settings.get(IteratorSettings::WELD_VERTICES) && +// !settings.get(IteratorSettings::NO_NORMALS); +// +// for (int i = 1; i <= nodes.Length(); ++i) { +// coords.push_back(nodes(i).Transformed(loc).XYZ()); +// trsf.Transforms(*coords.rbegin()); +// const gp_XYZ& last = *coords.rbegin(); +// dict[i] = t->addVertex(surface_style_id, last.X(), last.Y(), last.Z()); +// +// if (calculate_normals) { +// const gp_Pnt2d& uv = uvs(i); +// gp_Pnt p; +// gp_Vec normal_direction; +// prop.Normal(uv.X(), uv.Y(), p, normal_direction); +// gp_Vec normal(0., 0., 0.); +// if (normal_direction.Magnitude() > ALMOST_ZERO) { +// normal = gp_Dir(normal_direction.XYZ() * rotation_matrix); +// } +// t->normals().push_back(static_cast(normal.X())); +// t->normals().push_back(static_cast(normal.Y())); +// t->normals().push_back(static_cast(normal.Z())); +// } +// } +// +// const Poly_Array1OfTriangle& triangles = tri->Triangles(); +// for (int i = 1; i <= triangles.Length(); ++i) { +// int n1, n2, n3; +// if (face.Orientation() == TopAbs_REVERSED) +// triangles(i).Get(n3, n2, n1); +// else triangles(i).Get(n1, n2, n3); +// +// t->faces().push_back(dict[n1]); +// t->faces().push_back(dict[n2]); +// t->faces().push_back(dict[n3]); +// +// t->material_ids().push_back(surface_style_id); +// +// t->addEdge(dict[n1], dict[n2], edgecount, edges_temp); +// t->addEdge(dict[n2], dict[n3], edgecount, edges_temp); +// t->addEdge(dict[n3], dict[n1], edgecount, edges_temp); +// } +// for (std::vector >::const_iterator jt = edges_temp.begin(); jt != edges_temp.end(); ++jt) { +// if (edgecount[*jt] == 1) { +// // non manifold edge, face boundary +// t->edges().push_back(jt->first); +// t->edges().push_back(jt->second); +// } +// } +// } + } +// +// if (num_faces == 0) { +// // Edges are only emitted if there are no faces. A mixed representation of faces +// // and loose edges is discouraged by the standard. An alternative would be to use +// // TopExp_Explorer texp(s, TopAbs_EDGE, TopAbs_FACE) to find edges that do not +// // belong to any face. +// for (TopExp_Explorer texp(s, TopAbs_EDGE); texp.More(); texp.Next()) { +// BRepAdaptor_Curve crv(TopoDS::Edge(texp.Current())); +// GCPnts_QuasiUniformDeflection tessellater(crv, settings.deflection_tolerance()); +// int n = tessellater.NbPoints(); +// int start = (int)t->verts().size() / 3; +// for (int i = 1; i <= n; ++i) { +// gp_XYZ p = tessellater.Value(i).XYZ(); +// +// /* +// // In case you want direction arrows on your edges +// double u = tessellater.Parameter(i); +// gp_XYZ p2, p3; +// gp_Pnt tmp; +// gp_Vec tmp2; +// crv.D1(u, tmp, tmp2); +// gp_Dir d1, d2, d3, d4; +// d1 = tmp2; +// if (texp.Current().Orientation() == TopAbs_REVERSED) { +// d1 = -d1; +// } +// if (fabs(d1.Z()) < 0.5) { +// d2 = d1.Crossed(gp::DZ()); +// } else { +// d2 = d1.Crossed(gp::DY()); +// } +// d3 = d1.XYZ() + d2.XYZ(); +// d4 = d1.XYZ() - d2.XYZ(); +// p2 = p - d3.XYZ() / 10.; +// p3 = p - d4.XYZ() / 10.; +// trsf.Transforms(p2); +// trsf.Transforms(p3); +// _material_ids.push_back(surface_style_id); +// _material_ids.push_back(surface_style_id); +// _verts.push_back(static_cast

(p2.X())); +// _verts.push_back(static_cast

(p2.Y())); +// _verts.push_back(static_cast

(p2.Z())); +// _verts.push_back(static_cast

(p3.X())); +// _verts.push_back(static_cast

(p3.Y())); +// _verts.push_back(static_cast

(p3.Z())); +// */ +// +// trsf.Transforms(p); +// +// t->material_ids().push_back(surface_style_id); +// +// t->verts().push_back(static_cast(p.X())); +// t->verts().push_back(static_cast(p.Y())); +// t->verts().push_back(static_cast(p.Z())); +// +// if (i > 1) { +// t->edges().push_back(start + i - 2); +// t->edges().push_back(start + i - 1); +// // _edges.push_back(start + 3 * (i - 2) + 2); +// // _edges.push_back(start + 3 * (i - 1) + 2); +// } +// +// // _edges.push_back(start + 3 * (i - 1) + 0); +// // _edges.push_back(start + 3 * (i - 1) + 2); +// // _edges.push_back(start + 3 * (i - 1) + 1); +// // _edges.push_back(start + 3 * (i - 1) + 2); +// } +// } +// } +// +// BRepTools::Clean(s); } diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp index 6366590c8d..996926c978 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.cpp @@ -132,20 +132,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ face_list.push_back(face); } -// for (auto const &face : face_list) { -// std::cout << "Face" << std::endl; -// std::cout << "\touter: "; -// for (auto const &point: *face->outer) { -// std::cout << "(" << point << ") "; -// } std::cout << std::endl; -// for (auto const &inner: face->inner) { -// std::cout << "\tinner: "; -// for (auto const &point: *inner) { -// std::cout << "(" << point << ") "; -// } std::cout << std::endl; -// } -// } - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 48d7aea233..596fcacf4e 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -39,8 +39,12 @@ if ( it != cache.T.end() ) { e = it->second; return true; } #undef Handle +#include #include #include +#include +#include +#include typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; @@ -56,6 +60,8 @@ struct cgal_face_t { }; typedef CGAL::Polyhedron_3 cgal_shape_t; +typedef boost::graph_traits>::vertex_descriptor cgal_vertex_descriptor_t; +typedef boost::graph_traits>::face_descriptor cgal_face_descriptor_t; struct PolyhedronBuilder : public CGAL::Modifier_base::HalfedgeDS> { private: @@ -70,9 +76,9 @@ public: std::list> facet_vertices; CGAL::Polyhedron_incremental_builder_3::HalfedgeDS> builder(hds, true); - for (auto const &face: *face_list) { + for (auto &face: *face_list) { facet_vertices.push_back(std::list()); - for (auto const &point: face.outer) { + for (auto &point: face.outer) { if (points_map.count(point) == 0) { facet_vertices.back().push_back(points_map.size()); points_map[point] = points_map.size(); @@ -84,15 +90,15 @@ public: builder.begin_surface(points_map.size(), facet_vertices.size()); - for (auto const &point: points_map) { + for (auto &point: points_map) { // std::cout << "Adding point " << point.first << std::endl; builder.add_vertex(point.first); } - for (auto const &facet: facet_vertices) { + for (auto &facet: facet_vertices) { builder.begin_facet(); // std::cout << "Adding facet "; - for (auto const &vertex: facet) { + for (auto &vertex: facet) { // std::cout << vertex << " "; builder.add_vertex_to_facet(vertex); }