Пример #1
0
        internal List <Polygon> Cut(Vector v1, Vector v2, double cutRadius)
        {
            var clone = new Polygon(this);

            Vector.MarkDefault = VectorMark.Selected;
            int numberOfIntersections = 0;

            for (int i = 0; i < Vertices.Count; i++)
            {
                Vector isectPoint = GeometryUtils.GetIntersectionPoint(this[i], this[i + 1], v1, v2);
                if ((object)isectPoint != null)
                {
                    clone.InsertIntersection(isectPoint, Constants.Tolerance);
                    numberOfIntersections++;
                }
            }

            Vector.MarkDefault = VectorMark.None;
            if (numberOfIntersections % 2 == 0 && numberOfIntersections > 0)
            {
                var result = new List <Polygon> {
                    new Polygon()
                };
                int  k           = 0;
                bool isBeginning = true;
                while (k != clone.Count)
                {
                    if (clone.Vertices[k].Mark == VectorMark.Selected)
                    {
                        Vector cutVector = clone[k + 1] - clone[k - 1];
                        cutVector /= cutVector.Length;
                        var angleAbs = Math.Abs(cutVector.AngleBetween(v2 - v1));
                        if (angleAbs < Constants.Tolerance)
                        {
                            return(null);
                        }

                        cutVector *= cutRadius / Math.Sin(angleAbs * Constants.DegToRad);
                        double distance1 = (clone[k + 1] - clone[k]).Length;
                        double distance2 = (clone[k] - clone[k - 1]).Length;
                        if (cutVector.Length > Math.Min(distance1, distance2))
                        {
                            cutVector = cutVector / cutVector.Length * Math.Min(distance1, distance2) / 2;
                        }
                        if (!isBeginning)
                        {
                            result[result.Count - 1].Add(clone.Vertices[k] - cutVector);
                            result[0].Add(clone.Vertices[k] + cutVector);
                        }
                        else
                        {
                            result.Add(new Polygon());
                            result[result.Count - 1].Add(clone.Vertices[k] + cutVector);
                            result[0].Add(clone.Vertices[k] - cutVector);
                        }

                        isBeginning = !isBeginning;
                    }
                    else
                    {
                        if (isBeginning)
                        {
                            result[0].Add(clone.Vertices[k]);
                        }
                        else
                        {
                            result[result.Count - 1].Add(clone.Vertices[k]);
                        }
                    }

                    k++;
                }

                result.ForEach(p => p.IsGrass = IsGrass);
                return(result.Any(polygon => polygon.Count < 3) ? null : result);
            }

            return(null);
        }
Пример #2
0
        internal static Polygon Connect(Polygon p1, Polygon p2, Vector v1, Vector v2, double connectRadius)
        {
            if (p1.IntersectsWith(p2))
            {
                return(null);
            }
            bool isContained = p1.AreaHasPoint(p2[0]) || p2.AreaHasPoint(p1[0]);
            var  p1C         = new Polygon(p1);
            var  p2C         = new Polygon(p2);

            if (p1C.IsCounterClockwise)
            {
                p1C.ChangeOrientation();
            }
            if (p2C.IsCounterClockwise ^ isContained)
            {
                p2C.ChangeOrientation();
            }
            int    numberOfIntersectionsP1C = 0;
            int    numberOfIntersectionsP2C = 0;
            Vector p1IsectPoint             = null;
            Vector p2IsectPoint             = null;

            Vector.MarkDefault = VectorMark.Selected;
            for (int i = 0; i < p1.Vertices.Count; i++)
            {
                Vector isectPoint = GetIntersectionPoint(p1[i], p1[i + 1], v1, v2);
                if ((object)isectPoint != null)
                {
                    p1IsectPoint = isectPoint;
                    p1C.InsertIntersection(p1IsectPoint, Constants.Tolerance);
                    numberOfIntersectionsP1C++;
                }
            }

            if (numberOfIntersectionsP1C != 1)
            {
                return(null);
            }
            for (int i = 0; i < p2.Vertices.Count; i++)
            {
                Vector isectPoint = GetIntersectionPoint(p2[i], p2[i + 1], v1, v2);
                if ((object)isectPoint != null)
                {
                    p2IsectPoint = isectPoint;
                    p2C.InsertIntersection(p2IsectPoint, Constants.Tolerance);
                    numberOfIntersectionsP2C++;
                }
            }

            Vector.MarkDefault = VectorMark.None;
            if (numberOfIntersectionsP2C != 1)
            {
                return(null);
            }
            var    result          = new Polygon();
            int    p1Index         = 0;
            int    p2Index         = p2C.IndexOf(p2IsectPoint);
            bool   p1CCurrent      = true;
            Vector p1ConnectVector = null;
            Vector p2ConnectVector = null;

            while (!(p1Index == 0 && p1CCurrent && result.Count > 0))
            {
                if (p1CCurrent)
                {
                    if (p1C[p1Index].Mark != VectorMark.Selected)
                    {
                        result.Add(p1C[p1Index]);
                    }
                    else
                    {
                        p1ConnectVector  = p1C[p1Index + 1] - p1C[p1Index - 1];
                        p1ConnectVector /= p1ConnectVector.Length;
                        var p1AngleAbs = Math.Abs(p1ConnectVector.AngleBetween(v2 - v1));
                        if (p1AngleAbs < Constants.Tolerance)
                        {
                            return(null);
                        }

                        p1ConnectVector *= connectRadius /
                                           Math.Sin(p1AngleAbs * Constants.DegToRad);
                        double distance1 = (p1C[p1Index + 1] - p1C[p1Index]).Length;
                        double distance2 = (p1C[p1Index] - p1C[p1Index - 1]).Length;
                        if (p1ConnectVector.Length > Math.Min(distance1, distance2))
                        {
                            p1ConnectVector = p1ConnectVector / p1ConnectVector.Length *
                                              Math.Min(distance1, distance2) /
                                              2;
                        }
                        result.Add(p1IsectPoint - p1ConnectVector);

                        p2ConnectVector  = p2C[p2Index + 1] - p2C[p2Index - 1];
                        p2ConnectVector /= p2ConnectVector.Length;
                        var p2AngleAbs = Math.Abs(p2ConnectVector.AngleBetween(v2 - v1));
                        if (p2AngleAbs < Constants.Tolerance)
                        {
                            return(null);
                        }

                        p2ConnectVector *= connectRadius /
                                           Math.Sin(p2AngleAbs * Constants.DegToRad);
                        double dist1 = (p2C[p2Index + 1] - p2C[p2Index]).Length;
                        double dist2 = (p2C[p2Index] - p2C[p2Index - 1]).Length;
                        if (p2ConnectVector.Length > Math.Min(dist1, dist2))
                        {
                            p2ConnectVector = p2ConnectVector / p2ConnectVector.Length * Math.Min(dist1, dist2) / 2;
                        }
                        result.Add(p2IsectPoint + p2ConnectVector);

                        p2Index++;
                        p1CCurrent = false;
                    }

                    p1Index++;
                    p1Index = p1Index % p1C.Count;
                }
                else
                {
                    if (p2C[p2Index].Mark != VectorMark.Selected)
                    {
                        result.Add(p2C[p2Index]);
                    }
                    else
                    {
                        result.Add(p2IsectPoint - p2ConnectVector);
                        result.Add(p1IsectPoint + p1ConnectVector);
                        p1CCurrent = true;
                    }

                    p2Index++;
                }
            }

            result.UpdateDecomposition();
            return(result);
        }