IfcSurfaceCurveSweptAreaSolid improvements

This commit is contained in:
Thomas Krijnen
2014-03-31 14:00:02 +00:00
parent aae576aae2
commit 3e7c0cfd55
2 changed files with 60 additions and 33 deletions
+12 -1
View File
@@ -589,6 +589,7 @@ TopoDS_Vertex find_other(const TopoDS_Edge& edge, const TopoDS_Vertex& vertex) {
}
exp.Next();
}
return TopoDS_Vertex();
}
TopoDS_Edge find_next(const TopTools_IndexedMapOfShape& edge_set, const TopTools_IndexedDataMapOfShapeListOfShape& vertex_to_edges, const TopoDS_Vertex& current, const TopoDS_Edge& previous_edge) {
@@ -601,6 +602,7 @@ TopoDS_Edge find_next(const TopTools_IndexedMapOfShape& edge_set, const TopTools
return edge;
}
}
return TopoDS_Edge();
}
bool IfcGeom::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) {
@@ -651,7 +653,16 @@ bool IfcGeom::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) {
return false;
}
TopoDS_Vertex other = find_other(edge, current);
w.Add(edge);
if (other.IsNull()) {
// Dealing with a conical edge probably, for some reason
// this works better than adding the edge directly.
double u1, u2;
Handle(Geom_Curve) crv = BRep_Tool::Curve(edge, u1, u2);
w.Add(BRepBuilderAPI_MakeEdge(crv, u1, u2));
break;
} else {
w.Add(edge);
}
// See if the starting point of this loop has been reached. Note that
// additional wires after this one potentially will be created.
if (other.IsSame(first)) {
+48 -32
View File
@@ -562,57 +562,73 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangularTrimmedSurface::ptr l, Topo
}
bool IfcGeom::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid::ptr l, TopoDS_Shape& shape) {
gp_Trsf trsf, axis, position;
gp_Trsf directrix, position;
TopoDS_Shape face;
TopoDS_Wire wire, section;
if (!IfcGeom::convert_face(l->SweptArea(), face)) {
return false;
}
if (!IfcGeom::convert_wire(l->Directrix(), wire)) {
return false;
}
axis.SetTransformation(gp_Ax3(gp::Origin(), gp::DX(), -gp::DZ()));
IfcGeom::convert(l->Position(), position);
if (!l->ReferenceSurface()->is(IfcSchema::Type::IfcPlane)) {
// Not implemented
Logger::Message(Logger::LOG_WARNING, "Reference surface not supported", l->ReferenceSurface()->entity);
return false;
}
if (!IfcGeom::convert(l->Position(), position) ||
!IfcGeom::convert_face(l->SweptArea(), face) ||
!IfcGeom::convert_wire(l->Directrix(), wire) ) {
return false;
}
gp_Pln pln;
gp_Pnt directrix_origin;
gp_Vec directrix_tangent;
bool directrix_on_plane = true;
IfcGeom::convert((IfcSchema::IfcPlane*) l->ReferenceSurface(), pln);
trsf.SetTransformation(pln.Position());
trsf.Invert();
trsf.Multiply(axis);
// As per Informal propositions 2: The Directrix shall lie on the ReferenceSurface.
// This is not always the case with the test files in the repository. I am not sure
// how to deal with this and whether my interpretation of the propositions is
// correct. However, if it has been asserted that the vertices of the directrix do
// not conform to the ReferenceSurface, the ReferenceSurface is ignored.
{
for (TopExp_Explorer exp(wire, TopAbs_VERTEX); exp.More(); exp.Next()) {
if (pln.Distance(BRep_Tool::Pnt(TopoDS::Vertex(exp.Current()))) > ALMOST_ZERO) {
directrix_on_plane = false;
Logger::Message(Logger::LOG_WARNING, "The Directrix does not lie on the ReferenceSurface", l->entity);
break;
}
}
}
{
TopExp_Explorer exp(wire, TopAbs_EDGE);
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
double u0, u1;
Handle(Geom_Curve) crv = BRep_Tool::Curve(edge, u0, u1);
crv->D1(u0, directrix_origin, directrix_tangent);
}
if (pln.Axis().Direction().IsNormal(directrix_tangent, Precision::Approximation()) && directrix_on_plane) {
directrix.SetTransformation(gp_Ax3(directrix_origin, directrix_tangent, pln.Axis().Direction()), gp::XOY());
} else {
directrix.SetTransformation(gp_Ax3(directrix_origin, directrix_tangent), gp::XOY());
}
face = BRepBuilderAPI_Transform(face, directrix);
// NB: Note that StartParam and EndParam param are ignored and the assumption is
// made that the parametric range over which to be swept matches the IfcCurve in
// its entirety.
BRepOffsetAPI_MakePipeShell builder(wire);
face = BRepBuilderAPI_Transform(face, trsf);
TopExp_Explorer exp(face, TopAbs_WIRE);
section = TopoDS::Wire(exp.Current());
{ TopExp_Explorer exp(face, TopAbs_WIRE);
section = TopoDS::Wire(exp.Current()); }
builder.Add(section);
builder.SetTransitionMode(BRepBuilderAPI_RightCorner);
builder.Build();
shape = builder.Shape();
bool succeeded = false;
try {
succeeded = IfcGeom::fill_nonmanifold_wires_with_planar_faces(shape);
} catch(...) {}
if (!succeeded) {
Logger::Message(Logger::LOG_WARNING, "Failed to cap solid for:", l->entity);
if (directrix_on_plane) {
builder.SetMode(pln.Axis().Direction());
}
builder.Build();
builder.MakeSolid();
shape = builder.Shape();
shape.Move(position);
return true;