3

I have two points X = (x1,y1) and Y=(x2,y2) in the Cartesian plane. I need to find the third point Z = (x,y) such that these three points make an equilateral triangle.

I'm calculating the Euclidean distance between two points using the following code sample:

def distance(points, i, j):
dx = points[i][0] - points[j][0]
dy = points[i][1] - points[j][1]
return math.sqrt(dx*dx + dy*dy)

In theory, I need to equate the distances of XZ and YZ to XY.This gives us two possible answers and I need them both too. But I'm having a difficulty in initiating the point Z in my code. Can someone please help me with this? The following is a sample of what I tried.

L = [0, 6]  #known two points
d= distance(points, L[0], L[1])
x = Symbol('x')
y = Symbol('y')
newpoint = x,y   #coordintes of the third point of the triangle
f1 = distance(points, L[0], newpoint)
f2 = distance(points, L[1], newpoint)
print(nsolve((f1, f2), (x, y), (d,d)))

But this returns the following error:

 File "/Users/*.py", line 99, in <module>
    f1 = distance(points, L[0], newpoint)

  File "/Users/*.py", line 36, in distance
    dx = points[i][0] - points[j][0]

TypeError: list indices must be integers or slices, not tuple
Joel
  • 22,598
  • 6
  • 69
  • 93
ccc
  • 574
  • 2
  • 9
  • 22
  • Equilateral triangles have 60°angle. Use trigonometry. You have distance and angle, you can get position. – politinsa May 26 '18 at 21:28
  • Note: `math.hypot(dx, dy)` is the equivalent to the `math.sqrt(...)` call. @politinsa you don't need trig for this problem because you know that the points are the perpendiculars from the middle of the XY vector at a distance of `math.sqrt(distance()**2 - (distance()/2)**2) == math.sqrt(3)*distance()/2` [Pythagoras theorem] – AChampion May 26 '18 at 21:56
  • Why are you passing a `point` as the 3rd argument to `distance()`, it is meant to be an index into the list of points, assume you need to add `newpoint` to points and then pass the appropriate index, or change your `distance()` function. – AChampion May 26 '18 at 21:58
  • @AChampion Thanks for your comment! I'm calculating the Euclidean distance of two sides and equating that to the known distance (d). ` newpoint ` is the coordinates of the third vertex of the triangle. – ccc May 26 '18 at 21:59

2 Answers2

6

In order to get the third vertex, you could just rotate the point (x2, y2) by 60 degrees around point (x1, y1). The other admissible solution would be obtained with a rotation by -60 degrees, i.e., in the opposite direction.

import math


def get_point(x1, y1, x2, y2):
    #express coordinates of the point (x2, y2) with respect to point (x1, y1)
    dx = x2 - x1
    dy = y2 - y1

    alpha = 60./180*math.pi
    #rotate the displacement vector and add the result back to the original point
    xp = x1 + math.cos( alpha)*dx + math.sin(alpha)*dy
    yp = y1 + math.sin(-alpha)*dx + math.cos(alpha)*dy

    return (xp, yp)


print(get_point(1, 1, 2, 1))
# (1.5, 0.1339745962155614)
ewcz
  • 12,819
  • 1
  • 25
  • 47
2

To find the third point of a equilateral triangle doesn't need anything really complicated, simply find the mid-point between X and Y, you know that this forms a right angle to point Z so just map to the origin, multiply by sqrt(3) (simplification of Pythagoras theory for equilateral triangles) and rotate 90 degrees in both directions (x,y => y,-x, x,y => -y,x), and map back, e.g.:

X, Y = (1,1), (2,1)
M = (X[0]+Y[0])/2, (X[1]+Y[1])/2            # Mid point
O = (X[0]-M[0])*3**0.5, (X[1]-M[1])*3**0.5  # Map to origin, multiply sqrt(3)

In []:
M[0]+O[1], M[1]-O[0]                        # Rotate 90 (y,-x), map back

Out[]:
(1.5, 1.8660254037844386)

In []:
M[0]-O[1], M[1]+O[0]                        # Rotate -90 (-y,x), map back

Out[]:
(1.5, 0.1339745962155614)

You can do this in numpy:

X, Y = np.array([1,1]), np.array([2,1])
M = (X + Y) / 2
O = (X - M) * 3**0.5
t = np.array([[0, -1], [1, 0]])   # 90 degree transformation matrix

In []:
M + O @ t

Out[]:
array([1.5      , 1.8660254])

In []:
M + O @ t.T                       # the transpose gives -90

Out[]:
array([1.5      , 0.1339746])
AChampion
  • 29,683
  • 4
  • 59
  • 75