CSV转换为QGIS的简单分类符号

最近遇到一个需求是需要将客户提供的csv或者excel,按照某个字段进行分类然后转换为简单的分类符号,即csv里有对应的名字和颜色,需要把这些转化为qml。由于QGIS里可以使用python脚本,所以直接使用pyrhon去处理。在这里以面符号为例,点线面原理相同

1

首先随便加载一个客户的面数据

2

然后打开qgis python控制台,把如下代码粘进去

python 复制代码
from qgis.core import QgsProject, QgsVectorLayer, QgsCategorizedSymbolRenderer, QgsRendererCategory, QgsFillSymbol
import math
import chardet  # 用于检测文件编码

# ===== 配置参数 (根据实际情况修改这些值) =====
# 面图层的名称(在QGIS图层面板中显示的名称)
polygon_layer_name = "岩体"

# CSV文件的路径(确保已导出为CSV格式)
csv_path = "C:/D/Dev/project/dzsjk/其它/长大符号/V2/土体merge.csv"  # 请确认路径正确

# 输出QML文件的路径
output_qml_path = "C:/D/Dev/project/dzsjk/其它/长大符号/V2/土体一万.qml"

# CSV中的字段名称配置
label_field = "label"    # 编码字段名
name_field = "名称"      # 图例名称字段名
r_field = "R"           # 红色字段名
g_field = "G"           # 绿色字段名
b_field = "B"           # 蓝色字段名

# ===== 主程序开始 =====
# 获取面图层
polygon_layer = QgsProject.instance().mapLayersByName(polygon_layer_name)
if not polygon_layer:
    raise ValueError(f"找不到图层: {polygon_layer_name}")
polygon_layer = polygon_layer[0]

# 创建分类列表
categories = []

# 检测文件编码
with open(csv_path, 'rb') as f:
    raw_data = f.read()
    encoding_detection = chardet.detect(raw_data)
    file_encoding = encoding_detection['encoding'] or 'gbk'  # 默认使用gbk

print(f"检测到文件编码: {file_encoding} (置信度: {encoding_detection['confidence']})")

# 读取CSV数据
with open(csv_path, 'r', encoding=file_encoding, errors='ignore') as f:
    # 读取所有行
    lines = f.readlines()
    
    # 如果第一行有BOM标记,则移除
    if lines and lines[0].startswith('\ufeff'):
        lines[0] = lines[0][1:]
    
    # 获取字段行
    headers = lines[0].strip().split(',')
    print(f"CSV头部字段: {headers}")
    
    # 获取字段索引
    try:
        label_idx = headers.index(label_field)
        name_idx = headers.index(name_field)
        r_idx = headers.index(r_field)
        g_idx = headers.index(g_field)
        b_idx = headers.index(b_field)
    except ValueError as e:
        print(f"错误: CSV文件中缺少必要字段: {str(e)}")
        print(f"可用字段: {headers}")
        raise
    
    print(f"找到 {len(lines)-1} 条颜色记录")
    
    # 处理数据行
    for i, line in enumerate(lines[1:]):
        # 清理行并分割字段
        cleaned_line = line.strip().replace('\ufeff', '')
        parts = cleaned_line.split(',')
        
        # 确保有足够字段
        if len(parts) < max(label_idx, name_idx, r_idx, g_idx, b_idx) + 1:
            print(f"跳过第 {i+2} 行: 字段不足 ({len(parts)}/{max(label_idx, name_idx, r_idx, g_idx, b_idx) + 1})")
            continue
        
        label = parts[label_idx].strip()
        name_value = parts[name_idx].strip()
        
        print(f"处理记录 {i+1}: label={label}, name={name_value}")
        
        try:
            # 尝试解析RGB值
            r_val = parts[r_idx].strip()
            g_val = parts[g_idx].strip()
            b_val = parts[b_idx].strip()
            
            # 转换RGB值为浮点数
            r_float = float(r_val)
            g_float = float(g_val)
            b_float = float(b_val)
            
            # 浮点数转整数 (四舍五入)
            r = math.floor(r_float + 0.5)
            g = math.floor(g_float + 0.5)
            b = math.floor(b_float + 0.5)
            
            # 确保RGB值在0-255范围内
            r = max(0, min(255, r))
            g = max(0, min(255, g))
            b = max(0, min(255, b))
            
            # 创建RGB颜色字符串
            color_rgb = f"{int(r)},{int(g)},{int(b)}"
            
            # 创建符号
            symbol = QgsFillSymbol.createSimple({
                'color': color_rgb,
                'color_border': '0,0,0',  # 黑色边框
                'width_border': '0.26',   # 边框宽度
                'style': 'solid',         # 实心填充
                'style_border': 'solid'   # 实线边框
            })
            
            # 创建分类 - 使用名称字段作为图例标签
            category = QgsRendererCategory(label, symbol, name_value)
            categories.append(category)
            
            print(f"添加分类: {label} ({name_value}) -> RGB({r}, {g}, {b})")
            
        except (ValueError, TypeError) as e:
            print(f"无效的RGB值: 行 {i+2} - label={label}, R={r_val}, G={g_val}, B={b_val}")
            print(f"错误详情: {str(e)}")

# 检查是否找到有效分类
if not categories:
    raise ValueError("未创建任何有效分类,请检查数据和字段名")

# 创建分类渲染器
renderer = QgsCategorizedSymbolRenderer(label_field, categories)
polygon_layer.setRenderer(renderer)

# 刷新地图
polygon_layer.triggerRepaint()
iface.layerTreeView().refreshLayerSymbology(polygon_layer.id())

# 导出QML文件
success = polygon_layer.saveNamedStyle(output_qml_path)

print("="*50)
if success:
    print(f"成功导出QML文件: {output_qml_path}")
else:
    print(f"导出QML文件失败,请检查写入权限和路径")
print(f"处理了 {len(categories)} 个有效分类")
print("图例标签使用字段: " + name_field)
print("="*50)

一定要注意,这个代码是根据下面的csv字段配置的,大家使用代码一定要结合自己的csv再去修改,同时注意要把路径修改为自己的,csv字段如下:

需要按照label字段进行分类,然后图例就是名称字段

3

复制完之后再去运行,最后就得到了自己想要的qml

相关推荐
角砾岩队长1 天前
基于ArcGIS实现Shapefile转KML并保留标注
arcgis
细节控菜鸡1 天前
【2025最新】ArcGIS for JS二维底图与三维地图的切换
javascript·arcgis
zenithdev12 天前
开源库入门教程 Cesium:3D地球和地图库
其他·3d·arcgis
Rotion_深3 天前
海康 智能相机二开 绘制底图+测试工具应用框
c#·二次开发·海康·智能相机
徐赛俊4 天前
QGIS + ArcGIS Pro 下载常见卫星影像及 ESRI Wayback 历史影像
arcgis
大大大大大大大大大泡泡糖4 天前
使用arcgis提取评价指标时,导出数据是负数-9999
arcgis
杨超越luckly4 天前
HTML应用指南:利用POST请求获取全国索尼体验型零售店位置信息
前端·arcgis·html·数据可视化·门店数据
GIS阵地4 天前
在QGIS中将多个图层导出到一个geojson里 gdb转geojson qgis强大的格式转换工具
二次开发·qgis·地理信息系统·pyqgis
fenghx2585 天前
vscode使用arcpy-选择arcgis带的python+运行错误解决
vscode·python·arcgis