[Python][IfcOpenShell][BlenderBIM] Using an edge mesh to create IfcWallType instances

I have drawn a random mesh in blender like so:

Found this script wich gets the coordinates from the mesh:

import bpy, bmesh
obj = bpy.context.active_object

if obj.mode == 'EDIT':
    # this works only in edit mode,
    bm = bmesh.from_edit_mesh(obj.data)
    verts = [vert.co for vert in bm.verts]

else:
    # this works only in object mode,
    verts = [vert.co for vert in obj.data.vertices]

# coordinates as tuples
plain_verts = [vert.to_tuple() for vert in verts]
print(plain_verts)

It returns a list of coordinates

... truncated[(9.0, 0.0, 0.0), (9.0, 7.0, 0.0), (5.0, 7.0, 0.0), (5.0, 8.0, 0.0), (0.0, 8.0, 0.0), (0.0, 0.0, 0.0), (-2.0, 4.0, 0.0)]

I would like these coordinates to place IfcWallType instances from the IFC4 Demo Library,
When creating a new IFC project I see the following command

bpy.ops.bim.assign_class(   obj="Wall", 
                            ifc_class="IfcWall",
                            ifc_representation_class="IfcExtrudedAreaSolid/IfcArbitraryClosedProfileDef")

Which places a wall instance at the origin point. I can't find programmaticaly how to place a lot of walltype instances with this list of coordinates, or if it's even possible? How would the script now where to place the wall? I take it from each vertice coordinates? Then how would the script know where to stop?

theoryshaw

Comments



  • Almost there, I think I need to order the vertices...?
    This is what I came up with so far in general.

    def create_wall(coordinates, building_storey_height):
        print ("create wall")  
    
        extrusion=(building_storey_height)
        elevation = (building_storey.Elevation)
    
        ifc_wall    = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcWall", name="wall_from_edge" )
        ifc_walltype= ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcWallType")
        ifcopenshell.api.run("type.assign_type", ifc_file, related_object=ifc_wall, relating_type=ifc_walltype) 
    
        coordinate_list = []
        for coordinate in coordinates:
            point = ifc_file.createIfcCartesianPoint( (coordinate))
            coordinate_list.append(point)
    
        wall_line    = ifc_file.createIfcPolyline(coordinate_list)
        ifcclosedprofile = ifc_file.createIfcArbitraryClosedProfileDef("AREA", None, wall_line) 
        ifc_direction    = ifc_file.createIfcDirection(Z)
    
        point = ifc_file.createIfcCartesianPoint((0.0,0.0,0.0))
        dir1 = ifc_file.createIfcDirection((0., 0., 1.))
        dir2 = ifc_file.createIfcDirection((1., 0., 0.))
    
        axis2placement = ifc_file.createIfcAxis2Placement3D(point, dir1, dir2)
        wall_solid = ifc_file.createIfcExtrudedAreaSolid(ifcclosedprofile,  axis2placement, ifc_direction, extrusion)
    
    
    
        shape_representation    = ifc_file.createIfcShapeRepresentation( ContextOfItems=context,
                                                                        RepresentationIdentifier='Body', 
                                                                        RepresentationType='SweptSolid',
                                                                        Items=[wall_solid])
    
    
        ifcopenshell.api.run("geometry.assign_representation", ifc_file, product=ifc_walltype, representation=shape_representation)
        ifcopenshell.api.run("spatial.assign_container", ifc_file, product=ifc_wall, relating_structure=building_storey) 
    
    create_wall(coordinates=plain_verts, building_storey_height=3.0)  
    
    
    theoryshaw
  • edited September 2022

    found the following script on the internets, to reorder vertices

    obj = bpy.context.active_object
    
    def reordered(bm):
        f = bmesh.ops.contextual_create(
                bm,
                geom=bm.verts[:] + bm.edges[:],
                )["faces"][0]
    
        for i, v in enumerate(f.verts):
            v.index = i
        bm.verts.sort()
        bm.faces.remove(f)
        return bm
    
    if obj.mode == 'EDIT':
        # this works only in edit mode,
        bm = bmesh.from_edit_mesh(obj.data)
        reordered(bm)
        verts = [vert.co for vert in bm.verts]
    else:
        # this works only in object mode,
        reordered(bm)
        verts = [vert.co for vert in obj.data.vertices]
    
    Coen
  • I think that the natural way to draw a wall in blenderbim should be to draw vertical faces rather than horizontal lines:

    1. Collections of blender lines don't have any 'direction'. You can string them together programmatically, but walls have inside and outside, so you want to control the direction.
    2. Faces in blender have a normal direction, the inside and outside is implicit
    3. Not all walls have horizontal tops and bottoms, attics, under stairs, stepped footings etc.. in IFC this should be represented by a simple vertically extruded wall with half space clipping at the top and bottom. I can't imagine any intuitive way of specifying these clipping solids directly. But deriving them from a face geometry is doable.
    theoryshawCoen
    1. This is how it works in the Homemaker add-on. It probably doesn't make sense to transfer all the Homemaker functionality into blenderbim, but this is an obvious one.
    Coen
Sign In or Register to comment.