Пример #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ComplexPolygon" /> class.
        /// </summary>
        /// <param name="paths">The paths.</param>
        public ComplexPolygon(params IPath[] paths)
        {
            Guard.NotNull(paths, nameof(paths));

            this.paths         = paths;
            this.internalPaths = new List <InternalPath>(this.paths.Length);

            if (paths.Length > 0)
            {
                float minX   = float.MaxValue;
                float maxX   = float.MinValue;
                float minY   = float.MaxValue;
                float maxY   = float.MinValue;
                float length = 0;

                foreach (IPath p in this.paths)
                {
                    if (p.Bounds.Left < minX)
                    {
                        minX = p.Bounds.Left;
                    }

                    if (p.Bounds.Right > maxX)
                    {
                        maxX = p.Bounds.Right;
                    }

                    if (p.Bounds.Top < minY)
                    {
                        minY = p.Bounds.Top;
                    }

                    if (p.Bounds.Bottom > maxY)
                    {
                        maxY = p.Bounds.Bottom;
                    }

                    foreach (ISimplePath s in p.Flatten())
                    {
                        var ip = new InternalPath(s.Points, s.IsClosed);
                        length += ip.Length;
                        this.internalPaths.Add(ip);
                    }
                }

                this.length = length;
                this.Bounds = new RectangleF(minX, minY, maxX - minX, maxY - minY);
            }
            else
            {
                this.length = 0;
                this.Bounds = RectangleF.Empty;
            }

            this.PathType = PathTypes.Mixed;
        }
Пример #2
0
        /// <inheritdoc />
        public int FindIntersections(PointF start, PointF end, Span <PointF> buffer, IntersectionRule intersectionRule)
        {
            this.EnsureInternalPathsInitalized();

            int totalAdded = 0;

            InternalPath.PointOrientation[] orientations = ArrayPool <InternalPath.PointOrientation> .Shared.Rent(buffer.Length); // the largest number of intersections of any sub path of the set is the max size with need for this buffer.

            Span <InternalPath.PointOrientation> orientationsSpan = orientations;

            try
            {
                foreach (var ip in this.internalPaths)
                {
                    Span <PointF> subBuffer = buffer.Slice(totalAdded);
                    Span <InternalPath.PointOrientation> subOrientationsSpan = orientationsSpan.Slice(totalAdded);

                    var position = ip.FindIntersectionsWithOrientation(start, end, subBuffer, subOrientationsSpan);
                    totalAdded += position;
                }

                Span <float> distances = stackalloc float[totalAdded];
                for (int i = 0; i < totalAdded; i++)
                {
                    distances[i] = Vector2.DistanceSquared(start, buffer[i]);
                }

                var activeBuffer           = buffer.Slice(0, totalAdded);
                var activeOrientationsSpan = orientationsSpan.Slice(0, totalAdded);
                SortUtility.Sort(distances, activeBuffer, activeOrientationsSpan);

                if (intersectionRule == IntersectionRule.Nonzero)
                {
                    totalAdded = InternalPath.ApplyNonZeroIntersectionRules(activeBuffer, activeOrientationsSpan);
                }
            }
            finally
            {
                ArrayPool <InternalPath.PointOrientation> .Shared.Return(orientations);
            }

            return(totalAdded);
        }
Пример #3
0
        /// <summary>
        /// Finds the intersections.
        /// </summary>
        /// <param name="start">The start.</param>
        /// <param name="end">The end.</param>
        /// <returns>The points along the line the intersect with the boundaries of the polygon.</returns>
        internal static IEnumerable <PointF> FindIntersections(this InternalPath path, Vector2 start, Vector2 end, IntersectionRule intersectionRule = IntersectionRule.OddEven)
        {
            var results = new List <PointF>();

            PointF[] buffer = ArrayPool <PointF> .Shared.Rent(path.PointCount);

            try
            {
                int hits = path.FindIntersections(start, end, buffer, intersectionRule);
                for (int i = 0; i < hits; i++)
                {
                    results.Add(buffer[i]);
                }
            }
            finally
            {
                ArrayPool <PointF> .Shared.Return(buffer);
            }

            return(results);
        }
Пример #4
0
        private void EnsureInternalPathsInitalized()
        {
            if (this.internalPaths == null)
            {
                lock (this.paths)
                {
                    if (this.internalPaths == null)
                    {
                        this.internalPaths = new List <InternalPath>(this.paths.Length);

                        foreach (var p in this.paths)
                        {
                            foreach (var s in p.Flatten())
                            {
                                var ip = new InternalPath(s.Points, s.IsClosed);
                                this.internalPaths.Add(ip);
                            }
                        }
                    }
                }
            }
        }
Пример #5
0
 private EllipsePolygon(CubicBezierLineSegment segment)
 {
     this.segment   = segment;
     this.innerPath = new InternalPath(segment, true);
 }