Skip to content

Commit f9e94f5

Browse files
author
aothms
committed
IfcSurfaceCurveSweptAreaSolid improvements
1 parent 691e576 commit f9e94f5

2 files changed

Lines changed: 58 additions & 31 deletions

File tree

src/ifcgeom/IfcGeomFunctions.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ TopoDS_Vertex find_other(const TopoDS_Edge& edge, const TopoDS_Vertex& vertex) {
591591
}
592592
exp.Next();
593593
}
594+
return TopoDS_Vertex();
594595
}
595596

596597
TopoDS_Edge find_next(const TopTools_IndexedMapOfShape& edge_set, const TopTools_IndexedDataMapOfShapeListOfShape& vertex_to_edges, const TopoDS_Vertex& current, const TopoDS_Edge& previous_edge) {
@@ -603,6 +604,7 @@ TopoDS_Edge find_next(const TopTools_IndexedMapOfShape& edge_set, const TopTools
603604
return edge;
604605
}
605606
}
607+
return TopoDS_Edge();
606608
}
607609

608610
bool IfcGeom::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) {
@@ -653,7 +655,16 @@ bool IfcGeom::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) {
653655
return false;
654656
}
655657
TopoDS_Vertex other = find_other(edge, current);
656-
w.Add(edge);
658+
if (other.IsNull()) {
659+
// Dealing with a conical edge probably, for some reason
660+
// this works better than adding the edge directly.
661+
double u1, u2;
662+
Handle(Geom_Curve) crv = BRep_Tool::Curve(edge, u1, u2);
663+
w.Add(BRepBuilderAPI_MakeEdge(crv, u1, u2));
664+
break;
665+
} else {
666+
w.Add(edge);
667+
}
657668
// See if the starting point of this loop has been reached. Note that
658669
// additional wires after this one potentially will be created.
659670
if (other.IsSame(first)) {

src/ifcgeom/IfcGeomShapes.cpp

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -562,57 +562,73 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangularTrimmedSurface::ptr l, Topo
562562
}
563563

564564
bool 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

Comments
 (0)