mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 18:16:40 +00:00
#1269 implement SurfaceCurveSweptAreaSolid with non-planar ref
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user