2012-07-10 38 views
0

我有一个包含多个“区域”的地图,每个地图都创建为多边形叠加层。我还允许用户定义路线并使用DirectionsService,我将路线呈现为同一地图http://i.stack.imgur.com/DDZI1.png上的多段线。您可以看到两个区域,一个为绿色,另一个为蓝色,路线为红色。在最终版本中会定义多达30个区域。查找多边形内Polyline线段的总距离

我需要做的是计算折线(路线)在每个区域中的距离。路线可能会多次进入和退出一个区域,具体取决于道路曲折和转弯的方式,路线也可能完全存在于一个区域中,而不与区域的边界相交。

我该怎么办?

这是我目前拥有的代码,它只是将两个区域添加到地图并绘制线条。我还在'contains'方法中添加了一个方法,该方法允许我确定一个坐标是否位于一个多边形内,我使用该多边形在地图上绘制一条新的多段线(黑色),用于位于区域“a”中的多段。然而,这并不足以知道它何时首次进入区域,这可能发生在顶点之间。

// Functions =============== 
// ========================= 

var calcRoute = function (start, end) { 

var request = { 
    origin: start, 
    destination: end, 
    travelMode: google.maps.TravelMode.DRIVING, 
    provideRouteAlternatives: false, 
    avoidHighways: false, 
    avoidTolls: false, 
    optimizeWaypoints: false 
}; 

// Load directions 
directions.service.route(request, function (result, status) { 

    if (status == google.maps.DirectionsStatus.OK) { 

     // Iterate through each route, adding it to th map 
     $(result.routes).each(function onEach(index, route) { 

      // Create a new Polyline, set its path to the route path 
      var line = new google.maps.Polyline({ 
       path: route.overview_path, 
       strokeColor: "#FF0000", 
       strokeOpacity: 1, 
       strokeWeight: 2 
      }); 

      // Add line to the map 
      line.setMap(map); 

      // Find individual line segments 
      var inside = []; 
      var vertices = line.getPath(); 
      for (var i = 0; i < vertices.length; i++) { 

       var vertix = vertices.getAt(i); 

       // Check to see if the vertix exists within a specified Polygon 
       if (zones.a.polygon.contains(vertix)) { 
        inside.push(vertix); 
       } 

      } 

      // Add another Polyline for the segments inside the polygon 
      var line = new google.maps.Polyline({ 
       path: inside, 
       strokeColor: "#000000", 
       strokeOpacity: 1, 
       strokeWeight: 4 
      }); 

      // Add line to the map 
      line.setMap(map); 

     }); 

    } 

}); 

} 

// ray casting alogrithm http://rosettacode.org/wiki/Ray-casting_algorithm 
google.maps.Polygon.prototype.contains = function(point) { 

var crossings = 0, 
    path = this.getPath(); 

// for each edge 
for (var i=0; i < path.getLength(); i++) { 
    var a = path.getAt(i), 
     j = i + 1; 
    if (j >= path.getLength()) { 
     j = 0; 
    } 
    var b = path.getAt(j); 
    if (rayCrossesSegment(point, a, b)) { 
     crossings++; 
    } 
} 

// odd number of crossings? 
return (crossings % 2 == 1); 

function rayCrossesSegment(point, a, b) { 
    var px = point.lng(), 
     py = point.lat(), 
     ax = a.lng(), 
     ay = a.lat(), 
     bx = b.lng(), 
     by = b.lat(); 
    if (ay > by) { 
     ax = b.lng(); 
     ay = b.lat(); 
     bx = a.lng(); 
     by = a.lat(); 
    } 
    // alter longitude to cater for 180 degree crossings 
    if (px < 0) { px += 360 }; 
    if (ax < 0) { ax += 360 }; 
    if (bx < 0) { bx += 360 }; 

    if (py == ay || py == by) py += 0.00000001; 
    if ((py > by || py < ay) || (px > Math.max(ax, bx))) return false; 
    if (px < Math.min(ax, bx)) return true; 

    var red = (ax != bx) ? ((by - ay)/(bx - ax)) : Infinity; 
    var blue = (ax != px) ? ((py - ay)/(px - ax)) : Infinity; 
    return (blue >= red); 

} 

}; 


// Variables =============== 
// ========================= 
var $map = document.getElementById('map_canvas'), 
defaultLocation = new google.maps.LatLng(-37.813553, 144.96341899999993), // Melbourne CBD 
directions = { 
    display: new google.maps.DirectionsRenderer(), 
    service: new google.maps.DirectionsService() 
}, 
initialLocation = defaultLocation, 
map = null, 
options = { 
    center: initialLocation, 
    mapTypeId: google.maps.MapTypeId.ROADMAP, 
    zoom: 13 
}, 
zones = { 
    a: { 
     options: { 
      path: [ 
       new google.maps.LatLng(-37.839848,144.916192), 
       new google.maps.LatLng(-37.831374,144.911557), 
       new google.maps.LatLng(-37.822358,144.911128), 
       new google.maps.LatLng(-37.806627,144.908038), 
       new google.maps.LatLng(-37.794148,144.914218), 
       new google.maps.LatLng(-37.787636,144.924518), 
       new google.maps.LatLng(-37.788586,144.947520), 
       new google.maps.LatLng(-37.787365,144.950953), 
       new google.maps.LatLng(-37.789536,144.958507), 
       new google.maps.LatLng(-37.793063,144.966060), 
       new google.maps.LatLng(-37.792656,144.975501), 
       new google.maps.LatLng(-37.807983,144.972239), 
       new google.maps.LatLng(-37.815035,144.975158), 
       new google.maps.LatLng(-37.833069,144.971210), 
       new google.maps.LatLng(-37.836594,144.968463), 
       new google.maps.LatLng(-37.849066,144.950438), 
       new google.maps.LatLng(-37.839848,144.916192) 
      ], 
      fillColor: "#00FF00", 
      fillOpacity: 0.35, 
      strokeColor: "#00FF00", 
      strokeOpacity: 1, 
      strokeWeight: 2 
     }, 
     polygon: null 
    }, // End zone a 
    b: { 
     options: { 
      path: [ 
       new google.maps.LatLng(-37.840119,144.915591), 
       new google.maps.LatLng(-37.865465,144.914561), 
       new google.maps.LatLng(-37.867905,144.908467), 
       new google.maps.LatLng(-37.871970,144.902974), 
       new google.maps.LatLng(-37.859096,144.873277), 
       new google.maps.LatLng(-37.867498,144.843064), 
       new google.maps.LatLng(-37.870208,144.838944), 
       new google.maps.LatLng(-37.815984,144.849587), 
       new google.maps.LatLng(-37.812187,144.860230), 
       new google.maps.LatLng(-37.781531,144.864350), 
       new google.maps.LatLng(-37.770134,144.865724), 
       new google.maps.LatLng(-37.757378,144.859544), 
       new google.maps.LatLng(-37.728872,144.867097), 
       new google.maps.LatLng(-37.734574,144.904176), 
       new google.maps.LatLng(-37.732673,144.920999), 
       new google.maps.LatLng(-37.746791,145.022622), 
       new google.maps.LatLng(-37.764706,145.020562), 
       new google.maps.LatLng(-37.764435,145.027085), 
       new google.maps.LatLng(-37.790485,145.027429), 
       new google.maps.LatLng(-37.792927,145.031205), 
       new google.maps.LatLng(-37.826561,145.025369), 
       new google.maps.LatLng(-37.837136,145.026742), 
       new google.maps.LatLng(-37.836865,145.037042), 
       new google.maps.LatLng(-37.845812,145.039445), 
       new google.maps.LatLng(-37.847710,145.042535), 
       new google.maps.LatLng(-37.871292,145.038415), 
       new google.maps.LatLng(-37.879693,145.034295), 
       new google.maps.LatLng(-37.884571,145.038758), 
       new google.maps.LatLng(-37.903807,145.035325), 
       new google.maps.LatLng(-37.927371,145.029145), 
       new google.maps.LatLng(-37.931433,145.025712), 
       new google.maps.LatLng(-37.975560,145.015412), 
       new google.maps.LatLng(-37.969606,145.008546), 
       new google.maps.LatLng(-37.961485,145.011292), 
       new google.maps.LatLng(-37.944701,144.995843), 
       new google.maps.LatLng(-37.937932,144.996873), 
       new google.maps.LatLng(-37.925476,144.984857), 
       new google.maps.LatLng(-37.911392,144.984857), 
       new google.maps.LatLng(-37.894054,144.985200), 
       new google.maps.LatLng(-37.881861,144.977647), 
       new google.maps.LatLng(-37.856927,144.966660), 
       new google.maps.LatLng(-37.849066,144.951554), 
       new google.maps.LatLng(-37.837136,144.969064), 
       new google.maps.LatLng(-37.833340,144.971810), 
       new google.maps.LatLng(-37.814899,144.976274), 
       new google.maps.LatLng(-37.807847,144.973527), 
       new google.maps.LatLng(-37.792384,144.976274), 
       new google.maps.LatLng(-37.791299,144.967004), 
       new google.maps.LatLng(-37.785873,144.952584), 
       new google.maps.LatLng(-37.786958,144.947434), 
       new google.maps.LatLng(-37.786144,144.924088), 
       new google.maps.LatLng(-37.791842,144.915162), 
       new google.maps.LatLng(-37.805135,144.906236), 
       new google.maps.LatLng(-37.820052,144.908982), 
       new google.maps.LatLng(-37.831171,144.910012), 
       new google.maps.LatLng(-37.840119,144.915591) 
      ], 
      fillColor: "#0000FF", 
      fillOpacity: 0.35, 
      strokeColor: "#0000FF", 
      strokeOpacity: 1, 
      strokeWeight: 2 
     } 
    } // End zone b 
}; 


// Load reference to map 
map = new google.maps.Map($map, options); 

// Load zones 
zones.a.polygon = new google.maps.Polygon(zones.a.options); 
zones.a.polygon.setMap(map); 

zones.b.polygon = new google.maps.Polygon(zones.b.options); 
zones.b.polygon.setMap(map); 

// Load route 
calcRoute(
    'Dandenong', 
    'South Melbourne' 
); 

回答

0

这取决于距离增量你使用(英尺,米,公里,英里),这里就是我会做...

var increment = 0; 
var zone = initial_zone; 

//loop structure 
if(current zone == zone){ 
    increment = increment + 1; 
} 
else{ 
    zone = zone_2; 
} 

等...等

+0

对不起,我不知道你的意思。 – tmcinerney 2012-07-10 02:16:46

+0

如果您仍在区域1中,则增加计数器变量....如果区域发生更改,则保存最后一个计数器,然后更改区域。如果你需要更多的帮助......发布一些代码,所以我可以给你一个具体的例子。 – reagan 2012-07-10 02:20:26

+0

我不确定当区域更改时我可以检测到的方式/位置。我应该有什么东西跟随多段线,按固定增量向上移动?我刚刚发布了我目前拥有的代码。 – tmcinerney 2012-07-10 02:51:16

0
  • 搜索line polygon intersection
  • 挑你了解的算法或者找到一个实现在JavaScript中,你可以移植到API
  • 用它来寻找路线的交叉点与多边形
  • 使用几何库,以确定每个多边形内部的线段的长度
相关问题