@@ -562,57 +562,73 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangularTrimmedSurface::ptr l, Topo
562562}
563563
564564bool IfcGeom::convert (const IfcSchema::IfcSurfaceCurveSweptAreaSolid::ptr l, TopoDS_Shape& shape) {
565- gp_Trsf trsf, axis , position;
565+ gp_Trsf directrix , position;
566566 TopoDS_Shape face;
567567 TopoDS_Wire wire, section;
568-
569- if (!IfcGeom::convert_face (l->SweptArea (), face)) {
570- return false ;
571- }
572568
573- if (!IfcGeom::convert_wire (l->Directrix (), wire)) {
569+ if (!l->ReferenceSurface ()->is (IfcSchema::Type::IfcPlane)) {
570+ Logger::Message (Logger::LOG_WARNING, " Reference surface not supported" , l->ReferenceSurface ()->entity );
574571 return false ;
575572 }
576-
577- axis.SetTransformation (gp_Ax3 (gp::Origin (), gp::DX (), -gp::DZ ()));
578- IfcGeom::convert (l->Position (), position);
579-
580- if (!l->ReferenceSurface ()->is (IfcSchema::Type::IfcPlane)) {
581- // Not implemented
573+
574+ if (!IfcGeom::convert (l->Position (), position) ||
575+ !IfcGeom::convert_face (l->SweptArea (), face) ||
576+ !IfcGeom::convert_wire (l->Directrix (), wire) ) {
582577 return false ;
583578 }
584579
585580 gp_Pln pln;
581+ gp_Pnt directrix_origin;
582+ gp_Vec directrix_tangent;
583+ bool directrix_on_plane = true ;
586584 IfcGeom::convert ((IfcSchema::IfcPlane*) l->ReferenceSurface (), pln);
587585
588- trsf.SetTransformation (pln.Position ());
589- trsf.Invert ();
590- trsf.Multiply (axis);
591-
586+ // As per Informal propositions 2: The Directrix shall lie on the ReferenceSurface.
587+ // This is not always the case with the test files in the repository. I am not sure
588+ // how to deal with this and whether my interpretation of the propositions is
589+ // correct. However, if it has been asserted that the vertices of the directrix do
590+ // not conform to the ReferenceSurface, the ReferenceSurface is ignored.
591+ {
592+ for (TopExp_Explorer exp (wire, TopAbs_VERTEX); exp.More (); exp.Next ()) {
593+ if (pln.Distance (BRep_Tool::Pnt (TopoDS::Vertex (exp.Current ()))) > ALMOST_ZERO) {
594+ directrix_on_plane = false ;
595+ Logger::Message (Logger::LOG_WARNING, " The Directrix does not lie on the ReferenceSurface" , l->entity );
596+ break ;
597+ }
598+ }
599+ }
600+
601+ {
602+ TopExp_Explorer exp (wire, TopAbs_EDGE);
603+ TopoDS_Edge edge = TopoDS::Edge (exp.Current ());
604+ double u0, u1;
605+ Handle (Geom_Curve) crv = BRep_Tool::Curve (edge, u0, u1);
606+ crv->D1 (u0, directrix_origin, directrix_tangent);
607+ }
608+
609+ if (pln.Axis ().Direction ().IsNormal (directrix_tangent, Precision::Approximation ()) && directrix_on_plane) {
610+ directrix.SetTransformation (gp_Ax3 (directrix_origin, directrix_tangent, pln.Axis ().Direction ()), gp::XOY ());
611+ } else {
612+ directrix.SetTransformation (gp_Ax3 (directrix_origin, directrix_tangent), gp::XOY ());
613+ }
614+ face = BRepBuilderAPI_Transform (face, directrix);
615+
592616 // NB: Note that StartParam and EndParam param are ignored and the assumption is
593617 // made that the parametric range over which to be swept matches the IfcCurve in
594618 // its entirety.
595619 BRepOffsetAPI_MakePipeShell builder (wire);
596620
597- face = BRepBuilderAPI_Transform (face, trsf);
598-
599- TopExp_Explorer exp (face, TopAbs_WIRE);
600- section = TopoDS::Wire (exp.Current ());
621+ { TopExp_Explorer exp (face, TopAbs_WIRE);
622+ section = TopoDS::Wire (exp.Current ()); }
601623
602624 builder.Add (section);
603625 builder.SetTransitionMode (BRepBuilderAPI_RightCorner);
626+ if (directrix_on_plane) {
627+ builder.SetMode (pln.Axis ().Direction ());
628+ }
604629 builder.Build ();
605-
630+ builder. MakeSolid ();
606631 shape = builder.Shape ();
607-
608- bool succeeded = false ;
609- try {
610- succeeded = IfcGeom::fill_nonmanifold_wires_with_planar_faces (shape);
611- } catch (...) {}
612- if (!succeeded) {
613- Logger::Message (Logger::LOG_WARNING, " Failed to cap solid for:" , l->entity );
614- }
615-
616632 shape.Move (position);
617633
618634 return true ;
0 commit comments