Triangulate a surface given as a MeshRegion
Why not use DiscretizeRegion
again but with a lower MaxCellMeasure
?
mr = DiscretizeRegion[RegionBoundary[Cuboid[]], MaxCellMeasure -> ∞,
MeshCellStyle -> {1 -> Black}]
DiscretizeRegion[mr, MaxCellMeasure -> {2 -> .01}, MeshCellStyle -> {1 -> Black}]
After a bit of spelunking I got this:
r = DiscretizeRegion[RegionBoundary@Cuboid[],
MaxCellMeasure -> Infinity, MeshCellStyle -> {1 -> Black}];
Needs["TriangleLink`"]
r2 = Region`Mesh`Triangulate3DFaces[r, TriangleTriangulate[#, "pqa0.01"] &]
{RegionDimension[r2], RegionEmbeddingDimension[r2]}
(* {2, 3} *)
The TriangleTriangulate documentation describes how to control the triangulation.
This is a hack, but it does the trick. The problem is that you can't use TriangulateMesh
on a 2D polygon embedded in 3D. One solution is to translate/rotate your polygon to the xy plane, triangulate, then reverse the transformation.
triangulate3DPolygon[Polygon[pts__], opts : OptionsPattern[]] := Module[
{a, b, c, U, V, W, tr, trpgon, newpts, newpgns},
(*The rotation matrix - http://math.stackexchange.com/a/856705 *)
{a, b, c} = pts[[;; 3]];
tr = a;
{a, b, c} = # - a & /@ {a, b, c};
{U, W} = {Normalize[b], Normalize[Cross[b, c]]};
V = Cross[U, W];
{U, V, W}.(# - tr) & /@ pts;
trpgon = TriangulateMesh[
DiscretizeGraphics[
Polygon[Most /@ ({U, V, W}.(# - tr) & /@ pts)]],
opts
];
newpts = (Transpose[{U, V, W}].PadRight[#, 3] + tr) & /@ MeshCoordinates[trpgon];
newpgns = MeshCells[trpgon, 2];
{newpts, newpgns}
];
Options[triangulate2DMeshEmb3D] = {"OutputType" -> "MeshRegion"};
triangulate2DMeshEmb3D[mesh_,opts : OptionsPattern[
{MeshRegion, TriangulateMesh, Graphics3D, triangulate2DMeshEmb3D}]
] :=Module[ {pgons, data, extracount, bag, pgonPrimitives, head, pts},
pgons = MeshPrimitives[mesh, 2];
data = triangulate3DPolygon[#,
Evaluate@FilterRules[{opts}, Options[TriangulateMesh]]] & /@ pgons;
extracount = 0;
bag = Internal`Bag[];
pgonPrimitives = {};
Do[
pgonPrimitives = Join[
pgonPrimitives,
data[[n, 2]] /. Polygon[a__] :> Polygon[a + extracount]
];
Do[
extracount++;
Internal`StuffBag[bag, pt],
{pt, data[[n, 1]]}
];
, {n, Length@data}
];
head = Switch[OptionValue["OutputType"], "MeshRegion", MeshRegion,
"Graphics3D", Graphics3D@*GraphicsComplex];
pts = Internal`BagPart[bag, All];
Clear[bag];
head[pts, pgonPrimitives,
Evaluate[FilterRules[{opts}, Options[head]]]]
];
If you don't tell MeshRegion
to color the lines in black, then you might think it didn't work,
But you can see that it does work, and the triangulation is customizable,
triangulate2DMeshEmb3D[
msh,
MeshCellStyle -> {1 -> Black},
MaxCellMeasure -> #] & /@ {.2, .01}
Through[{RegionEmbeddingDimension, RegionDimension}[First@%]]