У меня есть многоугольник, определенный в листе js map (над бинговым отображением).
Этот многоугольник имеет два отверстия (желтые полигоны), вырезанные из него. ВТОРОЙ дырочный многоугольник перекрывает внешнюю границу основного многоугольника.
Часть второго многоугольника, который проходит мимо внешнего края первичного многоугольника, получает цвет заливки основного многоугольника.
В этом случае основной многоугольник является красным, а все удаляется желтым
Я связал проблему в прилагаемом изображении.
Ниже приводится сценарий, в котором я воссоздал проблему.
Может ли кто-нибудь помочь мне разобраться, как удалить часть второй желтой формы из красного многоугольника без этой проблемы с перекрытием?
Для ясности здесь приведен весь код из скрипки:
// Create the map
var map = L.map('map').setView([53.631611, -113.323975], 9);
// Set up the OSM layer
L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{maxZoom: 18}).addTo(map);
//Create Polygon Orange
var polyOrange = new L.Polygon([
[[53.569268602609704,-113.71411800384523], [53.51214299292513,-113.71411800384523], [53.51214299292513,-113.68802547454835], [53.403391858715274,-113.6907720565796], [53.40461992848445,-113.64957332611085], [53.3960226956682,-113.64614009857179], [53.39684155458476,-113.34332942962648], [53.4471711023092,-113.35744857788087], [53.4471711023092,-113.24483871459962], [53.57212285981298,-113.24445247650148], [53.58149977709897,-113.29389095306398], [53.58435320870081,-113.36118221282959], [53.62102302920731,-113.3447027206421], [53.646672964306994,-113.36942195892335], [53.64952199454264,-113.57116699218751], [53.669866612978275,-113.6345958709717], [53.65603334084723,-113.70188713073732], [53.57620003591595,-113.68678092956544]]
], {color:'orange', opacity:1, fillOpacity:0.05});
//Create polygon YELLOW
var polyYellow = new L.Polygon([
[
[[53.716006, -113.252565],[53.715496, -113.228546],[53.717052, -113.215209],[53.734927, -113.197527],[53.753505, -113.172980],[53.768016, -113.168688],[53.774205, -113.157874],[53.774284, -113.148883],[53.715867, -113.149098],[53.715934, -113.172036],[53.686769, -113.172207],[53.686935, -113.196896],[53.367132, -113.197204],[53.366818, -113.221196],[53.337761, -113.220792],[53.337882, -113.801601],[53.367033, -113.807995],[53.367197, -113.836702],[53.716273, -113.836434]],
[[53.569268602609704,-113.71411800384523], [53.51214299292513,-113.71411800384523], [53.51214299292513,-113.68802547454835], [53.403391858715274,-113.6907720565796], [53.40461992848445,-113.64957332611085], [53.3960226956682,-113.64614009857179], [53.39684155458476,-113.34332942962648], [53.4471711023092,-113.35744857788087], [53.4471711023092,-113.24483871459962], [53.57212285981298,-113.24445247650148], [53.58149977709897,-113.29389095306398], [53.58435320870081,-113.36118221282959], [53.62102302920731,-113.3447027206421], [53.646672964306994,-113.36942195892335], [53.64952199454264,-113.57116699218751], [53.669866612978275,-113.6345958709717], [53.65603334084723,-113.70188713073732], [53.57620003591595,-113.68678092956544]]
],
[
[[53.555985, -114.002024],[53.555804, -114.038727],[53.541397, -114.038512],[53.541372, -114.050958],[53.512009, -114.050958],[53.512111, -114.026410],[53.505169, -114.026410],[53.505373, -113.971564],[53.512034, -113.971650],[53.512034, -113.959076],[53.520338, -113.959179],[53.519726, -113.885364],[53.541153, -113.885364],[53.541101, -113.845993],[53.571438, -113.846851],[53.570012, -113.885364],[53.571082, -113.916435],[53.569349, -113.959007],[53.555451, -113.959383]]
]
], {color:'yellow', opacity:1, fillOpacity:0.05});
// CREATE POLYGONE RED
var polyRed = new L.Polygon([
[
[[53.773877,-114.001813],[53.774105,-113.998508],[53.774105,-113.917720],[53.803400,-113.917398],[53.803575,-113.661065],[53.812242,-113.660379],[53.818221,-113.652482],[53.818221,-113.620124],[53.803575,-113.620124],[53.803499,-113.347294],[53.818120,-113.347380],[53.818145,-113.345062],[53.830178,-113.334934],[53.835015,-113.335750],[53.842232,-113.324506],[53.840485,-113.321759],[53.845245,-113.314550],[53.845448,-113.309958],[53.847321,-113.309271],[53.847296,-113.305537],[53.845827,-113.306310],[53.845827,-113.304164],[53.844030,-113.306267],[53.842283,-113.310601],[53.825365,-113.310601],[53.825340,-113.322317],[53.803524,-113.322961],[53.803244,-113.124330],[53.774265,-113.124223],[53.715852,-113.124309],[53.715846,-113.098581],[53.571181,-113.098811],[53.366714,-113.098865],[53.366702,-113.074291],[53.279625,-113.074530],[53.279664,-113.098670],[53.279606,-113.220582],[53.250595,-113.220603],[53.250582,-113.488503],[53.250531,-113.499918],[53.235790,-113.499918],[53.235892,-113.561716],[53.250531,-113.561716],[53.250556,-113.598323],[53.257720,-113.598452],[53.257771,-113.610425],[53.265139,-113.610468],[53.265062,-113.927419],[53.366600,-113.927333],[53.366715,-114.001904]]
],
[
[[53.716006, -113.252565],[53.715496, -113.228546],[53.717052, -113.215209],[53.734927, -113.197527],[53.753505, -113.172980],[53.768016, -113.168688],[53.774205, -113.157874],[53.774284, -113.148883],[53.715867, -113.149098],[53.715934, -113.172036],[53.686769, -113.172207],[53.686935, -113.196896],[53.367132, -113.197204],[53.366818, -113.221196],[53.337761, -113.220792],[53.337882, -113.801601],[53.367033, -113.807995],[53.367197, -113.836702],[53.716273, -113.836434]],
[[53.555985, -114.002024],[53.555804, -114.038727],[53.541397, -114.038512],[53.541372, -114.050958],[53.512009, -114.050958],[53.512111, -114.026410],[53.505169, -114.026410],[53.505373, -113.971564],[53.512034, -113.971650],[53.512034, -113.959076],[53.520338, -113.959179],[53.519726, -113.885364],[53.541153, -113.885364],[53.541101, -113.845993],[53.571438, -113.846851],[53.570012, -113.885364],[53.571082, -113.916435],[53.569349, -113.959007],[53.555451, -113.959383]]
]
], {color:'red', opacity:1, fillOpacity:0.03});
//Add polygons to map
polyRed.addTo(map);
polyYellow.addTo(map);
polyOrange.addTo(map);
и вам просто нужно тонкое на странице html:
и ссылку на leaflet.js и.css cdn
Ваше внешнее кольцо (т.е. Первый многоугольник в вашем RED-мультиполигоне) должно привязать вашу геометрию, включая отверстие.
В вашем текущем определении второе отверстие (т.е. Второе кольцо второго многоугольника в вашем RED-мультиполигоне) распространяется больше на запад, чем внешнее кольцо (некоторые координаты имеют более низкую долготу, чем нижняя часть внешнего кольца).
Эта несогласованность делает попытку рендеринга правильно представлять ваш мультиполигон с отверстиями, в результате чего часть вашей дыры окрашивается цветом заливки.
"Простое" решение состоит в том, чтобы вручную изменить внешнее кольцо, чтобы полностью включить ваше отверстие:
// Create the map
var map = L.map('map').setView([53.54, -113.9], 10);
// Set up the OSM layer
L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
//Create polygon YELLOW
var polyYellow = new L.Polygon([
[
[
[53.716006, -113.252565],
[53.715496, -113.228546],
[53.717052, -113.215209],
[53.734927, -113.197527],
[53.753505, -113.172980],
[53.768016, -113.168688],
[53.774205, -113.157874],
[53.774284, -113.148883],
[53.715867, -113.149098],
[53.715934, -113.172036],
[53.686769, -113.172207],
[53.686935, -113.196896],
[53.367132, -113.197204],
[53.366818, -113.221196],
[53.337761, -113.220792],
[53.337882, -113.801601],
[53.367033, -113.807995],
[53.367197, -113.836702],
[53.716273, -113.836434]
],
[
[53.569268602609704, -113.71411800384523],
[53.51214299292513, -113.71411800384523],
[53.51214299292513, -113.68802547454835],
[53.403391858715274, -113.6907720565796],
[53.40461992848445, -113.64957332611085],
[53.3960226956682, -113.64614009857179],
[53.39684155458476, -113.34332942962648],
[53.4471711023092, -113.35744857788087],
[53.4471711023092, -113.24483871459962],
[53.57212285981298, -113.24445247650148],
[53.58149977709897, -113.29389095306398],
[53.58435320870081, -113.36118221282959],
[53.62102302920731, -113.3447027206421],
[53.646672964306994, -113.36942195892335],
[53.64952199454264, -113.57116699218751],
[53.669866612978275, -113.6345958709717],
[53.65603334084723, -113.70188713073732],
[53.57620003591595, -113.68678092956544]
]
],
[
[
[53.555985, -114.002024],
[53.555804, -114.038727],
[53.541397, -114.038512],
[53.541372, -114.050958],
[53.512009, -114.050958],
[53.512111, -114.026410],
[53.505169, -114.026410],
[53.505373, -113.971564],
[53.512034, -113.971650],
[53.512034, -113.959076],
[53.520338, -113.959179],
[53.519726, -113.885364],
[53.541153, -113.885364],
[53.541101, -113.845993],
[53.571438, -113.846851],
[53.570012, -113.885364],
[53.571082, -113.916435],
[53.569349, -113.959007],
[53.555451, -113.959383]
]
]
], {
color: 'yellow',
opacity: 1,
fillOpacity: 0.5
});
// CREATE POLYGONE RED
var polyRed = new L.Polygon([
// First polygon.
[
// First ring = outer ring, must bound the surface.
[
[53.773877, -114.001813],
[53.774105, -113.998508],
[53.774105, -113.917720],
[53.803400, -113.917398],
[53.803575, -113.661065],
[53.812242, -113.660379],
[53.818221, -113.652482],
[53.818221, -113.620124],
[53.803575, -113.620124],
[53.803499, -113.347294],
[53.818120, -113.347380],
[53.818145, -113.345062],
[53.830178, -113.334934],
[53.835015, -113.335750],
[53.842232, -113.324506],
[53.840485, -113.321759],
[53.845245, -113.314550],
[53.845448, -113.309958],
[53.847321, -113.309271],
[53.847296, -113.305537],
[53.845827, -113.306310],
[53.845827, -113.304164],
[53.844030, -113.306267],
[53.842283, -113.310601],
[53.825365, -113.310601],
[53.825340, -113.322317],
[53.803524, -113.322961],
[53.803244, -113.124330],
[53.774265, -113.124223],
[53.715852, -113.124309],
[53.715846, -113.098581],
[53.571181, -113.098811],
[53.366714, -113.098865],
[53.366702, -113.074291],
[53.279625, -113.074530],
[53.279664, -113.098670],
[53.279606, -113.220582],
[53.250595, -113.220603],
[53.250582, -113.488503],
[53.250531, -113.499918],
[53.235790, -113.499918],
[53.235892, -113.561716],
[53.250531, -113.561716],
[53.250556, -113.598323],
[53.257720, -113.598452],
[53.257771, -113.610425],
[53.265139, -113.610468],
[53.265062, -113.927419],
[53.366600, -113.927333],
[53.366715, -114.001904],
// up to here, -114.001904 is the West-most longitude
[53.505169, -114.001904], // Intersection point, manually built, but you can see a small gap.
// Reversed order
[53.505169, -114.026410], // More West than -114.001904
[53.512111, -114.026410], // More West than -114.001904
[53.512009, -114.050958], // More West than -114.001904
[53.541372, -114.050958], // More West than -114.001904
[53.541397, -114.038512], // More West than -114.001904
[53.555804, -114.038727], // More West than -114.001904
[53.555985, -114.002024], // More West than -114.001904
[53.555985, -114.001813] // Intersection point, manually built
]
// No other ring, therefore it should have no hole, but see 2nd polygon below.
],
// Second polygon, incorrectly rendered by Leaflet as a hole.
[
// First ring = outer ring, but incorrectly rendered by Leaflet as 1st hole of 1st polygon.
[
[53.716006, -113.252565],
[53.715496, -113.228546],
[53.717052, -113.215209],
[53.734927, -113.197527],
[53.753505, -113.172980],
[53.768016, -113.168688],
[53.774205, -113.157874],
[53.774284, -113.148883],
[53.715867, -113.149098],
[53.715934, -113.172036],
[53.686769, -113.172207],
[53.686935, -113.196896],
[53.367132, -113.197204],
[53.366818, -113.221196],
[53.337761, -113.220792],
[53.337882, -113.801601],
[53.367033, -113.807995],
[53.367197, -113.836702],
[53.716273, -113.836434]
],
// Second ring = hole.
[
[53.555985, -114.002024], // More West than -114.001904
[53.555804, -114.038727], // More West than -114.001904
[53.541397, -114.038512], // More West than -114.001904
[53.541372, -114.050958], // More West than -114.001904
[53.512009, -114.050958], // More West than -114.001904
[53.512111, -114.026410], // More West than -114.001904
[53.505169, -114.026410], // More West than -114.001904
[53.505373, -113.971564],
[53.512034, -113.971650],
[53.512034, -113.959076],
[53.520338, -113.959179],
[53.519726, -113.885364],
[53.541153, -113.885364],
[53.541101, -113.845993],
[53.571438, -113.846851],
[53.570012, -113.885364],
[53.571082, -113.916435],
[53.569349, -113.959007],
[53.555451, -113.959383]
]
]
], {
color: 'red',
opacity: 1,
fillOpacity: 0.3
});
//Add polygons to map
polyRed.addTo(map);
polyYellow.addTo(map);
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>
<div id="map" style="height: 200px"></div>
Кстати, это подчеркивает несогласованность в Leaflet, в котором используется 1-й полигон вашего определения multipolygon как внешнего кольца, а все кольца второго многоугольника - как дыры 1-го многоугольника. В то время как пример документов придерживается спецификации GeoJSON. Вероятно, это связано с выпуском лифлета № 3498.
Более надежным решением было бы правильно удалить ваши отверстия из вашего внешнего кольца, например, используя difference
Turf.js:
var outerRingLatLng = [
[53.773877, -114.001813],
[53.774105, -113.998508],
[53.774105, -113.917720],
[53.803400, -113.917398],
[53.803575, -113.661065],
[53.812242, -113.660379],
[53.818221, -113.652482],
[53.818221, -113.620124],
[53.803575, -113.620124],
[53.803499, -113.347294],
[53.818120, -113.347380],
[53.818145, -113.345062],
[53.830178, -113.334934],
[53.835015, -113.335750],
[53.842232, -113.324506],
[53.840485, -113.321759],
[53.845245, -113.314550],
[53.845448, -113.309958],
[53.847321, -113.309271],
[53.847296, -113.305537],
[53.845827, -113.306310],
[53.845827, -113.304164],
[53.844030, -113.306267],
[53.842283, -113.310601],
[53.825365, -113.310601],
[53.825340, -113.322317],
[53.803524, -113.322961],
[53.803244, -113.124330],
[53.774265, -113.124223],
[53.715852, -113.124309],
[53.715846, -113.098581],
[53.571181, -113.098811],
[53.366714, -113.098865],
[53.366702, -113.074291],
[53.279625, -113.074530],
[53.279664, -113.098670],
[53.279606, -113.220582],
[53.250595, -113.220603],
[53.250582, -113.488503],
[53.250531, -113.499918],
[53.235790, -113.499918],
[53.235892, -113.561716],
[53.250531, -113.561716],
[53.250556, -113.598323],
[53.257720, -113.598452],
[53.257771, -113.610425],
[53.265139, -113.610468],
[53.265062, -113.927419],
[53.366600, -113.927333],
[53.366715, -114.001904],
[53.773877, -114.001813] // Finish by first position for GeoJSON compliancy.
];
var hole1LatLng = [
[53.716006, -113.252565],
[53.715496, -113.228546],
[53.717052, -113.215209],
[53.734927, -113.197527],
[53.753505, -113.172980],
[53.768016, -113.168688],
[53.774205, -113.157874],
[53.774284, -113.148883],
[53.715867, -113.149098],
[53.715934, -113.172036],
[53.686769, -113.172207],
[53.686935, -113.196896],
[53.367132, -113.197204],
[53.366818, -113.221196],
[53.337761, -113.220792],
[53.337882, -113.801601],
[53.367033, -113.807995],
[53.367197, -113.836702],
[53.716273, -113.836434],
[53.716006, -113.252565] // Finish by first position for GeoJSON compliancy.
];
var hole2LatLng = [
[53.555985, -114.002024],
[53.555804, -114.038727],
[53.541397, -114.038512],
[53.541372, -114.050958],
[53.512009, -114.050958],
[53.512111, -114.026410],
[53.505169, -114.026410],
[53.505373, -113.971564],
[53.512034, -113.971650],
[53.512034, -113.959076],
[53.520338, -113.959179],
[53.519726, -113.885364],
[53.541153, -113.885364],
[53.541101, -113.845993],
[53.571438, -113.846851],
[53.570012, -113.885364],
[53.571082, -113.916435],
[53.569349, -113.959007],
[53.555451, -113.959383],
[53.555985, -114.002024] // Finish by first position for GeoJSON compliancy.
];
var outerRing = turf.polygon([latLngArrayToLngLat(outerRingLatLng)]);
var holes = turf.multiPolygon([
[latLngArrayToLngLat(hole1LatLng)],
[latLngArrayToLngLat(hole2LatLng)]
]);
var result = turf.difference(outerRing, holes);
var resultGeoJSON = turf.getGeom(result);
var map = L.map('map');
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
var geojsonLayer = L.geoJSON(resultGeoJSON, {
style: {
color: 'red',
opacity: 1,
fillOpacity: 0.3
}
}).addTo(map);
map.fitBounds(geojsonLayer.getBounds());
function latLngArrayToLngLat(latLngArray) {
return latLngArray.map(latLngToLngLat);
}
function latLngToLngLat(latLng) {
return [latLng[1], latLng[0]];
}
//Create polygon YELLOW
var polyYellow = new L.Polygon([
[
[
[53.716006, -113.252565],
[53.715496, -113.228546],
[53.717052, -113.215209],
[53.734927, -113.197527],
[53.753505, -113.172980],
[53.768016, -113.168688],
[53.774205, -113.157874],
[53.774284, -113.148883],
[53.715867, -113.149098],
[53.715934, -113.172036],
[53.686769, -113.172207],
[53.686935, -113.196896],
[53.367132, -113.197204],
[53.366818, -113.221196],
[53.337761, -113.220792],
[53.337882, -113.801601],
[53.367033, -113.807995],
[53.367197, -113.836702],
[53.716273, -113.836434]
],
[
[53.569268602609704, -113.71411800384523],
[53.51214299292513, -113.71411800384523],
[53.51214299292513, -113.68802547454835],
[53.403391858715274, -113.6907720565796],
[53.40461992848445, -113.64957332611085],
[53.3960226956682, -113.64614009857179],
[53.39684155458476, -113.34332942962648],
[53.4471711023092, -113.35744857788087],
[53.4471711023092, -113.24483871459962],
[53.57212285981298, -113.24445247650148],
[53.58149977709897, -113.29389095306398],
[53.58435320870081, -113.36118221282959],
[53.62102302920731, -113.3447027206421],
[53.646672964306994, -113.36942195892335],
[53.64952199454264, -113.57116699218751],
[53.669866612978275, -113.6345958709717],
[53.65603334084723, -113.70188713073732],
[53.57620003591595, -113.68678092956544]
]
],
[
[
[53.555985, -114.002024],
[53.555804, -114.038727],
[53.541397, -114.038512],
[53.541372, -114.050958],
[53.512009, -114.050958],
[53.512111, -114.026410],
[53.505169, -114.026410],
[53.505373, -113.971564],
[53.512034, -113.971650],
[53.512034, -113.959076],
[53.520338, -113.959179],
[53.519726, -113.885364],
[53.541153, -113.885364],
[53.541101, -113.845993],
[53.571438, -113.846851],
[53.570012, -113.885364],
[53.571082, -113.916435],
[53.569349, -113.959007],
[53.555451, -113.959383]
]
]
], {
color: 'yellow',
opacity: 1,
fillOpacity: 0.5
});
//Add polygons to map
polyYellow.addTo(map);
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>
<script src="https://unpkg.com/@turf/[email protected]/turf.js"></script>
<div id="map" style="height: 200px"></div>
Конечно, вы могли бы просто сохранить результат этого рефакторинга в качестве своего нового определения для вашего КРАСНОГО многоугольника, который теперь имеет только 1 отверстие.