检查用户是否遵循路线(iphone)
我正在做一个基于导航的应用程序。 在这个应用程序中,我正在绘制从用户select的点的路线。 如果用户没有遵循路线,我有重新计算路线的要求。
计算我使用Google direction API
的路线。 并绘制我使用此代码的路线
- (void) drawRoute:(NSArray *) path { NSInteger numberOfSteps = path.count; [self.objMapView removeOverlays: self.objMapView.overlays]; CLLocationCoordinate2D coordinates[numberOfSteps]; for (NSInteger index = 0; index < numberOfSteps; index++) { CLLocation *location = [path objectAtIndex:index]; CLLocationCoordinate2D coordinate = location.coordinate; coordinates[index] = coordinate; } for( id <MKOverlay> ovr in [self.objMapView overlays]) { MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:ovr]; if (polylineView.tag == 22) { [self.objMapView removeOverlay:ovr]; } [polylineView release]; } MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps]; [self.objMapView addOverlay:polyLine]; }
直到现在,每件事情都是奥凯。
现在,我想要一个通知,如果用户不在路线(超过100米),我也可以得到通知
问题:如果道路平直(超过100米),那么我不能在道路上得分。 为了解释我附加的图像的问题…
在这个图像中,假设黑线是我的path(折线),红圈是我从Google apis获得的点。 但在蓝色圆圈所示的直线path我不能得到点进行比较,并在此path中重新计算函数被调用。
任何人都可以告诉我,即使是直路,我也可以得到所有路线点的解决scheme。
我知道这是一个古老的线程,但最近遇到了同样的问题,并find了一个好的解决scheme。 其概念是,您不计算到每条线段的距离,而只计算连接到最近点的两条线段。
- 计算您当前位置到MKPolyline中所有点的距离,并从中取最小值。 (有可能有一些很好的方法来优化这个,就像没有迭代每个位置更新上的所有点一样,但是没有时间去挖掘它们)。
- 您现在知道距离最近的折线点的距离。 然而,这一点可能仍然很远,而折线本身(连接这一点和上一点或下一点)可能会更接近。 所以,计算你的当前位置和这两条线段之间的距离,你有最近的距离。
现在,这不是防水的。 在某些情况下(如果你在MKPolyline中有疯狂的弯曲和弯曲),它可能会在不需要的时候调用api,但是,嘿,那么同样的行会再次被绘制,没有损害。 在我的testing中,它工作得很好,你也可以调整精度。 我已经把它设置在200米(0.2公里)在下面的代码。
//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; }
对于每一步中的每一对点,可以使用毕达哥拉斯定理计算它们之间的距离:
distance = sqrt( pow((point1.x - point2.x), 2) + pow((point1.y - point2.y), 2) )
那么,如果距离大于100米,沿线段添加中间点。