【问题标题】:How to determine the next POI in a navigation route?如何确定导航路线中的下一个 POI?
【发布时间】:2014-10-07 15:53:38
【问题描述】:

我有一条路线(MKPolyline 派生自从 Apple 的 MKDirections API 检索的 MKRoute)和一组靠近路线的兴趣点(MKAnnotations 数组)。

我想知道如何选择用户将在路线后遇到的下一个 POI,以便通过 UI 呈现它。

我想到了两种不同的方法,但没有一个是真正足够的:

  • 第一个方法是在每次足够接近 POI 时将其标记为已检查,并简单地显示数组中第一个未标记的 POI(我们假设它们的顺序正确)。问题是,如果出于某种原因或另一个 POI 没有被检查,那么应用程序将永远显示它,而不是显示实际的下一个 POI。这种情况可能会出现,例如如果用户遵循的路线与建议的路线略有不同,则说明该路线距离 POI 不够近,无法对其进行检查;或者用户在第一个 POI 之后开始导航;等等。

  • 第二个是选择离用户最近的 POI(可能还带有标记系统以避免显示您刚刚检查的 POI)。但这仅适用于足够直的路线:有时在山区或其他蜿蜒的路线中,您可以更接近稍后实际穿越的点。我预计这种情况实际上会经常发生。

有什么想法吗?

【问题讨论】:

    标签: ios algorithm mapkit


    【解决方案1】:

    当我不得不在我们的一个应用程序中实现轮流时,我使用了您所说的第一个项目符号。为了弄清楚用户是否偏离了原始折线,我每次读取新位置时都会计算当前位置和线段之间的距离。一旦我检测到我没有遵循路径,我就会重新计算路线,同时为用户显示“重新计算...”消息。

    这是我的代码

    - (BOOL)isCoordinate:(CLLocationCoordinate2D)coordinate closeToPolyline:(MKPolyline *)polyline {
      CLLocationCoordinate2D polylineCoordinates[polyline.pointCount];
      [polyline getCoordinates:polylineCoordinates range:NSMakeRange(0, polyline.pointCount)];
    
      for (int i = 0; i < polyline.pointCount - 1; i++) {
        CLLocationCoordinate2D a = polylineCoordinates[i];
        CLLocationCoordinate2D b = polylineCoordinates[i + 1];
    
        double distance = [self distanceToPoint:MKMapPointForCoordinate(coordinate) fromLineSegmentBetween:MKMapPointForCoordinate(a) and:MKMapPointForCoordinate(b)];
        if (distance < 25) {
          return YES;
        }
      }
    
      return NO;
    }
    
    - (double)distanceToPoint:(MKMapPoint)p fromLineSegmentBetween:(MKMapPoint)l1 and:(MKMapPoint)l2 {
      double A = p.x - l1.x;
      double B = p.y - l1.y;
      double C = l2.x - l1.x;
      double D = l2.y - l1.y;
    
      double dot = A * C + B * D;
      double len_sq = C * C + D * D;
      double param = dot / len_sq;
    
      double xx, yy;
    
      if (param < 0 || (l1.x == l2.x && l1.y == l2.y)) {
        xx = l1.x;
        yy = l1.y;
      }
      else if (param > 1) {
        xx = l2.x;
        yy = l2.y;
      }
      else {
        xx = l1.x + param * C;
        yy = l1.y + param * D;
      }
    
      return MKMetersBetweenMapPoints(p, MKMapPointMake(xx, yy));
    }
    

    然后我打电话给- (BOOL)isCoordinate:(CLLocationCoordinate2D)coordinate closeToPolyline:(MKPolyline *)polyline {coordinate 是用户的当前位置,polyline 是您的MKDirections 的路径。

    在我的情况下,我不允许超过 25 米,但这可能取决于您的纬度/经度精度。

    也许它会帮助你或某人。

    【讨论】:

    • 谢谢!在我的情况下,我不想重新计算路线,因为它是向用户建议的预定义路径(公路旅行的组织者已经为参与者选择了这条特定路径)。但我确信这在另一个项目中会有用。
    • ho @peter 你从哪里调用这个方法 - (BOOL)isCoordinate:(CLLocationCoordinate2D)coordinate closeToPolyline:(MKPolyline *)polyline,是从 didUpdateLocation 来的吗?
    • @PramodShukla 是的,这是一个不错的调用方法。基本上,您可以在拥有最新 CLLocationCoordinate2D 的任何地方调用该方法
    【解决方案2】:

    使用以下伪度量,我将其称为路线距离。直观地说,它的工作方式类似于highway location markers。假设路线折线不接触或交叉自身(很简单)。对于折线的某段 pr 上的每个点 q,其中 p 首先出现,该点在我们的 1D 坐标系中的位置是欧几里得(球形?)从 pq 的距离,加上在 pr 之前的所有线段的长度。两个这样的点之间的路线距离是它们在我们的 1D 坐标系中的位置差异的绝对值。通过将这些点视为路线上的最近点,将路线距离扩展到路线外的点(this question about computing point-to-segment distance 的答案应该有助于计算最近的路线点)。

    按路线距离向用户显示最近的 POI(当该距离足够小时将其选中)。

    【讨论】:

    • 感谢您的回答。我认为不清楚的是我将如何根据沿路线的距离(相对于直线)来计算最近的 POI。
    • @KPM 我添加了描述。
    • 谢谢!我还发现了这个可能有用的相关问答:stackoverflow.com/questions/14789706/…
    猜你喜欢
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    相关资源
    最近更新 更多