feat: 拆分 DXF 解析为模块化结构,新增图层分析和实体分析模块

- 新增 layer_analysis.py:图层实体统计 + 角色推断(22条启发式规则)
- 新增 entity_analysis.py:实体类型统计、INSERT 块聚合、文本提取
- 重构 main.py:调度分析模块,输出 {文件名}_cad_analysis.json
- 新增 README.md 使用说明
- 输出文件名使用模型名作为前缀,避免多次测试覆盖
This commit is contained in:
zwt13703
2026-07-08 14:31:27 +08:00
parent 6501364164
commit 9feeb14910
5 changed files with 428 additions and 394 deletions
+94
View File
@@ -0,0 +1,94 @@
"""图层分析模块 —— 统计每层实体数量与类型,并基于图层名称进行角色推断。"""
# 角色推断规则(启发式,基于常见中文/英文命名)
_ROLE_RULES = [
(["WALL", "", "W", "A-WALL", "A-WALL-"], "墙体"),
(["DOOR", "", "", "WINDOW", "D", "M"], "门窗"),
(["DIM", "标注", "DEFPOINTS", "PUB_DIM", "PUB_DIM"], "标注"),
(["TEXT", "文字", "NOTE"], "文字"),
(["COLUMN", "", "Z"], ""),
(["E", "EQUIP", "设备"], "设备"),
(["HATCH", "填充", "BH"], "填充"),
(["AXIS", "", "AXIS"], "轴网"),
(["GRID", "网格"], "网格"),
(["FURN", "家具", "FURNITURE"], "家具"),
(["BEAM", "", "B"], ""),
(["SLAB", ""], ""),
(["STAIR", "楼梯", "S"], "楼梯"),
(["ROOF", "屋顶", "R"], "屋顶"),
(["PIPE", "", "P"], "管道"),
(["DUCT", "风管"], "风管"),
(["ELEC", "电气", "E-"], "电气"),
(["PLUMB", "给排水", "P-"], "给排水"),
(["FOUND", "基础", "F"], "基础"),
(["SITE", "场地", "总图"], "场地"),
(["CEIL", "天花", "吊顶", "C"], "天花"),
(["FLOOR", "地面", "FL"], "地面"),
(["SECTION", "剖面", "SECT"], "剖面"),
(["ELEV", "立面", "ELEVATION"], "立面"),
(["0", "A-"], "主体结构"),
]
def _infer_role(layer_name: str) -> str:
"""根据图层名称推断图层角色(仅作建议)。"""
upper_name = layer_name.upper()
for keywords, role in _ROLE_RULES:
for kw in keywords:
if kw in upper_name or kw in layer_name:
return role
return "其他"
def analyze_layers(doc) -> list:
"""分析所有图层,返回每层的实体统计和角色推断。
Args:
doc: ezdxf Drawing 对象
Returns:
list[dict]: 每层信息,格式为 {
"name": str,
"entity_count": int,
"entity_types": list[str],
"suggested_role": str
}
"""
msp = doc.modelspace()
# 按图层聚合实体
layer_entities = {} # layer_name -> list of dxftype
for entity in msp:
layer_name = entity.dxf.layer
if layer_name not in layer_entities:
layer_entities[layer_name] = []
layer_entities[layer_name].append(entity.dxftype())
# 也包含没有实体的图层(在 doc.layers 中定义但模型空间无实体)
result = []
seen_layers = set()
for layer_name, types in layer_entities.items():
seen_layers.add(layer_name)
unique_types = sorted(set(types))
result.append({
"name": layer_name,
"entity_count": len(types),
"entity_types": unique_types,
"suggested_role": _infer_role(layer_name),
})
# 补充空图层(在图层定义中存在但无实体)
for layer in doc.layers:
name = layer.dxf.name
if name not in seen_layers:
result.append({
"name": name,
"entity_count": 0,
"entity_types": [],
"suggested_role": _infer_role(name),
})
# 按实体数降序排列
result.sort(key=lambda x: -x["entity_count"])
return result