示例#1
0
        public MeshResult FlipEdge(int eab, out EdgeFlipInfo flip)
        {
            flip = new EdgeFlipInfo();
            if (!IsEdge(eab))
            {
                return(MeshResult.Failed_NotAnEdge);
            }
            if (edge_is_boundary(eab))
            {
                return(MeshResult.Failed_IsBoundaryEdge);
            }

            // find oriented edge [a,b], tris t0,t1, and other verts c in t0, d in t1
            int eab_i = 4 * eab;
            int a = edges[eab_i], b = edges[eab_i + 1];
            int t0 = edges[eab_i + 2], t1 = edges[eab_i + 3];

            int[] T0tv = GetTriangle(t0).array;
            int[] T1tv = GetTriangle(t1).array;
            int   c    = IndexUtil.orient_tri_edge_and_find_other_vtx(ref a, ref b, T0tv);
            int   d    = IndexUtil.find_tri_other_vtx(a, b, T1tv);

            if (c == InvalidID || d == InvalidID)
            {
                return(MeshResult.Failed_BrokenTopology);
            }

            int flipped = find_edge(c, d);

            if (flipped != InvalidID)
            {
                return(MeshResult.Failed_FlippedEdgeExists);
            }

            // find edges bc, ca, ad, db
            int ebc = find_tri_neighbour_edge(t0, b, c);
            int eca = find_tri_neighbour_edge(t0, c, a);
            int ead = find_tri_neighbour_edge(t1, a, d);
            int edb = find_tri_neighbour_edge(t1, d, b);

            // update triangles
            set_triangle(t0, c, d, b);
            set_triangle(t1, d, c, a);

            // update edge AB, which becomes flipped edge CD
            set_edge_vertices(eab, c, d);
            set_edge_triangles(eab, t0, t1);
            int ecd = eab;

            // update the two other edges whose triangle nbrs have changed
            if (replace_edge_triangle(eca, t0, t1) == -1)
            {
                throw new ArgumentException("DMesh3.FlipEdge: first replace_edge_triangle failed");
            }
            if (replace_edge_triangle(edb, t1, t0) == -1)
            {
                throw new ArgumentException("DMesh3.FlipEdge: second replace_edge_triangle failed");
            }

            // update triangle nbr lists (these are edges)
            set_triangle_edges(t0, ecd, edb, ebc);
            set_triangle_edges(t1, ecd, eca, ead);

            // remove old eab from verts a and b, and decrement ref counts
            if (vertex_edges[a].Remove(eab) == false)
            {
                throw new ArgumentException("DMesh3.FlipEdge: first vertex_edges remove failed");
            }
            if (vertex_edges[b].Remove(eab) == false)
            {
                throw new ArgumentException("DMesh3.FlipEdge: second vertex_edges remove failed");
            }
            vertices_refcount.decrement(a);
            vertices_refcount.decrement(b);
            if (IsVertex(a) == false || IsVertex(b) == false)
            {
                throw new ArgumentException("DMesh3.FlipEdge: either a or b is not a vertex?");
            }

            // add new edge ecd to verts c and d, and increment ref counts
            vertex_edges[c].Add(ecd);
            vertex_edges[d].Add(ecd);
            vertices_refcount.increment(c);
            vertices_refcount.increment(d);

            // success! collect up results
            flip.eID = eab;
            flip.v0  = a; flip.v1 = b;
            flip.ov0 = c; flip.ov1 = d;
            flip.t0  = t0; flip.t1 = t1;

            updateTimeStamp(true);
            return(MeshResult.Ok);
        }
示例#2
0
        public MeshResult SplitEdge(int eab, out EdgeSplitInfo split)
        {
            split = new EdgeSplitInfo();
            if (!IsEdge(eab))
            {
                return(MeshResult.Failed_NotAnEdge);
            }

            // look up primary edge & triangle
            int eab_i = 4 * eab;
            int a = edges[eab_i], b = edges[eab_i + 1];
            int t0 = edges[eab_i + 2];

            if (t0 == InvalidID)
            {
                return(MeshResult.Failed_BrokenTopology);
            }
            Index3i T0tv = GetTriangle(t0);

            int[] T0tv_array = T0tv.array;
            int   c          = IndexUtil.orient_tri_edge_and_find_other_vtx(ref a, ref b, T0tv_array);

            // create new vertex
            Vector3d vNew = 0.5 * (GetVertex(a) + GetVertex(b));
            int      f    = AppendVertex(vNew);

            // quite a bit of code is duplicated between boundary and non-boundary case, but it
            //  is too hard to follow later if we factor it out...
            if (edge_is_boundary(eab))
            {
                // look up edge bc, which needs to be modified
                Index3i T0te = GetTriEdges(t0);
                int     ebc  = T0te[IndexUtil.find_edge_index_in_tri(b, c, T0tv_array)];

                // rewrite existing triangle
                replace_tri_vertex(t0, b, f);

                // add new second triangle
                int t2 = add_triangle_only(f, b, c, InvalidID, InvalidID, InvalidID);
                if (triangle_groups != null)
                {
                    triangle_groups.insert(triangle_groups[t0], t2);
                }

                // rewrite edge bc, create edge af
                replace_edge_triangle(ebc, t0, t2);
                int eaf = eab;
                replace_edge_vertex(eaf, b, f);
                vertex_edges[b].Remove(eab);
                vertex_edges[f].Add(eaf);

                // create new edges fb and fc
                int efb = add_edge(f, b, t2);
                int efc = add_edge(f, c, t0, t2);

                // update triangle edge-nbrs
                replace_triangle_edge(t0, ebc, efc);
                set_triangle_edges(t2, efb, ebc, efc);

                // update vertex refcounts
                vertices_refcount.increment(c);
                vertices_refcount.increment(f, 2);

                split.bIsBoundary = true;
                split.vNew        = f;
                split.eNew        = efb;

                updateTimeStamp(true);
                return(MeshResult.Ok);
            }
            else                                // interior triangle branch

            // look up other triangle
            {
                int     t1         = edges[eab_i + 3];
                Index3i T1tv       = GetTriangle(t1);
                int[]   T1tv_array = T1tv.array;
                int     d          = IndexUtil.find_tri_other_vtx(a, b, T1tv_array);

                // look up edges that we are going to need to update
                // [TODO OPT] could use ordering to reduce # of compares here
                Index3i T0te = GetTriEdges(t0);
                int     ebc  = T0te[IndexUtil.find_edge_index_in_tri(b, c, T0tv_array)];
                Index3i T1te = GetTriEdges(t1);
                int     edb  = T1te[IndexUtil.find_edge_index_in_tri(d, b, T1tv_array)];

                // rewrite existing triangles
                replace_tri_vertex(t0, b, f);
                replace_tri_vertex(t1, b, f);

                // add two new triangles to close holes we just created
                int t2 = add_triangle_only(f, b, c, InvalidID, InvalidID, InvalidID);
                int t3 = add_triangle_only(f, d, b, InvalidID, InvalidID, InvalidID);
                if (triangle_groups != null)
                {
                    triangle_groups.insert(triangle_groups[t0], t2);
                    triangle_groups.insert(triangle_groups[t1], t3);
                }

                // update the edges we found above, to point to new triangles
                replace_edge_triangle(ebc, t0, t2);
                replace_edge_triangle(edb, t1, t3);

                // edge eab became eaf
                int eaf = eab;                 //Edge * eAF = eAB;
                replace_edge_vertex(eaf, b, f);

                // update a/b/f vertex-edges
                vertex_edges[b].Remove(eab);
                vertex_edges[f].Add(eaf);

                // create new edges connected to f  (also updates vertex-edges)
                int efb = add_edge(f, b, t2, t3);
                int efc = add_edge(f, c, t0, t2);
                int edf = add_edge(d, f, t1, t3);

                // update triangle edge-nbrs
                replace_triangle_edge(t0, ebc, efc);
                replace_triangle_edge(t1, edb, edf);
                set_triangle_edges(t2, efb, ebc, efc);
                set_triangle_edges(t3, edf, edb, efb);

                // update vertex refcounts
                vertices_refcount.increment(c);
                vertices_refcount.increment(d);
                vertices_refcount.increment(f, 4);

                split.bIsBoundary = false;
                split.vNew        = f;
                split.eNew        = efb;

                updateTimeStamp(true);
                return(MeshResult.Ok);
            }
        }