Beispiel #1
0
        /// <summary>
        /// Merges the with hole.
        /// </summary>
        public Polygon2D MergeWithHole(Polygon2D actHole, Polygon2DMergeOptions mergeOptions, List <Vector2> cutPoints)
        {
            //This algorithm uses the method described in http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf

            //Find the hole vertex with the highest x value
            Vector2 holeVertexWithHighestX      = new Vector2(float.MinValue, 0f);
            int     holeVertexIndexWithHighestX = -1;

            for (int loopVertex = 0; loopVertex < actHole.m_vertices.Length; loopVertex++)
            {
                if (actHole.m_vertices[loopVertex].X > holeVertexWithHighestX.X)
                {
                    holeVertexWithHighestX      = actHole.m_vertices[loopVertex];
                    holeVertexIndexWithHighestX = loopVertex;
                }
            }
            if (cutPoints != null)
            {
                cutPoints.Add(holeVertexWithHighestX);
            }

            //Define a ray from the found vertex pointing in x direction
            Ray2D ray2D = new Ray2D(holeVertexWithHighestX, new Vector2(1f, 0f));

            //Find the line on current filling polygon with intersects first with the created ray
            Tuple <int, float, Vector2> foundLine = null;
            int actLineIndex = 0;

            foreach (Line2D actLine in this.Lines)
            {
                var actIntersection = actLine.Intersect(ray2D);
                if (actIntersection.Item1)
                {
                    Ray2D rayToIntersectionPoint = new Ray2D(
                        ray2D.Origin,
                        Vector2.Normalize(actIntersection.Item2 - ray2D.Origin));
                    float lengthToIntersectionPoint = Vector2.Distance(actIntersection.Item2, ray2D.Origin);
                    if ((lengthToIntersectionPoint > 0f) &&
                        (rayToIntersectionPoint.EqualsWithTolerance(ray2D)))
                    {
                        if (foundLine == null)
                        {
                            //First found intersection
                            foundLine = Tuple.Create(actLineIndex, lengthToIntersectionPoint, actIntersection.Item2);
                        }
                        else if (lengthToIntersectionPoint < foundLine.Item2)
                        {
                            //More intersections found.. take the one with smalles distance to intersection point
                            foundLine = Tuple.Create(actLineIndex, lengthToIntersectionPoint, actIntersection.Item2);
                        }
                    }
                }
                actLineIndex++;
            }
            if (cutPoints != null)
            {
                cutPoints.Add(foundLine.Item3);
            }

            //Check for found intersection
            if (foundLine == null)
            {
                throw new SeeingSharpException("No point found on which given polygons can be combinded!");
            }

            //Now generate result polygon
            List <Vector2> resultBuilder = new List <Vector2>(this.m_vertices.Length + actHole.m_vertices.Length + 2);

            for (int loopFillVertex = 0; loopFillVertex < this.m_vertices.Length; loopFillVertex++)
            {
                //Add current vertex from filling polygon first
                resultBuilder.Add(m_vertices[loopFillVertex]);

                //Do special logic on cut point
                if (loopFillVertex == foundLine.Item1)
                {
                    //Cut point.. place here the hole polygon
                    if (!m_vertices[loopFillVertex].Equals(foundLine.Item3))
                    {
                        resultBuilder.Add(foundLine.Item3);
                    }

                    //Add all vertices from the hole polygon
                    resultBuilder.Add(actHole.m_vertices[holeVertexIndexWithHighestX]);
                    int loopHoleVertex = holeVertexIndexWithHighestX + 1;
                    while (loopHoleVertex != holeVertexIndexWithHighestX)
                    {
                        if (loopHoleVertex >= actHole.m_vertices.Length)
                        {
                            loopHoleVertex = 0;
                        }

                        resultBuilder.Add(actHole.m_vertices[loopHoleVertex]);

                        loopHoleVertex++;
                        if (loopHoleVertex >= actHole.m_vertices.Length)
                        {
                            loopHoleVertex = 0;
                        }
                    }

                    //Add cutpoints again to continue with main polygon
                    if (mergeOptions.MakeMergepointSpaceForTriangulation)
                    {
                        resultBuilder.Add(actHole.m_vertices[holeVertexIndexWithHighestX] + new Vector2(0f, 0.001f));

                        //Add the cutpoint again
                        resultBuilder.Add(foundLine.Item3 + new Vector2(0f, 0.001f));
                    }
                    else
                    {
                        resultBuilder.Add(actHole.m_vertices[holeVertexIndexWithHighestX]);

                        //Add the cutpoint again
                        resultBuilder.Add(foundLine.Item3);
                    }

                    //Handle the case in which next vertex would equal current cut point
                    if ((m_vertices.Length > loopFillVertex + 1) &&
                        (m_vertices[loopFillVertex + 1].Equals(foundLine.Item3)))
                    {
                        loopFillVertex++;
                    }
                }
            }

            //Return new generate polygon
            return(new Polygon2D(resultBuilder.ToArray()));
        }
Beispiel #2
0
 /// <summary>
 /// Merges this polygon with the given one defining a hole. The result is a new polygon.
 /// </summary>
 public Polygon2D MergeWithHole(Polygon2D actHole, Polygon2DMergeOptions mergeOptions)
 {
     return(MergeWithHole(actHole, mergeOptions, null));
 }