/// <summary> /// The y-coordinate of the intersection of the vertically projected line with the provided segment. /// </summary> /// <param name="xPtN">The x-coordinate of pt n, where the projection starts.</param> /// <param name="ptI">Vertex i of the segment.</param> /// <param name="ptJ">Vertex j of the segment.</param> /// <returns>System.Double.</returns> public static double IntersectionPointY( double xPtN, CartesianCoordinate ptI, CartesianCoordinate ptJ) { if (LinearCurve.IsVertical(ptI, ptJ)) { throw new ArgumentException("Segment is vertical, so intersection point is either infinity or NAN."); } LinearCurve curve = new LinearCurve(ptI, ptJ); return(curve.Y(xPtN)); }
/// <summary> /// The numbers of shape boundary intersections a horizontal line makes when projecting to the right from the provided point. /// An odd number indicates the point is inside the shape. /// An even number indicates the point is outside the shape. /// If the point is on a vertex or segment, the function returns 0. /// </summary> /// <param name="coordinate">The coordinate.</param> /// <param name="shapeBoundary">The shape boundary composed of n points.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Int32.</returns> /// <exception cref="System.ArgumentException">Shape boundary describes a shape. Closure to the shape boundary is needed.</exception> public static int NumberOfIntersectionsOnHorizontalProjection( CartesianCoordinate coordinate, CartesianCoordinate[] shapeBoundary, 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 horizontal line projection from a pt. n to the right // 2. Count # of intersections of the line with shape edges int currentNumberOfIntersections = 0; for (int i = 0; i < shapeBoundary.Length - 1; i++) { CartesianCoordinate vertexI = shapeBoundary[i]; if (PointIntersection.IsOnPoint(coordinate, vertexI)) { // Pt lies on vertex return(0); } CartesianCoordinate vertexJ = shapeBoundary[i + 1]; LineSegment segment = new LineSegment(vertexI, vertexJ); if (segment.IncludesCoordinate(coordinate)) { // Pt lies on boundary return(0); } if (!PointIsLeftOfLineEndInclusive(coordinate.X, vertexI, vertexJ)) { // Pt is to the right of the line segment. continue; } if (!PointIsWithinLineHeightInclusive(coordinate.Y, vertexI, vertexJ)) { // Pt is out of vertical bounds of the line segment. continue; } LinearCurve segmentCurve = segment.Curve; if (segmentCurve.IsHorizontal()) { // Projection is tangent to segment continue; } if (pointHorizontalProjectionIntersectsVertex(coordinate, vertexI)) { // Projection hits vertex at point I. Do offset check on current segment if (slopeIsDownwardBetweenCoordinates(vertexI, vertexJ, tolerance)) { continue; } currentNumberOfIntersections++; continue; } if (pointHorizontalProjectionIntersectsVertex(coordinate, vertexJ)) { // Projection hits vertex at point J. Do offset check on current segment if (slopeIsDownwardBetweenCoordinates(vertexJ, vertexI, tolerance)) { continue; } currentNumberOfIntersections++; continue; } if (segmentCurve.IsVertical()) { // Projection hits vertical segment currentNumberOfIntersections++; continue; } currentNumberOfIntersections += numberOfIntersectionsHorizontal(coordinate, vertexI, vertexJ); } return(currentNumberOfIntersections); }