Skill 详情
bim-qto
Generates BIM quantity takeoffs for construction cost estimation.
使用前先检查
自动化审核只检查相关性,不代表安全审查或推荐。使用前请阅读来源中的说明。
SKILL.md
这段内容是审核时保存的快照。外部来源才是完整且最新的版本。
---
name: "bim-qto"
description: "Extract quantities from BIM/CAD data for cost estimation. Group by type, level, zone. Generate QTO reports."
homepage: "https://datadrivenconstruction.io"
metadata: {"openclaw": {"emoji": "⚡", "os": ["win32"], "homepage": "https://datadrivenconstruction.io", "requires": {"bins": ["python3"]}}}
---
# BIM Quantity Takeoff
## Overview
Quantity Takeoff (QTO) extracts measurable quantities from BIM models. This skill processes BIM exports to generate grouped quantity reports for cost estimation.
## Python Implementation
```python
import pandas as pd
import numpy as np
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass, field
from enum import Enum
class QTOUnit(Enum):
"""Quantity takeoff measurement units."""
COUNT = "ea"
LENGTH = "m"
AREA = "m2"
VOLUME = "m3"
WEIGHT = "kg"
LINEAR_FOOT = "lf"
SQUARE_FOOT = "sf"
CUBIC_YARD = "cy"
@dataclass
class QTOItem:
"""Single QTO line item."""
category: str
type_name: str
description: str
quantity: float
unit: str
level: Optional[str] = None
material: Optional[str] = None
element_count: int = 0
@dataclass
class QTOReport:
"""Complete QTO report."""
project_name: str
items: List[QTOItem]
total_elements: int
categories: int
generated_date: str
class BIMQuantityTakeoff:
"""Extract quantities from BIM data."""
# Column mappings for different BIM exports
COLUMN_MAPPINGS = {
'type': ['Type Name', 'TypeName', 'type_name', 'Family and Type', 'IfcType'],
'category': ['Category', 'category', 'IfcClass', 'Element Category'],
'level': ['Level', 'level', 'Building Storey', 'BuildingStorey', 'Floor'],
'volume': ['Volume', 'volume', 'Volume (m³)', 'Qty_Volume'],
'area': ['Area', 'area', 'Surface Area', 'Area (m²)', 'Qty_Area'],
'length': ['Length', 'length', 'Length (m)', 'Qty_Length'],
'count': ['Count', 'count', 'Quantity', 'ElementCount'],
'material': ['Material', 'material', 'Structural Material', 'MaterialName']
}
def __init__(self, df: pd.DataFrame):
"""Initialize with BIM data DataFrame."""
self.df = df
self.column_map = self._detect_columns()
def _detect_columns(self) -> Dict[str, str]:
"""Detect which columns exist in data."""
mapping = {}
for standard, variants in self.COLUMN_MAPPINGS.items():
for variant in variants:
if variant in self.df.columns:
mapping[standard] = variant
break
return mapping
def get_column(self, standard_name: str) -> Optional[str]:
"""Get actual column name from standard name."""
return self.column_map.get(standard_name)
def group_by_type(self, sum_column: str = 'volume') -> pd.DataFrame:
"""Group quantities by type name."""
type_col = self.get_column('type')
qty_col = self.get_column(sum_column)
if type_col is None:
raise ValueError("Type column not found")
if qty_col is None:
# Fall back to count
result = self.df.groupby(type_col).size().reset_index(name='count')
else:
result = self.df.groupby(type_col).agg({
qty_col: 'sum'
}).reset_index()
result['count'] = self.df.groupby(type_col).size().values
result.columns = ['Type', 'Quantity', 'Count'] if len(result.columns) == 3 else ['Type', 'Count']
return result.sort_values('Count', ascending=False)
def group_by_category(self, sum_column: str = 'volume') -> pd.DataFrame:
"""Group quantities by category."""
cat_col = self.get_column('category')
qty_col = self.get_column(sum_column)
if cat_col is None:
raise ValueError("Category column not found")
agg_dict = {}
if qty_col:
agg_dict[qty_col在 GitHub 阅读完整来源 (打开外部页面)