More robust processing of IfcPolyline and IfcPolyLoop

This commit is contained in:
Thomas Krijnen
2014-07-28 20:03:53 +00:00
parent cf2e82e8f5
commit e77216d41c
4 changed files with 103 additions and 41 deletions
+2 -1
View File
@@ -36,6 +36,7 @@
#include <TopoDS_Face.hxx> #include <TopoDS_Face.hxx>
#include <Geom_Curve.hxx> #include <Geom_Curve.hxx>
#include <gp_Pln.hxx> #include <gp_Pln.hxx>
#include <TColgp_SequenceOfPnt.hxx>
#include "../ifcparse/IfcParse.h" #include "../ifcparse/IfcParse.h"
#include "../ifcparse/IfcUtil.h" #include "../ifcparse/IfcUtil.h"
@@ -106,7 +107,7 @@ namespace IfcGeom {
double GetValue(GeomValue var); double GetValue(GeomValue var);
bool fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape); bool fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape);
IfcSchema::IfcProductDefinitionShape* tesselate(TopoDS_Shape& shape, double deflection, IfcEntityList::ptr es); IfcSchema::IfcProductDefinitionShape* tesselate(TopoDS_Shape& shape, double deflection, IfcEntityList::ptr es);
void remove_redundant_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.);
namespace Cache { namespace Cache {
+23
View File
@@ -793,3 +793,26 @@ bool IfcGeom::flatten_shape_list(const IfcGeom::IfcRepresentationShapeItems& sha
return !result.IsNull(); return !result.IsNull();
} }
void IfcGeom::remove_redundant_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol) {
if (tol <= 0.) tol = GetValue(GV_POINT_EQUALITY_TOLERANCE);
tol *= tol;
while (true) {
bool removed = false;
int n = polygon.Length() - (closed ? 0 : 1);
for (int i = 1; i <= n; ++i) {
// wrap around to the first point in case of a closed loop
int j = (i % polygon.Length()) + 1;
double dist = polygon.Value(i).SquareDistance(polygon.Value(j));
if (dist < tol) {
// do not remove the first or last point to
// maintain connectivity with other wires
if ((closed && j == 1) || (!closed && j == n)) polygon.Remove(i);
else polygon.Remove(j);
removed = true;
break;
}
}
if (!removed) break;
}
}
+17 -5
View File
@@ -393,7 +393,11 @@ bool IfcGeom::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& sha
builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) { for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) {
TopoDS_Face face; TopoDS_Face face;
if ( IfcGeom::convert_face(*it,face) && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) { bool converted_face = false;
try {
converted_face = IfcGeom::convert_face(*it,face);
} catch (...) {}
if ( converted_face && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) {
builder.Add(face); builder.Add(face);
facesAdded = true; facesAdded = true;
} else { } else {
@@ -401,9 +405,11 @@ bool IfcGeom::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& sha
} }
} }
if ( ! facesAdded ) return false; if ( ! facesAdded ) return false;
builder.Perform(); try {
shape = builder.SewedShape(); builder.Perform();
valid_shell = BRepCheck_Analyzer(shape).IsValid(); shape = builder.SewedShape();
valid_shell = BRepCheck_Analyzer(shape).IsValid();
} catch(...) {}
if (valid_shell) { if (valid_shell) {
try { try {
ShapeFix_Solid solid; ShapeFix_Solid solid;
@@ -416,6 +422,8 @@ bool IfcGeom::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& sha
} catch (...) {} } catch (...) {}
} }
} catch(...) {} } catch(...) {}
} else {
Logger::Message(Logger::LOG_WARNING,"Failed to sew faceset:",l->entity);
} }
} }
if (!valid_shell) { if (!valid_shell) {
@@ -424,7 +432,11 @@ bool IfcGeom::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& sha
builder.MakeCompound(compound); builder.MakeCompound(compound);
for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) { for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) {
TopoDS_Face face; TopoDS_Face face;
if ( IfcGeom::convert_face(*it,face) && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) { bool converted_face = false;
try {
converted_face = IfcGeom::convert_face(*it,face);
} catch (...) {}
if ( converted_face && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) {
builder.Add(compound,face); builder.Add(compound,face);
facesAdded = true; facesAdded = true;
} else { } else {
+58 -32
View File
@@ -47,15 +47,18 @@
#include <TColgp_Array1OfPnt2d.hxx> #include <TColgp_Array1OfPnt2d.hxx>
#include <TColStd_Array1OfReal.hxx> #include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx> #include <TColStd_Array1OfInteger.hxx>
#include <Geom_Line.hxx> #include <Geom_Line.hxx>
#include <Geom_Circle.hxx> #include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx> #include <Geom_Ellipse.hxx>
#include <Geom_TrimmedCurve.hxx> #include <Geom_TrimmedCurve.hxx>
#include <BRepOffsetAPI_Sewing.hxx> #include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeFace.hxx> #include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx> #include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx> #include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeShell.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx> #include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx> #include <BRepBuilderAPI_MakeVertex.hxx>
@@ -63,23 +66,21 @@
#include <TopoDS_Wire.hxx> #include <TopoDS_Wire.hxx>
#include <TopoDS_Face.hxx> #include <TopoDS_Face.hxx>
#include <TopExp_Explorer.hxx> #include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
#include <TopTools_ListOfShape.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepBuilderAPI_MakeShell.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepPrimAPI_MakeHalfSpace.hxx>
#include <BRepAlgoAPI_Cut.hxx> #include <BRepAlgoAPI_Cut.hxx>
#include <BRepOffsetAPI_Sewing.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepPrimAPI_MakeHalfSpace.hxx>
#include <BRepFilletAPI_MakeFillet2d.hxx>
#include <BRep_Tool.hxx>
#include <ShapeFix_Shape.hxx> #include <ShapeFix_Shape.hxx>
#include <ShapeFix_ShapeTolerance.hxx> #include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeFix_Solid.hxx> #include <ShapeFix_Solid.hxx>
#include <BRepFilletAPI_MakeFillet2d.hxx>
#include <TopLoc_Location.hxx>
#include <BRep_Tool.hxx>
#include "../ifcgeom/IfcGeom.h" #include "../ifcgeom/IfcGeom.h"
bool IfcGeom::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) { bool IfcGeom::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) {
@@ -274,13 +275,20 @@ bool IfcGeom::convert(const IfcSchema::IfcTrimmedCurve* l, TopoDS_Wire& wire) {
bool IfcGeom::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& result) { bool IfcGeom::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& result) {
IfcSchema::IfcCartesianPoint::list::ptr points = l->Points(); IfcSchema::IfcCartesianPoint::list::ptr points = l->Points();
BRepBuilderAPI_MakeWire w; // Parse and store the points in a sequence
gp_Pnt P1;gp_Pnt P2; TColgp_SequenceOfPnt polygon;
for( IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it ) { for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) {
IfcGeom::convert(*it,P2); gp_Pnt pnt;
if ( it != points->begin() && ( !P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) ) IfcGeom::convert(*it, pnt);
w.Add(BRepBuilderAPI_MakeEdge(P1,P2)); polygon.Append(pnt);
P1 = P2; }
// Remove points that are too close to one another
remove_redundant_points_from_loop(polygon, false);
BRepBuilderAPI_MakePolygon w;
for (int i = 1; i <= polygon.Length(); ++i) {
w.Add(polygon.Value(i));
} }
result = w.Wire(); result = w.Wire();
@@ -290,22 +298,40 @@ bool IfcGeom::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& result) {
bool IfcGeom::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& result) { bool IfcGeom::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& result) {
IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon(); IfcSchema::IfcCartesianPoint::list::ptr points = l->Polygon();
BRepBuilderAPI_MakeWire w; // Parse and store the points in a sequence
gp_Pnt P1;gp_Pnt P2;gp_Pnt F; TColgp_SequenceOfPnt polygon;
int count = 0; for(IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it) {
for( IfcSchema::IfcCartesianPoint::list::it it = points->begin(); it != points->end(); ++ it ) { gp_Pnt pnt;
IfcGeom::convert(*it,P2); IfcGeom::convert(*it, pnt);
if ( it != points->begin() && ( !P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) ) { polygon.Append(pnt);
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
count ++;
} else if ( ! count ) F = P2;
P1 = P2;
} }
if ( !P1.IsEqual(F,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) {
w.Add(BRepBuilderAPI_MakeEdge(P1,F)); // A loop should consist of at least three vertices
count ++; int original_count = polygon.Length();
if (original_count < 3) {
Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity);
return false;
} }
if ( count < 3 ) return false;
// Remove points that are too close to one another
remove_redundant_points_from_loop(polygon, true);
int count = polygon.Length();
if (original_count - count != 0) {
std::stringstream ss; ss << (original_count - count) << " edges removed for:";
Logger::Message(Logger::LOG_WARNING, ss.str(), l->entity);
}
if (count < 3) {
Logger::Message(Logger::LOG_ERROR, "Not enough edges for:", l->entity);
return false;
}
BRepBuilderAPI_MakePolygon w;
for (int i = 1; i <= polygon.Length(); ++i) {
w.Add(polygon.Value(i));
}
w.Close();
result = w.Wire(); result = w.Wire();
return true; return true;