Esempio n. 1
0
        /// <summary>
        /// Constructor that uses a List of Points and an optional List of Point-Indices
        /// </summary>
        /// <param name="points">The Polygon-Defining Points</param>
        /// <param name="indices">Optional List of Point-Indices</param>
        public PolygonData(List <Point> points, List <int> indices = null)
        {
            // Initialize
            mPoints            = new List <PolygonPoint>(points.Select(p => new PolygonPoint(p)));
            mHoles             = new List <List <PolygonPoint> >();
            mNumBoundaryPoints = mPoints.Count;

            // If no Indices were specified, add them manually
            if (indices == null)
            {
                for (int i = 0; i < mPoints.Count; i++)
                {
                    mPoints[i].Index = i;
                }
            }
            // If there were Indices specified, use them to set the PolygonPoint's Index Property
            else
            {
                for (int i = 0; i < mPoints.Count; i++)
                {
                    mPoints[i].Index = indices[i];
                }
            }

            // Add Edges between the Points (to be able to navigate along the Polygon easily later)
            var cnt = mPoints.Count;

            for (int i = 0; i < cnt; i++)
            {
                var lastIdx = (i + cnt - 1) % cnt;
                var edge    = new PolygonEdge(mPoints[lastIdx], mPoints[i]);
                mPoints[lastIdx].EdgeTwo = edge;
                mPoints[i].EdgeOne       = edge;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Constructor taking an Edge and a Helper
        /// </summary>
        /// <param name="edge">The Edge of the StatusHelperElement</param>
        /// <param name="point">The Helper for the Edge of the StatusHelperElement</param>
        internal StatusHelperElement(PolygonEdge edge, PolygonPoint point)
        {
            this.Edge   = edge;
            this.Helper = point;
            var vector = edge.PointTwo.Point - edge.PointOne.Point;

            this.mFactor = vector.X / vector.Y;
            this.MinX    = Math.Min(edge.PointOne.X, edge.PointTwo.X);
        }
Esempio n. 3
0
        /// <summary>
        /// For a Point, last used Edge and possible Edges, retrieve the best next Edge
        /// </summary>
        /// <param name="point">The current Point</param>
        /// <param name="lastEdge">The last used Edge</param>
        /// <param name="possibleEdges">The possible next Edges</param>
        /// <returns>Best next Edge</returns>
        internal static PolygonEdge BestEdge(PolygonPoint point, PolygonEdge lastEdge, List <PolygonEdge> possibleEdges)
        {
            // If just Starting, return the first possible Edge of the Point
            // If only one possibility, return that
            if ((lastEdge.PointOne == null && lastEdge.PointTwo == null) || possibleEdges.Count == 1)
            {
                return(possibleEdges[0]);
            }

            // Variables needed to determine the next Edge
            var bestEdge  = possibleEdges[0];
            var bestAngle = (float)Math.PI * 2;
            // Vector from last Point to current Point
            var lastVector = (lastEdge.PointTwo.Point - lastEdge.PointOne.Point);

            lastVector.Normalize();
            // Using CCW Point Order, so the left Vector always points towards the Polygon Center
            var insideVector = new Point(-lastVector.Y, lastVector.X);

            // Check all possible Edges
            foreach (var possibleEdge in possibleEdges)
            {
                // Next Edge Vector
                var edgeVector = (possibleEdge.PointTwo.Point - possibleEdge.PointOne.Point);
                edgeVector.Normalize();
                // Dot determines if the Vector also points towards the Polygon Center or not (> 0, yes, < 0, no)
                var dot = insideVector.X * edgeVector.X + insideVector.Y * edgeVector.Y;
                // Cos represents the Angle between the last Edge and the next Edge
                var cos   = lastVector.X * edgeVector.X + lastVector.Y * edgeVector.Y;
                var angle = 0f;
                // Depending on the Dot-Value, calculate the actual "inner" Angle
                if ((insideVector.X * edgeVector.X + insideVector.Y * edgeVector.Y) > 0)
                {
                    angle = (float)Math.PI - (float)Math.Acos(cos);
                }
                else
                {
                    angle = (float)Math.PI + (float)Math.Acos(cos);
                }
                // Replace the old Values if a better Edge was found
                if (angle < bestAngle)
                {
                    bestAngle = angle;
                    bestEdge  = possibleEdge;
                }
            }
            return(bestEdge);
        }
Esempio n. 4
0
        /// <summary>
        /// 将孔的点添加到PolygonData
        /// Add Points of a Hole to the PolygonData
        /// </summary>
        /// <param name="points">The Points that define the Hole in the Polygon</param>
        internal void AddHole(List <Point> points)
        {
            // Make Hole Clockwise
            if (SweepLinePolygonTriangulator.IsCCW(points))
            {
                points.Reverse();
            }
            // The Hole Points
            var polyPoints = points.Select(p => new PolygonPoint(p)).ToList();

            // If Endpoint equals Startpoint
            if (polyPoints[0].Equals(polyPoints[polyPoints.Count - 1]))
            {
                polyPoints.RemoveAt(polyPoints.Count - 1);
            }
            mHoles.Add(polyPoints);

            var cntBefore  = mPoints.Count;
            var pointCount = points.Count;

            // Add the PolygonPoints for this Polygon Object
            mPoints.AddRange(polyPoints);

            // Add the Indices
            for (int i = cntBefore; i < mPoints.Count; i++)
            {
                polyPoints[i - cntBefore].Index = i;
            }

            // Add Edges between the Points (to be able to navigate along the Polygon easily later)
            var cnt = mPoints.Count;

            for (int i = 0; i < pointCount; i++)
            {
                var lastIdx = (i + pointCount - 1) % pointCount;
                var edge    = new PolygonEdge(polyPoints[lastIdx], polyPoints[i]);
                polyPoints[lastIdx].EdgeTwo = edge;
                polyPoints[i].EdgeOne       = edge;
            }
        }
Esempio n. 5
0
 /// <summary>
 /// Removes all StatusHelperElements with a specific Edge
 /// </summary>
 /// <param name="edge"></param>
 internal void Remove(PolygonEdge edge)
 {
     this.EdgesHelpers.RemoveAll(she => she.Edge == edge);
 }
Esempio n. 6
0
        /// <summary>
        /// Split Polygon into subpolagons using the calculated Diagonals
        /// </summary>
        /// <param name="poly">The Base-Polygon</param>
        /// <param name="diagonals">The Split-Diagonals</param>
        /// <returns>List of Subpolygons</returns>
        private static List <PolygonData> SplitIntoPolygons(PolygonData poly, List <Tuple <int, int> > diagonals)
        {
            if (diagonals.Count == 0)
            {
                return new List <PolygonData>()
                       {
                           poly
                       }
            }
            ;

            diagonals = diagonals.OrderBy(d => d.Item1).ThenBy(d => d.Item2).ToList();
            var edges = new SortedDictionary <int, List <PolygonEdge> >();

            foreach (var edge in poly.Points.Select(p => p.EdgeTwo)
                     .Union(diagonals.Select(d => new PolygonEdge(poly.Points[d.Item1], poly.Points[d.Item2])))
                     .Union(diagonals.Select(d => new PolygonEdge(poly.Points[d.Item2], poly.Points[d.Item1]))))
            {
                if (!edges.ContainsKey(edge.PointOne.Index))
                {
                    edges.Add(edge.PointOne.Index, new List <PolygonEdge>()
                    {
                        edge
                    });
                }
                else
                {
                    edges[edge.PointOne.Index].Add(edge);
                }
            }

            var subPolygons = new List <PolygonData>();

            var cnt = 0;

            foreach (var edge in edges)
            {
                cnt += edge.Value.Count;
            }

            // For each Diagonal
            while (edges.Count > 0)
            {
                // Start at first Diagonal Point
                var currentPoint     = edges.First().Value.First().PointOne;
                var nextEdge         = new PolygonEdge(null, null);
                var subPolygonPoints = new List <PolygonPoint>();
                // March along the edges to form a monotone Polygon
                // Until the current Point equals the StartPoint
                do
                {
                    // Add the current Point
                    subPolygonPoints.Add(currentPoint);
                    // Select the next Edge
                    var possibleEdges = edges[currentPoint.Index].ToList();
                    nextEdge = BestEdge(currentPoint, nextEdge, possibleEdges);
                    // Remove Edge from possible Edges
                    edges[currentPoint.Index].Remove(nextEdge);
                    if (edges[currentPoint.Index].Count == 0)
                    {
                        edges.Remove(currentPoint.Index);
                    }

                    // Move to the next Point
                    currentPoint = nextEdge.PointTwo;
                }while (subPolygonPoints[0].Index != currentPoint.Index);
                // Add the new SubPolygon
                subPolygons.Add(new PolygonData(subPolygonPoints));
            }

            return(subPolygons);
        }
Esempio n. 7
0
 /// <summary>
 /// Constructor taking an Edge and a Helper
 /// </summary>
 /// <param name="edge">The Edge of the StatusHelperElement</param>
 /// <param name="point">The Helper for the Edge of the StatusHelperElement</param>
 internal StatusHelperElement(PolygonEdge edge, PolygonPoint point)
 {
     this.Edge   = edge;
     this.Helper = point;
 }