/// <summary> /// Finds the nearest point to the requested location that is within the tolerance radius. /// </summary> /// <param name="ProjectedRadius">The tolerance radius in projected units used to search for the nearest point that can be snapped to.</param> /// <param name="x">x coordinate in projected map units</param> /// <param name="y">y coordinate in projected map units</param> /// <param name="curShape">The shape that is currently being created. Points from this shape are also checked.</param> /// <param name="BestPoint">A PointD class with the location of the nearest point to snap to if there is are any within the tolerance, null if no points are found.</param> /// <returns>Returns true if there is a point to snap to.</returns> public bool CanSnap(double ProjectedRadius, double x, double y, ShapeClass curShape, ref System.Collections.ArrayList BestPoints) { System.Collections.IDictionaryEnumerator ie = m_lists.GetEnumerator(); PointD myBest = null; System.Collections.ArrayList myBestPoints = null; while (ie.MoveNext()) { int snaplayeridx = (int)ie.Key; // find any points that are within the tolerance in curShape. for (int i = 0; i < curShape.NumPoints; i++) { PointD pt = curShape[i]; double d = pt.Dist(x, y); if (d < ProjectedRadius) { if (myBest != null) { if (d < myBest.Dist(x, y)) { myBest = pt; } } else { myBest = pt; } } } if (myBest != null) { SnapData d = new SnapData(-1, -1, myBest); myBestPoints = new System.Collections.ArrayList(); myBestPoints.Add(d); } if (CanSnap(ProjectedRadius, x, y, ref BestPoints)) { // work with that best point. if (myBest != null) { PointD tPoint = ((SnapData)BestPoints[0]).point; if (myBest.Dist(x, y) < tPoint.Dist(x, y)) { if (BestPoints == null) { BestPoints = new System.Collections.ArrayList(); } BestPoints.AddRange(myBestPoints); } } } else { if (myBestPoints != null) { if (BestPoints == null) { BestPoints = new System.Collections.ArrayList(); } BestPoints.AddRange(myBestPoints); } } } if (BestPoints == null) { return(false); } else { return(true); } }
/********************************************************************/ // Test the point if it's within the line segements of the curShape // returns the insertIndex if within tolerance else -1 /********************************************************************/ private bool WithinTolerance(double x, double y, int shpIndex, double tol, ref double storeX, ref double storeY, ref int insertIndex) { int numPoints = 0; Point p1, p2; double m1, m2; double dist, shortestDist = 9999999999; double b1, b2; double newX, newY; int index = -1; try { //get the array of points for this shape MapWinGIS.Shapefile sf = m_Globals.CurrentLayer; System.Array points = sf.QuickPoints(shpIndex, ref numPoints); //System.Collections.ArrayList points = (System.Collections.ArrayList)m_Points[shpIndex]; if (numPoints <= 1) { return(false); } for (int p = 0; p < numPoints * 2 - 2; p += 2) { p1 = new Point((double)points.GetValue(p), (double)points.GetValue(p + 1)); p2 = new Point((double)points.GetValue(p + 2), (double)points.GetValue(p + 3)); //p1 = (Point)points[i]; //p2 = (Point)points[i+1]; //find the slope make sure there is no divide by zero if (p2.x == p1.x) { m1 = 0; } else { m1 = (p2.y - p1.y) / (p2.x - p1.x); } //find the y-intercept b1 = p1.y - m1 * p1.x; //find the slope of the perpendicular line relative to the given point if (m1 == 0) { m2 = 0; } else { m2 = -1 / m1; } //find the y-intercept of the perpendicular line relative to the given point b2 = y - m2 * x; //find the intersection point between the two lines if (m1 - m2 == 0) // Horizontal line { newX = p1.x; if (p1.y == p2.y) { newY = m1 * newX + b1; newX = x; } else { newY = m1 * newX + b2; } } else { newX = (b2 - b1) / (m1 - m2); newY = m1 * newX + b1; } //check to make sure the new point is within the line segment if (PointWithinLineSegementBounds(p1, p2, new Point(newX, newY))) { //find the dist between the cursor point and the new point dist = PointD.Dist(x, y, newX, newY); //keep track of the shortest distance if (dist <= shortestDist) { storeX = newX; storeY = newY; shortestDist = dist; index = p / 2; } } } if (shortestDist <= tol) { insertIndex = index + 1; return(true); } } catch (System.Exception ex) { m_MapWin.ShowErrorDialog(ex); } //the point is not within the line segment tolerance insertIndex = -1; return(false); }