#1269 implement SurfaceCurveSweptAreaSolid with non-planar ref

This commit is contained in:
Thomas Krijnen
2021-01-22 16:32:51 +01:00
parent 2f2611e0cb
commit 923771f448
+53 -18
View File
@@ -91,6 +91,7 @@
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <ShapeFix_Edge.hxx>
#include <ShapeFix_Shape.hxx>
#include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeFix_Solid.hxx>
@@ -104,6 +105,8 @@
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <ShapeAnalysis_Surface.hxx>
#include "../ifcgeom/IfcGeom.h"
#include <memory>
@@ -1024,11 +1027,22 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangularTrimmedSurface* l,
bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, TopoDS_Shape& shape) {
gp_Trsf directrix;
TopoDS_Shape face;
TopoDS_Face surface_face;
TopoDS_Wire wire, section;
if (!l->ReferenceSurface()->declaration().is(IfcSchema::IfcPlane::Class())) {
Logger::Message(Logger::LOG_WARNING, "Reference surface not supported", l->ReferenceSurface());
return false;
const bool is_plane = l->ReferenceSurface()->declaration().is(IfcSchema::IfcPlane::Class());
if (!is_plane) {
TopoDS_Shape surface_shell;
if (!convert_shape(l->ReferenceSurface(), surface_shell)) {
return false;
}
if (count(surface_shell, TopAbs_FACE) != 1) {
return false;
}
std::ofstream ofs("debug.txt");
BRepTools::Dump(surface_shell, ofs);
surface_face = TopoDS::Face(TopExp_Explorer(surface_shell, TopAbs_FACE).Current());
}
gp_Trsf trsf;
@@ -1048,25 +1062,28 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l,
gp_Pln pln;
gp_Pnt directrix_origin;
gp_Vec directrix_tangent;
bool directrix_on_plane = true;
IfcGeom::Kernel::convert((IfcSchema::IfcPlane*) l->ReferenceSurface(), pln);
bool directrix_on_plane = is_plane;
// 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);
break;
if (is_plane) {
IfcGeom::Kernel::convert((IfcSchema::IfcPlane*) l->ReferenceSurface(), pln);
// 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);
break;
}
}
}
}
{
{
TopExp_Explorer exp(wire, TopAbs_EDGE);
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
double u0, u1;
@@ -1074,13 +1091,29 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l,
crv->D1(u0, directrix_origin, directrix_tangent);
}
if (pln.Axis().Direction().IsNormal(directrix_tangent, Precision::Approximation()) && directrix_on_plane) {
if (is_plane && 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 if (!is_plane) {
ShapeAnalysis_Surface sas(BRep_Tool::Surface(surface_face));
auto pnt2d = sas.ValueOfUV(directrix_origin, getValue(GV_PRECISION) * 10.);
BRepGProp_Face prop(surface_face);
gp_Pnt _;
gp_Vec surface_normal;
prop.Normal(pnt2d.X(), pnt2d.Y(), _, surface_normal);
directrix.SetTransformation(gp_Ax3(directrix_origin, directrix_tangent, surface_normal), gp::XOY());
} else {
directrix.SetTransformation(gp_Ax3(directrix_origin, directrix_tangent), gp::XOY());
}
face = BRepBuilderAPI_Transform(face, directrix);
if (!is_plane) {
TopExp_Explorer exp(wire, TopAbs_EDGE);
for (; exp.More(); exp.Next()) {
ShapeFix_Edge sfe;
sfe.FixAddPCurve(TopoDS::Edge(exp.Current()), surface_face, false, getValue(GV_PRECISION));
}
}
// 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.
@@ -1093,6 +1126,8 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l,
builder.SetTransitionMode(BRepBuilderAPI_RightCorner);
if (directrix_on_plane) {
builder.SetMode(pln.Axis().Direction());
} else if (!is_plane) {
builder.SetMode(surface_face);
}
builder.Build();
builder.MakeSolid();