/// <summary> /// Gets the point on this line that is closest to a specified position. /// </summary> /// <param name="p">The position to search from.</param> /// <param name="tol">Maximum distance from line to the search position</param> /// <returns>The closest position (null if the line is further away than the specified /// max distance)</returns> internal override IPosition GetClosest(IPointGeometry p, ILength tol) { // Get the distance from the centre of the circle to the search point. IPointGeometry center = m_Circle.Center; double dist = Geom.Distance(center, p); // Return if the search point is beyond tolerance. double radius = m_Circle.Radius; double diff = Math.Abs(dist - radius); if (diff > tol.Meters) { return(null); } // If the vertex lies in the curve sector, the closest position // is along the bearing from the centre through the search // position. Otherwise the closest position is the end of // the curve that's closest (given that it's within tolerance). if (CircularArcGeometry.IsInSector(this, p, 0.0)) { double bearing = Geom.BearingInRadians(center, p); return(Geom.Polar(center, bearing, radius)); } double d1 = Geom.DistanceSquared(p, BC); double d2 = Geom.DistanceSquared(p, EC); double t = tol.Meters; if (Math.Min(d1, d2) < (t * t)) { if (d1 < d2) { return(BC); } else { return(EC); } } return(null); }
/// <summary> /// Cuts back a horizontal line segment to the closest intersection with this line. /// Used in point in polygon. /// </summary> /// <param name="s">Start of horizontal segment.</param> /// <param name="e">End of segment (will be modified if segment intersects this line)</param> /// <param name="status">Return code indicating whether an error has arisen (returned /// as 0 if no error).</param> /// <returns>True if the horizontal line was cut back.</returns> internal override bool GetCloser(IPointGeometry s, ref PointGeometry e, out uint status) { status = 0; // Get the window of the circle that this curve lies on. IWindow cwin = m_Circle.Extent; // Get a window for the horizontal segment. IWindow segwin = new Window(s, e); // Return if the windows don't overlap. if (!cwin.IsOverlap(segwin)) { return(false); } // Return if the the segment is to the west of the circle's window. if (segwin.Max.X < cwin.Min.X) { return(false); } // Represent the horizontal segment in a class of its own HorizontalRay hseg = new HorizontalRay(s, e.X - s.X); if (!hseg.IsValid) { status = 1; return(false); } // Locate up to two intersections of the horizontal segment with the circle. IPosition x1 = null; IPosition x2 = null; uint nx = hseg.Intersect(m_Circle, ref x1, ref x2); // Return if no intersections if (nx == 0) { return(false); } // Return if this arc curve is a complete circle. if (this.IsCircle) { return(false); } // Check whether the first intersection lies on this arc. If // so, update the end of segment, and return. if (CircularArcGeometry.IsInSector(this, x1, 0.0)) { e = new PointGeometry(x1); return(true); } // If we got two intersections with the circle, check the // second intersection as well. if (nx == 2 && CircularArcGeometry.IsInSector(this, x2, 0.0)) { e = new PointGeometry(x2); return(true); } return(false); }