ifc-commit/docs/ifcfile.md
2026-03-25 10:36:30 +01:00

160 lines
4.1 KiB
Markdown

# `ifcopenshell.file`
An `ifcopenshell.file` is the in-memory representation of a parsed IFC file.
It is the central object in every ifcbus operation — all reading, querying,
modifying, and writing go through it.
---
## Opening a file
```python
import ifcopenshell
model = ifcopenshell.open("input.ifc")
# model is an ifcopenshell.file object
```
`ifcopenshell.open()` parses the STEP-encoded `.ifc` file and loads all
entities into memory. The result is a live, mutable object graph.
---
## What it contains
An IFC file is a flat list of **entity instances**, each identified by a
sequential integer id (`#1`, `#2`, …). Entities reference each other by id,
forming a directed graph.
```
#1 = IfcOrganization(...)
#2 = IfcApplication(#1, ...)
#33 = IfcOwnerHistory(#32, #2, ...)
#514 = IfcSpace('0BTBFw6f90Nfh9rP1dlXrr', #33, 'A101', ...)
```
The `ifcopenshell.file` object holds:
- **All entity instances** (the flat list above)
- **Schema** — e.g. `IFC2X3`, `IFC4`
- **Header** — file metadata (author, application, description, timestamp)
---
## Key methods
### Querying
```python
# By entity id (integer)
el = model.by_id(514)
# By GlobalId (GUID string)
el = model.by_guid("0BTBFw6f90Nfh9rP1dlXrr")
# All instances of a type (includes subtypes)
walls = model.by_type("IfcWall") # returns list
spaces = model.by_type("IfcSpace")
# Iterate over every entity in the file
for entity in model:
print(entity.id(), entity.is_a())
```
### Relationships
```python
# All entities that reference this element (inverse links)
refs = model.get_inverse(el) # returns set of entity instances
# All entities reachable from this element (deep graph traversal)
graph = model.traverse(el) # returns list, breadth-first
```
### Modifying
```python
# Create a new entity
org = model.create_entity("IfcOrganization", Name="ACME")
# Remove an entity and clean up its relationships
model.remove(el)
# Higher-level removal (cleans containment, placements, etc.)
import ifcopenshell.api
ifcopenshell.api.run("root.remove_product", model, product=el)
```
### Writing
```python
# Write back to a file
model.write("output.ifc")
# Or via ifcpatch (used when the result comes from a recipe)
import ifcpatch
ifcpatch.write(result, "output.ifc")
```
---
## Schema and header
```python
print(model.schema) # "IFC2X3" or "IFC4"
print(model.header.file_description) # ViewDefinition, ...
print(model.header.file_name.name) # original filename
```
---
## Entity instances
Each element returned by the methods above is an **entity instance**
(`ifcopenshell.entity_instance`). Its attributes are accessed as properties:
```python
wall = model.by_type("IfcWall")[0]
wall.GlobalId # GUID string
wall.Name # element name
wall.is_a() # "IfcWall" — runtime type string
wall.id() # integer entity id (file-local, unstable across extractions)
wall.get_info() # dict of all attribute name → value
```
Entity ids are **not stable** — the same physical element will have a different
id after extraction or merging. Always use `GlobalId` or `Name` to identify
elements across files.
---
## Relationship to ifcpatch
`ifcpatch.execute()` takes an `ifcopenshell.file` as input and returns a new
one as output. The input is never modified in place. `ifcpatch.write()` is a
thin wrapper around `model.write()` with some post-processing.
```python
result = ifcpatch.execute({
"input": "input.ifc",
"file": model, # ← ifcopenshell.file
"recipe": "ExtractElements",
"arguments": ["IfcWall"],
})
# result is a new ifcopenshell.file
ifcpatch.write(result, "output.ifc")
```
---
## Memory model
The entire file is loaded into memory as a C++ object graph (via a Python
binding). This means:
- Operations are fast (no re-parsing on each query).
- Large files consume significant RAM.
- The object is **not thread-safe** — do not share across threads.
- Passing the object to `MergeProjects` as a file path string (instead of the
object itself) triggers a segfault in the current version — always pass the
live object.