diff --git a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h index 77c654e604..a6e8430528 100644 --- a/src/ifcgeom/kernels/cgal/CgalEntityMapping.h +++ b/src/ifcgeom/kernels/cgal/CgalEntityMapping.h @@ -63,6 +63,7 @@ WIRE(IfcEdgeLoop); WIRE(IfcOrientedEdge); WIRE(IfcPolyLoop); WIRE(IfcPolyline); +WIRE(IfcCompositeCurve); CLASS(IfcCartesianPoint,cgal_point_t); CLASS(IfcDirection,cgal_direction_t); diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp index 8882d9e961..07df06545f 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomShapes.cpp @@ -127,7 +127,7 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcExtrudedAreaSolid *l, cgal face_list.push_back(bottom_face); // if (true) { -// cgal_shape_t polyhedron = CGAL::Polyhedron_3(); +// CGAL::Polyhedron_3 polyhedron; // PolyhedronBuilder builder(&face_list); // polyhedron.delegate(builder); // @@ -166,12 +166,13 @@ 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::Polyhedron_3 old_polyhedron(polyhedron); 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 << old_polyhedron << std::endl; fresult.close(); } diff --git a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp index 220b854930..72ac78fa2d 100644 --- a/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp +++ b/src/ifcgeom/kernels/cgal/CgalIfcGeomWires.cpp @@ -85,3 +85,93 @@ bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcOrientedEdge* l, cgal_wire return false; } } + +bool IfcGeom::CgalKernel::convert(const IfcSchema::IfcCompositeCurve* l, cgal_wire_t& wire) { + if ( getValue(GV_PLANEANGLE_UNIT)<0 ) { + Logger::Message(Logger::LOG_WARNING,"Creating a composite curve without unit information:",l->entity); + + // Temporarily pretend we do have unit information + setValue(GV_PLANEANGLE_UNIT,1.0); + + bool succes_radians = false; + bool succes_degrees = false; + bool use_radians = false; + bool use_degrees = false; + + // First try radians + cgal_wire_t wire_radians, wire_degrees; + try { + succes_radians = IfcGeom::CgalKernel::convert(l,wire_radians); + } catch (...) {} + + // Now try degrees + setValue(GV_PLANEANGLE_UNIT,0.0174532925199433); + try { + succes_degrees = IfcGeom::CgalKernel::convert(l,wire_degrees); + } catch (...) {} + + // Restore to unknown unit state + setValue(GV_PLANEANGLE_UNIT,-1.0); + + if ( succes_degrees && ! succes_radians ) { + use_degrees = true; + } else if ( succes_radians && ! succes_degrees ) { + use_radians = true; + } else if ( succes_radians && succes_degrees ) { + if ( wire_degrees.back() == wire_degrees.front() && wire_radians.back() != wire_radians.front() ) { + use_degrees = true; + } else if ( wire_radians.back() == wire_radians.front() && wire_degrees.back() != wire_degrees.front() ) { + use_radians = true; + } else { + // No heuristic left to prefer the one over the other, + // apparently both variants are equally succesful. + // The curve might be composed of only straight segments. + // Let's go with the wire created using radians as that + // at least is a SI unit. + use_radians = true; + } + } + + if ( use_radians ) { + Logger::Message(Logger::LOG_NOTICE,"Used radians to create composite curve"); + wire = wire_radians; + } else if ( use_degrees ) { + Logger::Message(Logger::LOG_NOTICE,"Used degrees to create composite curve"); + wire = wire_degrees; + } + + return use_radians || use_degrees; + } + IfcSchema::IfcCompositeCurveSegment::list::ptr segments = l->Segments(); + cgal_wire_t w; + //TopoDS_Vertex last_vertex; + for( IfcSchema::IfcCompositeCurveSegment::list::it it = segments->begin(); it != segments->end(); ++ it ) { + IfcSchema::IfcCurve* curve = (*it)->ParentCurve(); + cgal_wire_t wire2; + if ( !convert_wire(curve,wire2) ) { + Logger::Message(Logger::LOG_ERROR,"Failed to convert curve:",curve->entity); + continue; + } + if ( ! (*it)->SameSense() ) std::reverse(wire2.begin(),wire2.end()); + + if (wire2.empty()) { + continue; + } else if (w.empty()) { + w = wire2; + } else if (w.back() == w.front()) { + std::vector::const_iterator vertex = wire2.begin(); + ++vertex; + while (vertex != wire2.end()) { + w.push_back(*vertex); + ++vertex; + } + } else { + for (auto &vertex: wire2) w.push_back(vertex); + } + } + + remove_duplicate_points_from_loop(w, false); + + wire = w; + return true; +}