OSArch Community

[IfcOpenShell][BlenderBIM] Creating an IfcGrid,IfcBuildingStorey,IfcSlab,IfcWall and youtube demo.

  1. C

    After reading this thread and seeing this post on a Freecad forum from 2016.

    It made me wonder if I could create an .ifc with Python starting from the basics with a grid.

    Conclusion, it seems I can, I barely changed the script and loaded the .ifc in BlenderBIM

    Here is the python code:

    <details>

    <summary>See the python code</summary>

    
    import os
    
    import sys
    
    import time
    
    import uuid
    
    import math
    
    
    import ifcopenshell
    
    
    O = 0., 0., 0.
    
    X = 1., 0., 0.
    
    Y = 0., 1., 0.
    
    Z = 0., 0., 1.
    
    
    create_guid = lambda: ifcopenshell.guid.compress(uuid.uuid1().hex)
    
    
    
    
    file_name = 'grid.ifc'
    
    timestamp = time.time()
    
    timestring = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(timestamp))
    
    creator = "C. Claus"
    
    organization = "Claus aannemingsmaatschappij"
    
    application, application_version = "IfcOpenShell", "0.5"
    
    project_globalid, project_name = create_guid(), "Grid"
    
    
    
    
    # open for Blank
    
    ifc_file = ifcopenshell.file()
    
    
    
    
    #=============================================
    
    
    org = ifc_file.createIfcOrganization()
    
    org.Name = organization
    
    
    app = ifc_file.createIfcApplication()
    
    app.ApplicationDeveloper = org
    
    app.Version = "3.2"
    
    app.ApplicationFullName = "BlenderBIM"
    
    
    person = ifc_file.createIfcPerson()
    
    person.FamilyName="C. Claus"
    
    
    
    
    person_org= ifc_file.createIfcPersonAndOrganization()
    
    person_org.ThePerson=person
    
    person_org.TheOrganization=org
    
    
    owner_hist= ifc_file.createIfcOwnerHistory()
    
    owner_hist.OwningUser = person_org
    
    owner_hist.OwningApplication = app
    
    owner_hist.ChangeAction= "NOCHANGE"
    
    owner_hist.CreationDate= int(time.time())
    
    
    #  Global unit definitions
    
    LengthUnit = ifc_file.createIfcSIUnit()
    
    LengthUnit.UnitType = "LENGTHUNIT"
    
    LengthUnit.Prefix = "MILLI"
    
    LengthUnit.Name="METRE"
    
    
    #AreaUnit = ifc_file.createIfcSIUnit("AREAUNIT" , None, "SQUARE_METRE")
    
    AreaUnit = ifc_file.createIfcSIUnit()
    
    AreaUnit.UnitType = "AREAUNIT"
    
    AreaUnit.Name="SQUARE_METRE"
    
    
    
    
    VolumeUnit = ifc_file.createIfcSIUnit()
    
    VolumeUnit.UnitType = "VOLUMEUNIT"
    
    VolumeUnit.Name="CUBIC_METRE"
    
    
    
    
    PlaneAngleUnit = ifc_file.createIfcSIUnit()
    
    PlaneAngleUnit.UnitType = "PLANEANGLEUNIT"
    
    PlaneAngleUnit.Name  ="RADIAN"
    
    
    AngleUnit = ifc_file.createIfcMeasureWithUnit()
    
    AngleUnit.UnitComponent =PlaneAngleUnit 
    
    AngleUnit.ValueComponent = ifc_file.createIfcPlaneAngleMeasure(math.pi/180)
    
    
    
    
    DimExp = ifc_file.createIfcDimensionalExponents(0,0,0,0,0,0,0)
    
    
    
    
    ConvertBaseUnit = ifc_file.createIfcConversionBasedUnit()
    
    ConvertBaseUnit.Dimensions = DimExp
    
    ConvertBaseUnit.UnitType="PLANEANGLEUNIT"
    
    ConvertBaseUnit.Name="DEGREE"
    
    ConvertBaseUnit.ConversionFactor = AngleUnit
    
    
    
    
    UnitAssignment=ifc_file.createIfcUnitAssignment([LengthUnit , AreaUnit , VolumeUnit ,ConvertBaseUnit])
    
    
    axis_X = ifc_file.createIfcDirection(X)
    
    axis_Y = ifc_file.createIfcDirection(Y)
    
    axis_Z = ifc_file.createIfcDirection(Z)
    
    Pnt_O = ifc_file.createIfcCartesianPoint(O)
    
    
    
    
    # Defining project and representation contexts 
    
    WorldCoordinateSystem = ifc_file.createIfcAxis2Placement3D()
    
    WorldCoordinateSystem.Location=Pnt_O
    
    WorldCoordinateSystem.Axis = axis_Z
    
    WorldCoordinateSystem.RefDirection = axis_X
    
    
    context = ifc_file.createIfcGeometricRepresentationContext()
    
    context.ContextType = "Model"
    
    context.CoordinateSpaceDimension = 3
    
    context.Precision = 1.e-05
    
    context.WorldCoordinateSystem = WorldCoordinateSystem
    
    
    
    
    footprint_context = ifc_file.createIfcGeometricRepresentationSubContext()
    
    footprint_context.ContextIdentifier = 'FootPrint'
    
    footprint_context.ContextType = "Model"
    
    footprint_context.ParentContext = context
    
    footprint_context.TargetView = 'MODEL_VIEW'
    
    
    myProject = ifc_file.createIfcProject(create_guid())
    
    myProject.OwnerHistory = owner_hist
    
    myProject.Name = "Test Grid"
    
    myProject.RepresentationContexts = [context]
    
    myProject.UnitsInContext = UnitAssignment
    
    
    
    
    # Defining site, building and first story ------------
    
    site_placement = ifc_file.createIfcLocalPlacement()
    
    site_placement.RelativePlacement=WorldCoordinateSystem
    
    mySite = ifc_file.createIfcSite( create_guid() )
    
    mySite.OwnerHistory = owner_hist
    
    mySite.Name = "My Site"
    
    mySite.ObjectPlacement = site_placement
    
    mySite.CompositionType="ELEMENT"
    
    
    building_placement = ifc_file.createIfcLocalPlacement()
    
    building_placement.PlacementRelTo = site_placement
    
    building_placement.RelativePlacement = WorldCoordinateSystem
    
    
    myBuilding = ifc_file.createIfcBuilding( create_guid(), owner_hist )
    
    myBuilding.Name = "Test Building"
    
    myBuilding.ObjectPlacement = building_placement
    
    myBuilding.CompositionType="ELEMENT"
    
    
    floor1_placement = ifc_file.createIfcLocalPlacement()
    
    floor1_placement.PlacementRelTo = building_placement
    
    floor1_placement.RelativePlacement = WorldCoordinateSystem
    
    
    floor1 = ifc_file.createIfcBuildingStorey( create_guid(), owner_hist )
    
    floor1.Name = "Floor 1"
    
    floor1.ObjectPlacement = floor1_placement
    
    floor1.CompositionType="ELEMENT"
    
    floor1.Elevation = 1000
    
    
    
    
    container_project = ifc_file.createIfcRelAggregates(create_guid() , owner_hist)
    
    container_project.Name="Project Container"
    
    container_project.RelatingObject = myProject 
    
    container_project.RelatedObjects = [mySite]
    
    
    container_site = ifc_file.createIfcRelAggregates(create_guid() , owner_hist)
    
    container_site.Name = "Site Container"
    
    container_site.RelatingObject = mySite
    
    container_site.RelatedObjects = [myBuilding] 
    
    
    container_storey = ifc_file.createIfcRelAggregates(create_guid() , owner_hist)
    
    container_storey.Name = "Building Container"
    
    container_storey.RelatingObject = myBuilding
    
    container_storey.RelatedObjects = [floor1] 
    
    
    
    
    #####################################################
    
    ###       Defining the grid axes geometry         ###
    
    #####################################################
    
    GridXList = [   {'id':'1' , 'distance':0.0 } ,
    
                    {'id':'2' , 'distance':4000.0}  ]
    
    
    GridYList = [   {'id':'A' , 'distance':0.0 } ,
    
                    {'id':'B' , 'distance':4000.0}  ]
    
    
    xMin = GridXList[0]['distance']-2000.0 ; xMax =  GridXList[-1]['distance']+2000.0 
    
    yMin =  GridYList[0]['distance']-2000.0 ; yMax =  GridYList[-1]['distance']+2000.0 
    
    
    
    
    polylineSet = []
    
    gridX = []
    
    for iGrid in GridXList:
    
        pnt1 = ifc_file.createIfcCartesianPoint( (iGrid['distance'],yMin) )
    
        pnt2 = ifc_file.createIfcCartesianPoint( (iGrid['distance'],yMax) )
    
        Line = ifc_file.createIfcPolyline( [pnt1 , pnt2] )
    
        polylineSet.append(Line)
    
        grid = ifc_file.createIfcGridAxis()
    
        grid.AxisTag = iGrid['id']
    
        grid.AxisCurve = Line
    
        grid.SameSense = True
    
        gridX.append(grid)
    
    
    gridY = []
    
    for iGrid in GridYList:
    
        pnt1 = ifc_file.createIfcCartesianPoint( (xMin ,iGrid['distance']) )
    
        pnt2 = ifc_file.createIfcCartesianPoint( (xMax,iGrid['distance']) )
    
        Line = ifc_file.createIfcPolyline( [pnt1 , pnt2] )
    
        polylineSet.append(Line)
    
        grid = ifc_file.createIfcGridAxis()
    
        grid.AxisTag = iGrid['id']
    
        grid.AxisCurve = Line
    
        grid.SameSense = True
    
        gridY.append(grid)
    
    
    # Defining the grid 
    
    PntGrid = ifc_file.createIfcCartesianPoint( O )
    
    
    myGridCoordinateSystem = ifc_file.createIfcAxis2Placement3D()
    
    myGridCoordinateSystem.Location= PntGrid
    
    myGridCoordinateSystem.Axis = axis_Z
    
    myGridCoordinateSystem.RefDirection = axis_X
    
    
    grid_placement = ifc_file.createIfcLocalPlacement()
    
    grid_placement.PlacementRelTo = floor1_placement
    
    grid_placement.RelativePlacement = myGridCoordinateSystem
    
    
    grid_curvedSet =  ifc_file.createIfcGeometricCurveSet(polylineSet)
    
    
    gridShape_Reppresentation = ifc_file.createIfcShapeRepresentation()
    
    gridShape_Reppresentation.ContextOfItems = footprint_context
    
    gridShape_Reppresentation.RepresentationIdentifier = 'FootPrint'
    
    gridShape_Reppresentation.RepresentationType = 'GeometricCurveSet'
    
    gridShape_Reppresentation.Items = [grid_curvedSet]
    
    
    grid_Reppresentation = ifc_file.createIfcProductDefinitionShape()
    
    grid_Reppresentation.Representations  = [gridShape_Reppresentation]
    
    
    myGrid = ifc_file.createIfcGrid(create_guid() , owner_hist)
    
    myGrid.ObjectPlacement = grid_placement
    
    myGrid.Representation = grid_Reppresentation
    
    myGrid.UAxes=gridX
    
    myGrid.VAxes=gridY
    
    
    # assignment to spatial structure ------------------------------------------ 
    
    container_SpatialStructure= ifc_file.createIfcRelContainedInSpatialStructure(create_guid() , owner_hist)
    
    container_SpatialStructure.Name='BuildingStoreyContainer'
    
    container_SpatialStructure.Description = 'BuildingStoreyContainer for Elements'
    
    container_SpatialStructure.RelatingStructure = floor1
    
    container_SpatialStructure.RelatedElements = [myGrid]
    
    
    
    
    file_path = "C:\\Algemeen\\07_prive\\08_ifc_bestanden\\"
    
    file_ifc = file_path  + file_name
    
    print (file_ifc)
    
    ifc_file.write(file_ifc)
    

    </details>

    How would I add the grid letter and number visibility in BlenderBIM? Like it is in BIMVision

  2. C

    @Coen Is it an idea to start putting Snippets found here on the wiki?

  3. T

    @CadGiru said:

    @Coen Is it an idea to start putting Snippets found here on the wiki?

    i like that idea. Posting them to our https://gitlab.com/osarch/Example_Files repo, i think would be a better idea.

    ...

    @Coen noob question, is there anyway to run a script like this in BB... and have the results show 'live' in the 3D viewport? That is, instead of running the script, creating the IFC file, and then importing the IFC into BB.

  4. C

    @CadGiru said:

    @Coen Is it an idea to start putting Snippets found here on the wiki?

    That is probably a good idea,

    @theoryshaw said:

    @Coen noob question, is there anyway to run a script like this in BB... and have the results show 'live' in the 3D viewport? That is, instead of running the script, creating the IFC file, and then importing the IFC into BB.

    Live interaction with BlenderBIM would be great. BIMVision has this feature when a change is detected in IFC it prompts you to load the new version. Would be cool if BlenderBIM could do the same. I don't know if this is hard thing to do. I should look into it, I vaguely remember someone already made this before....? Or I dreamt it.

  5. T

    How would I add the grid letter and number visibility in BlenderBIM? Like it is in BIMVision

    How to do it via the UI...

  6. C

    @theoryshaw

    @Coen noob question, is there anyway to run a script like this in BB... and have the results show 'live' in the 3D viewport? That is, instead of running the script, creating the IFC file, and then importing the IFC into BB.

    I was thinking about this, I think I'm almost there.

    You could just put this line at the end of your script:

    
    bpy.ops.bim.load_project(filepath=file_ifc)
    

    And then then store the timestamp in a temporary variable, I need to do some more research on where it's stored usally in IFC and catch the exceptions, I now do relatively dumb string parsing, which is not really fool proof...

    
    def get_timestamp():
    
        ifc_file = ifcopenshell.open(IfcStore.path)
    
    
        with open(IfcStore.path) as ifc_text:
    
            for line_no, line_file in enumerate(ifc_text):
    
                if line_no  == 3:
    
                    if line_file.startswith("FILE_NAME"):
    
                        time_stamp = (line_file.split(',')[1])
    
    
    
        print (time_stamp)
    
    
    
    
    
    
    
    get_timestamp()   
    
    
    
    bpy.ops.bim.reload_ifc_file()
    

    If the user clicks save project, or somehow it detects the ifc file is being overwritten. It should start comparing the time stamps, if a difference in time stampts is detected it should unload the old ifc and load the the new ifc.

  7. C

    Just created a little workaround, this works, but be very careful! it throws an entire blender collection away where the IFC is located. Only store things in IFC and don't save the Blender file.

    
    project = ifc_file.by_type('IfcProject')
    
    
    for i in project:
    
        collection_name = 'IfcProject/' + i.Name
    
    
    
    collection = bpy.data.collections.get(str(collection_name))
    
    
    
    for obj in collection.objects:
    
        bpy.data.objects.remove(obj, do_unlink=True)
    
    
    
    bpy.data.collections.remove(collection)
    
    bpy.ops.bim.load_project(filepath=file_ifc)
    

    If you copy paste this at the end of your IfcOpenShell python scripts it automatically load the IFC file in BlenderBIM (Taking it you're coding in BlenderBIM ofcourse)..

  8. T

    nice.. this noob will play around. :)

  9. C

    Seems to work... ?

  10. C
  11. T
  12. T

    @Coen a few suggestions here

    I removed IFCPRODUCTDEFINITIONSHAPE and IFCGEOMETRICCURVESET, since the native gridlines in BB don't have these entities associated with them.

    You might have had a good reason to include them, if so, please disregard. I'm mostly doing this for practice. :)

    Best, Ryan

  13. T

    It also looks like the IFCLOCALPLACEMENT is different. Not sure which one's right... local placement confuses me a little.

    In the create_grid_refactored_clean.py script...

    
      /*#101=IFCGRID('2dgA7o4TeHxRPiIF5$qabM',#5,$,$,$,#97,#100,(#46,#50,#54,#58),(#62,#66,#70,#74,#78,#82,#86,#90,#94),$,$);*/
    
        /*#97=IFCLOCALPLACEMENT(#38,#96);*/
    
          /*#38=IFCLOCALPLACEMENT(#32,#37);*/
    
            /*#32=IFCLOCALPLACEMENT(#26,#31);*/
    
              /*#26=IFCLOCALPLACEMENT($,#25);*/
    
                /*#25=IFCAXIS2PLACEMENT3D(#22,#23,#24);*/
    
                  /*#22=IFCCARTESIANPOINT((0.,0.,0.));*/
    
                  /*#23=IFCDIRECTION((0.,0.,1.));*/
    
                  /*#24=IFCDIRECTION((1.,0.,0.));*/
    
              /*#31=IFCAXIS2PLACEMENT3D(#28,#29,#30);*/
    
                /*#28=IFCCARTESIANPOINT((0.,0.,0.));*/
    
                /*#29=IFCDIRECTION((0.,0.,1.));*/
    
                /*#30=IFCDIRECTION((1.,0.,0.));*/
    
            /*#37=IFCAXIS2PLACEMENT3D(#34,#35,#36);*/
    
              /*#34=IFCCARTESIANPOINT((0.,0.,0.));*/
    
              /*#35=IFCDIRECTION((0.,0.,1.));*/
    
              /*#36=IFCDIRECTION((1.,0.,0.));*/
    
          /*#96=IFCAXIS2PLACEMENT3D(#95,#16,#14);*/
    
            /*#95=IFCCARTESIANPOINT((0.,0.,0.));*/
    
            /*#16=IFCDIRECTION((0.,0.,1.));*/
    
            /*#14=IFCDIRECTION((1.,0.,0.));*/
    
    

    In native BB....

    
    #60=IFCGRID('1FWhmuU9jB0u2KIDhbgjcq',$,'Grid',$,$,#71,$,(#72,#76,#80),(#84,#88,#92),$,$);
    
      /*#71=IFCLOCALPLACEMENT(#47,#70);*/
    
        /*#47=IFCLOCALPLACEMENT($,#46);*/
    
          /*#46=IFCAXIS2PLACEMENT3D(#43,#44,#45);*/
    
            /*#43=IFCCARTESIANPOINT((0.,0.,0.));*/
    
            /*#44=IFCDIRECTION((0.,0.,1.));*/
    
            /*#45=IFCDIRECTION((1.,0.,0.));*/
    
        /*#70=IFCAXIS2PLACEMENT3D(#67,#68,#69);*/
    
          /*#67=IFCCARTESIANPOINT((0.,0.,0.));*/
    
          /*#68=IFCDIRECTION((0.,0.,1.));*/
    
          /*#69=IFCDIRECTION((1.,0.,0.));*/
    
  14. C

    @theoryshaw

    Thanks for the info, I thought BlenderBIM had no curve support? But it seem to export succesfully.

    I am now placing beams on the grid as I seen in the code from @BIMrookie92

    Some screenshots of auto generated results:

    BlenderBIM is so insanely fast with creating an entire IFC model and loading it....When I click run script it almost creates the geometry instantly.

    Also make it easy to place columns along a grid,

  15. C

    @theoryshaw

    i'm curious how this could be codified in the IFC, to survive an IFC roundtrip.

    Me as well, the method I'm using now is just removing and rewriting the entire IFC in BlenderBIM. (seems to work, because BlenderBIM is insanely fast with loading an IFC).

    I made some little experiments with a IfcWall and IfcSlab, but I barely can't find any good Python documentation on how to create geometry with IfcOpenShell... Or maybe I am looking in the wrong places?. The only sources I used are the FreeCAD Forum, snippets from this forum and ifcopenshell academy. It's a lot of trial and error... and reading BuildingSmart documentation and logically trying to translate it to python code.

    Anyway some results:

    IfcWall placement moves if you change the slab thickness.

  16. C

    Next step, trying to create an IfcSlab through IfcOpenShell and add it to certain grid points. Probably worth another thread.

  17. T

    Imagine if IFC allowed us to do this?! :)

  18. C

    I managed to get a slab and beam system to move along with the grid, probaly in a stupid way but it works.

    Still don't know how to create a IfcWall from a curve2D in ifcopenshell. ?

  19. C

    Managed to create 1000 storey slabs. ?

    Just amazing how fast BlenderBIM is with creating and loading...

  20. C

    For now I finished playing around with ifcopenshell and python :-)

    Here is the refactored code:

    https://github.com/C-Claus/BlenderScripts/blob/master/BlenderBIMGrid/create_grid_with_slabs_and_building_stories.py

    Removed a lot of stupid mistakes and unnecessary variables. Tried to keep it as simple as possible

    Scripts allow for creation of grids/building storeys and IfcSlabs created in IfcOpenShell and loaded in BlenderBIM. I think it could maybe serve as a basis for other things? . I highly appreciate feedback :-).

    And a screenshot:

    Don't know if this is worth a youtube demo?

  21. N

    @Coen you do a lot of cool work, do the YouTube please. It helps people like me and closes off your mini project nicely

  22. C

    It's kind of a challenge to create as much geometry as possible with as little config parameters as possible

  23. N

    Hi @Coen this is cool, I downloaded the earlier code that makes the grids and builds the floors, thank you. Now I'm really interested in how the walls get built

  24. C

    @Nigel

    @Coen you do a lot of cool work, do the YouTube please. It helps people like me and closes off your mini project nicely

    Thanks, I made a youtube video.

    The code is to be found here.

    I tested it thoroughly, everything in this image should be easily adjustable through the python script, with the following parameters:

    
    filename                    = "demo.ifc"
    
    folder_path                 = "C:\\Algemeen\\07_prive\\08_ifc_bestanden\\"
    
    
    building_storeys_amount     = 2         # is the n number of building storeys, can't be 0 or less than 0
    
    elevation                   = 0.0       # is where the first of the building storeys start
    
    building_storey_height      = 3000      # is the equal distance between the building storeys
    
    
    
    grids_x_direction_amount    = 5        # is the n number of grids in x direction
    
    grids_y_direction_amount    = 5         # is the n number of grids in y direction
    
    grids_x_distance_between    = 1000.0     # is the distance between the x grids, always should be a float
    
    grids_y_distance_between    = 1000.0    # is the distance between the y grids, always should be a float
    
    grid_extends                = 2000.0    # is the distance on how much the grid extends
    
    
    slab_thickness              = 200.0  
    
    wall_interior_thickness     = 200.0
    
    wall_exterior_thickness     = 100.0
    
    wall_covering_thickness     = 150.0
    
    cavity_thickness            = 200.0
    
    slab_covering_thickness     = 150.0
    
    foundation_beam_height      = 1000.0
    

    I made this script because I wanted to learn ifcopenshell, the idea was it to keep it as simple as possible so end users could maybe one day make a parametric grid, building storey, walls, which are modular. Everything is referenced from the (0,0,0) point.

    I don't know where to take it from here, I could start coding an entire building with ifcopenshell, but the practicality of it seem to get lost.

    Plus the homemaker add-on from @brunopostle already does this way better :-).

    All the sources for the ifcopenshell code I uses were relatively old, forum posts from 2015 and such.

    But this code could serve to make a structural basis for modeling, or for people who want to learn ifcopenshell as I did myself.

  25. M

    This would be great to share on social media! By the way, IfcGridPlacement would be how to link objects to a grid's placement. However, it is not supported in IfcOpenShell.

  1. Page 1
  2. 2

Login or Register to reply.