Getting current X, Y coordinate from a bezier curve moving object - python

I want to find the x, y coordinate of an object moving in a bezier curve after it moved for a certain amount of time.
I have included a simple graph of the object trajectory here.
Consider the following known attributes of the object:
startingXY = [900, 450]
destinationXY = [-300, -600]
innerXY = [100, -50]
move_time = 15 # Moving duration in seconds
I tried using the below formula to calculate the (x,y), but it does not appear to be correct.
def calculate(a, b, c, d, t):
return math.pow(1 - t, 3) * a + 3 * t * math.pow(1 - t, 2) * b + 3 * math.pow(t, 2) * (1 - t) * c + math.pow(t, 3) * d
t = (now - start_time) * 0.1
x = calculate(0, startx, innerx, destinationx, t)
y = calculate(0, starty, innery, destinationy, t)
I somewhat solved my problem with the following fomula:
def the_math(a, b, c, t, p, f):
return (math.pow((1 - t), 2) * a + 2 * math.pow((1 - t), t) * b + math.pow(t, 2) * c) + p * f
elapsed_time = round(now - start)
t = elapsed_time / self.config.move_time[fish.fish_type]
x = the_math(path[0][0], path[1][0], path[2][0], t, 667, 0.85)
y = the_math(path[0][1], path[1][1], path[2][1], t, 375, 0.8)
print(x,y)
What would be a better formula to calculate the (x,y) coordinates?

Related

Faster way to iterate through pixel using numpy with conditions?

def colorize(im, h, s, l_adjust):
result = Image.new('RGBA', im.size)
pixin = np.copy(im)
pixout = np.array(result)
>>>>>>>>>>>>>>>>> loop <<<<<<<<<<<<<<<<<
for y in range(pixout.shape[1]):
for x in range(pixout.shape[0]):
lum = currentRGB(pixin[x, y][0], pixin[x, y][1], pixin[x, y][2])
r, g, b = colorsys.hls_to_rgb(h, lum, s)
r, g, b = int(r * 255.99), int(g * 255.99), int(b * 255.99)
pixout[x, y] = (r, g, b, 255)
>>>>>>>>>>>>>>>>>>>>> Loop end <<<<<<<<<<<
return result
Trying to find the HSL per pixel value from a frame of input video but it's taking too much time about 1.5s but want to reduce the time to at least within 0.3s. Any faster way to do this without using these 2 loops? Looking for something like LUT(Look up table)/vectorize/something with NumPy shortcut to avoid those 2 loops. Thanks
OR
Part 2 ->>
If I break the custom currentRGB() into the for loops it looks like :
def colorize(im, h, s, l_adjust):
result = Image.new('RGBA', im.size)
pixin = np.copy(im)
pixout = np.array(result)
for y in range(pixout.shape[1]):
for x in range(pixout.shape[0]):
currentR, currentG, currentB = pixin[x, y][0]/255 , pixin[x, y][1]/255, pixin[x, y][2]/255
#luminance
lum = (currentR * 0.2126) + (currentG * 0.7152) + (currentB * 0.0722)
if l_adjust > 0:
lum = lum * (1 - l_adjust)
lum = lum + (1.0 - (1.0 - l_adjust))
else:
lum = lum * (l_adjust + 1)
l = lum
r, g, b = colorsys.hls_to_rgb(h, l, s)
r, g, b = int(r * 255.99), int(g * 255.99), int(b * 255.99)
pixout[x, y] = (r, g, b, 255)
return pixout
You can use Numba to drastically speed the computation up. Here is the implementation:
import numba as nb
#nb.njit('float32(float32,float32,float32)')
def hue_to_rgb(p, q, t):
if t < 0: t += 1
if t > 1: t -= 1
if t < 1./6: return p + (q - p) * 6 * t
if t < 1./2: return q
if t < 2./3: return p + (q - p) * (2./3 - t) * 6
return p
#nb.njit('UniTuple(uint8,3)(float32,float32,float32)')
def hls_to_rgb(h, l, s):
if s == 0:
# achromatic
r = g = b = l
else:
q = l * (1 + s) if l < 0.5 else l + s - l * s
p = 2 * l - q
r = hue_to_rgb(p, q, h + 1./3)
g = hue_to_rgb(p, q, h)
b = hue_to_rgb(p, q, h - 1./3)
return (int(r * 255.99), int(g * 255.99), int(b * 255.99))
#nb.njit('void(uint8[:,:,::1],uint8[:,:,::1],float32,float32,float32)', parallel=True)
def colorize_numba(pixin, pixout, h, s, l_adjust):
for x in nb.prange(pixout.shape[0]):
for y in range(pixout.shape[1]):
currentR, currentG, currentB = pixin[x, y, 0]/255 , pixin[x, y, 1]/255, pixin[x, y, 2]/255
#luminance
lum = (currentR * 0.2126) + (currentG * 0.7152) + (currentB * 0.0722)
if l_adjust > 0:
lum = lum * (1 - l_adjust)
lum = lum + (1.0 - (1.0 - l_adjust))
else:
lum = lum * (l_adjust + 1)
l = lum
r, g, b = hls_to_rgb(h, l, s)
pixout[x, y, 0] = r
pixout[x, y, 1] = g
pixout[x, y, 2] = b
pixout[x, y, 3] = 255
def colorize(im, h, s, l_adjust):
result = Image.new('RGBA', im.size)
pixin = np.copy(im)
pixout = np.array(result)
colorize_numba(pixin, pixout, h, s, l_adjust)
return pixout
This optimized parallel implementation is about 2000 times faster than the original code on my 6-core machine (on 800x600 images). The hls_to_rgb implementation is coming from this post. Note that the string in #nb.njit decorators are not mandatory but enable Numba to compile the function ahead of time instead of at the first call. For more information about the types, please read the Numba documentation.

Rotation of arbitrary plane around a given axis results in inconsistent results

I am trying to rotate and translate arbitrary planes around some arbitrary axis.
For testing purposes I have written a simple python program that rotates a random plane around the X axis in degrees.
Unfortunately when checking the angle between the planes I get inconsistent results. This is the code:
def angle_between_planes(plane1, plane2):
plane1 = (plane1 / np.linalg.norm(plane1))[:3]
plane2 = (plane2/ np.linalg.norm(plane2))[:3]
cos_a = np.dot(plane1.T, plane2) / (np.linalg.norm(plane1) * np.linalg.norm(plane2))
print(np.arccos(cos_a)[0, 0])
def test():
axis = np.array([1, 0, 0])
theta = np.pi / 2
translation = np.array([0, 0, 0])
T = get_transformation(translation, axis * theta)
for i in range(1, 10):
source = np.append(np.random.randint(1, 20, size=3), 0).reshape(4, 1)
target = np.dot(T, source)
angle_between_planes(source, target)
It prints:
1.21297144225
1.1614420953
1.48042948278
1.10098697889
0.992418096794
1.16954303911
1.04180591409
1.08015300394
1.51949177153
When debugging this code I see that the transformation matrix is correct, as it shows that it is
I'm not sure what's wrong and would love any assistance here.
*
The code that generates the transformation matrix is:
def get_transformation(translation_vec, rotation_vec):
r_4 = np.array([0, 0, 0, 1]).reshape(1, 4)
rotation_vec= rotation_vec.reshape(3, 1)
theta = np.linalg.norm(rotation_vec)
axis = rotation_vec/ theta
R = get_rotation_mat_from_axis_and_angle(axis, theta)
T = translation_vec.reshape(3, 1)
R_T = np.append(R, T, axis = 1)
return np.append(R_T, r_4, axis=0)
def get_rotation_mat_from_axis_and_angle(axis, theta):
axis = axis / np.linalg.norm(axis)
a, b, c = axis
omct = 1 - np.cos(theta)
ct = np.cos(theta)
st = np.sin(theta)
rotation_matrix = np.array([a * a * omct + ct, a * b * omct - c * st, a * c * omct + b * st,
a * b * omct + c * st, b * b * omct + ct, b * c * omct - a * st,
a * c * omct - b * st, b * c * omct + a * st, c * c * omct + ct]).reshape(3, 3)
rotation_matrix[abs(rotation_matrix) < 1e-8] = 0
return rotation_matrix
The source you generate is not a vector. In order to be one, it should have its fourth coordinate equal to zero.
You could generate valid ones with:
source = np.append(np.random.randint(1, 20, size=3), 0).reshape(4, 1)
Note that your code can't be tested as you pasted it in your question: for example, vec = vec.reshape(3, 1) in get_transformation uses vec that hasn't been defined anywhere before...

Image perspective transform using Pillow

I tried to draw bounding box of text on a image.The image
is perspective-transformed with a given set of coefficients. The coordinates of text before transformation is known, and I want to calculate the coordinates of text after transformation.
To my understanding if I apply perspective transformation with the coefficients used in image transform to the text coordinates, I will get the resulting coordinates of the text after transformation. However, the text does not appear on the place it is supposed to be.
See the following graphs
The smaller white box bounds the text well because I know the coordinates of the text.
The smaller white box is not bounding the text because of some error during transforming the coordinates.
I follow the documentation reference for coefficients of perspective transformation
and find the coefficients of image transformation using the following code:origin of the code is from this answer
def find_coeffs(pa, pb):
'''
find the coefficients for perspective transform.
parameters:
pa : verticies in the resulting plane
pb : verticies in the current plane
retrun:
coeffs : 8- tuple
coefficents for PIL perspective transform
'''
matrix = []
for p1, p2 in zip(pa, pb):
matrix.append([p1[0], p1[1], 1, 0, 0, 0, -p2[0]*p1[0], -p2[0]*p1[1]])
matrix.append([0, 0, 0, p1[0], p1[1], 1, -p2[1]*p1[0], -p2[1]*p1[1]])
A = np.matrix(matrix, dtype=np.float)
B = np.array(pb).reshape(8)
res = np.dot(np.linalg.inv(A.T * A) * A.T, B)
return np.array(res).reshape(8)
My code for text bounding box transformation:
# perspective transformation
a, b, c, d, e, f, g, h = coeffs
# return two vertices defining the bounding box
new_x0 = float(a * new_x0 - b * new_y0 + c) / float(g * new_x0 + h * new_y0 + 1)
new_y0 = float(d * new_x0 + e * new_y0 + f) / float(g * new_x0 + h * new_y0 + 1)
new_x1 = float(a * new_x1 - b * new_y1 + c) / float(g * new_x1 + h * new_y1 + 1)
new_y1 = float(d * new_x1 + e * new_y1 + f) / float(g * new_x1 + h * new_y1 + 1)
I also went to Pillow Github, but I could not find the source code where perspective transformation is defined.
Some more info about the math of perspective transformation. The Geometry of Perspective Drawing on the Computer
Thanks.
To compute the new point after a transformation you should get the coefficients from A -> B not from B -> A, which is the standard from PIL library. As example:
# A1, B1 ... are points
# direct transform
coefs = find_coefs([B1, B2, B3, B4], [A1, A2, A3, A4])
# inverse transform
coefs_inv = find_coefs([A1, A2, A3, A4], [B1, B2, B3, B4])
You call the image.transform() function using the coefs_inv but calculate the new point using coefs to get something like this:
img = image.transform(((1500,800)),
method=Image.PERSPECTIVE,
data=coefs_inv)
a, b, c, d, e, f, g, h = coefs
old_p1 = [50, 100]
x,y = old_p1
new_x = (a * x + b * y + c) / (g * x + h * y + 1)
new_y = (d * x + e * y + f) / (g * x + h * y + 1)
new_p1 = (int(new_x),int(new_y))
old_p2 = [400, 500]
x,y = old_p2
new_x = (a * x + b * y + c) / (g * x + h * y + 1)
new_y = (d * x + e * y + f) / (g * x + h * y + 1)
new_p2 = (int(new_x),int(new_y))
Full code below:
import os
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
def find_coefs(original_coords, warped_coords):
matrix = []
for p1, p2 in zip(original_coords, warped_coords):
matrix.append([p1[0], p1[1], 1, 0, 0, 0, -p2[0]*p1[0], -p2[0]*p1[1]])
matrix.append([0, 0, 0, p1[0], p1[1], 1, -p2[1]*p1[0], -p2[1]*p1[1]])
A = np.matrix(matrix, dtype=np.float)
B = np.array(warped_coords).reshape(8)
res = np.dot(np.linalg.inv(A.T * A) * A.T, B)
return np.array(res).reshape(8)
coefs = find_coefs(
[(867,652), (1020,580), (1206,666), (1057,757)],
[(700,732), (869,754), (906,916), (712,906)]
)
coefs_inv = find_coefs(
[(700,732), (869,754), (906,916), (712,906)],
[(867,652), (1020,580), (1206,666), (1057,757)]
)
image = Image.open('sample.png')
img = image.transform(((1500,800)),
method=Image.PERSPECTIVE,
data=coefs_inv)
a, b, c, d, e, f, g, h = coefs
old_p1 = [50, 100]
x,y = old_p1
new_x = (a * x + b * y + c) / (g * x + h * y + 1)
new_y = (d * x + e * y + f) / (g * x + h * y + 1)
new_p1 = (int(new_x),int(new_y))
old_p2 = [400, 500]
x,y = old_p2
new_x = (a * x + b * y + c) / (g * x + h * y + 1)
new_y = (d * x + e * y + f) / (g * x + h * y + 1)
new_p2 = (int(new_x),int(new_y))
plt.figure()
plt.imshow(image)
plt.scatter([old_p1[0], old_p2[0]],[old_p1[1], old_p2[1]] , s=150, marker='.', c='b')
plt.show()
plt.figure()
plt.imshow(img)
plt.scatter([new_p1[0], new_p2[0]],[new_p1[1], new_p2[1]] , s=150, marker='.', c='r')
plt.show()

Plotting a NACA 4-series airfoil

I'm trying to plot an airfoil from the formula as described on this wikipedia page.
This Jupyter notebook can be viewed on this github page.
%matplotlib inline
import math
import matplotlib.pyplot as pyplot
def frange( start, stop, step ):
yield start
while start <= stop:
start += step
yield start
#https://en.wikipedia.org/wiki/NACA_airfoil#Equation_for_a_cambered_4-digit_NACA_airfoil
def camber_line( x, m, p, c ):
if 0 <= x <= c * p:
yc = m * (x / math.pow(p,2)) * (2 * p - (x / c))
#elif p * c <= x <= c:
else:
yc = m * ((c - x) / math.pow(1-p,2)) * (1 + (x / c) - 2 * p )
return yc
def dyc_over_dx( x, m, p, c ):
if 0 <= x <= c * p:
dyc_dx = ((2 * m) / math.pow(p,2)) * (p - x / c)
#elif p * c <= x <= c:
else:
dyc_dx = ((2 * m ) / math.pow(1-p,2)) * (p - x / c )
return dyc_dx
def thickness( x, t, c ):
term1 = 0.2969 * (math.sqrt(x/c))
term2 = -0.1260 * (x/c)
term3 = -0.3516 * math.pow(x/c,2)
term4 = 0.2843 * math.pow(x/c,3)
term5 = -0.1015 * math.pow(x/c,4)
return 5 * t * c * (term1 + term2 + term3 + term4 + term5)
def naca4( m, p, t, c=1 ):
for x in frange( 0, 1.0, 0.01 ):
dyc_dx = dyc_over_dx( x, m, p, c )
th = math.atan( dyc_dx )
yt = thickness( x, t, c )
yc = camber_line( x, m, p, c )
xu = x - yt * math.sin(th)
xl = x + yt * math.sin(th)
yu = yc + yt * math.cos(th)
yl = yc - yt * math.cos(th)
yield (xu, yu), (xl, yl)
#naca2412
m = 0.02
p = 0.4
t = 12
naca4points = naca4( m, p, t )
for (xu,yu),(xl,yl) in naca4points:
pyplot.plot( xu, yu, 'r,')
pyplot.plot( xl, yl, 'r,')
pyplot.ylabel('y')
pyplot.xlabel('x')
pyplot.axis('equal')
figure = pyplot.gcf()
figure.set_size_inches(16,16,forward=True)
The result looks like .
I expected it to look more like .
Questions: Why is the line not completely smooth? There seems to be a discontinuity where the beginning and end meet. Why does it not look like the diagram on wikipedia? How do I remove the extra loop at the trailing edge? How do I fix the chord so that it runs from 0.0 to 1.0?
First, t should be 0.12 not 12. Second, to make a smoother plot, increase the sample points.
It is also a good idea to use vectorize method in numpy:
%matplotlib inline
import math
import matplotlib.pyplot as plt
import numpy as np
#https://en.wikipedia.org/wiki/NACA_airfoil#Equation_for_a_cambered_4-digit_NACA_airfoil
def camber_line( x, m, p, c ):
return np.where((x>=0)&(x<=(c*p)),
m * (x / np.power(p,2)) * (2.0 * p - (x / c)),
m * ((c - x) / np.power(1-p,2)) * (1.0 + (x / c) - 2.0 * p ))
def dyc_over_dx( x, m, p, c ):
return np.where((x>=0)&(x<=(c*p)),
((2.0 * m) / np.power(p,2)) * (p - x / c),
((2.0 * m ) / np.power(1-p,2)) * (p - x / c ))
def thickness( x, t, c ):
term1 = 0.2969 * (np.sqrt(x/c))
term2 = -0.1260 * (x/c)
term3 = -0.3516 * np.power(x/c,2)
term4 = 0.2843 * np.power(x/c,3)
term5 = -0.1015 * np.power(x/c,4)
return 5 * t * c * (term1 + term2 + term3 + term4 + term5)
def naca4(x, m, p, t, c=1):
dyc_dx = dyc_over_dx(x, m, p, c)
th = np.arctan(dyc_dx)
yt = thickness(x, t, c)
yc = camber_line(x, m, p, c)
return ((x - yt*np.sin(th), yc + yt*np.cos(th)),
(x + yt*np.sin(th), yc - yt*np.cos(th)))
#naca2412
m = 0.02
p = 0.4
t = 0.12
c = 1.0
x = np.linspace(0,1,200)
for item in naca4(x, m, p, t, c):
plt.plot(item[0], item[1], 'b')
plt.plot(x, camber_line(x, m, p, c), 'r')
plt.axis('equal')
plt.xlim((-0.05, 1.05))
# figure.set_size_inches(16,16,forward=True)
Thanks for the code.
I have modified the code for symmetrical airfoils:
def naca4s(x, t, c=1):
yt = thickness(x, t, c)
return ((x, yt),
(x, -yt))

Intersections between Geodesics (shortest distance paths) on the surface of a sphere

I've searched far and wide but have yet to find a suitable answer to this problem. Given two lines on a sphere, each defined by their start and end points, determine whether or not and where they intersect. I've found this site (http://mathforum.org/library/drmath/view/62205.html) which runs through a good algorithm for the intersections of two great circles, although I'm stuck on determining whether the given point lies along the finite section of the great circles.
I've found several sites which claim they've implemented this, Including some questions here and on stackexchange, but they always seem to reduce back to the intersections of two great circles.
The python class I'm writing is as follows and seems to almost work:
class Geodesic(Boundary):
def _SecondaryInitialization(self):
self.theta_1 = self.point1.theta
self.theta_2 = self.point2.theta
self.phi_1 = self.point1.phi
self.phi_2 = self.point2.phi
sines = math.sin(self.phi_1) * math.sin(self.phi_2)
cosines = math.cos(self.phi_1) * math.cos(self.phi_2)
self.d = math.acos(sines - cosines * math.cos(self.theta_2 - self.theta_1))
self.x_1 = math.cos(self.theta_1) * math.cos(self.phi_1)
self.x_2 = math.cos(self.theta_2) * math.cos(self.phi_2)
self.y_1 = math.sin(self.theta_1) * math.cos(self.phi_1)
self.y_2 = math.sin(self.theta_2) * math.cos(self.phi_2)
self.z_1 = math.sin(self.phi_1)
self.z_2 = math.sin(self.phi_2)
self.theta_wraps = (self.theta_2 - self.theta_1 > PI)
self.phi_wraps = ((self.phi_1 < self.GetParametrizedCoords(0.01).phi and
self.phi_2 < self.GetParametrizedCoords(0.99).phi) or (
self.phi_1 > self.GetParametrizedCoords(0.01).phi) and
self.phi_2 > self.GetParametrizedCoords(0.99))
def Intersects(self, boundary):
A = self.y_1 * self.z_2 - self.z_1 * self.y_2
B = self.z_1 * self.x_2 - self.x_1 * self.z_2
C = self.x_1 * self.y_2 - self.y_1 * self.x_2
D = boundary.y_1 * boundary.z_2 - boundary.z_1 * boundary.y_2
E = boundary.z_1 * boundary.x_2 - boundary.x_1 * boundary.z_2
F = boundary.x_1 * boundary.y_2 - boundary.y_1 * boundary.x_2
try:
z = 1 / math.sqrt(((B * F - C * E) ** 2 / (A * E - B * D) ** 2)
+ ((A * F - C * D) ** 2 / (B * D - A * E) ** 2) + 1)
except ZeroDivisionError:
return self._DealWithZeroZ(A, B, C, D, E, F, boundary)
x = ((B * F - C * E) / (A * E - B * D)) * z
y = ((A * F - C * D) / (B * D - A * E)) * z
theta = math.atan2(y, x)
phi = math.atan2(z, math.sqrt(x ** 2 + y ** 2))
if self._Contains(theta, phi):
return point.SPoint(theta, phi)
theta = (theta + 2* PI) % (2 * PI) - PI
phi = -phi
if self._Contains(theta, phi):
return spoint.SPoint(theta, phi)
return None
def _Contains(self, theta, phi):
contains_theta = False
contains_phi = False
if self.theta_wraps:
contains_theta = theta > self.theta_2 or theta < self.theta_1
else:
contains_theta = theta > self.theta_1 and theta < self.theta_2
phi_wrap_param = self._PhiWrapParam()
if phi_wrap_param <= 1.0 and phi_wrap_param >= 0.0:
extreme_phi = self.GetParametrizedCoords(phi_wrap_param).phi
if extreme_phi < self.phi_1:
contains_phi = (phi < max(self.phi_1, self.phi_2) and
phi > extreme_phi)
else:
contains_phi = (phi > min(self.phi_1, self.phi_2) and
phi < extreme_phi)
else:
contains_phi = (phi > min(self.phi_1, self.phi_2) and
phi < max(self.phi_1, self.phi_2))
return contains_phi and contains_theta
def _PhiWrapParam(self):
a = math.sin(self.d)
b = math.cos(self.d)
c = math.sin(self.phi_2) / math.sin(self.phi_1)
param = math.atan2(c - b, a) / self.d
return param
def _DealWithZeroZ(self, A, B, C, D, E, F, boundary):
if (A - D) is 0:
y = 0
x = 1
elif (E - B) is 0:
y = 1
x = 0
else:
y = 1 / math.sqrt(((E - B) / (A - D)) ** 2 + 1)
x = ((E - B) / (A - D)) * y
theta = (math.atan2(y, x) + PI) % (2 * PI) - PI
return point.SPoint(theta, 0)
def GetParametrizedCoords(self, param_value):
A = math.sin((1 - param_value) * self.d) / math.sin(self.d)
B = math.sin(param_value * self.d) / math.sin(self.d)
x = A * math.cos(self.phi_1) * math.cos(self.theta_1) + (
B * math.cos(self.phi_2) * math.cos(self.theta_2))
y = A * math.cos(self.phi_1) * math.sin(self.theta_1) + (
B * math.cos(self.phi_2) * math.sin(self.theta_2))
z = A * math.sin(self.phi_1) + B * math.sin(self.phi_2)
new_phi = math.atan2(z, math.sqrt(x**2 + y**2))
new_theta = math.atan2(y, x)
return point.SPoint(new_theta, new_phi)
EDIT: I forgot to specify that if two curves are determined to intersect, I then need to have the point of intersection.
A simpler approach is to express the problem in terms of geometric primitive operations like the dot product, the cross product, and the triple product. The sign of the determinant of u, v, and w tells you which side of the plane spanned by v and w contains u. This enables us to detect when two points are on opposite sites of a plane. That's equivalent to testing whether a great circle segment crosses another great circle. Performing this test twice tells us whether two great circle segments cross each other.
The implementation requires no trigonometric functions, no division, no comparisons with pi, and no special behavior around the poles!
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def dot(v1, v2):
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
def cross(v1, v2):
return Vector(v1.y * v2.z - v1.z * v2.y,
v1.z * v2.x - v1.x * v2.z,
v1.x * v2.y - v1.y * v2.x)
def det(v1, v2, v3):
return dot(v1, cross(v2, v3))
class Pair:
def __init__(self, v1, v2):
self.v1 = v1
self.v2 = v2
# Returns True if the great circle segment determined by s
# straddles the great circle determined by l
def straddles(s, l):
return det(s.v1, l.v1, l.v2) * det(s.v2, l.v1, l.v2) < 0
# Returns True if the great circle segments determined by a and b
# cross each other
def intersects(a, b):
return straddles(a, b) and straddles(b, a)
# Test. Note that we don't need to normalize the vectors.
print(intersects(Pair(Vector(1, 0, 1), Vector(-1, 0, 1)),
Pair(Vector(0, 1, 1), Vector(0, -1, 1))))
If you want to initialize unit vectors in terms of angles theta and phi, you can do that, but I recommend immediately converting to Cartesian (x, y, z) coordinates to perform all subsequent calculations.
Intersection using plane trig can be calculated using the below code in UBasic.
5 'interx.ub adapted from code at
6 'https://rosettacode.org
7 '/wiki/Find_the_intersection_of_two_linesSinclair_ZX81_BASIC
8 'In U Basic by yuji kida https://en.wikipedia.org/wiki/UBASIC
10 XA=48.7815144526:'669595.708
20 YA=-117.2847245001:'2495736.332
30 XB=48.7815093807:'669533.412
40 YB=-117.2901673467:'2494425.458
50 XC=48.7824947147:'669595.708
60 YC=-117.28751374:'2495736.332
70 XD=48.77996737:'669331.214
80 YD=-117.2922957:'2494260.804
90 print "THE TWO LINES ARE:"
100 print "YAB=";YA-XA*((YB-YA)/(XB-XA));"+X*";((YB-YA)/(XB-XA))
110 print "YCD=";YC-XC*((YD-YC)/(XD-XC));"+X*";((YD-YC)/(XD-XC))
120 X=((YC-XC*((YD-YC)/(XD-XC)))-(YA-XA*((YB-YA)/(XB-XA))))/(((YB-YA)/(XB-XA))-((YD-YC)/(XD-XC)))
130 print "Lat = ";X
140 Y=YA-XA*((YB-YA)/(XB-XA))+X*((YB-YA)/(XB-XA))
150 print "Lon = ";Y
160 'print "YCD=";YC-XC*((YD-YC)/(XD-XC))+X*((YD-YC)/(XD-XC))

Categories

Resources