过滤覆盖层的漏洞,然后将其无重复地推送到数据层
Filtering overlay for holes and then pushing it to the Data Layer without duplicates
我在 DrawManager 绘图和将叠加层导出到 GeoJSON 对象时遇到问题。
我可以在 DrawManager 中绘制带孔的多边形,叠加层将显示对象中的孔。问题是将其导出到 DataLayer 时。
数据层使导出 GeoJSON 变得容易。关于漏洞:polygon data layer
map.data.add({
geometry: new google.maps.Data.Polygon([
outerCoords,
innerCoords1,//hole
innerCoords2, //hole
]),
});
如何导出 DrawManager 绘图以适合此模式?
我已经尝试使用数据层上倒带路径的解决方案。但是,我无法将孔 link 到带孔的多边形。它会创建重复项。 DrawingManager 显示数据,但我很难将此数据导出为看起来像绘制的图像。
绘制图像:
输出 GeoJSON 数据:
{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[150.3308896484375,-34.242748228904865],[150.0232724609375,-34.555492148137766],[150.764849609375,-34.70465158215243],[151.0779599609375,-34.27452911659509],[150.3308896484375,-34.242748228904865]]]},"properties":{}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[150.3308896484375,-34.242748228904865],[150.0232724609375,-34.555492148137766],[150.764849609375,-34.70465158215243],[151.0779599609375,-34.27452911659509],[150.3308896484375,-34.242748228904865]],[[150.8362607421875,-34.41512862111033],[150.35835546875,-34.51476578284105],[150.53413671875,-34.392467230948675],[150.8362607421875,-34.41512862111033]]]},"properties":{}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[150.3308896484375,-34.242748228904865],[150.0232724609375,-34.555492148137766],[150.764849609375,-34.70465158215243],[151.0779599609375,-34.27452911659509],[150.3308896484375,-34.242748228904865]],[[150.44624609375,-34.35619624254908],[150.237505859375,-34.49213141771243],[150.1606015625,-34.47854784880349],[150.369341796875,-34.29722239841581],[150.44624609375,-34.35619624254908]]]},"properties":{}}]}
绘制输出:
数据没有附加孔,它正在重新创建 [outer,inner] 数据层。
代码片段:
// This example requires the Drawing library. Include the libraries=drawing
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBIwzALxUPNbatRBj3Xi1Uhp0fFzwWNBkE&libraries=drawing">
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 8,
});
const drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON,
google.maps.drawing.OverlayType.CIRCLE
],
},
});
var dataLayer = new google.maps.Data();
drawingManager.setMap(map);
var overlayArr = [] //Store all completed objects
var holeArr = [] //Keep track of holes to build polygon with data layer
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
if (e.type === 'polygon') {
console.log("overlaycomplete start overlayArr.length=" + overlayArr.length);
var path = e.overlay.getPath().getArray()
path = rewindRing(path, true);
var found = false;
for (var i = 0; i < overlayArr.length; i++) {
if (isPolygonInsidePolygon(e.overlay, overlayArr[i])) {
found = true;
var path = e.overlay.getPath().getArray();
path = rewindRing(path, false);
overlayArr[i].getPaths().push(new google.maps.MVCArray(path))
dataLayer.add(new google.maps.Data.Feature({
geometry: new google.maps.Data.Polygon([overlayArr[i].getPath().getArray(), path]) //Store holes as the secondary "outer" to save to GeoJSON
}));
holeArr.push(overlayArr[i]);
e.overlay.setMap(null); //make hole
break;
}
}
if (!found) {
overlayArr.push(e.overlay);
//This is a duplicate object in the datalayer after a hole is drawn -- how to remove if hole is drawn?
dataLayer.add(new google.maps.Data.Feature({
geometry: new google.maps.Data.Polygon([e.overlay.getPath().getArray()]) //No holes add normal
}));
found = false;
}
}
if (e.type === 'circle') {
dataLayer.add(new google.maps.Data.Feature({
properties: {
radius: e.overlay.getRadius()
},
geometry: new google.maps.Data.Point(e.overlay.getCenter())
}));
}
});
google.maps.event.addDomListener(document.getElementById('save'), 'click', function() {
dataLayer.toGeoJson(function(obj) {
document.getElementById('geojson').innerHTML = JSON.stringify(obj);
});
})
//Helper function
function isPolygonInsidePolygon(innerPolygon, outerPolygon) {
var points = innerPolygon.getPath().getArray();
for (var i = 0; i < points.length; i++) {
if (!google.maps.geometry.poly.containsLocation(points[i], outerPolygon)) {
return false;
}
}
return true;
}
// from https://github.com/mapbox/geojson-rewind/blob/main/index.js
function rewindRing(ring, dir) {
var area = 0;
for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
area += ((ring[i].lng() - ring[j].lng()) * (ring[j].lat() + ring[i].lat()));
}
console.log("area=" + area + " dir=" + dir);
if (area >= 0 !== !dir)
ring.reverse();
return ring;
}
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<!DOCTYPE html>
<html>
<head>
<title>Drawing Tools</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<input id="save" value="save" type="button" />
<div id="geojson"></div>
<div id="map"></div>
<!-- Async script executes immediately and must be after any DOM elements used in callback. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=drawing&v=weekly" async></script>
</body>
</html>
我的建议是在需要导出多边形之前不要将它们添加到 DataLayer。删除在绘制时将多边形添加到 DataLayer 的代码,然后像这样创建导出函数:
google.maps.event.addDomListener(document.getElementById('export'), 'click', function() {
for (var i=0; i<overlayArr.length;i++) {
// for each polygon drawn, get its paths
var paths = [];
for (var j=0; j<overlayArr[i].getPaths().getLength();j++) {
var path = [];
for (k=0; k<overlayArr[i].getPaths().getAt(j).getLength(); k++) {
path.push(overlayArr[i].getPaths().getAt(j).getAt(k));
}
paths.push(path);
}
// create a Data.Polygon
map.data.add({
geometry: new google.maps.Data.Polygon(paths)
});
}
// export the GeoJson from the Data Layer
map.data.toGeoJson(function(geoJson){
console.log(geoJson);
document.getElementById('geoJson').innerHTML = JSON.stringify(geoJson);
});
});
// This example requires the Drawing library. Include the libraries=drawing
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBIwzALxUPNbatRBj3Xi1Uhp0fFzwWNBkE&libraries=drawing">
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 8,
});
const drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON,
google.maps.drawing.OverlayType.CIRCLE
],
},
});
var dataLayer = new google.maps.Data();
drawingManager.setMap(map);
var overlayArr = [] //Store all completed objects
var holeArr = [] //Keep track of holes to build polygon with data layer
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
if (e.type === 'polygon') {
console.log("overlaycomplete start overlayArr.length=" + overlayArr.length);
var path = e.overlay.getPath().getArray()
path = rewindRing(path, true);
var found = false;
for (var i = 0; i < overlayArr.length; i++) {
if (isPolygonInsidePolygon(e.overlay, overlayArr[i])) {
found = true;
var path = e.overlay.getPath().getArray();
path = rewindRing(path, false);
overlayArr[i].getPaths().push(new google.maps.MVCArray(path))
dataLayer.add(new google.maps.Data.Feature({
geometry: new google.maps.Data.Polygon([overlayArr[i].getPath().getArray(), path]) //Store holes as the secondary "outer" to save to GeoJSON
}));
holeArr.push(overlayArr[i]);
e.overlay.setMap(null); //make hole
break;
}
}
if (!found) {
overlayArr.push(e.overlay);
//This is a duplicate object in the datalayer after a hole is drawn -- how to remove if hole is drawn?
dataLayer.add(new google.maps.Data.Feature({
geometry: new google.maps.Data.Polygon([e.overlay.getPath().getArray()]) //No holes add normal
}));
found = false;
}
}
if (e.type === 'circle') {
dataLayer.add(new google.maps.Data.Feature({
properties: {
radius: e.overlay.getRadius()
},
geometry: new google.maps.Data.Point(e.overlay.getCenter())
}));
}
});
google.maps.event.addDomListener(document.getElementById('export'), 'click', function() {
dataLayer.toGeoJson(function(obj) {
document.getElementById('geoJson').innerHTML = JSON.stringify(obj);
});
})
//Helper function
function isPolygonInsidePolygon(innerPolygon, outerPolygon) {
var points = innerPolygon.getPath().getArray();
for (var i = 0; i < points.length; i++) {
if (!google.maps.geometry.poly.containsLocation(points[i], outerPolygon)) {
return false;
}
}
return true;
}
// from https://github.com/mapbox/geojson-rewind/blob/main/index.js
function rewindRing(ring, dir) {
var area = 0;
for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
area += ((ring[i].lng() - ring[j].lng()) * (ring[j].lat() + ring[i].lat()));
}
console.log("area=" + area + " dir=" + dir);
if (area >= 0 !== !dir)
ring.reverse();
return ring;
}
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 90%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<!DOCTYPE html>
<html>
<head>
<title>Drawing Tools</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<input id="export" value="export" type="button" />
<div id="map"></div>
<div id="geoJson"></div>
<!-- Async script executes immediately and must be after any DOM elements used in callback. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=drawing&v=weekly" async></script>
</body>
</html>
我在 DrawManager 绘图和将叠加层导出到 GeoJSON 对象时遇到问题。
我可以在 DrawManager 中绘制带孔的多边形,叠加层将显示对象中的孔。问题是将其导出到 DataLayer 时。
数据层使导出 GeoJSON 变得容易。关于漏洞:polygon data layer
map.data.add({
geometry: new google.maps.Data.Polygon([
outerCoords,
innerCoords1,//hole
innerCoords2, //hole
]),
});
如何导出 DrawManager 绘图以适合此模式?
我已经尝试使用数据层上倒带路径的解决方案。但是,我无法将孔 link 到带孔的多边形。它会创建重复项。 DrawingManager 显示数据,但我很难将此数据导出为看起来像绘制的图像。
绘制图像:
输出 GeoJSON 数据:
{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[150.3308896484375,-34.242748228904865],[150.0232724609375,-34.555492148137766],[150.764849609375,-34.70465158215243],[151.0779599609375,-34.27452911659509],[150.3308896484375,-34.242748228904865]]]},"properties":{}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[150.3308896484375,-34.242748228904865],[150.0232724609375,-34.555492148137766],[150.764849609375,-34.70465158215243],[151.0779599609375,-34.27452911659509],[150.3308896484375,-34.242748228904865]],[[150.8362607421875,-34.41512862111033],[150.35835546875,-34.51476578284105],[150.53413671875,-34.392467230948675],[150.8362607421875,-34.41512862111033]]]},"properties":{}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[150.3308896484375,-34.242748228904865],[150.0232724609375,-34.555492148137766],[150.764849609375,-34.70465158215243],[151.0779599609375,-34.27452911659509],[150.3308896484375,-34.242748228904865]],[[150.44624609375,-34.35619624254908],[150.237505859375,-34.49213141771243],[150.1606015625,-34.47854784880349],[150.369341796875,-34.29722239841581],[150.44624609375,-34.35619624254908]]]},"properties":{}}]}
绘制输出:
代码片段:
// This example requires the Drawing library. Include the libraries=drawing
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBIwzALxUPNbatRBj3Xi1Uhp0fFzwWNBkE&libraries=drawing">
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 8,
});
const drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON,
google.maps.drawing.OverlayType.CIRCLE
],
},
});
var dataLayer = new google.maps.Data();
drawingManager.setMap(map);
var overlayArr = [] //Store all completed objects
var holeArr = [] //Keep track of holes to build polygon with data layer
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
if (e.type === 'polygon') {
console.log("overlaycomplete start overlayArr.length=" + overlayArr.length);
var path = e.overlay.getPath().getArray()
path = rewindRing(path, true);
var found = false;
for (var i = 0; i < overlayArr.length; i++) {
if (isPolygonInsidePolygon(e.overlay, overlayArr[i])) {
found = true;
var path = e.overlay.getPath().getArray();
path = rewindRing(path, false);
overlayArr[i].getPaths().push(new google.maps.MVCArray(path))
dataLayer.add(new google.maps.Data.Feature({
geometry: new google.maps.Data.Polygon([overlayArr[i].getPath().getArray(), path]) //Store holes as the secondary "outer" to save to GeoJSON
}));
holeArr.push(overlayArr[i]);
e.overlay.setMap(null); //make hole
break;
}
}
if (!found) {
overlayArr.push(e.overlay);
//This is a duplicate object in the datalayer after a hole is drawn -- how to remove if hole is drawn?
dataLayer.add(new google.maps.Data.Feature({
geometry: new google.maps.Data.Polygon([e.overlay.getPath().getArray()]) //No holes add normal
}));
found = false;
}
}
if (e.type === 'circle') {
dataLayer.add(new google.maps.Data.Feature({
properties: {
radius: e.overlay.getRadius()
},
geometry: new google.maps.Data.Point(e.overlay.getCenter())
}));
}
});
google.maps.event.addDomListener(document.getElementById('save'), 'click', function() {
dataLayer.toGeoJson(function(obj) {
document.getElementById('geojson').innerHTML = JSON.stringify(obj);
});
})
//Helper function
function isPolygonInsidePolygon(innerPolygon, outerPolygon) {
var points = innerPolygon.getPath().getArray();
for (var i = 0; i < points.length; i++) {
if (!google.maps.geometry.poly.containsLocation(points[i], outerPolygon)) {
return false;
}
}
return true;
}
// from https://github.com/mapbox/geojson-rewind/blob/main/index.js
function rewindRing(ring, dir) {
var area = 0;
for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
area += ((ring[i].lng() - ring[j].lng()) * (ring[j].lat() + ring[i].lat()));
}
console.log("area=" + area + " dir=" + dir);
if (area >= 0 !== !dir)
ring.reverse();
return ring;
}
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<!DOCTYPE html>
<html>
<head>
<title>Drawing Tools</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<input id="save" value="save" type="button" />
<div id="geojson"></div>
<div id="map"></div>
<!-- Async script executes immediately and must be after any DOM elements used in callback. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=drawing&v=weekly" async></script>
</body>
</html>
我的建议是在需要导出多边形之前不要将它们添加到 DataLayer。删除在绘制时将多边形添加到 DataLayer 的代码,然后像这样创建导出函数:
google.maps.event.addDomListener(document.getElementById('export'), 'click', function() {
for (var i=0; i<overlayArr.length;i++) {
// for each polygon drawn, get its paths
var paths = [];
for (var j=0; j<overlayArr[i].getPaths().getLength();j++) {
var path = [];
for (k=0; k<overlayArr[i].getPaths().getAt(j).getLength(); k++) {
path.push(overlayArr[i].getPaths().getAt(j).getAt(k));
}
paths.push(path);
}
// create a Data.Polygon
map.data.add({
geometry: new google.maps.Data.Polygon(paths)
});
}
// export the GeoJson from the Data Layer
map.data.toGeoJson(function(geoJson){
console.log(geoJson);
document.getElementById('geoJson').innerHTML = JSON.stringify(geoJson);
});
});
// This example requires the Drawing library. Include the libraries=drawing
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBIwzALxUPNbatRBj3Xi1Uhp0fFzwWNBkE&libraries=drawing">
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 8,
});
const drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON,
google.maps.drawing.OverlayType.CIRCLE
],
},
});
var dataLayer = new google.maps.Data();
drawingManager.setMap(map);
var overlayArr = [] //Store all completed objects
var holeArr = [] //Keep track of holes to build polygon with data layer
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
if (e.type === 'polygon') {
console.log("overlaycomplete start overlayArr.length=" + overlayArr.length);
var path = e.overlay.getPath().getArray()
path = rewindRing(path, true);
var found = false;
for (var i = 0; i < overlayArr.length; i++) {
if (isPolygonInsidePolygon(e.overlay, overlayArr[i])) {
found = true;
var path = e.overlay.getPath().getArray();
path = rewindRing(path, false);
overlayArr[i].getPaths().push(new google.maps.MVCArray(path))
dataLayer.add(new google.maps.Data.Feature({
geometry: new google.maps.Data.Polygon([overlayArr[i].getPath().getArray(), path]) //Store holes as the secondary "outer" to save to GeoJSON
}));
holeArr.push(overlayArr[i]);
e.overlay.setMap(null); //make hole
break;
}
}
if (!found) {
overlayArr.push(e.overlay);
//This is a duplicate object in the datalayer after a hole is drawn -- how to remove if hole is drawn?
dataLayer.add(new google.maps.Data.Feature({
geometry: new google.maps.Data.Polygon([e.overlay.getPath().getArray()]) //No holes add normal
}));
found = false;
}
}
if (e.type === 'circle') {
dataLayer.add(new google.maps.Data.Feature({
properties: {
radius: e.overlay.getRadius()
},
geometry: new google.maps.Data.Point(e.overlay.getCenter())
}));
}
});
google.maps.event.addDomListener(document.getElementById('export'), 'click', function() {
dataLayer.toGeoJson(function(obj) {
document.getElementById('geoJson').innerHTML = JSON.stringify(obj);
});
})
//Helper function
function isPolygonInsidePolygon(innerPolygon, outerPolygon) {
var points = innerPolygon.getPath().getArray();
for (var i = 0; i < points.length; i++) {
if (!google.maps.geometry.poly.containsLocation(points[i], outerPolygon)) {
return false;
}
}
return true;
}
// from https://github.com/mapbox/geojson-rewind/blob/main/index.js
function rewindRing(ring, dir) {
var area = 0;
for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
area += ((ring[i].lng() - ring[j].lng()) * (ring[j].lat() + ring[i].lat()));
}
console.log("area=" + area + " dir=" + dir);
if (area >= 0 !== !dir)
ring.reverse();
return ring;
}
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 90%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<!DOCTYPE html>
<html>
<head>
<title>Drawing Tools</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<input id="export" value="export" type="button" />
<div id="map"></div>
<div id="geoJson"></div>
<!-- Async script executes immediately and must be after any DOM elements used in callback. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=drawing&v=weekly" async></script>
</body>
</html>