#816 Use more than one cycle of self intersections in IfcArbitraryClosedProfileDef

This commit is contained in:
Thomas Krijnen
2020-08-25 13:51:59 +02:00
parent c15fdc7fa9
commit 5c20e7b62a
3 changed files with 73 additions and 2 deletions
+1
View File
@@ -289,6 +289,7 @@ public:
void set_rotation(const std::array<double, 4>& rotation);
bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face);
bool convert_wire_to_faces(const TopoDS_Wire& wire, TopoDS_Compound& face);
bool convert_curve_to_wire(const Handle(Geom_Curve)& curve, TopoDS_Wire& wire);
bool convert_shapes(const IfcUtil::IfcBaseClass* L, IfcRepresentationShapeItems& result);
IfcGeom::ShapeType shape_type(const IfcUtil::IfcBaseClass* L);
+2 -2
View File
@@ -447,8 +447,8 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcArbitraryClosedProfileDef* l,
assert_closed_wire(wire);
TopoDS_Face f;
bool success = convert_wire_to_face(wire, f);
TopoDS_Compound f;
bool success = convert_wire_to_faces(wire, f);
if (success) {
face = f;
}
+70
View File
@@ -1139,6 +1139,76 @@ bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& w, TopoDS_Face& fa
return true;
}
bool IfcGeom::Kernel::convert_wire_to_faces(const TopoDS_Wire& w, TopoDS_Compound& faces) {
bool is_2d = true;
TopExp_Explorer exp(w, TopAbs_EDGE);
for (; exp.More(); exp.Next()) {
double a, b;
Handle(Geom_Curve) crv = BRep_Tool::Curve(TopoDS::Edge(exp.Current()), a, b);
if (crv->DynamicType() != STANDARD_TYPE(Geom_Line)) {
is_2d = false;
break;
}
Handle(Geom_Line) line = Handle(Geom_Line)::DownCast(crv);
if (line->Lin().Direction().Z() > ALMOST_ZERO) {
is_2d = false;
break;
}
}
TopTools_ListOfShape results;
if (wire_intersections(w, results)) {
Logger::Warning("Self-intersections with " + boost::lexical_cast<std::string>(results.Extent()) + " cycles detected");
} else {
results.Clear();
results.Append(w);
}
TopoDS_Compound C;
BRep_Builder B;
B.MakeCompound(faces);
std::list<std::pair<double, TopoDS_Face>> face_list;
double max_area = 0.;
TopTools_ListIteratorOfListOfShape it(results);
for (; it.More(); it.Next()) {
const TopoDS_Wire& wire = TopoDS::Wire(it.Value());
if (!is_2d) {
// For 2d wires (e.g. profiles) a higher tolerance for plane fitting is never required.
ShapeFix_ShapeTolerance FTol;
FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE);
}
BRepBuilderAPI_MakeFace mf(wire, false);
BRepBuilderAPI_FaceError er = mf.Error();
if (er != BRepBuilderAPI_FaceDone) {
Logger::Error("Failed to create face.");
continue;
}
TopoDS_Face face = mf.Face();
const double m = face_area(face);
face_list.push_back({ m, face });
if (m > max_area) {
max_area = m;
}
}
for (auto& p : face_list) {
if (p.first >= max_area / 10.) {
B.Add(faces, p.second);
} else {
Logger::Warning("Ignoring self-intersection loop with area " + boost::lexical_cast<std::string>(p.first));
}
}
return true;
}
void IfcGeom::Kernel::assert_closed_wire(TopoDS_Wire& wire) {
if (wire.Closed() == 0) {
TopoDS_Vertex v0, v1;