-2

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,

Farid Alijani
  • 839
  • 1
  • 7
  • 25
  • Does your function work? Are you asking for a critique? – wwii Jun 27 '22 at 15:47
  • From a glance at the math, it seems there are many possible solutions when N > 2 https://math.stackexchange.com/questions/686530/finding-the-third-point-of-an-equilateral-triangle-in-three-dimensions - so it won't be possible to write a function that gets a single set of coordinates. – Stuart Jun 27 '22 at 15:48
  • It works only for 2D vectors! I need to extend it for N-dimensional vertices as well – Farid Alijani Jun 27 '22 at 15:49
  • Did you write that script? Do you understand it? I suggest that you convert it from *coordinates* to *vectors.* Find the vector from A to B, and a vector normal to that vector, and use them to construct the third point. Once you have that working, you will see that the number of dimensions doesn't matter. – Beta Jun 27 '22 at 15:56
  • @Beta 'Find... a vector normal to that vector' - but there are infinite such vectors when N > 2. I guess the function could choose one arbitrarily. – Stuart Jun 27 '22 at 16:04
  • 2
    In 2D you have TWO possible positions of the third vertex. In 3D, the third vertex might be in *any point of the circle* centered at the midlle of AB, so there is infinite number of solutions. Perhaps you really need an arbitrary valid point? – MBo Jun 27 '22 at 16:05
  • I updated my question in which my purpose is to get `||A-B|| = ||A-Z|| = ||B-Z||`. – Farid Alijani Jun 27 '22 at 16:52
  • Maybe you should include a written description of your algorithm for the N-dimensional function and explain which part of it you are having trouble coding - probably include an [mre] for that portion you are having trouble with. – wwii Jun 27 '22 at 17:05

1 Answers1

1

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
Stuart
  • 9,597
  • 1
  • 21
  • 30