Equation for Sliding Collision of LineSegments - geometry

I need an equation to find point F.
Point A, B, and D are known. Point F is unknown. Point F is on line AB. Line AB is perpendicular to line DF. What is the equation for F?

I'm assuming you want something computationally fast, since you mention 'collision', and this is Stack Overflow. First, a diagram:
We want to calculate the components of AF, which we'll label f = qi + pj. AFD forms a triangle, so we can get the length of f from AD, which we'll label d. Let's mark lengths in italics versus vectors in bold:
f = d cos(θ).
But trig is computationally expensive. So let's use the fact that the vector dot product between b (AB) and d is:
b · d = b d cos(θ)
The angle is the same because AF and AB are on the same line. Substituting in for dcos(θ):
b · d = b f
f = (b · d) / b
Now we have f, but we want its components p and q. Calling the angle to the horizontal φ:
q = f cos(φ)
p = f sin(φ)
But again we're avoiding trig. We know that f is along b, so f = kb, and in fact using the unit vector in the direction of b:
f = f (b/b)
Substituting our expression for f:
f = [(b · d) / b ] (b/b)
= [(b/ b) · d ] (b/b)
= [b · d] b / (b2)
Defining a factor k which is common to both components:
k = (bx dx + by dy) /b2
By keeping the b2 separate, we can avoid a square root operation to get the unit vector along b
Our components, then:
q = k bx
p = k by
Finally, add back in the offset of point A.
Fx = Ax + q
Fy = Ay + p
So, the pseudo code:
var vbx = Bx - Ax; //vector b x component
var vby = By - Ay; //vector b y component
var dot = vbx*(Dx-Ax) + vby*(Dy-Ay); // dot product of b and d
var k = dot/(vbx*vbx + vby*vby); // inverse of square of vector b length
var fx = Ax + k*vbx
var fy = Ay + k*vby
No square root calls, no trig, 8 additions/subtractions, 6 multiplications, 1 division. The only instabilities I can see are: divide by zero when A and B are at the same position, possible overflow calculating dot if AB is large and AD is large.

First, find the slope of line AB with the point-slope formula using A and B's coordinates:
Point Slope Formula
You can then find b to finished the equation for line AB:
y = mx + b where m is the slope you already found and b is the y-intercept that you just found.
The slope of line DF would be the negative reciprocal of the slope of line AB. Plug this into the equation:
y = mx + b where m is the negative reciprocal of the slope of line AB and b comes later.
Now, solve for b using the x and y values of point D, and plug that into the equation.
You should now have an equation for line DF and another equation for line AB. Now solve for the intercept of the two equations by setting them equal to one another and solving for x first and then plugging in x and finding y.
Here's an example.
A = (1, 2). B = (4, 8). D = (2, 5).
Line AB:
(y - y1) = m*(x - x1)
(1 - 4) = m*(2 - 8)
-3 = m*(-6)
0.5 = m
y = (0.5)*x + b
2 = (0.5)*1 + b
2 = (0.5) + b
1.5 = b
y = 0.5*x + 1.5
Line DF:
m = -(1/mAB)
m = -(1/0.5)
m = -2
y = -2*x + b
5 = -2*2 + b
5 = -4 + b
9 = b
y = -2*x + 9
Intersection of AB and DF (i.e. coordinates of point F)
Line DF: y = -2*x + 9
Line AB: y = 0.5*x + 1.5
-2*x + 9 = 0.5*x + 1.5
9 = 2.5*x + 1.5
7.5 = 2.5*x
x = 3
y = -2*x + 9
y = -2*3 + 9
y = -6 + 9
y = 3
F = (3, 3)

You haven't specified exactly where point F is along line DF, so there's no single answer. If you're just trying to find SOME point along a line perpendicular to line AB, from point D, then
F.x = D.x + (B.y - A.y)
F.y = D.y + (B.x - A.x)
will work.

Related

Understanding implementation of Extended Euclidean algorithm

After some experimentation and search, I came up with the following definition:
emcd' :: Integer -> Integer -> (Integer,Integer,Integer)
emcd' a 0 = (a, 1, 0)
emcd' a b =
let (g, t, s) = emcd' b r
in (g, s, t - (q * s))
where
(q, r) = divMod a b
What's the meaning behind this expression t - (q * s) ?
I've tried to evaluate it by hand; even though I arrived at the correct result (1, -4, 15), I can't see why that expression returns the value of t.
There is a famous method for calculating s and t in as + bt = gcd(a, b). In the process of finding the gcd, I get several equations.
By reversing the steps in the Euclidean Algorithm, it is possible to find these integers a and b. Those resulting equations look like the expression t - (q * s); however, I can't figure out the exact process.
Since (q, r) = divMod a b, we have the equation
a = qb + r
and because of the recursive call, we have:
tb + sr = g
Substituting a-qb for r in the second equation, that means
tb + s(a-qb) = g
tb + sa - qsb = g
sa + (t-qs)b = g
This explains why s and t - q*s are good choices to return.

Multi Parameter Function Replacement with Sympy

I've got a math equation that I want to visually record the substitution of.
The equation is y = h * f(t + h, h + f(t, h)), where f(x, y) = x + y - 1
I want to substitute f into y, such that I get:
y = h * f(t + h, h + (t + h - 1))
y = h * (t + h + h + (t + h - 1) - 1)
I've had issues with replace not allowing me to do multi-parameter substitution
I don't have much code, since I'm not sure how to implement it
from sympy import *
f = Function('f')(x, y)
eqn = h * f(t + h, h + f(t, h))
Thanks
sympy.Function is used for declaring undefined functions but in your case the function is known.
The following code seems to work fine over here
from sympy import *
x,y,t,h = symbols('x y t h')
def f(x,y):
return x + y - 1
y = h * f(t+h,h+f(t,h))
y = expand(y)
display(y)
The role of the expand function was to work out the outer multiplication by h in the definition of y.
You can run it in a Jupyter notebook or as an alternative use the print or display function, I get the following result:
Extending average's answer -- Their solution works perfectly if the function is known.
To make it work for a function that's input from the user, you need to do this:
function = input()
def f(x, y, evaluate = False):
eqn = sympify(function)
if evaluate:
eqn = eqn.subs([("x", x), ("y", y)])
return eqn
y = h + f(h, t, True)
This way, if the user inputs "x ** y" for f, y will expand to h + h ** t

Diagonals with same characters - Python

The program must accept a character matrix of size RxC as the input. The program must print the number of diagonals that parallel to the top-left to bottom-right diagonal and having the same characters in the matrix.
def lower_diagonals(row,matrix):
# a list to store the lower diagonals
# which are || to top left to bottom right
d=[]
# Iterating from the second row till the last row
for i in range(1,row):
nop,dummy = [],0
for j in range(i,row):
try:
nop.append(matrix[j][dummy])
except:
break
dummy+=1
d.append(nop)
return d
def upper_diagonals(col,matrix):
# a list to store the lower diagonals
# which are || to top left to bottom right
d=[]
# Iterating from 1st column till the last column
for i in range(1,col):
dum , nop = i,[]
# Iterating till the last before row
for j in range(row-1):
try:
nop.append(matrix[j][dum])
except:
break
dum+=1
d.append(nop)
return d
def diagonals(matrix,row,col):
return lower_diagonals(row,matrix) + upper_diagonals(col,matrix)
row,col = map(int,input().input().split())
matrix =[input().strip().split(' ') for i in range(row)]
new_matrix = diagonals(matrix,row,col)
t=0
for i in new_matrix:
if len(list(set(i))) == 1 : t+=1
print(t)
Example :
Input :
4 4
u m o a
h n a o
y h r w
b n h e
Output:
4
Input :
5 7
G a # z U p 3
e G b # n U p
a e G m # e U
L l e g k # t
j L a e G s #
Output:
6
My code works perfect for all the above mentioned cases but it fails for the below case
Input :
2 100
b h D k 2 D 9 I e Q # * B 5 H Z r q u n P C 4 a e K l 2 E p 6 R V v 0 d 8 x C F P M F C e m K H O y # 0 I T r P 8 P N 9 Z 7 S J J P c L g x X f 5 1 o i Y V Y G Y 9 A E O 2 r 2 # S 8 z D 6 a q r i k r
V o 4 T M m z p 6 G H D Y a 6 t O 7 # w y t 2 m A 1 a + 0 p t P D z 7 V N T x + I t 4 x x y 1 Q G M t M 0 v d G e u 4 b 8 m D # I v D i T 1 u L f e 1 Y E Y q Y c A 8 P 2 q 2 A 8 y b u E 3 c 1 s M n X
Expected Output:
9
My Output:
100
Can anyone help me in structuring the logic for this case Thanks in advance
Note :
2<=R,C<=100
Time limit : 500ms
I think i probably found a logic for my problem
r,c = map(int,input().strip().split())
mat = []
for i in range(r):
l = list(map(str,input().strip().split()))
mat.append(l[::-1])
count = 0
for i in range(r+c-1):
l = []
for row in range(r):
for col in range(c):
if row+col == i:
l.append(mat[row][col])
l = list(set(l))
if len(l) == 1:
count+=1
print(count)

Algorithm to calculate exponent using recursion and mod

I was taught a different way to calculate exponents using mod and recursion, but I don't fully understand it. The method is: To do b^e, we can break it down like so:
q = e div 2
r = e mod 2
then e = 2q+r, and r could be 0 or 1.
If r=0:
b^e = (b^q)^2
If r=1:
b^e = (b^q)^2 * b
base case: b^0 = 1.
For example: 2^2, b=2, e=2.
q = 2/2 = 1
r = 2mod2 = 0
r=0, therefore 2^2 = 2^1^2
I am trying to code this.
pow :: Integer -> Integer -> Integer
pow b e
| e == 0 = 1
| r == 0 = pow (pow b q) 2
| r == 1 = b * pow (pow b q) 2
where
(q, r) = divMod e 2
But the code does not end any time when e!=0, for example, pow (-2) 4 or pow 1 1 goes on forever. Any idea why?
If you try evaluating pow b 2 by hand you'll quickly see why. Since divMod 2 2 = (1, 0), we expand from pow b 2 to pow (pow b 1) 2. Note that this is also of the form pow b' 2, with b' = pow b 1. So we just get an infinite chain:
pow b 2
=
pow (pow b 1) 2
=
pow (pow (pow b 1) 1) 2
=
pow (pow (pow (pow b 1) 1) 1) 2
=
...
There's a couple ways to solve it. You could add a base case for e == 2, or instead of recursively calling pow twice you could just do the multiplication yourself (as in replacing pow foo 2 with foo * foo in your existing code).
You also need to provide a base case for when e is 2:
pow b 2 = b * b
Without this, your recursion doesn't end, because it becomes pow (pow b 1) 2 and you don't get anywhere.
As mentioned in the previous answers, your code almost works, and it is just a matter of allowing the recursion to stop.
See the code below for a possible fix. The argument of the recursive call is at most half the current argument, hence the recursion will have to stop.
On a side note, this algorithm is more than 2,000 years old, and originated in ancient India. Please treat it with all due respect :-)
https://mathoverflow.net/questions/107708/origin-of-square-and-multiply-algorithm
pow :: Integer -> Integer -> Integer
pow b e
| e == 0 = 1
| r == 0 = let bpq = pow b q in bpq*bpq
| r == 1 = let bpq = pow b q in bpq*bpq*b
where
(q, r) = divMod e 2
main = do
let b = 3 :: Integer
let e = 7 :: Integer
let x = b^e
putStrLn ("b^e = " ++ show x)
let y = pow b e
putStrLn ("pow b e = " ++ show y)

Haskell numerical integration via Trapezoidal rule results in wrong sign

I've written some code that's meant to integrate a function numerically using the trapezoidal rule. It works, but the answer it produces has a wrong sign. Why might that be?
The code is:
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + partial_sum)
where
h = (b - a) / 1000
most_parts = map f (points (1000-1) h)
partial_sum = sum most_parts
points :: Double -> Double -> [Double]
points x1 x2
| x1 <= 0 = []
| otherwise = (x1*x2) : points (x1-1) x2
Trapezoidal rule
The code is probably inelegant, but I'm only a student of Haskell and would like to deal with the current problem first and coding style matters after that.
Note: This answer is written in literate Haskell. Save it with .lhs as extension and load it in GHCi to test the solution.
Finding the culprit
First of all, let's take a look at integration. In its current form, it contains only summation of function values f x. Even though the factors aren't correct at the moment, the overall approach is fine: you evaluate f at the grid points. However, we can use the following function to verify that there's something wrong:
ghci> integration (\x -> if x >= 10 then 1 else (-1)) 10 15
-4.985
Wait a second. x isn't even negative in [10,15]. This suggests that you use the wrong grid points.
Grid points revisited
Even though you've linked the article, let's have a look at an exemplary use of the trapezoidal rule (public domain, original file by Oleg Alexandrov):
Although this doesn't use a uniform grid, let's suppose that the 6 grid points are equidistant with grid distance h = (b - a) / 5. What are the x coordinates of those points?
x_0 = a + 0 * h (== a)
x_1 = a + 1 * h
x_2 = a + 2 * h
x_3 = a + 3 * h
x_4 = a + 4 * h
x_5 = a + 5 * h (== b)
If we use set a = 10 and b = 15 (and therefore h = 1), we should end up with [10, 11, 12, 13, 14, 15]. Let's check your points. In this case, you would use points 5 1 and end up with [5,4,3,2,1].
And there's the error. points doesn't respect the boundary. We can easily fix this by using pointsWithOffset:
> points :: Double -> Double -> [Double]
> points x1 x2
> | x1 <= 0 = []
> | otherwise = (x1*x2) : points (x1-1) x2
>
> pointsWithOffset :: Double -> Double -> Double -> [Double]
> pointsWithOffset x1 x2 offset = map (+offset) (points x1 x2)
That way, we can still use your current points definition to generate grid points from x1 to 0 (almost). If we use integration with pointsWithOffset, we end up with
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + partial_sum)
where
h = (b - a) / 1000
most_parts = map f (pointsWithOffset (1000-1) h a)
partial_sum = sum most_parts
Tying up loose ends
However, this doesn't take into account that you use all inner points twice in the trapezoid rule. If we add the factors, we end up with
> integration :: (Double -> Double) -> Double -> Double -> Double
> integration f a b =
> h / 2 * (f a + f b + 2 * partial_sum)
> -- ^^^ ^^^
> where
> h = (b - a) / 1000
> most_parts = map f (pointsWithOffset (1000-1) h a)
> partial_sum = sum most_parts
Which yields the correct value for our test function above.
Exercise
Your current version only supports 1000 grid points. Add an Int argument so that one can change the number of grid points:
integration :: Int -> (Double -> Double) -> Double -> Double -> Double
integration n f a b = -- ...
Furthermore, try to write points in different ways, for example go from a to b, use takeWhile and iterate, or even a list comprehension.
Yes it indeed was the points plus you had some factors wrong (the inner points are multiplied by 2) - this is the fixed version of your code:
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + innerSum) / 2
where
h = (b - a) / 1000
innerPts = map ((2*) . f . (a+)) (points (1000-1) h)
innerSum = sum innerPts
points :: Double -> Double -> [Double]
points i x
| i <= 0 = []
| otherwise = (i*x) : points (i-1) x
which gives sensible approximations (to 1000 points):
λ> integration (const 2) 1 2
2.0
λ> integration id 1 2
1.5
λ> integration (\x -> x*x) 1 2
2.3333334999999975
λ> 7/3
2.3333333333333335

Resources