Exemplo n.º 1
0
        /// <summary>
        /// Grow selection outwards from seed triangles, until it hits boundaries defined by triangle and edge filters.
        /// Edge filter is not effective unless it (possibly combined w/ triangle filter) defines closed loops.
        /// </summary>
        public void FloodFill(int[] Seeds, Func <int, bool> TriFilterF = null, Func <int, bool> EdgeFilterF = null)
        {
            DVector <int> stack = new DVector <int>(Seeds);

            for (int k = 0; k < Seeds.Length; ++k)
            {
                add(Seeds[k]);
            }
            while (stack.size > 0)
            {
                int tID = stack.back;
                stack.pop_back();

                Index3i nbrs = Mesh.GetTriNeighbourTris(tID);
                for (int j = 0; j < 3; ++j)
                {
                    int nbr_tid = nbrs[j];
                    if (nbr_tid == DMesh3.InvalidID || IsSelected(nbr_tid))
                    {
                        continue;
                    }
                    if (TriFilterF != null && TriFilterF(nbr_tid) == false)
                    {
                        continue;
                    }
                    if (EdgeFilterF != null && EdgeFilterF(Mesh.GetTriEdge(tID, j)) == false)
                    {
                        continue;
                    }
                    add(nbr_tid);

                    stack.push_back(nbr_tid);
                }
            }
        }
Exemplo n.º 2
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);
        }
        // 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 bary_tol, double spatial_tol, out bool is_existing_v)
        {
            is_existing_v = false;
            Vector2d vInsert = Curve[iCorner];
            Index3i  tv      = Mesh.GetTriangle(tid);

            // handle cases where corner is on a vertex
            int cornerv = -1;

            if (bary_coords.x > 1 - bary_tol)
            {
                cornerv = tv.a;
            }
            else if (bary_coords.y > 1 - bary_tol)
            {
                cornerv = tv.b;
            }
            else if (bary_coords.z > 1 - bary_tol)
            {
                cornerv = tv.c;
            }
            if (cornerv != -1 && PointF(cornerv).Distance(vInsert) < spatial_tol)
            {
                is_existing_v = true;
                return(cornerv);
            }

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

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

                Index2i   ev  = Mesh.GetEdgeV(eid);
                Segment2d seg = new Segment2d(PointF(ev.a), PointF(ev.b));
                if (seg.DistanceSquared(vInsert) < spatial_tol * spatial_tol)
                {
                    Index2i et = Mesh.GetEdgeT(eid);
                    spatial_remove_triangles(et.a, et.b);

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

                    spatial_add_triangles(et.a, et.b);
                    spatial_add_triangles(split_info.eNewT2, split_info.eNewT3);

                    return(split_info.vNew);
                }
            }

            spatial_remove_triangle(tid);

            // 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_from_bary: face poke failed - " + result.ToString());
            }

            SetPointF(pokeinfo.new_vid, vInsert);

            spatial_add_triangle(tid);
            spatial_add_triangle(pokeinfo.new_t1);
            spatial_add_triangle(pokeinfo.new_t2);

            return(pokeinfo.new_vid);
        }