0

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

  • I love your approach! Very neat! Still, I hope (and assume) you realise that there are easier and more efficient alternative ways to determine the volume of a space in Revit? – Jeremy Tammik Nov 10 '20 at 09:22
  • I used a very simple room for my use case, but what I'll actually be using it for is calculating the rough volume of an arena seating bowl. If you have suggestions (or links) on how to better do this calculation I am all ears. @JeremyTammik – martinservold Nov 10 '20 at 21:37
  • Quite possibly this is the best approach for an open arena. If you close the arena, i.e., put a lid on it, Revit might be able to tell you the volume offhand. No idea how Revit will behave if you try that, though.m Still, you could use the approximate arena geometry to define a solid volume, and then that will tell you its volume right out of the box. – Jeremy Tammik Nov 12 '20 at 07:28
  • Rooms in revit do not calculate volume very well, they assume the outer bounds of the room are static and can be calculated at a specific height. This can be set by editing the 'Computation Height'. In the past we've done the method of creating an in-place component and via sections and floor plans to approximate geometry. Below is a link to what I get out of my script (left is script output, right is revit geometry) [Imgur Link](https://imgur.com/a/J5dh2me) – martinservold Nov 13 '20 at 19:46
  • Revit supports several different space volume calculation algorithms: https://thebuildingcoder.typepad.com/blog/2017/01/family-category-and-two-energy-model-types.html#3 – Jeremy Tammik Nov 15 '20 at 15:40

1 Answers1

0

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).

Omni
  • 1,002
  • 6
  • 12
  • I had to use `for y in range(360):` to get it on all surfaces, but otherwise your solution did fix my problem! Maybe it's only going 0-180 degrees on the XY axis so it has to go the full 360 in the Z? Thanks for the explanation, though! – martinservold Nov 10 '20 at 02:22