// convert vertex selection to face selection. Require at least minCount verts of // tri to be selected (valid values are 1,2,3) public MeshFaceSelection(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, MeshVertexSelection convertV, int minCount = 3) : this(mesh) { minCount = math.MathUtil.Clamp(minCount, 1, 3); foreach (int tid in mesh.TriangleIndices()) { Index3i tri = mesh.GetTriangle(tid); if (minCount == 1) { if (convertV.IsSelected(tri.a) || convertV.IsSelected(tri.b) || convertV.IsSelected(tri.c)) { Add(tid); } } else if (minCount == 3) { if (convertV.IsSelected(tri.a) && convertV.IsSelected(tri.b) && convertV.IsSelected(tri.c)) { Add(tid); } } else { int n = (convertV.IsSelected(tri.a) ? 1 : 0) + (convertV.IsSelected(tri.b) ? 1 : 0) + (convertV.IsSelected(tri.c) ? 1 : 0); if (n >= minCount) { Add(tid); } } } }
public MeshDecomposition(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, IMeshComponentManager manager) { MaxComponentSize = 62000; // max for unity is 64 this.mesh = mesh; this.Manager = manager; }
// t in range [0,1] public static Vector3D UniformSmooth(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int vID, double t) { Vector3D v = mesh.GetVertex(vID); Vector3D c = MeshWeights.OneRingCentroid(mesh, vID); return((1 - t) * v + (t) * c); }
public static void EdgeLengthStatsFromEdges(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, IEnumerable <int> EdgeItr, out double minEdgeLen, out double maxEdgeLen, out double avgEdgeLen, int samples = 0) { minEdgeLen = double.MaxValue; maxEdgeLen = double.MinValue; avgEdgeLen = 0; int avg_count = 0; int MaxID = mesh.MaxEdgeID; Vector3D a = Vector3D.Zero, b = Vector3D.Zero; foreach (int eid in EdgeItr) { if (mesh.IsEdge(eid)) { mesh.GetEdgeV(eid, ref a, ref b); double len = a.Distance(b); if (len < minEdgeLen) { minEdgeLen = len; } if (len > maxEdgeLen) { maxEdgeLen = len; } avgEdgeLen += len; avg_count++; } } ; avgEdgeLen /= (double)avg_count; }
// for all vertices in loopV, constrain to target // for all edges in loopV, disable flips and constrain to target public static void ConstrainVtxLoopTo(MeshConstraints cons, NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int[] loopV, IProjectionTarget target, int setID = -1) { VertexConstraint vc = new VertexConstraint(target); for (int i = 0; i < loopV.Length; ++i) { cons.SetOrUpdateVertexConstraint(loopV[i], vc); } EdgeConstraint ec = new EdgeConstraint(EdgeRefineFlags.NoFlip, target); ec.TrackingSetID = setID; for (int i = 0; i < loopV.Length; ++i) { int v0 = loopV[i]; int v1 = loopV[(i + 1) % loopV.Length]; int eid = mesh.FindEdge(v0, v1); Debug.Assert(eid != NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID); if (eid != NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID) { cons.SetOrUpdateEdgeConstraint(eid, ec); } } }
public static void QuickCompute(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh) { MeshNormals normals = new MeshNormals(mesh); normals.Compute(); normals.CopyTo(mesh); }
public MeshFaceSelection(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh) { Mesh = mesh; Selected = new HashSet <int>(); temp = new List <int>(); temp2 = new List <int>(); }
public EdgeLoopRemesher(NGonsCore.geometry3Sharp.mesh.DMesh3 m, EdgeLoop loop) : base(m) { UpdateLoop(loop); EnableFlips = false; CustomSmoothF = loop_smooth_vertex; }
public MeshIterativeSmooth(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int[] vertices, bool bOwnVertices = false) { Mesh = mesh; Vertices = (bOwnVertices) ? vertices : (int[])vertices.Clone(); SmoothedPostions = new Vector3D[Vertices.Length]; ProjectF = null; }
public static void MassProperties( NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, out double mass, out Vector3D center, out double[,] inertia3x3, bool bodyCoords = false) { MassProperties( mesh.Triangles(), (vID) => { return(mesh.GetVertex(vID)); }, out mass, out center, out inertia3x3, false); }
public EdgeLoop(EdgeLoop copy) { Mesh = copy.Mesh; Vertices = new int[copy.Vertices.Length]; Array.Copy(copy.Vertices, Vertices, Vertices.Length); Edges = new int[copy.Edges.Length]; Array.Copy(copy.Edges, Edges, Edges.Length); BowtieVertices = new int[copy.BowtieVertices.Length]; Array.Copy(copy.BowtieVertices, BowtieVertices, BowtieVertices.Length); }
public static void PreserveBoundaryLoops(MeshConstraints cons, NGonsCore.geometry3Sharp.mesh.DMesh3 mesh) { MeshBoundaryLoops loops = new MeshBoundaryLoops(mesh); foreach (EdgeLoop loop in loops) { DCurve3 loopC = MeshUtil.ExtractLoopV(mesh, loop.Vertices); DCurveProjectionTarget target = new DCurveProjectionTarget(loopC); ConstrainVtxLoopTo(cons, mesh, loop.Vertices, target); } }
public int AppendNewMesh(bool bHaveVtxNormals, bool bHaveVtxColors, bool bHaveVtxUVs, bool bHaveFaceGroups) { int index = Meshes.Count; NGonsCore.geometry3Sharp.mesh.DMesh3 m = new NGonsCore.geometry3Sharp.mesh.DMesh3(bHaveVtxNormals, bHaveVtxColors, bHaveVtxUVs, bHaveFaceGroups); Meshes.Add(m); MaterialAssignment.Add(-1); // no material is known Metadata.Add(new Dictionary <string, object>()); nActiveMesh = index; return(index); }
public static void SetGroupID(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, IEnumerable <int> triangles, int to) { if (mesh.HasTriangleGroups == false) { return; } foreach (int tid in triangles) { mesh.SetTriangleGroup(tid, to); } }
public static void SetGroupID(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int to) { if (mesh.HasTriangleGroups == false) { return; } foreach (int tid in mesh.TriangleIndices()) { mesh.SetTriangleGroup(tid, to); } }
public static void ScaleMesh(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, Frame3f f, Vector3F vScale) { foreach (int vid in mesh.VertexIndices()) { Vector3D v = mesh.GetVertex(vid); Vector3F vScaledInF = f.ToFrameP((Vector3F)v) * vScale; Vector3D vNew = f.FromFrameP(vScaledInF); mesh.SetVertex(vid, vNew); // TODO: normals } }
// Check if Loop2 is the same set of positions on another mesh. // Does not require the indexing to be the same // Currently doesn't handle loop-reversal public bool IsSameLoop(EdgeLoop Loop2, bool bReverse2 = false, double tolerance = math.MathUtil.ZeroTolerance) { // find a duplicate starting vertex int N = Vertices.Length; int N2 = Loop2.Vertices.Length; if (N != N2) { return(false); } NGonsCore.geometry3Sharp.mesh.DMesh3 Mesh2 = Loop2.Mesh; int start_i = 0, start_j = -1; // try to find a unique same-vertex on each loop. Do not // use vertices that have duplicate positions. bool bFoundGoodStart = false; while (!bFoundGoodStart && start_i < N) { Vector3D start_v = Mesh.GetVertex(start_i); int count = Loop2.CountWithinTolerance(start_v, tolerance, out start_j); if (count == 1) { bFoundGoodStart = true; } else { start_i++; } } if (!bFoundGoodStart) { return(false); // no within-tolerance duplicate vtx to start at } for (int ii = 0; ii < N; ++ii) { int i = (start_i + ii) % N; int j = (bReverse2) ? math.MathUtil.WrapSignedIndex(start_j - ii, N2) : (start_j + ii) % N2; Vector3D v = Mesh.GetVertex(Vertices[i]); Vector3D v2 = Mesh2.GetVertex(Loop2.Vertices[j]); if (v.Distance(v2) > tolerance) { return(false); } } return(true); }
public void AppendBox(Frame3f frame, float size) { TrivialBox3Generator boxgen = new TrivialBox3Generator() { Box = new Box3d(frame, size * 0.5 * Vector3D.One), NoSharedVertices = false }; boxgen.Generate(); NGonsCore.geometry3Sharp.mesh.DMesh3 mesh = new NGonsCore.geometry3Sharp.mesh.DMesh3(); boxgen.MakeMesh(mesh); AppendMesh(mesh, Mesh.AllocateTriangleGroup()); }
public static double OpeningAngleD(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int eid) { Index2i et = mesh.GetEdgeT(eid); if (et[1] == NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID) { return(double.MaxValue); // boundary edge!! } Vector3D n0 = mesh.GetTriNormal(et[0]); Vector3D n1 = mesh.GetTriNormal(et[1]); return(Vector3D.AngleD(n0, n1)); }
// utility function public static int[] VertexLoopToEdgeLoop(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int[] vertex_loop) { int NV = vertex_loop.Length; int[] edges = new int[NV]; for (int i = 0; i < NV; ++i) { int v0 = vertex_loop[i]; int v1 = vertex_loop[(i + 1) % NV]; edges[i] = mesh.FindEdge(v0, v1); } return(edges); }
// utility function public static int[] VerticesToEdges(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int[] vertex_span) { int NV = vertex_span.Length; int[] edges = new int[NV - 1]; for (int i = 0; i < NV - 1; ++i) { int v0 = vertex_span[i]; int v1 = vertex_span[(i + 1)]; edges[i] = mesh.FindEdge(v0, v1); } return(edges); }
// Returns array of triangle lists (stored as arrays) // This requires 2 passes over mesh, but each pass is linear public static int[][] FindTriangleSetsByGroup(NGonsCore.geometry3Sharp.mesh.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); }
// convenience function to construct a DistPoint3Triangle3 object for a mesh triangle public static DistPoint3Triangle3 TriangleDistance(NGonsCore.geometry3Sharp.mesh.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); }
public RegionRemesher(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int[] regionTris) { BaseMesh = mesh; Region = new DSubmesh3(mesh, regionTris); Region.ComputeBoundaryInfo(regionTris); base.mesh = Region.SubMesh; cur_base_tris = (int[])regionTris.Clone(); // constrain region-boundary edges bdry_constraints = new MeshConstraints(); MeshConstraintUtil.FixSubmeshBoundaryEdges(bdry_constraints, Region); SetExternalConstraints(bdry_constraints); }
// convenience function to construct a IntrRay3Triangle3 object for a mesh triangle public static IntrRay3Triangle3 TriangleIntersection(NGonsCore.geometry3Sharp.mesh.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); }
public static IEnumerable <int> GroupBoundaryVertices(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh) { int N = mesh.MaxVertexID; for (int i = 0; i < N; ++i) { if (mesh.IsVertex(i)) { if (mesh.IsGroupBoundaryVertex(i)) { yield return(i); } } } }
public static IEnumerable <int> FilteredVertices(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, Func <NGonsCore.geometry3Sharp.mesh.DMesh3, int, bool> FilterF) { int N = mesh.MaxVertexID; for (int i = 0; i < N; ++i) { if (mesh.IsVertex(i)) { if (FilterF(mesh, i)) { yield return(i); } } } }
public static IEnumerable <int> BoundaryEdges(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh) { int N = mesh.MaxEdgeID; for (int i = 0; i < N; ++i) { if (mesh.IsEdge(i)) { if (mesh.IsBoundaryEdge(i)) { yield return(i); } } } }
public MeshFacesFromLoop(NGonsCore.geometry3Sharp.mesh.DMesh3 Mesh, DCurve3 SpaceCurve, ISpatial Spatial, int tSeed) { this.Mesh = Mesh; int N = SpaceCurve.VertexCount; InitialLoopT = new int[N]; for (int i = 0; i < N; ++i) { InitialLoopT[i] = Spatial.FindNearestTriangle(SpaceCurve[i]); } find_path(); find_interior_from_seed(tSeed); }
// Compute cotan-weighted neighbour sum around a vertex. // These weights are numerically unstable if any of the triangles are degenerate. // We catch these problems and return input vertex as centroid // http://www.geometry.caltech.edu/pubs/DMSB_III.pdf public static Vector3D CotanCentroid(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int v_i) { Vector3D vSum = Vector3D.Zero; double wSum = 0; Vector3D Vi = mesh.GetVertex(v_i); int v_j = NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID, opp_v1 = NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID, opp_v2 = NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID; int t1 = NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID, t2 = NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID; bool bAborted = false; foreach (int eid in mesh.GetVtxEdges(v_i)) { opp_v2 = NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID; mesh.GetVtxNbrhood(eid, v_i, ref v_j, ref opp_v1, ref opp_v2, ref t1, ref t2); Vector3D Vj = mesh.GetVertex(v_j); Vector3D Vo1 = mesh.GetVertex(opp_v1); double cot_alpha_ij = math.MathUtil.VectorCot( (Vi - Vo1).Normalized, (Vj - Vo1).Normalized); if (cot_alpha_ij == 0) { bAborted = true; break; } double w_ij = cot_alpha_ij; if (opp_v2 != NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID) { Vector3D Vo2 = mesh.GetVertex(opp_v2); double cot_beta_ij = math.MathUtil.VectorCot( (Vi - Vo2).Normalized, (Vj - Vo2).Normalized); if (cot_beta_ij == 0) { bAborted = true; break; } w_ij += cot_beta_ij; } vSum += w_ij * Vj; wSum += w_ij; } if (bAborted || Math.Abs(wSum) < math.MathUtil.ZeroTolerance) { return(Vi); } return(vSum / wSum); }