[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:
representation
variable? Is it what you expect?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:
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.
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):
With print(self.placement):
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.
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:
Represantation:
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:
@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! :)