mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 22:50:56 +00:00
IfcSurfaceCurveSweptAreaSolid improvements
This commit is contained in:
@@ -589,6 +589,7 @@ TopoDS_Vertex find_other(const TopoDS_Edge& edge, const TopoDS_Vertex& vertex) {
|
|||||||
}
|
}
|
||||||
exp.Next();
|
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) {
|
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 edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return TopoDS_Edge();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IfcGeom::fill_nonmanifold_wires_with_planar_faces(TopoDS_Shape& shape) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
TopoDS_Vertex other = find_other(edge, current);
|
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
|
// See if the starting point of this loop has been reached. Note that
|
||||||
// additional wires after this one potentially will be created.
|
// additional wires after this one potentially will be created.
|
||||||
if (other.IsSame(first)) {
|
if (other.IsSame(first)) {
|
||||||
|
|||||||
@@ -562,57 +562,73 @@ bool IfcGeom::convert(const IfcSchema::IfcRectangularTrimmedSurface::ptr l, Topo
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IfcGeom::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid::ptr l, TopoDS_Shape& shape) {
|
bool IfcGeom::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid::ptr l, TopoDS_Shape& shape) {
|
||||||
gp_Trsf trsf, axis, position;
|
gp_Trsf directrix, position;
|
||||||
TopoDS_Shape face;
|
TopoDS_Shape face;
|
||||||
TopoDS_Wire wire, section;
|
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)) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
gp_Pln pln;
|
gp_Pln pln;
|
||||||
|
gp_Pnt directrix_origin;
|
||||||
|
gp_Vec directrix_tangent;
|
||||||
|
bool directrix_on_plane = true;
|
||||||
IfcGeom::convert((IfcSchema::IfcPlane*) l->ReferenceSurface(), pln);
|
IfcGeom::convert((IfcSchema::IfcPlane*) l->ReferenceSurface(), pln);
|
||||||
|
|
||||||
trsf.SetTransformation(pln.Position());
|
// As per Informal propositions 2: The Directrix shall lie on the ReferenceSurface.
|
||||||
trsf.Invert();
|
// This is not always the case with the test files in the repository. I am not sure
|
||||||
trsf.Multiply(axis);
|
// 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
|
// 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
|
// made that the parametric range over which to be swept matches the IfcCurve in
|
||||||
// its entirety.
|
// its entirety.
|
||||||
BRepOffsetAPI_MakePipeShell builder(wire);
|
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.Add(section);
|
||||||
builder.SetTransitionMode(BRepBuilderAPI_RightCorner);
|
builder.SetTransitionMode(BRepBuilderAPI_RightCorner);
|
||||||
builder.Build();
|
if (directrix_on_plane) {
|
||||||
|
builder.SetMode(pln.Axis().Direction());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
builder.Build();
|
||||||
|
builder.MakeSolid();
|
||||||
|
shape = builder.Shape();
|
||||||
shape.Move(position);
|
shape.Move(position);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user