Given an ArcByCenterPoint, defined by:
center position (lat,lon in WGS84)
radius (meters)
startAngle (degrees)
endAngle (degrees)
how can we compute the position (lat, lon) of start/end points? I'm looking for a formula.
You can find appropriate formulas in the section Destination point given distance and bearing from start point here
Excerpt:
Formula:
φ2 = asin( sin φ1 ⋅ cos δ + cos φ1 ⋅ sin δ ⋅ cos θ )
λ2 = λ1 + atan2( sin θ ⋅ sin δ ⋅ cos φ1, cos δ − sin φ1 ⋅ sin φ2 )
where
φ is latitude, λ is longitude,
θ is the bearing (clockwise from north),
δ is the angular distance d/R;
d being the distance travelled, R the earth’s radius
If you want extreme accuracy try using GeographicLib and the formula in the source code under the hood of the Direct Problem at the "Geodesic calculations for an ellipsoid done right" web page.
Related
y ~ x1 + x2
y ~ (x1 + x2) + (x1 - x2)
Question: For the above two linear models, with regularization (such as Lasso and Ridge), are the coefficient estimates the same? how about the predictions (are they the same)?
Lazy fold uses a lot of RAM. In Data.List, foldl' provides a left fold that uses strict evaluation. For example, the following computes the sum of 10 million zeros with little increase in RAM usage.
sum0 = foldl' (+) 0 (replicate 10000000 0)
However, this does not seem to hold with complex data structures. For example, if we define addition for pairs of numbers and compute the sum of zero pairs, there is significant increase in RAM usage:
(x1,y1) <+> (x2,y2) = (x1 + x2,y1 + y2)
sum00 = foldl' (<+>) (0,0) (replicate 10000000 (0,0))
Why does that happen? Is there a way to decrease RAM usage?
foldl' only evaluates the intermediate state to weak head normal form—i.e. up to the first constructor. That's the most a generic function can do, and what functions that are called "strict" generally do. Evaluating (x1, y1) <+> (x2, y2) until it looks like a constructor gives (x1 + x2, y1 + y2), where the parts are still unevaluated (they have been "protected" by the (,)). Through the iteration, foldl' being strict keeps the state in the form (_, _) instead of (_, _) <+> (_, _) <+> ..., but the _s grow into huge unevaluated terms of form _ + _ + _ + ....
Modify <+> to evaluate the additions before it exposes the constructor.
(x1, y1) <+> (x2, y2) = x `seq` y `seq` (x, y)
where x = x1 + x2; y = y1 + y2
-- or
(x1, y1) <+> (x2, y2) = ((,) $! x1 + y1) $! x2 + y2
-- or (with deepseq package)
(x1, y1) <+> (x2, y2) = force (x1 + x2, y1 + y2)
-- x `seq` y = y, but only if x reaches WHNF
-- usually, evaluating x `seq` y to WHNF evaluates x (to WHNF) before it returns the result of evaluating y to WHNF
-- though that's not the official definition of `seq`, since Haskell nominally doesn't have an evaluation strategy
-- (and GHC's actual `seq` may do something different if GHC is feeling smart)
In 2D the maximum number of faces for n vertices in a 'perfect'(non-overlapping) mesh is f = 2n - 4. Is there an equivalent result for 3 dimensions?
The Euler characteristic chi is defined as:
chi = V - E + F
where V, E, and F are the numbers of vertices, edges and faces, respectively.
For closed triangular meshes, we know that each edge has two incident faces and each face has three incident edges. Therefore:
3 * F = 2 * E
E = 3/2 * F
Hence,
chi = V - 3/2 * F + F
= V - 1/2 F
F = 2 * (V - chi)
In the 2D case for planar graphs, chi is 2, resulting in your definition F = 2 * V - 4.
For any 3D surface, the Euler characteristic can be calculated from its genus. In general, the more handles the surface has, the smaller its Euler characteristic. Hence, chi (and by that F) is not limited. However, for a fixed surface topology, the number of faces (relative to the number of vertices) is fixed.
I almost finish the chapter 3 of Real World Haskell. The last exercise blocks me. My code will crash while running. Does anyone can tell me which part is wrong in my code? Thanks.
Question:
Using the code from the preceding three exercises, implement Graham's scan algorithm for the convex hull of a set of 2D points. You can find good description of what a convex hull is, and how the Graham scan algorithm should work, on Wikipedia.
Answer:
-- Graham Scan, get the convex hull.
-- Implement the algorithm on http://en.wikipedia.org/wiki/Graham_scan
import Data.List
import Data.Ord
data Direction = TurnLeft | TurnRight | GoStraight deriving (Eq, Show)
-- Determine if three points constitute a "left turn" or "right turn" or "go straight".
-- For three points (x1,y1), (x2,y2) and (x3,y3), simply compute the direction of the cross product of the two vectors defined by points (x1,y1), (x2,y2) and (x1,y1), (x3,y3), characterized by the sign of the expression (x2 − x1)(y3 − y1) − (y2 − y1)(x3 − x1). If the result is 0, the points are collinear; if it is positive, the three points constitute a "left turn", otherwise a "right turn".
direction a b c = case compare ((x2 - x1) * (y3 - y1)) ((y2 - y1) * (x3 - x1)) of
EQ -> GoStraight
GT -> TurnLeft
LT -> TurnRight
where x1 = fst a
y1 = snd a
x2 = fst b
y2 = snd b
x3 = fst c
y3 = snd c
grahamScan points = scan (sort points)
-- For each point, it is determined whether moving from the two previously considered points to this point is a "left turn" or a "right turn". If it is a "right turn", this means that the second-to-last point is not part of the convex hull and should be removed from consideration. This process is continued for as long as the set of the last three points is a "right turn". As soon as a "left turn" is encountered, the algorithm moves on to the next point in the sorted array. (If at any stage the three points are collinear, one may opt either to discard or to report it, since in some applications it is required to find all points on the boundary of the convex hull.)
where scan (a : (b : (c : points)))
| (direction a b c) == TurnRight = scan (a : (c : points))
| otherwise = a : (scan (b : (c : points)))
scan (a : (b : [])) = []
-- Put prime to the head.
sort points = prime : (reverse (sortBy (compareByCosine prime) rest))
-- Sort a list to compute. The first step is to find a point whose y-coordinate is lowest. If there are more than one points with lowest y-coordinate, take the one whose x-coordinate is lowest. I name it prime.
where compareByYAndX a b
| compareByY == EQ = comparing fst a b
| otherwise = compareByY
where compareByY = comparing snd a b
prime = minimumBy compareByYAndX points
-- Delete prime from the candidate points. Sort the rest part by the cosine value of the angle between each vector from prime to each point. Reverse it and put prime to the head.
rest = delete prime points
compareByCosine p a b = comparing cosine pa pb
where pa = (fst a - fst p, snd a - snd p)
pb = (fst b - fst p, snd b - snd p)
cosine v = x / sqrt (x ^ 2 + y ^ 2)
where x = fst v
y = snd v
When doing the scan on the sorted set of points, when you finish, you throw away points that are supposed to be in the hull. In this line
scan (a : (b : [])) = []
you are deleting the last two points in the hull. Really it should be
scan (a : (b : [])) = [a, b]
or even better,
scan ps = ps
which covers cases with only one point.
Is it possible to rotate body which has its vertices defined in spherical coordinates.
Currently I am doing collage project in VHDL and is about rotating dodecahedron and presenting over VGA.
I applied pinhole camera model equations and that required just two sin/cos calculation and two multiplication per vertice.
I was just thinking about rotating around 3rd axis using 3 steps over two angles but i am unable to figure out proper equations and even if this is possible.
Edit
I think I got it.
Rotating over 3rd axis which is in same direction as camera is just 2D transform of camera coordinates once you you compute them. That mean than for rotating in 3 axes (ok two axis and one inclination) you need to apply total of 4 sin/cos computations and 4 multiplications. If somebody came up whit something better, fell free to post answer.
You can rotate around the y-axis by changing θ, and rotate around the z-axis by changing φ. Rotating around the x-axis, though, is a bit tougher.
One simple way would be to convert everything to catesian coordinates, perform the rotation, and convert back.
The equations for (x,y,z) (spherical-to-cartesian) are
x = r sin θ cos φ
y = r sin θ sin φ
z = r cos θ
The equations for rotating (x,y,z) to new points (x', y', z') around the x-axis by an angle α are
x' = x
= r sin θ cos φ
y' = y cos α - z sin α
= (r sin θ sin φ) cos α - (r cos θ) sin α
z' = y sin α + z cos α
= (r sin θ sin φ) sin α + (r cos θ) cos α
The equations for (r, θ, φ) (cartesian-to-spherical) are
r' = sqrt(x'2 + y'2 + z'2)
= r
θ' = cos-1(z'/r')
= cos-1(sin θ sin φ sin α + cos θ cos α)
φ' = tan-1(y'/x')
= tan-1(tan φ cos α - cotan θ sin α sec φ)
I don't know if there is a way to reduce that any further, but it should work.
Hopefully this will be helpful to someone in the future, but there is a small mistake in the above answer. It should be:
φ' = tan-1(y'/x')
= tan-1(tan φ cos α - cotan θ sin α sec φ)
I don't have the rep points to post this in the comment, but thought it would be useful.