Skip to main content
ClaudeWave
Skill173 repo starsupdated 3mo ago

bim-validation-report

Generate comprehensive BIM model validation reports. Check data quality, completeness, and compliance with standards.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction /tmp/bim-validation-report && cp -r /tmp/bim-validation-report/1_DDC_Toolkit/BIM-Analysis/bim-validation-report ~/.claude/skills/bim-validation-report
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# BIM Validation Report Generator

## Business Case

### Problem Statement
BIM models often have quality issues:
- Missing required properties
- Invalid or inconsistent data
- Non-compliant with project standards
- Incomplete model information

### Solution
Automated BIM validation system that checks models against configurable rules and generates detailed compliance reports.

### Business Value
- **Quality assurance** - Catch issues early
- **Standards compliance** - Meet project requirements
- **Automation** - Reduce manual QC effort
- **Transparency** - Clear validation results

## Technical Implementation

```python
import pandas as pd
from datetime import datetime
from typing import Dict, Any, List, Optional, Callable
from dataclasses import dataclass, field
from enum import Enum


class ValidationSeverity(Enum):
    """Validation issue severity."""
    ERROR = "error"
    WARNING = "warning"
    INFO = "info"


class ValidationStatus(Enum):
    """Overall validation status."""
    PASSED = "passed"
    PASSED_WITH_WARNINGS = "passed_with_warnings"
    FAILED = "failed"


class RuleCategory(Enum):
    """Validation rule categories."""
    REQUIRED_PROPERTIES = "required_properties"
    DATA_FORMAT = "data_format"
    NAMING_CONVENTION = "naming_convention"
    GEOMETRIC = "geometric"
    CLASSIFICATION = "classification"
    RELATIONSHIPS = "relationships"


@dataclass
class ValidationRule:
    """Single validation rule."""
    rule_id: str
    name: str
    category: RuleCategory
    description: str
    severity: ValidationSeverity
    check_function: Callable
    applicable_categories: List[str] = field(default_factory=list)
    enabled: bool = True


@dataclass
class ValidationIssue:
    """Single validation issue."""
    issue_id: str
    rule_id: str
    rule_name: str
    element_id: str
    element_name: str
    element_category: str
    severity: ValidationSeverity
    message: str
    details: Dict[str, Any] = field(default_factory=dict)

    def to_dict(self) -> Dict[str, Any]:
        return {
            'issue_id': self.issue_id,
            'rule_id': self.rule_id,
            'rule_name': self.rule_name,
            'element_id': self.element_id,
            'element_name': self.element_name,
            'element_category': self.element_category,
            'severity': self.severity.value,
            'message': self.message
        }


@dataclass
class ValidationReport:
    """Complete validation report."""
    project_name: str
    model_name: str
    validated_at: datetime
    status: ValidationStatus
    total_elements: int
    elements_with_issues: int
    issues: List[ValidationIssue]
    rules_checked: int
    summary_by_severity: Dict[str, int]
    summary_by_category: Dict[str, int]


class BIMValidationEngine:
    """BIM model validation engine."""

    def __init__(self, project_name: str, model_name: str):
        self.project_name = project_name
        self.model_name = model_name
        self.rules: List[ValidationRule] = []
        self.issues: List[ValidationIssue] = []
        self._issue_counter = 0

        # Load default rules
        self._load_default_rules()

    def _load_default_rules(self):
        """Load standard validation rules."""

        # Required properties rules
        self.add_rule(ValidationRule(
            rule_id="REQ-001",
            name="Element Name Required",
            category=RuleCategory.REQUIRED_PROPERTIES,
            description="All elements must have a name",
            severity=ValidationSeverity.ERROR,
            check_function=lambda e: bool(e.get('name'))
        ))

        self.add_rule(ValidationRule(
            rule_id="REQ-002",
            name="Level Assignment Required",
            category=RuleCategory.REQUIRED_PROPERTIES,
            description="Elements must be assigned to a level",
            severity=ValidationSeverity.WARNING,
            check_function=lambda e: bool(e.get('level')),
            applicable_categories=["Walls", "Floors", "Doors", "Windows"]
        ))

        self.add_rule(ValidationRule(
            rule_id="REQ-003",
            name="Material Required",
            category=RuleCategory.REQUIRED_PROPERTIES,
            description="Structural elements must have material defined",
            severity=ValidationSeverity.ERROR,
            check_function=lambda e: bool(e.get('material')),
            applicable_categories=["Structural Columns", "Structural Framing", "Floors"]
        ))

        # Naming convention rules
        self.add_rule(ValidationRule(
            rule_id="NAM-001",
            name="No Special Characters",
            category=RuleCategory.NAMING_CONVENTION,
            description="Names should not contain special characters",
            severity=ValidationSeverity.WARNING,
            check_function=self._check_no_special_chars
        ))

        self.add_rule(ValidationRule(
            rule_id="NAM-002",
            name="Name Length Check",
            category=RuleCategory.NAMING_CONVENTION,
            description="Names should be between 3 and 100 characters",
            severity=ValidationSeverity.INFO,
            check_function=lambda e: 3 <= len(e.get('name', '')) <= 100
        ))

        # Classification rules
        self.add_rule(ValidationRule(
            rule_id="CLS-001",
            name="Classification Code Present",
            category=RuleCategory.CLASSIFICATION,
            description="Elements should have classification code",
            severity=ValidationSeverity.WARNING,
            check_function=lambda e: bool(e.get('classification_code') or e.get('uniformat'))
        ))

        # Geometric rules
        self.add_rule(ValidationRule(
            rule_id="GEO-001",
            name="Non-Zero Volume",
            category=RuleCategory.GEOMETRIC,
            description="3D elements must have non-zero volume",
            severity=ValidationSeverity.ERROR,
            check_function=lambda e: float(e.get('