If you're reading this, we've just migrated servers! If anything looks broken please email dion@thinkmoult.com :)

IfcOpenShell: create face with interior holes

Hi all,
I have some problems with creating geometry in IfcOpenShell & thought maybe some of you could help me. Here's the problem:

I have a face with one or more interior holes (as a python list of lists, where the first list corresponds to the outer boundary and the others are all interior holes). In the case of the figure, it looks like: [[1,2,3,4],[5,6,7,8],[9,10,11,12]]. I'd like to convert that to a IfcFace.

The code now looks like this. IFC_vertices is a dictionary of IfcCartesianPoints based on the vertex index.

IFC_model = ifcopenshell.open("ifcmodel.ifc")
face = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
cartesian_points = []
for vertex in face[0]:
    cartesian_points.append(IFC_vertices[vertex])
polyloop = IFC_model.create_entity("IfcPolyLoop", Polygon=cartesian_points)
outerbound = IFC_model.create_entity("IfcFaceOuterBound", Bound=polyloop, Orientation=True)  # orientation of vertices is CCW
innerbounds = []
for interior_face in face[1:]:
    for vertex in interior_face:
        cartesian_points.append(IFC_vertices[vertex])
    polyloop = IFC_model.create_entity("IfcPolyLoop",  Polygon=cartesian_points)
    innerbounds.append(IFC_model.create_entity("IfcFaceBound",  Bound=polyloop, Orientation=False))  # orientation of vertices is CW 
IFC_model.create_entity("IfcFace", Bounds=[outerbound] + innerbounds)

I thought it was pretty straightforward this way, as it is explained in the BuildingSMART documentation. But there is definitely something wrong with the IfcFaceBounds / IfcOuterFaceBounds. Here's an output of such a case in BlenderBIM (likely not a bug there because in Solibri it looks similar):

Is there any IFC/IfcOpenShell hero that knows what went wrong in the code?

Tagged:

Comments

  • Output of this building can be found in following file

  • edited November 2021

    Blender's mesh system does not allow holes in geometry polygons. A face must have at most one continuous edge ring. See https://blender.stackexchange.com/a/33325/86891 Solibri might work the same way. The solution is to add edges to cut the face so there is at most one continuous edge ring.
    Note that using a 2D curve with multiple loops does the job quite well as hinted in the BSE question.
    There might be a case here to automatically tidy up the mesh when translating from ifc to bmesh ? but the result may not be consistent so I don't know if we'd be able to ensure no data is lost or modified when importing / exporting.

    LaurensJN
  • @LaurensJN I only quickly skimmed through but can you confirm cartesian_points.append(IFC_vertices[vertex])? Note that face indices start from 1 (which it looks like you have) but python indices start from 0.

    LaurensJN
  • @Moult indices here are for simplicity & visualisation. The cartesian_points are actually built using CJIO indexing. Faces are also correctly displayed if there are no holes, so I don't think there are problems there.
    @Gorgious that might be the problem. The solution there is blender-based, but I need a solution for IFC files, because I just use BlenderBIM to import the faces. @Moult do you know if BlenderBIM could possibly have problems with handling IfcFaces with holes?

    I will check if I could easily add the closest vertex on the boundary to each polyloop, maybe that could solve the problem (in the easy example 4/6 and 2/12).

  • I found the mistake... I didn't empty cartesian_points each loop in the interior_face, so that produces some weird outputs. Bad news: I wasted my whole sunday on this single line. Good news: cityjson files converted to IFC can now have their accurate representation :)

    GorgiousAceCadGiruMoult
Sign In or Register to comment.