/// <summary> /// figure out which vtx/edge the input vtx is on /// </summary> void update_from_split(SegmentVtx sv, Index2i splitEdges) { // check if within tolerance of existing vtx, because we did not // sort that out before... int existing_v = find_existing_vertex(sv.v); if (existing_v >= 0) { sv.type = 0; sv.elem_id = existing_v; sv.vtx_id = existing_v; VIDToSegVtxMap[sv.vtx_id] = sv; return; } for (int j = 0; j < 2; ++j) { if (is_on_edge(splitEdges[j], sv.v)) { sv.type = 1; sv.elem_id = splitEdges[j]; return; } } throw new Exception("update_from_split: unsortable vertex?"); }
public SegmentVtx this[int key] { get { return((key == 0) ? v0 : v1); } set { if (key == 0) { v0 = value; } else { v1 = value; } } }
/// <summary> /// For each on-face vtx, we poke the face, and re-sort /// the remaining vertices on that face onto new faces/edges /// </summary> void insert_face_vertices() { while (FaceVertices.Count > 0) { var pair = FaceVertices.First(); int tid = pair.Key; List <SegmentVtx> triVerts = pair.Value; SegmentVtx v = triVerts[triVerts.Count - 1]; triVerts.RemoveAt(triVerts.Count - 1); DMesh3.PokeTriangleInfo pokeInfo; MeshResult result = Target.PokeTriangle(tid, out pokeInfo); if (result != MeshResult.Ok) { throw new Exception("shit"); } int new_v = pokeInfo.new_vid; Target.SetVertex(new_v, v.v); v.vtx_id = new_v; VIDToSegVtxMap[v.vtx_id] = v; PointHash.InsertPoint(v.vtx_id, v.v); // remove this triangles vtx list because it is no longer valid FaceVertices.Remove(tid); // update remaining verts Index3i pokeEdges = pokeInfo.new_edges; var pokeTris = new Index3i(tid, pokeInfo.new_t1, pokeInfo.new_t2); foreach (SegmentVtx sv in triVerts) { update_from_poke(sv, pokeEdges, pokeTris); if (sv.type == 1) { add_edge_vtx(sv.elem_id, sv); } else if (sv.type == 2) { add_face_vtx(sv.elem_id, sv); } } // track poke subfaces add_poke_subfaces(tid, ref pokeInfo); } }
void add_face_vtx(int tid, SegmentVtx vtx) { List <SegmentVtx> l; if (FaceVertices.TryGetValue(tid, out l)) { l.Add(vtx); } else { l = new List <SegmentVtx>() { vtx }; FaceVertices[tid] = l; } }
void add_edge_vtx(int eid, SegmentVtx vtx) { List <SegmentVtx> l; if (EdgeVertices.TryGetValue(eid, out l)) { l.Add(vtx); } else { l = new List <SegmentVtx>() { vtx }; EdgeVertices[eid] = l; } }
/// <summary> /// for each on-edge vtx, we split the edge and then /// re-sort any of the vertices on that edge onto new edges /// </summary> void insert_edge_vertices() { while (EdgeVertices.Count > 0) { var pair = EdgeVertices.First(); int eid = pair.Key; List <SegmentVtx> edgeVerts = pair.Value; SegmentVtx v = edgeVerts[edgeVerts.Count - 1]; edgeVerts.RemoveAt(edgeVerts.Count - 1); Index2i splitTris = Target.GetEdgeT(eid); DMesh3.EdgeSplitInfo splitInfo; MeshResult result = Target.SplitEdge(eid, out splitInfo); if (result != MeshResult.Ok) { throw new Exception("insert_edge_vertices: split failed!"); } int new_v = splitInfo.vNew; var splitEdges = new Index2i(eid, splitInfo.eNewBN); Target.SetVertex(new_v, v.v); v.vtx_id = new_v; VIDToSegVtxMap[v.vtx_id] = v; PointHash.InsertPoint(v.vtx_id, v.v); // remove this triangles vtx list because it is no longer valid EdgeVertices.Remove(eid); // update remaining verts foreach (SegmentVtx sv in edgeVerts) { update_from_split(sv, splitEdges); if (sv.type == 1) { add_edge_vtx(sv.elem_id, sv); } } // track subfaces add_split_subfaces(splitTris, ref splitInfo); } }
/// <summary> /// figure out which vtx/edge/face the input vtx is on /// </summary> void update_from_poke(SegmentVtx sv, Index3i pokeEdges, Index3i pokeTris) { // check if within tolerance of existing vtx, because we did not // sort that out before... int existing_v = find_existing_vertex(sv.v); if (existing_v >= 0) { sv.type = 0; sv.elem_id = existing_v; sv.vtx_id = existing_v; VIDToSegVtxMap[sv.vtx_id] = sv; return; } for (int j = 0; j < 3; ++j) { if (is_on_edge(pokeEdges[j], sv.v)) { sv.type = 1; sv.elem_id = pokeEdges[j]; return; } } // [TODO] should use PrimalQuery2d for this! for (int j = 0; j < 3; ++j) { if (is_in_triangle(pokeTris[j], sv.v)) { sv.type = 2; sv.elem_id = pokeTris[j]; return; } } System.Console.WriteLine("unsorted vertex!"); sv.elem_id = pokeTris.a; }
/// <summary> /// 1) Find intersection segments /// 2) sort onto existing input mesh vtx/edge/face /// </summary> void find_segments() { Dictionary <Vector3d, SegmentVtx> SegVtxMap = new Dictionary <Vector3d, SegmentVtx>(); // find intersection segments // TODO: intersection polygons // TODO: do we need to care about intersection vertices? DMeshAABBTree3 targetSpatial = new DMeshAABBTree3(Target, true); DMeshAABBTree3 cutSpatial = new DMeshAABBTree3(CutMesh, true); var intersections = targetSpatial.FindAllIntersections(cutSpatial); // for each segment, for each vtx, determine if it is // at an existing vertex, on-edge, or in-face Segments = new IntersectSegment[intersections.Segments.Count]; for (int i = 0; i < Segments.Length; ++i) { var isect = intersections.Segments[i]; Vector3dTuple2 points = new Vector3dTuple2(isect.point0, isect.point1); IntersectSegment iseg = new IntersectSegment() { base_tid = isect.t0 }; Segments[i] = iseg; for (int j = 0; j < 2; ++j) { Vector3d v = points[j]; // if this exact vtx coord has been seen, use same vtx SegmentVtx sv; if (SegVtxMap.TryGetValue(v, out sv)) { iseg[j] = sv; continue; } sv = new SegmentVtx() { v = v }; SegVertices.Add(sv); SegVtxMap[v] = sv; iseg[j] = sv; // this vtx is tol-equal to input mesh vtx int existing_v = find_existing_vertex(isect.point0); if (existing_v >= 0) { sv.initial_type = sv.type = 0; sv.elem_id = existing_v; sv.vtx_id = existing_v; VIDToSegVtxMap[sv.vtx_id] = sv; continue; } Triangle3d tri = new Triangle3d(); Target.GetTriVertices(isect.t0, ref tri.V0, ref tri.V1, ref tri.V2); Index3i tv = Target.GetTriangle(isect.t0); // this vtx is tol-on input mesh edge int on_edge_i = on_edge(ref tri, ref v); if (on_edge_i >= 0) { sv.initial_type = sv.type = 1; sv.elem_id = Target.FindEdge(tv[on_edge_i], tv[(on_edge_i + 1) % 3]); Util.gDevAssert(sv.elem_id != DMesh3.InvalidID); add_edge_vtx(sv.elem_id, sv); continue; } // otherwise contained in input mesh face sv.initial_type = sv.type = 2; sv.elem_id = isect.t0; add_face_vtx(sv.elem_id, sv); } } }