pythongeometrycoordinatestrigonometrytriangulation

finding the third point in a triangle using python


I am trying to create a python function to find the coordinates of a preestablished position given two reference points which can change.

At the start I have three points on the grid reference point 1 (Xr1,Yr1), reference point 2 (Xr2,Yr2), and the custom point (Xc,Yc). Initialy all three points are known, but for subsequent movements reference point 1 and reference point 2 can be measured but the custom point is unknown. The shape and size of the triangle drawn between these 3 points dose not change.

Given this, is there a good way in python to take the coordinates of the initial 3 points and the coordinates of the new 2 reference points and calculate the coordinates of the new position of the custom point. (Green values are known, red values are not)

enter image description here

I have tried drawing circles around the new points using the distance between the reference points and the custom point as the radius and finding the intercept. however, this method was slow, and memory intensive as I am using very large coordinate distances, also it was rather unreliable in its implementation.

Any help on this would be most appreciated.


Solution

  • Here's one possible solution using a function that rotates a point around the origin (0,0):

    The strategy is to transpose the coordinates to a frame of reference around one of the known points. Then apply the relative rotation of the other known point to compute the unknown third point.

    If we name the 3 points of the triangle A, B and C with C being the unknown after moving A and B, the process would go as follows:

    ...

    import math
    def rotatePoint(x,y,angle):
        s,c = math.sin(angle), math.cos(angle)
        return (x*c-y*s, x*s+y*c)
    
    def getNewC(A,B,C,newA,newB):
        Ax,Ay = A
        Bx,By = B
        Cx,Cy = C
        
        B0x,B0y    = Bx-Ax, By-Ay
        oldAngleAB = math.atan2(B0y,B0x)
    
        newAx,newAy   = newA
        newBx,newBy   = newB
        newB0x,newB0y = newBx-newAx, newBy-newAy
        newAngleAB    = math.atan2(newB0y,newB0x)
    
        C0x,C0y       = Cx-Ax, Cy-Ay
        newC0x,newC0y = rotatePoint(C0x,C0y,newAngleAB - oldAngleAB)
        newCx,newCy   = newAx+newC0x, newAy+newC0y
        
        return newCx,newCy
    

    outut: (using turtle to illustrate)

    import turtle
    t = turtle.Turtle()
    
    A = (10,10)
    B = (60,10)
    C = (30,120)        
    t.penup()
    t.goto(*A)
    t.pendown()
    t.goto(*B)
    t.goto(*C)
    t.goto(*A)
    
    newA = (-10,-10)
    newB = (-10,-60)
    newC = getNewC(A,B,C,newA,newB)    
    t.pen(pencolor="red")
    t.penup()
    t.goto(*newA)
    t.pendown()
    t.goto(*newB)
    t.goto(*newC)
    t.goto(*newA)
    
    newA = (-40,40)
    newB = (-70,80)
    newC = getNewC(A,B,C,newA,newB)    
    t.pen(pencolor="blue")
    t.penup()
    t.goto(*newA)
    t.pendown()
    t.goto(*newB)
    t.goto(*newC)
    t.goto(*newA)
    

    Note that this does not perform any scaling. It assumes that the distance between the two base points remains the same after being moved. If, eventually, you do need scaling, it can be added at the end in the transposition from newC0 to newC:

    scale         = ((newB0x**2+newB0y**2)/(B0x**2+B0y**2))**0.5
    newCx,newCy   = newAx+newC0x*scale, newAy+newC0y*scale
    

    output:

    newA = (110,110)
    newB = (150,220)
    newC = getNewC(A,B,C,newA,newB)    
    t.pen(pencolor="purple")
    t.penup()
    t.goto(*newA)
    t.pendown()
    t.goto(*newB)
    t.goto(*newC)
    t.goto(*newA)
    

    turtle output