OSArch Community

IfcOpenShell Python - Calculate Quantities

  1. A

    Hi everyone,

    Still working on a script that exports main quantities to csv. By now, I am working on calculating basic quantities (volume, area, lenght, width...) of walls, slabs, beams...

    I saw there was a script here that does exactly what I want but it seems it doesn't work if ifc isn't opened in BlenderBIM (which is what I need) ? (QtoCalculator().get_net_volume() tries to access object.data source here)

    Am I right ? Is there a way to achieve what I want without using FreeCAD as I saw here ?

    Thanks a lot !!

  2. M

    Hello @arthur595 , i saw that you pointed to my old script, so here i am :-)

    That script is the old script i created but now it's replaced by the the operator that you can find in n-panel under BlenderBim->Quantity Take Off-> Calculate All Quantities (if you want of course to calculate all quantities).

    Btw, your problem is to run that operator (or a qto_calculator function) without actually run the blender ui, right? I think that is possible, because, for example, tests run blender headlessy so maybe if you import the proper libraries you can do that. Of course, the object you are trying to calculate has to be a blender obj... This is all that i know...

  3. A

    Thanks @Massimo , I didn't know it had been updated and integrated to the UI, I'll check it out !

    And yes, indeed I would like to run my script without having to load my IFC into Blender. I'll keep searching for libraries, if you or anyone has some info about it, I'll take it :-)

    Thx

  4. M
  5. A

    Actually, my main goal is to avoid importing the IFC to Blender because it can be long in some cases. If I run Blender headless as you suggest, I would still have to import it ? (it would be a bit faster because Blender wouldn't have to render graphics).

    What I don't understand is why this operator (the qto_calculator) needs to have the file imported ? I know it uses the geometry of the objects (vertices, edges and faces) but this data actually exists inside the IFC file, right ? A wall is defined by points inside the IFC file, each point has an (X,Y,Z) position stored too.

    There should be a way to do all this math with only this data ?

    What if I decide to accept losing a bit of time importing IFC to Blender (even with the UI), what is the appropriate python code to use this operator : BlenderBim->Quantity Take Off-> Calculate All Quantities ?

    Sorry for all my questions, but I am a bit confused ! Answer what you can :-)

  6. A

    why not directly from ifcopenshell api

    qto = ifcopenshell.util.element.get_psets(element, qtos_only=True)

  7. A

    Hi @Arv ,

    Yes I tried this one but it only works if psets are exported to the IFC file. I am trying to make this script to be able to get quantities from any IFC we receive from clients. Sometimes, IFC are very poor and they don't contain any pset.

    That's why I am trying to calculcate this data. But I will definitely check if there is a pset for quantities and use it before doing all the math ;)

  8. A
  9. A
  10. A

    If anyone is interested in this, I am working on recreating the base function to guess length, area and volume from IFC Element shapes.

    This is what I have by the end of the day for volume calculation, but I think it doesn't work properly (inspired by this)

    def SignedVol(shape, firstIndex_p1, firstIndex_p2, firstIndex_p3):
    
        vertices = shape.geometry.verts
    
    
    
        p1 = (vertices[3*firstIndex_p1], vertices[3*firstIndex_p1+1], vertices[3*firstIndex_p1+2])
    
        p2 = (vertices[3*firstIndex_p2], vertices[3*firstIndex_p2+1], vertices[3*firstIndex_p2+2])
    
        p3 = (vertices[3*firstIndex_p3], vertices[3*firstIndex_p3+1], vertices[3*firstIndex_p3+2])
    
    
    
        v321 = p3[0] * p2[1] * p1[2]
    
        v231 = p2[0] * p3[1] * p1[2]
    
        v312 = p3[0] * p1[1] * p2[2]
    
        v132 = p1[0] * p3[1] * p2[2]
    
        v213 = p2[0] * p1[1] * p3[2]
    
        v123 = p1[0] * p2[1] * p3[2]
    
    
    
        return (-v321 + v231 + v312 - v132 - v213 + v123)/6
    
    
    
    
    def VolMesh(elem):
    
        shape = geom.create_shape(settings , elem )
    
        faces = shape.geometry.faces
    
    
    
        faceCount = int(len(faces)/3)
    
        print(faceCount)
    
    
    
        totVolList = []
    
    
    
        for i in range(faceCount):
    
            totVolList.append(SignedVol(shape, faces[i],faces[i+1],faces[i+2]))
    
        print(totVolList)
    
        return sum(totVolList)
  11. M
  12. M

    What if I decide to accept losing a bit of time importing IFC to Blender (even with the UI), what is the appropriate python code to use this operator : BlenderBim->Quantity Take Off-> Calculate All Quantities ?

    So, in order to know the exact command to execute, it's sufficient to right click on the operator button (in blender ui) and put the mouse over the "edit source" with the option "python tooltips" activated in blender preferences (submenù interface). In this way you know the command for every operator.

    In this case the command is _bpy.ops.bim.calculate_allquantities()

    Looking at the qto_calculator functions, basically, in order to calculate the quantities (volume, length, height, etc...) qto_calculator uses blender functions or bmesh or shapely, etc.. but it's always needed the blender object to perform the calculations.

    But i think that what you are attempting to do is doable.

    For example, the trick i've done to calculate the gross volume was to recreate another blender object from ifc entity without openings and, in order to do that, i used the ifcopenshell geom functions. Look at this and also the documentation of course.

    Keep going btw, i'm also interested in what you are doing because this could be the beginning of a "native ifc" quantity takeoff method :-)

  13. A

    Thank you @Martin156131 , I'll take a look !

    So, in order to know the exact command to execute, it's sufficient to right click on the operator button (in blender ui) and put the mouse over the "edit source" with the option "python tooltips" activated in blender preferences (submenù interface). In this way you know the command for every operator.

    I didn't know that, very usefull thx @Massimo !

    I am still wondering where is the link between the wall object I see in my Blender UI and the ifc wall object defined by wall = model.by_type("IfcWall")[0].

    How do I switch from one to another ?

    Anyway, I'll keep working on that, thanks for your support !

  14. M

    @arthur595 with script, if obj = bpy.context.active_object you can use entity = blenderbim.tool.Ifc.get_entity(obj) to get the ifc entity from obj.

    There is also the function blenderbim.tool.Ifc.get_object(entity) to do the inverse

  15. M
  16. M
  17. A

    Thx @Moult very usefull indeed, I am able to do what I want with your logic and code !

    I am still doing some adjustements and I'll try to post my final code on Github ! maybe even my excel dynamic tables if I manage to do smthg ok :-)

  18. C

    Slightly related to this thread

    How do you get the NetSideArea of an IfcWall using qsets = ifcopenshell.util.element.get_psets(ifc_product, qtos_only=True) ?

    I tried it on the schependomlaan.ifc as following, but I think I'm using this function in an extremely stupid way:

    
        qsets = ifcopenshell.util.element.get_psets(ifc_product, qtos_only=True)
    
    
        if (qsets.keys()):
    
            for keys in (qsets.keys()):
    
                if keys == 'BaseQuantities':
    
                    for keys_quantity in (qsets['BaseQuantities'].keys()):
    
                        print (keys_quantity)
    
                        if str(keys_quantity) == 'NetSideArea' :
    
                            print (keys_quantity)
    

    Couldn't find any documenation.

  19. M

    @Coen ifcopenshell.util.element.get_psets(ifc_product, qtos_only=True) returns a dictionary so, if you assign it to qsets, you can get the values with qsets[qto_name][quantity_name].

    In your example you can use qtos['BaseQuantities']['NetSideArea'].

    You can use also ifcopenshell.util.element.get_pset(ifc_product, 'BaseQuantities')['NetSideArea'] that documentation says is more efficient than .get_psets. A tip, if you use blender python console, you can use tab key right after ( to see the documentation about that function.

    Btw, please note that IFC provides a QtoPset with official quantities and the name begins with 'Qto'.

    In your example, the 'NetSideArea' should be stored in a pset called 'Qto_WallBaseQuantities'

  20. M

    There is now a more direct ifcopenshell.util.element.get_pset(ifc_product, "BaseQuantities", "NetSideArea") which immediately fetches the property / quantity instead of needing to manage a full dictionary and check for existence.

  21. A

    Hello,

    Back with some good news ! I have managed to get a first working prototype. For now, I did the most difficult part which is calculating quantities based on the geometry. We could imagine checking if psets already contains the data we need (as Moult just explained) before calculating.

    As promised, here is the files I used !

    Sorry I am not comfortable with Github, that's why I created a zip file. (feel free to use and share this as you wish, if anyone wants to post this to Github i'll be honored)

    This zip file contains :

    • Python script to extract quantities

    • IFC example file I used to extract data

    • Excel file to process data

    [EDIT]

    Just added this to github : https://github.com/arthur-bellemin/ifcopenshell

    Here is an example of what I can get with a larger model. I did compare with the quantities from Revit, it is quite accurate (I would say about 2% diff for length and areas, and less than 1% for volume).

  22. C

    @arthur595

    For now, I did the most difficult part which is calculating quantities based on the geometry. We could imagine checking if psets already contains the data we need (as Moult just explained) before calculating.

    Nice! If I understand you correctly, the script checks for existing quantities in psets, if they are not present it's going to calculate the quantities from the geometry and assign them to psets? So let's say someone export a Revit model to IFC in which the 'BaseQuantities' are not exported your script can quantify it from geometry ?

  23. A

    @Coen said:

    Nice! If I understand you correctly, the script checks for existing quantities in psets, if they are not present it's going to calculate the quantities from the geometry and assign them to psets? So let's say someone export a Revit model to IFC in which the 'BaseQuantities' are not exported your script can quantify it from geometry ?

    Not exactly, The script doesn't check for existing quantities in pset (I may improve this later). It does quantify the base quantities from geometry, so wether or not your IFC file contains quantity psets, it will process elements'geometry to determine quantities.

    Updated with github link, hope it works :-)

  24. M

    @arthur595 very interesting! It would be nice also to confront the results with calculated quantities given by blenderbim (qto_calculator) and yours ...

    also, do you know that there is an awesome addon that export properties to excel, right? :-)

  25. A

    @Moult said:

    There is now a more direct ifcopenshell.util.element.get_pset(ifc_product, "BaseQuantities", "NetSideArea") which immediately fetches the property / quantity instead of needing to manage a full dictionary and check for existence.

    @Moult The latest conda-forge version of ifcopenshell doesn't have ifcopenshell.util.element.get_pset yet. I guess compared to conda, the pypi versions are updated much faster, is that so?

  1. Page 1
  2. 2
  3. 3

Login or Register to reply.