@@ -637,6 +637,81 @@ bool IfcGeom::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid::ptr l, Top
637637 return true ;
638638}
639639
640+ bool IfcGeom::convert (const IfcSchema::IfcSweptDiskSolid::ptr l, TopoDS_Shape& shape) {
641+ TopoDS_Wire wire, section1, section2;
642+
643+ const bool hasInnerRadius = l->hasInnerRadius ();
644+
645+ if (!IfcGeom::convert_wire (l->Directrix (), wire)) {
646+ return false ;
647+ }
648+
649+ gp_Ax2 directrix;
650+ {
651+ gp_Pnt directrix_origin;
652+ gp_Vec directrix_tangent;
653+ TopExp_Explorer exp (wire, TopAbs_EDGE);
654+ TopoDS_Edge edge = TopoDS::Edge (exp.Current ());
655+ double u0, u1;
656+ Handle (Geom_Curve) crv = BRep_Tool::Curve (edge, u0, u1);
657+ crv->D1 (u0, directrix_origin, directrix_tangent);
658+ directrix = gp_Ax2 (directrix_origin, directrix_tangent);
659+ }
660+
661+ const double r1 = l->Radius () * IfcGeom::GetValue (GV_LENGTH_UNIT);
662+ Handle (Geom_Circle) circle = new Geom_Circle (directrix, r1);
663+ section1 = BRepBuilderAPI_MakeWire (BRepBuilderAPI_MakeEdge (circle));
664+
665+ if (hasInnerRadius) {
666+ const double r2 = l->InnerRadius () * IfcGeom::GetValue (GV_LENGTH_UNIT);
667+ Handle (Geom_Circle) circle = new Geom_Circle (directrix, r2);
668+ section2 = BRepBuilderAPI_MakeWire (BRepBuilderAPI_MakeEdge (circle));
669+ }
670+
671+ // NB: Note that StartParam and EndParam param are ignored and the assumption is
672+ // made that the parametric range over which to be swept matches the IfcCurve in
673+ // its entirety.
674+ // NB2: Contrary to IfcSurfaceCurveSweptAreaSolid the transition mode has been
675+ // set to create round corners as this has proven to work better with the types
676+ // of directrices encountered, which do not necessarily conform to a surface.
677+ { BRepOffsetAPI_MakePipeShell builder (wire);
678+ builder.Add (section1);
679+ builder.SetTransitionMode (BRepBuilderAPI_RoundCorner);
680+ builder.Build ();
681+ builder.MakeSolid ();
682+ shape = builder.Shape (); }
683+
684+ if (hasInnerRadius) {
685+ BRepOffsetAPI_MakePipeShell builder (wire);
686+ builder.Add (section2);
687+ builder.SetTransitionMode (BRepBuilderAPI_RoundCorner);
688+ builder.Build ();
689+ builder.MakeSolid ();
690+ TopoDS_Shape inner = builder.Shape ();
691+
692+ BRepAlgoAPI_Cut brep_cut (shape, inner);
693+ bool is_valid = false ;
694+ if (brep_cut.IsDone ()) {
695+ TopoDS_Shape result = brep_cut;
696+
697+ ShapeFix_Shape fix (result);
698+ fix.Perform ();
699+ result = fix.Shape ();
700+
701+ is_valid = BRepCheck_Analyzer (result).IsValid () != 0 ;
702+ if (is_valid) {
703+ shape = result;
704+ }
705+ }
706+
707+ if (!is_valid) {
708+ Logger::Message (Logger::LOG_WARNING, " Failed to subtract inner radius void for:" , l->entity );
709+ }
710+ }
711+
712+ return true ;
713+ }
714+
640715#ifdef USE_IFC4
641716
642717bool IfcGeom::convert (const IfcSchema::IfcCylindricalSurface::ptr l, TopoDS_Shape& face) {
0 commit comments