查找多边形中多段线段的总距离
Find the total distance of a Polyline segment within a Polygon
我有一个地图,它将由多个"区域"组成,每个区域都创建为多边形覆盖。我还允许用户定义路线,并使用DirectionsService将路线渲染为同一地图上的多段线https://i.stack.imgur.com/DDZI1.png.你可以看到两个区域,一个是绿色,另一个是蓝色,路线是红色。在最终版本中,最多可以定义30个区域。
我需要做的是计算多段线(管线)在每个分区中花费的距离。根据道路的曲折程度,路线可能多次进出一个区域,也有可能完全存在于一个区域内,而不与区域边界相交。
我该怎么办?
这是我目前拥有的代码,它只需在地图上添加两个区域并绘制线。我还添加了"包含"方法,该方法允许我确定坐标是否位于多边形内,我使用该多边形在地图上为位于区域"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'
);
根据您使用的距离增量(英尺、米、公里、英里),以下是我要做的…
var increment = 0;
var zone = initial_zone;
//loop structure
if(current zone == zone){
increment = increment + 1;
}
else{
zone = zone_2;
}
等等。。。etc
- 搜索线多边形交点
- 选择您理解的算法或在javascript中找到一个可以移植到API的实现
- 使用它可以找到路线与多边形的交点
- 使用几何图形库可以确定每个多边形内线段的长度
相关文章:
- 正在添加'X'按钮,在文本字段旁边使用javascript
- 将输入字段中的文本提交到我的数据库,同时将其添加到我的列表中
- 而循环只设置php中输入字段中的第一个值
- 如何为json对象中的段发送array[]
- 在输入字段中将最小金额设置为
- 如果文本字段为空,则使用JavaScript应用CSS样式
- 从Rally获取一个特定的标记,以便计算另一个字段中的值
- 如何在输入字段中的按钮的帮助下打开日历,该字段的类型为“=”;日期”;
- JavaScript 检查隐藏字段中的值并将其设置为隐藏字段值
- 在wordpress一定时间后更改自定义字段
- 如何在HTML输入字段中添加不可删除的后缀
- Meteor-添加用户自定义字段的方法不起作用
- 互斥单选按钮和相应的输入字段
- 在IE9中的输入字段中输入焦点最近按钮
- 查找多边形中多段线段的总距离
- 查询距离线段的区域内点的集合
- 在滚动一段距离后移除JavaScript中的固定位置
- 如何在类似传单的geojson.io中计算多段线的距离
- 引导年历..更改弹出框与文本字段的距离
- 如何使一个盒子从侧面扩大一段距离