【问题标题】:leaflet js fill color error when hole overlaps boundary of polygon当孔与多边形的边界重叠时,传单js填充颜色错误
【发布时间】:2018-02-10 14:32:23
【问题描述】:

我在传单 js 地图中定义了一个多边形(在 bing 地图上)。
这个多边形有两个洞(黄色多边形)切出来。 SECOND 孔多边形与主多边形的外边界重叠。

问题:

SECOND 多边形超出主多边形外边缘的部分将获得主多边形的填充颜色。

在这种情况下,主多边形是红色,被移除的整体是黄色

我在附图中圈出了问题。

以下是fiddle where I have recreated the issue

问题

有人可以帮我弄清楚如何从红色多边形中删除第二个黄色形状的部分,而不会出现这种重叠颜色问题吗?

为清楚起见,这里是小提琴中的所有代码:

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

【问题讨论】:

    标签: javascript maps leaflet


    【解决方案1】:

    您的外环(即您的 RED 多面体定义中的第一个多边形阵列)应该限制您的几何体,包括孔。

    在您当前的定义中,第 2 个孔(即 RED 多面体定义中的第 2 个多边形的第 2 个环)比外环向西延伸(某些坐标的经度低于外环的最低位置)。

    这种不一致使得渲染难以正确地表示带有孔的多面体,导致孔的一部分被填充颜色。

    一个“简单”的解决方案是手动修改您的外圈以完全包含您的孔:

    // 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/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>
    
    <div id="map" style="height: 200px"></div>

    顺便说一句,这突出了 Leaflet 中的一个不一致之处,即使用多多边形定义的第一个多边形作为外环,将第二个多边形的所有环作为第一个多边形的孔。而docs example 坚持 GeoJSON 规范。这可能与Leaflet issue #3498有关。

    更可靠的解决方案是从外环上正确移除孔,例如使用Turf.jsdifference:

    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/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>
    
    <script src="https://unpkg.com/@turf/turf@5.1.6/turf.js"></script>
    
    <div id="map" style="height: 200px"></div>

    当然,您可以简单地将重构的结果保存为您的 RED 多边形的新定义,该多边形现在只有 1 个孔。

    【讨论】:

    • 感谢吉布斯。我花时间重新加工原始多边形,只剪掉形状本身,而不是使用“洞”。我不知道 turf,它看起来像一个超级有用的库,我会深入研究它。再次感谢您提供详细的答案和示例!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多