如何使用 Leaflet 将四色定理应用于 GeoJSON 特征集合

问题描述 投票:0回答:1

假设您有一个 GeoJSON 特征集合,其中包含在 Leaflet 地图中显示的相邻彩色多边形;在本案中,里斯本市的教区

运行代码片段以查看地图

fetch('https://geoapi.pt/municipio/lisboa/freguesias?json=1').then(r => r.json()).then(data => {
  const geojsons = data.geojsons
  
  var map = L.map('map')

  const bbox = geojsons.municipio.bbox
  const corner1 = L.latLng(bbox[1], bbox[0])
  const corner2 = L.latLng(bbox[3], bbox[2])
  const bounds = L.latLngBounds(corner1, corner2)
  map.fitBounds(bounds)
  
  L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
  }).addTo(map)

  // feature collection
  const parishesGeoJsonFeatureCollection = {
    type: 'FeatureCollection',
    features: geojsons.freguesias
  }

  // need this for color pallete
  const numberOfParishes = parishesGeoJsonFeatureCollection.features.length
  parishesGeoJsonFeatureCollection.features.forEach((parish, index) => {
    parish.properties.index = index
  })

  L.geoJson(parishesGeoJsonFeatureCollection, {
    style
  }).addTo(map)

  function style (feature) {
    return {
      weight: 2,
      opacity: 1,
      color: 'white',
      dashArray: '3',
      fillOpacity: 0.7,
      fillColor: getColor(feature.properties.index, numberOfParishes)
    }
  }

})

// get random color
function getColor (index, size) {
  const colors = {
    3: ['#8dd3c7', '#ffffb3', '#bebada'],
    4: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072'],
    5: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3'],
    6: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462'],
    7: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69'],
    8: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5'],
    9: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9'],
    10: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd'],
    11: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5'],
    12: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffed6f']
  }

  if (size < 3) {
    return colors[3][index]
  } else if (size <= 12) {
    return colors[size][index]
  } else {
    return colors[12][index % 12]
  }
}
#map { height: 220px; }
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
     integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI="
     crossorigin=""/>
 <script src="https://unpkg.com/[email protected]/dist/leaflet.js"
     integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM="
     crossorigin=""></script>

<div id="map"></div>

您将如何应用四色定理或任何合适的算法来避免相邻的多边形具有相同的颜色?

leaflet mathematical-optimization color-theory
1个回答
0
投票

感谢来自other stack exchange site的@TomazicM,我可以实现它。请相应地给他投票,而不是我,我只是在这里发帖让刚到这里的用户知道,因为 SO 允许插入代码片段,因此你可以看到它在现场工作。

它利用了另一个名为TopoJSON

的库

const colors = ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffed6f']

function style (feature) {
  return {
    weight: 2,
    opacity: 1,
    color: 'white',
    dashArray: '3',
    fillOpacity: 0.7,
    fillColor: colors[feature.properties.colorIndex]
  }
} 

fetch('https://geoapi.pt/municipio/lisboa/freguesias?json=1').then(r => r.json()).then(data => {
  const geojsons = data.geojsons
  
  var map = L.map('map')

  const bbox = geojsons.municipio.bbox
  const corner1 = L.latLng(bbox[1], bbox[0])
  const corner2 = L.latLng(bbox[3], bbox[2])
  const bounds = L.latLngBounds(corner1, corner2)
  map.fitBounds(bounds)
    L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
  }).addTo(map)

  // feature collection
  const parishesGeoJsonFeatureCollection = {
    type: 'FeatureCollection',
    features: geojsons.freguesias
  }

var topoJSON = topojson.topology([parishesGeoJsonFeatureCollection], 1e4);

  var neighbors = topojson.neighbors(topoJSON.objects[0].geometries);
  
  var featureColors = [];
  parishesGeoJsonFeatureCollection.features.forEach((parish, index) => {
    for (var i = 0; i < colors.length; i++) {
      var found = false;
      for (var j = 0; j < neighbors[index].length; j++) {
        if (featureColors[neighbors[index][j]] == i) {
          found = true;
          break;
        }
      }
      if (!found) break;
    }
    featureColors[index] = i;
    parish.properties.colorIndex = i;
  });

  L.geoJson(parishesGeoJsonFeatureCollection, {
    style
  }).addTo(map)
})
#map { height: 220px; }
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
     integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI="
     crossorigin=""/>
 <script src="https://unpkg.com/[email protected]/dist/leaflet.js"
     integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM="
     crossorigin=""></script>
<script src="https://unpkg.com/topojson@3"></script>

<div id="map"></div>

© www.soinside.com 2019 - 2024. All rights reserved.