Determine Whether a Point is 'in' a Volume
-
Is there any easy way of saying whether or not a given point is enclosed by some volume?
I've got a cunning plan for a volume calculating plugin but it kind of relies on there being some easy way to do the above.
-
This is something I've been meaning to ask myself. Paying close attention to this topic.
-
@remus said:
Is there any easy way of saying whether or not a given point is enclosed by some volume?
I've got a cunning plan for a volume calculating plugin but it kind of relies on there being some easy way to do the above.I've already done a couple of volume calculating scripts using quite different approaches...
To check if a point is inside a volume do a 'raytest'...
raytest=model.raytest(point,[1,0,0])
This vector [1,0,0] shouldn't matter if its a 'manifold' shape - alternatively you could use [0,0,-1] to look straight down - unless your shape might be bottomless etc !!!
raytest
returns a 2 item array ornil
if the ray misses everything and hits nothing.
raytest[0]
is the point where the ray hit something.
raytest[1]
is an array giving the hit object and perhaps its container, and its container's container etc etc e.g.[group, component_instance, group, face]
Soraytest[1][-1]
is the thing that was 'hit' by the ray e.g. a face
and its container israytest[1][-2]
etc
whereasraytest[1][0]
is the main container - if it's a lone face in the model it has no container and the array has only one item ...
You'll need to test that what's hit is in the selection or group entities etc being analyzed etc... -
Hmmm, all sounding pretty computationally intensive at the moment.
The original idea was to check lots of points in the bounding box of the object and see what proportion of them are in the volume, then take that proportion of the volume. I think some testing is in order.
Thanks for the tips TIG
Oh and i dont mean for the script to compete with yours, its more of an exercise than anything
-
@tig said:
I've already done a couple of volume calculating scripts using quite different approaches...
To check if a point is inside a volume do a 'raytest'...
raytest=model.raytest(point,[1,0,0])
This vector [1,0,0] shouldn't matter if its a 'manifold' shape - alternatively you could use [0,0,-1] to look straight down - unless your shape might be bottomless etc !!!
raytest
returns a 2 item array ornil
if the ray misses everything and hits nothing.
raytest[0]
is the point where the ray hit something.
raytest[1]
is an array giving the hit object and perhaps its container, and its container's container etc etc e.g.[group, component_instance, group, face]
Soraytest[1][-1]
is the thing that was 'hit' by the ray e.g. a face
and its container israytest[1][-2]
etc
whereasraytest[1][0]
is the main container - if it's a lone face in the model it has no container and the array has only one item ...
You'll need to test that what's hit is in the selection or group entities etc being analyzed etc...This is essentially the foundation for my BoolTools script. One pitfall though is self-intersections caused by floating point precision errors. You can get around this by 'nudging' the ray origin a very small distance after it intersects a face.
Performing one raytest is not enough. Once you find an intersection, you have to do another raytest using the intersection point as the origin (remember to nudge the origin).
A point will be inside a manifold mesh if a ray intersects the faces of the mesh an odd number of times.
-
@remus said:
The original idea was to check lots of points in the bounding box of the object and see what proportion of them are in the volume, then take that proportion of the volume.
IF the object is box-like, it would be very easy.
pt=[1,2,3] bb=obj.bounds in_volume=bb.contains?(pt)
Unfortunately, not all volumes can be box-like and aligned with the x,y,z axes.
-
I also use similar techniques to check if a shape is 'inside-out'.
Make a group of the surfaces.
Find the topmost face of that envelope [comparing face.bb.max.z and then face.bb.min.z].
Find a point on it's surface [sometimes easier said than done - I use the mid-point between vertices[0] and vertices[2] as the bb.center is unreliable].
Find that face's normal.
Do a raytest from that point using this normal as the vector.
If it intersects with nil then the surface faces outwards
It it intersects with something that belongs to the group it faces inwards.
If it intersects with 'something else' repeat the raytest from the new intersection point using the same vector until it returns the group - then it faces inwards or nil and then it faces outwards...
If it faces inwards reverse all of its faces... -
is there a better solution for this now?
Advertisement