// (sequentially) find each triangle that path point lies in, and insert a vertex for // that point into mesh. void insert_corners(HashSet <int> MeshVertsOnCurve) { PrimalQuery2d query = new PrimalQuery2d(PointF); if (UseTriSpatial) { int count = Mesh.TriangleCount + Curve.VertexCount; int bins = 32; if (count < 25) { bins = 8; } else if (count < 100) { bins = 16; } AxisAlignedBox3d bounds3 = Mesh.CachedBounds; AxisAlignedBox2d bounds2 = new AxisAlignedBox2d(bounds3.Min.xy, bounds3.Max.xy); triSpatial = new TriangleBinsGrid2d(bounds2, bins); foreach (int tid in Mesh.TriangleIndices()) { spatial_add_triangle(tid); } } Func <int, Vector2d, bool> inTriangleF = (tid, pos) => { Index3i tv = Mesh.GetTriangle(tid); int query_result = query.ToTriangleUnsigned(pos, tv.a, tv.b, tv.c); return(query_result == -1 || query_result == 0); }; CurveVertices = new int[Curve.VertexCount]; for (int i = 0; i < Curve.VertexCount; ++i) { Vector2d vInsert = Curve[i]; bool inserted = false; int contain_tid = DMesh3.InvalidID; if (triSpatial != null) { contain_tid = triSpatial.FindContainingTriangle(vInsert, inTriangleF); } else { foreach (int tid in Mesh.TriangleIndices()) { Index3i tv = Mesh.GetTriangle(tid); // [RMS] using unsigned query here because we do not need to care about tri CW/CCW orientation // (right? otherwise we have to explicitly invert mesh. Nothing else we do depends on tri orientation) //int query_result = query.ToTriangle(vInsert, tv.a, tv.b, tv.c); int query_result = query.ToTriangleUnsigned(vInsert, tv.a, tv.b, tv.c); if (query_result == -1 || query_result == 0) { contain_tid = tid; break; } } } if (contain_tid != DMesh3.InvalidID) { Index3i tv = Mesh.GetTriangle(contain_tid); Vector3d bary = MathUtil.BarycentricCoords(vInsert, PointF(tv.a), PointF(tv.b), PointF(tv.c)); // SpatialEpsilon is our zero-tolerance, so merge if we are closer than that bool is_existing_v; int vid = insert_corner_from_bary(i, contain_tid, bary, 0.01, 100 * SpatialEpsilon, out is_existing_v); if (vid > 0) // this should be always happening.. { CurveVertices[i] = vid; if (is_existing_v) { MeshVertsOnCurve.Add(vid); } inserted = true; } else { throw new Exception("MeshInsertUVPolyCurve.insert_corners: failed to insert vertex " + i.ToString()); } } if (inserted == false) { throw new Exception("MeshInsertUVPolyCurve.insert_corners: curve vertex " + i.ToString() + " is not inside or on any mesh triangle!"); } } }
// (sequentially) find each triangle that path point lies in, and insert a vertex for // that point into mesh. void insert_corners(HashSet <int> MeshVertsOnCurve) { PrimalQuery2d query = new PrimalQuery2d(PointF); if (UseTriSpatial) { int count = Mesh.TriangleCount + Curve.VertexCount; int bins = 32; if (count < 25) { bins = 8; } else if (count < 100) { bins = 16; } AxisAlignedBox3d bounds3 = Mesh.CachedBounds; AxisAlignedBox2d bounds2 = new AxisAlignedBox2d(bounds3.Min.xy, bounds3.Max.xy); triSpatial = new TriangleBinsGrid2d(bounds2, bins); foreach (int tid in Mesh.TriangleIndices()) { spatial_add_triangle(tid); } } Func <int, Vector2d, bool> inTriangleF = (tid, pos) => { Index3i tv = Mesh.GetTriangle(tid); int query_result = query.ToTriangleUnsigned(pos, tv.a, tv.b, tv.c); return(query_result == -1 || query_result == 0); }; CurveVertices = new int[Curve.VertexCount]; for (int i = 0; i < Curve.VertexCount; ++i) { Vector2d vInsert = Curve[i]; bool inserted = false; // find the triangle that contains this curve point int contain_tid = DMesh3.InvalidID; if (triSpatial != null) { contain_tid = triSpatial.FindContainingTriangle(vInsert, inTriangleF); } else { foreach (int tid in Mesh.TriangleIndices()) { Index3i tv = Mesh.GetTriangle(tid); // [RMS] using unsigned query here because we do not need to care about tri CW/CCW orientation // (right? otherwise we have to explicitly invert mesh. Nothing else we do depends on tri orientation) //int query_result = query.ToTriangle(vInsert, tv.a, tv.b, tv.c); int query_result = query.ToTriangleUnsigned(vInsert, tv.a, tv.b, tv.c); if (query_result == -1 || query_result == 0) { contain_tid = tid; break; } } } // if we found one, insert the point via face-poke or edge-split, // unless it is exactly at existing vertex, in which case we can re-use it if (contain_tid != DMesh3.InvalidID) { Index3i tv = Mesh.GetTriangle(contain_tid); Vector3d bary = MathUtil.BarycentricCoords(vInsert, PointF(tv.a), PointF(tv.b), PointF(tv.c)); // SpatialEpsilon is our zero-tolerance, so merge if we are closer than that bool is_existing_v; int vid = insert_corner_from_bary(i, contain_tid, bary, 0.01, 100 * SpatialEpsilon, out is_existing_v); if (vid > 0) { CurveVertices[i] = vid; if (is_existing_v) { MeshVertsOnCurve.Add(vid); } inserted = true; } } // if we did not find containing triangle, // try matching with any existing vertices. // This can happen if curve point is right on mesh border... if (inserted == false) { foreach (int vid in Mesh.VertexIndices()) { Vector2d v = PointF(vid); if (vInsert.Distance(v) < SpatialEpsilon) { CurveVertices[i] = vid; MeshVertsOnCurve.Add(vid); inserted = true; } } } // TODO: also case where curve point is right on mesh border edge, // and so it ends up being outside all triangles? if (inserted == false) { throw new Exception("MeshInsertUVPolyCurve.insert_corners: curve vertex " + i.ToString() + " is not inside or on any mesh triangle!"); } } }