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.
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
Prerequisites:
Your algorithm is:
(x0,y0)
(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:
|A| = 5
, so (xhat, yhat) = (3/5, 4/5)
(xhat', yhat') = (-4/5, 3/5)
3*(-4/5, 3/5) = (-12/5, 9/5)
(-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)