如何在Leaflet中为GeoJSON要素集应用四色定理避免邻接多边形同色
解决Leaflet邻接多边形同色问题(基于四色定理)
原代码按索引直接分配颜色,会出现邻接教区颜色重复的情况。根据四色定理,任何平面地图都可以用最多4种颜色完成无冲突着色,下面是具体实现方案:
核心思路
- 构建邻接关系表:遍历所有多边形,找出每个多边形的相邻对象
- 贪心着色算法:为每个多边形分配第一个未被相邻多边形使用的颜色
修改后的完整代码
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: '© <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
相关产品推荐
相关产品推荐

