Physical Model - Tables
Introduction
erDiagram
spatialUnit {
uuid id PK
string name
string type
string description
json unitGuide "'User Guide' for the spatialUnit"
}
bundle {
int id PK
int parentId
string name
json files
json jsonInDBHeader
string description
bool active
}
object {
int bundleId "part of PK"
uuid objectId "part of PK"
string type
string name
array representationIds "array of str(uuid)"
json elementJson "contains the object placement data"
}
object ||--o{ representation : has
representation {
int bundleId "part of PK"
uuid representationId "part of PK"
string type
json elementJson "contains the shape representation data"
geometry geom "geometry column for PostGIS"
}
propertySet {
int bundleId "part of PK"
uuid propertySetId "part of PK"
string name
json elementJson
}
relationship {
int bundleId "part of PK"
uuid relationshipId "part of PK"
string type
string relatingType
uuid relatingId "part of FK"
json elementJson
}
relationship }|..|| object : relating
relationship }|..|| propertySet : relating
relatedMembership {
uuid id PK
int bundleId "part of FK"
uuid relationshipId FK "part of FK"
string objectType
uuid objectId "part of FK"
}
relatedMembership }|--|| relationship : ""
relatedMembership }|--|| object : related
bundleUnit {
uuid5 bundleunit_id PK "The Id as a hash of all columns except unitJson"
int bundle_id "The Id of the bundle"
uuid unit_id "The Id of the Object "
string unitType "The type of the Object (e.g. IfcSpatiaZone)"
string unitName "The name of the object (e.g. Apartment 01-09)"
string unitObjectType "The objectType of the object (e.g. Private Parts - Apartment)"
string relationship_type "The type of the relationship (e.g. 'IfcRelAggregates)"
uuid parent_id "The Id of the Parent"
string parent_type "The type of the parent (e.g. 'IfcBuildingStorey')"
json unitJson "Information that is specific to the type."
}
bundleUnit }o..|{ object : "member"
bundleUnit }|--|| bundle : ""
spatialUnitBundleUnit {
uuid id PK
uuid spatialUnitId
int bundleId FK
uuid bundleUnitEdgeId FK
}
spatialUnitBundleUnit }|--|| spatialUnit : ""
spatialUnitBundleUnit }|--|| bundle: ""
spatialUnitBundleUnit }|--|| bundleUnit: ""
bundleJournal {
uuid id PK
int bundleId FK
uuid proctoken
json operationJson
}
bundleJournal }|--|| bundle : entry
erDiagram
bundleUnitPropertyset {
uuid id PK
int bundle_id "The id of the bundle"
uuid sz_id "The id of the SpatialZone (or more generally of the parent of a unit in bundleunit)"
string sz_type "Type of the spatial zone (e.g. Private parts - Apartment)"
string sz_name "Name of the spatial zone"
uuid unit_id "The id of a unit of bundleunit"
string unit_name "The name of the unit (e.g. Kitchen)"
uuid unit_id "The id of an object in the space boundary of a unit or contained in the spatial structure of a unit"
string object_type "The type of the object in the space boundary or contained in the spatial structure (e.g. an IfcDoor)"
string object_name "The name of the object"
uuid type_object_id "The id of the type of the Object"
string type_object_type "The ifc type of the type of the object (e.g. IfcDoorStyle)"
string type_object_name "The name of the type of the object"
uuid propertyset_id "The id of the property set"
string propertyset_name "The name of the propertyset (e.g. Pset_DoorCommon)"
json propertyset_json "The elementjson of the propertuset"
uuid properties_id "The id of a property associated to a type of object in its 'hasProperties', but which is not a property set"
string properties_type "The type of the property (e.g. IfcDoorPanelProperties)"
string properties_name "The name of the property (e.g. Door Panel Properties - Panel 1)"
json properties_json ""
}
bundleHistory {
uuid id PK
int bundleId
uuid parentId
string name
string source
string sourceHeader
bool active
}
elementHistory {
uuid id PK
int bundleId
uuid elementId
string elementType
json elementJson
}
There are 2 parts in the physical model: the D4SU model and the technical model based on ifcJSON
There are two parts in the data model. One part contains the information on the spatial units, their corresponding bundle of ifc file(s), the history of the processing and the data of the corresponding spatial zones and of their properties. Those data are collected by processing the technical model based on IfcJSON, but this is a design choice and they could also be collected by processing the IFC files directly.
The D4SU data model
The D4SU model contains the information for the Spatial Units and their data. The tables are: spatialUnit, bundle, bundleJournal, bundleUnit, spatialUnitBundleUnit, bundleJournalbundleUnitPropertyset.
The technical model based on ifcJSON
The model does not allocate IFC entities to DB tables but allocates ifcJSON entities to DB tables: object, representation, relationship, propertyset an add a table relatedmembership. The ifcJSON entities already aggregate a number of IFC entities. For instance, some ifcJSON relationships contain the data pertaining to one side of the relationship.
spatial_ref_sys table
In PostgreSQL, the table model also contains a table 'spatial_ref_sys' that is created by the PostGIS extension.
The physical technical model is articulated around simple principles:
- The entities are those provided by the ifc2json transformation
- The the ifc2json transformation is assumed to be lossless with respect to information that matters for Spatial Units; - if not, the transformation must be enhanced
- Items from the ifc2json are distributed in 4 blocks:
- object - applies to all items that are not in one of the 3 other groups
- representation
- propertySet (including IfcPropertySet and IfcElementQuantity)
- relationship
- All information from the ifc2json source is preserved. Each items keeps the totality of its original data into an elementJson field
One of the reasons for this choice is that data in the json can easily be accessed (as a python dictionary, a python pandas DataFrame or as a result of a postgres 'sql', or all combined).
So access is easy, provided that the structure is expected and understood.
Generally speaking, data processing that need to enhance entities or apply algorithms on the entities have an understanding of the data. They can therefore easily access and process the content of the the json.
But other treatments might just not care about these entities and would be confused by details that they don't need.
Tables
All tables details can be found under src/model with their pydantic definition.
Spatial Unit
The Spatial Unit acts as a relay for the Spatial Unit in the external adminirative system. The other tables will reference the id of this Spatial Unit which is turn will - when needed or convenient -- hold an external id for the external Spatial Unit.
Bundle
The bundle (elsewhere referred to as the dataBundle) is the logical 'bucket' for all files and data related to a 'source' project (whether IFC or not). It maintains a list of all files processed in relationship to the bundle.
Bundle Journal
The bundle journal keeps track of all operations that have been performed in relation with the bundle. This can be e.g.,
- import the source IFC
- transform the IFC in an elementJson
- filter the elementJson
- store the elementJson content in the database
Bundle Unit
The table stores the graph structure and the groups of entities that can be referred to by a Spatial Unit, namely the Site(s), Building(s), Storey(s), Space(s), Zone(s) and Spatial Zone(s). The same unit can be present multiple times. For instance, a 'Kitchen' space may be linked to the 'Apartment' SpatialZone to which it belongs via an 'IfcRelReferencedInSpatialStructure' relationship while being also linked to the containing 'Storey' via an 'IfcRelAgreggates' relationship.
The Id/PK (bundleunit_id) is based on a hash of all columns except the unitJson (and the technical data such as 'created_at' and 'updated_at'). The idea is that an update applies to the combination of these elements, and if one of them changes it must be an 'insert' or a 'delete old' + 'insert new'.
Spatial Unit Bundle Unit (junction between a spatial unit and a bundle unit)
Makes the junction between a Spatial Unit and a BundleIUnit.
Bundle Membership included in the primary key of elements
We don't use a junction table between the bundle and the elements of the bundle (object, representation, propertySet and relationship). Instead, we use the bundleId in the primary key of its elements (object, representation, propertySet, relationship) so that the primary key of an element is (bundleId, elementId).
For the elementId's we prefer to keep the uuid provided by the IFC GUID (globalId) in its extended form.
This GUID is technically unique but may be used repeatedly in different contexts. For instance, an IfcWall with a given GUID could appear for that wall in distinct IFC's for the design, construction and as-built phases. And there could be variations in the IfcWall data.
Also the discussion on the buildingSMART forum about GUIDs in an BIM Project brings additional perspective on the use of the guid: in a federation of IFC from distinct disciplines, the same GUID could be used for the given IfcWall but with a different use.
Therefore, the GUID will bear a unicity property only within a given bundle and a convenient unique key will be provided by (bundleId, elementId) dispensing from using a junction table.
Also, comparison across bundles could help identify variations in a specific element or help in federating different views, but with no guarantee as made clear in the discussion GUIDs in an BIM Project where an example is given of a project with multiple disciplines using different tools and producing distincts GUIDs for the same element.
Object
Contains all the items not in Represention, PropertySet or Relationship.
An object can be an element with a representation (geometry), i.e. an IfcProduct such as:
- IfcWall, IfcSlab, IfcColumn, IfcBeam, ...
- IfcDoor, IfcWindow, ...
- IfcCovering, ...
- IfcStair, ...
- IfcSpace, ...
- IfcDistributionFlowElement, ...
- IfcAnnotation
- ...
An IfcProduct may have a representation, and if it has a representation, it must have an IfcObjectPlacement
An object It can also be an element without a representaion
- IfcActor, IfcTaslk, IfcProcess, IfcResource
- IfcWorkPlan, IfcWorkPlanSchedule
- ...
Representation
Contains the items for the products that have one or more shape representation(s) (support for the 3D rendering and for measurement). Representations are separated from the product themselves which are in the object table. The separation is mainly for data management purpose: not all processes need the representation and several applications / model sources do not have shape representations. The representation table has a 'Geometry' column that is intended to support geometry related functions.
A representation has a IfcGeometricRepresentationContext which defines the context that applies to several shape representations of products within a project.
PropertySet
Contains the propertySets and elementQuantities that apply to one or more other items.
Relationship
All types of Relationships are stored in the same table with a structure that account for
- the type of the relationship
- the id of the unique relating item
- the type of the relating item
- the elementJson of the source relationship
The list of the related items is included in the elementJson and is also expanded in the Related Membership table.
When applying a filter on the import (or when creating a dependent bundle), some elements in the original IFC will be filtered out and will not remain in the bundle. This means that a relationship with a relating element in the the bundle may originally contain references to related elements that have been filtered out. In that case, the relationship is pruned for the references to the missing related elements. Therefore the database may contain different versions of a relationship with the same globalId (uuid of the relationship). To access the version of the relationship relevant for a bundle, it is necessary to give both the bundleId and the relationshipId.
The column for the relating_id may be null. Indeed for IfcRelAssociateMaterial, the relating material is in the relationship itself.
Related Membership
The table expand the relationships with one row per related item in de relationship. This is more convenient for SQL based queries.
As noted hereinabove the related membership exist for a combination of a bundleId and relationshipId (globalId of the relationship).
For some relationships, there are no related item. This is the case for IfcRelSpaceBoundary for a virtual boundary.
Bundle History
If a bundle is dropped,
- the detailed data pertaining the bundle (object, relationhips, ...) are deleted
- the summary data of that bundle is moved to the history table. Therefore, the links to the source and transformed file(s) is maintained
This is not activated and tested at this stage. It is more a placeholder to remember to address this topic more in depth
Elements History
The idea is that each time an element is modified, the before update version is saved in this history.
This is rarely used as in most cases we do not update IFC elements. However, as we create IfcSpatialZone elements, we can also update them with a PATCH. In that case, the before image of the modified IfcSpatialZone gets written in the Element History.
Bundle Unit Properties
Contains a flat structure of all units and their construction or distribution objects with all their propertysets or associated object type properties. This could be a in a file instead of a table and helps provide a fast response to a query on all properties that are relevant for the elements of a spatial zone associated to a spatial unit.
There are properties :
- that are associated with a set of objects and are element of the IfcPropertySet type, e.g. Pset_DoorCommon associated via an IfcRelDefinesByProperties with elements of type IfcDoor, or
- that are associated to the type/style of an object and that are are not in the elements of type IfcPropertySet, e.g. an IfcDoor can have an IfcDoorStyle with hasProperties that reference an IfcDoorPanelProperties
For propetyset we have:
- propertyset_id
- propertyset_name
- propertyset_json; in the json we have either properties in hasProperties or quantities in quantities
For objectTypes we have:
- type_object_id
- type_object_type
- type_object_name
For properties of objectTypes found in the 'hasProperties' and not in the propertyset, we have:
- properties_id
- properties_type
- properties_name
- properties_json