pythonrevit-apirevitpythonshellpyrevit

Raycasting to calculate the volume of a space


I'm trying to use ray casting to gather all the surfaces in a room and determine it's volume. I have a centroid location where the rays will be coming from, but I'm drawing a blank on how to get the rays in all 360 degrees (in 3D space).

I'm not getting any points on the floors or ceilings, it's like it's doing a 60 degree spread rotated about the Z axis. I think I have the rest of it working, but this is stumping me.

for y in range(360):
    for x in range(360):
        vector = DB.XYZ(math.sin(math.radians(x)), math.cos(math.radians(x)), math.cos(math.radians(y))).Normalize()
        prox = ri.FindNearest(origin, direction).Proximity
        point = origin + (direction * prox)

enter image description here

enter image description here


Solution

  • Look at it this way: x and y of vector are created from angle x (-> a circle in the plane) and then you add a z component which lies between -1 and 1 (which cos does). So it's obvious that you end up with a cylindrical distribution.

    What you might want are spherical coordinates. Modify your code like this:

    for y in range(-90, 91):
        for x in range(360):
            vector = DB.XYZ(math.sin(math.radians(x)) * cos(math.radians(y)), 
                            math.cos(math.radians(x)) * cos(math.radians(y)),                   
                            math.sin(math.radians(y))) # Normalize unnecessary, since vector² = sin² * cos² + cos² * cos² + sin² = 1
        prox = ri.FindNearest(origin, direction).Proximity
        point = origin + (direction * prox)
    

    But be aware that the angle distribution of rays is not uniform using spherical coordinates. At the poles it's more dense than at the equator. You can mitigate this e.g. by scaling the density of x down, depending on y. The surface elements scale down by cos(y)², so I think you have to scale by cos(y).