Given the first line from a to b where a < b and the second line from x to y where x < y, how do you calculate the intersection length of those two?
Example:
a =0, b=5, x=3, y=7
012345
|----|
|---|
34567
the result would be 2 since they are intersection from 3 to 5.
Is there an expression with these 4 variables to extract the result? There is no guarantee that there is an intersection nor is it guaranteed that x > a
I have looked at timespan intersection examples but they all have an if expression in them which is not possible in my situation.
Logic is quite simple:
if (y<a) or (x>b):
return no intersection
intersection.left = max(a, x)
intersectioni.right = min(b, y)
Related
I have a line AB. I would like to draw a line BC, perpendicular to AB. I know xyz of the points A and B, I also know the distance N between B and C. How can I find an arbitrary point C which fits into the given parameters? The calculations should be done in 3-D. Any point, perpendicular to AB can be the point C, if its distance to B equals N.
An almost identical question is given here, but I would like to know how the same thing is done in 3-D: How do you find a point at a given perpendicular distance from a line?
The calculation that works for me in 2-D was given in the link above:
dx = A.x-B.x
dy = A.y-B.y
dist = sqrt(dx*dx + dy*dy)
dx /= dist
dy /= dist
C.x = B.x + N*dy
C.y = B.y - N*dx
I tried adding Z axis to it like this:
dz = A.z - B.z
dist = sqrt(dx*dx + dy*dy + dz*dz)
dz /=dist
C.z = .... at this point it becomes a mystery to me
If I put something like "C.z - N*dz" into C.z, the distance is accurate only in some rotation angles, I would like to know the correct solution. I can imagine that in 3-D it is calculated in a completely different manner.
Clarification
Point C is not unique. It can be any point on a circle with its
centre at B and radius N. The circle is perpendicular to AB
If the desired point C can be any of the infinitely-many points fitting your requirements, here is one method.
Choose any vector that is not parallel or anti-parallel to vector AB. You could try the vector (1, 0, 0), and if that is parallel you could use (0, 1, 0) instead. Then take the cross-product of vector AB and the chosen vector. That cross-product is perpendicular to vector AB. Divide that cross-product by its length then multiply by the desired length N. Finally extend that vector from point B to find your desired point C.
Here is code in Python 3 that follows that algorithm. This code is somewhat non-pythonic to make it easier to convert to other languages. (If I really did this for myself I would use the numpy module to avoid coordinates completely and shorten this code.) But it does treat the points as tuples of 3 values: many languages will require you to handle each coordinate separately. Any real-life code would need to check for "near zero" rather than "zero" and to check that the sqrt calculation does not result in zero. I'll leave those additional steps to you. Ask if you have more questions.
from math import sqrt
def pt_at_given_distance_from_line_segment_and_endpoint(a, b, dist):
"""Return a point c such that line segment bc is perpendicular to
line segment ab and segment bc has length dist.
a and b are tuples of length 3, dist is a positive float.
"""
vec_ab = (b[0]-a[0], b[1]-a[1], b[2]-a[2])
# Find a vector not parallel or antiparallel to vector ab
if vec_ab[1] != 0 or vec_ab[2] != 0:
vec = (1, 0, 0)
else:
vec = (0, 1, 0)
# Find the cross product of the vectors
cross = (vec_ab[1] * vec[2] - vec_ab[2] * vec[1],
vec_ab[2] * vec[0] - vec_ab[0] * vec[2],
vec_ab[0] * vec[1] - vec_ab[1] * vec[0])
# Find the vector in the same direction with length dist
factor = dist / sqrt(cross[0]**2 + cross[1]**2 + cross[2]**2)
newvec = (factor * cross[0], factor * cross[1], factor * cross[2])
# Find point c such that vector bc is that vector
c = (b[0] + newvec[0], b[1] + newvec[1], b[2] + newvec[2])
# Done!
return c
The resulting output from the command
print(pt_at_given_distance_from_line_segment_and_endpoint((1, 2, 3), (4, 5, 6), 2))
is
(4.0, 6.414213562373095, 4.585786437626905)
I have two points which form one line: (1,4) and (3,6), and another two which form another line: (2,1) and (4,2). These lines are continuous and I can find their intersection points by finding the equation for each line, and then equating them to find the x value at the intersection point, and then the y value.
i.e. for the first line, the equation is y = x + 3, and the second is y = 0.5x. At the intersection the y values are the same so x + 3 = 0.5x. So x = -6. Subbing this back into either of the equations gives a y value of -3.
From those steps, I now know that the intersection point is (-6,-3). The problem is I need to do the same steps in Excel, preferably as one formula. Can anyone give me some advice on how I would start this?
Its long but here it is:
Define x1,y1 and x2,y2 for the 1st line and x3,y3 and x4,y4 for the second.
x = (x2y1-x1y2)(x4-x3)-(x4y3-x3y4)(x2-x1) / [ (x2-x1)(y4-y3) - (x4-x3)(y2-y1) ]
y = (x2y1-x1y2)(y4-y3)-(x4y3-x3y4)(y2-y1) / [ (x2-x1)(y4-y3) - (x4-x3)(y2-y1) ]
Note that the denominators are the same. They will be ZERO! when the system has no solution. So you may want to check that in another cell and conditionally compute the answer.
Essentially, this formula is derived by solving a system of equations for x and y by hand using generic points (x1,y1), (x2,y2), (x3,y3), and (x4,y4). Easier yet, is solving the system by hand using well developed linear algebra concepts.
Wikipedia outlines this procedure well: Line-line intersection.
Also, this website describes all the different formulas and lets you put in whatever data you have in any mixed format and provides many details of the solutions: Everything about 2 lines.
Here's a matrix based solution:
x - y = -3
0.5*x - y = 0
Written as a matrix equation (I apologize for the poor typesetting):
| 1.0 -1.0 |{ x } { -3 }
| 0.5 -1.0 |{ y } = { 0 }
You can invert this matrix or use LU decomposition to solve it to get the answer. That method will work for any number of cases where you have one equation for each unknown.
This is easy to do by hand:
Subtract the second equation from the first: 0.5*x = -3
Divide both sides by 0.5: x = -6
Substitute this result into the other equation: y = 0.5*x = -3
I have 4 points in space A(x,y,z), B(x,y,z), C(x,y,z) and D(x,y,z). How can I check if these points are the corner points of a rectangle?
You must first determine whether or not the points are all coplanar, since a rectangle is a 2D geometric object, but your points are in 3-space. You can determine they are coplanar by comparing cross products as in:
V1 = (B-A)×(B-C)
V2 = (C-A)×(C-D)
This will give you two vectors which, if A, B, C, and D are coplanar are linearly dependent. By considering what Wolfram has to say on vector dependence, we can test the vectors for linear dependence by using
C = (V1∙V1)(V2∙V2) - (V1∙V2)(V2∙V1)
If C is 0 then the vectors V1 and V2 are linearly dependent and all the points are coplanar.
Next compute the distances between each pair of points. There should be a total of 6 such distances.
D1 = |A-B|
D2 = |A-C|
D3 = |A-D|
D4 = |B-C|
D5 = |B-D|
D6 = |C-D|
Assuming none of these distances are 0, these points form a rectangle if and only if the vertices are coplanar (already verified) and these lengths can be grouped into three pairs where elements of each pair have the same length. If the figure is a square, two sets of the pairs will have be the same length and will be shorter than the remaining pair.
Update: Reading this again, I realize the the above could define a parallelogram, so an additional check is required to check that the square of the longest distance is equal to the sum of the squares of the two shorter distances. Only then will the parallelogram also be a rectangle.
Keep in mind all of this is assuming infinite precision and within a strictly mathematical construct. If you're planning to code this up, you will need to account for rounding and accept a degree of imprecision that's not really a player when speaking in purely mathematical terms.
Check if V1=B-A and V2=D-A are orthogonal using the dot product. Then check if
C-A == V1+V2
within numerical tolerances. If both are true, the points are coplanar and form a rectangle.
Here a function is defined to check whether the 4 points represents the rectangle or not .
from math import sqrt
def Verify(A, B, C, D, epsilon=0.0001):
# Verify A-B = D-C
zero = sqrt( (A[0]-B[0]+C[0]-D[0])**2 + (A[1]-B[1]+C[1]-D[1])**2 + (A[2]-B[2]+C[2]-D[2])**2 )
if zero > epsilon:
raise ValueError("Points do not form a parallelogram; C is at %g distance from where it should be" % zero)
# Verify (D-A).(B-A) = 0
zero = (D[0]-A[0])*(B[0]-A[0]) + (D[1]-A[1])*(B[1]-A[1]) + (D[2]-A[2])*(B[2]-A[2])
if abs(zero) > epsilon:
raise ValueError("Corner A is not a right angle; edge vector dot product is %g" % zero)
else:
print('rectangle')
A = [x1,y1,z1]
print(A)
B = [x2,y2,z2]
C = [x3,y3,z3]
D = [x4,y4,z4]
Verify(A, B, C, D, epsilon=0.0001)
I'm need to compute the fact of intersection of ray and segment in one plane and the distance from ray origin to intersection point, but I very bad know computation geometry, so... how to do it?
Segment with endpoints A and B (all vectors) has an equation:
P(x) = A * x + B * (1 - x)
where 0 <= x <= 1.
Ray with origin R and directional (unit) vector U has an equation:
Q(y) = R + U * y
where y >= 0.
You just need to solve the equation:
P(x) = Q(y)
That is, to find parameters x and y (if they exist), satisfying this (vector) equation. You will have two scalar equations and two variables to calculate. You can easily solve this linear system and then check conditions 0 <= x <= 1 and y >= 0. If these conditions are both satisfied you got a solution, otherwise there are no intersection. The y value will give you distance from the ray origin to the intersection point.
Also you have to consider many degenerate cases, for example - the ray passes via both segment endpoints etc.
How to find a bisecor b = (bx, by) of two vectors in general (we consider two non–zero vectors u = (ux, uy), v = (vx, vy), that may be collinear ).
For non-collinear vector we can write:
bx = ux/|u| + vx / |v|
by = uy/|u| + vy / |v|
But for collinear vectors
bx = by = 0.
Example:
u = (0 , 1)
v = (0, -1)
b = (0, 0)
A general and uniform approach is to get the angle of both vectors
theta_u = math.atan2(ux, uy)
theta_v = math.atan2(vx, vy)
and to create a new vector with the average angle:
middle_theta = (theta_u+theta_v)/2
(bx, by) = (cos(middle_theta), sin(middle_theta))
This way, you avoid the pitfall that you observed with opposite vectors.
PS: Note that there is an ambiguity in what the "bisector" vector is: there are generally two bisector vectors (typically one for the smaller angle and one for the larger angle). If you want the bisector vector inside the smaller angle, then your original formula is quite good; you may handle separately the special case that you observed for instance by taking a vector orthogonal to any of the two input vectors (-uy/|u|, ux/|u|) if your formula yields the null vector.
To find the unit bisection vectors of u and v.
if u/|u|+v/|v| !=0
first calculate the unit vector of u and v
then use the parallelogram rule to get the bisection (just add them)
since they both have unit of 1, their sum is the bisector vector
then calculate the unit vector of the calculated vector.
else (if u/|u|+v/|v| ==0):
(if you use the method above, it's like a indintermination: 0*infinity=?)
if you want the bisector of (u0v) if u/|u| = (cos(t),sin(t))
take b=(cost(t+Pi/2),sin(t+Pi/2)) = (-sin(t),cos(t) )as the bisector
therefore if u/|u|=(a1,a2) chose b=(-a2,a1)
Example:
u=(0,1)
v=(0,-1)
the bisector of (u0v):
b=(-1,0)