листовка js заполняет цветовую ошибку, когда отверстие перекрывает границу многоугольника

1

У меня есть многоугольник, определенный в листе js map (над бинговым отображением).
Этот многоугольник имеет два отверстия (желтые полигоны), вырезанные из него. ВТОРОЙ дырочный многоугольник перекрывает внешнюю границу основного многоугольника.

Изображение 174551

ПРОБЛЕМА:

Часть второго многоугольника, который проходит мимо внешнего края первичного многоугольника, получает цвет заливки основного многоугольника.

В этом случае основной многоугольник является красным, а все удаляется желтым

Я связал проблему в прилагаемом изображении.

Ниже приводится сценарий, в котором я воссоздал проблему.

ВОПРОС

Может ли кто-нибудь помочь мне разобраться, как удалить часть второй желтой формы из красного многоугольника без этой проблемы с перекрытием?

Для ясности здесь приведен весь код из скрипки:

// 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

Теги:
leaflet
maps

1 ответ

1
Лучший ответ

Ваше внешнее кольцо (т.е. Первый многоугольник в вашем 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: '&copy; <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 отверстие.

  • 0
    спасибо, гибриды. Я потратил время на переработку оригинального многоугольника, чтобы просто вырезать саму фигуру вместо использования «дыры». Я не знал о газоне, который выглядит как супер полезная библиотека, и я буду копаться в нем. Еще раз спасибо за подробный ответ и пример!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню