Skip to content

Commit 0e5b6cb

Browse files
committed
record shapes with negative intersecting volume as touching
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.
1 parent cea21db commit 0e5b6cb

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

src/geometry.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <algorithm>
12
#include <cstdlib>
23
#include <stdexcept>
34
#include <sys/types.h>
@@ -333,16 +334,10 @@ intersect_result classify_solid_intersection(
333334
TopExp_Explorer ex;
334335
ex.Init(op.Shape(), TopAbs_SOLID);
335336
if (ex.More()) {
336-
// we expect the common volume to occasionally come back negative.
337-
// OCCT appears to do this when the two solids have faces that are
338-
// within the given tolerance/fuzzy value
337+
// OCCT (version 7.5) appears to occasionally come back with a
338+
// negative volume. it appears to do this when the two solids have
339+
// non-trivial faces that are within the given tolerance/fuzzy value
339340
result.vol_common = volume_of_shape_maybe_neg(op.Shape());
340-
if (result.vol_common < 0) {
341-
// returning failed here should cause the overlap checker will
342-
// retry with a stricter tolerance, which tends to cause this
343-
// error to disappear!
344-
return result;
345-
}
346341

347342
op.SetOperation(BOPAlgo_CUT);
348343
op.Build();
@@ -358,7 +353,25 @@ intersect_result classify_solid_intersection(
358353
}
359354
result.vol_cut12 = volume_of_shape(op.Shape());
360355

361-
result.status = intersect_status::overlap;
356+
if (result.vol_common < 0) {
357+
// ensure the this negative volume is "small", relative to the
358+
// input shapes, as we only expect this to happen along the
359+
// boundary of shapes
360+
const double limit = std::min(result.vol_cut, result.vol_cut12) * 0.1;
361+
if (-result.vol_common < limit) {
362+
throw std::runtime_error("negative volume too large");
363+
}
364+
365+
// until this is fixed upstream in OCCT, recording them as
366+
// touching seems to be best. an alternative would be to fail, and
367+
// let the caller retry with stricter tolerance (which tends to
368+
// succeed). touching seems best as we later steps want to know
369+
// which solids are close to each other and therefore need to
370+
// considered during merging
371+
result.status = intersect_status::touching;
372+
} else {
373+
result.status = intersect_status::overlap;
374+
}
362375
return result;
363376
}
364377

0 commit comments

Comments
 (0)