Distinguish between inner and outer boundary in MeshRegion

You can use ConnectedMeshComponents as follows:

cmc = ConnectedMeshComponents[DiscretizeGraphics[MeshPrimitives[mr, {1, "Boundary"}]]]; 

Show[mr,  Epilog -> Thread[{Thickness[.01], {Red, Blue},  MeshPrimitives[#, 1] & /@ cmc}]]

enter image description here


You can convert your MeshRegion to a boundary element mesh with auto generated markers by:

Needs["NDSolve`FEM`"]
bmesh = ToBoundaryMesh[RegionBoundary[mr]];
bmesh["Wireframe"["MeshElementStyle" -> "BoundaryGrouping"]]

enter image description here

The fact that the rectangle has also been split is desirable for FEM. You can look at the markers generated.

bmesh["BoundaryElementMarkerUnion"]
{1, 2, 3, 4, 5}

Here is a mesh that has an outer boundary, an inner boundary and a material boundary:

Needs["NDSolve`FEM`"]
\[CapitalOmega] = 
  ImplicitRegion[(x - 1/2)^2 + (y - 1/2)^2 >= (1/
        2)^2 && (x + 1/2)^2 + (y + 1/2)^2 >= (1/2)^2, {{x, -2, 
     2}, {y, -2, 2}}];
(mesh = ToElementMesh[\[CapitalOmega], 
    "RegionHoles" -> {{-1/2, -1/2}}, 
    "RegionMarker" -> {{{1/2, 1/2}, 2}, {{1/2, -1/2}, 1}}, 
    "MaxBoundaryCellMeasure" -> 0.125])["Wireframe"]

enter image description here

You can then extract the boundary element marker union; these markers are auto generated.

groups = mesh["BoundaryElementMarkerUnion"]
{1, 2, 3, 4, 5, 6}

Some colors for the markers:

temp = Most[Range[0, 1, 1/(Length[groups])]];
colors = ColorData["BrightBands"][#] & /@ temp

enter image description here

mesh["Wireframe"["MeshElement" -> "BoundaryElements", 
  "MeshElementStyle" -> (Directive[#] & /@ colors)]]

enter image description here

To further work with this you could use MeshElementSplitByMarker:

mesbm = Flatten[
   MeshElementSplitByMarker[
    MeshOrderAlteration[mesh, 1]["BoundaryElements"]]];

and extract one of the components:

Graphics[GraphicsComplex[mesh["Coordinates"], 
  Line[ElementIncidents[mesbm[[6]]]]]]

enter image description here

This selection works by looking at normals and grouping them with some threshold. There are a few examples in the ElementMesh ref page in the Scope section under "BoundaryNormals".

Another approach is to use the "VertexBoundaryConnectivity" in conjunction with StronglyConnectedComponents.

bmesh = ToBoundaryMesh[mesh];
belems = bmesh["BoundaryElements"];

bincidents = Join @@ ElementIncidents[belems];
S = bmesh["VertexBoundaryConnectivity"];
S = Transpose[S].S;
components = SparseArray`StronglyConnectedComponents[S];
pls = Map[Line[Developer`ToPackedArray /@ (Part[bincidents, #])] &, 
  components]
Graphics[GraphicsComplex[bmesh["Coordinates"], pls]]

enter image description here