DMesh3 ComputeInflation(DMesh3 planarMesh) { DMesh3 mesh = new DMesh3(planarMesh); DijkstraGraphDistance dist = new DijkstraGraphDistance( mesh.MaxVertexID, false, (vid) => { return(mesh.IsVertex(vid)); }, (a, b) => { return((float)mesh.GetVertex(a).Distance(mesh.GetVertex(b))); }, mesh.VtxVerticesItr); foreach (int vid in MeshIterators.BoundaryVertices(mesh)) { dist.AddSeed(vid, 0); } dist.Compute(); float max_dist = dist.MaxDistance; float[] distances = new float[mesh.MaxVertexID]; foreach (int vid in mesh.VertexIndices()) { distances[vid] = dist.GetDistance(vid); } List <int> local_maxima = new List <int>(); foreach (int vid in MeshIterators.InteriorVertices(mesh)) { float d = distances[vid]; bool is_maxima = true; foreach (int nbrid in mesh.VtxVerticesItr(vid)) { if (distances[nbrid] > d) { is_maxima = false; } } if (is_maxima) { local_maxima.Add(vid); } } // smooth distances (really should use cotan here!!) float smooth_alpha = 0.1f; int smooth_rounds = 5; foreach (int ri in Interval1i.Range(smooth_rounds)) { foreach (int vid in mesh.VertexIndices()) { float cur = distances[vid]; float centroid = 0; int nbr_count = 0; foreach (int nbrid in mesh.VtxVerticesItr(vid)) { centroid += distances[nbrid]; nbr_count++; } centroid /= nbr_count; distances[vid] = (1 - smooth_alpha) * cur + (smooth_alpha) * centroid; } } Vector3d normal = Vector3d.AxisZ; foreach (int vid in mesh.VertexIndices()) { if (dist.IsSeed(vid)) { continue; } float h = distances[vid]; // [RMS] there are different options here... h = 2 * (float)Math.Sqrt(h); float offset = h; Vector3d d = mesh.GetVertex(vid); mesh.SetVertex(vid, d + (Vector3d)(offset * normal)); } DMesh3 compacted = new DMesh3(); var compactInfo = compacted.CompactCopy(mesh); IndexUtil.Apply(local_maxima, compactInfo.MapV); mesh = compacted; MeshVertexSelection boundary_sel = new MeshVertexSelection(mesh); HashSet <int> boundaryV = new HashSet <int>(MeshIterators.BoundaryVertices(mesh)); boundary_sel.Select(boundaryV); boundary_sel.ExpandToOneRingNeighbours(); LaplacianMeshSmoother smoother = new LaplacianMeshSmoother(mesh); foreach (int vid in boundary_sel) { if (boundaryV.Contains(vid)) { smoother.SetConstraint(vid, mesh.GetVertex(vid), 100.0f, true); } else { smoother.SetConstraint(vid, mesh.GetVertex(vid), 10.0f, false); } } foreach (int vid in local_maxima) { smoother.SetConstraint(vid, mesh.GetVertex(vid), 50, false); } bool ok = smoother.SolveAndUpdateMesh(); Util.gDevAssert(ok); List <int> intVerts = new List <int>(MeshIterators.InteriorVertices(mesh)); MeshIterativeSmooth smooth = new MeshIterativeSmooth(mesh, intVerts.ToArray(), true); smooth.SmoothType = MeshIterativeSmooth.SmoothTypes.Cotan; smooth.Rounds = 10; smooth.Alpha = 0.1f; smooth.Smooth(); return(mesh); }