Skip to content

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 if 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  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
        json    operationJson  
    }
    bundleJournal }|--|| bundle : entry
erDiagram
    bundleHistory {
        uuid    id PK
        int     bundleId
        uuid    parentId
        string  name
        string  source
        string  sourceHeader
        bool    active
    }
    elementHistory {
        uuid    id PK
        int     bundleId
        string  elementType
        uuid    elementId
        json    elementJson
        int     version
    }

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 model is based on ifcJSON

The model hereunder does not allocate IFC entities to DB tables but allocates ifcJSON entities to DB tables. 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.

The physical 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 of the items not in Represention, PropertySet or Relationship.

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.

To be challenged: the local placement is in the Object table and the geometry in the Representation table.

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.

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 not activated and tested at this stage. It is more a placeholder to remember to address this topic more in depth