Remove IfcSpaces with IfcOpenShell
I was hoping to get rid of the ifcspaces in a ifc exported from ArchiCad which I would like to link in to Revit. I tried this simple code:
import ifcopenshell
f = ifcopenshell.open(ifc_path)
for space in f.by_type("ifcspace"):
f.remove(space)
But it seems like the basement needet the spaces to end up in the correct location.
Is there any way to check if it is safe to delete an ifcspace element? I guess the best way to start is to figure out how the basement is dependent on the spaces to get the correct elevation.
Tagged:
Comments
You are correct that elements may be contained within a space, and therefore inherit their local relative placement. Would you like to have a shot at coding this? If not, I can show you how to do it.
Also, would you be interested in contributing the script as an IfcPatch recipe? That way in the future all users can easily use your script if they want to remove spaces.
It looks like some of the elements are contained in storeys and some in spaces. I used
element.ContainedInStructure
which I think returns the IfcRelContainedInSpatialStructure object. Should we replace the spaces with storeys? I would love to see the solution to this, because at this point i'm just confused :D.I will be happy to contribute a recipe if I can figure out how.
Yep! Elements can be contained in any spatial element, like a space, or a storey, or a building, etc. The spatial element can also be contained in other spatial elements. This creates a "spatial tree", like Site > Building > Storey > Space > Wall (Element). So if you want to remove the Space, you need to make the wall inside the storey. The next thing you'll need to modify is the
ObjectPlacement
of the element (wall, in this example). The object placement may be aLocalPlacement
. If it is, it is placed relative to the placement of the space, which is relative to the storey, etc all the way back to Site. As you see - the spatial tree is represented twice: once in the contained in structure / aggregation relationship, and another in the relative local object placements.Hope it made sense :) Let me know if you need more hints!
Thanks! How do I get the parent of the IfcSpace? It does not have the "ContainedInStructure" property as the IfcProducts like IfcWall?
@Einar when an element is contained in a spatial element, it uses
ContainedInStructure
, see here. However, when a spatial element is contained in another spatial element, it usesDecomposes
, see here.Yes, agree that it seems a little odd to have two very similar relationships split into two... but :)
I tried with Decomposes too, but the result is not making sense to me:

Sorry, I missed the difference between

RelatingObject
andRelatedObjects
Good to hear you worked it out! A method I use to remember is that when parts (many) are aggregated into a whole (one), it's a many-to-one relationship. So it's RelatedObjects for the many parts, and RelatingObject for the one whole :)
I was hoping to be able to iterate trough all IfcSpace's and use
IsDecomposedBy
to find all elements assigned to it, but since it is empty do I have to iterate throgh all IfcElements and find the spaces viaContainedInStructure[0].RelatingStructure
?To answer my self again: I guess "the inverse" of
wall.ContainedInStructure[0].RelatingStructure
isspace.ContainsElements[0].RelatedElements
Task 1) "Change spatial container of elements from space to bulding storey" is complete:
Next challenge is the ObjectLocation...
Here is what I think i need to do, in this example a wall which is placed relative to a space.
ObjectPlacement
RelativePlacement
PlacementRelTo
RelativePlacement
What I don't understand is this: When the IfcSpace is deleted, the corresponding IfcLocalPlacement is not. Why would deleting the IfcSpace affect the position of the IfcWall?
Regarding your code snippet, I'd recommend removing the check for building storey - as it may be a building storey, but could be also a different type of spatial element, like an IfcBuilding.
You are correct that deleting the space shouldn't have an impact on the wall placement, since the wall is placed relative to the a local placement that is not deleted. Does it work?
The reason I recommended replacing the coordinates was because there is an old IFC2X3 implementer agreement that says the spatial tree should mirror the local placement tree. This agreement is now no longer applicable, but... just in case an application expects it...
It didn't work in Solibri. No difference between just deleting the spaces and changing elements containers from space to storey before deleting the spaces.
@Einar perhaps I can take a look at your full script and file to help debug? Also up for a screenshare - I'm available on IRC live chat at https://blenderbim.org/community.html
I finally found some time and energy to look at this again. Here is the full script so far. Messing with the locations made this even worse, I guess I need to figure out how I can merge two RelativePlacements with different RefDirections. @Moult I can send the file if you want to take a quick look, but Mozilla send seems to be taken down.
For a simple 2D-case It seems like this rotation matrix is giving me the expected result:
But the same function implemented in the complete script widely scatters the model in Solibir:
@Einar sorry for the delay in replying. Here's some code which simply swaps the spatial container. It seems to work for me:
Thank you very much for the answer, I really appreciate all the work you are doing here.
The swapping part works for me too, but if I go one step further and delete the spaces from the file, the basement of the building drops down in Solibri. Then I started to mess around with the local placements in case Solibri is following the "implementers agreement" you mentioned.
Anyways, the specific case I want to solve is this:
@Einar the following works for me.
It's probably a Solibri Bug then. I used exactly the same code as you and got this in Solibri:

@Einar can you try with XBIM Xplorer, which is what I tested with?
It works both in Xbim Xplorer and Revit, which after all was the main goal.
I guess this is the convention you mentioned earlier? Is this also saying that ArchiCads behavior with placement relative to IfcSpace is not correct?
from: IFC2x3/TC1/HTML/ifcgeometricconstraintresource/lexical/ifclocalplacement.htm
@Einar I see. That is indeed the convention (there is actually another document reference, but it's not important), but I would hesitate saying it's a bug with XBim Xplorer, as the implementer agreement is only valid for IFC2X3, but not IFC4. Your file is IFC2X3, so one could argue that XBim Xplorer is "allowed" to interpret it that way. It's not ideal, but it is an excuse. I'm curious if the same behaviour occurs for IFC4, and also curious why only the bottom storey dropped out but all other storeys remained correct.
I don't see any bug with ArchiCAD. What makes you think ArchiCAD did something wrong?
Simply because IfcSpace (edited) isn't among the classes listed in the paranthesis above
(IfcSite, IfcBuilding, IfcBuildingStorey)
. It's probably not wrong, but depends on how we choose to interpret the convention.@Einar do you mean
IfcSpace
? If so,IfcSpace
is indeed in the same "category" asIfcSite
,IfcBuilding
, etc. Those three are provided as examples. The struct rule lies in this sentence:You are right, I indeed meant IfcSpace.
Me too! It would also be interesting to see if it was possible to fix it by replacing the IfcLocalPlacements, but maybe it would be easier to just ask Solibri.
@Einar I've linked this thread to someone I know who is closer to the Solibri guys and may be able to get a response, I'll update this thread if anything comes out of it.
@Einar regarding the transformations and without getting into the details of your implementation, are you sure you are rotating the objects with respect to the right center? It looks to me your are always rotating with respect to 0, 0, 0
@Jesusbill I'm not sure at all! I can try to explain how I think, and maybe you have an idea if it makes sense or not:
As an example I have a wall that is positioned relative to a space in a certain coordinate system. The space is then positioned relative to a building storey. If both locations where in the same coordinate system it would just be a matter of adding the coordinates in each point togeter the get the walls placement relative to the building storey. That is not the case here because the points are given in two different coordinate systems, where the difference between them is the direction of the x-axis. My next step is to transform the point in the space to the coordinate system of the wall before they are added together. Isn't the coordinate systems origin the most logical point to rotate about?