Calculate approximate location between two locations - algorithm

I'm implementing simple navigation, and I need to compute approximate location (GPS) on my route. Route is a list of points, so basically it looks like this:
(latX, longX)
(lat1, long1) o------o---------------o (lat2, long2)
|
|
o
(lat3, long3) - GPS My location
I have a two points (lat1, long1) and (lat2, long2) and my location (lat3, long3). How can I compute (latX, longX)?

Let me try to give you a sketch of how I would divide the problem into smaller steps.
Consider the Earth as a perfect 3D sphere of radius r.
Transform positions given by (lat, long) pairs into 3D points (x, y, z) on the surface of the sphere, i.e., with x^2 + y^2 + z^2 = r^2. You will also need the inverse transformation to get back to (lat, long) coordinates.
Lets put (using 2 above)
P1 := (x1, y1, z1) <-> (lat1, long1)
P2 := (x2, y2, z2) <-> (lat2, long2)
P3 := (x3, y3, z3) <-> (lat3, long3)
P := (x, y, z) <-> (latX, longX)
Let H be the plane containing the origin (at the center of the Earth) and the points P1 and P2. Note that H intersects the surface of the sphere in the path that joins P1 with P2 as in your illustration.
Let (a, b, c) perpendicular to H. You can find it by solving the matrix equation Mv = 0, where M is the matrix whose rows are (x1, y1, z1) and (x2, y2, z2) and v is the unknown column with coordinates (a, b, c).
Let Q = (x3, y3, z3) + u*(a, b, c), where u is the coefficient for which Q = (q1, q2, q3) lines in H. You can calculate u by solving the matrix equation Mv = P3, where M is the 3x3 matrix with columns (x1, y1, z1), (x2, y2, z2) and (-a, -b, -c), v is the unknown column (s, t, u) and P3 stands for the column (x3, y3, z3).
Let P = w*Q, where w is the coefficient for which P = (x, y, z) with x^2 + y^2 + z^2 = r^2.
Use the inverse of the transformation mentioned in step 2 above to compute (latX, longX) <-> (x, y, z).

Related

How to Determine the Angle of Rotation for a Point

I have 2 points in an x, y plane. I want to rotate one point onto the other point by rotating it about the z-axis.
How can I find the angle to rotate one point onto the other?
Maybe the best thing is to get the angles from horizontal for the two points and then take the difference.
angle_1 = atan2( y_1, x_1 );
angle_2 = atan2( y_2, x_2 );
rotation_angle = angle_1-angle_2;
Well, the sin of this angle is [a, b] / (abs(a) * abs(b)) and its cos is (a, b) / (abs(a) * abs(b)), where [a, b] is a cross product of a and b, (a, b) is a scalar product and abs(x) is the length of the vector x. It is pretty easy to find an angle given its sin and cos.

3D variant for summed area table (SAT)

As per Wikipedia:
A summed area table is a data structure and algorithm for quickly and efficiently generating the sum of values in a rectangular subset of a grid.
For a 2D space a summed area table can be generated by iterating x,y over the desired range,
I(x,y) = i(x,y) + I(x-1,y) + I(x,y-1) - I(x-1,y-1)
And the query function for a rectangle corners A(top-left), B(top-right), C(bottom-right), D can be given by:-
I(C) + I(A) - I(B) - I(D)
I want to convert the above to 3D. Also please tell if any other method/data structure available for calculating partial sums in 3D space.
I'm not sure but something like the following can be thought of. ( I haven't gone through the Wikipedia code )
For every coordinate (x,y,z) find the sum of all elements from (0,0,0) to this element.
Call it S(0,0,0 to x,y,z) or S0(x,y,z).
This can be easily built by traversing the 3D matrix once.
S0( x,y,z ) = value[x,y,z] + S0(x-1,y-1,z-1) +
S0( x,y,z-1 ) + S0( x, y-1, z ) + S0( x-1, y, z )
- S0( x-1, y-1, z ) - S0( x, y-1, z-1 ) - S0( x-1, y, z-1 )
(basically element value + S0(x-1,y-1,z-1) + 3 faces (xy,yz,zx) )
Now for every query (x1,y1,z1) to (x2,y2,z2), first convert the coordinates so that x1,y1,z1 is the corner of the cuboid closest to origin and x2,y2,z2 is the corner that is farthest from origin.
S( (x1,y1,z1) to (x2,y2,z2) ) = S0( x2,y2,z2 ) - S0( x2, y2, z1 )
- S0( x2, y1, z2 ) - S0( x1, y2, z2 )
+ S0( x1, y1, z2 ) + S0( x1, y2, z1 ) + S0( x2, y1, z1 )
- S0( x1, y1, z1 )
(subject to corrections)
A bit late to the party, but anyway. There is a general formula for n-dimensional space in Wikipedia, presented in this paper. Following that notation, we assume that you are interested in the volume specified by a rectangular box with corners (x0,y0,z0) and (x1,y1,z1). Then, having an integral image (volume), the coefficients would be:
S((x0,y0,z0) to(x1,y1,z1))
= S(x1,y1,z1) - S(x1,y1,z0) - S(x1,y0,z1) + S(x1,y0,z0) - S(x0,y1,z1) + S(x0,y1,z0) + S(x0,y0,z1) - S(x0,y0,z0)
Here is matlab code I used to calculate them (can specify dimensionality)
%number of dimensions
nDim = 3;
for i=1:2^nDim
str=dec2bin(i-1,nDim);
strout='index combo (';
sum=0;
for n=1:nDim
strout = strcat(strout,str(n));
sum=sum + str2num(str(n));
end
strout = strcat(strout,') sign: ',num2str((-1)^(nDim-sum)));
disp(strout);
end
which outputs:
(000) sign:-1
(001) sign:1
(010) sign:1
(011) sign:-1
(100) sign:1
(101) sign:-1
(110) sign:-1
(111) sign:1

Distance between 2 points in a circle

I am given 2 points inside a circle. I have to find a point on the circle (not inside, not outside) so that the sum of the distances between the given 2 points and the point i found is minimum. I only have to find the minimum distance, not the position of the point.
It is a minimization problem:
minimize sqrt((x1-x0)^2 + (y1-y0)^2) + sqrt((x2-x0)^2 + (y2-y0)^2)
^ ^
(distance from point1) (distance from point 2)
subject to constraints:
x1 = C1
y1 = C2
x2 = C3
x4 = C4
x0^2 + y0^2 = r^2
(assuming the coordinates are already aligned to the center of the circle as (0,0)).
(C1,C2,C3,C4,r) are given constants, just need to assign them.
After assigning x1,y1,x2,y2 - you are given a minimization problem with 2 variables (x0,y0) and a constraint. The minimization problem can be solved using lagrange multiplier.
Let (x1, y1) and (x2, y2) be the points inside the circle, (x, y) be the point on the circle, r be the radius of the circle.
Your problem reduces to a Lagrange conditional extremum problem, namely:
extremum function:
f(x, y) = sqrt((x-x1)^2 + (y-y1)^2) + sqrt((x-x2)^2 + (y-y2)^2)
condition:
g(x, y) = x^2 + y^2 = r^2 (1)
Introduce an auxiliary function(reference):
Λ(x, y, λ) = f(x, y) + λ(g(x, y) - r^2)
Let ∂Λ / ∂x = 0, we have:
(x-x1)/sqrt((x-x1)^2 + (y-y1)^2) + (x-x2)/sqrt((x-x2)^2 + (y-y2)^2) + 2λx = 0 (2)
Let ∂Λ / ∂y = 0, we have:
(y-y1)/sqrt((x-x1)^2 + (y-y1)^2) + (y-y2)/sqrt((x-x2)^2 + (y-y2)^2) + 2λy = 0 (3)
Now we have 3 variables(i.e. x, y and λ) and 3 equations(i.e. (1), (2) and (3)), so it's solvable.
Please be noted that there should be two solutions(unless two inside points happen to be the center of the circle). One is the minimal value(which is what you need), the other is the maximal value(which will be ignored).
just another approach(which is more directly):
for simplicity, assume the circle is at (0,0) with radius r
and suppose two points are P1(x1,y1) and P2(x2,y2)
we can calculate the polar angle of these two points, suppose they are alpha1 and alpha2
obviously, the point which is on the circle and having the minimum sum of distance to P1 and P2 is within the circular sector composed of alpha1 and alpha2
meanwhile, the sum of distance between the point on the circle within that sector and P1 and P2 is a quadratic function. so, the minimum distance can be found by using trichotomy.

How to determine a semi-sphere's point x-y-z coordinates?

I'm having serious problems solving a problem illustrated on the pic below.
Let's say we have 3 points in 3D space (blue dots), and the some center of the triangle based on them (red dot - point P). We also have a normal to this triangle, so that we know which semi-space we talking about.
I need to determine, what is the position on a point (red ??? point) that depends on two angles, both in range of 0-180 degrees. Doesnt matter how the alfa=0 and betha=0 angle is "anchored", it is only important to be able to scan the whole semi-sphere (of radius r).
http://i.stack.imgur.com/a1h1B.png
If anybody could help me, I'd be really thankful.
Kind regards,
Rav
From the drawing it looks as if the position of the point on the sphere is given by a form of spherical coordinates. Let r be the radius of the sphere; let alpha be given relative to the x-axis; and let beta be the angle relative to the x-y-plane. The Cartesian coordinates of the point on the sphere are:
x = r * cos(beta) * cos(alpha)
y = r * cos(beta) * sin(alpha)
z = r * sin(beta)
Edit
But for a general coordinate frame with axes (L, M, N) centered at (X, Y, Z) the coordinates are (as in dmuir's answer):
(x, y, z) =
(X, Y, Z)
+ r * cos(beta) * cos(alpha) * L
+ r * cos(beta) * sin(alpha) * M
+ r * sin(beta) * N
The axes L and N must be orthogonal and M = cross(N, L). alpha is given relative to L, and beta is given relative to the L-M plane. If you don't know how L is related to points of the triangle, then the question can't be answered.
You need to find two unit length orthogonal vectors L, M say, in the plane of the triangle as well as the the unit normal N. The points on the sphere are
r*cos(beta)*cos(alpha) * L + r*cos(beta)*sin(alpha)*M + r*sin(beta)*N

drawing circle without floating point calculation

This is a common interview question (according to some interview sites) but I can find no normal answers on the Internet - some are wrong and some point to complex theory I expect not to be required in an interview (like the Bresenham algorithm).
The question is simple:
The circle equation is: x2 + y2 = R2.
Given R, draw 0,0-centered circle as best as possible without using any
floating point (no trig, square roots, and so on, only integers)
Bresenham-like algorithms are probably the expected answer, and can be derived without "complex theory". Start from a point (x,y) on the circle: (R,0) and maintain the value d=x^2+y^2-R^2, initially 0. D is the squared distance from the current point to the circle. We increment Y, and decrement X as needed to keep D minimal:
// Discretize 1/8 circle:
x = R ; y = 0 ; d = 0
while x >= y
print (x,y)
// increment Y, D must be updated by (Y+1)^2 - Y^2 = 2*Y+1
d += (2*y+1) ; y++
// now if we decrement X, D will be updated by -2*X+1
// do it only if it keeps D closer to 0
if d >= 0
d += (-2*x+1) ; x--
Honestly, isn't the Midpoint circle algorithm enough? Just mirror it in all quadrants. And by all means no -- unless you're trying to get a job as a window application tester, Bresenham's Line Algorithm isn't complex theory.
From the second method on this page:
for each pixel, evaluate
x2+y2 and see if
it is in the range from
R2-R+1 to R2+R
inclusive. If so, color the pixel on
the screen, and if not, don't.
Further details and explanation given on the aforementioned page, but the crux is that you are looking for pixels that are a distance between R-0.5 and R+0.5 from the origin, so the distance squared is x2+y2 and the threshold distances squared are R2-R+0.25 and R2+R+0.25.
For other methods, Google "draw a circle using integer arithmetic only".
Pretty old question but I will try to provide the end solution with visual tests in python as an alternative to Bresenham's algorithm - the best and the shortest solution for this task. I think this idea also can have a place and perhaps is simpler to understand but needs more code. Someone maybe also end up with this solution.
The idea is based on the following facts:
Every point on circle lies on the same distance to circle central point
A circle contains 4 quadrant which starts and ends in points (r, 0), (2r, r), (r, 2r) and (0, r) if r is radius and central point is in (r, r) point.
A circle is a continues figure and every point can have 8 neighbor points. If move on circle in one direction only three points are interesting for us - 3 lie in opposite direction and 2 are too far from center. For example for point (r, 0) with direction to (2r, r) interesting points will be (r + 1, 1), (r, 1) and (r + 1, 0)
import matplotlib.pyplot as plt
from itertools import chain
def get_distance(x1, y1, x2, y2):
"""
Calculates squared distance between (x1, y1) and (x2, y2) points
"""
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
def get_next_point(x, y, dx, dy, cx, cy, r):
"""
Returns the next circle point base on base point (x, y),
direction (dx, dy), circle central point (cx, cy) and radius r
"""
r2 = r * r
# three possible points
x1, y1 = x + dx, y + dy
x2, y2 = x, y + dy
x3, y3 = x + dx, y
# calculate difference between possible point distances
# with central point and squared radius
dif1 = abs(get_distance(x1, y1, cx, cy) - r2)
dif2 = abs(get_distance(x2, y2, cx, cy) - r2)
dif3 = abs(get_distance(x3, y3, cx, cy) - r2)
# choosing the point with minimum distance difference
diff_min = min(dif1, dif2, dif3)
if diff_min == dif1:
return x1, y1
elif diff_min == dif2:
return x2, y2
else:
return x3, y3
def get_quadrant(bx, by, dx, dy, cx, cy, r):
"""
Returns circle quadrant starting from base point (bx, by),
direction (dx, dy), circle central point (cx, cy) and radius r
"""
x = bx
y = by
# maximum or minimum quadrant point (x, y) values
max_x = bx + dx * r
max_y = by + dy * r
# choosing only quadrant points
while (dx * (x - max_x) <= 0) and (dy * (y - max_y) <= 0):
x, y = get_next_point(x, y, dx, dy, cx, cy, r)
yield x, y
def get_circle(r, cx, cy):
"""
Returns circle points (list) with radius r and center point (cx, cy)
"""
north_east_quadrant = get_quadrant(cx, cy - r, 1, 1, cx, cy, r)
south_east_quadrant = get_quadrant(cx + r, cy, -1, 1, cx, cy, r)
south_west_quadrant = get_quadrant(cx, cy + r, -1, -1, cx, cy, r)
north_west_quadrant = get_quadrant(cy - r, cy, 1, -1, cx, cy, r)
return chain(north_east_quadrant, south_east_quadrant,
south_west_quadrant, north_west_quadrant)
# testing
r = 500
circle_points = get_circle(r, r, r)
for x, y in circle_points:
plt.plot([x], [y], marker='o', markersize=3, color="red")
plt.show()
I will use the Bresenham's Circle drawing algorithm or the Midpoint Circle drawing algorithm. Both produce the same coordinate points. And with the symmetry between the eight octants of the circle, we just need to generate one octant and reflect and copy it to all the other positions.
Here would be my interview answer (no research, this is on the spot)...
Set up two nested for loops that collectively loop over the square defined by {-R, -R, 2R, 2R}. For each pixel, calculate (i^2 + j^2) where i and j are your loop variables. If this is within some tolerance to R^2, then color that pixel black, if not then leave that pixel alone.
I'm too lazy to determine what that tolerance should be. You may need to store the last calculated value to zero-in on which pixel best represents the circle... But this basic method should work pretty well.
Has anyone considered they might be looking for a lateral answer such as "with a compass and pencil" or "use the inside of a roll of sellotape as a template".
Everyone assumes all problems have to be solved with a computer.
You can easily calculate the x in x^2= r^2- y^2 using the first order Taylor approximation
sqrt(u^2 + a) = u + a / 2u
This is a program for that in Mathematica (short, but perhaps not nice)
rad=87; (* Example *)
Calcy[r_,x_]:= (
y2 = rad^2 - x^2;
u = Ordering[Table[ Abs[n^2-y2], {n,1,y2}]] [[1]]; (* get the nearest perfect square*)
Return[ u-(u^2-y2)/(2 u) ]; (* return Taylor approx *)
)
lista = Flatten[Table[{h Calcy[rad, x], j x}, {x, 0, rad}, {h, {-1, 1}}, {j, {-1, 1}}], 2];
ListPlot[Union[lista, Map[Reverse, lista]], AspectRatio -> 1];
This is the result
Not too bad IMHO ... I don't know anything about graphic algorithms ...

Resources