数据生成
- 作者仓库星标 155
- 作者更新于 实时读取
- 作者仓库 DDC_Skills_for_AI_Agents_in_Construction
- 领域
- 数据
- 兼容 Agent
-
- Claude Code
- Cursor
- Cline
- Codex
- Windsurf
- Gemini CLI
- +20
- 信任分
- 88 / 100 · 社区维护
- 作者 / 版本 / 许可
- @datadrivenconstruction · 未声明 license
- Token 消耗评级
- 中等消耗
- 接入复杂程度
- 需简单配置
- 是否需要外部 API Key
- 不需要
- 兼容的系统
- Windows
- 底层运行要求
- Python
- 文件与系统权限
-
- 只读
- 允许写入 / 修改
- Shell 执行
- 网络行为
- 仅限本地
- 安装命令数
- 26 条
档案由构建时根据 SKILL.md 与安装命令自动衍生,可能与作者实际意图存在差异。
需要注意: 未限定 allowed-tools,默认拥有全部工具权限。
---
name: cad-to-data
description: Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files.…
category: 数据
runtime: Python
---
# cad-to-data 输出预览
## PART A: 任务判断
- 适用问题:表格、CSV、数据集、指标或分析流程。
- 输入要求:目标材料、限制条件、期望输出和验收方式。
- 证据边界:围绕“Overview / Quick Start / Elements by Category”读取原文规则,不把推断写成作者承诺。
## PART B: 执行结果
- **01** 任务判断:确认你的需求是否属于表格、CSV、数据集、指标或分析流程,并标出输入、限制和预期结果。
- **02** 执行计划:优先按“Overview / Quick Start / Elements by Category”拆成步骤,说明每一步会读取什么、修改什么、产出什么。
- **03** 交付结果:给出可复制的命令、文件改动、检查清单或内容草稿,并说明如何继续迭代。
- **04** 风险边界:结合 读取文件、写入/修改文件、执行终端命令、主要在本地完成、通常不需要额外 API Key 给出执行前确认项。
## Running Rules
- 读取文件、写入/修改文件、执行终端命令;主要在本地完成;通常不需要额外 API Key。
- 先小样例验证,再放大到真实任务。
- 交付时同时给结果、检查口径和下一步迭代建议。 先确认触发方式
原文没有稳定的斜杠命令要求。安装验证后通常全局生效,直接在对话里点名这个 Skill 并描述任务即可。
给清楚输入和边界
告诉 Agent 目标文件或材料、期望结果、不可改范围、是否允许联网或执行命令。本 Skill 的权限画像是:读取文件、写入/修改文件、执行终端命令。
小样例验证后再放大
先用一个小任务确认它会围绕“Overview / Quick Start / Elements by Category”工作;涉及文件或命令时,先看 diff、日志、预览或测试结果。
复核后再交付
检查最终产物是否包含明确结果、必要证据和下一步动作;如果输出泛泛而谈,就补充输入、边界和验收标准后重跑。
---
name: cad-to-data
description: Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files.…
category: 数据
source: datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction
---
# cad-to-data
## 什么时候使用
- cad-to-data 是数据方向的技能,让 Agent 处理结构化文件(Excel / CSV / 表格) 适合处理表格、CSV、指标、数据集、分析和可视化报告,核心价值是把输入、判断、执行、验证和交付边界固定下来,避免 Agent…
- 面向表格、CSV、数据集、指标或分析流程,优先处理能明确输入、步骤和验收标准的工作。
## 需要提供什么
- 目标材料、目录范围、期望结果和不可改动内容。
- 是否允许联网、执行命令、读写文件或调用外部服务。
## 执行规则
- 围绕「Overview / Quick Start / Elements by Category」组织步骤,不把推断写成作者事实。
- 读取文件、写入/修改文件、执行终端命令;主要在本地完成;通常不需要额外 API Key。
- 先跑小样例,确认结果可检查后再扩大任务范围。
## 输出要求
- 给出最终产物、关键证据、验证方式和下一步动作。
- 信息不足时标记 unknown,不编造命令、平台或依赖。 证据边界与执行链路
作者原文负责流程事实;仓库文件负责来源和命令;流狐只补充适用场景、限制和质量判断。
skill "cad-to-data" {
输入层 -> 用户目标 + 目标文件 + 禁止范围 + 验收标准
上下文层 -> Overview / Quick Start / Elements by Category
规则层 -> SKILL.md 触发条件 / 执行顺序 / 输出格式
运行层 -> Python | 读取文件、写入/修改文件、执行终端命令 | 主要在本地完成
安全层 -> 通常不需要额外 API Key + 小任务验证 + diff / 日志复核
输出层 -> 可复制结果 + 检查清单 + 下一步迭代
} CAD To Data
Overview
Based on DDC methodology (Chapter 2.4), this skill converts CAD and BIM files to structured data, extracting element properties, quantities, and relationships from Revit, IFC, DWG, and DGN files.
Book Reference: "Преобразование данных в структурированную форму" / "Data Transformation to Structured Form"
Quick Start
from dataclasses import dataclass, field
from enum import Enum
from typing import List, Dict, Optional, Any, Tuple, Generator
from datetime import datetime
import json
class CADFormat(Enum):
"""Supported CAD/BIM formats"""
IFC = "ifc"
RVT = "rvt"
DWG = "dwg"
DXF = "dxf"
DGN = "dgn"
NWD = "nwd"
STEP = "step"
class ElementCategory(Enum):
"""BIM element categories"""
WALL = "wall"
FLOOR = "floor"
ROOF = "roof"
CEILING = "ceiling"
DOOR = "door"
WINDOW = "window"
COLUMN = "column"
BEAM = "beam"
STAIR = "stair"
RAMP = "ramp"
FURNITURE = "furniture"
EQUIPMENT = "equipment"
PIPE = "pipe"
DUCT = "duct"
CABLE_TRAY = "cable_tray"
SPACE = "space"
GENERIC = "generic"
@dataclass
class Point3D:
"""3D point"""
x: float
y: float
z: float
@dataclass
class BoundingBox3D:
"""3D bounding box"""
min_point: Point3D
max_point: Point3D
@property
def width(self) -> float:
return abs(self.max_point.x - self.min_point.x)
@property
def depth(self) -> float:
return abs(self.max_point.y - self.min_point.y)
@property
def height(self) -> float:
return abs(self.max_point.z - self.min_point.z)
@property
def volume(self) -> float:
return self.width * self.depth * self.height
@dataclass
class MaterialInfo:
"""Material information"""
name: str
category: str
color: Optional[str] = None
area: float = 0.0
volume: float = 0.0
properties: Dict[str, Any] = field(default_factory=dict)
@dataclass
class CADElement:
"""Extracted CAD/BIM element"""
id: str
guid: str
name: str
category: ElementCategory
type_name: str
level: Optional[str] = None
bounding_box: Optional[BoundingBox3D] = None
properties: Dict[str, Any] = field(default_factory=dict)
quantities: Dict[str, float] = field(default_factory=dict)
materials: List[MaterialInfo] = field(default_factory=list)
relationships: Dict[str, List[str]] = field(default_factory=dict)
@dataclass
class CADLayer:
"""CAD layer information"""
name: str
color: Optional[str] = None
line_type: Optional[str] = None
visible: bool = True
element_count: int = 0
@dataclass
class CADExtractionResult:
"""Result of CAD extraction"""
file_path: str
file_format: CADFormat
elements: List[CADElement]
layers: List[CADLayer]
levels: List[str]
total_elements: int
categories: Dict[str, int]
extraction_time: float
metadata: Dict[str, Any] = field(default_factory=dict)
class IFCExtractor:
"""Extract data from IFC files"""
def __init__(self):
self.schema_version = "IFC4"
self.element_mapping = self._build_element_mapping()
def _build_element_mapping(self) -> Dict[str, ElementCategory]:
"""Map IFC types to categories"""
return {
"IfcWall": ElementCategory.WALL,
"IfcWallStandardCase": ElementCategory.WALL,
"IfcSlab": ElementCategory.FLOOR,
"IfcRoof": ElementCategory.ROOF,
"IfcCeiling": ElementCategory.CEILING,
"IfcDoor": ElementCategory.DOOR,
"IfcWindow": ElementCategory.WINDOW,
"IfcColumn": ElementCategory.COLUMN,
"IfcBeam": ElementCategory.BEAM,
"IfcStair": ElementCategory.STAIR,
"IfcRamp": ElementCategory.RAMP,
"IfcFurnishingElement": ElementCategory.FURNITURE,
"IfcPipeSegment": ElementCategory.PIPE,
"IfcDuctSegment": ElementCategory.DUCT,
"IfcCableCarrierSegment": ElementCategory.CABLE_TRAY,
"IfcSpace": ElementCategory.SPACE,
}
def extract(
self,
file_path: str,
categories: Optional[List[ElementCategory]] = None
) -> CADExtractionResult:
"""
Extract data from IFC file.
Args:
file_path: Path to IFC file
categories: Optional filter for categories
Returns:
Extraction result
"""
start_time = datetime.now()
# In production, use ifcopenshell:
# import ifcopenshell
# ifc_file = ifcopenshell.open(file_path)
# Simulated extraction
elements = self._simulate_ifc_elements()
# Filter by category if specified
if categories:
elements = [e for e in elements if e.category in categories]
# Build category counts
category_counts = {}
for element in elements:
cat = element.category.value
category_counts[cat] = category_counts.get(cat, 0) + 1
# Extract levels
levels = list(set(e.level for e in elements if e.level))
extraction_time = (datetime.now() - start_time).total_seconds()
return CADExtractionResult(
file_path=file_path,
file_format=CADFormat.IFC,
elements=elements,
layers=[], # IFC doesn't use layers in traditional sense
levels=levels,
total_elements=len(elements),
categories=category_counts,
extraction_time=extraction_time,
metadata={
"schema": self.schema_version,
"project_name": "Sample Project"
}
)
def _simulate_ifc_elements(self) -> List[CADElement]:
"""Simulate IFC element extraction"""
elements = []
# Sample walls
for i in range(10):
elements.append(CADElement(
id=f"wall_{i}",
guid=f"1234567890ABCDEF{i:04d}",
name=f"Basic Wall {i}",
category=ElementCategory.WALL,
type_name="Basic Wall:200mm Concrete",
level="Level 1",
bounding_box=BoundingBox3D(
min_point=Point3D(i * 5, 0, 0),
max_point=Point3D(i * 5 + 5, 0.2, 3)
),
properties={
"IsExternal": True,
"FireRating": "1 HR",
"LoadBearing": True
},
quantities={
"Length": 5.0,
"Height": 3.0,
"Width": 0.2,
"Area": 15.0,
"Volume": 3.0
},
materials=[
MaterialInfo(
name="Concrete",
category="Concrete",
area=15.0,
volume=3.0
)
]
))
# Sample doors
for i in range(5):
elements.append(CADElement(
id=f"door_{i}",
guid=f"DOOR0000000000{i:04d}",
name=f"Single Door {i}",
category=ElementCategory.DOOR,
type_name="Single Flush:900x2100",
level="Level 1",
properties={
"FireRating": "None",
"IsExternal": False
},
quantities={
"Width": 0.9,
"Height": 2.1,
"Area": 1.89
},
relationships={
"host_wall": [f"wall_{i}"]
}
))
# Sample spaces
for i in range(3):
elements.append(CADElement(
id=f"space_{i}",
guid=f"SPACE000000000{i:04d}",
name=f"Room {i+101}",
category=ElementCategory.SPACE,
type_name="Office",
level="Level 1",
quantities={
"Area": 25.0 + i * 5,
"Volume": 75.0 + i * 15,
"Perimeter": 20.0 + i * 2
},
properties={
"OccupancyType": "Office",
"DesignOccupancy": 4
}
))
return elements
def get_quantities(
self,
elements: List[CADElement],
quantity_type: str = "all"
) -> Dict[str, float]:
"""Aggregate quantities from elements"""
totals = {}
for element in elements:
for qty_name, qty_value in element.quantities.items():
if quantity_type == "all" or qty_name.lower() == quantity_type.lower():
key = f"{element.category.value}_{qty_name}"
totals[key] = totals.get(key, 0) + qty_value
return totals
class DWGExtractor:
"""Extract data from DWG/DXF files"""
def __init__(self):
self.supported_entities = ["LINE", "POLYLINE", "CIRCLE", "ARC", "TEXT", "MTEXT", "INSERT", "HATCH"]
def extract(
self,
file_path: str,
layers: Optional[List[str]] = None
) -> CADExtractionResult:
"""Extract data from DWG file"""
start_time = datetime.now()
# In production, use ezdxf:
# import ezdxf
# doc = ezdxf.readfile(file_path)
# Simulated extraction
elements, cad_layers = self._simulate_dwg_extraction()
# Filter by layers if specified
if layers:
elements = [e for e in elements if e.properties.get("layer") in layers]
extraction_time = (datetime.now() - start_time).total_seconds()
return CADExtractionResult(
file_path=file_path,
file_format=CADFormat.DWG,
elements=elements,
layers=cad_layers,
levels=[],
total_elements=len(elements),
categories={"generic": len(elements)},
extraction_time=extraction_time,
metadata={"units": "millimeters"}
)
def _simulate_dwg_extraction(self) -> Tuple[List[CADElement], List[CADLayer]]:
"""Simulate DWG extraction"""
elements = []
layers = [
CADLayer("Walls", "Red", "Continuous", True, 15),
CADLayer("Doors", "Blue", "Continuous", True, 8),
CADLayer("Windows", "Cyan", "Continuous", True, 12),
CADLayer("Dimensions", "Green", "Continuous", True, 50),
CADLayer("Text", "White", "Continuous", True, 25),
]
# Simulate polylines (walls)
for i in range(15):
elements.append(CADElement(
id=f"polyline_{i}",
guid=f"PL{i:08d}",
name=f"Polyline {i}",
category=ElementCategory.GENERIC,
type_name="POLYLINE",
properties={
"layer": "Walls",
"color": "Red",
"closed": True
},
quantities={
"Length": 10.5 + i * 0.5
}
))
return elements, layers
class CADDataConverter:
"""
Convert CAD/BIM files to structured data.
Based on DDC methodology Chapter 2.4.
"""
def __init__(self):
self.ifc_extractor = IFCExtractor()
self.dwg_extractor = DWGExtractor()
def convert(
self,
file_path: str,
output_format: str = "json"
) -> Dict[str, Any]:
"""
Convert CAD file to structured data.
Args:
file_path: Path to CAD file
output_format: Output format (json, csv, dataframe)
Returns:
Structured data
"""
# Detect file format
file_format = self._detect_format(file_path)
# Extract based on format
if file_format == CADFormat.IFC:
result = self.ifc_extractor.extract(file_path)
elif file_format in [CADFormat.DWG, CADFormat.DXF]:
result = self.dwg_extractor.extract(file_path)
else:
raise ValueError(f"Unsupported format: {file_format}")
# Convert to output format
return self._format_output(result, output_format)
def _detect_format(self, file_path: str) -> CADFormat:
"""Detect CAD file format"""
extension = file_path.lower().split(".")[-1]
format_map = {
"ifc": CADFormat.IFC,
"rvt": CADFormat.RVT,
"dwg": CADFormat.DWG,
"dxf": CADFormat.DXF,
"dgn": CADFormat.DGN,
"nwd": CADFormat.NWD,
}
return format_map.get(extension, CADFormat.IFC)
def _format_output(
self,
result: CADExtractionResult,
format: str
) -> Dict[str, Any]:
"""Format extraction result"""
output = {
"file": result.file_path,
"format": result.file_format.value,
"total_elements": result.total_elements,
"categories": result.categories,
"levels": result.levels,
"extraction_time": result.extraction_time,
"elements": []
}
for element in result.elements:
output["elements"].append({
"id": element.id,
"guid": element.guid,
"name": element.name,
"category": element.category.value,
"type": element.type_name,
"level": element.level,
"properties": element.properties,
"quantities": element.quantities,
"materials": [
{"name": m.name, "area": m.area, "volume": m.volume}
for m in element.materials
]
})
return output
def extract_quantities(
self,
file_path: str,
categories: Optional[List[ElementCategory]] = None
) -> Dict[str, Any]:
"""Extract quantity takeoff from CAD file"""
file_format = self._detect_format(file_path)
if file_format == CADFormat.IFC:
result = self.ifc_extractor.extract(file_path, categories)
else:
result = self.dwg_extractor.extract(file_path)
# Aggregate quantities by category
quantities = {}
for element in result.elements:
cat = element.category.value
if cat not in quantities:
quantities[cat] = {
"count": 0,
"totals": {}
}
quantities[cat]["count"] += 1
for qty_name, qty_value in element.quantities.items():
if qty_name not in quantities[cat]["totals"]:
quantities[cat]["totals"][qty_name] = 0
quantities[cat]["totals"][qty_name] += qty_value
return {
"file": file_path,
"quantities": quantities,
"summary": {
"total_elements": result.total_elements,
"categories": list(quantities.keys())
}
}
def extract_schedule(
self,
file_path: str,
category: ElementCategory,
fields: List[str]
) -> List[Dict]:
"""Extract schedule data for specific category"""
file_format = self._detect_format(file_path)
if file_format == CADFormat.IFC:
result = self.ifc_extractor.extract(file_path, [category])
else:
result = self.dwg_extractor.extract(file_path)
schedule = []
for element in result.elements:
if element.category == category:
row = {"id": element.id, "name": element.name, "type": element.type_name}
for field in fields:
if field in element.properties:
row[field] = element.properties[field]
elif field in element.quantities:
row[field] = element.quantities[field]
schedule.append(row)
return schedule
def export_to_json(
self,
result: CADExtractionResult,
output_path: str
):
"""Export extraction result to JSON file"""
output = self._format_output(result, "json")
with open(output_path, 'w') as f:
json.dump(output, f, indent=2)
def generate_report(self, result: CADExtractionResult) -> str:
"""Generate extraction report"""
report = f"""
# CAD Extraction Report
**File:** {result.file_path}
**Format:** {result.file_format.value}
**Total Elements:** {result.total_elements}
**Extraction Time:** {result.extraction_time:.2f}s
## Elements by Category
"""
for cat, count in result.categories.items():
report += f"- **{cat.title()}:** {count}\n"
if result.levels:
report += "\n## Levels\n"
for level in result.levels:
report += f"- {level}\n"
if result.layers:
report += "\n## Layers\n"
for layer in result.layers:
report += f"- {layer.name}: {layer.element_count} elements\n"
return report
Common Use Cases
Extract IFC Data
converter = CADDataConverter()
# Convert IFC to structured data
data = converter.convert("building.ifc", output_format="json")
print(f"Total elements: {data['total_elements']}")
print(f"Categories: {data['categories']}")
# Access elements
for element in data['elements'][:5]:
print(f" {element['name']}: {element['type']}")
Extract Quantities
quantities = converter.extract_quantities(
"building.ifc",
categories=[ElementCategory.WALL, ElementCategory.FLOOR]
)
print(f"Wall count: {quantities['quantities']['wall']['count']}")
print(f"Total wall area: {quantities['quantities']['wall']['totals']['Area']}")
Generate Schedule
door_schedule = converter.extract_schedule(
"building.ifc",
category=ElementCategory.DOOR,
fields=["Width", "Height", "FireRating", "IsExternal"]
)
for door in door_schedule:
print(f"{door['name']}: {door.get('Width')}x{door.get('Height')}")
Generate Report
ifc_extractor = IFCExtractor()
result = ifc_extractor.extract("building.ifc")
report = converter.generate_report(result)
print(report)
Quick Reference
| Component | Purpose |
|---|---|
CADDataConverter |
Main conversion engine |
IFCExtractor |
IFC file extraction |
DWGExtractor |
DWG/DXF extraction |
CADElement |
Extracted element data |
CADExtractionResult |
Complete extraction result |
ElementCategory |
BIM element categories |
Resources
- Book: "Data-Driven Construction" by Artem Boiko, Chapter 2.4
- Website: https://datadrivenconstruction.io
Next Steps
- Use image-to-data for image extraction
- Use qto-report for quantity reports
- Use bim-validation-pipeline for validation
先判断是否适合
作者设计意图
作者的方法与取舍
边界和复核