/// <summary> /// Determines if the point is below the vertically projected segment intersection. /// </summary> /// <param name="yPtN">The y-coordinate of pt n.</param> /// <param name="yIntersection">The y-coordinate of the intersection of the projected line.</param> /// <param name="vertexI">The vertex i.</param> /// <param name="vertexJ">The vertex j.</param> /// <param name="includeEnds">if set to <c>true</c> [include ends].</param> /// <returns><c>true</c> if the point is below the vertically projected segment intersection, <c>false</c> otherwise.</returns> public static bool PointIsBelowSegmentIntersection( double yPtN, double yIntersection, Point vertexI, Point vertexJ, bool includeEnds = true) { return(yPtN < yIntersection && ProjectionHorizontal.PointIsWithinSegmentHeight(yIntersection, vertexI, vertexJ, includeEnds: includeEnds)); }
/// <summary> /// The numbers of shape boundary intersections a vertical line makes when projecting to the top from the provided point. /// If the point is on a vertex or segment, the function returns either 0 or 1. /// </summary> /// <param name="coordinate">The coordinate.</param> /// <param name="shapeBoundary">The shape boundary composed of n points.</param> /// <param name="includePointOnSegment">if set to <c>true</c> [include point on segment].</param> /// <param name="includePointOnVertex">if set to <c>true</c> [include point on vertex].</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Int32.</returns> public static int NumberOfIntersections( Point coordinate, Point[] shapeBoundary, bool includePointOnSegment = true, bool includePointOnVertex = true, double tolerance = GeometryLibrary.ZeroTolerance) { if (shapeBoundary[0] != shapeBoundary[shapeBoundary.Length - 1]) { throw new ArgumentException("Shape boundary describes a shape. Closure to the shape boundary is needed."); } // 1. Check vertical line projection from a pt. n to the top // 2. Count # of intersections of the line with shape edges // Note shape coordinates from XML already repeat starting node as an ending node. // No need to handle wrap-around below. int numberOfIntersections = 0; for (int i = 0; i < shapeBoundary.Length - 1; i++) { Point vertexI = shapeBoundary[i]; if (PointIntersection.PointsOverlap(coordinate, vertexI)) { return(includePointOnVertex ? 1 : 0); } Point vertexJ = shapeBoundary[i + 1]; if (!PointIsBelowSegmentBottom(coordinate.X, vertexI, vertexJ)) { // Pt is above the segment. continue; } bool pointIsWithinSegmentWidth = PointIsWithinSegmentWidth( coordinate.X, vertexI, vertexJ, includeEnds: includePointOnSegment); if (!pointIsWithinSegmentWidth) { // Point is out of horizontal bounds of the segment extents. continue; } bool pointIsWithinSegmentHeight = ProjectionHorizontal.PointIsWithinSegmentHeight( coordinate.Y, vertexI, vertexJ, includeEnds: includePointOnSegment); if (Segment.IsHorizontal(vertexI, vertexJ)) { if (pointIsWithinSegmentHeight) { // Point is on horizontal segment return(includePointOnSegment ? 1 : 0); } // Point hits horizontal segment numberOfIntersections++; continue; } if (Segment.IsVertical(vertexI, vertexJ)) { // Segment would be parallel to line projection. // Point is collinear since it is within segment height if (pointIsWithinSegmentHeight) { // Point is on vertical segment return(includePointOnSegment ? 1 : 0); } continue; } double yIntersection = IntersectionPointY(coordinate.X, vertexI, vertexJ); if (PointIsBelowSegmentIntersection(coordinate.Y, yIntersection, vertexI, vertexJ)) { numberOfIntersections++; } else if (NMath.Abs(coordinate.Y - yIntersection) < tolerance) { // Point is on sloped segment return(includePointOnSegment ? 1 : 0); } } return(numberOfIntersections); }