Skip to content

Commit

Permalink
record shapes with negative intersecting volume as touching
Browse files Browse the repository at this point in the history
after sleeping on my change last night, this seems like the least bad
solution. at least until this gets fixed in OCCT!

this limit of 10% is debatable, in practice I've only seen volumes of
smaller than 0.1% so should be generous.
  • Loading branch information
smason committed Feb 1, 2022
1 parent cea21db commit 0e5b6cb
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions src/geometry.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <algorithm>
#include <cstdlib>
#include <stdexcept>
#include <sys/types.h>
Expand Down Expand Up @@ -333,16 +334,10 @@ intersect_result classify_solid_intersection(
TopExp_Explorer ex;
ex.Init(op.Shape(), TopAbs_SOLID);
if (ex.More()) {
// we expect the common volume to occasionally come back negative.
// OCCT appears to do this when the two solids have faces that are
// within the given tolerance/fuzzy value
// OCCT (version 7.5) appears to occasionally come back with a
// negative volume. it appears to do this when the two solids have
// non-trivial faces that are within the given tolerance/fuzzy value
result.vol_common = volume_of_shape_maybe_neg(op.Shape());
if (result.vol_common < 0) {
// returning failed here should cause the overlap checker will
// retry with a stricter tolerance, which tends to cause this
// error to disappear!
return result;
}

op.SetOperation(BOPAlgo_CUT);
op.Build();
Expand All @@ -358,7 +353,25 @@ intersect_result classify_solid_intersection(
}
result.vol_cut12 = volume_of_shape(op.Shape());

result.status = intersect_status::overlap;
if (result.vol_common < 0) {
// ensure the this negative volume is "small", relative to the
// input shapes, as we only expect this to happen along the
// boundary of shapes
const double limit = std::min(result.vol_cut, result.vol_cut12) * 0.1;
if (-result.vol_common < limit) {
throw std::runtime_error("negative volume too large");
}

// until this is fixed upstream in OCCT, recording them as
// touching seems to be best. an alternative would be to fail, and
// let the caller retry with stricter tolerance (which tends to
// succeed). touching seems best as we later steps want to know
// which solids are close to each other and therefore need to
// considered during merging
result.status = intersect_status::touching;
} else {
result.status = intersect_status::overlap;
}
return result;
}

Expand Down

0 comments on commit 0e5b6cb

Please sign in to comment.