Exemple #1
0
        /// <summary>
        /// Sets the number of intersections for one of the polygon link points.
        /// </summary>
        /// <param name="index">The array index of the link point to process.</param>
        /// <returns>The number of intersections assigned.</returns>
        uint SetIntersectionCount(uint index)
        {
            // No intersections so far
            uint nx = 0;

            //	Point to the thing we want to set the count for.
            PolygonLink link = m_Links[index];

            // Go through all link points searching for intersections.
            for (uint i = 0; i < m_Links.Length; i++)
            {
                if (link.IsIntersected(m_Links[i]))
                {
                    nx++;
                }
            }

            // Set the intersect count.
            link.NumIntersect = nx;
            return(nx);
        }
Exemple #2
0
        /// <summary>
        /// Constructor (that does a lot of stuff)
        /// </summary>
        /// <param name="polygon">The polygon being subdivided.</param>
        internal PolygonSub(Polygon polygon)
        {
            m_Polygon = polygon;
            m_Faces   = null;
            m_Links   = null;

            // Get the boundaries defining the exterior edge of the polygon
            IDivider[] lines = polygon.Edge;
            if (lines == null || lines.Length == 0)
            {
                return;
            }

            // Allocate an array for holding info on each polygon face,
            // and associate each one with the divider that acts as the primary face.
            uint numLink = 0;

            m_Faces = new PolygonFace[lines.Length];
            for (int i = 0; i < lines.Length; i++)
            {
                m_Faces[i] = new PolygonFace();
                numLink   += m_Faces[i].SetDivider(m_Polygon, lines[i]);
            }

            // Create an array of link objects (one for each point)
            if (numLink == 0)
            {
                return;
            }

            m_Links = new PolygonLink[numLink];

            // Initialize the links for first face
            int nDone = 0;

            PolygonLink[] links = m_Faces[0].CreateLinks(m_Faces[m_Faces.Length - 1]);
            Array.Copy(links, m_Links, links.Length);
            nDone += links.Length;

            // Initialize links for each subsequent face
            for (int i = 1; i < m_Faces.Length; i++)
            {
                links = m_Faces[i].CreateLinks(m_Faces[i - 1]);
                for (int j = 0; j < links.Length; j++)
                {
                    m_Links[nDone + j] = links[j];
                }

                nDone += links.Length;
            }


            Debug.Assert(nDone == m_Links.Length);

            // Assign a side number to each link position

            uint nside = 0;               // No side number assigned so far.
            uint ncorn = 0;               // Number of corners

            for (int i = 0; i < m_Links.Length; i++)
            {
                // Skip if we are dealing with a corner.
                if (m_Links[i].IsCorner())
                {
                    ncorn++;
                    continue;
                }

                // Skip if the side number has already been assigned.
                if (m_Links[i].Side != 0)
                {
                    continue;
                }

                // Assign next side number.
                nside++;

                // Continue till we reach a corner, assigning intermediate
                // faces the same side number.
                for (int j = i; j < m_Links.Length; j++)
                {
                    if (m_Links[j].IsCorner())
                    {
                        break;
                    }
                    m_Links[j].Side = nside;
                }

                // If we just assigned a side number to the very first face,
                //  loop back from the end of the array.
                if (i == 0)
                {
                    for (int k = m_Links.Length - 1; k > 0; k--)
                    {
                        if (m_Links[k].IsCorner())
                        {
                            break;
                        }
                        m_Links[k].Side = nside;
                    }
                }
            }

            // Return if we only have one side (or less)
            // if ( nside<2 ) return;

            // Define the max angular difference (10 degrees, but in radians)
            double ANGTOL = (10.0 * Constants.DEGTORAD);

            // Process all the radial faces first.

            for (uint i = 0; i < m_Links.Length; i++)
            {
                if (m_Links[i].IsRadial)
                {
                    this.SetLink(i, ANGTOL);
                }
            }

            // For each point that is not a corner or a curve end, cycle
            // through all the subsequent points, looking for a point to
            // connect to. Don't try to do curve end points just yet.

            for (uint i = 0; i < m_Links.Length; i++)
            {
                if (!m_Links[i].IsRadial && !m_Links[i].IsCurveEnd)
                {
                    this.SetLink(i, ANGTOL);
                }
            }

            // Process any points at the end of curves.

            for (uint i = 0; i < m_Links.Length; i++)
            {
                if (m_Links[i].IsCurveEnd)
                {
                    this.SetLink(i, ANGTOL);
                }
            }

            // Eliminate self-intersections ...

            // Start by counting the number of intersections each link has.
            uint maxnx = 0;

            for (uint i = 0; i < m_Links.Length; i++)
            {
                uint nx = this.SetIntersectionCount(i);
                maxnx = Math.Max(maxnx, nx);
            }

            uint nloop = 0;               // Number of loops (just in case of infinite loop).

            while (maxnx > 0)
            {
                // Find a link with the max number of intersections.
                int rem = -1;
                for (int i = 0; i < m_Links.Length; i++)
                {
                    if (m_Links[i].NumIntersect == maxnx)
                    {
                        rem = i;
                        break;
                    }
                }

                // We SHOULD have found something.
                if (rem < 0)
                {
                    throw new Exception("PolygonSub: Unexpected intersection count");
                }

                // If the count was greater than one, just remove the link. Otherwise get the
                // thing that was intersected. If one is a radial or a curve end, & the other isn't,
                // drop the radial. Otherwise drop the one with the poorer link angle.

                if (maxnx > 1)
                {
                    m_Links[rem].SetLink(null);
                }
                else
                {
                    PolygonLink pLink1 = m_Links[rem];
                    PolygonLink pLink2 = null;
                    for (int i = 0; pLink2 != null && i < m_Links.Length; i++)
                    {
                        if (pLink1.IsIntersected(m_Links[i]))
                        {
                            pLink2 = m_Links[i];
                        }
                    }

                    if (pLink2 == null)
                    {
                        throw new Exception("PolygonSub: Intersection not found");
                    }

                    // Check if radial.
                    bool rad1 = pLink1.IsRadial || pLink1.Link.IsRadial;
                    bool rad2 = pLink2.IsRadial || pLink2.Link.IsRadial;

                    // Check if end of curves.
                    bool end1 = pLink1.IsCurveEnd || pLink1.Link.IsCurveEnd;
                    bool end2 = pLink2.IsCurveEnd || pLink2.Link.IsCurveEnd;

                    // We treat radials and end of curves the same.
                    bool curve1 = (rad1 || end1);
                    bool curve2 = (rad2 || end2);

                    // If one is a curve-related and the other isn't, drop
                    // the one that's curve-related.
                    if (curve1 != curve2)
                    {
                        if (curve1)
                        {
                            pLink1.SetLink(null);
                        }
                        else
                        {
                            pLink2.SetLink(null);
                        }
                    }
                    else
                    {
                        // Neither is curve related, or both are. Drop the
                        // one with the poorer link angle.

                        if (pLink1.LinkAngle > pLink2.LinkAngle)
                        {
                            pLink1.SetLink(null);
                        }
                        else
                        {
                            pLink2.SetLink(null);
                        }
                    }
                }

                // Rework the intersect counts where necessary.

                maxnx = 0;
                for (uint i = 0; i < m_Links.Length; i++)
                {
                    if (m_Links[i].NumIntersect > 0)
                    {
                        maxnx = Math.Max(maxnx, this.SetIntersectionCount(i));
                    }
                }

                // Make sure we don't go into an infinite loop.
                nloop++;
                if (nloop > m_Links.Length)
                {
                    throw new Exception("PolygonSub: Breaking from infinite loop");
                }
            } // end while
        }