← All skills
Tencent SkillHub · AI

Ifc Data Extraction

Extract structured data from IFC (Industry Foundation Classes) files using IfcOpenShell. Parse BIM models, extract quantities, properties, spatial relationships, and export to various formats.

skill openclawclawhub Free
0 Downloads
0 Stars
0 Installs
0 Score
High Signal

Extract structured data from IFC (Industry Foundation Classes) files using IfcOpenShell. Parse BIM models, extract quantities, properties, spatial relationships, and export to various formats.

⬇ 0 downloads ★ 0 stars Unverified but indexed

Install for OpenClaw

Quick setup
  1. Download the package from Yavira.
  2. Extract the archive and review SKILL.md first.
  3. Import or place the package into your OpenClaw setup.

Requirements

Target platform
OpenClaw
Install method
Manual import
Extraction
Extract archive
Prerequisites
OpenClaw
Primary doc
SKILL.md

Package facts

Download mode
Yavira redirect
Package format
ZIP package
Source platform
Tencent SkillHub
What's included
claw.json, instructions.md, SKILL.md

Validation

  • Use the Yavira download entry.
  • Review SKILL.md after the package is downloaded.
  • Confirm the extracted package contains the expected setup assets.

Install with your agent

Agent handoff

Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.

  1. Download the package from Yavira.
  2. Extract it into a folder your agent can access.
  3. Paste one of the prompts below and point your agent at the extracted folder.
New install

I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.

Upgrade existing

I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.

Trust & source

Release facts

Source
Tencent SkillHub
Verification
Indexed source record
Version
2.0.0

Documentation

ClawHub primary doc Primary doc: SKILL.md 9 sections Open source page

Overview

This skill provides comprehensive IFC file parsing and data extraction using IfcOpenShell. Extract element data, quantities, properties, and relationships from BIM models for analysis and reporting. Based on Open BIM Standards - Working with vendor-neutral IFC format for maximum interoperability. "IFC является открытым стандартом для обмена BIM-данными, позволяющим извлекать информацию независимо от программного обеспечения." — DDC Methodology

Quick Start

import ifcopenshell import ifcopenshell.util.element as element_util import pandas as pd # Open IFC file ifc = ifcopenshell.open("model.ifc") # Get project info project = ifc.by_type("IfcProject")[0] print(f"Project: {project.Name}") # Extract all walls walls = ifc.by_type("IfcWall") print(f"Total walls: {len(walls)}") # Get wall data wall_data = [] for wall in walls: psets = element_util.get_psets(wall) wall_data.append({ 'GlobalId': wall.GlobalId, 'Name': wall.Name, 'Type': wall.is_a(), 'Level': get_level(wall), 'Properties': psets }) df = pd.DataFrame(wall_data) print(df.head())

Element Extractor Class

import ifcopenshell import ifcopenshell.util.element as element_util import ifcopenshell.util.placement as placement_util import ifcopenshell.geom import pandas as pd from typing import List, Dict, Optional, Any class IFCExtractor: """Extract data from IFC files""" def __init__(self, ifc_path: str): self.model = ifcopenshell.open(ifc_path) self.settings = ifcopenshell.geom.settings() def get_project_info(self) -> Dict: """Extract project metadata""" project = self.model.by_type("IfcProject")[0] site = self.model.by_type("IfcSite") building = self.model.by_type("IfcBuilding") return { 'project_id': project.GlobalId, 'project_name': project.Name, 'description': project.Description, 'site_count': len(site), 'building_count': len(building), 'schema': self.model.schema } def get_all_elements(self, element_types: List[str] = None) -> pd.DataFrame: """Extract all elements of specified types""" if element_types is None: element_types = [ 'IfcWall', 'IfcSlab', 'IfcColumn', 'IfcBeam', 'IfcDoor', 'IfcWindow', 'IfcStair', 'IfcRoof' ] all_elements = [] for ifc_type in element_types: elements = self.model.by_type(ifc_type) for elem in elements: data = self._extract_element_data(elem) data['IFC_Type'] = ifc_type all_elements.append(data) return pd.DataFrame(all_elements) def _extract_element_data(self, element) -> Dict: """Extract data from single element""" # Basic info data = { 'GlobalId': element.GlobalId, 'Name': element.Name, 'Description': element.Description, 'ObjectType': element.ObjectType if hasattr(element, 'ObjectType') else None } # Get level/storey data['Level'] = self._get_element_level(element) # Get material data['Material'] = self._get_element_material(element) # Get type data['TypeName'] = self._get_element_type(element) # Get all property sets psets = element_util.get_psets(element) data['PropertySets'] = psets # Extract common quantities base_quantities = psets.get('BaseQuantities', {}) data.update({ 'Length': base_quantities.get('Length'), 'Width': base_quantities.get('Width'), 'Height': base_quantities.get('Height'), 'Area': base_quantities.get('NetSideArea') or base_quantities.get('GrossArea'), 'Volume': base_quantities.get('NetVolume') or base_quantities.get('GrossVolume') }) return data def _get_element_level(self, element) -> Optional[str]: """Get the building storey for an element""" if hasattr(element, 'ContainedInStructure'): for rel in element.ContainedInStructure or []: if rel.RelatingStructure.is_a('IfcBuildingStorey'): return rel.RelatingStructure.Name return None def _get_element_material(self, element) -> Optional[str]: """Get material name for element""" if hasattr(element, 'HasAssociations'): for rel in element.HasAssociations or []: if rel.is_a('IfcRelAssociatesMaterial'): material = rel.RelatingMaterial if hasattr(material, 'Name'): return material.Name elif hasattr(material, 'ForLayerSet'): layers = material.ForLayerSet.MaterialLayers if layers: return layers[0].Material.Name return None def _get_element_type(self, element) -> Optional[str]: """Get element type name""" if hasattr(element, 'IsTypedBy'): for rel in element.IsTypedBy or []: return rel.RelatingType.Name return None def extract_quantities(self) -> pd.DataFrame: """Extract quantities for all elements""" elements = self.get_all_elements() # Group by category and level quantities = elements.groupby(['IFC_Type', 'Level']).agg({ 'GlobalId': 'count', 'Volume': 'sum', 'Area': 'sum', 'Length': 'sum' }).rename(columns={'GlobalId': 'Count'}).reset_index() return quantities def extract_levels(self) -> pd.DataFrame: """Extract building levels/storeys""" storeys = self.model.by_type("IfcBuildingStorey") level_data = [] for storey in storeys: level_data.append({ 'GlobalId': storey.GlobalId, 'Name': storey.Name, 'Elevation': storey.Elevation, 'Description': storey.Description }) return pd.DataFrame(level_data).sort_values('Elevation') def extract_spaces(self) -> pd.DataFrame: """Extract spaces/rooms""" spaces = self.model.by_type("IfcSpace") space_data = [] for space in spaces: psets = element_util.get_psets(space) base_qty = psets.get('BaseQuantities', {}) space_data.append({ 'GlobalId': space.GlobalId, 'Name': space.Name, 'LongName': space.LongName, 'Level': self._get_element_level(space), 'Area': base_qty.get('NetFloorArea'), 'Volume': base_qty.get('NetVolume'), 'Height': base_qty.get('Height') }) return pd.DataFrame(space_data) def extract_materials(self) -> pd.DataFrame: """Extract material summary""" materials = {} for elem in self.model.by_type("IfcProduct"): material = self._get_element_material(elem) if material: if material not in materials: materials[material] = {'count': 0, 'volume': 0} materials[material]['count'] += 1 psets = element_util.get_psets(elem) volume = psets.get('BaseQuantities', {}).get('NetVolume', 0) if volume: materials[material]['volume'] += volume return pd.DataFrame.from_dict(materials, orient='index').reset_index() def extract_relationships(self) -> pd.DataFrame: """Extract element relationships""" relationships = [] # Spatial containment for rel in self.model.by_type("IfcRelContainedInSpatialStructure"): for elem in rel.RelatedElements: relationships.append({ 'Element': elem.GlobalId, 'Element_Type': elem.is_a(), 'Relationship': 'ContainedIn', 'Related_To': rel.RelatingStructure.GlobalId, 'Related_Type': rel.RelatingStructure.is_a() }) # Aggregation for rel in self.model.by_type("IfcRelAggregates"): for part in rel.RelatedObjects: relationships.append({ 'Element': part.GlobalId, 'Element_Type': part.is_a(), 'Relationship': 'PartOf', 'Related_To': rel.RelatingObject.GlobalId, 'Related_Type': rel.RelatingObject.is_a() }) return pd.DataFrame(relationships)

Extract Geometry Data

import numpy as np class IFCGeometryExtractor: """Extract geometry data from IFC elements""" def __init__(self, ifc_path: str): self.model = ifcopenshell.open(ifc_path) self.settings = ifcopenshell.geom.settings() self.settings.set(self.settings.USE_WORLD_COORDS, True) def get_element_geometry(self, element) -> Dict: """Extract geometry for single element""" try: shape = ifcopenshell.geom.create_shape(self.settings, element) verts = shape.geometry.verts faces = shape.geometry.faces # Calculate bounding box vertices = np.array(verts).reshape(-1, 3) min_coords = vertices.min(axis=0) max_coords = vertices.max(axis=0) dimensions = max_coords - min_coords return { 'GlobalId': element.GlobalId, 'vertices_count': len(vertices), 'faces_count': len(faces) // 3, 'min_x': min_coords[0], 'min_y': min_coords[1], 'min_z': min_coords[2], 'max_x': max_coords[0], 'max_y': max_coords[1], 'max_z': max_coords[2], 'length': dimensions[0], 'width': dimensions[1], 'height': dimensions[2], 'center_x': (min_coords[0] + max_coords[0]) / 2, 'center_y': (min_coords[1] + max_coords[1]) / 2, 'center_z': (min_coords[2] + max_coords[2]) / 2 } except: return {'GlobalId': element.GlobalId, 'error': 'Geometry extraction failed'} def get_bounding_boxes(self, element_type: str) -> pd.DataFrame: """Get bounding boxes for all elements of type""" elements = self.model.by_type(element_type) boxes = [self.get_element_geometry(e) for e in elements] return pd.DataFrame(boxes) def calculate_volumes(self, element_type: str) -> pd.DataFrame: """Calculate volumes using geometry""" elements = self.model.by_type(element_type) volumes = [] for elem in elements: try: shape = ifcopenshell.geom.create_shape(self.settings, elem) # Calculate volume from mesh (simplified) verts = np.array(shape.geometry.verts).reshape(-1, 3) bbox_volume = np.prod(verts.max(axis=0) - verts.min(axis=0)) volumes.append({ 'GlobalId': elem.GlobalId, 'Name': elem.Name, 'BBox_Volume': bbox_volume }) except: pass return pd.DataFrame(volumes)

Export to Various Formats

class IFCExporter: """Export IFC data to various formats""" def __init__(self, extractor: IFCExtractor): self.extractor = extractor def to_excel(self, output_path: str, include_all: bool = True): """Export to Excel with multiple sheets""" with pd.ExcelWriter(output_path, engine='openpyxl') as writer: # Project info project_info = pd.DataFrame([self.extractor.get_project_info()]) project_info.to_excel(writer, sheet_name='Project', index=False) # All elements if include_all: elements = self.extractor.get_all_elements() elements.to_excel(writer, sheet_name='Elements', index=False) # Quantities quantities = self.extractor.extract_quantities() quantities.to_excel(writer, sheet_name='Quantities', index=False) # Levels levels = self.extractor.extract_levels() levels.to_excel(writer, sheet_name='Levels', index=False) # Spaces spaces = self.extractor.extract_spaces() spaces.to_excel(writer, sheet_name='Spaces', index=False) # Materials materials = self.extractor.extract_materials() materials.to_excel(writer, sheet_name='Materials', index=False) return output_path def to_csv(self, output_dir: str): """Export to multiple CSV files""" import os os.makedirs(output_dir, exist_ok=True) exports = { 'elements.csv': self.extractor.get_all_elements(), 'quantities.csv': self.extractor.extract_quantities(), 'levels.csv': self.extractor.extract_levels(), 'spaces.csv': self.extractor.extract_spaces(), 'materials.csv': self.extractor.extract_materials() } for filename, df in exports.items(): df.to_csv(os.path.join(output_dir, filename), index=False) return output_dir def to_json(self, output_path: str): """Export to JSON""" import json data = { 'project': self.extractor.get_project_info(), 'elements': self.extractor.get_all_elements().to_dict('records'), 'quantities': self.extractor.extract_quantities().to_dict('records'), 'levels': self.extractor.extract_levels().to_dict('records'), 'materials': self.extractor.extract_materials().to_dict('records') } with open(output_path, 'w', encoding='utf-8') as f: json.dump(data, f, indent=2, default=str) return output_path def to_database(self, connection_string: str, table_prefix: str = 'ifc_'): """Export to SQL database""" from sqlalchemy import create_engine engine = create_engine(connection_string) tables = { f'{table_prefix}elements': self.extractor.get_all_elements(), f'{table_prefix}quantities': self.extractor.extract_quantities(), f'{table_prefix}levels': self.extractor.extract_levels(), f'{table_prefix}spaces': self.extractor.extract_spaces(), f'{table_prefix}materials': self.extractor.extract_materials() } for table_name, df in tables.items(): # Remove complex columns for database storage simple_df = df.select_dtypes(exclude=['object']).copy() for col in df.columns: if df[col].dtype == 'object': simple_df[col] = df[col].astype(str) simple_df.to_sql(table_name, engine, if_exists='replace', index=False) return list(tables.keys())

Quick Reference

Element TypeCommon PropertiesQuantitiesIfcWallIsExternal, FireRatingLength, Height, Area, VolumeIfcSlabIsExternal, LoadBearingArea, Volume, PerimeterIfcColumnLoadBearingHeight, CrossSectionAreaIfcBeamLoadBearingLength, CrossSectionAreaIfcDoorFireRating, AcousticRatingWidth, HeightIfcWindowThermalTransmittanceWidth, Height, Area

Property Set Lookup

# Common IFC Property Sets PSETS = { 'Pset_WallCommon': ['IsExternal', 'LoadBearing', 'FireRating'], 'Pset_SlabCommon': ['IsExternal', 'LoadBearing', 'AcousticRating'], 'Pset_ColumnCommon': ['IsExternal', 'LoadBearing'], 'Pset_BeamCommon': ['LoadBearing', 'FireRating'], 'Pset_DoorCommon': ['FireRating', 'AcousticRating', 'SecurityRating'], 'Pset_WindowCommon': ['ThermalTransmittance', 'GlazingType'], 'BaseQuantities': ['Length', 'Width', 'Height', 'Area', 'Volume'] }

Resources

IfcOpenShell: https://ifcopenshell.org IFC Standard: https://www.buildingsmart.org/standards/bsi-standards/industry-foundation-classes/ DDC Website: https://datadrivenconstruction.io

Next Steps

See bim-validation-pipeline for validating extracted data See qto-report for quantity take-off reports See 4d-simulation for linking to schedules

Category context

Agent frameworks, memory systems, reasoning layers, and model-native orchestration.

Source: Tencent SkillHub

Largest current source with strong distribution and engagement signals.

Package contents

Included in package
2 Docs1 Config
  • SKILL.md Primary doc
  • instructions.md Docs
  • claw.json Config