mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-07 16:31:37 +00:00
Move sweep directrix closer to origin #7408
This commit is contained in:
@@ -84,6 +84,50 @@ namespace {
|
||||
}
|
||||
|
||||
bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, TopoDS_Shape& result) {
|
||||
using namespace ifcopenshell::geometry;
|
||||
|
||||
bool applied_temporary_offset = false;
|
||||
Eigen::Vector3d mean;
|
||||
|
||||
auto curve = scs->curve;
|
||||
|
||||
// Apply temporary offset if the geometry is far away from origin
|
||||
// Re: https://github.com/IfcOpenShell/IfcOpenShell/issues/7408
|
||||
// The norm2 that used as a treshold is actually really small though
|
||||
// is this a coincedence that it solves the problem in this one test case?
|
||||
if (curve->kind() == taxonomy::LOOP && std::dynamic_pointer_cast<taxonomy::loop>(curve)->is_polyhedron()) {
|
||||
Eigen::Vector3d sum = Eigen::Vector3d::Zero();
|
||||
size_t count = 0;
|
||||
|
||||
visit_2<taxonomy::point3, taxonomy::loop>(std::dynamic_pointer_cast<taxonomy::loop>(curve), [&](const taxonomy::point3::ptr& p) {
|
||||
const Eigen::Vector3d& coords = p->ccomponents();
|
||||
|
||||
sum += coords;
|
||||
++count;
|
||||
});
|
||||
|
||||
mean = (count > 0) ? (sum / static_cast<double>(count)).eval() : Eigen::Vector3d::Zero().eval();
|
||||
|
||||
if (mean.norm() > 1.e2) {
|
||||
curve = taxonomy::loop::ptr((taxonomy::loop*)scs->curve->clone_());
|
||||
applied_temporary_offset = true;
|
||||
std::set<taxonomy::point3::ptr> unique_points;
|
||||
for (auto& e : std::dynamic_pointer_cast<taxonomy::loop>(curve)->children) {
|
||||
auto* a = boost::get<taxonomy::point3::ptr>(&e->start);
|
||||
auto* b = boost::get<taxonomy::point3::ptr>(&e->end);
|
||||
if (a) {
|
||||
unique_points.insert(*a);
|
||||
}
|
||||
if (b) {
|
||||
unique_points.insert(*b);
|
||||
}
|
||||
}
|
||||
for (auto& p : unique_points) {
|
||||
p->components() -= mean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto w = convert_curve(scs->curve);
|
||||
if (w.which() != 2) {
|
||||
Logger::Error("Unsupported directrix");
|
||||
@@ -207,13 +251,13 @@ bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, Topo
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (TopExp_Explorer exp(face, TopAbs_WIRE); exp.More(); exp.Next()) {
|
||||
const auto& section = TopoDS::Wire(exp.Current());
|
||||
if (section.IsSame(outer) != i == 0) {
|
||||
if (section.IsSame(outer) != (i == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BRepOffsetAPI_MakePipeShell builder(wire);
|
||||
builder.Add(section);
|
||||
builder.SetTransitionMode(contains_circular_segments(wire) && wire_is_c1_continuous(wire, 1.e-2) ? BRepBuilderAPI_Transformed : BRepBuilderAPI_RightCorner);
|
||||
builder.SetTransitionMode(contains_circular_segments(wire) && wire_is_c1_continuous(wire, 1.e-2) ? BRepBuilderAPI_Transformed : BRepBuilderAPI_RightCorner);
|
||||
if (directrix_on_plane) {
|
||||
builder.SetMode(pln.Axis().Direction());
|
||||
} else if (!is_plane) {
|
||||
@@ -238,8 +282,8 @@ bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, Topo
|
||||
mf1.reset(new BRepBuilderAPI_MakeFace(f1));
|
||||
}
|
||||
|
||||
for (TopExp_Explorer exp(builder.Shape(), TopAbs_FACE); exp.More(); exp.Next()) {
|
||||
BB.Add(comp, exp.Current());
|
||||
for (TopExp_Explorer exp2(builder.Shape(), TopAbs_FACE); exp2.More(); exp2.Next()) {
|
||||
BB.Add(comp, exp2.Current());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,6 +298,12 @@ bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, Topo
|
||||
|
||||
result = BRepBuilderAPI_MakeSolid(comp).Solid();
|
||||
|
||||
if (applied_temporary_offset) {
|
||||
gp_Trsf trsf;
|
||||
trsf.SetTranslation(gp_Vec(-mean.x(), -mean.y(), -mean.z()));
|
||||
result.Move(trsf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+22
-30
@@ -1649,42 +1649,34 @@ typedef item const* ptr;
|
||||
}
|
||||
|
||||
template <typename T, typename U, typename Fn>
|
||||
void visit_2(const typename U::ptr& c, const Fn& fn) {
|
||||
void visit_2(const typename U::ptr& collection, const Fn& fn) {
|
||||
static_assert(std::is_same<T, taxonomy::point3>::value, "@todo Only implemented for point3");
|
||||
for (auto& i : c->children) {
|
||||
for (auto& child : collection->children) {
|
||||
// @todo Sad... now that we have templated collection members,
|
||||
// we can't generally use collection_base anymore as a cast target.
|
||||
if (auto s = taxonomy::dcast<taxonomy::collection>(i)) {
|
||||
visit_2<T, taxonomy::collection>(s, fn);
|
||||
}
|
||||
else if (auto s = taxonomy::dcast<taxonomy::loop>(i)) {
|
||||
visit_2<T, taxonomy::loop>(s, fn);
|
||||
}
|
||||
else if (auto s = taxonomy::dcast<taxonomy::face>(i)) {
|
||||
visit_2<T, taxonomy::face>(s, fn);
|
||||
}
|
||||
else if (auto s = taxonomy::dcast<taxonomy::shell>(i)) {
|
||||
visit_2<T, taxonomy::shell>(s, fn);
|
||||
}
|
||||
else if (auto s = taxonomy::dcast<taxonomy::solid>(i)) {
|
||||
visit_2<T, taxonomy::solid>(s, fn);
|
||||
}
|
||||
else if (auto s = taxonomy::dcast<taxonomy::loft>(i)) {
|
||||
visit_2<T, taxonomy::loft>(s, fn);
|
||||
}
|
||||
else if (auto s = taxonomy::dcast<taxonomy::boolean_result>(i)) {
|
||||
visit_2<T, taxonomy::boolean_result>(s, fn);
|
||||
}
|
||||
else if (auto pt = taxonomy::dcast<taxonomy::point3>(i)) {
|
||||
if (auto col = std::dynamic_pointer_cast<taxonomy::collection>(child)) {
|
||||
visit_2<T, taxonomy::collection>(col, fn);
|
||||
} else if (auto loop = std::dynamic_pointer_cast<taxonomy::loop>(child)) {
|
||||
visit_2<T, taxonomy::loop>(loop, fn);
|
||||
} else if (auto face = std::dynamic_pointer_cast<taxonomy::face>(child)) {
|
||||
visit_2<T, taxonomy::face>(face, fn);
|
||||
} else if (auto shell = std::dynamic_pointer_cast<taxonomy::shell>(child)) {
|
||||
visit_2<T, taxonomy::shell>(shell, fn);
|
||||
} else if (auto solid = std::dynamic_pointer_cast<taxonomy::solid>(child)) {
|
||||
visit_2<T, taxonomy::solid>(solid, fn);
|
||||
} else if (auto loft = std::dynamic_pointer_cast<taxonomy::loft>(child)) {
|
||||
visit_2<T, taxonomy::loft>(loft, fn);
|
||||
} else if (auto bl = std::dynamic_pointer_cast<taxonomy::boolean_result>(child)) {
|
||||
visit_2<T, taxonomy::boolean_result>(bl, fn);
|
||||
} else if (auto pt = std::dynamic_pointer_cast<taxonomy::point3>(child)) {
|
||||
fn(pt);
|
||||
}
|
||||
else if (auto l = taxonomy::dcast<taxonomy::edge>(i)) {
|
||||
} else if (auto ed = std::dynamic_pointer_cast<taxonomy::edge>(child)) {
|
||||
// @todo maybe make edge a collection then as well?
|
||||
if (l->start.which() == 1) {
|
||||
fn(boost::get<taxonomy::point3::ptr>(l->start));
|
||||
if (ed->start.which() == 1) {
|
||||
fn(boost::get<taxonomy::point3::ptr>(ed->start));
|
||||
}
|
||||
if (l->end.which() == 1) {
|
||||
fn(boost::get<taxonomy::point3::ptr>(l->end));
|
||||
if (ed->end.which() == 1) {
|
||||
fn(boost::get<taxonomy::point3::ptr>(ed->end));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user