相关文章推荐
风流的沙滩裤  ·  搜索结果·  1 周前    · 
风流的沙滩裤  ·  延安样本·  1 周前    · 
风流的沙滩裤  ·  搜索结果·  1 周前    · 

在圖論(graph theory)與地圖學(cartography)中,「 四色定理(Four Color Theorem) 」與「 五色定理(Five Color Theorem) 」是兩項經典的重要命題。 四色定理指出,任意一張平面地圖,只需使用四種顏色,就能保證所有相鄰區域都不會使用相同顏色 ,是1852年由數學家賈斯禮(Francis Guthrie)首次提出四色定理的猜想,雖然從地圖設計的實務上確實能僅用四種顏色就把地圖著色,且相鄰不同色,但一直與無法用數學方式證明它,直到 1976 年由 Appel 與 Haken 借助電腦演算法輔助(暴力窮舉法)成功證明,成為數學史上首例以電腦完成的證明之一。

四色地圖的案例(來源:wiki百科)

在四色定理尚未被正式證明前,數學家 Heawood 於 1890 年提出了較為保守但易於證明的 五色定理,主張任意平面圖最多使用五種顏色也可避免相鄰區域顏色重複 。五色定理雖非最精簡解法,卻在地圖設計實務上提供了一項重要保證,特別適用於複雜地圖或圖層自動著色演算法中。

目前在QGIS 3.x版中內建有拓撲著色(Topological coloring)功能,但因演算法設計需求而採用最多五色完成著色任務,即使理論上四色已經足夠,以下為簡要操作說明:

import networkx as nx
from qgis.core import (
QgsProject, QgsField, QgsSpatialIndex, QgsFeature, QgsGeometry, QgsPointXY
)
from PyQt5.QtCore import QVariant

layer = iface.activeLayer()
if not layer or layer.geometryType() != 2:
raise Exception("請選取一個多邊形圖層")

# 新增 color_id 欄位
layer.startEditing()
if 'color_id' not in [f.name() for f in layer.fields()]:
layer.dataProvider().addAttributes([QgsField('color_id', QVariant.Int)])
layer.updateFields()

# 建立要素快取與空間索引
features = {f.id(): f for f in layer.getFeatures()}
index = QgsSpatialIndex()
for feat in features.values():
index.insertFeature(feat)

# 建立鄰接圖
G = nx.Graph()
for fid, feat in features.items():
G.add_node(fid)
neighbor_ids = index.intersects(feat.geometry().boundingBox())
for nid in neighbor_ids:
if nid != fid and feat.geometry().touches(features[nid].geometry()):
G.add_edge(fid, nid)

# 計算圖層中心點
layer_center = layer.extent().center()
center_geom = QgsGeometry.fromPointXY(QgsPointXY(layer_center))

# 根據與中心距離排序
def dist_to_center(feat):
return feat.geometry().centroid().distance(center_geom)

sorted_nodes = sorted(G.nodes, key=lambda fid: dist_to_center(features[fid]))

# 自行進行貪婪著色(最多使用 4 色)
coloring = {}
for fid in sorted_nodes:
neighbor_colors = {coloring[n] for n in G.neighbors(fid) if n in coloring}
for color in range(1, 5): # 限定四色
if color not in neighbor_colors:
coloring[fid] = color
break

# 寫入 color_id
field_idx = layer.fields().indexFromName('color_id')
for fid, color in coloring.items():
layer.changeAttributeValue(fid, field_idx, color)

layer.commitChanges()
print(f"完成!已從圖層中心開始排序並套用四色著色,共使用顏色:{max(coloring.values())}")
臺灣四色地圖

進階閱讀: