I am programming an algorithm where I have broken up the surface of a sphere into grid points (for simplicity I have the grid lines parallel and perpendicular to the meridians). Given a point A, I would like to be able to efficiently take any grid "square" and determine the point B in the square with the least spherical coordinate distance AB. In the degenerate case the "squares" are actually "triangles".
I am actually only using it to bound which squares I am searching, so I can also accept a lower bound if it is only a tiny bit off. For this reason, I need the algorithm to be extremely quick otherwise it would be better to just take the loss of accuracy and search a few more squares.
I decided to repost this question to Math Overflow: https://mathoverflow.net/questions/854/closest-grid-square-to-a-point-in-spherical-coordinates. More progress has been made here
For points on a sphere, the points closest in the full 3D space will also be closest when measured along the surface of the sphere. The actual distances will be different, but if you're just after the closest point it's probably easiest to minimize the 3D distance rather than worry about great circle arcs, etc.
To find the actual great-circle distance between two (latitidude, longitude) points on the sphere, you can use the first formula in this link.
A few points, for clarity.
Unless you specifically wish these squares to be square (and hence to not fit exactly in this parallel and perpendicular layout with regards to the meridians), these are not exactly squares. This is particularly visible if the dimensions of the square are big.
The question speaks of a [perfect] sphere. Matters would be somewhat different if we were considering the Earth (or other planets) with its flattened poles.
Following is a "algorithm" that would fit the bill, I doubt it is optimal, but could offer a good basis. EDIT: see Tom10's suggestion to work with the plain 3D distance between the points rather than the corresponding great cirle distance (i.e. that of the cord rather than the arc), as this will greatly reduce the complexity of the formulas.
Problem layout: (A, B and Sq as defined in the OP's question)
A : a given point the the surface of the sphere
Sq : a given "square" from the grid
B : solution to problem : point located within Sq which has the shortest
distance to A.
C : point at the center of Sq
Tentative algorithm:
Using the formulas associated with [Great Circle][1], we can:
- find the equation of the circle that includes A and C
- find the distance between A and C. See the [formula here][2] (kindly lifted
from Tom10's reply).
- find the intersect of the Great Circle arc between these points, with the
arcs of parallel or meridian defining the Sq.
There should be only one such point, unless this finds a "corner" of Sq,
or -a rarer case- if the two points are on the same diameter (see
'antipodes' below).
Then comes the more algorithmic part of this procedure (so far formulas...):
- find, by dichotomy, the point on Sq's arc/seqment which is the closest from
point A. We're at B! QED.
Optimization:
It is probably possible make a good "guess" as to the location
of B, based on the relative position of A and C, hence cutting the number of
iterations for the binary search.
Also, if the distance A and C is past a certain threshold the intersection
of the cicles' arcs is probably a good enough estimate of B. Only when A
and C are relatively close will B be found a bit further on the median or
parallel arc in these cases, projection errors between A and C (or B) are
smaller and it may be ok to work with orthogonal coordinates and their
simpler formulas.
Another approach is to calculate the distance between A and each of the 4
corners of the square and to work the dichotomic search from two of these
points (not quite sure which; could be on the meridian or parallel...)
( * ) *Antipodes case*: When points A and C happen to be diametrically
opposite to one another, all great circle lines between A and C have the same
length, that of 1/2 the circonference of the sphere, which is the maximum any
two points on the surface of a sphere may be. In this case, the point B will
be the "square"'s corner that is the furthest from C.
I hope this helps...
The lazy lower bound method is to find the distance to the center of the square, then subtract the half diagonal distance and bound using the triangle inequality. Given these aren't real squares, there will actually be two diagonal distances - we will use the greater. I suppose that it will be reasonably accurate as well.
See Math Overflow: https://mathoverflow.net/questions/854/closest-grid-square-to-a-point-in-spherical-coordinates for an exact solution
Related
I have a 3D mesh consisting of triangle polygons. My mesh can be either oriented left or right:
I'm looking for a method to detect mesh direction: right vs left.
So far I tried to use mesh centroid:
Compare centroid to bounding-box (b-box) center
See if centroid is located left of b-box center
See if centroid is located right of b-box center
But the problem is that the centroid and b-box center don't have a reliable difference in most cases.
I wonder what is a quick algorithm to detect my mesh direction.
Update
An idea proposed by #collapsar is ordering Convex Hull points in clockwise order and investigating the longest edge:
UPDATE
Another approach as suggested by #YvesDaoust is to investigate two specific regions of the mesh:
Count the vertices in two predefined regions of the bounding box. This is a fairly simple O(N) procedure.
Unless your dataset is sorted in some way, you can't be faster than O(N). But if the point density allows it, you can subsample by taking, say, every tenth point while applying the procedure.
You can as well keep your idea of the centroid, but applying it also in a subpart.
The efficiency of an algorithm to solve your problem will depend on the data structures that represent your mesh. You might need to be more specific about them in order to obtain a sufficiently performant procedure.
The algorithms are presented in an informal way. For a more rigorous analysis, math.stackexchange might be a more suitable place to ask (or another contributor is more adept to answer ...).
The algorithms are heuristic by nature. Proposals 1 and 3 will work fine for meshes whose local boundary's curvature is mostly convex locally (skipping a rigorous mathematical definition here). Proposal 2 should be less dependent on the mesh shape (and can be easily tuned to cater for ill-behaved shapes).
Proposal 1 (Convex Hull, 2D)
Let M be the set of mesh points, projected onto a 'suitable' plane as suggested by the graphics you supplied.
Compute the convex hull CH(M) of M.
Order the n points of CH(M) in clockwise order relative to any point inside CH(M) to obtain a point sequence seq(P) = (p_0, ..., p_(n-1)), with p_0 being an arbitrary element of CH(M). Note that this is usually a by-product of the convex hull computation.
Find the longest edge of the convex polygon implied by CH(M).
Specifically, find k, such that the distance d(p_k, p_((k+1) mod n)) is maximal among all d(p_i, p_((i+1) mod n)); 0 <= i < n;
Consider the vector (p_k, p_((k+1) mod n)).
If the y coordinate of its head is greater than that of its tail (ie. its projection onto the line ((0,0), (0,1)) is oriented upwards) then your mesh opens to the left, otherwise to the right.
Step 3 exploits the condition that the mesh boundary be mostly locally convex. Thus the convex hull polygon sides are basically short, with the exception of the side that spans the opening of the mesh.
Proposal 2 (bisector sampling, 2D)
Order the mesh points by their x coordinates int a sequence seq(M).
split seq(M) into 2 halves, let seq_left(M), seq_right(M) denote the partition elements.
Repeat the following steps for both point sets.
3.1. Select randomly 2 points p_0, p_1 from the point set.
3.2. Find the bisector p_01 of the line segment (p_0, p_1).
3.3. Test whether p_01 lies within the mesh.
3.4. Keep a count on failed tests.
Statistically, the mesh point subset that 'contains' the opening will produce more failures for the same given number of tests run on each partition. Alternative test criteria will work as well, eg. recording the average distance d(p_0, p_1) or the average length of (p_0, p_1) portions outside the mesh (both higher on the mesh point subset with the opening). Cut off repetition of step 3 if the difference of test results between both halves is 'sufficiently pronounced'. For ill-behaved shapes, increase the number of repetitions.
Proposal 3 (Convex Hull, 3D)
For the sake of completeness only, as your problem description suggests that the analysis effectively takes place in 2D.
Similar to Proposal 1, the computations can be performed in 3D. The convex hull of the mesh points then implies a convex polyhedron whose faces should be ordered by area. Select the face with the maximum area and compute its outward-pointing normal which indicates the direction of the opening from the perspective of the b-box center.
The computation gets more complicated if there is much variation in the side lengths of minimal bounding box of the mesh points, ie. if there is a plane in which most of the variation of mesh point coordinates occurs. In the graphics you've supplied that would be the plane in which the mesh points are rendered assuming that their coordinates do not vary much along the axis perpendicular to the plane.
The solution is to identify such a plane and project the mesh points onto it, then resort to proposal 1.
I have a set of distinct 2D vectors (over real numbers), pointing in different directions. We are allowed to pick a pair of vectors and construct their linear combination, such that the coefficients are positive and their sum is 1.
In simple words we are allowed to take a "weighted average" of any two vectors.
My goal is for an arbitrary direction to pick a pair of vectors whose "weighted average" is in this direction and is maximized.
Speaking algebraically given vectors a and b and a direction vector n we are interested in maximizing this value:
[ a cross b ] / [ (a - b) cross n ]
i.e. pick a and b which maximize this value.
To be concrete the application of this problem is for sailing boats. For every apparent wind direction the boat will have a velocity given by a polar diagram. Here's an example of such a diagram:
(Each line in this diagram corresponds to a specific wind magnitude). Note the "impossible" front sector of about 30 degrees in each direction.
So that in some direction the velocity will be high, for some - low, and for some directions it's impossible to sail directly (for instance in the direction strictly opposite to the wind).
If we need to advance in a direction in which we can't sail directly (or the velocity isn't optimal) - it's possible to advance in zigzags. This is called tacking.
Now, my goal is to recalculate a new diagram which denotes the average advance velocity in any direction, either directly or indirectly. For instance for the above diagram the corrected diagram would be this:
Note that there are no more "impossible" directions. For some directions the diagram resembles the original one, where it's best to advance directly, and no maneuver is required. For others - it shows the maximum average advance velocity in this direction assuming the most optimal maneuver is periodically performed.
What would be the most optimal algorithm to calculate this? Assume the diagram is given as a discrete set of azimuth-velocity pairs, from which we can calculate the vectors.
So far I just check all the vector pairs to select the best. Well, there're cut-off criterias, such as picking only vectors with positive projection on the advance direction, and opposite perpendicular projections, but still the complexity is O(N^2).
I wonder if there's a more efficient algorithm.
EDIT
Many thanks to #mcdowella. For both computer-science and sailor answers!
I too thought in terms of convex polygon, figured out that it's only worth probing vectors on that hull (i.e. if you take a superposition of 2 vectors on this hull, and try to replace one of them by a vector which isn't on this hull, the result would be worse since new vector's projection on the needed direction is worse than of both source vectors).
However I didn't realize that any "weighted average" of 2 vectors is actually a straight line segment connecting those vectors, hence the final diagram is indeed this convex hull! And, as we can see, this is also in agreement with what I calculated by "brute-force" algorithm.
Now the computer science answer
A tacking strategy gives you the convex combination of the vectors from the legs that make up the tacks.
So consider the outline made by just one contour in your diagram. The set of all possible best speeds and directions is the convex polygon formed by taking all convex combinations of the vectors to the contour. So what you want to do is form the convex hull of your contour (https://en.wikipedia.org/wiki/Convex_hull). To find out how to go fast in any particular direction, intersect that vector with the convex hull, and use tacks with legs that correspond to the corners on either side of the edge of the convex hull that you intersect with.
Looking at your diagram, the contour is concave straight upwind and straight downwind, which is what you would expect. However there is also another concave section, somewhere between 4 and 5 O'Clock and also symmetrically between 7 and 8 O'Clock, which appears as a straight line in your corrected diagram - so I guess there is a third direction to tack in, using two reaches on the same side of the wind which I don't recognise from traditional sailing.
First the ex-laser sailor answer
At least for going straight upwind or downwind, the obvious guess is to tack so that each leg is of the same length and of the same bearing to the wind. If the polar diagram is symmetric around the upwind-downwind axis this is correct. Suppose upwind is the Y axis and possible legs are (A, B), (-A, B), (a, b) and (-a, b). Symmetrical tacking moves (A, B)/2 + (-A, B)/2 = (0, B) and the other symmetrical tack gives you (0, b). Asymmetrical tacking is (-A, B)a/(a+A) + (a, b)A/(a+A) = (0, (a/(a+A))B + (A/(a+A))b) and if b!=B lies between b and B and so is not as good as whichever of b or B is best.
For any direction which lies between the port and starboard tacks that you would take to work your way upwind, the obvious strategy is to change the length of those legs but not their direction so that the average vector traveled is in the required direction. Is this the best strategy? If not, the better strategy is making progress upwind faster that the port and starboard tacks that you would take to work your way upwind, which I think is a contradiction - so for any direction which lies between the port and starboard tacks made to go upwind I think the best strategy is indeed to make those tacks but alter the leg lengths to go in the required direction. The same thing should apply for tacking downwind, if you have a boat that makes that a good idea.
I'm working with a really slow renderer, and I need to approximate polygons so that they look almost the same when confined to a screen area containing very few pixels. That is, I'd need an algorithm to go through a polygon and subtract/move a bunch of vertices until the end polygon has a good combination of shape preservation and economy of vertice usage.
I don't know if there's a formal name for these kind of problems, but if anyone knows what it is it would help me get started with my research.
My untested plan is to remove the vertices that change the polygon area the least, and protect the vertices that touch the bounding box from removal, until the difference in area from the original polygon to the proposed approximate one exceeds a tolerance I specify.
This would all be done only once, not in real time.
Any other ideas?
Thanks!
You're thinking about the problem in a slightly off way. If your goal is to reduce the number of vertices with a minimum of distortion, you should be defining your distortion in terms of those same vertices, which define the shape. There's a very simple solution here, which I believe would solve your problem:
Calculate distance between adjacent vertices
Choose a tolerance between vertices, below which the vertices are resolved into a single vertex
Replace all pairs of vertices with distances lower than your cutoff with a single vertex halfway between the two.
Repeat until no vertices are removed.
Since your area is ultimately decided by the vertex placement, this method preserves shape and minimizes shape distortion. The one drawback is that distance between vertices might be slightly less intuitive than polygon area, but the two are proportional. If you really wish, you could run through the change in area that would result from vertex removal, but that's a lot more work for questionable benefit imo.
As mentioned by Angus, if you want a direct solution for the change in area, it's not actually super difficult. Was originally going to leave this as an exercise to the reader, but it's totally possible to solve this exactly, though you need to include vertices on either side.
Assume you're looking at a window of vertices [A, B, C, D] that are connected in that order. In this example we're determining the "cost" of combining B and C.
Calculate the angle offset from collinearity from A toward C. Basically you just want to see how far from collinear the two points are. This is |sin(|arctan(B - A)| - |arctan(C - A)|)| Where pipes are absolute value, and differences are the sensical notion of difference.
Calculate the total distance over which the angle change will effectively be applied, this is just the euclidean distance from A to B times the euclidean distance from B to C.
Multiply the terms from 2 and 3 to get your first term
To get your second term, repeat steps 2 - 4 replacing A with D, B with C, and C with B (just going in the opposite direction)
Calculate the geometric mean of the two terms obtained.
The number that results in step 6 presents the full-picture minus a couple constants.
I tried my own plan first: Protect the vertices touching the bounding box, then remove the rest in the order that changes the resultant area the least, until you can't find a vertice to remove that keeps the new polygon area within X% of the original one. This is the result with X = 5%:
When the user zooms out really far these shapes fit the bill well enough for me. I haven't tried any of the other suggestions. The savings are quite astonishing, sometimes from 80-100 vertices down to 4 or 5.
Just wanted to know what is the best approach (in terms of speed and accuracy) to determine the points of intersection on N spheres (it was asked for two spheres here); wanted to know what would be the best language to do this. More detailed explanation about what I want to do is here.
As near as I can tell, you are asking for the intersection loci of each pair of N 3D spheres.
Counting symmetry, there are N * (N-1) / 2 pairs.
So take each pair.
If the distance between centers is greater than the sum of their radii, there is no intersection.
(Edit: Or, as #Ben points out, if the distance is less than the difference of radii, there is also no intersection.)
If it is equal, the intersection is a single point, easily found on the line segment between centers.
If it is less, the locus is a circle, not a point.
To find the center of that circle and its radius, you're going to need to take a plane slice through the two spheres.
That reduces the problem to finding the intersection of two circles.
For that you need the Law of Cosines.
Elaborated: Look at that Wikipedia diagram. a and b are the radii of the two spheres, and c is the distance between centers.
Use the second-to-last equation and solve for cos(alpha).
From that you can easily get sin(alpha).
Then b sin(alpha) is the radius of the circle,
and b cos(alpha) is the distance to its center.
(Note - this doesn't call any trig functions, only sqrt.)
Once you know the center and radius of the circle of intersection, the circle itself is just in a plane normal to the line segment connecting the sphere centers.
Beyond that, I'm not really sure what you want.
If i get you right, you want all intersections of at least two spheres from a group of N spheres, right?
If so, this is acually not an easy problem for high performance computing, at least not if you need an accurate solution.
This problem is also solved when calculating the "Reduced Surface" of molecules:
http://www.ncbi.nlm.nih.gov/pubmed/8906967
There are several publications on how to efficiently calculate these points and circles, but it is not an easy task.
I believe there was a publication to calculating these values with CUDA, but I don't remember the details. Google (Scholar) should be able to help you in this direction.
However, depending on what you want to achieve, there can be easier solutions.
So, perhaps you could detail your question?
I found some solutions, but they're too messy.
Yes. The Chebyshev center, x*, of a set C is the center of the largest ball that lies inside C. [Boyd, p. 416] When C is a convex set, then this problem is a convex optimization problem.
Better yet, when C is a polyhedron, then this problem becomes a linear program.
Suppose the m-sided polyhedron C is defined by a set of linear inequalities: ai^T x <= bi, for i in {1, 2, ..., m}. Then the problem becomes
maximize R
such that ai^T x + R||a|| <= bi, i in {1, 2, ..., m}
R >= 0
where the variables of minimization are R and x, and ||a|| is the Euclidean norm of a.
Perhaps these "too messy" solutions are what you actually looking for, and there are no simplier ones?
I can suggest a simple, but potentially imprecise solution, which uses numerical analysis. Assume you have a resilient ball, and you inflate it, starting from radius zero. If its center is not in the center you're looking for, then it will move, because the walls would "push" it in the proper direction, until it reaches the point, from where he can't move anywhere else. I guess, for a convex polygon, the ball will eventually move to the point where it has maximum radius.
You can write a program that emulates the process of circle inflation. Start with an arbitrary point, and "inflate" the circle until it reaches a wall. If you keep inflating it, it will move in one of the directions that don't make it any closer to the walls it already encounters. You can determine the possible ways where it could move by drawing the lines that are parallel to the walls through the center you're currently at.
In this example, the ball would move in one of the directions marked with green:
(source: coldattic.info)
Then, move your ball slightly in one of these directions (a good choice might be moving along the bisection of the angle), and repeat the step. If the new radius would be less than the one you have, retreat and decrease the pace you move it. When you'll have to make your pace less than a value of, say, 1 inch, then you've found the centre with precision of 1 in. (If you're going to draw it on a screen, precision of 0.5 pixel would be good enough, I guess).
If an imprecise solution is enough for you, this is simple enough, I guess.
Summary: It is not trivial. So it is very unlikely that it will not get messy. But there are some lecture slides which you may find useful.
Source: http://www.eggheadcafe.com/software/aspnet/30304481/finding-the-maximum-inscribed-circle-in-c.aspx
Your problem is not trivial, and there
is no C# code that does this straight
out of the box. You will have to write
your own. I found the problem
intriguing, and did some research, so
here are a few clues that may help.
First, here's an answer in "plain
English" from mathforum.org:
Link
The answer references Voronoi Diagrams
as a methodology for making the
process more efficient. In researching
Voronoi diagrams, in conjunction with
the "maximum empty circle" problem
(same problem, different name), I came
across this informative paper:
http://www.cosy.sbg.ac.at/~held/teaching/compgeo/slides/vd_slides.pdf
It was written by Martin Held, a
Computational Geometry professor at
the University of Salzberg in Austria.
Further investigation of Dr. Held's
writings yielded a couple of good
articles:
http://www.cosy.sbg.ac.at/~held/projects/vroni/vroni.html
http://www.cosy.sbg.ac.at/~held/projects/triang/triang.html
Further research into Vornoi Diagrams
yielded the following site:
http://www.voronoi.com/
This site has lots of information,
code in various languages, and links
to other resources.
Finally, here is the URL to the
Mathematics and Computational Sciences
Division of the National Institute of
Standards and Technology (U.S.), a
wealth of information and links
regarding mathematics of all sorts:
http://math.nist.gov/mcsd/
-- HTH,
Kevin Spencer Microsoft MVP
The largest inscribed circle (I'm assuming it's unique) will intersect some of the faces tangentially, and may fail to intersect others. Let's call a face "relevant" if the largest inscribed circle intersects it, and "irrelevant" otherwise.
If your convex polygon is in fact a triangle, then the problem can be solved by calculating the triangle's incenter, by intersecting angle bisectors. This may seem a trivial case, but even when
your convex polygon is complicated, the inscribed circle will always be tangent to at least three faces (proof? seems geometrically obvious), and so its center can be calculated as the incenter of three relevant faces (extended outwards to make a triangle which circumscribes the original polygon).
Here we assume that no two such faces are parallel. If two are parallel, we have to interpret the "angle bisector" of two parallel lines to mean that third parallel line between them.
This immediately suggests a rather terrible algorithm: Consider all n-choose-3 subsets of faces, find the incenters of all triangles as above, and test each circle for containment in the original polygon. Maximize among those that are legal. But this is cubic in n and we can do much better.
But it's possible instead to identify faces that are irrelevant upfront: If a face is tangent
to some inscribed circle, then there is a region of points bounded by that face and by the two angle bisectors at its endpoints, wherein the circle's center must lie. If even the circle whose center lies at the farthest tip of that triangular region is "legal" (entirely contained in the polygon), then the face itself is irrelevant, and can be removed. The two faces touching it should be extended beyond it so that they meet.
By iteratively removing faces which are irrelevant in this sense, you should be able to reduce the
polygon to a triangle, or perhaps a trapezoid, at which point the problem will be easily solved, and its solution will still lie within the original polygon.