Given:
Two vertices of an equilateral trainable as A,B ∊ RN when N > 1.
Goal:
Find the third vertex Z ∊ RN in which ||A-B|| = ||A-Z|| = ||B-Z||
.
I have the following python script from here which calculates it for 2-dimensional points (A,B ∊ R2 and Z ∊ R2):
import numpy as np
def equilateral(A, B):
# Computes `x coordinate` of the third vertex.
vx = ( A[0] B[0] np.sqrt(3) * ( A[1] - B[1] ) ) / 2
# Computes 'y coordinate' of the third vertex.
vy = ( A[1] B[1] np.sqrt(3) * ( A[0] - B[0] ) ) / 2
z = np.array([vx, vy]) #This point z is the third vertex.
return z
# Test for 2D vectors:
A = np.array([2,0])
B = np.array([5,0])
Z = equilateral(A,B)
print(z) # [ 3.5, -2.59807621]
How can I extend this (or maybe come up with more intelligent) solution to obtain the third vertex of N-dimensional vector such as the following test example?
N = 5
A = np.random.normal(size=(N, ))
B = np.random.normal(size=(N, ))
z = equilateral(A, B)
Cheers,
CodePudding user response:
You can use a general function to find a perpendicular to a vector based on this method. Then you just add a perpendicular vector of the right length to the midpoint of the first two vertices. As noted in comments, there are an infinite number of vertices that would solve this when the number of dimensions is more than 2. This method simply identifies one that is easy to calculate.
def magnitude(v):
""" Return the magnitude of a vector. See https://stackoverflow.com/a/9184560/567595 """
return np.sqrt(v.dot(v))
def perpendicular(u):
""" Return a vector perpendicular to vector v, of magnitude 1.
Based on https://math.stackexchange.com/a/3175858
"""
r = np.zeros(u.shape)
zeros, = np.where(u == 0)
if zeros.size > 0: # If any u[i] is zero, return standard vector e_i
r[zeros[0]] = 1
else: # Otherwise return u[1]e_0 - u[0]e_1
m = magnitude(u[:2])
r[:2] = u[1] / m, -u[0] / m
return r
def third_vertex_equilateral(A, B):
""" Find a third vertex of an equilateral triangle with vertices A and B, in N dimensions """
side = A - B
midpoint = (A B) / 2
bisector = perpendicular(side) * np.sqrt(.75) * magnitude(side)
return midpoint bisector
N = 5
A = np.random.normal(size=N)
B = np.random.normal(size=N)
C = third_vertex_equilateral(A, B)
np.isclose(magnitude(A - B), magnitude(A - C)) # True
np.isclose(magnitude(A - B), magnitude(B - C)) # True
Note that when written more succinctly, the function is quite similar to the one in the question:
def third_vertex_equilateral(A, B):
""" Find a third vertex of an equilateral triangle with vertices A and B, in N dimensions """
return (A B np.sqrt(3) * perpendicular(A - B) * magnitude(A - B)) / 2