4
$\begingroup$

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}]]; 

enter image description here

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

enter image description here

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

enter image description here

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:

enter image description here

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}] }] 

enter image description here

Adverserial example for cvgmt's solution

The proposed solution of

BoundaryDiscretizeRegion @ RegionUnion[{p1,p2}] // Region`Mesh`MergeCells 

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}}]}; 

enter image description here

(* doesn't evaluate *) BoundaryDiscretizeRegion @ RegionUnion[vols] >>> BoundaryDiscretizeRegion[BooleanRegion[#1 || #2 || #3 || #4 || #5 &, {vols}]] % // Region`Mesh`MergeCells >>> Region`Mesh`MergeCells[ BoundaryDiscretizeRegion[ ... ] ] 

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

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

enter image description here

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.

Another strange adverserial example

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!

enter image description here

$\endgroup$
5
  • $\begingroup$ I have provide three methods,but you still down vote my answer. So I will never answer all of your question! $\endgroup$ Commented Oct 29, 2022 at 23:05
  • $\begingroup$ What is the reason that you want a single polyhedron? $\endgroup$ Commented Oct 31, 2022 at 15:56
  • $\begingroup$ @user21 the final single Polyhedron is exported to use in other software $\endgroup$ Commented Oct 31, 2022 at 20:51
  • $\begingroup$ @cvgmt I have your original answer, and it made no mention of returning Polyhedron. What's your game here? $\endgroup$ Commented Nov 2, 2022 at 17:27
  • $\begingroup$ If it is possible to work with the faces of the polygon rather than the polyhedron one could merge polygons that are coplanar using CoplanarPoints in version 13. That could be done by making a list of faces and using Gather with CoplanarPoints and maybe applying RegionUnion on each group of faces. There are also answers on stack exchange for grouping coplanar faces. $\endgroup$ Commented Nov 5, 2022 at 15:44

3 Answers 3

5
$\begingroup$

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

Needs["OpenCascadeLink`"] r = RegionUnion @@ vols; shape = OpenCascadeShape[r]; bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]; mr = MeshRegion[bmesh]; Region`Mesh`MergeCells[mr] 

enter image description here

$\endgroup$
2
$\begingroup$

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

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

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:

Mathematica graphics

Mathematica graphics

Mathematica graphics

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.

$\endgroup$
2
  • $\begingroup$ You can use OpenCascadeLink to extrude, no need to write a function. $\endgroup$ Commented Mar 23, 2023 at 4:40
  • $\begingroup$ 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. $\endgroup$ Commented Mar 23, 2023 at 20:37

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.