/// <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); }
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()); }
/// <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); }
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); }
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); }
/// <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); }
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); }
/// <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); }
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}"); }
public static LucidLine Create(Map geometry) { return(LucidLine.Create(geometry.ToString())); }
public static LucidLine operator+(LucidLine first, LucidLine second) { return(LucidLine.Create(first.Vertices.Concat(second.Vertices))); }