int[] get_tri_order_by_axis_sort() { int i = 0; int[] tri_order = new int[mesh.TriangleCount]; int nT = mesh.MaxTriangleID; for (int ti = 0; ti < nT; ++ti) { if (mesh.IsTriangle(ti)) { tri_order[i++] = ti; } } // precompute triangle centroids - wildly expensive to // do it inline in sort (!) I guess O(N) vs O(N log N) Vector3d[] centroids = new Vector3d[mesh.MaxTriangleID]; gParallel.ForEach(mesh.TriangleIndices(), (ti) => { if (mesh.IsTriangle(ti)) { centroids[ti] = mesh.GetTriCentroid(ti); } }); Array.Sort(tri_order, (t0, t1) => { double f0 = centroids[t0].x; double f1 = centroids[t1].x; return((f0 == f1) ? 0 : (f0 < f1) ? -1 : 1); }); return(tri_order); }
public void Select(int tid) { Debug.Assert(Mesh.IsTriangle(tid)); if (Mesh.IsTriangle(tid)) { add(tid); } }
public void InitializeFromExisting(DMesh3 mesh, IEnumerable <int> added_v, IEnumerable <int> added_t) { initialize_buffers(mesh); bool has_groups = mesh.HasTriangleGroups; if (added_v != null) { foreach (int vid in added_v) { Util.gDevAssert(mesh.IsVertex(vid)); append_vertex(mesh, vid); } } foreach (int tid in added_t) { Util.gDevAssert(mesh.IsTriangle(tid)); Index3i tv = mesh.GetTriangle(tid); Index4i tri = new Index4i(tv.a, tv.b, tv.c, has_groups ? mesh.GetTriangleGroup(tid) : DMesh3.InvalidID); AddedT.Add(tid); Triangles.Add(tri); } }
public void Initialize(DMesh3 mesh, IEnumerable <int> triangles) { initialize_buffers(mesh); bool has_groups = mesh.HasTriangleGroups; foreach (int tid in triangles) { if (!mesh.IsTriangle(tid)) { continue; } Index3i tv = mesh.GetTriangle(tid); bool va = save_vertex(mesh, tv.a); bool vb = save_vertex(mesh, tv.b); bool vc = save_vertex(mesh, tv.c); Index4i tri = new Index4i(tv.a, tv.b, tv.c, has_groups ? mesh.GetTriangleGroup(tid) : DMesh3.InvalidID); RemovedT.Add(tid); Triangles.Add(tri); MeshResult result = mesh.RemoveTriangle(tid, true, false); if (result != MeshResult.Ok) { throw new Exception("RemoveTrianglesMeshChange.Initialize: exception in RemoveTriangle(" + tid.ToString() + "): " + result.ToString()); } Util.gDevAssert(mesh.IsVertex(tv.a) == va && mesh.IsVertex(tv.b) == vb && mesh.IsVertex(tv.c) == vc); } }
// [RMS] estimate can be zero void compute(IEnumerable <int> triangles, int tri_count_est) { int est_verts = tri_count_est / 2; SubMesh = new DMesh3(BaseMesh.Components & WantComponents); BaseSubmeshV = new IndexFlagSet(BaseMesh.MaxVertexID, est_verts); BaseToSubV = new IndexMap(BaseMesh.MaxVertexID, est_verts); SubToBaseV = new DVector <int>(); if (ComputeTriMaps) { BaseToSubT = new IndexMap(BaseMesh.MaxTriangleID, tri_count_est); SubToBaseT = new DVector <int>(); } foreach (int tid in triangles) { if (!BaseMesh.IsTriangle(tid)) { throw new Exception("DSubmesh3.compute: triangle " + tid + " does not exist in BaseMesh!"); } Index3i base_t = BaseMesh.GetTriangle(tid); Index3i new_t = Index3i.Zero; int gid = BaseMesh.GetTriangleGroup(tid); for (int j = 0; j < 3; ++j) { int base_v = base_t[j]; int sub_v = -1; if (BaseSubmeshV[base_v] == false) { sub_v = SubMesh.AppendVertex(BaseMesh, base_v); BaseSubmeshV[base_v] = true; BaseToSubV[base_v] = sub_v; SubToBaseV.insert(base_v, sub_v); } else { sub_v = BaseToSubV[base_v]; } new_t[j] = sub_v; } if (OverrideGroupID >= 0) { gid = OverrideGroupID; } int sub_tid = SubMesh.AppendTriangle(new_t, gid); if (ComputeTriMaps) { BaseToSubT[tid] = sub_tid; SubToBaseT.insert(tid, sub_tid); } } }
// dictionary pairs are [group_id, tri_count] public static Dictionary <int, int> CountAllGroups(DMesh3 mesh) { Dictionary <int, int> GroupCounts = new Dictionary <int, int>(); if (mesh.HasTriangleGroups) { int NT = mesh.MaxTriangleID; for (int tid = 0; tid < NT; ++tid) { if (mesh.IsTriangle(tid)) { int gid = mesh.GetTriangleGroup(tid); if (GroupCounts.ContainsKey(gid) == false) { GroupCounts[gid] = 1; } else { GroupCounts[gid]++; } } } } return(GroupCounts); }
// [TODO] cannot back-out this operation right now // // Remove list of triangles. Values of triangles[] set to InvalidID are ignored. public bool RemoveTriangles(IEnumerable <int> triangles, bool bRemoveIsolatedVerts) { bool bAllOK = true; foreach (int tid in triangles) { if (!Mesh.IsTriangle(tid)) { bAllOK = false; continue; } MeshResult result = Mesh.RemoveTriangle(tid, bRemoveIsolatedVerts, false); if (result != MeshResult.Ok) { bAllOK = false; } } return(bAllOK); }
/// <summary> /// Get barycentric coords of point in triangle /// </summary> public static Vector3d BaryCoords(DMesh3 mesh, int tID, Vector3d point) { if (!mesh.IsTriangle(tID)) { throw new Exception("MeshQueries.SurfaceFrame: triangle " + tID + " does not exist!"); } Triangle3d tri = new Triangle3d(); mesh.GetTriVertices(tID, ref tri.V0, ref tri.V1, ref tri.V2); return(tri.BarycentricCoords(point)); }
/// <summary> /// collect triangles by group id. Returns array of triangle lists (stored as arrays). /// This requires 2 passes over mesh, but each pass is linear /// </summary> public static int[][] FindTriangleSetsByGroup(DMesh3 mesh, int ignoreGID = int.MinValue) { if (!mesh.HasTriangleGroups) { return(new int[0][]); } // find # of groups and triangle count for each SparseList <int> counts = CountAllGroups(mesh); List <int> GroupIDs = new List <int>(); foreach (var idxval in counts.Values()) { if (idxval.Key != ignoreGID && idxval.Value > 0) { GroupIDs.Add(idxval.Key); } } GroupIDs.Sort(); // might as well sort ascending... SparseList <int> groupMap = new SparseList <int>(mesh.MaxGroupID, GroupIDs.Count, -1); // allocate sets int[][] sets = new int[GroupIDs.Count][]; int[] counters = new int[GroupIDs.Count]; for (int i = 0; i < GroupIDs.Count; ++i) { int gid = GroupIDs[i]; sets[i] = new int[counts[gid]]; counters[i] = 0; groupMap[gid] = i; } // accumulate triangles int NT = mesh.MaxTriangleID; for (int tid = 0; tid < NT; ++tid) { if (mesh.IsTriangle(tid)) { int gid = mesh.GetTriangleGroup(tid); int i = groupMap[gid]; if (i >= 0) { int k = counters[i]++; sets[i][k] = tid; } } } return(sets); }
/// <summary> /// convenience function to construct a IntrRay3Triangle3 object for a mesh triangle /// </summary> public static IntrRay3Triangle3 TriangleIntersection(DMesh3 mesh, int ti, Ray3d ray) { if (!mesh.IsTriangle(ti)) { return(null); } Triangle3d tri = new Triangle3d(); mesh.GetTriVertices(ti, ref tri.V0, ref tri.V1, ref tri.V2); IntrRay3Triangle3 q = new IntrRay3Triangle3(ray, tri); q.Find(); return(q); }
/// <summary> /// construct a DistPoint3Triangle3 object for a mesh triangle /// </summary> public static DistPoint3Triangle3 TriangleDistance(DMesh3 mesh, int ti, Vector3d point) { if (!mesh.IsTriangle(ti)) { return(null); } Triangle3d tri = new Triangle3d(); mesh.GetTriVertices(ti, ref tri.V0, ref tri.V1, ref tri.V2); DistPoint3Triangle3 q = new DistPoint3Triangle3(point, tri); q.GetSquared(); return(q); }
/// <summary> /// shortcut to construct graph for mesh triangles /// </summary> public static DijkstraGraphDistance MeshTriangles(DMesh3 mesh, bool bSparse = false) { Func <int, int, float> tri_dist_f = (a, b) => { return((float)mesh.GetTriCentroid(a).Distance(mesh.GetTriCentroid(b))); }; return((bSparse) ? new DijkstraGraphDistance(mesh.MaxTriangleID, true, (id) => { return mesh.IsTriangle(id); }, tri_dist_f, mesh.TriTrianglesItr, null) : new DijkstraGraphDistance(mesh.MaxTriangleID, false, (id) => { return true; }, tri_dist_f, mesh.TriTrianglesItr, null)); }
public static IEnumerable <int> FilteredTriangles(DMesh3 mesh, Func <DMesh3, int, bool> FilterF) { int N = mesh.MaxTriangleID; for (int i = 0; i < N; ++i) { if (mesh.IsTriangle(i)) { if (FilterF(mesh, i)) { yield return(i); } } } }
/// <summary> /// find the set of group ids used in mesh /// </summary> public static HashSet <int> FindAllGroups(DMesh3 mesh) { HashSet <int> Groups = new HashSet <int>(); if (mesh.HasTriangleGroups) { int NT = mesh.MaxTriangleID; for (int tid = 0; tid < NT; ++tid) { if (mesh.IsTriangle(tid)) { int gid = mesh.GetTriangleGroup(tid); Groups.Add(gid); } } } return(Groups); }
/// <summary> /// count number of tris in each group in mesh /// returned pairs are [group_id, tri_count] /// </summary> public static SparseList <int> CountAllGroups(DMesh3 mesh) { SparseList <int> GroupCounts = new SparseList <int>(mesh.MaxGroupID, 0, 0); if (mesh.HasTriangleGroups) { int NT = mesh.MaxTriangleID; for (int tid = 0; tid < NT; ++tid) { if (mesh.IsTriangle(tid)) { int gid = mesh.GetTriangleGroup(tid); GroupCounts[gid] = GroupCounts[gid] + 1; } } } return(GroupCounts); }
public void InitializeFromExisting(DMesh3 mesh, IEnumerable <int> remove_t) { initialize_buffers(mesh); bool has_groups = mesh.HasTriangleGroups; HashSet <int> triangles = new HashSet <int>(remove_t); HashSet <int> vertices = new HashSet <int>(); IndexUtil.TrianglesToVertices(mesh, remove_t, vertices); List <int> save_v = new List <int>(); foreach (int vid in vertices) { bool all_contained = true; foreach (int tid in mesh.VtxTrianglesItr(vid)) { if (triangles.Contains(tid) == false) { all_contained = false; break; } } if (all_contained) { save_v.Add(vid); } } foreach (int vid in save_v) { save_vertex(mesh, vid, true); } foreach (int tid in remove_t) { Util.gDevAssert(mesh.IsTriangle(tid)); Index3i tv = mesh.GetTriangle(tid); Index4i tri = new Index4i(tv.a, tv.b, tv.c, has_groups ? mesh.GetTriangleGroup(tid) : DMesh3.InvalidID); RemovedT.Add(tid); Triangles.Add(tri); } }
// Returns array of triangle lists (stored as arrays) // This requires 2 passes over mesh, but each pass is linear public static int[][] FindTriangleSetsByGroup(DMesh3 mesh) { if (!mesh.HasTriangleGroups) { return(new int[0][]); } // find # of groups and triangle count for each Dictionary <int, int> counts = CountAllGroups(mesh); List <int> GroupIDs = new List <int>(counts.Keys); GroupIDs.Sort(); // might as well sort ascending... Dictionary <int, int> groupMap = new Dictionary <int, int>(); // allocate sets int[][] sets = new int[GroupIDs.Count][]; int[] counters = new int[GroupIDs.Count]; for (int i = 0; i < GroupIDs.Count; ++i) { int gid = GroupIDs[i]; sets[i] = new int[counts[gid]]; counters[i] = 0; groupMap[gid] = i; } // accumulate triangles int NT = mesh.MaxTriangleID; for (int tid = 0; tid < NT; ++tid) { if (mesh.IsTriangle(tid)) { int gid = mesh.GetTriangleGroup(tid); int i = groupMap[gid]; int k = counters[i]++; sets[i][k] = tid; } } return(sets); }
/// <summary> /// convenience function to construct a DistTriangle3Triangle3 object for two mesh triangles /// </summary> public static DistTriangle3Triangle3 TrianglesDistance(DMesh3 mesh1, int ti, DMesh3 mesh2, int tj, Func <Vector3d, Vector3d> TransformF = null) { if (mesh1.IsTriangle(ti) == false || mesh2.IsTriangle(tj) == false) { return(null); } Triangle3d tri1 = new Triangle3d(), tri2 = new Triangle3d(); mesh1.GetTriVertices(ti, ref tri1.V0, ref tri1.V1, ref tri1.V2); mesh2.GetTriVertices(tj, ref tri2.V0, ref tri2.V1, ref tri2.V2); if (TransformF != null) { tri2.V0 = TransformF(tri2.V0); tri2.V1 = TransformF(tri2.V1); tri2.V2 = TransformF(tri2.V2); } DistTriangle3Triangle3 dist = new DistTriangle3Triangle3(tri1, tri2); dist.GetSquared(); return(dist); }
/// <summary> /// convenience function to construct a IntrTriangle3Triangle3 object for two mesh triangles /// </summary> public static IntrTriangle3Triangle3 TrianglesIntersection(DMesh3 mesh1, int ti, DMesh3 mesh2, int tj, Func <Vector3d, Vector3d> TransformF = null) { if (mesh1.IsTriangle(ti) == false || mesh2.IsTriangle(tj) == false) { return(null); } Triangle3d tri1 = new Triangle3d(), tri2 = new Triangle3d(); mesh1.GetTriVertices(ti, ref tri1.V0, ref tri1.V1, ref tri1.V2); mesh2.GetTriVertices(tj, ref tri2.V0, ref tri2.V1, ref tri2.V2); if (TransformF != null) { tri2.V0 = TransformF(tri2.V0); tri2.V1 = TransformF(tri2.V1); tri2.V2 = TransformF(tri2.V2); } IntrTriangle3Triangle3 intr = new IntrTriangle3Triangle3(tri1, tri2); intr.Find(); return(intr); }
/// <summary> /// replace group id in mesh /// </summary> public static void SetGroupToGroup(DMesh3 mesh, int from, int to) { if (mesh.HasTriangleGroups == false) { return; } int NT = mesh.MaxTriangleID; for (int tid = 0; tid < NT; ++tid) { if (mesh.IsTriangle(tid)) { int gid = mesh.GetTriangleGroup(tid); if (gid == from) { mesh.SetTriangleGroup(tid, to); } } } }
/// <summary> /// Get point-normal frame on surface of mesh. Assumption is that point lies in tID. /// returns interpolated vertex-normal frame if available, otherwise tri-normal frame. /// </summary> public static Frame3f SurfaceFrame(DMesh3 mesh, int tID, Vector3d point) { if (!mesh.IsTriangle(tID)) { throw new Exception("MeshQueries.SurfaceFrame: triangle " + tID + " does not exist!"); } Triangle3d tri = new Triangle3d(); mesh.GetTriVertices(tID, ref tri.V0, ref tri.V1, ref tri.V2); Vector3d bary = tri.BarycentricCoords(point); point = tri.PointAt(bary); if (mesh.HasVertexNormals) { Vector3d normal = mesh.GetTriBaryNormal(tID, bary.x, bary.y, bary.z); return(new Frame3f(point, normal)); } else { return(new Frame3f(point, mesh.GetTriNormal(tID))); } }
protected virtual void InitializeVertexQuadrics() { int NT = mesh.MaxTriangleID; QuadricError[] triQuadrics = new QuadricError[NT]; double[] triAreas = new double[NT]; gParallel.BlockStartEnd(0, mesh.MaxTriangleID - 1, (start_tid, end_tid) => { Vector3d c, n; for (int tid = start_tid; tid <= end_tid; tid++) { if (mesh.IsTriangle(tid)) { mesh.GetTriInfo(tid, out n, out triAreas[tid], out c); triQuadrics[tid] = new QuadricError(ref n, ref c); } } }); int NV = mesh.MaxVertexID; vertQuadrics = new QuadricError[NV]; gParallel.BlockStartEnd(0, mesh.MaxVertexID - 1, (start_vid, end_vid) => { for (int vid = start_vid; vid <= end_vid; vid++) { vertQuadrics[vid] = QuadricError.Zero; if (mesh.IsVertex(vid)) { foreach (int tid in mesh.VtxTrianglesItr(vid)) { vertQuadrics[vid].Add(triAreas[tid], ref triQuadrics[tid]); } //Util.gDevAssert(MathUtil.EpsilonEqual(0, vertQuadrics[i].Evaluate(mesh.GetVertex(i)), MathUtil.Epsilon * 10)); } } }); }
int[] get_tri_order_by_axis_sort() { int i = 0; int[] tri_order = new int[mesh.TriangleCount]; int nT = mesh.MaxTriangleID; for (int ti = 0; ti < nT; ++ti) { if (mesh.IsTriangle(ti)) { tri_order[i++] = ti; } } Array.Sort(tri_order, (t0, t1) => { double f0 = mesh.GetTriCentroid(t0).x; double f1 = mesh.GetTriCentroid(t1).x; return((f0 == f1) ? 0 : (f0 < f1) ? -1 : 1); }); return(tri_order); }
/// <summary> /// Check if this m2 is the same as this mesh. By default only checks /// vertices and triangles, turn on other parameters w/ flags /// </summary> public bool IsSameMesh(DMesh3 m2, bool bCheckEdges = false, bool bCheckNormals = false, bool bCheckColors = false, bool bCheckUVs = false, bool bCheckGroups = false, float Epsilon = MathUtil.Epsilonf) { if (VertexCount != m2.VertexCount) { return(false); } if (TriangleCount != m2.TriangleCount) { return(false); } foreach (int vid in VertexIndices()) { if (m2.IsVertex(vid) == false || GetVertex(vid).EpsilonEqual(m2.GetVertex(vid), Epsilon) == false) { return(false); } } foreach (int tid in TriangleIndices()) { if (m2.IsTriangle(tid) == false || GetTriangle(tid).Equals(m2.GetTriangle(tid)) == false) { return(false); } } if (bCheckEdges) { if (EdgeCount != m2.EdgeCount) { return(false); } foreach (int eid in EdgeIndices()) { if (m2.IsEdge(eid) == false || GetEdge(eid).Equals(m2.GetEdge(eid)) == false) { return(false); } } } if (bCheckNormals) { if (HasVertexNormals != m2.HasVertexNormals) { return(false); } if (HasVertexNormals) { foreach (int vid in VertexIndices()) { if (GetVertexNormal(vid).EpsilonEqual(m2.GetVertexNormal(vid), Epsilon) == false) { return(false); } } } } if (bCheckColors) { if (HasVertexColors != m2.HasVertexColors) { return(false); } if (HasVertexColors) { foreach (int vid in VertexIndices()) { if (GetVertexColor(vid).EpsilonEqual(m2.GetVertexColor(vid), Epsilon) == false) { return(false); } } } } if (bCheckUVs) { if (HasVertexUVs != m2.HasVertexUVs) { return(false); } if (HasVertexUVs) { foreach (int vid in VertexIndices()) { if (GetVertexUV(vid).EpsilonEqual(m2.GetVertexUV(vid), Epsilon) == false) { return(false); } } } } if (bCheckGroups) { if (HasTriangleGroups != m2.HasTriangleGroups) { return(false); } if (HasTriangleGroups) { foreach (int tid in TriangleIndices()) { if (GetTriangleGroup(tid) != m2.GetTriangleGroup(tid)) { return(false); } } } } return(true); }
// Assumption here is that Submesh has been modified, but boundary loop has // been preserved, and that old submesh has already been removed from this mesh. // So, we just have to append new vertices and then rewrite triangles // If new_tris or new_verts is non-null, we will return this info. // new_tris should be set to TriangleCount (ie it is not necessarily a map) // For new_verts, if we used an existing bdry vtx instead, we set the value to -(existing_index+1), // otherwise the value is new_index (+1 is to handle 0) // // Returns true if submesh successfully inserted, false if any triangles failed // (which happens if triangle would result in non-manifold mesh) public bool ReinsertSubmesh(DSubmesh3 sub, ref int[] new_tris, out IndexMap SubToNewV) { if (sub.BaseBorderV == null) { throw new Exception("MeshEditor.ReinsertSubmesh: Submesh does not have required boundary info. Call ComputeBoundaryInfo()!"); } DMesh3 submesh = sub.SubMesh; bool bAllOK = true; IndexFlagSet done_v = new IndexFlagSet(submesh.MaxVertexID, submesh.TriangleCount / 2); SubToNewV = new IndexMap(submesh.MaxVertexID, submesh.VertexCount); int nti = 0; int NT = submesh.MaxTriangleID; for (int ti = 0; ti < NT; ++ti) { if (submesh.IsTriangle(ti) == false) { continue; } Index3i sub_t = submesh.GetTriangle(ti); int gid = submesh.GetTriangleGroup(ti); Index3i new_t = Index3i.Zero; for (int j = 0; j < 3; ++j) { int sub_v = sub_t[j]; int new_v = -1; if (done_v[sub_v] == false) { // first check if this is a boundary vtx on submesh and maps to a bdry vtx on base mesh if (submesh.vertex_is_boundary(sub_v)) { int base_v = (sub_v < sub.SubToBaseV.size) ? sub.SubToBaseV[sub_v] : -1; if (base_v >= 0 && Mesh.IsVertex(base_v) && sub.BaseBorderV[base_v] == true) { // [RMS] this should always be true, but assert in tests to find out Debug.Assert(Mesh.vertex_is_boundary(base_v)); if (Mesh.vertex_is_boundary(base_v)) { new_v = base_v; } } } // if that didn't happen, append new vtx if (new_v == -1) { new_v = Mesh.AppendVertex(submesh, sub_v); } SubToNewV[sub_v] = new_v; done_v[sub_v] = true; } else { new_v = SubToNewV[sub_v]; } new_t[j] = new_v; } Debug.Assert(Mesh.FindTriangle(new_t.a, new_t.b, new_t.c) == DMesh3.InvalidID); int new_tid = Mesh.AppendTriangle(new_t, gid); Debug.Assert(new_tid != DMesh3.InvalidID && new_tid != DMesh3.NonManifoldID); if (!Mesh.IsTriangle(new_tid)) { bAllOK = false; } if (new_tris != null) { new_tris[nti++] = new_tid; } } return(bAllOK); }
/// <summary> /// Check if this m2 is the same as this mesh. By default only checks /// vertices and triangles, turn on other parameters w/ flags /// </summary> public bool IsSameMesh(DMesh3 m2, bool bCheckConnectivity, bool bCheckEdgeIDs = false, bool bCheckNormals = false, bool bCheckColors = false, bool bCheckUVs = false, bool bCheckGroups = false, float Epsilon = MathUtil.Epsilonf) { if (VertexCount != m2.VertexCount) { return(false); } if (TriangleCount != m2.TriangleCount) { return(false); } foreach (int vid in VertexIndices()) { if (m2.IsVertex(vid) == false || GetVertex(vid).EpsilonEqual(m2.GetVertex(vid), Epsilon) == false) { return(false); } } foreach (int tid in TriangleIndices()) { if (m2.IsTriangle(tid) == false || GetTriangle(tid).Equals(m2.GetTriangle(tid)) == false) { return(false); } } if (bCheckConnectivity) { foreach (int eid in EdgeIndices()) { Index4i e = GetEdge(eid); int other_eid = m2.FindEdge(e.a, e.b); if (other_eid == InvalidID) { return(false); } Index4i oe = m2.GetEdge(other_eid); if (Math.Min(e.c, e.d) != Math.Min(oe.c, oe.d) || Math.Max(e.c, e.d) != Math.Max(oe.c, oe.d)) { return(false); } } } if (bCheckEdgeIDs) { if (EdgeCount != m2.EdgeCount) { return(false); } foreach (int eid in EdgeIndices()) { if (m2.IsEdge(eid) == false || GetEdge(eid).Equals(m2.GetEdge(eid)) == false) { return(false); } } } if (bCheckNormals) { if (HasVertexNormals != m2.HasVertexNormals) { return(false); } if (HasVertexNormals) { foreach (int vid in VertexIndices()) { if (GetVertexNormal(vid).EpsilonEqual(m2.GetVertexNormal(vid), Epsilon) == false) { return(false); } } } } if (bCheckColors) { if (HasVertexColors != m2.HasVertexColors) { return(false); } if (HasVertexColors) { foreach (int vid in VertexIndices()) { if (GetVertexColor(vid).EpsilonEqual(m2.GetVertexColor(vid), Epsilon) == false) { return(false); } } } } if (bCheckUVs) { if (HasVertexUVs != m2.HasVertexUVs) { return(false); } if (HasVertexUVs) { foreach (int vid in VertexIndices()) { if (GetVertexUV(vid).EpsilonEqual(m2.GetVertexUV(vid), Epsilon) == false) { return(false); } } } } if (bCheckGroups) { if (HasTriangleGroups != m2.HasTriangleGroups) { return(false); } if (HasTriangleGroups) { foreach (int tid in TriangleIndices()) { if (GetTriangleGroup(tid) != m2.GetTriangleGroup(tid)) { return(false); } } } } return(true); }
public void FindConnectedT() { Components = new List <Component>(); int NT = Mesh.MaxTriangleID; // [TODO] could use Euler formula to determine if mesh is closed genus-0... Func <int, bool> filter_func = (i) => { return(Mesh.IsTriangle(i)); }; if (FilterF != null) { filter_func = (i) => { return(Mesh.IsTriangle(i) && FilterF(i)); } } ; // initial active set contains all valid triangles byte[] active = new byte[Mesh.MaxTriangleID]; Interval1i activeRange = Interval1i.Empty; if (FilterSet != null) { for (int i = 0; i < NT; ++i) { active[i] = 255; } foreach (int tid in FilterSet) { bool bValid = filter_func(tid); if (bValid) { active[tid] = 0; activeRange.Contain(tid); } } } else { for (int i = 0; i < NT; ++i) { bool bValid = filter_func(i); if (bValid) { active[i] = 0; activeRange.Contain(i); } else { active[i] = 255; } } } // temporary buffers List <int> queue = new List <int>(NT / 10); List <int> cur_comp = new List <int>(NT / 10); // keep finding valid seed triangles and growing connected components // until we are done IEnumerable <int> range = (FilterSet != null) ? FilterSet : activeRange; foreach (int i in range) { //for ( int i = 0; i < NT; ++i ) { if (active[i] == 255) { continue; } int seed_t = i; if (SeedFilterF != null && SeedFilterF(seed_t) == false) { continue; } queue.Add(seed_t); active[seed_t] = 1; // in queue while (queue.Count > 0) { int cur_t = queue[queue.Count - 1]; queue.RemoveAt(queue.Count - 1); active[cur_t] = 2; // tri has been processed cur_comp.Add(cur_t); Index3i nbrs = Mesh.GetTriNeighbourTris(cur_t); for (int j = 0; j < 3; ++j) { int nbr_t = nbrs[j]; if (nbr_t != DMesh3.InvalidID && active[nbr_t] == 0) { queue.Add(nbr_t); active[nbr_t] = 1; // in queue } } } Component comp = new Component() { Indices = cur_comp.ToArray() }; Components.Add(comp); // remove tris in this component from active set for (int j = 0; j < comp.Indices.Length; ++j) { active[comp.Indices[j]] = 255; } cur_comp.Clear(); queue.Clear(); } }
public void FindConnectedT() { Components = new List <Component>(); int NT = Mesh.MaxTriangleID; // [TODO] could use Euler formula to determine if mesh is closed genus-0... // initial active set contains all triangles byte[] active = new byte[Mesh.MaxTriangleID]; for (int i = 0; i < NT; ++i) { if (Mesh.IsTriangle(i)) { active[i] = 0; } else { active[i] = 255; } } // temporary buffers List <int> queue = new List <int>(NT / 10); List <int> cur_comp = new List <int>(NT / 10); // keep finding valid seed triangles and growing connected components // until we are done for (int i = 0; i < NT; ++i) { if (active[i] == 255) { continue; } int seed_t = i; queue.Add(seed_t); active[seed_t] = 1; // in queue while (queue.Count > 0) { int cur_t = queue[queue.Count - 1]; queue.RemoveAt(queue.Count - 1); active[cur_t] = 2; // tri has been processed cur_comp.Add(cur_t); Index3i nbrs = Mesh.GetTriNeighbourTris(cur_t); for (int j = 0; j < 3; ++j) { int nbr_t = nbrs[j]; if (nbr_t != DMesh3.InvalidID && active[nbr_t] == 0) { queue.Add(nbr_t); active[nbr_t] = 1; // in queue } } } Component comp = new Component() { Indices = cur_comp.ToArray() }; Components.Add(comp); // remove tris in this component from active set for (int j = 0; j < comp.Indices.Length; ++j) { active[comp.Indices[j]] = 255; } cur_comp.Clear(); queue.Clear(); } }