public static IEnumerable <IPoint> LineIntersections(ILucidLine first, ILucidLine second, bool infinitLines = false) { var firstExtent = CalculateExtent(first); var secondExtent = CalculateExtent(second); if (infinitLines || GeometryHelper.Intersects(first, second)) { foreach (var firstLine in from p in first.Vertices.TumblingWindow(2) select new AlgebraicLine(p.First(), p.Last())) { foreach (var secondLine in from p in second.Vertices.TumblingWindow(2) select new AlgebraicLine(p.First(), p.Last())) { var intersection = Intersection(firstLine, secondLine); if (intersection != null && (infinitLines || (GeometryHelper.Intersects(intersection, firstExtent) && GeometryHelper.Intersects(intersection, secondExtent)))) { yield return(intersection); } } } } }
/// <summary> /// Finds the largest angular gap between lines that all touch at a reference point /// and returns the angle, in degrees, of a line passing through the reference point /// that bisects that widest angle. /// </summary> /// <param name="referencePoint">The point of reference for calculating angles.</param> /// <param name="lines">The lines to avoid</param> /// <returns>An optimal angle for placment for a point</returns> public static double GetPlacementAngleAvoidingExistingLines(IPoint referencePoint, IEnumerable <IEnumerable <IPoint> > existingLines) { var lineAngles = new SortedList <double, double>(); foreach (var line in existingLines) { var lineVertices = line.ToList(); if (lineVertices.Count < 2) { continue; } var anglePoints = new List <IPoint>(); if (NearlyCoincident(referencePoint, lineVertices.First(), 0.001)) { anglePoints.Add(lineVertices[1]); } else if (NearlyCoincident(referencePoint, lineVertices.Last(), 0.001)) { anglePoints.Add(lineVertices[lineVertices.Count - 2]); } else { var vertices = lineVertices.SlidingWindow(3); foreach (var window3 in vertices) { var v3 = window3.ToList(); if (NearlyCoincident(v3[1].AsVertex(), referencePoint.AsVertex(), 0.001)) { anglePoints.Add(v3[0]); anglePoints.Add(v3[2]); } } } var angles = anglePoints.Select(p => GeometryHelper.Angle(referencePoint, p)); // The angles so far are in the range (-Pi, Pi), but we need them normalized // to the range (0, 2Pi). angles = angles.Select(a => a >= 0 ? a : a + 2D * Math.PI); foreach (var a in angles) { if (!lineAngles.ContainsKey(a)) { lineAngles.Add(a, a); } } } // Special case: if there is only one line terminating on the reference point, // then we will recommend placement at a 90 degree angle to that line. if (lineAngles.Count == 1) { var perpendicularAngle = lineAngles.Keys[0] + 0.5 * Math.PI; return(180D * perpendicularAngle / Math.PI); } // Find the bisector angle of the largest angular gap between adjacent line angles. double bisectorAngle = 0; double maxDiff = double.MinValue; for (int i = 0; i < lineAngles.Count; i++) { var angle1 = lineAngles.Keys[i]; var angle2 = lineAngles.Keys[(i + 1) % lineAngles.Count]; if (IsPrettyMuchTheSame(angle1, angle2, 0.000001)) { continue; } var diff = angle2 - angle1; if (diff < 0) { diff = 2d * Math.PI + diff; } var bisector = angle1 + diff / 2.0D; if (bisector > 2D * Math.PI) { bisector -= 2D * Math.PI; } if (diff > maxDiff) { maxDiff = diff; bisectorAngle = bisector; } } return(180D * bisectorAngle / Math.PI); }
public static IEnumerable <ILucidGeometry> FindNearby(IEnumerable <IPoint> referencePoints, double distance, IEnumerable <ILucidGeometry> geometries, bool recursive = false) { var nearbyGeometries = (from g in geometries let nearbyVertices = from v in g.Vertices where referencePoints.Where(p => GeometryHelper.DistanceBetween(p, v) < distance).Any() select v where nearbyVertices.Any() select g); foreach (var geometry in nearbyGeometries) { yield return(geometry); } if (recursive && nearbyGeometries.Any()) { foreach (var nearby in FindNearby(nearbyGeometries.SelectMany(g => g.Vertices), distance, geometries.Except(nearbyGeometries), recursive)) { yield return(nearby); } } }
public bool ExtentOverlaps(LucidPolygon other) { return(GeometryHelper.Intersects(this.AsExtent(), other.AsExtent())); }
public ILucidExtent AsExtent() { return(GeometryHelper.CalculateExtent(this)); }
public ILucidExtent Buffer(double bufferSize) { return(GeometryHelper.Buffer(this, bufferSize)); }