public bool Insert() { Func <int, bool> is_contained_v = (vid) => { Vector3d v = Mesh.GetVertex(vid); Vector2f vf2 = ProjectFrame.ToPlaneUV((Vector3f)v, 2); return(Polygon.Contains(vf2)); }; MeshVertexSelection vertexROI = new MeshVertexSelection(Mesh); Index3i seedT = Mesh.GetTriangle(SeedTriangle); // if a seed vert of seed triangle is containd in polygon, we will // flood-fill out from there, this gives a better ROI. // If not, we will try flood-fill from the seed triangles. List <int> seed_verts = new List <int>(); for (int j = 0; j < 3; ++j) { if (is_contained_v(seedT[j])) { seed_verts.Add(seedT[j]); } } if (seed_verts.Count == 0) { seed_verts.Add(seedT.a); seed_verts.Add(seedT.b); seed_verts.Add(seedT.c); } // flood-fill out from seed vertices until we have found all vertices // contained in polygon vertexROI.FloodFill(seed_verts.ToArray(), is_contained_v); // convert vertex ROI to face ROI MeshFaceSelection faceROI = new MeshFaceSelection(Mesh, vertexROI, 1); faceROI.ExpandToOneRingNeighbours(); faceROI.FillEars(true); // this might be a good idea... // construct submesh RegionOperator regionOp = new RegionOperator(Mesh, faceROI); DSubmesh3 roiSubmesh = regionOp.Region; DMesh3 roiMesh = roiSubmesh.SubMesh; // save 3D positions of unmodified mesh Vector3d[] initialPositions = new Vector3d[roiMesh.MaxVertexID]; // map roi mesh to plane MeshTransforms.PerVertexTransform(roiMesh, roiMesh.VertexIndices(), (v, vid) => { Vector2f uv = ProjectFrame.ToPlaneUV((Vector3f)v, 2); initialPositions[vid] = v; return(new Vector3d(uv.x, uv.y, 0)); }); // save a copy of 2D mesh and construct bvtree. we will use // this later to project back to 3d // [TODO] can we use a better spatial DS here, that takes advantage of 2D? DMesh3 projectMesh = new DMesh3(roiMesh); DMeshAABBTree3 projecter = new DMeshAABBTree3(projectMesh, true); MeshInsertUVPolyCurve insertUV = new MeshInsertUVPolyCurve(roiMesh, Polygon); //insertUV.Validate() bool bOK = insertUV.Apply(); if (!bOK) { throw new Exception("insertUV.Apply() failed"); } if (SimplifyInsertion) { insertUV.Simplify(); } int[] insertedPolyVerts = insertUV.CurveVertices; // grab inserted loop, assuming it worked EdgeLoop insertedLoop = null; if (insertUV.Loops.Count == 1) { insertedLoop = insertUV.Loops[0]; } // find interior triangles List <int> interiorT = new List <int>(); foreach (int tid in roiMesh.TriangleIndices()) { Vector3d centroid = roiMesh.GetTriCentroid(tid); if (Polygon.Contains(centroid.xy)) { interiorT.Add(tid); } } if (RemovePolygonInterior) { MeshEditor editor = new MeshEditor(roiMesh); editor.RemoveTriangles(interiorT, true); InteriorTriangles = null; } else { InteriorTriangles = interiorT.ToArray(); } // map back to 3d Vector3d a = Vector3d.Zero, b = Vector3d.Zero, c = Vector3d.Zero; foreach (int vid in roiMesh.VertexIndices()) { // [TODO] somehow re-use exact positions from regionOp maps? // construct new 3D pos w/ barycentric interpolation Vector3d v = roiMesh.GetVertex(vid); int tid = projecter.FindNearestTriangle(v); Index3i tri = projectMesh.GetTriangle(tid); projectMesh.GetTriVertices(tid, ref a, ref b, ref c); Vector3d bary = MathUtil.BarycentricCoords(ref v, ref a, ref b, ref c); Vector3d pos = bary.x * initialPositions[tri.a] + bary.y * initialPositions[tri.b] + bary.z * initialPositions[tri.c]; roiMesh.SetVertex(vid, pos); } bOK = BackPropagate(regionOp, insertedPolyVerts, insertedLoop); return(bOK); }