- Home /
Is there a functionality for finding how much two objects intersect each other
Hi, say I have two identical spheres, and want to know how much each intersect each other.
For example, when both at (0,0,0) it would be 100% intersect, and when one sphere is moved, maybe only 80% of the volume is intersected.
I looked at methods such as Bounds.Intersects and Physics.OverlapSphere, but those seems to only say if there is intersection, but not by how much.
Is there an functionality for what I am describing? A similar question is here, but wondering if there is simpler solution.
The scenario I am trying to use is to determine if a game object is moved to a specific place indicated by a silhouette.
Answer by Bunny83 · Jan 05, 2017 at 01:37 PM
Well, if you constraint your problem so you always have two identical spheres it's relatively easy.
Two identical spheres, as long as they intersect, have a single "cutting plane" which is located exactly halfway between the two spheres. Just imagine you cut both spheres at this plane. You will get 4 sphere pieces. Each sphere breaks up into a larger (`>50%`) and a smaller (`< 50%`) piece. You will ignore the larger ones and simply look at the smaller ones. The smaller pieces are Sphere caps so you can simply calculate the volume of each piece and add them together to get the whole intersection volume. Since the spheres are identical, both caps are also identical. So you can just calculate the volume of one cap and multiply it by 2. The result can be divided by the volume of a whole sphere to get a value between 0 and 1.
Let "a" and "b" be the position of sphere A and sphere B. "r" is the radius of both spheres
float IntersectSphereVolume(Vector3 a, Vector3 b, float r)
{
Vector3 ab = b - a;
float halfLength = ab.magnitude * 0.5f;
if (halfLength > r)
return 0; // no intersection
float circleRadiusSqr = r * r - halfLength * halfLength;
float height = (r - halfLength);
float vCap = (3*circleRadiusSqr + height*height) * height * Mathf.PI / 6f;
float vIntersect = vCap * 2f;
float vSphere = r*r*r*Mathf.PI * 4f / 3f
return vIntersect / vSphere;
}
Just written from scratch so i can't confirm it works properly ^^. This method returns a value betwen 0 and 1 where 0 means no intersection and 1 when the two spheres are at the exact same position.
If you don't need the exact volume matching you could simply use a linear error like this:
float IntersectSphereVolume(Vector3 a, Vector3 b, float r)
{
Vector3 ab = b - a;
return Mathf.Clamp01(1f - ab.magnitude / (2*r));
}
This will also return a value between 0 and 1 but the curve will be linear.
ps: In the first method one could cancel out Mathf.PI and some other factors as we finally just divide both volumes through each other, However i kept it so it's clear what happens. Also you can use the volume for other things.
If the spheres have different radii or aren't spheres at all this is getting much more complicated and doesn't have a general solution.
Answer by Fressbrett · May 22, 2020 at 01:44 PM
This is an old question, but for concave meshes you need boolean operations, which is quite complex math - but luckly well understood.
If one of your meshes is concave and the other is convex, have a look at the Sutherland-Hodgman algorithm. However, this algorithm requeries one mesh to be convex. If you want both to be convace and also want to take care of edge cases, you need to go for boolean operations, such as the Martinez algorithm. The paper is called "A new algorithm for computing Boolean operations on polygons".