{"id":"7dd0ed97-bc1a-49b8-91c2-d8c64ec21afb","entityType":"agent","slug":"clawhub-datadrivenconstruction-cad-to-data","name":"Cad To Data","canonicalUrl":"https://www.xpersona.co/agent/clawhub-datadrivenconstruction-cad-to-data","canonicalPath":"/agent/clawhub-datadrivenconstruction-cad-to-data","generatedAt":"2026-10-10T07:53:43.847Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-10T02:10:57.278Z","emptyReason":null},"description":"Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files. Skill: Cad To Data Owner: datadrivenconstruction Summary: Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files. Tags: latest:2.0.0 Version history: v2.0.0 | 2026-02-13T17:00:28.015Z | auto cad-to-data 2.0.0 - Major update: New data structures and extraction logic for structured extraction from CAD/BIM files. - Expanded support for multiple formats: Revit, IFC, DWG, DGN, plus","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.8K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s1774mv3t1cm8r1kgs9hccdnmn8852nb:cad-to-data","sourceUrl":"https://clawhub.ai/datadrivenconstruction/cad-to-data","homepage":"https://clawhub.ai/datadrivenconstruction/skills/cad-to-data","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/datadrivenconstruction/cad-to-data","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/datadrivenconstruction/skills/cad-to-data","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":65,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files. Skill: Cad To Data Owner: datadrivenconstruction Summary: Conver"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T02:10:57.278Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T02:10:57.278Z","emptyReason":null},"stars":null,"forks":null,"downloads":1784,"packageName":null,"latestVersion":"2.0.0","tractionLabel":"1.8K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T02:10:57.277Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T02:10:57.278Z","lastCrawledAt":"2026-10-10T02:10:57.277Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T02:10:57.277Z","lastVerifiedAt":null,"highlights":[{"version":"2.0.0","createdAt":"2026-02-13T17:00:28.015Z","changelog":"cad-to-data 2.0.0 - Major update: New data structures and extraction logic for structured extraction from CAD/BIM files. - Expanded support for multiple formats: Revit, IFC, DWG, DGN, plus new formats (DXF, NWD, STEP). - Introduced detailed dataclasses for elements, materials, layers, and results. - Defines granular element categories (wall, floor, roof, etc.). - Implements a simulated IFC extraction workflow as a reference. - Includes Quick Start code and documentation updates.","fileCount":4,"zipByteSize":6771},{"version":"1.0.0","createdAt":"2026-02-07T14:44:19.808Z","changelog":"Initial release of CAD To Data – convert CAD/BIM files to structured data. - Extracts element data (properties, quantities, relationships) from Revit, IFC, DWG, DGN files. - Defines data classes for elements, materials, layers, and extraction results. - Includes simulated IFC file extraction logic with example data structures. - Supports category-based filtering and extraction metadata.","fileCount":2,"zipByteSize":5562}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s1774mv3t1cm8r1kgs9hccdnmn8852nb:cad-to-data","setupComplexity":"low","setupSteps":["Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-datadrivenconstruction-cad-to-data/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-datadrivenconstruction-cad-to-data/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-datadrivenconstruction-cad-to-data/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-datadrivenconstruction-cad-to-data/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-datadrivenconstruction-cad-to-data/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-datadrivenconstruction-cad-to-data/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T07:53:43.847Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-datadrivenconstruction-cad-to-data/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-datadrivenconstruction-cad-to-data/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-datadrivenconstruction-cad-to-data/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-datadrivenconstruction-cad-to-data/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-10T02:10:57.278Z","emptyReason":null},"readme":"Skill: Cad To Data\n\nOwner: datadrivenconstruction\n\nSummary: Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files.\n\nTags: latest:2.0.0\n\nVersion history:\n\nv2.0.0 | 2026-02-13T17:00:28.015Z | auto\n\ncad-to-data 2.0.0\n\n- Major update: New data structures and extraction logic for structured extraction from CAD/BIM files.\n- Expanded support for multiple formats: Revit, IFC, DWG, DGN, plus new formats (DXF, NWD, STEP).\n- Introduced detailed dataclasses for elements, materials, layers, and results.\n- Defines granular element categories (wall, floor, roof, etc.).\n- Implements a simulated IFC extraction workflow as a reference.\n- Includes Quick Start code and documentation updates.\n\nv1.0.0 | 2026-02-07T14:44:19.808Z | auto\n\nInitial release of CAD To Data – convert CAD/BIM files to structured data.\n\n- Extracts element data (properties, quantities, relationships) from Revit, IFC, DWG, DGN files.\n- Defines data classes for elements, materials, layers, and extraction results.\n- Includes simulated IFC file extraction logic with example data structures.\n- Supports category-based filtering and extraction metadata.\n\nArchive index:\n\nArchive v2.0.0: 4 files, 6771 bytes\n\nFiles: claw.json (446b), instructions.md (1469b), SKILL.md (20105b), _meta.json (130b)\n\nFile v2.0.0:SKILL.md\n\n---\r\nname: \"cad-to-data\"\r\ndescription: \"Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files.\"\r\n---\r\n\r\n# CAD To Data\r\n\r\n## Overview\r\n\r\nBased 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.\r\n\r\n**Book Reference:** \"Преобразование данных в структурированную форму\" / \"Data Transformation to Structured Form\"\r\n\r\n## Quick Start\r\n\r\n```python\r\nfrom dataclasses import dataclass, field\r\nfrom enum import Enum\r\nfrom typing import List, Dict, Optional, Any, Tuple, Generator\r\nfrom datetime import datetime\r\nimport json\r\n\r\nclass CADFormat(Enum):\r\n    \"\"\"Supported CAD/BIM formats\"\"\"\r\n    IFC = \"ifc\"\r\n    RVT = \"rvt\"\r\n    DWG = \"dwg\"\r\n    DXF = \"dxf\"\r\n    DGN = \"dgn\"\r\n    NWD = \"nwd\"\r\n    STEP = \"step\"\r\n\r\nclass ElementCategory(Enum):\r\n    \"\"\"BIM element categories\"\"\"\r\n    WALL = \"wall\"\r\n    FLOOR = \"floor\"\r\n    ROOF = \"roof\"\r\n    CEILING = \"ceiling\"\r\n    DOOR = \"door\"\r\n    WINDOW = \"window\"\r\n    COLUMN = \"column\"\r\n    BEAM = \"beam\"\r\n    STAIR = \"stair\"\r\n    RAMP = \"ramp\"\r\n    FURNITURE = \"furniture\"\r\n    EQUIPMENT = \"equipment\"\r\n    PIPE = \"pipe\"\r\n    DUCT = \"duct\"\r\n    CABLE_TRAY = \"cable_tray\"\r\n    SPACE = \"space\"\r\n    GENERIC = \"generic\"\r\n\r\n@dataclass\r\nclass Point3D:\r\n    \"\"\"3D point\"\"\"\r\n    x: float\r\n    y: float\r\n    z: float\r\n\r\n@dataclass\r\nclass BoundingBox3D:\r\n    \"\"\"3D bounding box\"\"\"\r\n    min_point: Point3D\r\n    max_point: Point3D\r\n\r\n    @property\r\n    def width(self) -> float:\r\n        return abs(self.max_point.x - self.min_point.x)\r\n\r\n    @property\r\n    def depth(self) -> float:\r\n        return abs(self.max_point.y - self.min_point.y)\r\n\r\n    @property\r\n    def height(self) -> float:\r\n        return abs(self.max_point.z - self.min_point.z)\r\n\r\n    @property\r\n    def volume(self) -> float:\r\n        return self.width * self.depth * self.height\r\n\r\n@dataclass\r\nclass MaterialInfo:\r\n    \"\"\"Material information\"\"\"\r\n    name: str\r\n    category: str\r\n    color: Optional[str] = None\r\n    area: float = 0.0\r\n    volume: float = 0.0\r\n    properties: Dict[str, Any] = field(default_factory=dict)\r\n\r\n@dataclass\r\nclass CADElement:\r\n    \"\"\"Extracted CAD/BIM element\"\"\"\r\n    id: str\r\n    guid: str\r\n    name: str\r\n    category: ElementCategory\r\n    type_name: str\r\n    level: Optional[str] = None\r\n    bounding_box: Optional[BoundingBox3D] = None\r\n    properties: Dict[str, Any] = field(default_factory=dict)\r\n    quantities: Dict[str, float] = field(default_factory=dict)\r\n    materials: List[MaterialInfo] = field(default_factory=list)\r\n    relationships: Dict[str, List[str]] = field(default_factory=dict)\r\n\r\n@dataclass\r\nclass CADLayer:\r\n    \"\"\"CAD layer information\"\"\"\r\n    name: str\r\n    color: Optional[str] = None\r\n    line_type: Optional[str] = None\r\n    visible: bool = True\r\n    element_count: int = 0\r\n\r\n@dataclass\r\nclass CADExtractionResult:\r\n    \"\"\"Result of CAD extraction\"\"\"\r\n    file_path: str\r\n    file_format: CADFormat\r\n    elements: List[CADElement]\r\n    layers: List[CADLayer]\r\n    levels: List[str]\r\n    total_elements: int\r\n    categories: Dict[str, int]\r\n    extraction_time: float\r\n    metadata: Dict[str, Any] = field(default_factory=dict)\r\n\r\n\r\nclass IFCExtractor:\r\n    \"\"\"Extract data from IFC files\"\"\"\r\n\r\n    def __init__(self):\r\n        self.schema_version = \"IFC4\"\r\n        self.element_mapping = self._build_element_mapping()\r\n\r\n    def _build_element_mapping(self) -> Dict[str, ElementCategory]:\r\n        \"\"\"Map IFC types to categories\"\"\"\r\n        return {\r\n            \"IfcWall\": ElementCategory.WALL,\r\n            \"IfcWallStandardCase\": ElementCategory.WALL,\r\n            \"IfcSlab\": ElementCategory.FLOOR,\r\n            \"IfcRoof\": ElementCategory.ROOF,\r\n            \"IfcCeiling\": ElementCategory.CEILING,\r\n            \"IfcDoor\": ElementCategory.DOOR,\r\n            \"IfcWindow\": ElementCategory.WINDOW,\r\n            \"IfcColumn\": ElementCategory.COLUMN,\r\n            \"IfcBeam\": ElementCategory.BEAM,\r\n            \"IfcStair\": ElementCategory.STAIR,\r\n            \"IfcRamp\": ElementCategory.RAMP,\r\n            \"IfcFurnishingElement\": ElementCategory.FURNITURE,\r\n            \"IfcPipeSegment\": ElementCategory.PIPE,\r\n            \"IfcDuctSegment\": ElementCategory.DUCT,\r\n            \"IfcCableCarrierSegment\": ElementCategory.CABLE_TRAY,\r\n            \"IfcSpace\": ElementCategory.SPACE,\r\n        }\r\n\r\n    def extract(\r\n        self,\r\n        file_path: str,\r\n        categories: Optional[List[ElementCategory]] = None\r\n    ) -> CADExtractionResult:\r\n        \"\"\"\r\n        Extract data from IFC file.\r\n\r\n        Args:\r\n            file_path: Path to IFC file\r\n            categories: Optional filter for categories\r\n\r\n        Returns:\r\n            Extraction result\r\n        \"\"\"\r\n        start_time = datetime.now()\r\n\r\n        # In production, use ifcopenshell:\r\n        # import ifcopenshell\r\n        # ifc_file = ifcopenshell.open(file_path)\r\n\r\n        # Simulated extraction\r\n        elements = self._simulate_ifc_elements()\r\n\r\n        # Filter by category if specified\r\n        if categories:\r\n            elements = [e for e in elements if e.category in categories]\r\n\r\n        # Build category counts\r\n        category_counts = {}\r\n        for element in elements:\r\n            cat = element.category.value\r\n            category_counts[cat] = category_counts.get(cat, 0) + 1\r\n\r\n        # Extract levels\r\n        levels = list(set(e.level for e in elements if e.level))\r\n\r\n        extraction_time = (datetime.now() - start_time).total_seconds()\r\n\r\n        return CADExtractionResult(\r\n            file_path=file_path,\r\n            file_format=CADFormat.IFC,\r\n            elements=elements,\r\n            layers=[],  # IFC doesn't use layers in traditional sense\r\n            levels=levels,\r\n            total_elements=len(elements),\r\n            categories=category_counts,\r\n            extraction_time=extraction_time,\r\n            metadata={\r\n                \"schema\": self.schema_version,\r\n                \"project_name\": \"Sample Project\"\r\n            }\r\n        )\r\n\r\n    def _simulate_ifc_elements(self) -> List[CADElement]:\r\n        \"\"\"Simulate IFC element extraction\"\"\"\r\n        elements = []\r\n\r\n        # Sample walls\r\n        for i in range(10):\r\n            elements.append(CADElement(\r\n                id=f\"wall_{i}\",\r\n                guid=f\"1234567890ABCDEF{i:04d}\",\r\n                name=f\"Basic Wall {i}\",\r\n                category=ElementCategory.WALL,\r\n                type_name=\"Basic Wall:200mm Concrete\",\r\n                level=\"Level 1\",\r\n                bounding_box=BoundingBox3D(\r\n                    min_point=Point3D(i * 5, 0, 0),\r\n                    max_point=Point3D(i * 5 + 5, 0.2, 3)\r\n                ),\r\n                properties={\r\n                    \"IsExternal\": True,\r\n                    \"FireRating\": \"1 HR\",\r\n                    \"LoadBearing\": True\r\n                },\r\n                quantities={\r\n                    \"Length\": 5.0,\r\n                    \"Height\": 3.0,\r\n                    \"Width\": 0.2,\r\n                    \"Area\": 15.0,\r\n                    \"Volume\": 3.0\r\n                },\r\n                materials=[\r\n                    MaterialInfo(\r\n                        name=\"Concrete\",\r\n                        category=\"Concrete\",\r\n                        area=15.0,\r\n                        volume=3.0\r\n                    )\r\n                ]\r\n            ))\r\n\r\n        # Sample doors\r\n        for i in range(5):\r\n            elements.append(CADElement(\r\n                id=f\"door_{i}\",\r\n                guid=f\"DOOR0000000000{i:04d}\",\r\n                name=f\"Single Door {i}\",\r\n                category=ElementCategory.DOOR,\r\n                type_name=\"Single Flush:900x2100\",\r\n                level=\"Level 1\",\r\n                properties={\r\n                    \"FireRating\": \"None\",\r\n                    \"IsExternal\": False\r\n                },\r\n                quantities={\r\n                    \"Width\": 0.9,\r\n                    \"Height\": 2.1,\r\n                    \"Area\": 1.89\r\n                },\r\n                relationships={\r\n                    \"host_wall\": [f\"wall_{i}\"]\r\n                }\r\n            ))\r\n\r\n        # Sample spaces\r\n        for i in range(3):\r\n            elements.append(CADElement(\r\n                id=f\"space_{i}\",\r\n                guid=f\"SPACE000000000{i:04d}\",\r\n                name=f\"Room {i+101}\",\r\n                category=ElementCategory.SPACE,\r\n                type_name=\"Office\",\r\n                level=\"Level 1\",\r\n                quantities={\r\n                    \"Area\": 25.0 + i * 5,\r\n                    \"Volume\": 75.0 + i * 15,\r\n                    \"Perimeter\": 20.0 + i * 2\r\n                },\r\n                properties={\r\n                    \"OccupancyType\": \"Office\",\r\n                    \"DesignOccupancy\": 4\r\n                }\r\n            ))\r\n\r\n        return elements\r\n\r\n    def get_quantities(\r\n        self,\r\n        elements: List[CADElement],\r\n        quantity_type: str = \"all\"\r\n    ) -> Dict[str, float]:\r\n        \"\"\"Aggregate quantities from elements\"\"\"\r\n        totals = {}\r\n\r\n        for element in elements:\r\n            for qty_name, qty_value in element.quantities.items():\r\n                if quantity_type == \"all\" or qty_name.lower() == quantity_type.lower():\r\n                    key = f\"{element.category.value}_{qty_name}\"\r\n                    totals[key] = totals.get(key, 0) + qty_value\r\n\r\n        return totals\r\n\r\n\r\nclass DWGExtractor:\r\n    \"\"\"Extract data from DWG/DXF files\"\"\"\r\n\r\n    def __init__(self):\r\n        self.supported_entities = [\"LINE\", \"POLYLINE\", \"CIRCLE\", \"ARC\", \"TEXT\", \"MTEXT\", \"INSERT\", \"HATCH\"]\r\n\r\n    def extract(\r\n        self,\r\n        file_path: str,\r\n        layers: Optional[List[str]] = None\r\n    ) -> CADExtractionResult:\r\n        \"\"\"Extract data from DWG file\"\"\"\r\n        start_time = datetime.now()\r\n\r\n        # In production, use ezdxf:\r\n        # import ezdxf\r\n        # doc = ezdxf.readfile(file_path)\r\n\r\n        # Simulated extraction\r\n        elements, cad_layers = self._simulate_dwg_extraction()\r\n\r\n        # Filter by layers if specified\r\n        if layers:\r\n            elements = [e for e in elements if e.properties.get(\"layer\") in layers]\r\n\r\n        extraction_time = (datetime.now() - start_time).total_seconds()\r\n\r\n        return CADExtractionResult(\r\n            file_path=file_path,\r\n            file_format=CADFormat.DWG,\r\n            elements=elements,\r\n            layers=cad_layers,\r\n            levels=[],\r\n            total_elements=len(elements),\r\n            categories={\"generic\": len(elements)},\r\n            extraction_time=extraction_time,\r\n            metadata={\"units\": \"millimeters\"}\r\n        )\r\n\r\n    def _simulate_dwg_extraction(self) -> Tuple[List[CADElement], List[CADLayer]]:\r\n        \"\"\"Simulate DWG extraction\"\"\"\r\n        elements = []\r\n        layers = [\r\n            CADLayer(\"Walls\", \"Red\", \"Continuous\", True, 15),\r\n            CADLayer(\"Doors\", \"Blue\", \"Continuous\", True, 8),\r\n            CADLayer(\"Windows\", \"Cyan\", \"Continuous\", True, 12),\r\n            CADLayer(\"Dimensions\", \"Green\", \"Continuous\", True, 50),\r\n            CADLayer(\"Text\", \"White\", \"Continuous\", True, 25),\r\n        ]\r\n\r\n        # Simulate polylines (walls)\r\n        for i in range(15):\r\n            elements.append(CADElement(\r\n                id=f\"polyline_{i}\",\r\n                guid=f\"PL{i:08d}\",\r\n                name=f\"Polyline {i}\",\r\n                category=ElementCategory.GENERIC,\r\n                type_name=\"POLYLINE\",\r\n                properties={\r\n                    \"layer\": \"Walls\",\r\n                    \"color\": \"Red\",\r\n                    \"closed\": True\r\n                },\r\n                quantities={\r\n                    \"Length\": 10.5 + i * 0.5\r\n                }\r\n            ))\r\n\r\n        return elements, layers\r\n\r\n\r\nclass CADDataConverter:\r\n    \"\"\"\r\n    Convert CAD/BIM files to structured data.\r\n    Based on DDC methodology Chapter 2.4.\r\n    \"\"\"\r\n\r\n    def __init__(self):\r\n        self.ifc_extractor = IFCExtractor()\r\n        self.dwg_extractor = DWGExtractor()\r\n\r\n    def convert(\r\n        self,\r\n        file_path: str,\r\n        output_format: str = \"json\"\r\n    ) -> Dict[str, Any]:\r\n        \"\"\"\r\n        Convert CAD file to structured data.\r\n\r\n        Args:\r\n            file_path: Path to CAD file\r\n            output_format: Output format (json, csv, dataframe)\r\n\r\n        Returns:\r\n            Structured data\r\n        \"\"\"\r\n        # Detect file format\r\n        file_format = self._detect_format(file_path)\r\n\r\n        # Extract based on format\r\n        if file_format == CADFormat.IFC:\r\n            result = self.ifc_extractor.extract(file_path)\r\n        elif file_format in [CADFormat.DWG, CADFormat.DXF]:\r\n            result = self.dwg_extractor.extract(file_path)\r\n        else:\r\n            raise ValueError(f\"Unsupported format: {file_format}\")\r\n\r\n        # Convert to output format\r\n        return self._format_output(result, output_format)\r\n\r\n    def _detect_format(self, file_path: str) -> CADFormat:\r\n        \"\"\"Detect CAD file format\"\"\"\r\n        extension = file_path.lower().split(\".\")[-1]\r\n\r\n        format_map = {\r\n            \"ifc\": CADFormat.IFC,\r\n            \"rvt\": CADFormat.RVT,\r\n            \"dwg\": CADFormat.DWG,\r\n            \"dxf\": CADFormat.DXF,\r\n            \"dgn\": CADFormat.DGN,\r\n            \"nwd\": CADFormat.NWD,\r\n        }\r\n\r\n        return format_map.get(extension, CADFormat.IFC)\r\n\r\n    def _format_output(\r\n        self,\r\n        result: CADExtractionResult,\r\n        format: str\r\n    ) -> Dict[str, Any]:\r\n        \"\"\"Format extraction result\"\"\"\r\n        output = {\r\n            \"file\": result.file_path,\r\n            \"format\": result.file_format.value,\r\n            \"total_elements\": result.total_elements,\r\n            \"categories\": result.categories,\r\n            \"levels\": result.levels,\r\n            \"extraction_time\": result.extraction_time,\r\n            \"elements\": []\r\n        }\r\n\r\n        for element in result.elements:\r\n            output[\"elements\"].append({\r\n                \"id\": element.id,\r\n                \"guid\": element.guid,\r\n                \"name\": element.name,\r\n                \"category\": element.category.value,\r\n                \"type\": element.type_name,\r\n                \"level\": element.level,\r\n                \"properties\": element.properties,\r\n                \"quantities\": element.quantities,\r\n                \"materials\": [\r\n                    {\"name\": m.name, \"area\": m.area, \"volume\": m.volume}\r\n                    for m in element.materials\r\n                ]\r\n            })\r\n\r\n        return output\r\n\r\n    def extract_quantities(\r\n        self,\r\n        file_path: str,\r\n        categories: Optional[List[ElementCategory]] = None\r\n    ) -> Dict[str, Any]:\r\n        \"\"\"Extract quantity takeoff from CAD file\"\"\"\r\n        file_format = self._detect_format(file_path)\r\n\r\n        if file_format == CADFormat.IFC:\r\n            result = self.ifc_extractor.extract(file_path, categories)\r\n        else:\r\n            result = self.dwg_extractor.extract(file_path)\r\n\r\n        # Aggregate quantities by category\r\n        quantities = {}\r\n        for element in result.elements:\r\n            cat = element.category.value\r\n            if cat not in quantities:\r\n                quantities[cat] = {\r\n                    \"count\": 0,\r\n                    \"totals\": {}\r\n                }\r\n\r\n            quantities[cat][\"count\"] += 1\r\n\r\n            for qty_name, qty_value in element.quantities.items():\r\n                if qty_name not in quantities[cat][\"totals\"]:\r\n                    quantities[cat][\"totals\"][qty_name] = 0\r\n                quantities[cat][\"totals\"][qty_name] += qty_value\r\n\r\n        return {\r\n            \"file\": file_path,\r\n            \"quantities\": quantities,\r\n            \"summary\": {\r\n                \"total_elements\": result.total_elements,\r\n                \"categories\": list(quantities.keys())\r\n            }\r\n        }\r\n\r\n    def extract_schedule(\r\n        self,\r\n        file_path: str,\r\n        category: ElementCategory,\r\n        fields: List[str]\r\n    ) -> List[Dict]:\r\n        \"\"\"Extract schedule data for specific category\"\"\"\r\n        file_format = self._detect_format(file_path)\r\n\r\n        if file_format == CADFormat.IFC:\r\n            result = self.ifc_extractor.extract(file_path, [category])\r\n        else:\r\n            result = self.dwg_extractor.extract(file_path)\r\n\r\n        schedule = []\r\n        for element in result.elements:\r\n            if element.category == category:\r\n                row = {\"id\": element.id, \"name\": element.name, \"type\": element.type_name}\r\n\r\n                for field in fields:\r\n                    if field in element.properties:\r\n                        row[field] = element.properties[field]\r\n                    elif field in element.quantities:\r\n                        row[field] = element.quantities[field]\r\n\r\n                schedule.append(row)\r\n\r\n        return schedule\r\n\r\n    def export_to_json(\r\n        self,\r\n        result: CADExtractionResult,\r\n        output_path: str\r\n    ):\r\n        \"\"\"Export extraction result to JSON file\"\"\"\r\n        output = self._format_output(result, \"json\")\r\n\r\n        with open(output_path, 'w') as f:\r\n            json.dump(output, f, indent=2)\r\n\r\n    def generate_report(self, result: CADExtractionResult) -> str:\r\n        \"\"\"Generate extraction report\"\"\"\r\n        report = f\"\"\"\r\n# CAD Extraction Report\r\n\r\n**File:** {result.file_path}\r\n**Format:** {result.file_format.value}\r\n**Total Elements:** {result.total_elements}\r\n**Extraction Time:** {result.extraction_time:.2f}s\r\n\r\n## Elements by Category\r\n\"\"\"\r\n        for cat, count in result.categories.items():\r\n            report += f\"- **{cat.title()}:** {count}\\n\"\r\n\r\n        if result.levels:\r\n            report += \"\\n## Levels\\n\"\r\n            for level in result.levels:\r\n                report += f\"- {level}\\n\"\r\n\r\n        if result.layers:\r\n            report += \"\\n## Layers\\n\"\r\n            for layer in result.layers:\r\n                report += f\"- {layer.name}: {layer.element_count} elements\\n\"\r\n\r\n        return report\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### Extract IFC Data\r\n\r\n```python\r\nconverter = CADDataConverter()\r\n\r\n# Convert IFC to structured data\r\ndata = converter.convert(\"building.ifc\", output_format=\"json\")\r\n\r\nprint(f\"Total elements: {data['total_elements']}\")\r\nprint(f\"Categories: {data['categories']}\")\r\n\r\n# Access elements\r\nfor element in data['elements'][:5]:\r\n    print(f\"  {element['name']}: {element['type']}\")\r\n```\r\n\r\n### Extract Quantities\r\n\r\n```python\r\nquantities = converter.extract_quantities(\r\n    \"building.ifc\",\r\n    categories=[ElementCategory.WALL, ElementCategory.FLOOR]\r\n)\r\n\r\nprint(f\"Wall count: {quantities['quantities']['wall']['count']}\")\r\nprint(f\"Total wall area: {quantities['quantities']['wall']['totals']['Area']}\")\r\n```\r\n\r\n### Generate Schedule\r\n\r\n```python\r\ndoor_schedule = converter.extract_schedule(\r\n    \"building.ifc\",\r\n    category=ElementCategory.DOOR,\r\n    fields=[\"Width\", \"Height\", \"FireRating\", \"IsExternal\"]\r\n)\r\n\r\nfor door in door_schedule:\r\n    print(f\"{door['name']}: {door.get('Width')}x{door.get('Height')}\")\r\n```\r\n\r\n### Generate Report\r\n\r\n```python\r\nifc_extractor = IFCExtractor()\r\nresult = ifc_extractor.extract(\"building.ifc\")\r\n\r\nreport = converter.generate_report(result)\r\nprint(report)\r\n```\r\n\r\n## Quick Reference\r\n\r\n| Component | Purpose |\r\n|-----------|---------|\r\n| `CADDataConverter` | Main conversion engine |\r\n| `IFCExtractor` | IFC file extraction |\r\n| `DWGExtractor` | DWG/DXF extraction |\r\n| `CADElement` | Extracted element data |\r\n| `CADExtractionResult` | Complete extraction result |\r\n| `ElementCategory` | BIM element categories |\r\n\r\n## Resources\r\n\r\n- **Book**: \"Data-Driven Construction\" by Artem Boiko, Chapter 2.4\r\n- **Website**: https://datadrivenconstruction.io\r\n\r\n## Next Steps\r\n\r\n- Use [image-to-data](../image-to-data/SKILL.md) for image extraction\r\n- Use [qto-report](../../Chapter-3.2/qto-report/SKILL.md) for quantity reports\r\n- Use [bim-validation-pipeline](../../Chapter-4.3/bim-validation-pipeline/SKILL.md) for validation\n\nFile v2.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn75fhjxn1jz5xbgd9ggj0nrtd80q1dz\",\n  \"slug\": \"cad-to-data\",\n  \"version\": \"2.0.0\",\n  \"publishedAt\": 1771002028015\n}\n\nFile v2.0.0:instructions.md\n\nYou are a CAD/BIM data extraction assistant. You help users convert proprietary CAD and BIM files into structured, analyzable data formats (Excel, CSV, JSON, DataFrame).\n\nWhen the user asks to extract data from CAD/BIM files:\n1. Identify the file format (.rvt, .ifc, .dwg, .dgn) and select the right converter\n2. Extract element data: type, category, layer/level, properties, geometry\n3. Structure into tabular format with consistent columns\n4. Export to user's preferred format (Excel, CSV, JSON, pandas DataFrame)\n\nWhen the user asks about supported formats:\n1. Revit (.rvt/.rfa): categories, families, types, parameters, quantities\n2. IFC (.ifc): entities, property sets, quantities, spatial structure\n3. DWG (.dwg): layers, blocks, attributes, entities, coordinates\n4. DGN (.dgn): levels, cells, elements, tags, text nodes\n\n## Input Format\n- CAD/BIM file path (any supported format)\n- Optional: specific elements or properties to extract\n- Optional: output format (Excel, CSV, JSON)\n\n## Output Format\n- Structured table: element type, properties, quantities, coordinates\n- One sheet/table per element category\n- Summary with element counts and basic statistics\n- Metadata: source file, extraction date, converter version\n\n## Constraints\n- Filesystem permission required for file reading and writing\n- Format-specific CLI converters invoked via subprocess.run()\n- No proprietary CAD software licenses required\n- Large models may need category-by-category extraction\n\nFile v2.0.0:claw.json\n\n{\n  \"name\": \"cad-to-data\",\n  \"version\": \"2.0.0\",\n  \"description\": \"Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files.\",\n  \"author\": \"datadrivenconstruction\",\n  \"license\": \"MIT\",\n  \"permissions\": [\"filesystem\"],\n  \"entry\": \"instructions.md\",\n  \"tags\": [\"construction\", \"CAD\", \"BIM\", \"data-extraction\", \"Revit\", \"IFC\", \"DWG\", \"DGN\"],\n  \"models\": [\"claude-*\", \"gpt-*\"],\n  \"minOpenClawVersion\": \"0.8.0\"\n}\n\nArchive v1.0.0: 2 files, 5562 bytes\n\nFiles: SKILL.md (20133b), _meta.json (130b)\n\nFile v1.0.0:SKILL.md\n\n---\r\nslug: \"cad-to-data\"\r\ndisplay_name: \"CAD To Data\"\r\ndescription: \"Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files\"\r\n---\r\n\r\n# CAD To Data\r\n\r\n## Overview\r\n\r\nBased 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.\r\n\r\n**Book Reference:** \"Преобразование данных в структурированную форму\" / \"Data Transformation to Structured Form\"\r\n\r\n## Quick Start\r\n\r\n```python\r\nfrom dataclasses import dataclass, field\r\nfrom enum import Enum\r\nfrom typing import List, Dict, Optional, Any, Tuple, Generator\r\nfrom datetime import datetime\r\nimport json\r\n\r\nclass CADFormat(Enum):\r\n    \"\"\"Supported CAD/BIM formats\"\"\"\r\n    IFC = \"ifc\"\r\n    RVT = \"rvt\"\r\n    DWG = \"dwg\"\r\n    DXF = \"dxf\"\r\n    DGN = \"dgn\"\r\n    NWD = \"nwd\"\r\n    STEP = \"step\"\r\n\r\nclass ElementCategory(Enum):\r\n    \"\"\"BIM element categories\"\"\"\r\n    WALL = \"wall\"\r\n    FLOOR = \"floor\"\r\n    ROOF = \"roof\"\r\n    CEILING = \"ceiling\"\r\n    DOOR = \"door\"\r\n    WINDOW = \"window\"\r\n    COLUMN = \"column\"\r\n    BEAM = \"beam\"\r\n    STAIR = \"stair\"\r\n    RAMP = \"ramp\"\r\n    FURNITURE = \"furniture\"\r\n    EQUIPMENT = \"equipment\"\r\n    PIPE = \"pipe\"\r\n    DUCT = \"duct\"\r\n    CABLE_TRAY = \"cable_tray\"\r\n    SPACE = \"space\"\r\n    GENERIC = \"generic\"\r\n\r\n@dataclass\r\nclass Point3D:\r\n    \"\"\"3D point\"\"\"\r\n    x: float\r\n    y: float\r\n    z: float\r\n\r\n@dataclass\r\nclass BoundingBox3D:\r\n    \"\"\"3D bounding box\"\"\"\r\n    min_point: Point3D\r\n    max_point: Point3D\r\n\r\n    @property\r\n    def width(self) -> float:\r\n        return abs(self.max_point.x - self.min_point.x)\r\n\r\n    @property\r\n    def depth(self) -> float:\r\n        return abs(self.max_point.y - self.min_point.y)\r\n\r\n    @property\r\n    def height(self) -> float:\r\n        return abs(self.max_point.z - self.min_point.z)\r\n\r\n    @property\r\n    def volume(self) -> float:\r\n        return self.width * self.depth * self.height\r\n\r\n@dataclass\r\nclass MaterialInfo:\r\n    \"\"\"Material information\"\"\"\r\n    name: str\r\n    category: str\r\n    color: Optional[str] = None\r\n    area: float = 0.0\r\n    volume: float = 0.0\r\n    properties: Dict[str, Any] = field(default_factory=dict)\r\n\r\n@dataclass\r\nclass CADElement:\r\n    \"\"\"Extracted CAD/BIM element\"\"\"\r\n    id: str\r\n    guid: str\r\n    name: str\r\n    category: ElementCategory\r\n    type_name: str\r\n    level: Optional[str] = None\r\n    bounding_box: Optional[BoundingBox3D] = None\r\n    properties: Dict[str, Any] = field(default_factory=dict)\r\n    quantities: Dict[str, float] = field(default_factory=dict)\r\n    materials: List[MaterialInfo] = field(default_factory=list)\r\n    relationships: Dict[str, List[str]] = field(default_factory=dict)\r\n\r\n@dataclass\r\nclass CADLayer:\r\n    \"\"\"CAD layer information\"\"\"\r\n    name: str\r\n    color: Optional[str] = None\r\n    line_type: Optional[str] = None\r\n    visible: bool = True\r\n    element_count: int = 0\r\n\r\n@dataclass\r\nclass CADExtractionResult:\r\n    \"\"\"Result of CAD extraction\"\"\"\r\n    file_path: str\r\n    file_format: CADFormat\r\n    elements: List[CADElement]\r\n    layers: List[CADLayer]\r\n    levels: List[str]\r\n    total_elements: int\r\n    categories: Dict[str, int]\r\n    extraction_time: float\r\n    metadata: Dict[str, Any] = field(default_factory=dict)\r\n\r\n\r\nclass IFCExtractor:\r\n    \"\"\"Extract data from IFC files\"\"\"\r\n\r\n    def __init__(self):\r\n        self.schema_version = \"IFC4\"\r\n        self.element_mapping = self._build_element_mapping()\r\n\r\n    def _build_element_mapping(self) -> Dict[str, ElementCategory]:\r\n        \"\"\"Map IFC types to categories\"\"\"\r\n        return {\r\n            \"IfcWall\": ElementCategory.WALL,\r\n            \"IfcWallStandardCase\": ElementCategory.WALL,\r\n            \"IfcSlab\": ElementCategory.FLOOR,\r\n            \"IfcRoof\": ElementCategory.ROOF,\r\n            \"IfcCeiling\": ElementCategory.CEILING,\r\n            \"IfcDoor\": ElementCategory.DOOR,\r\n            \"IfcWindow\": ElementCategory.WINDOW,\r\n            \"IfcColumn\": ElementCategory.COLUMN,\r\n            \"IfcBeam\": ElementCategory.BEAM,\r\n            \"IfcStair\": ElementCategory.STAIR,\r\n            \"IfcRamp\": ElementCategory.RAMP,\r\n            \"IfcFurnishingElement\": ElementCategory.FURNITURE,\r\n            \"IfcPipeSegment\": ElementCategory.PIPE,\r\n            \"IfcDuctSegment\": ElementCategory.DUCT,\r\n            \"IfcCableCarrierSegment\": ElementCategory.CABLE_TRAY,\r\n            \"IfcSpace\": ElementCategory.SPACE,\r\n        }\r\n\r\n    def extract(\r\n        self,\r\n        file_path: str,\r\n        categories: Optional[List[ElementCategory]] = None\r\n    ) -> CADExtractionResult:\r\n        \"\"\"\r\n        Extract data from IFC file.\r\n\r\n        Args:\r\n            file_path: Path to IFC file\r\n            categories: Optional filter for categories\r\n\r\n        Returns:\r\n            Extraction result\r\n        \"\"\"\r\n        start_time = datetime.now()\r\n\r\n        # In production, use ifcopenshell:\r\n        # import ifcopenshell\r\n        # ifc_file = ifcopenshell.open(file_path)\r\n\r\n        # Simulated extraction\r\n        elements = self._simulate_ifc_elements()\r\n\r\n        # Filter by category if specified\r\n        if categories:\r\n            elements = [e for e in elements if e.category in categories]\r\n\r\n        # Build category counts\r\n        category_counts = {}\r\n        for element in elements:\r\n            cat = element.category.value\r\n            category_counts[cat] = category_counts.get(cat, 0) + 1\r\n\r\n        # Extract levels\r\n        levels = list(set(e.level for e in elements if e.level))\r\n\r\n        extraction_time = (datetime.now() - start_time).total_seconds()\r\n\r\n        return CADExtractionResult(\r\n            file_path=file_path,\r\n            file_format=CADFormat.IFC,\r\n            elements=elements,\r\n            layers=[],  # IFC doesn't use layers in traditional sense\r\n            levels=levels,\r\n            total_elements=len(elements),\r\n            categories=category_counts,\r\n            extraction_time=extraction_time,\r\n            metadata={\r\n                \"schema\": self.schema_version,\r\n                \"project_name\": \"Sample Project\"\r\n            }\r\n        )\r\n\r\n    def _simulate_ifc_elements(self) -> List[CADElement]:\r\n        \"\"\"Simulate IFC element extraction\"\"\"\r\n        elements = []\r\n\r\n        # Sample walls\r\n        for i in range(10):\r\n            elements.append(CADElement(\r\n                id=f\"wall_{i}\",\r\n                guid=f\"1234567890ABCDEF{i:04d}\",\r\n                name=f\"Basic Wall {i}\",\r\n                category=ElementCategory.WALL,\r\n                type_name=\"Basic Wall:200mm Concrete\",\r\n                level=\"Level 1\",\r\n                bounding_box=BoundingBox3D(\r\n                    min_point=Point3D(i * 5, 0, 0),\r\n                    max_point=Point3D(i * 5 + 5, 0.2, 3)\r\n                ),\r\n                properties={\r\n                    \"IsExternal\": True,\r\n                    \"FireRating\": \"1 HR\",\r\n                    \"LoadBearing\": True\r\n                },\r\n                quantities={\r\n                    \"Length\": 5.0,\r\n                    \"Height\": 3.0,\r\n                    \"Width\": 0.2,\r\n                    \"Area\": 15.0,\r\n                    \"Volume\": 3.0\r\n                },\r\n                materials=[\r\n                    MaterialInfo(\r\n                        name=\"Concrete\",\r\n                        category=\"Concrete\",\r\n                        area=15.0,\r\n                        volume=3.0\r\n                    )\r\n                ]\r\n            ))\r\n\r\n        # Sample doors\r\n        for i in range(5):\r\n            elements.append(CADElement(\r\n                id=f\"door_{i}\",\r\n                guid=f\"DOOR0000000000{i:04d}\",\r\n                name=f\"Single Door {i}\",\r\n                category=ElementCategory.DOOR,\r\n                type_name=\"Single Flush:900x2100\",\r\n                level=\"Level 1\",\r\n                properties={\r\n                    \"FireRating\": \"None\",\r\n                    \"IsExternal\": False\r\n                },\r\n                quantities={\r\n                    \"Width\": 0.9,\r\n                    \"Height\": 2.1,\r\n                    \"Area\": 1.89\r\n                },\r\n                relationships={\r\n                    \"host_wall\": [f\"wall_{i}\"]\r\n                }\r\n            ))\r\n\r\n        # Sample spaces\r\n        for i in range(3):\r\n            elements.append(CADElement(\r\n                id=f\"space_{i}\",\r\n                guid=f\"SPACE000000000{i:04d}\",\r\n                name=f\"Room {i+101}\",\r\n                category=ElementCategory.SPACE,\r\n                type_name=\"Office\",\r\n                level=\"Level 1\",\r\n                quantities={\r\n                    \"Area\": 25.0 + i * 5,\r\n                    \"Volume\": 75.0 + i * 15,\r\n                    \"Perimeter\": 20.0 + i * 2\r\n                },\r\n                properties={\r\n                    \"OccupancyType\": \"Office\",\r\n                    \"DesignOccupancy\": 4\r\n                }\r\n            ))\r\n\r\n        return elements\r\n\r\n    def get_quantities(\r\n        self,\r\n        elements: List[CADElement],\r\n        quantity_type: str = \"all\"\r\n    ) -> Dict[str, float]:\r\n        \"\"\"Aggregate quantities from elements\"\"\"\r\n        totals = {}\r\n\r\n        for element in elements:\r\n            for qty_name, qty_value in element.quantities.items():\r\n                if quantity_type == \"all\" or qty_name.lower() == quantity_type.lower():\r\n                    key = f\"{element.category.value}_{qty_name}\"\r\n                    totals[key] = totals.get(key, 0) + qty_value\r\n\r\n        return totals\r\n\r\n\r\nclass DWGExtractor:\r\n    \"\"\"Extract data from DWG/DXF files\"\"\"\r\n\r\n    def __init__(self):\r\n        self.supported_entities = [\"LINE\", \"POLYLINE\", \"CIRCLE\", \"ARC\", \"TEXT\", \"MTEXT\", \"INSERT\", \"HATCH\"]\r\n\r\n    def extract(\r\n        self,\r\n        file_path: str,\r\n        layers: Optional[List[str]] = None\r\n    ) -> CADExtractionResult:\r\n        \"\"\"Extract data from DWG file\"\"\"\r\n        start_time = datetime.now()\r\n\r\n        # In production, use ezdxf:\r\n        # import ezdxf\r\n        # doc = ezdxf.readfile(file_path)\r\n\r\n        # Simulated extraction\r\n        elements, cad_layers = self._simulate_dwg_extraction()\r\n\r\n        # Filter by layers if specified\r\n        if layers:\r\n            elements = [e for e in elements if e.properties.get(\"layer\") in layers]\r\n\r\n        extraction_time = (datetime.now() - start_time).total_seconds()\r\n\r\n        return CADExtractionResult(\r\n            file_path=file_path,\r\n            file_format=CADFormat.DWG,\r\n            elements=elements,\r\n            layers=cad_layers,\r\n            levels=[],\r\n            total_elements=len(elements),\r\n            categories={\"generic\": len(elements)},\r\n            extraction_time=extraction_time,\r\n            metadata={\"units\": \"millimeters\"}\r\n        )\r\n\r\n    def _simulate_dwg_extraction(self) -> Tuple[List[CADElement], List[CADLayer]]:\r\n        \"\"\"Simulate DWG extraction\"\"\"\r\n        elements = []\r\n        layers = [\r\n            CADLayer(\"Walls\", \"Red\", \"Continuous\", True, 15),\r\n            CADLayer(\"Doors\", \"Blue\", \"Continuous\", True, 8),\r\n            CADLayer(\"Windows\", \"Cyan\", \"Continuous\", True, 12),\r\n            CADLayer(\"Dimensions\", \"Green\", \"Continuous\", True, 50),\r\n            CADLayer(\"Text\", \"White\", \"Continuous\", True, 25),\r\n        ]\r\n\r\n        # Simulate polylines (walls)\r\n        for i in range(15):\r\n            elements.append(CADElement(\r\n                id=f\"polyline_{i}\",\r\n                guid=f\"PL{i:08d}\",\r\n                name=f\"Polyline {i}\",\r\n                category=ElementCategory.GENERIC,\r\n                type_name=\"POLYLINE\",\r\n                properties={\r\n                    \"layer\": \"Walls\",\r\n                    \"color\": \"Red\",\r\n                    \"closed\": True\r\n                },\r\n                quantities={\r\n                    \"Length\": 10.5 + i * 0.5\r\n                }\r\n            ))\r\n\r\n        return elements, layers\r\n\r\n\r\nclass CADDataConverter:\r\n    \"\"\"\r\n    Convert CAD/BIM files to structured data.\r\n    Based on DDC methodology Chapter 2.4.\r\n    \"\"\"\r\n\r\n    def __init__(self):\r\n        self.ifc_extractor = IFCExtractor()\r\n        self.dwg_extractor = DWGExtractor()\r\n\r\n    def convert(\r\n        self,\r\n        file_path: str,\r\n        output_format: str = \"json\"\r\n    ) -> Dict[str, Any]:\r\n        \"\"\"\r\n        Convert CAD file to structured data.\r\n\r\n        Args:\r\n            file_path: Path to CAD file\r\n            output_format: Output format (json, csv, dataframe)\r\n\r\n        Returns:\r\n            Structured data\r\n        \"\"\"\r\n        # Detect file format\r\n        file_format = self._detect_format(file_path)\r\n\r\n        # Extract based on format\r\n        if file_format == CADFormat.IFC:\r\n            result = self.ifc_extractor.extract(file_path)\r\n        elif file_format in [CADFormat.DWG, CADFormat.DXF]:\r\n            result = self.dwg_extractor.extract(file_path)\r\n        else:\r\n            raise ValueError(f\"Unsupported format: {file_format}\")\r\n\r\n        # Convert to output format\r\n        return self._format_output(result, output_format)\r\n\r\n    def _detect_format(self, file_path: str) -> CADFormat:\r\n        \"\"\"Detect CAD file format\"\"\"\r\n        extension = file_path.lower().split(\".\")[-1]\r\n\r\n        format_map = {\r\n            \"ifc\": CADFormat.IFC,\r\n            \"rvt\": CADFormat.RVT,\r\n            \"dwg\": CADFormat.DWG,\r\n            \"dxf\": CADFormat.DXF,\r\n            \"dgn\": CADFormat.DGN,\r\n            \"nwd\": CADFormat.NWD,\r\n        }\r\n\r\n        return format_map.get(extension, CADFormat.IFC)\r\n\r\n    def _format_output(\r\n        self,\r\n        result: CADExtractionResult,\r\n        format: str\r\n    ) -> Dict[str, Any]:\r\n        \"\"\"Format extraction result\"\"\"\r\n        output = {\r\n            \"file\": result.file_path,\r\n            \"format\": result.file_format.value,\r\n            \"total_elements\": result.total_elements,\r\n            \"categories\": result.categories,\r\n            \"levels\": result.levels,\r\n            \"extraction_time\": result.extraction_time,\r\n            \"elements\": []\r\n        }\r\n\r\n        for element in result.elements:\r\n            output[\"elements\"].append({\r\n                \"id\": element.id,\r\n                \"guid\": element.guid,\r\n                \"name\": element.name,\r\n                \"category\": element.category.value,\r\n                \"type\": element.type_name,\r\n                \"level\": element.level,\r\n                \"properties\": element.properties,\r\n                \"quantities\": element.quantities,\r\n                \"materials\": [\r\n                    {\"name\": m.name, \"area\": m.area, \"volume\": m.volume}\r\n                    for m in element.materials\r\n                ]\r\n            })\r\n\r\n        return output\r\n\r\n    def extract_quantities(\r\n        self,\r\n        file_path: str,\r\n        categories: Optional[List[ElementCategory]] = None\r\n    ) -> Dict[str, Any]:\r\n        \"\"\"Extract quantity takeoff from CAD file\"\"\"\r\n        file_format = self._detect_format(file_path)\r\n\r\n        if file_format == CADFormat.IFC:\r\n            result = self.ifc_extractor.extract(file_path, categories)\r\n        else:\r\n            result = self.dwg_extractor.extract(file_path)\r\n\r\n        # Aggregate quantities by category\r\n        quantities = {}\r\n        for element in result.elements:\r\n            cat = element.category.value\r\n            if cat not in quantities:\r\n                quantities[cat] = {\r\n                    \"count\": 0,\r\n                    \"totals\": {}\r\n                }\r\n\r\n            quantities[cat][\"count\"] += 1\r\n\r\n            for qty_name, qty_value in element.quantities.items():\r\n                if qty_name not in quantities[cat][\"totals\"]:\r\n                    quantities[cat][\"totals\"][qty_name] = 0\r\n                quantities[cat][\"totals\"][qty_name] += qty_value\r\n\r\n        return {\r\n            \"file\": file_path,\r\n            \"quantities\": quantities,\r\n            \"summary\": {\r\n                \"total_elements\": result.total_elements,\r\n                \"categories\": list(quantities.keys())\r\n            }\r\n        }\r\n\r\n    def extract_schedule(\r\n        self,\r\n        file_path: str,\r\n        category: ElementCategory,\r\n        fields: List[str]\r\n    ) -> List[Dict]:\r\n        \"\"\"Extract schedule data for specific category\"\"\"\r\n        file_format = self._detect_format(file_path)\r\n\r\n        if file_format == CADFormat.IFC:\r\n            result = self.ifc_extractor.extract(file_path, [category])\r\n        else:\r\n            result = self.dwg_extractor.extract(file_path)\r\n\r\n        schedule = []\r\n        for element in result.elements:\r\n            if element.category == category:\r\n                row = {\"id\": element.id, \"name\": element.name, \"type\": element.type_name}\r\n\r\n                for field in fields:\r\n                    if field in element.properties:\r\n                        row[field] = element.properties[field]\r\n                    elif field in element.quantities:\r\n                        row[field] = element.quantities[field]\r\n\r\n                schedule.append(row)\r\n\r\n        return schedule\r\n\r\n    def export_to_json(\r\n        self,\r\n        result: CADExtractionResult,\r\n        output_path: str\r\n    ):\r\n        \"\"\"Export extraction result to JSON file\"\"\"\r\n        output = self._format_output(result, \"json\")\r\n\r\n        with open(output_path, 'w') as f:\r\n            json.dump(output, f, indent=2)\r\n\r\n    def generate_report(self, result: CADExtractionResult) -> str:\r\n        \"\"\"Generate extraction report\"\"\"\r\n        report = f\"\"\"\r\n# CAD Extraction Report\r\n\r\n**File:** {result.file_path}\r\n**Format:** {result.file_format.value}\r\n**Total Elements:** {result.total_elements}\r\n**Extraction Time:** {result.extraction_time:.2f}s\r\n\r\n## Elements by Category\r\n\"\"\"\r\n        for cat, count in result.categories.items():\r\n            report += f\"- **{cat.title()}:** {count}\\n\"\r\n\r\n        if result.levels:\r\n            report += \"\\n## Levels\\n\"\r\n            for level in result.levels:\r\n                report += f\"- {level}\\n\"\r\n\r\n        if result.layers:\r\n            report += \"\\n## Layers\\n\"\r\n            for layer in result.layers:\r\n                report += f\"- {layer.name}: {layer.element_count} elements\\n\"\r\n\r\n        return report\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### Extract IFC Data\r\n\r\n```python\r\nconverter = CADDataConverter()\r\n\r\n# Convert IFC to structured data\r\ndata = converter.convert(\"building.ifc\", output_format=\"json\")\r\n\r\nprint(f\"Total elements: {data['total_elements']}\")\r\nprint(f\"Categories: {data['categories']}\")\r\n\r\n# Access elements\r\nfor element in data['elements'][:5]:\r\n    print(f\"  {element['name']}: {element['type']}\")\r\n```\r\n\r\n### Extract Quantities\r\n\r\n```python\r\nquantities = converter.extract_quantities(\r\n    \"building.ifc\",\r\n    categories=[ElementCategory.WALL, ElementCategory.FLOOR]\r\n)\r\n\r\nprint(f\"Wall count: {quantities['quantities']['wall']['count']}\")\r\nprint(f\"Total wall area: {quantities['quantities']['wall']['totals']['Area']}\")\r\n```\r\n\r\n### Generate Schedule\r\n\r\n```python\r\ndoor_schedule = converter.extract_schedule(\r\n    \"building.ifc\",\r\n    category=ElementCategory.DOOR,\r\n    fields=[\"Width\", \"Height\", \"FireRating\", \"IsExternal\"]\r\n)\r\n\r\nfor door in door_schedule:\r\n    print(f\"{door['name']}: {door.get('Width')}x{door.get('Height')}\")\r\n```\r\n\r\n### Generate Report\r\n\r\n```python\r\nifc_extractor = IFCExtractor()\r\nresult = ifc_extractor.extract(\"building.ifc\")\r\n\r\nreport = converter.generate_report(result)\r\nprint(report)\r\n```\r\n\r\n## Quick Reference\r\n\r\n| Component | Purpose |\r\n|-----------|---------|\r\n| `CADDataConverter` | Main conversion engine |\r\n| `IFCExtractor` | IFC file extraction |\r\n| `DWGExtractor` | DWG/DXF extraction |\r\n| `CADElement` | Extracted element data |\r\n| `CADExtractionResult` | Complete extraction result |\r\n| `ElementCategory` | BIM element categories |\r\n\r\n## Resources\r\n\r\n- **Book**: \"Data-Driven Construction\" by Artem Boiko, Chapter 2.4\r\n- **Website**: https://datadrivenconstruction.io\r\n\r\n## Next Steps\r\n\r\n- Use [image-to-data](../image-to-data/SKILL.md) for image extraction\r\n- Use [qto-report](../../Chapter-3.2/qto-report/SKILL.md) for quantity reports\r\n- Use [bim-validation-pipeline](../../Chapter-4.3/bim-validation-pipeline/SKILL.md) for validation\n\nFile v1.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn75fhjxn1jz5xbgd9ggj0nrtd80q1dz\",\n  \"slug\": \"cad-to-data\",\n  \"version\": \"1.0.0\",\n  \"publishedAt\": 1770475459808\n}","readmeExcerpt":"Skill: Cad To Data Owner: datadrivenconstruction Summary: Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files. Tags: latest:2.0.0 Version history: v2.0.0 | 2026-02-13T17:00:28.015Z | auto cad-to-data 2.0.0 - Major update: New data structures and extraction logic for structured extraction from CAD/BIM files. - Expanded support for multiple formats: Revit, IFC, DWG, DGN, plus ","codeSnippets":[],"executableExamples":[],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\r\nname: \"cad-to-data\"\r\ndescription: \"Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files.\"\r\n---\r\n\r\n# CAD To Data\r\n\r\n## Overview\r\n\r\nBased 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.\r\n\r\n**Book Reference:** \"Преобразование данных в структурированную форму\" / \"Data Transformation to Structured Form\"\r\n\r\n## Quick Start\r\n\r\n```python\r\nfrom dataclasses import dataclass, field\r\nfrom enum import Enum\r\nfrom typing import List, Dict, Optional, Any, Tuple, Generator\r\nfrom datetime import datetime\r\nimport json\r\n\r\nclass CADFormat(Enum):\r\n    \"\"\"Supported CAD/BIM formats\"\"\"\r\n    IFC = \"ifc\"\r\n    RVT = \"rvt\"\r\n    DWG = \"dwg\"\r\n    DXF = \"dxf\"\r\n    DGN = \"dgn\"\r\n    NWD = \"nwd\"\r\n    STEP = \"step\"\r\n\r\nclass ElementCategory(Enum):\r\n    \"\"\"BIM element categories\"\"\"\r\n    WALL = \"wall\"\r\n    FLOOR = \"floor\"\r\n    ROOF = \"roof\"\r\n    CEILING = \"ceiling\"\r\n    DOOR = \"door\"\r\n    WINDOW = \"window\"\r\n    COLUMN = \"column\"\r\n    BEAM = \"beam\"\r\n    STAIR = \"stair\"\r\n    RAMP = \"ramp\"\r\n    FURNITURE = \"furniture\"\r\n    EQUIPMENT = \"equipment\"\r\n    PIPE = \"pipe\"\r\n    DUCT = \"duct\"\r\n    CABLE_TRAY = \"cable_tray\"\r\n    SPACE = \"space\"\r\n    GENERIC = \"generic\"\r\n\r\n@dataclass\r\nclass Point3D:\r\n    \"\"\"3D point\"\"\"\r\n    x: float\r\n    y: float\r\n    z: float\r\n\r\n@dataclass\r\nclass BoundingBox3D:\r\n    \"\"\"3D bounding box\"\"\"\r\n    min_point: Point3D\r\n    max_point: Point3D\r\n\r\n    @property\r\n    def width(self) -> float:\r\n        return abs(self.max_point.x - self.min_point.x)\r\n\r\n    @property\r\n    def depth(self) -> float:\r\n        return abs(self.max_point.y - self.min_point.y)\r\n\r\n    @property\r\n    def height(self) -> float:\r\n        return abs(self.max_point.z - self.min_point.z)\r\n\r\n    @property\r\n    def volume(self) -> float:\r\n        return self.width * self.depth * self.height\r\n\r\n@dataclass\r\nclass MaterialInfo:\r\n    \"\"\"Material information\"\"\"\r\n    name: str\r\n    category: str\r\n    color: Optional[str] = None\r\n    area: float = 0.0\r\n    volume: float = 0.0\r\n    properties: Dict[str, Any] = field(default_factory=dict)\r\n\r\n@dataclass\r\nclass CADElement:\r\n    \"\"\"Extracted CAD/BIM element\"\"\"\r\n    id: str\r\n    guid: str\r\n    name: str\r\n    category: ElementCategory\r\n    type_name: str\r\n    level: Optional[str] = None\r\n    bounding_box: Optional[BoundingBox3D] = None\r\n    properties: Dict[str, Any] = field(default_factory=dict)\r\n    quantities: Dict[str, float] = field(default_factory=dict)\r\n    materials: List[MaterialInfo] = field(default_factory=list)\r\n    relationships: Dict[str, List[str]] = field(default_factory=dict)\r\n\r\n@dataclass\r\nclass CADLayer:\r\n    \"\"\"CAD layer information\"\"\"\r\n    name: str\r\n    color: Optional[str] = None\r\n    line_type: Optional[str] = None\r\n    visible: bool = True\r\n    element_count: int = 0\r\n\r\n@dataclass\r\nclass CADExtractionResult:\r\n    \"\"\"Result of CAD extraction\"\"\"\r\n    file_path: str\r"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn75fhjxn1jz5xbgd9ggj0nrtd80q1dz\",\n  \"slug\": \"cad-to-data\",\n  \"version\": \"2.0.0\",\n  \"publishedAt\": 1771002028015\n}"},{"path":"instructions.md","content":"You are a CAD/BIM data extraction assistant. You help users convert proprietary CAD and BIM files into structured, analyzable data formats (Excel, CSV, JSON, DataFrame).\n\nWhen the user asks to extract data from CAD/BIM files:\n1. Identify the file format (.rvt, .ifc, .dwg, .dgn) and select the right converter\n2. Extract element data: type, category, layer/level, properties, geometry\n3. Structure into tabular format with consistent columns\n4. Export to user's preferred format (Excel, CSV, JSON, pandas DataFrame)\n\nWhen the user asks about supported formats:\n1. Revit (.rvt/.rfa): categories, families, types, parameters, quantities\n2. IFC (.ifc): entities, property sets, quantities, spatial structure\n3. DWG (.dwg): layers, blocks, attributes, entities, coordinates\n4. DGN (.dgn): levels, cells, elements, tags, text nodes\n\n## Input Format\n- CAD/BIM file path (any supported format)\n- Optional: specific elements or properties to extract\n- Optional: output format (Excel, CSV, JSON)\n\n## Output Format\n- Structured table: element type, properties, quantities, coordinates\n- One sheet/table per element category\n- Summary with element counts and basic statistics\n- Metadata: source file, extraction date, converter version\n\n## Constraints\n- Filesystem permission required for file reading and writing\n- Format-specific CLI converters invoked via subprocess.run()\n- No proprietary CAD software licenses required\n- Large models may need category-by-category extraction"},{"path":"claw.json","content":"{\n  \"name\": \"cad-to-data\",\n  \"version\": \"2.0.0\",\n  \"description\": \"Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files.\",\n  \"author\": \"datadrivenconstruction\",\n  \"license\": \"MIT\",\n  \"permissions\": [\"filesystem\"],\n  \"entry\": \"instructions.md\",\n  \"tags\": [\"construction\", \"CAD\", \"BIM\", \"data-extraction\", \"Revit\", \"IFC\", \"DWG\", \"DGN\"],\n  \"models\": [\"claude-*\", \"gpt-*\"],\n  \"minOpenClawVersion\": \"0.8.0\"\n}"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files. Skill: Cad To Data Owner: datadrivenconstruction Summary: Convert CAD/BIM files to structured data. Extract element data from Revit, IFC, DWG, DGN files. Tags: latest:2.0.0 Version history: v2.0.0 | 2026-02-13T17:00:28.015Z | auto cad-to-data 2.0.0 - Major update: New data structures and extraction logic for structured extraction from CAD/BIM files. - Expanded support for multiple formats: Revit, IFC, DWG, DGN, plus","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1097,"uniquenessScore":46,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T02:10:57.278Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T02:10:57.278Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T07:53:43.847Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}