mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Work-around for tiny radii sweeps #5474
This commit is contained in:
@@ -128,7 +128,7 @@ public:
|
||||
const IfcGeom::ConversionResults& entity_shapes, const ifcopenshell::geometry::taxonomy::matrix4& entity_trsf, IfcGeom::ConversionResults& cut_shapes);
|
||||
virtual bool unify_shapes(const IfcGeom::ConversionResults& input, IfcGeom::ConversionResults& output);
|
||||
|
||||
typedef boost::variant<Handle(Geom_Curve), TopoDS_Wire> curve_creation_visitor_result_type;
|
||||
typedef boost::variant<boost::blank, Handle(Geom_Curve), TopoDS_Wire> curve_creation_visitor_result_type;
|
||||
curve_creation_visitor_result_type convert_curve(const ifcopenshell::geometry::taxonomy::ptr);
|
||||
Handle(Geom_Surface) convert_surface(const ifcopenshell::geometry::taxonomy::ptr);
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace {
|
||||
// It's a bit more convenient to use high level BRepPrimAPI calls that operate on
|
||||
// topology. On a single edge that will create a Geom_TrimmedCurve for us.
|
||||
auto crv_or_wire = kernel->convert_curve(i);
|
||||
if (crv_or_wire.which() == 1) {
|
||||
if (crv_or_wire.which() == 2) {
|
||||
const auto& w = boost::get<TopoDS_Wire>(crv_or_wire);
|
||||
return w;
|
||||
} else {
|
||||
@@ -163,8 +163,10 @@ namespace {
|
||||
// @todo unify with trimmed curve handling
|
||||
auto crv_or_wire = kernel->convert_curve(i);
|
||||
if (crv_or_wire.which() == 0) {
|
||||
throw std::runtime_error("Failed to obtain curve");
|
||||
} else if (crv_or_wire.which() == 1) {
|
||||
return boost::get<Handle(Geom_Curve)>(crv_or_wire);
|
||||
} else {
|
||||
} else if (crv_or_wire.which() == 2) {
|
||||
// @todo
|
||||
const double precision_ = 1.e-5;
|
||||
Logger::Warning("Approximating BasisCurve due to possible discontinuities", i->instance);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <TopTools_ListOfShape.hxx>
|
||||
#include <BRepTools_WireExplorer.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
|
||||
#include <Standard_Version.hxx>
|
||||
#if OCC_VERSION_HEX < 0x70600
|
||||
@@ -98,7 +99,7 @@ namespace {
|
||||
if (!kernel->convert(l, wire)) {
|
||||
throw std::runtime_error("Failed to convert loop to wire");
|
||||
}
|
||||
return result;
|
||||
return result = wire;
|
||||
}
|
||||
|
||||
OpenCascadeKernel::curve_creation_visitor_result_type operator()(const taxonomy::edge::ptr& e) {
|
||||
@@ -119,6 +120,9 @@ namespace {
|
||||
auto crv_or_wire = kernel->convert_curve(e_basis);
|
||||
Handle(Geom_Curve) curve;
|
||||
if (crv_or_wire.which() == 0) {
|
||||
// raise exception
|
||||
return result;
|
||||
} else if (crv_or_wire.which() == 1) {
|
||||
curve = boost::get<Handle(Geom_Curve)>(crv_or_wire);
|
||||
} else {
|
||||
// @todo
|
||||
@@ -355,6 +359,17 @@ bool OpenCascadeKernel::convert(const taxonomy::loop::ptr loop, TopoDS_Wire& wir
|
||||
wire = mw.Wire();
|
||||
}
|
||||
|
||||
if (loop->matrix && !loop->matrix->is_identity()) {
|
||||
const auto& m = loop->matrix->ccomponents();
|
||||
gp_Trsf tr;
|
||||
tr.SetValues(
|
||||
m(0, 0), m(0, 1), m(0, 2), m(0, 3),
|
||||
m(1, 0), m(1, 1), m(1, 2), m(1, 3),
|
||||
m(2, 0), m(2, 1), m(2, 2), m(2, 3)
|
||||
);
|
||||
wire = TopoDS::Wire(BRepBuilderAPI_Transform(wire, tr).Shape());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,9 @@ using namespace IfcGeom::util;
|
||||
|
||||
bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, TopoDS_Shape& result) {
|
||||
auto w = convert_curve(scs->curve);
|
||||
if (w.which() == 0) {
|
||||
if (w.which() != 2) {
|
||||
Logger::Error("Unsupported directrix");
|
||||
return false;
|
||||
}
|
||||
TopoDS_Shape face;
|
||||
convert(taxonomy::cast<taxonomy::face>(scs->basis), face);
|
||||
@@ -136,6 +137,9 @@ bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, Topo
|
||||
builder.SetMode(surface_face);
|
||||
}
|
||||
builder.Build();
|
||||
if (!builder.IsDone()) {
|
||||
return false;
|
||||
}
|
||||
builder.MakeSolid();
|
||||
result = builder.Shape();
|
||||
|
||||
@@ -144,12 +148,45 @@ bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, Topo
|
||||
|
||||
bool OpenCascadeKernel::convert_impl(const taxonomy::sweep_along_curve::ptr scs, IfcGeom::ConversionResults& results) {
|
||||
TopoDS_Shape shape;
|
||||
// For tiny radii occt will fail building the sweep, in which case we enlarge the inputs to occt, and add a scale matrix to the output
|
||||
bool enlarged = false;
|
||||
static double enlarge_factor = 1000.;
|
||||
if (scs->basis->kind() == taxonomy::FACE) {
|
||||
auto w = std::static_pointer_cast<taxonomy::face>(scs->basis)->children[0];
|
||||
if (w->children.size() == 1 && w->children[0]->basis && w->children[0]->basis->kind() == taxonomy::CIRCLE) {
|
||||
auto circ = std::static_pointer_cast<taxonomy::circle>(w->children[0]->basis);
|
||||
enlarged = circ->radius < 1.e-4;
|
||||
if (enlarged) {
|
||||
// @todo immutability
|
||||
circ->radius *= enlarge_factor;
|
||||
auto crv = std::static_pointer_cast<taxonomy::geom_item>(scs->curve);
|
||||
if (crv->matrix) {
|
||||
crv->matrix = taxonomy::make<taxonomy::matrix4>(
|
||||
Eigen::Scaling(enlarge_factor) *
|
||||
crv->matrix->ccomponents()
|
||||
);
|
||||
} else {
|
||||
crv->matrix = taxonomy::make<taxonomy::matrix4>();
|
||||
crv->matrix->components().topLeftCorner<3, 3>() = Eigen::Scaling(enlarge_factor, enlarge_factor, enlarge_factor).toDenseMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!convert(scs, shape)) {
|
||||
return false;
|
||||
}
|
||||
taxonomy::matrix4::ptr m;
|
||||
if (enlarged) {
|
||||
m = taxonomy::make<taxonomy::matrix4>(
|
||||
Eigen::Scaling(1. / enlarge_factor) *
|
||||
scs->matrix->ccomponents()
|
||||
);
|
||||
} else {
|
||||
m = scs->matrix;
|
||||
}
|
||||
results.emplace_back(ConversionResult(
|
||||
scs->instance->as<IfcUtil::IfcBaseEntity>()->id(),
|
||||
scs->matrix,
|
||||
m,
|
||||
new OpenCascadeShape(shape),
|
||||
scs->surface_style
|
||||
));
|
||||
|
||||
Reference in New Issue
Block a user