[IfcOpenShell-Python] How to calculate a distance between two IFC entities?
In the past, I used successfully PythonOCC to determine the volume from one IFC entity. So I thought, why not also use PythonOCC for this problem and got the following code:
import ifcopenshell
from ifcopenshell import geom
import OCC.Core.BRepExtrema as BRepExtrema
File = "two-cube-built-element.ifc"
ifc_file = ifcopenshell.open(File)
Units = ifc_file.by_type("IFCSIUNIT")
for unit in Units:
if unit.UnitType == "LENGTHUNIT":
length_unit = unit.Name
break
# Define settings
settings = geom.settings()
settings.set(settings.USE_PYTHON_OPENCASCADE, True) # tells ifcopenshell to use pythonocc
ifc_products = ifc_file.by_type("IfcBuiltElement")
Shapes = [ ifcopenshell.geom.create_shape(settings, product) for product in ifc_products]
# Create the BRepExtrema_DistShapeShape object
dist = BRepExtrema.BRepExtrema_DistShapeShape(Shapes[0].geometry, Shapes[1].geometry)
# Perform the distance calculation
dist.Perform()
# Get the minimum distance
min_distance = dist.Value()
print("Minimum distance between the two IfcBuiltElement:", min_distance, length_unit.lower())
For my test IFC file (attached see below), I got the right result! See image:
And it is the same value as in BIMVision:
My next step is to calculate the distance between the bottom faces of both cubes, like in the image below:
My question is, before I go down deeper in this rabbit hole named PythonOCC, to solve my new problem: Are there other possibilities how I can solve this with a python script? Maybe other Python libraries?
Tagged:
Comments
@Martin156131 This can be achieved in ifcopenshell by creating a Geometry Tree and then using the
select_ray
method. This returns a list which also holds the distance between the ray origin and the intersected object. More info here https://docs.ifcopenshell.org/ifcopenshell-python/geometry_tree.html#selecting-elements-using-a-ray.I've used this in a few scripts.
A little update, I got this script, which calculate the distance between the bottom faces of both cubes:
With this code, I got the right result:

@Arv Thanks for the hint. Is there a way to specify that I want the distance between the bottom faces of the two cubes?
You can use
ifcopenshell.util.shape.get_volume()
to get the volume and not worry about OCC.I wouldn't recommend using BRepExtrema_DistShapeShape because it's actually extremely slow. We use an implementation in the geometry tree (typically for IfcClash) using an implementation from NVidia Omniverse's PhysX written by very clever people who invent these types of algos. It's got lots of toys I'd highly recommend investigating.
It's exposed as a many-many but should work with two objects too: https://docs.ifcopenshell.org/ifcopenshell-python/geometry_tree.html#detecting-clearance-clashes-between-elements
very useful, I did not know about this.
BTW: I do use for all kind of geometry algos I need to do a FreeCAD shape and the methods of FreeCAD. It might not be the fastest, but it has hundreds of methods to evaluate geometry including geometry checking.
Indeed, another option is mathutils.geometry from Blender. However for distance checks, BVH trees are extremely useful so I'd highly recommend the IfcOpenShell geometry tree.
FWIW Blender also has BVHTree and KDTree utilities https://docs.blender.org/api/current/mathutils.bvhtree.html
While we're at it, I'd also like to shoutout to
shapely
which is awesome library for 2D geometry analysis. Great for cross sectional profiles, cut shapes, wall topology...