placement of objects in ifc
i am trying to retrieve the coordinates of different types of objects in my model. for one type of objects, ifcopenshell.util.placement.get_local_placement() returns the actual placement within the model , while for all other objects it returns the origin. therefore, i tried to workaround using object.Representation[2][0][3][0][0][0][0]. Strangely, this returns the coordinates for all objects, where get_local_placement() does not work, while for the object type where it worked, it returns the origin. I am aware that this is most probably a modelling issue, but maybe someone has experienced something similar and can help out?
code example:
object type 1:
ifcopenshell.util.placement.get_local_placement(schwelle.ObjectPlacement)
Output:
array([[ 3.53002661e-01, -9.35588086e-01, -8.00344999e-03,
3.83472340e+02],
[ 9.35347713e-01, 3.53093378e-01, -2.12066600e-02,
1.77756250e+03],
[ 2.26666701e-02, -1.23988390e-09, 9.99743078e-01,
4.50623840e+02],
[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
1.00000000e+00]])
np.array(schwelle.Representation[2][0][3][0][0][0][0])
Output:
array([[0., 0., 0.]])
object type 2 (and all others):
ifcopenshell.util.placement.get_local_placement(schienen[0].ObjectPlacement)
Output:
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
np.array(schienen[0].Representation[2][0][3][0][0][0][0])
array([1213.69775, 1355.36921, 455.17992])
does anyone have suggestions as to why this could be? and how i could consistently handle objects and retrieve their coordinates?
thanks in advance
Comments
All objects with geometry require two bits of data:
For something like say a furniture table, the placement would typically be at the base of the table, perhaps at a corner or at the center of the table. The actual geometry's coordinates will be relative to the placement.
There is no rule requiring this placement to be at a particular point. It's equally technically valid for that placement to be at the center of the table, at a corner of the table, or 200km away in Wisconsin. Of course the latter is not really useful, but there you have it.
Some software choose to, for certain objects, not choose a point for this placement and typically leave it at 0,0,0 (or at some random point, which I've seen), which has no significance on the geometry of the object. It's not useful, but it's also not illegal. I'd raise this as a complaint to the vendor, but they may very well push back saying "it's technically allowed, we don't care what the 'placement' is".
The unfortunate side effect is that if you want to reliably determine "whereabouts" is my object, you need to be a little cleverer about it - maybe pick the first vertex, or find the average vertex XYZ, or a bounding centroid (see util.shape module). To do this I'd use the geometry iterator then the util.shape module to get a centroid.
This is general advice and applies not just to IFC, but pretty much any 3D geometry out there in the world, quite a lot have this separation between 'local origin' and 'geometry'. E.g. in Blender it would be the matrix_world and data.vertices for meshes.
thanks for clarifying!
i understand that the get_local_placement(xxx.ObjectPlacement) is not a reliable way to retrieve the location of objects if the insertion points of objects are not consistently the corner or similar of the objects. could you tell me what xxx.Representation[2][0][3][0][0][0][0] is exactly? and why with it returns #26=IfcCartesianPoint((0.0,0.0,0.0)) for one type of object and (400.28169, 1772.00751, 450.64455) for another type of object (consistently across the model)?
i tried your suggestion using geometry iterator, have never used it before:
runs but does not print anything.
using create_shape:
yields Runtime Error: Failed to process shape.
Sorry, I'm relatively new to this (as you can imagine).
xxx.Representation[2][0][3][0][0][0][0]
is getting the representation's 2nd, the 0th, then 3rd, etc argument. Exactly why this magic sequence works is specific to your file and your file only. It's not something you can rely on. It may even only work on that one particular element - it depends on how the geometry is stored. You're basically accessing data by index, which is not guaranteed to be the same everywhere.It's probably failing because it uses one of the newer IFC4X3 geometry types. You may have an older version on IfcOpenShell that does not have that capability. Where / how did you install IfcOpenShell?
I've installed ifcopenshell 0.7.10 using pip. I've installed it in a virtual environment.