예제 #1
0
        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);
                        }
                    }
                }
            }
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        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);
                }
            }
        }
예제 #4
0
 public bool ExtentOverlaps(LucidPolygon other)
 {
     return(GeometryHelper.Intersects(this.AsExtent(), other.AsExtent()));
 }
예제 #5
0
 public ILucidExtent AsExtent()
 {
     return(GeometryHelper.CalculateExtent(this));
 }
예제 #6
0
 public ILucidExtent Buffer(double bufferSize)
 {
     return(GeometryHelper.Buffer(this, bufferSize));
 }