[IfcOpenShell-Python] How to convert many obj files to an ifc file?

So we have this script which can create from one obj file an ifc file.

I did a little modification, so this script load several obj file from a directory.
Here the modified script.
and here four example cubus.obj files in a directory. The four cubus have different location.
The main function that i added to the script:

 def load_several_obj_files(self):
        p = Path(self.path_to_dir)
        list_of_obj_files = list(p.glob("*.obj"))
        print(list_of_obj_files)
        for obj_file in list_of_obj_files:
            self.mesh_set.load_new_mesh(str(obj_file))

Unfortunately i got a error, when i tried out :(
Here the error Message:

Traceback (most recent call last):
  File "C:\Users\Martin\objstoifc_meshlab.py", line 145, in <module>
    obj2ifc.execute()
  File "C:\Users\Martin\objstoifc_meshlab.py", line 83, in execute
    product = self.file.create_entity(
  File "C:\Users\Martin\miniforge\miniforge\envs\pyifc\lib\site-packages\ifcopenshell\file.py", line 276, in create_entity
    e[idx] = arg
  File "C:\Users\Martin\miniforge\miniforge\envs\pyifc\lib\site-packages\ifcopenshell\entity_instance.py", line 196, in __setitem__
    self.method_list[idx](self.wrapped_data, idx, entity_instance.unwrap_value(value))
  File "C:\Users\Martin\miniforge\miniforge\envs\pyifc\lib\site-packages\ifcopenshell\ifcopenshell_wrapper.py", line 4867, in setArgumentAsEntityInstance
    return _ifcopenshell_wrapper.entity_instance_setArgumentAsEntityInstance(self, i, v)
RuntimeError: An unknown error occurred

Does someone has a solution? In this particular case, how to create from four cubus obj files one ifc file.

Comments

  • The error means that assigning one of the entity instances failed. So the error is likely related to L88 or L89. At a guess L89 is more likely since it depends on input data. Things to try debugging:

    1. Does it work with one OBJ file, not all?
    2. What is the value of the representation variable? Is it what you expect?
    Martin156131
  • Thanks for the input @Moult
    So first i did test each cubus.obj file, can i create an ifc with the unmodified script.
    it was possible, see here:

    And then i tried to inspect the representation variable by introducing a print statement before the create_entity function, see here:

    So so i could interpret the error message:

    #111=IfcProductDefinitionShape($,$,(#110))
    #196=IfcProductDefinitionShape($,$,(#195))
    Traceback (most recent call last):
    File "C:\Users\Martin\obj2ifc4_meshlab.py", line 148, in
    obj2ifc.execute()
    File "C:\Users\Martin\obj2ifc4_meshlab.py", line 86, in execute
    product = self.file.create_entity(
    File "C:\Users\Martin\miniforge\miniforge\envs\pyifc\lib\site-packages\ifcopenshell\file.py", line 276, in create_entity
    e[idx] = arg
    File "C:\Users\Martin\miniforge\miniforge\envs\pyifc\lib\site-packages\ifcopenshell\entity_instance.py", line 196, in setitem
    self.method_list[idx](self.wrapped_data, idx, entity_instance.unwrap_value(value))
    File "C:\Users\Martin\miniforge\miniforge\envs\pyifc\lib\site-packages\ifcopenshell\ifcopenshell_wrapper.py", line 4867, in setArgumentAsEntityInstance
    return _ifcopenshell_wrapper.entity_instance_setArgumentAsEntityInstance(self, i, v)
    RuntimeError: An unknown error occurred

    the error occurred by the second call of the create_entity function.

    so I did investigate the L88, because it was clear the representation was correct.
    so i changed the statement from "ObjectPlacement": self.placement to "ObjectPlacement": None
    Suprisingly now it created my ifc with the four cubes:

    However i don't understand, why "ObjectPlacement": self.placement created such a problem.

  • The next step would be to inspect the value of self.placement then :) Let me know what you find.

  • edited August 2022

    As you asked @Moult, here is my analysis:
    The self.placement is created once in the function cerate_ifc_file: see here

    So my guess was, each time a new entity was created, it would take the same statement. To control that, i created another print statement:

    Without the print(self.placement):

    #111=IfcProductDefinitionShape($,$,(#110))
    #196=IfcProductDefinitionShape($,$,(#195))
    Traceback (most recent call last):
    File "C:\Users\Martin\obj2ifc4_meshlab.py", line 148, in
    obj2ifc.execute()
    File "C:\Users\Martin\obj2ifc4_meshlab.py", line 86, in execute
    product = self.file.create_entity(
    File "C:\Users\Martin\miniforge\miniforge\envs\pyifc\lib\site-packages\ifcopenshell\file.py", line 276, in create_entity
    e[idx] = arg
    File "C:\Users\Martin\miniforge\miniforge\envs\pyifc\lib\site-packages\ifcopenshell\entity_instance.py", line 196, in setitem
    self.method_list[idx](self.wrapped_data, idx, entity_instance.unwrap_value(value))
    File "C:\Users\Martin\miniforge\miniforge\envs\pyifc\lib\site-packages\ifcopenshell\ifcopenshell_wrapper.py", line 4867, in setArgumentAsEntityInstance
    return _ifcopenshell_wrapper.entity_instance_setArgumentAsEntityInstance(self, i, v)
    RuntimeError: An unknown error occurred

    With print(self.placement):

    #111=IfcProductDefinitionShape($,$,(#110))
    #34=IfcLocalPlacement($,#33)
    #196=IfcProductDefinitionShape($,$,(#195))

    So i didn't expect that behavior, when run the script without the print(self.placement), it created an error by the create_entity line, however with the print(self.placement), it coudln't print the self.placement in the second round and the script stopped without an error. in both run it was with "ObjectPlacement": self.placement.
    I don't know why this happens.

  • edited August 2022

    So i read know the technical documentation from builingSmart, however i didn't understand what's the problem:
    Here under IfcProduct are the two attributes ObjectPlacement and Representation explained. So that the Representation are the geometric information and the ObjectPlacement is relative to whom the ifc_entity is placed in space:
    ObjectPlacement:

    Placement of the product in space, the placement can either be absolute (relative to the world coordinate system), relative (relative to the object placement of another product), or constraint (e.g. relative to grid axes). It is determined by the various subtypes of IfcObjectPlacement, which includes the axis placement information to determine the transformation for the object coordinate system.

    Represantation:

    Reference to the representations of the product, being either a representation (IfcProductRepresentation) or as a special case a shape representations (IfcProductDefinitionShape). The product definition shape provides for multiple geometric representations of the shape property of the object within the same object coordinate system, defined by the object placement.

    However the script with the statement "ObjectPlacement": None did function, however that should not be the case?

    And how in this interaction comes the IfcProjectedCRS to play? I did not understand this connection.
    IfcProjectedCRS:

    IfcProjectedCRS is a coordinate reference system of the map to which the map translation of the local engineering coordinate system of the construction or facility engineering project relates. The MapProjection and MapZone attributes uniquely identify the projection to the underlying geographic coordinate reference system, provided that they are well-known in the receiving application. The projected coordinate reference system is assumed to be a 2D or 3D right-handed Cartesian coordinate system, the optional MapUnit attribute can be used determine the length unit used by the map.

  • @Martin156131 "stopping without an error" means it crashes. Maybe the crash isn't obvious in your IDE. The reason is that self.placement is a reference to a local placement. However, you call spatial.assign_container to assign the product to be relative to the storey. This means that the placement (previously referenced by self.placement) needs to change to be relative to the coordinates of storey. This placement may either change in place, or be deleted and new coordinates added. In this case, it's the latter, which is why the second time you run the loop, self.placement no longer points to any valid value.

    The solution is either to take the assign_container call into a separate loop, or don't try to reuse self.placement, and instead generate fresh coordinates each time.

    I also noticed on L93 that self.path doesn't exist.

  • I see, in your script at https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.7.0/src/blenderbim/scripts/obj2ifc-meshlab.py, because of line 82 with ifcopenshell.api.run("spatial.assign_container", self.file, product=product, relating_structure=self.storey) the line 78 with "ObjectPlacement": self.placement is not needed right? Can't we just delete than the line 78, if the object placement is already regulated by line 82?

    Ps: You need tp change on line 96 org.Id = None to org[0] = None ?

  • L82 simply changes what the object placement is relative to, but doesn't add a blank ObjectPlacement, so L78 is still needed.

    Thanks for the tip on org[0], that's now been fixed! :)

Sign In or Register to comment.