示例#1
0
        /// <summary>
        /// Remove all bowtie vertices in mesh. Makes one pass unless
        ///   bRepeatUntilClean = true, in which case repeats until no more bowties found
        /// Returns true if any vertices were removed
        /// </summary>
        public bool RemoveAllBowtieVertices(bool bRepeatUntilClean)
        {
            int nRemoved = 0;

            while (true)
            {
                List <int> bowties = new List <int>();
                foreach (int vID in Mesh.VertexIndices())
                {
                    if (Mesh.IsBowtieVertex(vID))
                    {
                        bowties.Add(vID);
                    }
                }
                if (bowties.Count == 0)
                {
                    break;
                }

                foreach (int vID in bowties)
                {
                    MeshResult result = Mesh.RemoveVertex(vID, true, false);
                    Debug.Assert(result == MeshResult.Ok);
                    nRemoved++;
                }
                if (bRepeatUntilClean == false)
                {
                    break;
                }
            }
            return(nRemoved > 0);
        }
示例#2
0
        public static void flip_tests(bool bTestBoundary, int N = 100)
        {
            System.Console.WriteLine("DMesh3:flip_tests() starting");

            DMesh3 mesh = TestUtil.MakeCappedCylinder(bTestBoundary);

            mesh.CheckValidity();

            Random r = new Random(31377);

            for (int k = 0; k < N; ++k)
            {
                int eid = r.Next() % mesh.EdgeCount;
                if (!mesh.IsEdge(eid))
                {
                    continue;
                }
                bool bBoundary = mesh.IsBoundaryEdge(eid);

                DMesh3.EdgeFlipInfo flipInfo;
                MeshResult          result = mesh.FlipEdge(eid, out flipInfo);
                if (bBoundary)
                {
                    Debug.Assert(result == MeshResult.Failed_IsBoundaryEdge);
                }
                else
                {
                    Debug.Assert(result == MeshResult.Ok || result == MeshResult.Failed_FlippedEdgeExists);
                }
                mesh.CheckValidity();
            }

            System.Console.WriteLine("flips ok");
        }
示例#3
0
        /// <summary>
        /// insert new point into segment eid at parameter value t
        /// If t is within tol of endpoint of segment, we use that instead.
        /// </summary>
        protected Index2i split_segment_at_t(int eid, double t, double tol)
        {
            Index2i   ev  = Graph.GetEdgeV(eid);
            Segment2d seg = new Segment2d(Graph.GetVertex(ev.a), Graph.GetVertex(ev.b));

            int use_vid = -1;
            int new_eid = -1;

            if (t < -(seg.Extent - tol))
            {
                use_vid = ev.a;
            }
            else if (t > (seg.Extent - tol))
            {
                use_vid = ev.b;
            }
            else
            {
                DGraph2.EdgeSplitInfo splitInfo;
                MeshResult            result = Graph.SplitEdge(eid, out splitInfo);
                if (result != MeshResult.Ok)
                {
                    throw new Exception("insert_into_segment: edge split failed?");
                }
                use_vid = splitInfo.vNew;
                new_eid = splitInfo.eNewBN;
                Vector2d pt = seg.PointAt(t);
                Graph.SetVertex(use_vid, pt);
                PointHash.InsertPointUnsafe(splitInfo.vNew, pt);
            }
            return(new Index2i(use_vid, new_eid));
        }
示例#4
0
        void remove_remaining_interior_verts()
        {
            HashSet <int> interiorv  = new HashSet <int>(MeshIterators.InteriorVertices(fillmesh));
            int           prev_count = 0;

            while (interiorv.Count > 0 && interiorv.Count != prev_count)
            {
                prev_count = interiorv.Count;
                int[] curv = interiorv.ToArray();
                foreach (int vid in curv)
                {
                    foreach (int e in fillmesh.VtxEdgesItr(vid))
                    {
                        Index2i ev     = fillmesh.GetEdgeV(e);
                        int     otherv = (ev.a == vid) ? ev.b : ev.a;
                        DMesh3.EdgeCollapseInfo info;
                        MeshResult result = fillmesh.CollapseEdge(otherv, vid, out info);
                        if (result == MeshResult.Ok)
                        {
                            break;
                        }
                    }
                    if (fillmesh.IsVertex(vid) == false)
                    {
                        interiorv.Remove(vid);
                    }
                }
            }
            if (interiorv.Count > 0)
            {
                Util.gBreakToDebugger();
            }
        }
示例#5
0
        public static void split_tests_nonmanifold(int N = 100)
        {
            System.Console.WriteLine("split_tests_nonmanifold() starting");

            Random  r    = new Random(31337);
            NTMesh3 mesh = new NTMesh3();
            int     a    = mesh.AppendVertex(Vector3d.Zero);
            int     b    = mesh.AppendVertex(Vector3d.AxisZ);

            for (int k = 0; k < 5; ++k)
            {
                int c   = mesh.AppendVertex(TestUtil.RandomPoints3(1, r, Vector3d.Zero, 1)[0]);
                int tid = mesh.AppendTriangle(new Index3i(a, b, c));
                Debug.Assert(tid >= 0);
            }

            TestUtil.WriteTestOutputMesh(mesh.Deconstruct(), "nonmanifold_split_input.obj");

            for (int k = 0; k < N; ++k)
            {
                int eid = r.Next() % mesh.EdgeCount;
                if (!mesh.IsEdge(eid))
                {
                    continue;
                }

                NTMesh3.EdgeSplitInfo splitInfo;
                MeshResult            result = mesh.SplitEdge(eid, out splitInfo);
                Debug.Assert(result == MeshResult.Ok);
                mesh.CheckValidity(FailMode.DebugAssert);
            }

            TestUtil.WriteTestOutputMesh(mesh.Deconstruct(), "nonmanifold_split_output.obj");
        }
示例#6
0
        public static void split_tests(bool bTestBoundary, int N = 100)
        {
            System.Console.WriteLine("split_tests() starting");

            NTMesh3 mesh = new NTMesh3(TestUtil.MakeCappedCylinder(bTestBoundary));

            mesh.CheckValidity(FailMode.DebugAssert);

            Random r = new Random(31377);

            for (int k = 0; k < N; ++k)
            {
                int eid = r.Next() % mesh.EdgeCount;
                if (!mesh.IsEdge(eid))
                {
                    continue;
                }

                NTMesh3.EdgeSplitInfo splitInfo;
                MeshResult            result = mesh.SplitEdge(eid, out splitInfo);
                Debug.Assert(result == MeshResult.Ok);
                mesh.CheckValidity(FailMode.DebugAssert);
            }

            System.Console.WriteLine("splits ok");
        }
示例#7
0
        public static void poke_test()
        {
            NTMesh3 mesh = new NTMesh3(TestUtil.LoadTestInputMesh("plane_250v.obj"));

            //DMesh3 mesh = TestUtil.LoadTestInputMesh("sphere_bowtie_groups.obj");
            mesh.CheckValidity();

            int NT = mesh.TriangleCount;

            for (int i = 0; i < NT; i += 5)
            {
                Vector3d n = mesh.GetTriNormal(i);
                NTMesh3.PokeTriangleInfo pokeinfo;
                MeshResult result = mesh.PokeTriangle(i, out pokeinfo);

                Vector3d v = mesh.GetVertex(pokeinfo.new_vid);
                v += 0.25f * n;
                mesh.SetVertex(pokeinfo.new_vid, v);

                mesh.CheckValidity();
            }

            System.Console.WriteLine("pokes ok");

            //TestUtil.WriteTestOutputMesh(mesh, "poke_test_result.obj");
        }
示例#8
0
        /***************************************************/


        public static List <Mesh> DeformedShape(List <FEMesh> meshes, List <MeshResult> meshDeformations, string adapterId, object loadCase, double scaleFactor = 1.0)
        {
            meshDeformations = meshDeformations.SelectCase(loadCase);

            List <Mesh> defMeshes = new List <Mesh>();

            var resGroups = meshDeformations.GroupBy(x => x.ObjectId.ToString()).ToDictionary(x => x.Key);

            foreach (FEMesh feMesh in meshes)
            {
                string id = feMesh.CustomData[adapterId].ToString();

                List <MeshResult> deformations;

                IGrouping <string, MeshResult> outVal;
                if (resGroups.TryGetValue(id, out outVal))
                {
                    deformations = outVal.ToList();
                }
                else
                {
                    continue;
                }

                MeshResult singleDisp = deformations.Where(x => x.ObjectId.ToString() == id && x.Results.First() is MeshDisplacement).First();

                defMeshes.Add(DeformedMesh(feMesh, singleDisp.Results.Cast <MeshDisplacement>(), adapterId, scaleFactor));
            }

            return(defMeshes);
        }
        /// <summary>
        /// Remove vertices that are colinear w/ their two neighbours, within angle tolerance
        /// </summary>
        public void CollapseFlatVertices(double fMaxDeviationDeg = 5)
        {
            bool done       = false;
            int  max_passes = 200;
            int  pass_count = 0;

            while (done == false && pass_count++ < max_passes)
            {
                done = true;

                // [RMS] do modulo-indexing here to avoid pathological cases where we do things like
                // continually collapse a short edge adjacent to a long edge (which will result in crazy over-collapse)
                int       N       = Graph.MaxVertexID;
                const int nPrime  = 31337;                    // any prime will do...
                int       cur_vid = 0;
                do
                {
                    int vid = cur_vid;
                    cur_vid = (cur_vid + nPrime) % N;

                    if (!Graph.IsVertex(vid))
                    {
                        continue;
                    }

                    if (Graph.GetVtxEdgeCount(vid) != 2)
                    {
                        continue;
                    }

                    double open = Math.Abs(Graph.OpeningAngle(vid));
                    if (open < 180 - fMaxDeviationDeg)
                    {
                        continue;
                    }

                    var edges = Graph.GetVtxEdges(vid);
                    int eid   = edges.First();
                    int eid2  = edges.Last();
                    if (FixedEdgeFilterF(eid) || FixedEdgeFilterF(eid2))
                    {
                        continue;
                    }

                    Index2i ev      = Graph.GetEdgeV(eid);
                    int     other_v = (ev.a == vid) ? ev.b : ev.a;

                    DGraph2.EdgeCollapseInfo collapseInfo;
                    MeshResult result = Graph.CollapseEdge(other_v, vid, out collapseInfo);
                    if (result == MeshResult.Ok)
                    {
                        done = false;
                    }
                    else
                    {
                        throw new Exception("DGraph2Resampler.CollapseFlatVertices: failed!");
                    }
                } while (cur_vid != 0);
            }
        }
        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);
            }
        }
示例#11
0
        // insert point at bary_coords inside tid. If point is at vtx, just use that vtx.
        // If it is on an edge, do an edge split. Otherwise poke face.
        int insert_corner_from_bary(int iCorner, int tid, Vector3d bary_coords, double tol = MathUtil.ZeroTolerance)
        {
            Vector2d vInsert = Curve[iCorner];
            Index3i  tv      = Mesh.GetTriangle(tid);

            // handle cases where corner is on a vertex
            if (bary_coords.x > 1 - tol)
            {
                return(tv.a);
            }
            else if (bary_coords.y > 1 - tol)
            {
                return(tv.b);
            }
            else if (bary_coords.z > 1 - tol)
            {
                return(tv.c);
            }

            // handle cases where corner is on an edge
            int split_edge = -1;

            if (bary_coords.x < tol)
            {
                split_edge = 1;
            }
            else if (bary_coords.y < tol)
            {
                split_edge = 2;
            }
            else if (bary_coords.z < tol)
            {
                split_edge = 0;
            }
            if (split_edge >= 0)
            {
                int eid = Mesh.GetTriEdge(tid, split_edge);

                DMesh3.EdgeSplitInfo split_info;
                MeshResult           splitResult = Mesh.SplitEdge(eid, out split_info);
                if (splitResult != MeshResult.Ok)
                {
                    throw new Exception("MeshInsertUVPolyCurve.insert_corner_special: edge split failed in case sum==2");
                }
                SetPointF(split_info.vNew, vInsert);
                return(split_info.vNew);
            }

            // otherwise corner is inside triangle
            DMesh3.PokeTriangleInfo pokeinfo;
            MeshResult result = Mesh.PokeTriangle(tid, bary_coords, out pokeinfo);

            if (result != MeshResult.Ok)
            {
                throw new Exception("MeshInsertUVPolyCurve.insert_corner_special: face poke failed!");
            }

            SetPointF(pokeinfo.new_vid, vInsert);
            return(pokeinfo.new_vid);
        }
示例#12
0
        public void Apply(DMesh3 mesh)
        {
            int NV = AddedV.size;

            if (NV > 0)
            {
                NewVertexInfo vinfo = new NewVertexInfo(Positions[0]);
                mesh.BeginUnsafeVerticesInsert();
                for (int i = 0; i < NV; ++i)
                {
                    int vid = AddedV[i];
                    vinfo.v = Positions[i];
                    if (Normals != null)
                    {
                        vinfo.bHaveN = true; vinfo.n = Normals[i];
                    }
                    if (Colors != null)
                    {
                        vinfo.bHaveC = true; vinfo.c = Colors[i];
                    }
                    if (UVs != null)
                    {
                        vinfo.bHaveUV = true; vinfo.uv = UVs[i];
                    }
                    MeshResult result = mesh.InsertVertex(vid, ref vinfo, true);
                    if (result != MeshResult.Ok)
                    {
                        throw new Exception("AddTrianglesMeshChange.Revert: error in InsertVertex(" + vid.ToString() + "): " + result.ToString());
                    }
                }
                mesh.EndUnsafeVerticesInsert();
            }

            int NT = AddedT.size;

            if (NT > 0)
            {
                mesh.BeginUnsafeTrianglesInsert();
                for (int i = 0; i < NT; ++i)
                {
                    int        tid    = AddedT[i];
                    Index4i    tdata  = Triangles[i];
                    Index3i    tri    = new Index3i(tdata.a, tdata.b, tdata.c);
                    MeshResult result = mesh.InsertTriangle(tid, tri, tdata.d, true);
                    if (result != MeshResult.Ok)
                    {
                        throw new Exception("AddTrianglesMeshChange.Revert: error in InsertTriangle(" + tid.ToString() + "): " + result.ToString());
                    }
                }
                mesh.EndUnsafeTrianglesInsert();
            }

            if (OnApplyF != null)
            {
                OnApplyF(AddedV, AddedT);
            }
        }
示例#13
0
        private static void ProcessMesh(IMesh mesh, MeshResult result)
        {
            result.NumberOfTriangles += mesh.Triangles.Count;

            if (!MeshValidator.IsConsistent((Mesh)mesh))
            {
                result.Invalid += 1;
            }
        }
示例#14
0
        public static void collapse_tests(bool bTestBoundary, int N = 100)
        {
            bool write_debug_meshes = false;

            DMesh3 mesh = TestUtil.MakeCappedCylinder(bTestBoundary);

            mesh.CheckValidity();

            System.Console.WriteLine(string.Format("DMesh3:collapse_tests() starting - test bdry {2}, verts {0} tris {1}",
                                                   mesh.VertexCount, mesh.TriangleCount, bTestBoundary));

            if (write_debug_meshes)
            {
                TestUtil.WriteDebugMesh(mesh, string.Format("before_collapse_{0}.obj", ((bTestBoundary)?"boundary":"noboundary")));
            }


            Random r = new Random(31377);

            for (int k = 0; k < N; ++k)
            {
                int eid = r.Next() % mesh.EdgeCount;
                if (!mesh.IsEdge(eid))
                {
                    continue;
                }
                //bool bBoundary = mesh.IsBoundaryEdge(eid);
                //if (bTestBoundary && bBoundary == false)
                //	 continue;
                Index2i ev = mesh.GetEdgeV(eid);

                DMesh3.EdgeCollapseInfo collapseInfo;
                MeshResult result = mesh.CollapseEdge(ev[0], ev[1], out collapseInfo);
                Debug.Assert(
                    result != MeshResult.Failed_NotAnEdge &&
                    result != MeshResult.Failed_FoundDuplicateTriangle);

                mesh.CheckValidity();
            }

            System.Console.WriteLine(string.Format("random collapses ok - verts {0} tris {1}",
                                                   mesh.VertexCount, mesh.TriangleCount));


            collapse_to_convergence(mesh);

            System.Console.WriteLine(string.Format("all possible collapses ok - verts {0} tris {1}",
                                                   mesh.VertexCount, mesh.TriangleCount));

            if (write_debug_meshes)
            {
                TestUtil.WriteDebugMesh(mesh, string.Format("after_collapse_{0}.obj", ((bTestBoundary)?"boundary":"noboundary")));
            }
        }
示例#15
0
        /// <summary>
        /// Remove vertex vID, and all connected triangles if bRemoveAllTriangles = true
        /// (if false, them throws exception if there are still any triangles!)
        /// if bPreserveManifold, checks that we will not create a bowtie vertex first
        /// </summary>
        public MeshResult RemoveVertex(int vID, bool bRemoveAllTriangles = true, bool bPreserveManifold = true)
        {
            if (vertices_refcount.isValid(vID) == false)
            {
                return(MeshResult.Failed_NotAVertex);
            }

            if (bRemoveAllTriangles)
            {
                // if any one-ring vtx is a boundary vtx and one of its outer-ring edges is an
                // interior edge then we will create a bowtie if we remove that triangle
                if (bPreserveManifold)
                {
                    foreach (int tid in VtxTrianglesItr(vID))
                    {
                        Index3i tri = GetTriangle(tid);
                        int     j = IndexUtil.find_tri_index(vID, tri);
                        int     oa = tri[(j + 1) % 3], ob = tri[(j + 2) % 3];
                        int     eid = find_edge(oa, ob);
                        if (edge_is_boundary(eid))
                        {
                            continue;
                        }
                        if (vertex_is_boundary(oa) || vertex_is_boundary(ob))
                        {
                            return(MeshResult.Failed_WouldCreateBowtie);
                        }
                    }
                }

                List <int> tris = new List <int>();
                GetVtxTriangles(vID, tris, true);
                foreach (int tID in tris)
                {
                    MeshResult result = RemoveTriangle(tID, false, bPreserveManifold);
                    if (result != MeshResult.Ok)
                    {
                        return(result);
                    }
                }
            }

            if (vertices_refcount.refCount(vID) != 1)
            {
                throw new NotImplementedException("DMesh3.RemoveVertex: vertex is still referenced");
            }

            vertices_refcount.decrement(vID);
            Debug.Assert(vertices_refcount.isValid(vID) == false);
            vertex_edges[vID] = null;

            updateTimeStamp(true);
            return(MeshResult.Ok);
        }
示例#16
0
 // this is for backing out changes we have made...
 bool remove_triangles(int[] tri_list, int count)
 {
     for (int i = 0; i < count; ++i)
     {
         MeshResult result = Mesh.RemoveTriangle(tri_list[i], false, false);
         if (result != MeshResult.Ok)
         {
             return(false);
         }
     }
     return(true);
 }
        public void Apply(DMesh3 mesh)
        {
            int N = RemovedT.size;

            for (int i = 0; i < N; ++i)
            {
                int        tid    = RemovedT[i];
                MeshResult result = mesh.RemoveTriangle(RemovedT[i], true, false);
                if (result != MeshResult.Ok)
                {
                    throw new Exception("RemoveTrianglesMeshChange.Apply: error in RemoveTriangle(" + tid.ToString() + "): " + result.ToString());
                }
            }
        }
示例#18
0
        public MeshResult RemoveVertex(int vid, bool bRemoveIsolatedVertices)
        {
            var edges = new List <int>(GetVtxEdges(vid));

            foreach (int eid in edges)
            {
                MeshResult result = RemoveEdge(eid, bRemoveIsolatedVertices);
                if (result != MeshResult.Ok)
                {
                    return(result);
                }
            }
            return(MeshResult.Ok);
        }
示例#19
0
        public static List <Mesh> DeformedShape(List <FEMesh> meshes, List <MeshResult> meshDisplacements, Type adapterIdType, object loadcase, double scaleFactor = 1.0)
        {
            if (adapterIdType == null)
            {
                Reflection.Compute.RecordError("The provided adapter id type is null.");
                return(new List <Mesh>());
            }
            if (!typeof(IAdapterId).IsAssignableFrom(adapterIdType))
            {
                Reflection.Compute.RecordError($"The `{adapterIdType.Name}` is not a valid `{typeof(IAdapterId).Name}`.");
                return(new List <Mesh>());
            }

            meshDisplacements = meshDisplacements.SelectCase(loadcase);

            List <Mesh> defMeshes = new List <Mesh>();

            var resGroups = meshDisplacements.GroupBy(x => x.ObjectId.ToString()).ToDictionary(x => x.Key);

            foreach (FEMesh feMesh in meshes)
            {
                IAdapterId idFragment = feMesh.FindFragment <IAdapterId>(adapterIdType);
                if (idFragment == null)
                {
                    Engine.Reflection.Compute.RecordWarning("Could not find the adapter id for at least one FEMesh.");
                    continue;
                }

                string id = idFragment.Id.ToString();

                List <MeshResult> deformations;

                IGrouping <string, MeshResult> outVal;
                if (resGroups.TryGetValue(id, out outVal))
                {
                    deformations = outVal.ToList();
                }
                else
                {
                    continue;
                }

                MeshResult singleDisp = deformations.Where(x => x.ObjectId.ToString() == id && x.Results.First() is IMeshDisplacement).First();

                defMeshes.Add(DeformedMesh(feMesh, singleDisp.Results.Cast <IMeshDisplacement>(), adapterIdType, scaleFactor));
            }

            return(defMeshes);
        }
示例#20
0
        /// <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);
            }
        }
示例#21
0
        /// <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);
            }
        }
示例#22
0
        bool collapse_degenerate_edges(
            double minLength, bool bBoundaryOnly,
            out int collapseCount)
        {
            collapseCount = 0;
            // don't iterate sequentially because there may be pathological cases
            foreach (int eid in MathUtil.ModuloIteration(Mesh.MaxEdgeID))
            {
                if (Cancelled())
                {
                    break;
                }

                if (Mesh.IsEdge(eid) == false)
                {
                    continue;
                }

                bool is_boundary_edge = Mesh.IsBoundaryEdge(eid);
                if (bBoundaryOnly && is_boundary_edge == false)
                {
                    continue;
                }

                Index2i  ev = Mesh.GetEdgeV(eid);
                Vector3d a = Mesh.GetVertex(ev.a), b = Mesh.GetVertex(ev.b);
                if (a.Distance(b) < minLength)
                {
                    int keep    = Mesh.IsBoundaryVertex(ev.a) ? ev.a : ev.b;
                    int discard = (keep == ev.a) ? ev.b : ev.a;
                    DMesh3.EdgeCollapseInfo collapseInfo;
                    MeshResult result = Mesh.CollapseEdge(keep, discard, out collapseInfo);
                    if (result == MeshResult.Ok)
                    {
                        ++collapseCount;
                        if (Mesh.IsBoundaryVertex(keep) == false || is_boundary_edge)
                        {
                            Mesh.SetVertex(keep, (a + b) * 0.5);
                        }
                    }
                }
            }
            return(true);
        }
示例#23
0
        public void Revert(DMesh3 mesh)
        {
            int N = AddedT.size;

            for (int i = 0; i < N; ++i)
            {
                int        tid    = AddedT[i];
                MeshResult result = mesh.RemoveTriangle(AddedT[i], true, false);
                if (result != MeshResult.Ok)
                {
                    throw new Exception("AddTrianglesMeshChange.Apply: error in RemoveTriangle(" + tid.ToString() + "): " + result.ToString());
                }
            }

            if (OnRevertF != null)
            {
                OnRevertF(AddedV, AddedT);
            }
        }
示例#24
0
        // [TODO] cannot back-out this operation right now
        //
        // Remove list of triangles. Values of triangles[] set to InvalidID are ignored.
        public bool RemoveTriangles(int[] triangles, bool bRemoveIsolatedVerts)
        {
            bool bAllOK = true;

            for (int i = 0; i < triangles.Length; ++i)
            {
                if (triangles[i] == DMesh3.InvalidID)
                {
                    continue;
                }

                MeshResult result = Mesh.RemoveTriangle(triangles[i], bRemoveIsolatedVerts, false);
                if (result != MeshResult.Ok)
                {
                    bAllOK = false;
                }
            }
            return(bAllOK);
        }
示例#25
0
        // [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);
        }
示例#26
0
        // [TODO] cannot back-out this operation right now
        //
        // Remove all triangles identified by selectorF returning true
        public bool RemoveTriangles(Func <int, bool> selectorF, bool bRemoveIsolatedVerts)
        {
            bool bAllOK = true;
            int  NT     = Mesh.MaxTriangleID;

            for (int ti = 0; ti < NT; ++ti)
            {
                if (Mesh.IsTriangle(ti) == false || selectorF(ti) == false)
                {
                    continue;
                }
                MeshResult result = Mesh.RemoveTriangle(ti, bRemoveIsolatedVerts, false);
                if (result != MeshResult.Ok)
                {
                    bAllOK = false;
                }
            }
            return(bAllOK);
        }
示例#27
0
        private bool CollapseDegenerateEdges(DMesh3 mesh,
                                             CancellationToken cancellationToken,
                                             double minLength,
                                             bool bBoundaryOnly,
                                             out int collapseCount)
        {
            collapseCount = 0;
            // don't iterate sequentially because there may be pathological cases
            foreach (int eid in MathUtil.ModuloIteration(mesh.MaxEdgeID))
            {
                cancellationToken.ThrowIfCancellationRequested();
                if (mesh.IsEdge(eid) == false)
                {
                    continue;
                }

                bool isBoundaryEdge = mesh.IsBoundaryEdge(eid);
                if (bBoundaryOnly && isBoundaryEdge == false)
                {
                    continue;
                }

                Index2i  ev = mesh.GetEdgeV(eid);
                Vector3d a = mesh.GetVertex(ev.a), b = mesh.GetVertex(ev.b);
                if (a.Distance(b) < minLength)
                {
                    int        keep    = mesh.IsBoundaryVertex(ev.a) ? ev.a : ev.b;
                    int        discard = (keep == ev.a) ? ev.b : ev.a;
                    MeshResult result  = mesh.CollapseEdge(keep, discard, out DMesh3.EdgeCollapseInfo collapseInfo);
                    if (result == MeshResult.Ok)
                    {
                        ++collapseCount;
                        if (mesh.IsBoundaryVertex(keep) == false || isBoundaryEdge)
                        {
                            mesh.SetVertex(keep, (a + b) * 0.5);
                        }
                    }
                }
            }

            return(true);
        }
示例#28
0
        }         // Cut()

        protected void collapse_degenerate_edges(HashSet <int> OnCutEdges, HashSet <int> ZeroEdges)
        {
            var sets = new HashSet <int>[2] {
                OnCutEdges, ZeroEdges
            };

            double   tol2 = DegenerateEdgeTol * DegenerateEdgeTol;
            Vector3d a = Vector3d.Zero, b = Vector3d.Zero;
            int      collapsed = 0;

            do
            {
                collapsed = 0;
                foreach (var edge_set in sets)
                {
                    foreach (int eid in edge_set)
                    {
                        if (Mesh.IsEdge(eid) == false)
                        {
                            continue;
                        }

                        Mesh.GetEdgeV(eid, ref a, ref b);
                        if (a.DistanceSquared(b) > tol2)
                        {
                            continue;
                        }

                        Index2i ev = Mesh.GetEdgeV(eid);
                        DMesh3.EdgeCollapseInfo collapseInfo;
                        MeshResult result = Mesh.CollapseEdge(ev.a, ev.b, out collapseInfo);
                        if (result == MeshResult.Ok)
                        {
                            collapsed++;
                        }
                    }
                }
            } while (collapsed != 0);
        }
示例#29
0
        void split_missing(MeshMeshCut fromOp, MeshMeshCut toOp,
                           DMesh3 fromMesh, DMesh3 toMesh,
                           HashSet <int> fromVerts, HashSet <int> toVerts)
        {
            List <int> missing = new List <int>();

            foreach (int vid in fromVerts)
            {
                Vector3d v        = fromMesh.GetVertex(vid);
                int      near_vid = find_nearest_vertex(toMesh, v, toVerts);
                if (near_vid == DMesh3.InvalidID)
                {
                    missing.Add(vid);
                }
            }

            foreach (int vid in missing)
            {
                Vector3d v        = fromMesh.GetVertex(vid);
                int      near_eid = find_nearest_edge(toMesh, v, toVerts);
                if (near_eid == DMesh3.InvalidID)
                {
                    System.Console.WriteLine("could not find edge to split?");
                    continue;
                }

                DMesh3.EdgeSplitInfo splitInfo;
                MeshResult           result = toMesh.SplitEdge(near_eid, out splitInfo);
                if (result != MeshResult.Ok)
                {
                    System.Console.WriteLine("edge split failed");
                    continue;
                }

                toMesh.SetVertex(splitInfo.vNew, v);
                toVerts.Add(splitInfo.vNew);
            }
        }
示例#30
0
        // this function collapses edges until it can't anymore
        static void collapse_to_convergence(DMesh3 mesh)
        {
            bool bContinue = true;

            while (bContinue)
            {
                bContinue = false;
                for (int eid = 0; eid < mesh.MaxEdgeID; ++eid)
                {
                    if (!mesh.IsEdge(eid))
                    {
                        continue;
                    }
                    Index2i ev = mesh.GetEdgeV(eid);
                    DMesh3.EdgeCollapseInfo collapseInfo;
                    MeshResult result = mesh.CollapseEdge(ev[0], ev[1], out collapseInfo);
                    if (result == MeshResult.Ok)
                    {
                        bContinue = true;
                        break;
                    }
                }
            }
        }