You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Leaflet中为GeoJSON要素集应用四色定理避免邻接多边形同色

解决Leaflet邻接多边形同色问题(基于四色定理)

原代码按索引直接分配颜色,会出现邻接教区颜色重复的情况。根据四色定理,任何平面地图都可以用最多4种颜色完成无冲突着色,下面是具体实现方案:

核心思路

  1. 构建邻接关系表:遍历所有多边形,找出每个多边形的相邻对象
  2. 贪心着色算法:为每个多边形分配第一个未被相邻多边形使用的颜色

修改后的完整代码

JavaScript 代码

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)

  // 存储所有教区的Leaflet图层对象
  const parishLayers = [];
  // 邻接关系表:key是图层索引,value是相邻的图层索引数组
  const adjacencyList = {};

  // 先创建所有图层并添加到地图
  const parishesGeoJsonFeatureCollection = {
    type: 'FeatureCollection',
    features: geojsons.freguesias
  };

  L.geoJson(parishesGeoJsonFeatureCollection, {
    onEachFeature: (feature, layer) => {
      parishLayers.push(layer);
      // 给每个图层添加索引属性
      layer.index = parishLayers.length - 1;
      adjacencyList[layer.index] = [];
    }
  }).addTo(map);

  // 构建邻接关系表
  parishLayers.forEach((layerA, indexA) => {
    parishLayers.forEach((layerB, indexB) => {
      if (indexA !== indexB && layerA.intersects(layerB)) {
        // 避免重复添加邻接关系
        if (!adjacencyList[indexA].includes(indexB)) {
          adjacencyList[indexA].push(indexB);
        }
      }
    });
  });

  // 贪心着色:为每个图层分配颜色
  const colorPalette = ['#8dd3c7', '#fb8072', '#bebada', '#ffffb3']; // 4种符合四色定理的颜色
  parishLayers.forEach((layer, index) => {
    // 获取相邻图层已使用的颜色索引
    const usedColorIndices = adjacencyList[index].map(neighborIndex => parishLayers[neighborIndex].colorIndex);
    // 找到第一个未被使用的颜色索引
    let colorIndex = 0;
    while (usedColorIndices.includes(colorIndex)) {
      colorIndex++;
    }
    layer.colorIndex = colorIndex;
    // 更新图层样式
    layer.setStyle({
      weight: 2,
      opacity: 1,
      color: 'white',
      dashArray: '3',
      fillOpacity: 0.7,
      fillColor: colorPalette[colorIndex]
    });
  });
});

CSS 代码

#map { height: 220px; }

HTML 代码

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css"
     integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI="
     crossorigin=""/>
 <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"
     integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM="
     crossorigin=""></script>

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

关键部分说明

  • 邻接关系检测:利用Leaflet图层的intersects方法判断两个多边形是否相邻,构建邻接表存储每个多边形的邻居索引
  • 贪心着色:遍历每个多边形,排除邻居已使用的颜色,选择第一个可用的颜色。四色定理保证最多4种颜色足够,因此只需要定义4种颜色即可
  • 样式更新:为每个图层分配颜色后,通过setStyle方法更新填充色,确保邻接多边形颜色不重复

内容的提问来源于stack exchange,提问作者João Pimentel Ferreira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 21:12:16