7
$\begingroup$

I have a multiply connection two-dimensional region such as the following:

br = BoundaryDiscretizeGraphics@Graphics[Disk[#, 8/9] & /@ CirclePoints[9]]

Mathematica graphics

I am looking for a way to discard all inner "holes", i.e. get this:

enter image description here

In order to get this I was hoping to be able to separate the two boundaries of the region, then manually pick the outer one. What is a simple way to do this?

$\endgroup$
7
$\begingroup$

Here's an attempt to automate the selection of the outer boundaries with some undocumented properties. Here's a BoundaryMeshRegion with multiple holes and multiple outer boundaries:

g1 = Graphics[Table[Annulus[{x, 0}, {0.5 + x/20, 1}], {x, 0, 9, 3}]];
g2 = Graphics[Rectangle[{1.5, -0.3}, {7.5, 0.3}]];
br = RegionUnion[BoundaryDiscretizeGraphics /@ {g1, g2}]

enter image description here

The "BoundaryGroups" property groups the boundaries of connected regions, and it appears that the first element of each group is the outer boundary. (Pure conjecture of course, but that was the case for the limited number of tests I did).

bgps = br["BoundaryGroups"]
(* {{6, 2, 3, 4, 5}, {8, 7}, {1, 9}} *)

outer = bgps[[All, 1]]
(* {6, 8, 1} *)

I use another undocumented property, "IndexedBoundaryPolygons" to extract the polygons with those indices and construct a new region:

polys = br["IndexedBoundaryPolygons"][[outer]];

MeshRegion[MeshCoordinates[br], polys]

enter image description here

$\endgroup$
5
$\begingroup$

One possible solution is to take the boundary, then find the connected components:

ConnectedMeshComponents@RegionBoundary[br]

Mathematica graphics

Key functions: ConnectedMeshComponents, RegionBoundary.

We can then manually pick the boundary we want:

outer = First[%];

And convert it back to a polygon (a 2D region rather than a boundary):

BoundaryDiscretizeRegion@Polygon@MeshCoordinates[outer]

Mathematica graphics

In more complicated examples order of the points returned by MeshCoordinates may not follow the boundary in a continuous manner. In this case we can reorder them before converting them to a polygon:

pts = Part[
   MeshCoordinates[outer],
   DeleteDuplicates@Level[MeshCells[outer, 1], {-1}]
 ];
$\endgroup$
  • $\begingroup$ I arrived to this solution after I have written up the question. Given that it took me some time to figure this out, I though posting the solution would be more valuable than deleting the question. $\endgroup$ – Szabolcs Dec 21 '15 at 9:25
  • $\begingroup$ I was just about to post just another way of selecting the relevant mesh coordinates by selecting outside a disk...this is helpful and I am voting for it:) $\endgroup$ – ubpdqn Dec 21 '15 at 9:43
  • $\begingroup$ @ubpdqn If you have another solution, I would like to see it! $\endgroup$ – Szabolcs Dec 21 '15 at 9:49
  • $\begingroup$ @ubpdqn That would have worked too. I disk would not work for my real example, but I could have drawn an outline manually to separate the outer boundary from the inner ones, then test whether the points are within this outline. $\endgroup$ – Szabolcs Dec 21 '15 at 9:50
  • $\begingroup$ it probably just worked for this case where the internal boundary is conveniently separable by a disk and the outer coordinates conveniently ordered... $\endgroup$ – ubpdqn Dec 21 '15 at 9:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.