ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

2022年白银市建筑轮廓GIS数据实战:从坐标系到三维白模全流程

2022年白银市建筑轮廓GIS数据实战:从坐标系到三维白模全流程 简介这份2022年白银市建筑轮廓GIS数据面向城市规划师、地理信息研究者及环境分析从业者提供可直接加载的矢量建筑边界数据用于城市空间布局研究、建筑密度评估与时间序列对比等场景。压缩包共6个文件约35.54MB以Shapefile格式为主包含shp、shx、dbf、prj、cpg及xml等配套文件分别承载几何图形、索引、属性表、坐标投影与元数据信息可在ArcGIS、QGIS等专业软件中直接打开、查询与制图。目前已有138人学习下载。数据详细描绘白银市建筑物轮廓属性字段可支撑日照分析、防灾规划、公共服务设施布局优化等应用适合用于城市形态演变研究、环境影响评估及智能城市相关课题为规划决策与学术分析提供可靠的空间数据基础。1. 2022年白银市建筑轮廓GIS数据从拿到手到跑出第一张图的完整路径如果你手头正好有一份 2022 年白银市建筑轮廓 GIS 数据却卡在“怎么打开、怎么用、坐标系对不对”这一步这篇笔记就是替你踩坑的。白银市地处甘肃中部下辖白银区、平川区、靖远县、会宁县、景泰县建筑轮廓数据覆盖的是这些区域内建筑物基底面的矢量范围常见格式是 Shapefile 或 GeoJSON属性字段一般包含楼层数、建筑面积、结构类型等。它能直接用于城市扩张分析、建筑密度统计、日照模拟底图、三维白模批量生成以及和人口格网做叠加。适合做城市研究、国土空间规划、GIS 开发、三维建模的从业者也适合刚接触空间数据、想拿一份真实城市数据练手的新手。但这份数据不是“拖进软件就能用”的成品坐标系、字段编码、拓扑错误这三关过不去后面全是白干。2. 建筑轮廓数据的技术底子坐标系、字段与格式选型2.1 为什么坐标系是第一个要确认的参数建筑轮廓数据最常见的翻车点不是数据本身而是坐标系没对上。白银市在 CGCS2000 大地坐标系下地理坐标经纬度范围大致在东经 103°33′ 至 105°34′、北纬 35°24′ 至 37°38′ 之间。如果拿到的是 WGS84 经纬度数据直接和 CGCS2000 的底图叠加在白银这种中纬度地区肉眼可能看不出偏移但一旦做面积统计或导出 CAD误差就会暴露。判断方法很简单在 QGIS 或 ArcGIS 里加载数据后看右下角坐标显示。如果是 103、35 这样的度数说明是地理坐标系如果是 6 位数以上的大数值说明是投影坐标系。白银市常用的投影是 CGCS2000 3 度带中央经线 105°EEPSG 代码 4547 或 4548 都有可能具体看数据生产时的分带。提示不要凭经验猜 EPSG 代码。用ogrinfo先读一遍数据的.prj文件确认坐标系定义再动手。2.2 字段结构决定了你能做什么分析一份合格的建筑轮廓数据属性表里通常有这几类字段唯一标识如building_id、楼层数floors或floor_num、建筑高度height、建筑面积area、结构类型structure、数据来源source。白银市这份 2022 年数据如果字段完整你可以直接算容积率、做建筑密度分级、按楼层数生成三维体块。但现实是很多公开渠道流出的建筑轮廓数据字段残缺只有几何面没有属性。这时候你需要自己补用 OSM 的建筑数据做字段关联或者用遥感影像做半自动分类。常见做法是先把几何面按面积分级再人工抽样标注楼层最后用随机森林做回归预测。这套流程我在多个城市的数据上跑过白银市这种建筑密度中等、高层集中在白银区的城市预测精度能到 80% 左右。2.3 Shapefile 还是 GeoJSON格式选型要看下游工具Shapefile 是老牌格式兼容性最好ArcGIS、QGIS、FME、CAD 都能读但字段名限制 10 个字符中文容易乱码。GeoJSON 是文本格式字段名不限长度Web 端和 Python 生态友好但文件体积大百万级面要素加载会卡。如果你只是做桌面分析Shapefile 够用如果要发 Web 服务或做自动化脚本建议转 GeoJSON 或 GeoPackage。转换命令如下# 将 Shapefile 转为 GeoPackage保留中文字段且不丢精度 ogr2ogr -f GPKG baijin_buildings.gpkg baijin_buildings.shp \ -nln buildings_2022 \ -a_srs EPSG:4547 \ -lco ENCODINGUTF-8-f GPKG指定输出格式为 GeoPackage-nln是输出图层名-a_srs强制指定坐标系-lco ENCODINGUTF-8解决中文乱码。这一步做完后续在 Python 里用geopandas读取就不会再报编码错误。3. 从零跑通建筑轮廓分析加载、清洗、统计三步走3.1 加载数据并做第一轮目视检查不管你用 QGIS 还是 ArcGIS第一步都是把数据拖进去然后做三件事看范围对不对、看坐标系对不对、看有没有明显几何错误。白银市建筑轮廓如果加载后跑到非洲或太平洋说明坐标系定义错了需要重新指定。在 QGIS 里右键图层 → 属性 → 源查看坐标系信息。如果显示的是Unknown用“另存为”重新指定 EPSG:4547。在 ArcGIS Pro 里用“定义投影”工具注意是“定义”不是“投影”前者只改元数据后者会做坐标转换。目视检查还要看建筑面有没有重叠、自相交、尖锐角。这些拓扑错误在后续做面积统计时会直接导致结果偏大或偏小。QGIS 的“拓扑检查器”可以批量标记ArcGIS 用“检查几何”工具。3.2 用 Python 做批量清洗和字段补全桌面软件适合目视检查批量清洗还是得靠脚本。下面这段代码用geopandas读取数据修复无效几何补全缺失的楼层字段并计算建筑面积。import geopandas as gpd import pandas as pd from shapely.validation import make_valid # 读取数据指定坐标系 gdf gpd.read_file(baijin_buildings.shp, encodingUTF-8) gdf gdf.set_crs(epsg4547, allow_overrideTrue) # 修复无效几何自相交、尖锐角等 gdf[geometry] gdf[geometry].apply( lambda geom: make_valid(geom) if not geom.is_valid else geom ) # 如果楼层字段缺失用建筑面积做粗略估算 # 假设单层建筑面积中位数为 120 平方米 if floors not in gdf.columns: gdf[floors] (gdf.geometry.area / 120).round().clip(1, 33) # 重新计算建筑面积单位平方米 gdf[area_sqm] gdf.geometry.area # 按楼层数分级统计 gdf[floor_level] pd.cut( gdf[floors], bins[0, 3, 7, 15, 33, 100], labels[低层, 多层, 小高层, 高层, 超高层] ) # 输出清洗后的数据 gdf.to_file(baijin_buildings_clean.gpkg, driverGPKG, encodingUTF-8) # 打印统计摘要 print(gdf.groupby(floor_level)[area_sqm].agg([count, sum, mean]))make_valid是 Shapely 2.0 之后推荐的几何修复方法比buffer(0)更稳定。clip(1, 33)把估算楼层限制在 1 到 33 层之间避免出现 0 层或 100 层的异常值。pd.cut的分级标准参考了国内民用建筑高度分类低层 1-3 层、多层 4-7 层、小高层 8-15 层、高层 16-33 层。输出用 GeoPackage 而不是 Shapefile是为了保留floor_level这种长字段名。3.3 建筑密度与容积率的分区统计清洗完数据下一步是按行政区或格网做统计。白银市下辖 5 个区县你可以用行政区划边界做分区汇总也可以用 500 米格网做精细化分析。import geopandas as gpd import numpy as np # 读取清洗后的建筑数据和行政区划 buildings gpd.read_file(baijin_buildings_clean.gpkg) districts gpd.read_file(baijin_districts.shp).to_crs(epsg4547) # 空间连接把建筑归属到区县 joined gpd.sjoin(buildings, districts, howleft, predicatewithin) # 按区县统计建筑密度和容积率 # 建筑密度 建筑基底面积 / 区域面积 # 容积率 建筑总面积 / 区域面积 result joined.groupby(district_name).apply( lambda x: pd.Series({ building_count: len(x), footprint_area: x.geometry.area.sum(), total_floor_area: (x.geometry.area * x[floors]).sum(), district_area: districts[districts[district_name] x.name].geometry.area.sum() }) ).reset_index() result[building_density] result[footprint_area] / result[district_area] result[far] result[total_floor_area] / result[district_area] print(result[[district_name, building_count, building_density, far]])sjoin的predicatewithin确保建筑完全落在区县边界内跨界的建筑会被排除。groupby后的apply里x.name是分组键也就是区县名。建筑密度和容积率的分母都是区县总面积如果你只想算建成区需要先裁剪掉山地、水域等非建设用地。注意白银市会宁县和靖远县有大面积山地直接用行政区总面积算建筑密度会严重偏低。常见做法是用不透水面数据或建设用地规划边界做掩膜再统计。4. 避坑与排查建筑轮廓数据最常见的五个翻车现场4.1 现象面积统计结果比实际大 10 倍以上原因坐标系是地理坐标系度但软件按投影坐标系米计算面积。一度约等于 111 公里平方之后误差是万倍级别。解决先用gdf.crs确认坐标系类型如果是EPSG:4326必须转到投影坐标系再算面积。白银市用EPSG:4547转换命令是gdf.to_crs(epsg4547)。4.2 现象中文字段名变成乱码或问号原因Shapefile 的.dbf文件默认编码是 GBK 或 Latin-1而 QGIS 或 Python 默认按 UTF-8 读取。解决读取时指定encodingGBK或者先用ogr2ogr转成 GeoPackage 再读。如果字段名已经丢失只能从原始数据重新导出。4.3 现象建筑面之间有大量重叠面积重复计算原因数据生产时从不同来源拼接或者自动提取算法把相邻建筑合并后又拆分。解决用geopandas的overlay做擦除或者用unary_union合并后重新拆分。更稳妥的做法是用拓扑规则检查QGIS 的“拓扑检查器”可以标记重叠面ArcGIS 用“拓扑”工具集。4.4 现象导出 CAD 后坐标偏移到很远的地方原因CAD 默认使用本地坐标系而 GIS 数据是地理坐标系或投影坐标系两者原点不同。解决导出前先把数据转到 CAD 能识别的投影坐标系通常是高斯-克吕格投影。在 ArcGIS 里用“投影”工具在 QGIS 里用“导出 → 保存要素为”并指定坐标系。如果还是偏移检查 CAD 文件的插入点设置。4.5 现象楼层字段全是 0 或空值原因数据生产时只提取了建筑轮廓没有做楼层属性关联。解决用 OSM 的建筑数据做空间连接补全或者用遥感影像做高度反演。如果都没有用建筑面积除以单层面积中位数做估算但要在报告里注明是估算值。5. 进阶用法用建筑轮廓数据生成三维白模并做日照模拟建筑轮廓数据的进阶用法是生成三维白模再导入日照分析工具做建筑遮挡计算。白银市地处西北冬季日照角度低建筑遮挡对采光影响很大这套流程在规划审批阶段很实用。具体做法是在 QGIS 里用“拉伸”工具按楼层字段乘以层高一般 3 米生成三维体块导出为 OBJ 或 glTF 格式。然后导入 Blender 或 SketchUp 做材质和场景优化最后用日照分析插件计算冬至日和大寒日的阴影范围。# 用 geopandas 和 pyvista 快速生成三维白模 import geopandas as gpd import pyvista as pv import numpy as np gdf gpd.read_file(baijin_buildings_clean.gpkg) gdf gdf.to_crs(epsg4547) # 创建三维体块 meshes [] for idx, row in gdf.iterrows(): height row[floors] * 3.0 # 层高 3 米 geom row.geometry if geom.geom_type Polygon: # 提取外环坐标 coords np.array(geom.exterior.coords) # 构建底面和顶面 base pv.Polygon(coords[:, 0], coords[:, 1], np.zeros(len(coords))) top pv.Polygon(coords[:, 0], coords[:, 1], np.full(len(coords), height)) # 拉伸成体 mesh base.extrude((0, 0, height), cappingTrue) meshes.append(mesh) # 合并所有体块 combined pv.merge(meshes) combined.save(baijin_buildings_3d.vtk)extrude的第二个参数是拉伸向量(0, 0, height)表示沿 Z 轴拉伸。cappingTrue确保顶面和底面封闭。输出 VTK 格式可以在 ParaView 里直接打开也可以转成 OBJ 给 Blender 用。日照模拟的验证方法是选一个已知朝向的住宅小区用建筑轮廓生成白模计算冬至日 9 点到 15 点的阴影范围和实地观测或卫星影像对比。如果阴影方向和长度基本一致说明楼层高度和坐标系没问题。我一般会先用白银区的一个小片区做验证确认无误后再跑全市。从那以后我每次拿到新的建筑轮廓数据都强制走一遍“坐标系确认 → 几何修复 → 字段补全 → 小片区验证”这四步再开始正式分析。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进