예제 #1
0
        /// <summary>
        /// Splits the path at the given point if the point lies on the path.
        /// </summary>
        /// <param name="path">Path to split</param>
        /// <param name="splitPoint">Point at which to cut the path</param>
        /// <returns>An enumeration of parts, or a single part if no split occurred</returns>
        public static IEnumerable <ILucidLine> Split(IEnumerable <IPoint> path, IPoint splitPoint)
        {
            var current = new LucidLine();

            current.AddVertex(path.First());

            foreach (var vertices in path.SlidingWindow(2))
            {
                var line = new AlgebraicLine(vertices);

                var lineExtent = CalculateExtent(line);
                if (Intersects(splitPoint, lineExtent))
                {
                    current.AddVertex(splitPoint);
                    yield return(current);

                    current = new LucidLine();
                    current.AddVertex(splitPoint);
                }

                current.AddVertex(line.End);
            }

            yield return(current);
        }
예제 #2
0
        public static IEnumerable <ILucidVertex> RemoveSelfIntersections(ILucidLine lineIn)
        {
            var segments = (from s in lineIn.Vertices.SlidingWindow(2)
                            select s).Where(w => w.Count() == 2).ToArray();

            var state = true;

            foreach (var segment in segments)
            {
                if (state == true)
                {
                    yield return(segment.First());
                }

                foreach (var otherSegment in from s in segments
                         where s != segment
                         select s)
                {
                    var intersect = GeometryHelper.LineIntersections(LucidLine.Create(segment), LucidLine.Create(otherSegment)).Any();
                    if (intersect)
                    {
                        state = !state;
                        break;
                    }
                }
            }

            yield return(lineIn.Vertices.Last());
        }
예제 #3
0
        /// <summary>
        /// Splits the path by the supplied by line
        /// </summary>
        /// <param name="path">Path to split</param>
        /// <param name="cutter">Cutter to cut the path by</param>
        /// <returns>An enumeration of parts, or a single part if not split occurred</returns>
        public static IEnumerable <ILucidLine> Split(IEnumerable <IPoint> path, ILucidLine cutter)
        {
            var current = new LucidLine();

            current.AddVertex(path.First());

            foreach (var vertices in path.SlidingWindow(2))
            {
                var line       = new AlgebraicLine(vertices);
                var lineExtent = CalculateExtent(line);

                foreach (var cutterLine in cutter.Vertices.SlidingWindow(2))
                {
                    var byLine       = new AlgebraicLine(cutterLine);
                    var intersection = Intersection(line, byLine);

                    if (intersection != null && Intersects(intersection, lineExtent) &&
                        Intersects(intersection, CalculateExtent(byLine)))
                    {
                        current.AddVertex(intersection);
                        yield return(current);

                        current = new LucidLine();
                        current.AddVertex(intersection);
                        break;
                    }
                }

                current.AddVertex(line.End);
            }

            yield return(current);
        }
예제 #4
0
        public static ILucidLine FixDuplicateVertices(ILucidLine geometry, int precision = 2)
        {
            var vertexHash  = new HashSet <string>();
            var newVertices = new List <ILucidVertex>();

            var vertices = geometry.Vertices.ToArray();

            for (int i = 0; i < vertices.Length; i++)
            {
                var vertex = vertices[i];
                var id     = vertex.ToString(precision);
                if (!vertexHash.Contains(id))
                {
                    vertexHash.Add(id);
                    newVertices.Add(vertex);
                }
                else if (i == vertices.Length - 1)
                {
                    // We want to remove the interior duplicate not the last vertex
                    newVertices.Remove(newVertices.First(v => v.ToString(precision) == id));
                    newVertices.Add(vertex);
                }
            }

            var lineOut = LucidLine.Create(newVertices);

            return(lineOut);
        }
예제 #5
0
        public static LucidPolygon operator-(LucidPolygon first, LucidPolygon second)
        {
            throw new NotImplementedException();

            LucidPolygon intersection = null;

            if (!first.ExtentOverlaps(second))
            {
                return(null);
            }

            foreach (var segment in first.Vertices.SlidingWindow(2))
            {
                foreach (var secondSegment in second.Vertices.SlidingWindow(2))
                {
                    var point = GeometryHelper.LineIntersections(LucidLine.Create(segment), LucidLine.Create(secondSegment)).FirstOrDefault();
                    if (point != null)
                    {
                        if (intersection == null)
                        {
                            intersection = new LucidPolygon();
                        }

                        intersection += point;
                    }
                }
            }

            return(intersection);
        }
예제 #6
0
        /// <summary>
        /// Returns the nearest line segment from a line
        /// </summary>
        /// <param name="wholeLine"></param>
        /// <param name="referencePoint"></param>
        /// <returns></returns>
        public static ILucidLine NearestLineSegment(ILucidLine wholeLine, IPoint referencePoint)
        {
            if (wholeLine.Vertices.Count() == 2)
            {
                return(wholeLine);
            }

            var vertices = wholeLine.Vertices.SlidingWindow(2);
            var first    = LucidLine.Create(vertices.First());
            var last     = LucidLine.Create(vertices.Last());

            var nearest = NearestGeometry(referencePoint, first, last).First();

            return((ILucidLine)nearest);
        }
예제 #7
0
        public static bool Intersects(IPoint point, ILucidLine line, bool infinitLine = false, int precision = 1)
        {
            var coincidentPoint = line.Vertices.Where(v => v.IsCoincident(point)).FirstOrDefault();

            if (coincidentPoint == null)
            {
                var pointLine = LucidLine.Create(new IPoint[] {
                    new LucidPoint(0, 0),
                    point
                });

                var intersection = LineIntersections(pointLine, line, infinitLine).FirstOrDefault();
                if (intersection == null || !GeometryHelper.IsCoincident(intersection, point, precision))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #8
0
        /// <summary>
        /// Creates a circular path form the provided referenc point, with the provided radius (size) and number of vertices
        /// </summary>
        /// <param name="point">Center point</param>
        /// <param name="size">The radius of the circular path around the center point</param>
        /// <param name="vertexOutCount">The number of vertices on the path</param>
        /// <returns></returns>
        public static ILucidLine CircularPathFromPoint(IPoint point, double size, int vertexOutCount)
        {
            double vertextSpacing = ((2d * Math.PI) / (double)vertexOutCount);
            double currentAngle   = 0;
            var    lineOut        = new LucidLine();

            for (int i = 0; i < vertexOutCount; i++)
            {
                lineOut.AddVertex(new LucidVertex()
                {
                    X = (size * Math.Cos(currentAngle)) + point.X,
                    Y = (size * Math.Sin(currentAngle)) + point.Y
                });

                currentAngle += vertextSpacing;
            }

            lineOut.AddVertex(lineOut.Vertices.First());

            return(lineOut);
        }
예제 #9
0
        public static ILucidGeometry Create(string geometryJson)
        {
            if (geometryJson.Contains("\"x\""))
            {
                return(LucidPoint.Create(geometryJson));
            }
            if (geometryJson.Contains("\"xmax\""))
            {
                return(LucidExtent.Create(geometryJson));
            }
            if (geometryJson.Contains("\"paths\""))
            {
                return(LucidLine.Create(geometryJson));
            }
            if (geometryJson.Contains("\"rings\""))
            {
                return(LucidPolygon.Create(geometryJson));
            }

            throw new Exception($"Unrecognized geometry type {geometryJson}");
        }
예제 #10
0
 public static LucidLine Create(Map geometry)
 {
     return(LucidLine.Create(geometry.ToString()));
 }
예제 #11
0
 public static LucidLine operator+(LucidLine first, LucidLine second)
 {
     return(LucidLine.Create(first.Vertices.Concat(second.Vertices)));
 }