我知道这是一个旧线程,但最近遇到了同样的问题并找到了一个好的解决方案。这个概念是您不计算到每个线段的距离,而只计算到连接到最近点的两个线段的距离。
- 计算您当前位置到 MKPolyline 中所有点的距离,并从中取最小值。(可能有一些很好的方法来优化它。就像不迭代每次位置更新时的所有点,但现在没有时间深入研究)。
- 您现在知道到最近的折线点的距离。但是,该点可能仍然很远,而折线本身(连接该点和上一个或下一个点)可能更近。因此,计算您当前位置与这两个线段之间的距离,您就有了最近的距离。
现在,这不是防水的。虽然它最大限度地减少了 api 调用的 nr,但在某些情况下(如果您在 MKPolyline 中有疯狂的弯曲和曲线)它可能会在不需要时调用 api,但是嘿,那么将再次绘制相同的线,不会造成任何损坏。在我的测试中,它运行良好,您还可以调整准确性。我在下面的代码中将其设置为 200m(0.2km)。
//Get Coordinates of points in MKPolyline
NSUInteger pointCount = routeLineGuidanceTurn.pointCount;
CLLocationCoordinate2D *routeCoordinates = malloc(pointCount * sizeof(CLLocationCoordinate2D));
[routeLineGuidanceTurn getCoordinates:routeCoordinates
range:NSMakeRange(0, pointCount)];
NSLog(@"route pointCount = %d", pointCount);
//Determine Minimum Distance and GuidancePoints from
double MinDistanceFromGuidanceInKM = 1000;
CLLocationCoordinate2D prevPoint;
CLLocationCoordinate2D pointWithMinDistance;
CLLocationCoordinate2D nextPoint;
for (int c=0; c < pointCount; c++)
{
double newDistanceInKM = [self distanceBetweentwoPoints:Currentcordinate.latitude longitude:Currentcordinate.longitude Old:routeCoordinates[c].latitude longitude:routeCoordinates[c].longitude];
if (newDistanceInKM < MinDistanceFromGuidanceInKM) {
MinDistanceFromGuidanceInKM = newDistanceInKM;
prevPoint = routeCoordinates[MAX(c-1,0)];
pointWithMinDistance = routeCoordinates[c];
nextPoint = routeCoordinates[MIN(c+1,pointCount-1)];
}
}
free(routeCoordinates);
NSLog(@"MinDistanceBefore: %f",MinDistanceFromGuidanceInKM);
//If minimum distance > 200m we might have to recalc GuidanceLine.
//To be sure we take the two linesegments connected to the point with the shortest distance and calculate the distance from our current position to that linedistance.
if (MinDistanceFromGuidanceInKM > 0.2) {
MinDistanceFromGuidanceInKM = MIN(MIN([self lineSegmentDistanceFromOrigin:Currentcordinate onLineSegmentPointA:prevPoint pointB:pointWithMinDistance], [self lineSegmentDistanceFromOrigin:Currentcordinate onLineSegmentPointA:pointWithMinDistance pointB:nextPoint]),MinDistanceFromGuidanceInKM);
if (MinDistanceFromGuidanceInKM > 0.2) {
// Call the API and redraw the polyline.
}
}
这是计算两点之间距离的乐趣。我知道它有一个内置函数,但我的代码中已经有了它。
-(double)distanceBetweentwoPoints:(double)Nlat longitude:(double)Nlon Old:(double)Olat longitude:(double)Olon {
//NSLog(@"distanceBetweentwoPoints");
double Math=3.14159265;
double radlat1 = Math* Nlat/180;
double radlat2 = Math * Olat/180;
double theta = Nlon-Olon;
double radtheta = Math * theta/180;
double dist = sin(radlat1) * sin(radlat2) + cos(radlat1) * cos(radlat2) * cos(radtheta);
if (dist>1) {dist=1;} else if (dist<-1) {dist=-1;}
dist = acos(dist);
dist = dist * 180/Math;
dist = dist * 60 * 1.1515;
return dist * 1.609344;
}
这是计算点与其他两个点之间的线段之间距离的位。我从这里得到了这个:https : //stackoverflow.com/a/28028023/3139134 对其进行了一些修改以使用 CLLocationCoordinate2D 并返回距离。
- (CGFloat)lineSegmentDistanceFromOrigin:(CLLocationCoordinate2D)origin onLineSegmentPointA:(CLLocationCoordinate2D)pointA pointB:(CLLocationCoordinate2D)pointB {
CGPoint dAP = CGPointMake(origin.longitude - pointA.longitude, origin.latitude - pointA.latitude);
CGPoint dAB = CGPointMake(pointB.longitude - pointA.longitude, pointB.latitude - pointA.latitude);
CGFloat dot = dAP.x * dAB.x + dAP.y * dAB.y;
CGFloat squareLength = dAB.x * dAB.x + dAB.y * dAB.y;
CGFloat param = dot / squareLength;
CGPoint nearestPoint;
if (param < 0 || (pointA.longitude == pointB.longitude && pointA.latitude == pointB.latitude)) {
nearestPoint.x = pointA.longitude;
nearestPoint.y = pointA.latitude;
} else if (param > 1) {
nearestPoint.x = pointB.longitude;
nearestPoint.y = pointB.latitude;
} else {
nearestPoint.x = pointA.longitude + param * dAB.x;
nearestPoint.y = pointA.latitude + param * dAB.y;
}
CGFloat dx = origin.longitude - nearestPoint.x;
CGFloat dy = origin.latitude - nearestPoint.y;
return sqrtf(dx * dx + dy * dy) * 100;
}