【问题标题】:Which segment of a polyline was clicked?点击了折线的哪一段?
【发布时间】:2012-04-04 19:32:41
【问题描述】:

我已经设置了sample polyline with five segments,并且允许在用户单击折线时创建新标记。

我想知道是否有一种万无一失的方法来确定新标记是否在标记 0 和 1 之间,或 1 和 2 ... 或 4 和 5 之间。我考虑过检查新标记是否在边界框内,以及直线公式,但都不是 100% 精确的。

【问题讨论】:

    标签: javascript google-maps google-maps-api-3 map-projections


    【解决方案1】:

    由于 Google 地图使用 Mercator Projection 来投影 GPS 坐标,因此您不能将“直线方程”用于 gps 坐标,因为投影对于 gps 点来说不是线性的。但是您可以使用线性的 world coordinates。这里我使用线方程的参数形式来检查point是否在segment上:

    function isPointOnSegment( map, gpsPoint1, gpsPoint2, gpsPoint ){
         var p1 = map.getProjection().fromLatLngToPoint( gpsPoint1 );
         var p2 = map.getProjection().fromLatLngToPoint( gpsPoint2 );
         var p = map.getProjection().fromLatLngToPoint( gpsPoint );
         var t_x;
         var t_y;
         //Parametric form of line equation is:
         //--------------------------------
         //      x = x1 + t(x2-x1)
         //      y = y1 + t(y2-y1) 
         //--------------------------------
         //'p' is on [p1,p2] segment,if 't' is number from [0,1]
         //-----Case 1----
         //      x = x1
         //      y = y1
         //---------------
         if( p2.x-p1.x == 0 && p2.y-p1.y == 0){
            return p.x == p1.x && p.y == p1.y;
         }else 
         //-----Case 2----
         //      x = x1
         //      y = y1 + t(y2-y1)
         //---------------
         if( p2.x-p1.x == 0 && p2.y-p1.y != 0){
            t_y = (p.y - p1.y)/(p2.y-p1.y);
            return p.x == p1.x && t_y >= 0 && t_y <= 1;
         }else
         //-----Case 3----
         //      x = x1 + t(x2-x1)
         //      y = y1 
         //---------------
         if( p2.x-p1.x != 0 && p2.y-p1.y == 0){
            t_x = (p.x - p1.x)/(p2.x-p1.x);
            return p.y == p1.y && t_x >= 0 && t_x <= 1;
         }
         //-----Case 4----
         //      x = x1 + t(x2-x1)
         //      y = y1 + t(y2-y1) 
         //---------------
         t_x = (p.x - p1.x)/(p2.x-p1.x);
         t_y = (p.y - p1.y)/(p2.y-p1.y);
         return ( t_x == t_y && t_x >= 0 && t_x <= 1 && t_y >= 0 && t_y <= 1);
    } 
    

    通过点击点和折线的所有线段,您可以使用上面实现的功能并检索您正在寻找的线段。

    【讨论】:

    • 我见过的最佳解决方案。如果段完全是水平或垂直的,它只会中断(除以零),但这在实践中不太可能发生,因为我让用户手动放置标记。
    • @HeitorChang 啊,是的,关于水平和垂直案例,你是对的,我错过了。我已经更新了我的答案。请检查。
    • 感谢您的详尽。如果可以的话,我会再次投票:)
    猜你喜欢
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 2016-08-18
    • 2010-09-29
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 2019-06-22
    相关资源
    最近更新 更多