Search code examples
math3dgeometrylinear-algebra

Finding vector that creates specific angle between two other vectors


Given point A, point B, point J, and an angle X, find every point C where angle ACB is equal to X. Its all in 3d space where point J forms a plane with A and B so all of the solutions C should lie on that plane.

The solution points C never give me the correct angles. Also, how many solutions are there when X=90? How about X!=90?

def angle_between_vectors(v1, v2):
    # Calculate the angle between two vectors in degrees
    angle_rad = np.arccos(np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)))
    return np.degrees(angle_rad)

def find_points_with_angle_3d(A, B, J, X):

    # J forms a plane with A and B on which any solution C must lie
    # X is the angle (degrees) at which any solution C should make with A and B

    # set A, B, J as vectors
    A = np.array(A)
    B = np.array(B)
    J = np.array(J)

    # calculate vectors AB and AJ
    AB = B - A
    AJ = J - A

    # unit vector AB
    uAB = AB / np.linalg.norm(AB)

    # normal vector of the plane
    N = np.cross(AB, AJ)

    # unit vector N
    uN = N / np.linalg.norm(N)

    # project AJ onto plane
    AJ_proj = np.dot(AJ, uN) * uN

    # vector orthogonal to N and AB
    perpendicular_vector = np.cross(uN, AB)

    C1 = A + math.cos(np.radians(X)) * AJ_proj + math.sin(np.radians(X)) * perpendicular_vector

    C2 = A + math.cos(np.radians(X)) * AJ_proj - math.sin(np.radians(X)) * perpendicular_vector

    print("C1:", C1)
    print("C2:", C2)

    # Calculate angles ACB for C1 and C2
    AC1 = C1 - A
    BC1 = C1 - B
    angle_C1 = angle_between_vectors(AC1, BC1)

    AC2 = C2 - A
    BC2 = C2 - B
    angle_C2 = angle_between_vectors(AC2, BC2)

    print("Angle ACB for C1:", angle_C1)
    print("Angle ACB for C2:", angle_C2)

    return C1, C2

A = (2, 1, 3)
B = (4, 5, 4)
J = (7, 7, 7)
angle_X_deg = 45
C1, C2 = find_points_with_angle_3d(A, B, J, angle_X_deg)

Output:

C1: [ 3.55904966 -0.39776866  5.47297532]
C2: [0.44095034 2.39776866 0.52702468]
Angle ACB for C1: 54.735610317245346
Angle ACB for C2: 54.735610317245346

Solution

  • There is infinite number of C points.

    They lie on the circle arc with central angle AOB = 2*X (D case) or AOB = 2*(180-X) for X>90 (C case at the picture) (Inscribed angle theorem). Picture on ABJ plane:

    enter image description here

    Note that for X=90 AB is circle diameter, C might be in any place of the circle.

    Also note there are two circles with mirror symmetry relative to the same AB chord.


    To get formula for all possible C points, we can do the next:

    Find normal to the plane:

     N = AB.cross.AJ
    

    Get vector perpendicular to AB in the plane and normalize it:

    P = AB.cross.N
    uP = P / len(P)
    

    Also normalized AB:

    uAB = AB / len(AB)  
    

    Get middle of AB chord

    M = A + AB/2
    

    Get angle for AB chord:

    if X > Pi/2:
        Alpha = 2 * (Pi - X)
    else:
        Alpha = 2 * X
    

    Get circle center and radius

    HalfLen = len(AB) / 2
    O = M + uP * HalfLen / Tan(Alpha/2)   // M - uP... for mirrored circle
    
    R = HalfLen / Cos(Alpha/2)
    

    Now we can generate all points using angle parameter t in range (-Alpha/2.. +Alpha/2)

    C = O + R * uP * Cos(t) + R * uAB * Sin(t) 
    

    (Note we need to check and change signs to describe all cases)