如何在 JavaScript 中围绕折线绘制多边形?
Posted
技术标签:
【中文标题】如何在 JavaScript 中围绕折线绘制多边形?【英文标题】:How to draw a polygon around a polyline in JavaScript? 【发布时间】:2013-10-22 13:22:39 【问题描述】:我想在折线周围画一个多边形。在我的例子中,折线是一个谷歌地图方向,我需要在谷歌地图画布中围绕它显示一个多边形。
第一:
对于偏移,我使用 javascript Clipper 库。我有以下折线(路线):我使用 Clipper 在下面制作了一个偏移多边形:
我有一个工作的JS Bin example。
代码是:
<html>
<head>
<title>Javascript Clipper Library / Offset polyline</title>
<script src="clipper.js"></script>
<script>
function draw()
var polygons = [["X":72,"Y":59.45,"X":136,"Y":66,"X":170,"Y":99,"X":171,"Y":114,"X":183,"Y":125,"X":218,"Y":144,"X":218,"Y":165,"X":226,"Y":193,"X":254,"Y":195,"X":283,"Y":195,"X":292,"Y":202,"X":325,"Y":213,"X":341,"Y":234,"X":397,"Y":245,"X":417,"Y":248]];
var scale = 100;
reverse_copy(polygons);
polygons = scaleup(polygons, scale);
var cpr = new ClipperLib.Clipper();
var delta = 25;
var joinType = ClipperLib.JoinType.jtRound;
var miterLimit = 2;
var AutoFix = true;
var svg, offsetted_polygon,
cont = document.getElementById('svgcontainer');
offsetted_polygon = cpr.OffsetPolygons(polygons, delta * scale, joinType, miterLimit, AutoFix);
//console.log(JSON.stringify(offsetted_polygon));
// Draw red offset polygon
svg = '<svg style="margin-top:10px;margin-right:10px;margin-bottom:10px;background-color:#dddddd" >';
svg += '<path stroke="red" fill="red" stroke- stroke-opacity="0.6" fill-opacity="0.2" d="' + polys2path(offsetted_polygon, scale) + '"/>';
//Draw blue polyline
svg += '<path stroke="blue" stroke- d="' + polys2path(polygons, scale) + '"/>';
svg += '</svg>';
cont.innerHTML += svg;
// helper function to scale up polygon coordinates
function scaleup(poly, scale)
var i, j;
if (!scale)
scale = 1;
for(i = 0; i < poly.length; i++)
for(j = 0; j < poly[i].length; j++)
poly[i][j].X *= scale;
poly[i][j].Y *= scale;
return poly;
// converts polygons to SVG path string
function polys2path (poly, scale)
var path = "", i, j;
if (!scale)
scale = 1;
for(i = 0; i < poly.length; i++)
for(j = 0; j < poly[i].length; j++)
if (!j)
path += "M";
else
path += "L";
path += (poly[i][j].X / scale) + ", " + (poly[i][j].Y / scale);
path += "Z";
return path;
function reverse_copy(poly)
// Make reverse copy of polygons = convert polyline to a 'flat' polygon ...
var k, klen = poly.length, len, j;
for (k = 0; k < klen; k++)
len = poly[k].length;
poly[k].length = len * 2 - 2;
for (j = 1; j <= len - 2; j++)
poly[k][len - 1 + j] =
X: poly[k][len - 1 - j].X,
Y: poly[k][len - 1 - j].Y
</script>
</head>
<body onload="draw()">
<h2>Javascript Clipper Library / Offset polyline</h2>
This page shows an example of offsetting polyline and drawing it using SVG.
<div id="svgcontainer"></div>
</body>
</html>
这一切都很好,但现在我必须用谷歌地图方向的点替换多边形变量,所以我做了这个改变:
directionsService.route(request, function(response, status)
if (status == google.maps.DirectionsStatus.OK)
directionsDisplay.setDirections(response);
function draw()
var polygons = response.routes[0].overview_path;
//REST OF CODE
我有一个JS Bin example,其中包含用于偏移折线周围的多边形的代码。
但有一些问题,我无法重新定位,也无法获得方向周围的多边形。
有没有办法解决这个问题?
【问题讨论】:
【参考方案1】:我的工作解决方案:working example(基于 Manolis Xountasis 的回答)和这些相关问题的片段:
-
How to calculate intersection area in Google Maps API with JSTS Library?
Google Maps Polygons self intersecting detection
function googleMaps2JTS(boundaries)
var coordinates = [];
var length = 0;
if (boundaries && boundaries.getLength) length = boundaries.getLength();
else if (boundaries && boundaries.length) length = boundaries.length;
for (var i = 0; i < length; i++)
if (boundaries.getLength) coordinates.push(new jsts.geom.Coordinate(
boundaries.getAt(i).lat(), boundaries.getAt(i).lng()));
else if (boundaries.length) coordinates.push(new jsts.geom.Coordinate(
boundaries[i].lat(), boundaries[i].lng()));
return coordinates;
;
然后返回 google.maps.LatLng 数组
var jsts2googleMaps = function (geometry)
var coordArray = geometry.getCoordinates();
GMcoords = [];
for (var i = 0; i < coordArray.length; i++)
GMcoords.push(new google.maps.LatLng(coordArray[i].x, coordArray[i].y));
return GMcoords;
从DirectionsService 获取方向折线并将其缓冲
directionsService.route(request, function (response, status)
if (status == google.maps.DirectionsStatus.OK)
directionsDisplay.setDirections(response);
var overviewPath = response.routes[0].overview_path,
overviewPathGeo = [];
for (var i = 0; i < overviewPath.length; i++)
overviewPathGeo.push(
[overviewPath[i].lng(), overviewPath[i].lat()]);
var distance = 10 / 111.12, // Roughly 10km
geoInput =
type: "LineString",
coordinates: overviewPathGeo
;
var geoInput = googleMaps2JTS(overviewPath);
var geometryFactory = new jsts.geom.GeometryFactory();
var shell = geometryFactory.createLineString(geoInput);
var polygon = shell.buffer(distance);
var oLanLng = [];
var oCoordinates;
oCoordinates = polygon.shell.points[0];
for (i = 0; i < oCoordinates.length; i++)
var oItem;
oItem = oCoordinates[i];
oLanLng.push(new google.maps.LatLng(oItem[1], oItem[0]));
if (routePolygon && routePolygon.setMap) routePolygon.setMap(null);
routePolygon = new google.maps.Polygon(
paths: jsts2googleMaps(polygon),
map: map
);
);
【讨论】:
shell.buffer(distance)
期望的距离单位是多少?那是怎么计算的? @geocodezip
很高兴了解您如何计算此处的距离?你为什么要在 10/111.12 做?
根据代码中的注释 (var distance = 10 / 111.12, // Roughly 10km
) 大约 10 公里 (google.com/#q=km%20per%20degree%20longitude%20km)【参考方案2】:
这是有效的解决方案。你可以找到JSTS files at coderwall.com。
var overviewPath = response.routes[0].overview_path,
overviewPathGeo = [];
for (var i = 0; i < overviewPath.length; i++)
overviewPathGeo.push(
[overviewPath[i].lng(), overviewPath[i].lat()]
);
var distance = value / 10000, // Roughly 10km
geoInput =
type: "LineString",
coordinates: overviewPathGeo
;
var geoReader = new jsts.io.GeoJSONReader(),
geoWriter = new jsts.io.GeoJSONWriter();
var geometry = geoReader.read(geoInput).buffer(distance);
var polygon = geoWriter.write(geometry);
var oLanLng = [];
var oCoordinates;
oCoordinates = polygon.coordinates[0];
for (i = 0; i < oCoordinates.length; i++)
var oItem;
oItem = oCoordinates[i];
oLanLng.push(new google.maps.LatLng(oItem[1], oItem[0]));
var polygone = new google.maps.Polygon(
paths: oLanLng,
map:map
);
【讨论】:
完美。因为,你没有提供“价值”的价值,我认为distance = 0.001
的距离在路线周围给出了很好的近似多边形【参考方案3】:
这是使用 Turf.js 的缓冲区模块的替代解决方案。我使用 Leaflet 地图来展示结果 - 但这适用于任何映射库。
var center = [37.78791180770003, -122.40962505340575];
var map = L.map('map').setView(center, 14);;
L.tileLayer(
'https://s.tile.openstreetmap.org/z/x/y.png',
maxZoom: 18
).addTo(map);
var line =
"type": "Feature",
"properties":
"color": "blue"
,
"geometry":
"type": "LineString",
"coordinates": [
[-122.40447521209718,
37.79367718768535
],
[-122.40803718566895,
37.79171022624846
],
[-122.40769386291502,
37.79096412372944
],
[-122.40662097930908,
37.789641468930114
],
[-122.40941047668457,
37.789675383451495
],
[-122.40992546081543,
37.78875968591083
],
[-122.40962505340575,
37.78791180770003
]
]
;
L.geoJSON(line,
style: function(feature)
return
color: feature.properties.color
;
).addTo(map);
var polygon = turf.buffer(line, 50,
units: 'meters'
);
L.geoJSON(polygon,
style: function(feature)
return
color: feature.properties.color
;
).addTo(map);
#map
height: 400px;
<script src="https://npmcdn.com/@turf/turf@6.3.0/turf.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.js"></script>
<div id="map"></div>
【讨论】:
以上是关于如何在 JavaScript 中围绕折线绘制多边形?的主要内容,如果未能解决你的问题,请参考以下文章
如何计算像geojson.io这样的Leaflet中折线的距离?
Google Map API Javascript v3-如何在多边形/矩形区域内突出显示特定街道/街道段?
Python Esri Arcpy 比较多边形和折线的几何图形