From b9828b029c917019bce4524d697c08edf5690db0 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Fri, 3 Mar 2017 15:25:45 -0600 Subject: [PATCH 01/17] Right way to output more than one object --- .../kernels/cgal/CgalConversionResult.cpp | 42 +++++++++++++------ .../kernels/cgal/CgalIfcGeomShapes.cpp | 7 ++-- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 59225e53f0..cb25f900ef 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -12,6 +12,11 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, vertex->point() = vertex->point().transform(trsf); } +// std::ofstream fbefore; +// fbefore.open("/Users/ken/Desktop/before.off"); +// fbefore << s << std::endl; +// fbefore.close(); + // Triangulate the shape and compute the normals std::map vertex_normals; boost::associative_property_map> vertex_normals_map(vertex_normals); @@ -23,26 +28,37 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape"); return; } + +// std::ofstream fafter; +// fafter.open("/Users/ken/Desktop/after.off"); +// fafter << s << std::endl; +// fafter.close(); CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); - - // Iterates over the faces of the shape - int num_faces = 0, num_vertices = 0; + std::map::Vertex_const_handle, int> vertices_map; + std::size_t initial_size = t->verts().size()/3; + for (auto &vertex: vertices(s)) { + if (vertices_map.count(vertex) == 0) { + vertices_map[vertex] = (int)(vertices_map.size()+initial_size); + t->addVertex(surface_style_id, + CGAL::to_double(vertex->point().cartesian(0)), + CGAL::to_double(vertex->point().cartesian(1)), + CGAL::to_double(vertex->point().cartesian(2))); +// std::cout << "Size: " << t->verts().size() << std::endl; + for (int i = 0; i < 3; ++i) t->normals().push_back(CGAL::to_double(vertex_normals_map[vertex].cartesian(i))); + } + } + for (auto &face: faces(s)) { + if (!face->is_triangle()) { + std::cout << "Warning: non-triangular face!" << std::endl; + continue; + } 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; + t->faces().push_back(vertices_map[current_halfedge->vertex()]); ++current_halfedge; } while (current_halfedge != face->facet_begin()); t->material_ids().push_back(surface_style_id); - ++num_faces; } - -// std::cout << num_faces << " faces" << std::endl; } diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 95fe301e15..e163bea2b8 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -526,8 +526,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s face_list.back().outer.push_back(icosahedron_vertices[8]); face_list.back().outer.push_back(icosahedron_vertices[1]); - // TODO: Refine icosahedron to create icosphere - const unsigned int refinements = 3; + const unsigned int refinements = 2; for (unsigned int current_refinement = 0; current_refinement < refinements; ++current_refinement) { std::list refined_face_list; for (auto &face: face_list) { @@ -675,7 +674,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, std::list face_list; - const int segments = 25; + const int segments = 12; // Base face_list.push_back(cgal_face_t()); @@ -733,7 +732,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal std::list face_list; - const int segments = 25; + const int segments = 12; // Base face_list.push_back(cgal_face_t()); From 64bc8e9d4fcf9554e4111a7ffa1512e8659ddaa6 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 10:52:57 -0600 Subject: [PATCH 02/17] Circular profiles, added missing transformation for rectangles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 41 +++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index afbb9db9f5..e35dad0f01 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -47,6 +47,7 @@ SHAPE(IfcRightCircularCylinder); SHAPE(IfcRightCircularCone); FACE(IfcArbitraryClosedProfileDef); +FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 7c4e64337f..05de331234 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -24,9 +24,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cg #ifdef USE_IFC4 has_position = l->hasPosition(); #endif - if (has_position) { - IfcGeom::CgalKernel::convert(l->Position(), trsf2d); - } face = cgal_face_t(); face.outer.push_back(Kernel::Point_3(-x, -y, 0.0)); @@ -34,6 +31,44 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cg face.outer.push_back(Kernel::Point_3( x, y, 0.0)); face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_face_t& face) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); + if ( r == 0.0f ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 12; + + face = cgal_face_t(); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + return true; } From 1bcc369c7a66425b17f7e340e3bdfdc8228f4711 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 11:12:06 -0600 Subject: [PATCH 03/17] Rounded rectangles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index e35dad0f01..d2b1deeb90 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -50,6 +50,7 @@ FACE(IfcArbitraryClosedProfileDef); FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); +FACE(IfcRoundedRectangleProfileDef); WIRE(IfcPolyLoop); WIRE(IfcPolyline); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 05de331234..fad3b6affa 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -41,6 +41,57 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cg return true; } +// TODO: Untested +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, cgal_face_t& face) { + const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double r = l->RoundingRadius() * getValue(GV_LENGTH_UNIT); + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO || r < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 3; + + face = cgal_face_t(); + + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); + } + + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (0.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); + } + + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (1.0*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); + } + + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (1.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_face_t& face) { const double r = l->Radius() * getValue(GV_LENGTH_UNIT); if ( r == 0.0f ) { From 584b2e5584eaecf6144b0e5031ad279c0dabec4c Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 11:18:51 -0600 Subject: [PATCH 04/17] IfcTrapeziumProfileDef --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index d2b1deeb90..2528bb3622 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -51,6 +51,7 @@ FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); FACE(IfcRoundedRectangleProfileDef); +FACE(IfcTrapeziumProfileDef) WIRE(IfcPolyLoop); WIRE(IfcPolyline); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index fad3b6affa..4b8c369820 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -92,6 +92,39 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTrapeziumProfileDef* l, cgal_face_t& face) { + const double x1 = l->BottomXDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double w = l->TopXDim() * getValue(GV_LENGTH_UNIT); + const double dx = l->TopXOffset() * getValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); + + if ( x1 < ALMOST_ZERO || w < ALMOST_ZERO || y < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + face = cgal_face_t(); + face.outer.push_back(Kernel::Point_3(-x1, -y, 0.0)); + face.outer.push_back(Kernel::Point_3(x1, -y, 0.0)); + face.outer.push_back(Kernel::Point_3(dx+w-x1, y, 0.0)); + face.outer.push_back(Kernel::Point_3(dx-x1, y, 0.0)); + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_face_t& face) { const double r = l->Radius() * getValue(GV_LENGTH_UNIT); if ( r == 0.0f ) { From 1d3732aa62bf67ee9d1845b178b136fd215a09f1 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 11:23:37 -0600 Subject: [PATCH 05/17] IfcEllipseProfileDef --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 3 +- src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 2528bb3622..65cdb41309 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -51,7 +51,8 @@ FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); FACE(IfcRoundedRectangleProfileDef); -FACE(IfcTrapeziumProfileDef) +FACE(IfcTrapeziumProfileDef); +FACE(IfcEllipseProfileDef); WIRE(IfcPolyLoop); WIRE(IfcPolyline); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 4b8c369820..294b9d8105 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -156,6 +156,39 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_ return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEllipseProfileDef* l, cgal_face_t& face) { + double rx = l->SemiAxis1() * getValue(GV_LENGTH_UNIT); + double ry = l->SemiAxis2() * getValue(GV_LENGTH_UNIT); + + if ( rx < ALMOST_ZERO || ry < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 12; + + face = cgal_face_t(); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(rx*cos(current_angle), ry*sin(current_angle), 0)); + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFace* l, cgal_face_t& face) { IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds(); From 033a2e748262fc011e90e18ea34f2368f41b06a0 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 11:28:57 -0600 Subject: [PATCH 06/17] IfcFaceBasedSurfaceModel --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 65cdb41309..635da2cfd1 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -35,6 +35,7 @@ SHAPES(IfcRepresentation); // IfcAdvancedBrepWithVoids included SHAPES(IfcManifoldSolidBrep); SHAPES(IfcMappedItem); +SHAPES(IfcFaceBasedSurfaceModel); SHAPE(IfcExtrudedAreaSolid); SHAPE(IfcConnectedFaceSet); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index e163bea2b8..66578c5763 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -84,6 +84,21 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR return b; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, ConversionResults& shapes) { + bool part_success = false; + IfcSchema::IfcConnectedFaceSet::list::ptr facesets = l->FbsmFaces(); + const SurfaceStyle* collective_style = get_style(l); + for( IfcSchema::IfcConnectedFaceSet::list::it it = facesets->begin(); it != facesets->end(); ++ it ) { + cgal_shape_t s; + const SurfaceStyle* shell_style = get_style(*it); + if (convert_shape(*it,s)) { + shapes.push_back(ConversionResult(new CgalShape(s), shell_style ? shell_style : collective_style)); + part_success |= true; + } + } + return part_success; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal_shape_t &shape) { const double height = l->Depth() * getValue(GV_LENGTH_UNIT); if (height < getValue(GV_PRECISION)) { From 484cea968e40a441480dfb8f533231fa3180e3ad Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 11:41:58 -0600 Subject: [PATCH 07/17] IfcTriangulatedFaceSet --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 635da2cfd1..072594ce65 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -46,6 +46,7 @@ SHAPE(IfcSphere); SHAPE(IfcRectangularPyramid); SHAPE(IfcRightCircularCylinder); SHAPE(IfcRightCircularCone); +SHAPE(IfcTriangulatedFaceSet); FACE(IfcArbitraryClosedProfileDef); FACE(IfcCircleProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 66578c5763..10f7bde015 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -790,3 +790,65 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal shape = polyhedron; return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cgal_shape_t& shape) { + IfcSchema::IfcCartesianPointList3D* point_list = l->Coordinates(); + const std::vector< std::vector > coordinates = point_list->CoordList(); + std::vector points; + points.reserve(coordinates.size()); + for (std::vector< std::vector >::const_iterator it = coordinates.begin(); it != coordinates.end(); ++it) { + const std::vector& coords = *it; + if (coords.size() != 3) { + Logger::Message(Logger::LOG_ERROR, "Invalid dimensions encountered on Coordinates", l->entity); + return false; + } + points.push_back(Kernel::Point_3(coords[0] * getValue(GV_LENGTH_UNIT), + coords[1] * getValue(GV_LENGTH_UNIT), + coords[2] * getValue(GV_LENGTH_UNIT))); + } + + std::vector< std::vector > indices = l->CoordIndex(); + + std::list face_list; + + for(std::vector< std::vector >::const_iterator it = indices.begin(); it != indices.end(); ++ it) { + const std::vector& tri = *it; + if (tri.size() != 3) { + Logger::Message(Logger::LOG_ERROR, "Invalid dimensions encountered on CoordIndex", l->entity); + return false; + } + + const int min_index = *std::min_element(tri.begin(), tri.end()); + const int max_index = *std::max_element(tri.begin(), tri.end()); + + if (min_index < 1 || max_index > (int) points.size()) { + Logger::Message(Logger::LOG_ERROR, "Contents of CoordIndex out of bounds", l->entity); + return false; + } + + const Kernel::Point_3& a = points[tri[0] - 1]; // account for zero- vs + const Kernel::Point_3& b = points[tri[1] - 1]; // one-based indices in + const Kernel::Point_3& c = points[tri[2] - 1]; // c++ and express + + face_list.push_back(cgal_face_t()); + face_list.back().outer.push_back(a); + face_list.back().outer.push_back(b); + face_list.back().outer.push_back(c); + } + + // Naive creation + cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + PolyhedronBuilder builder(&face_list); + polyhedron.delegate(builder); + + // Stitch edges + // std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); + if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { + CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); + } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); + // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; + + shape = polyhedron; + return true; +} From ca19d447cce742c648fbe082dddb637b803d9756 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 15:03:57 -0600 Subject: [PATCH 08/17] Zero-radius rounded rectangles --- src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 294b9d8105..4d208bd4cc 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -60,26 +60,29 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef const int segments = 3; - face = cgal_face_t(); - - for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = current_segment*0.5*3.141592653589793/((double)segments); - face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); + if (r == 0.0) { + face = cgal_face_t(); + face.outer.push_back(Kernel::Point_3(-x, -y, 0.0)); + face.outer.push_back(Kernel::Point_3( x, -y, 0.0)); + face.outer.push_back(Kernel::Point_3( x, y, 0.0)); + face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); } - for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (0.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); - face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); - } - - for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (1.0*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); - face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); - } - - for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (1.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); - face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); + else { + face = cgal_face_t(); + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); + } for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (0.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); + } for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (1.0*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); + } for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = (1.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); + } } if (has_position) { From 4f5ecee81e59d6eb567c521d453905c0f78e7462 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 16:03:29 -0600 Subject: [PATCH 09/17] Removing duplicate points, IfcCartesianTransformationOperator3D with problems --- .../kernels/cgal/CgalConversionFunctions.cpp | 41 +++++++++++++++++++ src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + .../kernels/cgal/CgalIfcGeomShapes.cpp | 23 ++++++++++- src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 8 ++-- src/ifcgeom/kernels/cgal/CgalKernel.h | 2 + 5 files changed, 69 insertions(+), 6 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index d0d6be43bc..6866dea9e9 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -152,3 +152,44 @@ bool IfcGeom::CgalKernel::convert_wire_to_face(const cgal_wire_t& wire, cgal_fac face.outer = wire; return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOperator3D* l, cgal_placement_t& trsf) { +// IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf) + cgal_point_t origin; + IfcGeom::CgalKernel::convert(l->LocalOrigin(),origin); + cgal_direction_t axis1 (1.,0.,0.); + cgal_direction_t axis2 (0.,1.,0.); + cgal_direction_t axis3 (0.,0.,1.); + if ( l->hasAxis1() ) IfcGeom::CgalKernel::convert(l->Axis1(),axis1); + if ( l->hasAxis2() ) IfcGeom::CgalKernel::convert(l->Axis2(),axis2); + if ( l->hasAxis3() ) IfcGeom::CgalKernel::convert(l->Axis3(),axis3); + double scale = 1.0; + if (l->hasScale()) { + scale = l->Scale(); + } + + trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0), + axis1.cartesian(1), scale*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1), + axis1.cartesian(2), axis2.cartesian(2), scale*axis3.cartesian(2), origin.cartesian(2)); + +// CACHE(IfcCartesianTransformationOperator3D,l,trsf) + return true; +} + +void IfcGeom::CgalKernel::remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol) { + if (tol <= 0.) tol = getValue(GV_PRECISION); + tol *= tol; + + for (int i = 0; i < polygon.size(); ++i) { + for (int j = i+1; j < polygon.size(); ++j) { + if (CGAL::squared_distance(polygon[i], polygon[j]) < tol) { + polygon.erase(polygon.begin()+j); + --j; + } + } if (closed) { + if (CGAL::squared_distance(polygon.front(), polygon.back()) < tol) { + polygon.erase(polygon.begin()+polygon.size()-1); + } + } + } +} diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 072594ce65..78ab93c02e 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -64,3 +64,4 @@ CLASS(IfcDirection,cgal_direction_t); CLASS(IfcAxis2Placement2D,cgal_placement_t); CLASS(IfcAxis2Placement3D,cgal_placement_t); CLASS(IfcObjectPlacement,cgal_placement_t); +CLASS(IfcCartesianTransformationOperator3D,cgal_placement_t); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 10f7bde015..0bdd75128f 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -43,8 +43,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcMappedItem* l, ConversionR return false; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3D) ) { cgal_placement_t trsf; - Logger::Message(Logger::LOG_ERROR, "Unsupported MappingTarget:", transform->entity); -// IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); + IfcGeom::CgalKernel::convert((IfcSchema::IfcCartesianTransformationOperator3D*)transform,trsf); gtrsf = trsf; } else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) { cgal_placement_t trsf_2d; @@ -108,6 +107,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal cgal_face_t face; if ( !convert_face(l->SweptArea(),face) ) return false; +// std::cout << "Face vertices: " << face.outer.size() << std::endl; cgal_placement_t trsf; bool has_position = true; @@ -125,6 +125,17 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal std::list face_list; face_list.push_back(face); +// if (true) { +// cgal_shape_t polyhedron = CGAL::Polyhedron_3(); +// PolyhedronBuilder builder(&face_list); +// polyhedron.delegate(builder); +// +// std::ofstream fresult; +// fresult.open("/Users/ken/Desktop/profile.off"); +// fresult << polyhedron << std::endl; +// fresult.close(); +// } + for (std::vector::const_iterator current_vertex = face.outer.begin(); current_vertex != face.outer.end(); ++current_vertex) { @@ -155,6 +166,14 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal // Stitch edges // std::cout << "Before: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; CGAL::Polygon_mesh_processing::stitch_borders(polyhedron); + if (!polyhedron.is_valid()) { + std::cout << "Invalid polyhedron!" << std::endl; + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/invalid.off"); + fresult << polyhedron << std::endl; + fresult.close(); + } + if (!CGAL::Polygon_mesh_processing::is_outward_oriented(polyhedron)) { CGAL::Polygon_mesh_processing::reverse_face_orientations(polyhedron); } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index c6d8820c65..b605eac93a 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -18,8 +18,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyLoop* l, cgal_wire_t& return false; } - // TODO: Remove repeated points and points that are too close to one another - // remove_duplicate_points_from_loop(polygon, true); + // Remove points that are too close to one another + remove_duplicate_points_from_loop(polygon, true); std::size_t count = polygon.size(); if (original_count - count != 0) { @@ -53,8 +53,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyline* l, cgal_wire_t& polygon.push_back(pnt); } - // TODO: Remove points that are too close to one another - // remove_duplicate_points_from_loop(polygon, false); + // Remove points that are too close to one another + remove_duplicate_points_from_loop(polygon, false); result = polygon; return true; diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 748fd4fbb3..30d0a33792 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -133,6 +133,8 @@ namespace IfcGeom { bool convert_face(const IfcUtil::IfcBaseClass* L, cgal_face_t& result); bool convert_wire_to_face(const cgal_wire_t& wire, cgal_face_t& face); + + void remove_duplicate_points_from_loop(cgal_wire_t& polygon, bool closed, double tol = -1.); // bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, ConversionResults& cut_shapes); From 27b5fd0fc50cf45bff5f60a07abf2530ad013aea Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 17:29:20 -0600 Subject: [PATCH 10/17] Debug code --- src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp index 6866dea9e9..040b09bd59 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionFunctions.cpp @@ -167,11 +167,18 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCartesianTransformationOpe if (l->hasScale()) { scale = l->Scale(); } - + + // TODO: Untested trsf = Kernel::Aff_transformation_3(scale*axis1.cartesian(0), axis2.cartesian(0), axis3.cartesian(0), origin.cartesian(0), axis1.cartesian(1), scale*axis2.cartesian(1), axis3.cartesian(1), origin.cartesian(1), axis1.cartesian(2), axis2.cartesian(2), scale*axis3.cartesian(2), origin.cartesian(2)); +// for (int i = 0; i < 3; ++i) { +// for (int j = 0; j < 4; ++j) { +// std::cout << trsf.cartesian(i, j) << " "; +// } std::cout << std::endl; +// } + // CACHE(IfcCartesianTransformationOperator3D,l,trsf) return true; } From 64e385c3614e293303ca4eb5c7679e23ec043b37 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 17:45:55 -0600 Subject: [PATCH 11/17] Skeleton for IfcEdgeLoop and IfcOrientedEdge --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 ++ src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 78ab93c02e..1d50cdff5c 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -56,6 +56,8 @@ FACE(IfcRoundedRectangleProfileDef); FACE(IfcTrapeziumProfileDef); FACE(IfcEllipseProfileDef); +WIRE(IfcEdgeLoop); +WIRE(IfcOrientedEdge); WIRE(IfcPolyLoop); WIRE(IfcPolyline); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index b605eac93a..07adccfe8c 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -59,3 +59,29 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcPolyline* l, cgal_wire_t& result = polygon; return true; } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEdgeLoop* l, cgal_wire_t& result) { + IfcSchema::IfcOrientedEdge::list::ptr li = l->EdgeList(); + cgal_wire_t mw; + for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) { + cgal_wire_t w; + if (convert_wire(*it, w)) { + // TODO: What to do here? +// mw.Add(TopoDS::Edge(TopoDS_Iterator(w).Value())); + return false; + } + } + result = mw; + return true; +} + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcOrientedEdge* l, cgal_wire_t& result) { + if (convert_wire(l->EdgeElement(), result)) { + if (!l->Orientation()) { + std::reverse(result.begin(),result.end()); + } + return true; + } else { + return false; + } +} From b299c2747387c6e48f67174cf8c704f65c905586 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Mon, 6 Mar 2017 19:28:12 -0600 Subject: [PATCH 12/17] Switched to Nef_polyhedron_3. Some problems... --- .../kernels/cgal/CgalConversionResult.cpp | 13 ++-- .../kernels/cgal/CgalIfcGeomShapes.cpp | 64 +++++++++---------- src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp | 2 +- src/ifcgeom/kernels/cgal/CgalKernel.h | 2 +- 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index cb25f900ef..beffd368cb 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -7,8 +7,11 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, // std::cout << "Model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; // std::cout << "Valid: " << s.is_valid() << std::endl; + CGAL::Polyhedron_3 polyhedron; + s.convert_to_polyhedron(polyhedron); + // Apply transformation - if (place != NULL) for (auto &vertex: vertices(s)) { + if (place != NULL) for (auto &vertex: vertices(polyhedron)) { vertex->point() = vertex->point().transform(trsf); } @@ -22,7 +25,7 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, boost::associative_property_map> vertex_normals_map(vertex_normals); std::map face_normals; boost::associative_property_map> face_normals_map(face_normals); - if (CGAL::Polygon_mesh_processing::triangulate_faces(s)) { + if (CGAL::Polygon_mesh_processing::triangulate_faces(polyhedron)) { // std::cout << "Triangulated model: " << s.size_of_facets() << " facets and " << s.size_of_vertices() << " vertices" << std::endl; } else { Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape"); @@ -34,10 +37,10 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, // fafter << s << std::endl; // fafter.close(); - CGAL::Polygon_mesh_processing::compute_normals(s, vertex_normals_map, face_normals_map); + CGAL::Polygon_mesh_processing::compute_normals(polyhedron, vertex_normals_map, face_normals_map); std::map::Vertex_const_handle, int> vertices_map; std::size_t initial_size = t->verts().size()/3; - for (auto &vertex: vertices(s)) { + for (auto &vertex: vertices(polyhedron)) { if (vertices_map.count(vertex) == 0) { vertices_map[vertex] = (int)(vertices_map.size()+initial_size); t->addVertex(surface_style_id, @@ -49,7 +52,7 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, } } - for (auto &face: faces(s)) { + for (auto &face: faces(polyhedron)) { if (!face->is_triangle()) { std::cout << "Warning: non-triangular face!" << std::endl; continue; diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 0bdd75128f..6a5d2bf88a 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -159,7 +159,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal } face_list.push_back(top_face); // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -179,7 +179,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -209,7 +209,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ } // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -221,7 +221,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcConnectedFaceSet* l, cgal_ } // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -279,7 +279,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& sh face_list.back().outer.push_back(Kernel::Point_3(dx, 0, dz)); // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -298,7 +298,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBlock* l, cgal_shape_t& sh vertex->point() = vertex->point().transform(trsf); } - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -359,16 +359,12 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha const IfcSchema::IfcBooleanOperator::IfcBooleanOperator op = l->Operator(); - CGAL_precondition(s1.is_valid() && s1.is_closed()); - CGAL::Nef_polyhedron_3 nef1(s1); - if (!nef1.is_simple()) { + if (!s1.is_simple()) { Logger::Message(Logger::LOG_ERROR, "s1: Not simple Nef?", operand1->entity); return false; } - CGAL_precondition(s2.is_valid() && s2.is_closed()); - CGAL::Nef_polyhedron_3 nef2(s2); - if (!nef2.is_simple()) { + if (!s2.is_simple()) { Logger::Message(Logger::LOG_ERROR, "s2: Not simple Nef?", operand2->entity); return false; } @@ -385,52 +381,52 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcBooleanResult* l, cgal_sha if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { // std::cout << "Difference" << std::endl; - CGAL::Nef_polyhedron_3 nef_result = nef1-nef2; + CGAL::Nef_polyhedron_3 nef_result = s1-s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; } - cgal_shape_t result; - nef_result.convert_to_polyhedron(result); +// cgal_shape_t result; +// nef_result.convert_to_polyhedron(result); // std::ofstream fresult; // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - shape = result; + shape = nef_result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) { // std::cout << "Union" << std::endl; - CGAL::Nef_polyhedron_3 nef_result = nef1+nef2; + CGAL::Nef_polyhedron_3 nef_result = s1+s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; } - cgal_shape_t result; - nef_result.convert_to_polyhedron(result); +// cgal_shape_t result; +// nef_result.convert_to_polyhedron(result); // std::ofstream fresult; // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - shape = result; + shape = nef_result; return true; } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) { // std::cout << "Intersection" << std::endl; - CGAL::Nef_polyhedron_3 nef_result = nef1*nef2; + CGAL::Nef_polyhedron_3 nef_result = s1*s2; if (!nef_result.is_simple()) { std::cout << "Not simple: " << nef_result.number_of_volumes() << " volumes" << std::endl; return false; } - cgal_shape_t result; - nef_result.convert_to_polyhedron(result); +// cgal_shape_t result; +// nef_result.convert_to_polyhedron(result); // std::ofstream fresult; // fresult.open("/Users/ken/Desktop/result.off"); // fresult << result << std::endl; // fresult.close(); - shape = result; + shape = nef_result; return true; } @@ -608,7 +604,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s } // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -639,7 +635,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcSphere* l, cgal_shape_t& s // fresult << polyhedron << std::endl; // fresult.close(); - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -679,7 +675,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cga face_list.back().outer.push_back(Kernel::Point_3(0.5*dx, 0.5*dy, dz)); // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -698,7 +694,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangularPyramid* l, cga vertex->point() = vertex->point().transform(trsf); } - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -737,7 +733,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, } // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -756,7 +752,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCylinder* l, vertex->point() = vertex->point().transform(trsf); } - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -787,7 +783,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal } // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -806,7 +802,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRightCircularCone* l, cgal vertex->point() = vertex->point().transform(trsf); } - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } @@ -856,7 +852,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cg } // Naive creation - cgal_shape_t polyhedron = CGAL::Polyhedron_3(); + CGAL::Polyhedron_3 polyhedron = CGAL::Polyhedron_3(); PolyhedronBuilder builder(&face_list); polyhedron.delegate(builder); @@ -868,6 +864,6 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, cg } CGAL_postcondition(polyhedron.is_valid() && polyhedron.is_closed()); // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; - shape = polyhedron; + shape = CGAL::Nef_polyhedron_3(polyhedron); return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index 07adccfe8c..220b854930 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -66,7 +66,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEdgeLoop* l, cgal_wire_t& for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) { cgal_wire_t w; if (convert_wire(*it, w)) { - // TODO: What to do here? + // TODO: What to do here? Add some points only? // mw.Add(TopoDS::Edge(TopoDS_Iterator(w).Value())); return false; } diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 30d0a33792..ada2fdd91c 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -62,7 +62,7 @@ struct cgal_face_t { std::vector inner; }; -typedef CGAL::Polyhedron_3 cgal_shape_t; +typedef CGAL::Nef_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; From 1fb76a9749acfb4eb28381c0c016cdfc988e4bfd Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 12:50:06 -0600 Subject: [PATCH 13/17] Switched to normals per vertex per face --- .../kernels/cgal/CgalConversionResult.cpp | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index beffd368cb..171b7ee2e8 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -38,19 +38,6 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, // fafter.close(); CGAL::Polygon_mesh_processing::compute_normals(polyhedron, vertex_normals_map, face_normals_map); - std::map::Vertex_const_handle, int> vertices_map; - std::size_t initial_size = t->verts().size()/3; - for (auto &vertex: vertices(polyhedron)) { - if (vertices_map.count(vertex) == 0) { - vertices_map[vertex] = (int)(vertices_map.size()+initial_size); - t->addVertex(surface_style_id, - CGAL::to_double(vertex->point().cartesian(0)), - CGAL::to_double(vertex->point().cartesian(1)), - CGAL::to_double(vertex->point().cartesian(2))); -// std::cout << "Size: " << t->verts().size() << std::endl; - for (int i = 0; i < 3; ++i) t->normals().push_back(CGAL::to_double(vertex_normals_map[vertex].cartesian(i))); - } - } for (auto &face: faces(polyhedron)) { if (!face->is_triangle()) { @@ -59,7 +46,12 @@ void IfcGeom::CgalShape::Triangulate(const IfcGeom::IteratorSettings & settings, } CGAL::Polyhedron_3::Halfedge_around_facet_const_circulator current_halfedge = face->facet_begin(); do { - t->faces().push_back(vertices_map[current_halfedge->vertex()]); + t->faces().push_back((int)t->verts().size()/3); + 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))); ++current_halfedge; } while (current_halfedge != face->facet_begin()); t->material_ids().push_back(surface_style_id); From 29021d8b0638fb1d517a11caed04906f9efc68cb Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 13:04:22 -0600 Subject: [PATCH 14/17] Hollow circles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 1d50cdff5c..f9f1b43252 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -49,6 +49,7 @@ SHAPE(IfcRightCircularCone); SHAPE(IfcTriangulatedFaceSet); FACE(IfcArbitraryClosedProfileDef); +FACE(IfcCircleHollowProfileDef); FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRectangleProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index 4d208bd4cc..f49fcc8cf2 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -159,6 +159,45 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleProfileDef* l, cgal_ return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleHollowProfileDef* l, cgal_face_t& face) { + const double r = l->Radius() * getValue(GV_LENGTH_UNIT); + const double t = l->WallThickness() * getValue(GV_LENGTH_UNIT); + + if ( r == 0.0f || t == 0.0f ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 12; + + face = cgal_face_t(); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(r*cos(current_angle), r*sin(current_angle), 0)); + } + + face.inner.push_back(cgal_wire_t()); + for (int current_segment = 0; current_segment < segments; ++current_segment) { + double current_angle = current_segment*2.0*3.141592653589793/((double)segments); + face.inner.back().push_back(Kernel::Point_3((r-t)*cos(current_angle), (r-t)*sin(current_angle), 0)); + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } + } + + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcEllipseProfileDef* l, cgal_face_t& face) { double rx = l->SemiAxis1() * getValue(GV_LENGTH_UNIT); double ry = l->SemiAxis2() * getValue(GV_LENGTH_UNIT); From 31d4de228abc4136409845a3b0f63482e79771a4 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 13:18:49 -0600 Subject: [PATCH 15/17] Extrusions with holes (Nef) --- .../kernels/cgal/CgalIfcGeomShapes.cpp | 76 ++++++++++++++++--- 1 file changed, 67 insertions(+), 9 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 6a5d2bf88a..f028fec103 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -105,8 +105,9 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal return false; } - cgal_face_t face; - if ( !convert_face(l->SweptArea(),face) ) return false; + // Outer + cgal_face_t bottom_face; + if ( !convert_face(l->SweptArea(),bottom_face) ) return false; // std::cout << "Face vertices: " << face.outer.size() << std::endl; cgal_placement_t trsf; @@ -123,7 +124,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal // std::cout << "Direction: " << dir << std::endl; std::list face_list; - face_list.push_back(face); + face_list.push_back(bottom_face); // if (true) { // cgal_shape_t polyhedron = CGAL::Polyhedron_3(); @@ -136,13 +137,13 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal // fresult.close(); // } - for (std::vector::const_iterator current_vertex = face.outer.begin(); - current_vertex != face.outer.end(); + for (std::vector::const_iterator current_vertex = bottom_face.outer.begin(); + current_vertex != bottom_face.outer.end(); ++current_vertex) { std::vector::const_iterator next_vertex = current_vertex; ++next_vertex; - if (next_vertex == face.outer.end()) { - next_vertex = face.outer.begin(); + if (next_vertex == bottom_face.outer.end()) { + next_vertex = bottom_face.outer.begin(); } cgal_face_t side_face; side_face.outer.push_back(*next_vertex); side_face.outer.push_back(*current_vertex); @@ -152,8 +153,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal } cgal_face_t top_face; - for (std::vector::const_reverse_iterator vertex = face.outer.rbegin(); - vertex != face.outer.rend(); + for (std::vector::const_reverse_iterator vertex = bottom_face.outer.rbegin(); + vertex != bottom_face.outer.rend(); ++vertex) { top_face.outer.push_back(*vertex+height*dir); } face_list.push_back(top_face); @@ -180,6 +181,63 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal // std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl; shape = CGAL::Nef_polyhedron_3(polyhedron); + + // Inner + // TODO: Would be faster to triangulate top/bottom face template rather than use Nef polyhedra for subtraction + for (auto &inner: bottom_face.inner) { +// std::cout << "Inner wire" << std::endl; + face_list.clear(); + + cgal_face_t hole_bottom_face; + hole_bottom_face.outer = inner; + face_list.push_back(hole_bottom_face); + + for (std::vector::const_iterator current_vertex = inner.begin(); + current_vertex != inner.end(); + ++current_vertex) { + std::vector::const_iterator next_vertex = current_vertex; + ++next_vertex; + if (next_vertex == inner.end()) { + next_vertex = inner.begin(); + } cgal_face_t hole_side_face; + hole_side_face.outer.push_back(*next_vertex); + hole_side_face.outer.push_back(*current_vertex); + hole_side_face.outer.push_back(*current_vertex+height*dir); + hole_side_face.outer.push_back(*next_vertex+height*dir); + face_list.push_back(hole_side_face); + } + + cgal_face_t hole_top_face; + for (std::vector::const_reverse_iterator vertex = inner.rbegin(); + vertex != inner.rend(); + ++vertex) { + hole_top_face.outer.push_back(*vertex+height*dir); + } face_list.push_back(hole_top_face); + + // Naive creation + CGAL::Polyhedron_3 hole_polyhedron = CGAL::Polyhedron_3(); + PolyhedronBuilder builder(&face_list); + hole_polyhedron.delegate(builder); + + // Stitch edges + // std::cout << "Before: " << hole_polyhedron.size_of_vertices() << " vertices and " << hole_polyhedron.size_of_facets() << " facets" << std::endl; + CGAL::Polygon_mesh_processing::stitch_borders(hole_polyhedron); + if (!hole_polyhedron.is_valid()) { + std::cout << "Invalid hole polyhedron!" << std::endl; + std::ofstream fresult; + fresult.open("/Users/ken/Desktop/invalid.off"); + fresult << hole_polyhedron << std::endl; + fresult.close(); + } + + if (!CGAL::Polygon_mesh_processing::is_outward_oriented(hole_polyhedron)) { + CGAL::Polygon_mesh_processing::reverse_face_orientations(hole_polyhedron); + } CGAL_postcondition(hole_polyhedron.is_valid() && hole_polyhedron.is_closed()); + // std::cout << "After: " << hole_polyhedron.size_of_vertices() << " vertices and " << hole_polyhedron.size_of_facets() << " facets" << std::endl; + + shape -= CGAL::Nef_polyhedron_3(hole_polyhedron); + } + return true; } From 66048610e239232237983ede202bbc92bbbb4001 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 13:41:04 -0600 Subject: [PATCH 16/17] Rounded rectangles work now, def must be before rectangles --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 2 +- src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index f9f1b43252..52ca33352d 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -52,8 +52,8 @@ FACE(IfcArbitraryClosedProfileDef); FACE(IfcCircleHollowProfileDef); FACE(IfcCircleProfileDef); FACE(IfcFace); -FACE(IfcRectangleProfileDef); FACE(IfcRoundedRectangleProfileDef); +FACE(IfcRectangleProfileDef); FACE(IfcTrapeziumProfileDef); FACE(IfcEllipseProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index f49fcc8cf2..c5e861b587 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -43,6 +43,8 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cg // TODO: Untested bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, cgal_face_t& face) { + std::cout << "IfcRoundedRectangleProfileDef" << std::endl; + const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); const double r = l->RoundingRadius() * getValue(GV_LENGTH_UNIT); @@ -73,14 +75,17 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef for (int current_segment = 0; current_segment <= segments; ++current_segment) { double current_angle = current_segment*0.5*3.141592653589793/((double)segments); face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); - } for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (0.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), y-r+r*sin(current_angle), 0)); - } for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (1.0*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); face.outer.push_back(Kernel::Point_3(-x+r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); - } for (int current_segment = 0; current_segment <= segments; ++current_segment) { - double current_angle = (1.5*3.141592653589793+current_segment*0.5*3.141592653589793)/((double)segments); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); face.outer.push_back(Kernel::Point_3(x-r+r*cos(current_angle), -y+r+r*sin(current_angle), 0)); } } From 27d8e860245f9b3a725ca7bbad464337e35361f8 Mon Sep 17 00:00:00 2001 From: Ken Arroyo Ohori Date: Tue, 7 Mar 2017 13:52:29 -0600 Subject: [PATCH 17/17] Hollow rectangle profiles, all tested now --- src/ifcgeom/kernels/cgal/CgalEntityMapping.h | 1 + src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp | 101 +++++++++++++++++- 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 52ca33352d..b85f741966 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -53,6 +53,7 @@ FACE(IfcCircleHollowProfileDef); FACE(IfcCircleProfileDef); FACE(IfcFace); FACE(IfcRoundedRectangleProfileDef); +FACE(IfcRectangleHollowProfileDef); FACE(IfcRectangleProfileDef); FACE(IfcTrapeziumProfileDef); FACE(IfcEllipseProfileDef); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp index c5e861b587..9e8fe9fecf 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomFaces.cpp @@ -41,10 +41,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleProfileDef* l, cg return true; } -// TODO: Untested bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef* l, cgal_face_t& face) { - std::cout << "IfcRoundedRectangleProfileDef" << std::endl; - const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); const double r = l->RoundingRadius() * getValue(GV_LENGTH_UNIT); @@ -100,6 +97,100 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRoundedRectangleProfileDef return true; } +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcRectangleHollowProfileDef* l, cgal_face_t& face) { + const double x = l->XDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double y = l->YDim() / 2.0f * getValue(GV_LENGTH_UNIT); + const double d = l->WallThickness() * getValue(GV_LENGTH_UNIT); + + const bool fr1 = l->hasOuterFilletRadius(); + const bool fr2 = l->hasInnerFilletRadius(); + + const double r1 = fr1 ? l->OuterFilletRadius() * getValue(GV_LENGTH_UNIT) : 0.; + const double r2 = fr2 ? l->InnerFilletRadius() * getValue(GV_LENGTH_UNIT) : 0.; + + if ( x < ALMOST_ZERO || y < ALMOST_ZERO ) { + Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity); + return false; + } + + cgal_placement_t trsf2d; + bool has_position = true; +#ifdef USE_IFC4 + has_position = l->hasPosition(); +#endif + + const int segments = 3; + + if (!fr1 || r1 == 0.0) { + face = cgal_face_t(); + face.outer.push_back(Kernel::Point_3(-x, -y, 0.0)); + face.outer.push_back(Kernel::Point_3( x, -y, 0.0)); + face.outer.push_back(Kernel::Point_3( x, y, 0.0)); + face.outer.push_back(Kernel::Point_3(-x, y, 0.0)); + } + + else { + face = cgal_face_t(); + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r1+r1*cos(current_angle), y-r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r1+r1*cos(current_angle), y-r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(-x+r1+r1*cos(current_angle), -y+r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.outer.push_back(Kernel::Point_3(x-r1+r1*cos(current_angle), -y+r1+r1*sin(current_angle), 0)); + } + } + + if (!fr2 || r2 == 0.0) { + face.inner.push_back(cgal_wire_t()); + face.inner.back().push_back(Kernel::Point_3(-x+d, -y+d, 0.0)); + face.inner.back().push_back(Kernel::Point_3( x-d, -y+d, 0.0)); + face.inner.back().push_back(Kernel::Point_3( x-d, y-d, 0.0)); + face.inner.back().push_back(Kernel::Point_3(-x+d, y-d, 0.0)); + } + + else { + face.inner.push_back(cgal_wire_t()); + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = current_segment*0.5*3.141592653589793/((double)segments); + face.inner.back().push_back(Kernel::Point_3(x-d-r1+r1*cos(current_angle), y-d-r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 0.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.inner.back().push_back(Kernel::Point_3(-x+d+r1+r1*cos(current_angle), y-d-r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.0*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.inner.back().push_back(Kernel::Point_3(-x+d+r1+r1*cos(current_angle), -y+d+r1+r1*sin(current_angle), 0)); + } + for (int current_segment = 0; current_segment <= segments; ++current_segment) { + double current_angle = 1.5*3.141592653589793+current_segment*0.5*3.141592653589793/((double)segments); + face.inner.back().push_back(Kernel::Point_3(x-d-r1+r1*cos(current_angle), -y+d+r1+r1*sin(current_angle), 0)); + } + } + + if (has_position) { + IfcGeom::CgalKernel::convert(l->Position(), trsf2d); + for (auto &vertex: face.outer) { + vertex = vertex.transform(trsf2d); + } for (auto &inner: face.inner) { + for (auto &vertex: inner) { + vertex = vertex.transform(trsf2d); + } + } + } + + return true; +} + bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcTrapeziumProfileDef* l, cgal_face_t& face) { const double x1 = l->BottomXDim() / 2.0f * getValue(GV_LENGTH_UNIT); const double w = l->TopXDim() * getValue(GV_LENGTH_UNIT); @@ -197,6 +288,10 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCircleHollowProfileDef* l, IfcGeom::CgalKernel::convert(l->Position(), trsf2d); for (auto &vertex: face.outer) { vertex = vertex.transform(trsf2d); + } for (auto &inner: face.inner) { + for (auto &vertex: inner) { + vertex = vertex.transform(trsf2d); + } } }