# How to upsample a (non-boundary) mesh region

I have a simple 2D triangle mesh embedded in a 3D space; note that it is not a BoundaryMeshRegion, but it is a MeshRegion. What I would like to do is quite simple: I want to upsample the mesh such that the max cell measure is some small number. If the mesh were instead a Disk, I would do this:

DiscretizeRegion[Disk[x0, r], MaxCellMeasure -> 0.001]


However, the following code simply returns the original mesh:

mesh = MeshRegion[
{{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 0, 0}},
{Triangle[{1, 2, 3}], Triangle[{2, 3, 4}]}];
DiscretizeRegion[mesh, MaxCellMeasure -> 0.001]


I've seen a few similar questions on this site, but all of them involve boundary mesh objects or mesh objects that can be converted to a boundary mesh. None of these work for me.

My first intuition was that I might be able to discretize each triangle in the mesh individually then to use RegionUnion to put them all together; however, this fails both because DiscretizeRegion yields the original triangle (though it seems to work on 2D triangles) and because the RegionUnion seems to fail to join the triangles. Neither can you use TriangulateMesh on a single triangle because a single triangle cannot be a BoundaryMesh.

This seems like something that should be a simple operation: given a mesh, give me back a mesh that contains the identical set of points, but that is described using more vertices and faces. Is there an elegant way to do this in Mathematica?

Since you're not specifying the dimension of the measure, it's defaulting to 3. Specifying 2 -> 0.001 or "Area" -> 0.001 should work:

mesh = MeshRegion[{{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 0, 0}},
{Triangle[{1, 2, 3}], Triangle[{2, 3, 4}]}];
DiscretizeRegion[mesh, MaxCellMeasure -> {2 -> 0.001}] // MeshCellCount

{1159, 3320, 2162}


This is the documented behavior: • Doh. Very good! – Henrik Schumacher Apr 6 '18 at 22:28
• Oh, nice; this is actually what I felt ought to be present in the UI somewhere. I don't suppose you know what it means to set the MaxCellMeasure at dimension 3 equal to 0.001, though? It's not a boundary mesh, so has no volume, I would think. This seems like a poorly designed parameter specification, or am I missing something? – nben Apr 9 '18 at 14:06

I updated the function LoopSubdivide from this post in order to account also for planar subdivision.

mesh = MeshRegion[{{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 0, 0}}, {Triangle[{1, 2, 3}], Triangle[{2, 3, 4}]}];
DiscretizeRegion[mesh, MaxCellMeasure -> 0.001];


Default Loop subdivision with smoothing of boundary

Nest[LoopSubdivide, mesh, 3] Purely planar subdivision:

g = LoopSubdivide[#, "VertexWeightFunction" -> (x \[Function] 0),
"AverageBoundary" -> False, "EdgeWeight" -> 0.5] &;
Nest[g, mesh, 3] • Precisely what I'm looking for, thanks! Had hoped it would be a simple built-in, but this works fine. – nben Apr 6 '18 at 21:47
• Unfortunately, surfaces meshes are quite undersupported at the moment. I'm glad to hear that you like it! – Henrik Schumacher Apr 6 '18 at 21:49