In my recent efforts to design some 3D printable objects, I have been tempted to use relatively recent additions to the Wolfram Language such as RegionDifference only to be thrown into what can be best described as the Great Pit of Carkoon.
Here is one journey:
Let us start off with the simple subtraction of two objects:
RegionDifference[Region@Hexahedron[], Region@Cylinder[]]
So far so good. However, upon moving to more interesting objects, we quickly hit a brick wall.
hexpts = {{1.7, 1.5, 0}, {1.7, 10.8, 0}, {20.3, 10.8, 0}, {20.3, 1.5,
0}, {1.7, 1.5, 0.6}, {1.7, 10.8, 0.6}, {20.3, 10.8, 0.6}, {20.3,
1.5, 0.6}};
cylpts = {{14.3, 0.5, 0.6}, {14.3, 11.8, 0.6}};
cylr = 1.5;
RegionDifference[Region@Hexahedron[hexpts],
Region@Cylinder[cylpts, cylr]]
I can find no further information about this object, and subsequent operations on this region do not yield any meaningful results. Interestingly, when Rounding the Hexahedron points, functionality is restored:
Show[RegionDifference[Region@Hexahedron[Round@hexpts],
Region@Cylinder[cylpts, cylr]], Axes -> True]
If the problem can be solved by using only integers, then scaling the objects may serve as a workaround.
scale = 10;
Show[TransformedRegion[
RegionDifference[Region@Hexahedron[Round@(scale hexpts)],
Region@Cylinder[scale cylpts, scale cylr]],
ScalingTransform[{1, 1, 1}/scale]], Axes -> True]
I would have been satisfied with this solution, if it actually worked in a more general sense. However, it doesn't.
scale = 10;
hexpts2 = {{1.7, 1.5, 0.6}, {1.7, 10.8, 0.6}, {20.3, 10.8,
0.6}, {20.3, 1.5, 0.6}, {2.6, 2.1, 1.8}, {2.6, 10.2, 1.8}, {19.2,
10.2, 1.8}, {19.2, 2.1, 1.8}};
RegionUnion[
Region@Hexahedron@Round@(scale hexpts),
Region@Hexahedron@Round@(scale hexpts2)];
#[%, Cylinder[scale cylpts, scale cylr]] & /@ {RegionUnion,
RegionDifference}
I then came across this answer which recommends the use of BoundaryDiscretizeRegion which is encouraging, but slow.
scale = 10;
cylpts2 = {{1.7, 0.5, 0.6}, {1.7, 11.8, 0.6}};
cylr2 = 2.25;
reg1 = BoundaryDiscretizeRegion[Hexahedron@Round@(scale hexpts)];
reg2 = BoundaryDiscretizeRegion[Hexahedron@Round@(scale hexpts2)];
reg3 = BoundaryDiscretizeRegion[
Cylinder[Round@(scale cylpts), Round@(scale cylr)]];
reg4 = BoundaryDiscretizeRegion[
Cylinder[Round@(scale cylpts2), Round@(scale cylr2)]];
reg5 = RegionDifference[
BoundaryDiscretizeRegion@RegionUnion[reg1, reg2],
BoundaryDiscretizeRegion@RegionUnion[reg3, reg4]];
Show[TransformedRegion[reg5, ScalingTransform[{1, 1, 1}/scale]],
Axes -> True]
And as one can expect - since this is a question and not an answer - the workaround/hack fails when trying to scale to larger numbers in order to achieve slightly better precision in the object dimensions.
pts1 = {{1.7276, 1.47295, -0.01}, {1.7276, 10.77705, -0.01}, {20.2724,
10.77705, -0.01}, {20.2724, 1.47295, -0.01}, {1.7276, 1.47295,
0.6}, {1.7276, 10.77705, 0.6}, {20.2724, 10.77705, 0.6}, {20.2724,
1.47295, 0.6}};
pts2 = {{1.7276, 1.47295, 0.6}, {1.7276, 10.77705, 0.6}, {20.2724,
10.77705, 0.6}, {20.2724, 1.47295, 0.6}, {2.5802, 2.09795,
1.85}, {2.5802, 10.15205, 1.85}, {19.2235, 10.15205,
1.85}, {19.2235, 2.09795, 1.85}};
pts3 = {{1.7276, 0.47295, 0.6}, {1.7276, 11.77705, 0.6}};
pts4 = {{14.2533, 0.47295, 0.6}, {14.2533, 11.77705, 0.6}};
{cr1, cr2} = {2.25, 1.5};
scale = 100;
reg1 = BoundaryDiscretizeRegion[Hexahedron@Round@(scale pts1)];
reg2 = BoundaryDiscretizeRegion[Hexahedron@Round@(scale pts2)];
reg3 = BoundaryDiscretizeRegion[
Cylinder[Round@(scale pts3), Round@(scale cr1)]];
reg4 = BoundaryDiscretizeRegion[
Cylinder[Round@(scale pts3), Round@(scale cr2)]];
reg5 = RegionDifference[
BoundaryDiscretizeRegion@RegionUnion[reg1, reg2],
BoundaryDiscretizeRegion@RegionUnion[reg3, reg4]];
Show[TransformedRegion[reg5, ScalingTransform[{1, 1, 1}/scale]],
Axes -> True]
My question now is, should these operations work? Is the behavior I am observing a bug? Is it a limitation in newly implemented functionality? While recent, the functions have been around for at least 2 major releases of Mathematica, so I am making the (naive?) assumption that they are working as intended to some degree. Perhaps I am expecting too much from the software package.
Perhaps this is overly broad, but I am also interested in the extent to which we should find workarounds for these types of problems. On the one hand, the problems have existed long enough that developing solutions may prove useful. However, if Wolfram's intent is to solve these problems (eventually) then I don't know how much effort to put in to developing my own solutions.










BoundaryDiscretizeRegionsometimesDiscretizeRegionsometimes rationalized input and sometimes it is better to just use the Booleans on the symbolic (exact) region. This should be much simpler. I'd file a bug with WRI. – user21 Dec 18 '19 at 08:52