# Unify Polyhedrons into a single Polyhedron

Consider these two simple Polyhedrons which share a sub-face:

p1 = Polyhedron[
{{0, 0, 0}, {2, 0, 0}, {2, 1, 0}, {0, 1, 0}, {0, 0, 1}, {2, 0, 1}, {2, 1, 1}, {0, 1, 1}},
{{1, 2, 3, 4}, {5, 6, 7, 8}, {1, 2, 6, 5}, {2, 3, 7, 6}, {3, 4, 8, 7}, {4, 1, 5, 8}}];

p2 =  TransformedRegion[p1, TranslationTransform[{1, 0, 1}]];


I wish to produce a third Polyhedron which describes the union of these shapes, as suggested by the Region admitted by RegionUnion:

Unfortunately the Polyhedron produced by RegionUnion has not merged the 'side faces' but has actually split up previous individual faces!

It seems like MeshCells[] is unable to return a single Polyhedron describing the full volume.

MeshCells[RegionUnion[p1, p2], 3]

>>> MeshCells: There is no simple cell representation for the specified cells of the BoundaryMeshRegion


My issues with the generated polyhedron do not appear to constitute mesh defects:

In principle, I can obtain a list of all the individual faces admitted by RegionUnion...

p3 = RegionUnion[p1, p2];
coords = First[p3];
faces = MeshCells[p3, 2] /. i_Integer :> coords[[i]];


and attempt to stitch them myself into "clean" polyhedron faces by unifying co-planar edge-intersecting faces (using e.g. Not @ RegionDisjoint[faces[[i]], faces[[j]]). This appears to require rotating co-planar faces into 2D Polygon, merging them and rotating back - quite a pain for one might expect as a basic Mathematica function!

Is there a way to achieve a simple unified Polyhedron like the one I have constructed below by hand:

p3 = Polyhedron[{
{0, 0, 0}, {2, 0, 0}, {2, 0, 1}, {3, 0, 1}, {3, 0, 2}, {1, 0, 2}, {1, 0, 1}, {0, 0, 1},
{0, 1, 0}, {2, 1, 0}, {2, 1, 1}, {3, 1, 1}, {3, 1, 2}, {1, 1, 2}, {1, 1, 1}, {0, 1, 1}
}, {
Range[8], 8 + Range[8],
{1, 8,  16 , 9},
Sequence @@ Table[i + {0, 1, 9, 8}, {i, 7}]
}]


# Adverserial example for cvgmt's solution

The proposed solution of

BoundaryDiscretizeRegion @ RegionUnion[{p1,p2}] // RegionMeshMergeCells


has some issues for longer lists of more complicated Polyhedron.

For example:

vols = {Polyhedron[{{202., 277.22222222222223, 40}, {300., 250.,
40}, {300., 296., 40}, {202., 296., 40}, {202.,
277.22222222222223, 52}, {300., 250., 52}, {300., 296.,
52}, {202., 296., 52}}, {{1, 2, 3, 4}, {5, 6, 7, 8}, {1, 2, 6,
5}, {2, 3, 7, 6}, {3, 4, 8, 7}, {4, 1, 5, 8}}],
Polyhedron[{{400., 257.77777777777777, 40}, {400.,
222.22222222222223, 40}, {480., 200., 40}, {400.,
257.77777777777777, 52}, {400., 222.22222222222223,
52}, {480., 200., 52}}, {{1, 2, 3}, {4, 5, 6}, {1, 2, 5, 4}, {2,
3, 6, 5}, {3, 1, 4, 6}}],
Polyhedron[{{400., 257.77777777777777, 0}, {300., 330., 0}, {150.,
350., 0}, {120., 300., 0}, {202., 277.22222222222223,
0}, {202., 296., 0}, {300., 296., 0}, {300., 250., 0}, {400.,
222.22222222222223, 0}, {400., 257.77777777777777, 12}, {300.,
330., 12}, {150., 350., 12}, {120., 300., 12}, {202.,
277.22222222222223, 12}, {202., 296., 12}, {300., 296.,
12}, {300., 250., 12}, {400., 222.22222222222223, 12}}, {{1, 2,
3, 4, 5, 6, 7, 8, 9}, {10, 11, 12, 13, 14, 15, 16, 17, 18}, {1,
2, 11, 10}, {2, 3, 12, 11}, {3, 4, 13, 12}, {4, 5, 14, 13}, {5,
6, 15, 14}, {6, 7, 16, 15}, {7, 8, 17, 16}, {8, 9, 18, 17}, {9,
1, 10, 18}}],
Polyhedron[{{312., 246.66667169012294, 12}, {312., 308.,
12}, {190., 308., 12}, {190., 280.55554604499355, 12}, {202.,
277.22222222222223, 12}, {202., 296., 12}, {300., 296.,
12}, {300., 250., 12}, {312., 246.66667169012294, 52}, {312.,
308., 52}, {190., 308., 52}, {190., 280.55554604499355,
52}, {202., 277.22222222222223, 52}, {202., 296., 52}, {300.,
296., 52}, {300., 250., 52}}, {{1, 2, 3, 4, 5, 6, 7, 8}, {9, 10,
11, 12, 13, 14, 15, 16}, {1, 2, 10, 9}, {2, 3, 11, 10}, {3, 4,
12, 11}, {4, 5, 13, 12}, {5, 6, 14, 13}, {6, 7, 15, 14}, {7, 8,
16, 15}, {8, 1, 9, 16}}],
Polyhedron[{{388., 266.444472098731, 12}, {388.,
225.55554579605914, 12}, {400., 222.22222222222223,
12}, {400., 257.77777777777777, 12}, {388., 266.444472098731,
52}, {388., 225.55554579605914, 52}, {400.,
222.22222222222223, 52}, {400., 257.77777777777777, 52}}, {{1,
2, 3, 4}, {5, 6, 7, 8}, {1, 2, 6, 5}, {2, 3, 7, 6}, {3, 4, 8,
7}, {4, 1, 5, 8}}]};


(* doesn't evaluate *)
BoundaryDiscretizeRegion @ RegionUnion[vols]

>>> BoundaryDiscretizeRegion[BooleanRegion[#1 || #2 || #3 || #4 || #5 &, {vols}]]

% // RegionMeshMergeCells

>>> RegionMeshMergeCells[ BoundaryDiscretizeRegion[ ... ] ]


We could discretise first to avoid BooleanRegion as per this question...

(* evaluates to a BoundaryMeshRegion *)
reg = RegionUnion[BoundaryDiscretizeRegion /@ testvols]


Alas, now calling MergeCells[reg] throws an error:

>>> BoundaryMeshRegion::bsuncl: The boundary surface is not closed because the edges Line[{{34,36},{37,35},{36,37},{35,34}}] only come from a single face.


It is also not clear to me how to extract a Polyhedron from the resulting BoundaryMeshRegion when this technique does work.

Consider the list of polyhedrons:

vols = {InputForm[
Polyhedron[{{300., 164.53571428571428, 10}, {202.,
163.36904761904762, 10}, {202., -44.66666666666667,
10}, {249., -76., 10}, {300., -44.125, 10}, {300.,
164.53571428571428, 20}, {202., 163.36904761904762,
20}, {202., -44.66666666666667, 20}, {249., -76.,
20}, {300., -44.125, 20}}, {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {
1, 2, 7, 6}, {2, 3, 8, 7}, {3, 4, 9, 8}, {4, 5, 10, 9}, {5, 1, 6,
10}}]], InputForm[
Polyhedron[{{300., -44.125, 0}, {249., -76.,
0}, {202., -44.66666666666667, 0}, {202., -200.,
0}, {300., -200., 0}, {300., -44.125, 10}, {249., -76.,
10}, {202., -44.66666666666667, 10}, {202., -200.,
10}, {300., -200., 10}}, {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {1,
2, 7, 6}, {2, 3, 8, 7}, {3, 4, 9, 8}, {4, 5, 10, 9}, {5, 1, 6,
10}}]], InputForm[
Polyhedron[{{202., 296., 0}, {202., 163.36904761904762, 0}, {300.,
164.53571428571428, 0}, {300., 296., 0}, {202., 296.,
10}, {202., 163.36904761904762, 10}, {300.,
164.53571428571428, 10}, {300., 296., 10}}, {{1, 2, 3, 4}, {5,
6, 7, 8}, {1, 2, 6, 5}, {2, 3, 7, 6}, {3, 4, 8, 7}, {4, 1, 5,
8}}]], InputForm[
Polyhedron[{{300.00000220959214, -55.91747503407568,
10}, {300., -44.125, 10}, {249., -76.,
10}, {202., -44.66666666666667,
10}, {202.00000237873843, -56.68517250403892,
10}, {248.82501070724447, -87.90184472304296,
10}, {300.00000220959214, -55.91747503407568,
20}, {300., -44.125, 20}, {249., -76.,
20}, {202., -44.66666666666667,
20}, {202.00000237873843, -56.68517250403892,
20}, {248.82501070724447, -87.90184472304296, 20}}, {{1, 2, 3,
4, 5, 6}, {7, 8, 9, 10, 11, 12}, {1, 2, 8, 7}, {2, 3, 9, 8}, {3,
4, 10, 9}, {4, 5, 11, 10}, {5, 6, 12, 11}, {6, 1, 7, 12}}]],
InputForm[
Polyhedron[{{300., 174.5364228773892, 10}, {202., 173.36975621072256,
10}, {202., 163.36904761904762, 10}, {300.,
164.53571428571428, 10}, {300., 174.5364228773892, 20}, {202.,
173.36975621072256, 20}, {202., 163.36904761904762,
20}, {300., 164.53571428571428, 20}}, {{1, 2, 3, 4}, {5, 6, 7,
8}, {1, 2, 6, 5}, {2, 3, 7, 6}, {3, 4, 8, 7}, {4, 1, 5, 8}}]]}


Attempting to merge these volumes by the same technique above makes two of the faces (and the bounded volume in-between) disappear!

• I have provide three methods,but you still down vote my answer. So I will never answer all of your question! Oct 29, 2022 at 23:05
• Three methods with no explanatory text, which didn't work for my examples, and which didn't address my request for obtaining a Polyhedron. I hardly think you got to 43k rep doing that Oct 29, 2022 at 23:08
• What is the reason that you want a single polyhedron? Oct 31, 2022 at 15:56
• @user21 the final single Polyhedron is exported to use in other software Oct 31, 2022 at 20:51
• @cvgmt I have your original answer, and it made no mention of returning Polyhedron. What's your game here? Nov 2, 2022 at 17:27

This is a comment not an answer. This should be more robust:

Needs["OpenCascadeLink"]
r = RegionUnion @@ vols;
mr = MeshRegion[bmesh];
RegionMeshMergeCells[mr]


I did not read all the details of the question but I noticed that taking the complement of the complement of the union of the polygons reduces the number of faces and so it might be what you are looking for:

poly = RegionUnion[p1, p2];


Number of faces : 18 (seen in the Polyhedron box image)

boundr = RegionUnion[p1, p2] // BoundingRegion;
RegionDifference[boundr, RegionDifference[boundr, poly]];


Number of faces : 16

• BoundingRegion doesn't work on RegionUnion[vols] since the latter is a BooleanRegion Nov 2, 2022 at 18:00

Perhaps this may be useful.

extrude is a function I wrote to avoid a problem in RegionProduct. I have reported that issue to Wolfram support already. The problem appears as beveled corners and edges.

First the images and then the code:

Graphics[{EdgeForm[Black], FaceForm[None],
polygon1 = Rectangle[{0, 0}, {2, 1}],
polygon2 = Translate[polygon1, {1, 1}]},
AspectRatio -> Automatic]

MeshRegion[polygon1]

MeshRegion[polygon2]

shape = First[MeshPrimitives[CanonicalizeRegion[
RegionUnion[MeshRegion[polygon1], MeshRegion[polygon2]]],
2]]

extrude = Function[{interval, polygon},
Block[{span, canonical, bottom, top, edges, i, j, k,
points, faces}, span = Sort[interval];
canonical = CanonicalizePolygon[polygon];
points = Union[Sort[Join[(Append[#1, span[[1,1]]] & ) /@
canonical[[1]], (Append[#1, span[[1,2]]] & ) /@
canonical[[1]]]]]; bottom =
(Append[canonical[[1,#1]], span[[1,1]]] & ) /@
Reverse[canonical[[2]]]; bottom =
First[Flatten[(Position[points, #1] & ) /@ bottom,
{2, 3}]]; top = (Append[canonical[[1,#1]],
span[[1,2]]] & ) /@ canonical[[2]];
top = First[Flatten[(Position[points, #1] & ) /@ top,
{2, 3}]]; edges = Table[j = top[[i]];
k = top[[Mod[i + 1, Length[top], 1]]];
{j - 1, k - 1, k, j}, {i, Length[top]}];
faces = Join[{bottom, top}, edges];
CanonicalizePolyhedron[Polyhedron @@ {points, faces}]]];

InputForm[Rationalize[shape]]

Region[extrude[Interval[{0, 1}], shape]]

Region[RegionProduct[Interval[{0, 1}], shape]]

Wed 22 Mar 2023 19:49:53GMT-4
13.2.1 for Microsoft Windows (64-bit) (January 27, 2023)
Microsoft Windows 10 Pro  10.0.19045
{DisplayVersion,22H2}
Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
{NumberOfCores,8}
{Capacity     DeviceLocator   PartNumber        Speed,
17179869184  ChannelA-DIMM0  F4-3200C16-16GVK  3200,
17179869184  ChannelA-DIMM1  F4-3200C16-16GVK  3200,
17179869184  ChannelB-DIMM0  F4-3200C16-16GVK  3200,
17179869184  ChannelB-DIMM1  F4-3200C16-16GVK  3200}
`

Of course, I may have missed something.

• You can use OpenCascadeLink to extrude, no need to write a function. Mar 23 at 4:40
• Thank you for the information. I had "extrude" already on hand; it was written several months again and long before I heard of OpenCascadeLink. And, this way "the how it was done" is visible.
– anon
Mar 23 at 20:37