Skip to content

Commit 36a0a0f

Browse files
committed
Work-around for tiny radii sweeps #5474
1 parent 89b1f9c commit 36a0a0f

4 files changed

Lines changed: 60 additions & 6 deletions

File tree

src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class IFC_GEOM_API OpenCascadeKernel : public ifcopenshell::geometry::kernels::A
128128
const IfcGeom::ConversionResults& entity_shapes, const ifcopenshell::geometry::taxonomy::matrix4& entity_trsf, IfcGeom::ConversionResults& cut_shapes);
129129
virtual bool unify_shapes(const IfcGeom::ConversionResults& input, IfcGeom::ConversionResults& output);
130130

131-
typedef boost::variant<Handle(Geom_Curve), TopoDS_Wire> curve_creation_visitor_result_type;
131+
typedef boost::variant<boost::blank, Handle(Geom_Curve), TopoDS_Wire> curve_creation_visitor_result_type;
132132
curve_creation_visitor_result_type convert_curve(const ifcopenshell::geometry::taxonomy::ptr);
133133
Handle(Geom_Surface) convert_surface(const ifcopenshell::geometry::taxonomy::ptr);
134134

src/ifcgeom/kernels/opencascade/face.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ namespace {
151151
// It's a bit more convenient to use high level BRepPrimAPI calls that operate on
152152
// topology. On a single edge that will create a Geom_TrimmedCurve for us.
153153
auto crv_or_wire = kernel->convert_curve(i);
154-
if (crv_or_wire.which() == 1) {
154+
if (crv_or_wire.which() == 2) {
155155
const auto& w = boost::get<TopoDS_Wire>(crv_or_wire);
156156
return w;
157157
} else {
@@ -163,8 +163,10 @@ namespace {
163163
// @todo unify with trimmed curve handling
164164
auto crv_or_wire = kernel->convert_curve(i);
165165
if (crv_or_wire.which() == 0) {
166+
throw std::runtime_error("Failed to obtain curve");
167+
} else if (crv_or_wire.which() == 1) {
166168
return boost::get<Handle(Geom_Curve)>(crv_or_wire);
167-
} else {
169+
} else if (crv_or_wire.which() == 2) {
168170
// @todo
169171
const double precision_ = 1.e-5;
170172
Logger::Warning("Approximating BasisCurve due to possible discontinuities", i->instance);

src/ifcgeom/kernels/opencascade/loop.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <BRep_Tool.hxx>
1919
#include <TopTools_ListOfShape.hxx>
2020
#include <BRepTools_WireExplorer.hxx>
21+
#include <BRepBuilderAPI_Transform.hxx>
2122

2223
#include <Standard_Version.hxx>
2324
#if OCC_VERSION_HEX < 0x70600
@@ -98,7 +99,7 @@ namespace {
9899
if (!kernel->convert(l, wire)) {
99100
throw std::runtime_error("Failed to convert loop to wire");
100101
}
101-
return result;
102+
return result = wire;
102103
}
103104

104105
OpenCascadeKernel::curve_creation_visitor_result_type operator()(const taxonomy::edge::ptr& e) {
@@ -119,6 +120,9 @@ namespace {
119120
auto crv_or_wire = kernel->convert_curve(e_basis);
120121
Handle(Geom_Curve) curve;
121122
if (crv_or_wire.which() == 0) {
123+
// raise exception
124+
return result;
125+
} else if (crv_or_wire.which() == 1) {
122126
curve = boost::get<Handle(Geom_Curve)>(crv_or_wire);
123127
} else {
124128
// @todo
@@ -355,6 +359,17 @@ bool OpenCascadeKernel::convert(const taxonomy::loop::ptr loop, TopoDS_Wire& wir
355359
wire = mw.Wire();
356360
}
357361

362+
if (loop->matrix && !loop->matrix->is_identity()) {
363+
const auto& m = loop->matrix->ccomponents();
364+
gp_Trsf tr;
365+
tr.SetValues(
366+
m(0, 0), m(0, 1), m(0, 2), m(0, 3),
367+
m(1, 0), m(1, 1), m(1, 2), m(1, 3),
368+
m(2, 0), m(2, 1), m(2, 2), m(2, 3)
369+
);
370+
wire = TopoDS::Wire(BRepBuilderAPI_Transform(wire, tr).Shape());
371+
}
372+
358373
return true;
359374
}
360375

src/ifcgeom/kernels/opencascade/sweep_along_curve.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ using namespace IfcGeom::util;
3434

3535
bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, TopoDS_Shape& result) {
3636
auto w = convert_curve(scs->curve);
37-
if (w.which() == 0) {
37+
if (w.which() != 2) {
3838
Logger::Error("Unsupported directrix");
39+
return false;
3940
}
4041
TopoDS_Shape face;
4142
convert(taxonomy::cast<taxonomy::face>(scs->basis), face);
@@ -136,6 +137,9 @@ bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, Topo
136137
builder.SetMode(surface_face);
137138
}
138139
builder.Build();
140+
if (!builder.IsDone()) {
141+
return false;
142+
}
139143
builder.MakeSolid();
140144
result = builder.Shape();
141145

@@ -144,12 +148,45 @@ bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, Topo
144148

145149
bool OpenCascadeKernel::convert_impl(const taxonomy::sweep_along_curve::ptr scs, IfcGeom::ConversionResults& results) {
146150
TopoDS_Shape shape;
151+
// 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
152+
bool enlarged = false;
153+
static double enlarge_factor = 1000.;
154+
if (scs->basis->kind() == taxonomy::FACE) {
155+
auto w = std::static_pointer_cast<taxonomy::face>(scs->basis)->children[0];
156+
if (w->children.size() == 1 && w->children[0]->basis && w->children[0]->basis->kind() == taxonomy::CIRCLE) {
157+
auto circ = std::static_pointer_cast<taxonomy::circle>(w->children[0]->basis);
158+
enlarged = circ->radius < 1.e-4;
159+
if (enlarged) {
160+
// @todo immutability
161+
circ->radius *= enlarge_factor;
162+
auto crv = std::static_pointer_cast<taxonomy::geom_item>(scs->curve);
163+
if (crv->matrix) {
164+
crv->matrix = taxonomy::make<taxonomy::matrix4>(
165+
Eigen::Scaling(enlarge_factor) *
166+
crv->matrix->ccomponents()
167+
);
168+
} else {
169+
crv->matrix = taxonomy::make<taxonomy::matrix4>();
170+
crv->matrix->components().topLeftCorner<3, 3>() = Eigen::Scaling(enlarge_factor, enlarge_factor, enlarge_factor).toDenseMatrix();
171+
}
172+
}
173+
}
174+
}
147175
if (!convert(scs, shape)) {
148176
return false;
149177
}
178+
taxonomy::matrix4::ptr m;
179+
if (enlarged) {
180+
m = taxonomy::make<taxonomy::matrix4>(
181+
Eigen::Scaling(1. / enlarge_factor) *
182+
scs->matrix->ccomponents()
183+
);
184+
} else {
185+
m = scs->matrix;
186+
}
150187
results.emplace_back(ConversionResult(
151188
scs->instance->as<IfcUtil::IfcBaseEntity>()->id(),
152-
scs->matrix,
189+
m,
153190
new OpenCascadeShape(shape),
154191
scs->surface_style
155192
));

0 commit comments

Comments
 (0)