0

I have a set of x and y points (whatever the function behind) here in black. I would like to move the (x0, y0) point to the (x1,y1) knowing that there is 3 cm (whatever the unit) from (x0, y0) to (x1,y1) at 90° angle.

1

I would like to do it in Python, however obviously this is pretty bad.

fig = plt.figure()
from mpl_toolkits.mplot3d import Axes3D
ax = fig.add_subplot(111)

c = [55,  53, 54]
d = [29,  27,  27]

c = [55,  53 + 3, 54]
dd = [29,  27 + 3,  27 ]

ax.plot(c,d,'-o', c='g')
ax.plot(c,dd,'-o', c='b')

Partial final answer translated into Python (Thanks to picobit), however I would like to make the picobit function "orientation sensitive" :

fig = plt.figure()
from mpl_toolkits.mplot3d import Axes3D
ax = fig.add_subplot(111)
    
    
a = [0.22520001, 0.22140153, 0.21732369, 0.21258711, 0.20764232, 0.20515779,
0.20449048, 0.20467589, 0.20534733]
b = [0.21270538 ,0.21026637, 0.20749939, 0.20383899, 0.19925433, 0.19559762,
0.19440357, 0.19375025, 0.19344115]


dev = [0.0009969 , 0.00143304, 0.00174457, 0.00193148, 0.00199379, 0.00186918,
0.00149534, 0.00087228, 0.        ]

import math

def rotate_vector(x0, y0, angle, dev):
    magnitude = math.sqrt(x0**2 + y0**2)
    xhat = x0/magnitude
    yhat = y0/magnitude
    x_rot = -yhat * math.sin(angle) + xhat * math.cos(angle)
    y_rot = yhat * math.cos(angle) + xhat * math.sin(angle)
    x_rot = x_rot * dev
    y_rot = y_rot * dev

    anglee = 90 # Obviously different if 0 or 45, etc...

    x_rot = (x_rot * math.cos(np.radians(anglee))) - (y_rot * math.sin(np.radians(anglee)))
    y_rot = (x_rot * math.sin(np.radians(anglee))) + (y_rot * math.cos(np.radians(anglee))) 

    x_final = x_rot + x0
    y_final = y_rot + y0
    return x_final, y_final
Acqueux
  • 23
  • 4
  • 1
    Is it meant to be at 90 degrees to the original line? You need to do some mathematics. This isn't really a problem with Python. – Peter Wood Jan 27 '23 at 15:14
  • Yes indeed at 90 sorry for confusion – Acqueux Jan 27 '23 at 15:15
  • 1
    https://stackoverflow.com/questions/18136549/calculate-cartesian-coordinates-of-a-point-on-a-perpendicular-of-a-line – picobit Jan 27 '23 at 16:07
  • Be careful, you overwrote `c` so its first declaration is useless. – Cadeyrn Jan 27 '23 at 16:29
  • 1
    could you precise: 90° to what ? – Cadeyrn Jan 27 '23 at 16:31
  • Does this answer your question? [Calculate cartesian coordinates of a point on a perpendicular of a line](https://stackoverflow.com/questions/18136549/calculate-cartesian-coordinates-of-a-point-on-a-perpendicular-of-a-line) – Pranav Hosangadi Jan 27 '23 at 17:28
  • If (a,b) is a vector of length N, then (-3b/N, 3a/N) is the vector of length 3 going in the perpendicular direction to the right of the original vector's direction. – Will Ness Jan 27 '23 at 20:15

1 Answers1

4

Prerequisites:

Your algorithm is:

  1. Find the unit vector that points from the origin to (x0,y0)
  2. Multiply the unit vector by the rotation matrix
  3. Multiply this new vector by your desired length (3cm in your example)
  4. Move the newly-scaled vector's starting point back to (x0,y0)

Step 1: Let A be the vector between the origin and (x0,y0). We need to find |A|, magnitude of A, (aka the length of the line segment) using the Pythagorean Theorem.

Find the unit vector by dividing (x0,y0) by |A|, giving us (x0/|A|,y0/|A|). This is the unit vector along A. Prove it to yourself by drawing a little, tiny right triangle with one end of the hypotenuse at the origin and the other end at (x0/|A|,y0/|A|).

Just to make things easier to type, let xhat=x0/|A| and yhat=y0/|A|.

Step 2:
You can rotate the unit vector by any angle θ by multiplying by the rotation matrix. After shaking out the matrix multiplication, you get the new point (xhat',yhat') where

xhat' = xhat*Cosθ - yhat*Sinθ  
yhat' = xhat*Sinθ + yhat*Cosθ

90 degrees is a friendly angle, so this simplifies to:

xhat' = -yhat
yhat' = xhat

Step 3:
Scale the new vector by 3 units (centimeters in your example):

3*(-yhat,xhat) = (-3*yhat,3*xhat)

Step 4:
Move this new vector's starting point back to (x0,y0)

(x1,y1) = (-3*yhat,3*xhat) + (x0,y0) 
        = (-3*yhat+x0,3*xhat+y0)

Those are the coordinates for your new point.

As a quick example, if you have the point (3,4), and you want to perform the same translation as in your example image, then you'd do this:

  1. |A| = 5, so (xhat, yhat) = (3/5, 4/5)
  2. (xhat', yhat') = (-4/5, 3/5)
  3. 3*(-4/5, 3/5) = (-12/5, 9/5)
  4. (-12/5+3, 9/5+4) = (0.6, 5.8)

Now prove to yourself that the two points are 3 units apart, again using the Pythagorean Theorem. A right triangle with hypotenuse connecting the two points (3,4) and (0.6,5.8) has sides with lengths (3-0.6) and (5.8-3)

enter image description here

picobit
  • 527
  • 5
  • 15
  • Thanks a lot I edited the initial post with Python code. – Acqueux Jan 30 '23 at 06:20
  • One quick question then, if I have some 3D points, how can I take (in plus) the orientation like a rotation matrix ? – Acqueux Jan 30 '23 at 08:05
  • @Acqueux The example that I showed is for rotating a vector with zero z component around the z-axis (aka rotating a vector on the x-y plane), but there are other rotation matrices for rotating a 3D vector around either the X, Y, or X axes (see the Wikipedia article that I linked). If you're wanting to rotate around an arbitrary vector in 3 space, then check out https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions and Euler's rotation theorem – picobit Jan 30 '23 at 18:17