Skill detail

clash-detection-analysis

Narrow BIM geometric-clash analysis.

MatchPossibleReviewed for data analysis
Sourcedatadrivenconstruction/ddc_skills_for_ai_agents_in_constructionExternal source
Reported installs73Popularity signal only

Inspect before use

Automated review checks relevance, not safety or endorsement. Read the source instructions before using this skill.

Saved source preview

SKILL.md

The saved excerpt is a snapshot from review. The external source remains the complete and most current version.

---
name: "clash-detection-analysis"
description: "Detect and analyze geometric clashes between BIM elements. Identify hard clashes, soft clashes, and workflow conflicts using spatial analysis and rule-based detection."
homepage: "https://datadrivenconstruction.io"
metadata: {"openclaw": {"emoji": "🚀", "os": ["darwin", "linux", "win32"], "homepage": "https://datadrivenconstruction.io", "requires": {"bins": ["python3"], "anyBins": ["ifcopenshell"]}}}
---
# Clash Detection Analysis

## Overview

This skill implements automated clash detection for BIM models. Identify conflicts between building elements before construction to prevent costly rework and delays.

**Types of Clashes:**
- **Hard Clash**: Physical intersection of elements
- **Soft Clash**: Clearance/tolerance violations
- **Workflow Clash**: Scheduling/sequencing conflicts

> "Обнаружение коллизий на этапе проектирования может сократить затраты на исправление ошибок до 10 раз по сравнению с исправлением на стройплощадке."

## Quick Start

```python
import ifcopenshell
import ifcopenshell.geom
import numpy as np
from itertools import combinations

# Open model
ifc = ifcopenshell.open("model.ifc")

# Get structural and MEP elements
structural = ifc.by_type("IfcColumn") + ifc.by_type("IfcBeam")
mep = ifc.by_type("IfcPipeSegment") + ifc.by_type("IfcDuctSegment")

# Simple bounding box clash check
settings = ifcopenshell.geom.settings()

def get_bbox(element):
    try:
        shape = ifcopenshell.geom.create_shape(settings, element)
        verts = np.array(shape.geometry.verts).reshape(-1, 3)
        return verts.min(axis=0), verts.max(axis=0)
    except:
        return None, None

def check_bbox_clash(bbox1, bbox2):
    min1, max1 = bbox1
    min2, max2 = bbox2
    if min1 is None or min2 is None:
        return False
    return np.all(max1 >= min2) and np.all(max2 >= min1)

# Find clashes
clashes = []
for s_elem in structural:
    for m_elem in mep:
        bbox1 = get_bbox(s_elem)
        bbox2 = get_bbox(m_elem)
        if check_bbox_clash(bbox1, bbox2):
            clashes.append({
                'element1': s_elem.GlobalId,
                'element2': m_elem.GlobalId,
                'type': 'Structure-MEP'
            })

print(f"Found {len(clashes)} potential clashes")
```

## Clash Detection Engine

### Core Detector Class

```python
import ifcopenshell
import ifcopenshell.geom
import numpy as np
import pandas as pd
from dataclasses import dataclass
from typing import List, Dict, Optional, Tuple
from itertools import combinations
from scipy.spatial import cKDTree

@dataclass
class Clash:
    element1_id: str
    element1_type: str
    element1_name: str
    element2_id: str
    element2_type: str
    element2_name: str
    clash_type: str
    distance: float
    location: Tuple[float, float, float]
    severity: str

class ClashDetector:
    """Detect clashes between BIM 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)

        self._geometry_cache = {}
        self.clashes: List[Clash] = []

    def _get_geometry(self, element):
        """Get or compute element geometry"""
        if element.GlobalId in self._geometry_cache:
            return self._geometry_cache[element.GlobalId]

        try:
            shape = ifcopenshell.geom.create_shape(self.settings, element)
            verts = np.array(shape.geometry.verts).reshape(-1, 3)
            faces = np.array(shape.geometry.faces).reshape(-1, 3)

            geom = {
                'vertices': verts,
                'faces': faces,
                'min': verts.min(axis=0),
                'max': verts.max(axis=0),
                'center': verts.mean(axis=0)
            }
            self._geometry_cache[element.GlobalId] = geom
            return geom
        except:
            return None

    def detect_hard_clashes(self, group1_types:
Read the full source on GitHub (opens external page)
Context

Related work