Move 1 object at a given distance from 2 others objects

Hi, I’m trying to move my GameObject C at a position where the distance A-C and B-C are both a given distance while C must stay at his own height.

Description of the image:

  • C is the object I want to move
  • A & B are objects and I want C to be moved at a given distance from them
  • A & B spheres have both the radius of the given distance
  • The red circle is where both spheres are overlaping (at the given distance)
  • D & E are 2 positions where the distance to A & B are egal to the given distance while being are C height

The way I think it must be done:

  • Look if A & B spheres can overlap with the given radius
  • Find this red circle which is all intersection between the 2 spheres where the distance are the same
  • Find the 2 coordinates on the red circle where the height is egal to the C height
  • Move C to the D position

I don’t know if it’s the easier method or if I miss a build-in fonctionnality, I’m open to any other ideas.
I’m struggling with the math to find these D & E positions any suggestion ?

sfsf

Can you just do the math to find the solution, or is that what you need help with? I don't think you are missing any tool.

I don't know the math to find the intersection between 2 spheres, especially at a given height

3 Answers

3

Ok so I finally found a solution! I used a lot of vectors and Pythagoras.
Here is the simplified process:

  • Find the midpoint AB
  • Get the equidistant & horizontal vector from this midpoint AB
  • Move this vector to the desired height
  • Use Pythagoras to find the final position along this vector
    public Transform pointA, pointB, pointC;
    public float distanceFromPoints;
    private float fixedHeight;

    //Temporary positions
    Vector3 midPointAB, equidistantPointAtFixedHeight;
    //Resulting vectos
    Vector3 directionAB, upAB, rightAB; 
    //Finals positions
    Vector3 intersectionA, intersectionB;

    public void MoveObject()
    {
        // Set example references
        fixedHeight = 1.0f;
        distanceFromPoints = 0.7f;

        //Find AB midpoint
        midPointAB = (pointA.position + pointB.position) / 2.0f;

        //Find all AB Vectors
        //Find AB direction (Green Gizmo)
        directionAB = (pointB.position - pointA.position).normalized;
        //Find AB right direction which horizontal & is perpendicular to directionAB, all the positions on this vector are equidistant to A & B (Red Gizmo)
        rightAB = Vector3.Cross(directionAB, Vector3.up).normalized;
        //Find AB up direction which is perpendicular to both previous vectors (Blue Gizmo)
        upAB = Vector3.Cross(directionAB, -rightAB).normalized;


        //Find the distance to go from midPointAB to a position where Y=fixedHeight
        float upScaleFactor = (fixedHeight - midPointAB.y) / upAB.y;
        //Find the point along upAB where Y=fixedHeight
        equidistantPointAtFixedHeight = midPointAB + upAB * upScaleFactor;


        //Use Pythagore find the distanceFromPoints on rightAB (white Gizmo)
        float vertical = Vector3.Distance(pointA.position, equidistantPointAtFixedHeight); //Choose pointA or B do not matter since equidistantPointAtFixedHeight is equidistant with them
        float hypothenuse = distanceFromPoints;
        float distanceOnRightAB = (float)(Mathf.Sqrt(Mathf.Abs((hypothenuse * hypothenuse) - (vertical * vertical))));


        //Move the vector rightAB to equidistantPointAtFixedHeight and add the distanceOnRightAB of find the 2 equidistant points
        intersectionA = equidistantPointAtFixedHeight + rightAB * distanceOnRightAB;
        intersectionB = equidistantPointAtFixedHeight - rightAB * distanceOnRightAB;


        //Move Point C to the closer intersection
        if (Vector3.Distance(pointC.transform.position, intersectionA) < Vector3.Distance(pointC.transform.position, intersectionB))
            pointC.transform.position = intersectionA;
        else
            pointC.transform.position = intersectionB;

        //Print if correct result is impossible
        if (Mathf.Abs(Vector3.Distance(pointA.transform.position, pointC.transform.position) - distanceFromPoints) > 0.01f
            || Mathf.Abs(Vector3.Distance(pointB.transform.position, pointC.transform.position) - distanceFromPoints) > 0.01f)
            Debug.Log("Points A & B are too far from each others"); 

        // Print distances to prove it works 
        Debug.Log("Distance to A: " + Vector3.Distance(pointA.transform.position, pointC.transform.position) +
            " / Distance to B: " + Vector3.Distance(pointB.transform.position, pointC.transform.position) +
            " / Height: " + pointC.position.y +
            " / Angle (Pythagore need 90): " + Vector3.Angle((equidistantPointAtFixedHeight - pointA.position).normalized, (equidistantPointAtFixedHeight - intersectionA).normalized));
    }

    [ExecuteInEditMode]
    private void OnDrawGizmos()
    {
        // Draw directionAB vector
        Gizmos.color = Color.green;
        Gizmos.DrawLine(pointA.position, pointB.position);

        // Draw upAB vector
        Gizmos.color = Color.blue;
        Gizmos.DrawLine(midPointAB, midPointAB + upAB * 2);

        // Draw rightAB vector
        Gizmos.color = Color.red;
        Gizmos.DrawLine(midPointAB, midPointAB + rightAB * 2);
        Gizmos.DrawLine(equidistantPointAtFixedHeight, equidistantPointAtFixedHeight + rightAB * 2);

        //Draw Pythagore
        Gizmos.color = Color.white;
        Gizmos.DrawLine(pointA.position, equidistantPointAtFixedHeight);
        Gizmos.DrawLine(pointA.position, intersectionA);
        Gizmos.DrawLine(equidistantPointAtFixedHeight, intersectionA);

        // Draw pointOnCVectorFromA and pointOnCVectorFromB
        Gizmos.color = Color.yellow;
        Gizmos.DrawSphere(intersectionA, 0.05f);
        Gizmos.DrawSphere(intersectionB, 0.05f);
    }

There is a derivation for the circle defined by two intersecting spheres here:

The result is on steps 6 and 7. Since you have a fixed height, you would plug in the z value to get an equation for y^2, which will have two solutions.

Note that this derivation is done with one of the spheres at 0,0,0 and the other sphere offset only in the x direction. If the other sphere is at an arbitrary location, then you would have to modify step 2 and try to solve the resulting equations.

Some math variables:
r - radius
0 - dot with xyz = 0
A- = (Ax - Bx, 0, Az - Bz)
Aa:
A - name of object
a - name of axis
AB: distance between object A & object B
r of 2d circle on Cy (Cr) = Ar² / (Ay - Dy)²
Dz (if they’or on the same z, x if the same x, if not it, multiply it by abs of 0A- / 0B- or 0B- / 0A- if first is bigger than 1) = (Az > Bz? Az + Ar : Bz + Br) + (ACr > BCr? BCr - ACr : ACr - BCr)
ACr² = (Dz - Az)² + (Dx - Ax)²
ACr² = (Dz - Az)² + Dx² - 2Ax * Dx + Ax²
-Dx² = (Dz - Az)² - 2Ax * Dx + Ax² - ACr²
Dx² = (Dz - Az)² + 2Ax * Dx - Ax² + ACr²