Random point within 3D mathematical volume - math

Quick question, if I've a formula for a mathematical 3D volume, is it possible to calculate a random cartesian coordinate (XYZ) point within the volume?
And if possible, could the one to answer please provide what kind of formula I need to use? Currently I'm looking at signed distance functions but as far as I can see you can only calculate for a given cartesian coordinate if its in the volume.

An easy strategy is to use a bounding volume (box/sphere or ad-hoc) and use the rejection technique: draw a point at random in the bounding volume, until it falls inside the true volume. If the volume is reasonably compact, and the bounding volume is tight, you will need less than two drawings on average.
To get drawings only inside, you need use a parametric representation of the volume, which depends on the particular implicit equation, and the expression of the ranges of the parameters. But obtaining uniform distributions can be challenging.
For instance, points inside a torus are obtained by
X = (R + t cos u) cos v
Y = (R + t cos u) sin v
Z = t sin u
where u and v are random in 0..2π and t random in 0..r.

Related

GIS: Tunnel to geographical distance approximation

This question is more about math than programming. I am programming a function which takes a square of geographical distance between 2 points with known latitude and longitude as an argument. There's a straightforward way to compute it: calculate dot-product, then take arccos, and multiply by Earth radius. Then square the result and you get the square of geographical distance assuming Earth is a sphere (which is acceptable approximation in my case).
However I would like, if possible, to avoid an expensive arccos() call, especially given that I can easily obtain the square of the tunnel distance (by either Pythagorean theorem or the dot product).
I also read here http://en.wikipedia.org/wiki/Geographical_distance#Tunnel_distance about underestimation formula which I can use to get tunnel distance from geographical distance. In my case however, I need the opposite (tunnel to geographical), and for the square. I played with Taylor series and got a rough approximation:
G square = T2 / (1 - (T2/R2)/12.0) // here G2 is square of geographical distance, T2-square of tunnel, R2-square of Earth radius. I also was able to get a more accurate formula:
G square = T2 / (1 - (T2/R2)/12.0 - ((T2/R2)^2)/240.0).
This last formula gives error of only 3.8mm for G=1000 km, and less than 50cm for G=2000 km.
However, I still cannot mathematically prove this formula, at least when using Taylor series. Wonder if it's possible to get the mathematical proof and also expansion of this formula for larger values of G/T. Thanks!
Why tunnel distance from geo distance?. There is no geo distance. There are many possibilities to calculate a distance between two points on earth.
Just take the two lat/lon cooridnates, and then calculate the distance between them using a simmple cyclindrical projection.
This needs only a cos(centerLatitude), and a multiplication with a factor. (meters_per_degree)
See also Cyclindrical equi distant projection. Up to some kilomters (abou 10 to 100) this gives sufficient accuracy.

How to quantize surface normals

I am trying to quantize surface normals into let's say 8 bins.
For example, when computing features like HOG to quantize 2D gradients [x,y] into 8 bins we just take the angle with the y plane i.e. arctan(y/x) which will give us an angle between 0-360.
My question is, given a 3D direction [x,y,z], a surface normal in this case, how can we histogram it in a similar way? Do we just project onto one plane and use that angle i.e. the dot product of [x,y,z] and [0,1,0] for example?
Thanks
EDIT
I also read a paper recently where they quantized surface normals by measuring angles between normal and precomputed vectors that which are arranged around a right circular cone shape. I have added a link to this paper in the question (section 3.3.2 last paragraph), is this an effective approach? And if so, how do we compute these vectors?
Quantizing a continuous topological space corresponds to partitioning it and assigning labels to each partition. The straightforward standard approach for this scenario (quantizing normals) is as follows.
Choose your favorite uniform polyhedron:
http://en.wikipedia.org/wiki/Tetrahedron (4 faces)
http://en.wikipedia.org/wiki/Cube (6 faces)
http://en.wikipedia.org/wiki/Octahedron (8 faces)
http://en.wikipedia.org/wiki/Dodecahedron (12 faces)
http://en.wikipedia.org/wiki/Icosahedron (20 faces)
In general: http://en.wikipedia.org/wiki/Schl%C3%A4fli_symbol
Develop a mapping function from a normal on the unit sphere to the face of your chosen polyhedron that the normal intersects.
I would advise doing an argmax across polyhedron faces, taking the dot product of your normal and each polyhedron face normal. The one that gives the highest dot product is the face your normal should be binned into.
Use the face normal for each polyhedron face as the label for that face.
Prefer this approach to the approach suggested by others of mapping to spherical coordinates and then binning those. That approach suffers from too much sensitivity near the poles of the sphere.
Edit
In the paper you added to your question, the same idea is being used. There, however, the normals are restricted to a hemisphere - the only surfaces directly visible in an image have surface normals no more than 90 degrees away from the vector from the surface to the viewpoint.
The paper wants to quantize these surface normals into 8 values, represented by 8-bit integers with exactly one bit set to 1 and the rest set to 0. The 8 precomputed normals are computed as:
ntx = cos(a)*cos(t)
nty = cos(a)*sin(t)
ntz = sin(a)
where a = pi/4 and t = 0, pi/4, 2*pi/4, 3*pi/4, ..., 7*pi/4.
Notice
[cos(a)*cos(t)]2 + [cos(a)*sin(t)]2 + [sin(a)]2 = cos2(a)[cos2(t) + sin2(t)] + sin2(a) = cos2(a) + sin2(a) = 1
given a 3D direction [x,y,z], a surface normal in this case, how can
we histogram it in a similar way?
In the first case you quantize the polar orientation theta of the gradients. Now you need to quantize the spherical orientations theta and phi in a 2D histogram.
Do we just project onto one plane and use that angle
The binning of the sphere determines how you summarize the information to build a compact yet descriptive histogram.
Projecting the normal is not a good idea, if theta is more important than phi, just use more bins for theta
EDIT
Timothy Shields points in his comment and his answer that a regular binning of theta and phi won't produce a regular binning over the sphere as the bins will be bunched toward the poles.
His answer gives a solution. Alternatively, the non-regular binning described here can be hacked as follows:
Phi is quantized regularly in [0,pi]. For theta rather than quantizing the range [0,pi], the range [-1,1] is quantized instead;
For each quantized value u in [-1,1], theta is computed as
theta = arcsin(sqrt(1 - u * u)) * sign(u)
sign(u) returns -1 if u is negative, 1 otherwise.
The computed theta along with phi produce a regular quantization over the sphere.
To have an idea of the equation given above look at this article. It describes the situation in the context of random sampling though.
EDIT
In the above hack Timothy Shields points out that only the area of the bins is considered. The valence of the vertices (point of intersection of neighboring bins) won't be regular because of the poles singularity.
A hack for the previous hack would be to remesh the bins into a regular quadrilateral mesh and keep the regular area.
A heuristic to optimize this problem with the global constraints of having the same valence and the area can be inspired from Integer-Grid Maps Quad Meshing.
With the two hacks, this answer is too hacky and a little out of context as opposed to Timothy Shields answer.
A 3-dimensional normal cannot be quantized into a 1-D array as easily as for a 2-D normal (e.g., using arctan). I would recommend histogramming it into a 2-d space with a polar angle and an azimuth angle. For example, use spherical coordinates where the r (radius) value is always 1.0 (since your surface normal is normalized, length 1.0). In this case, you can throw away the r-value and just use polar angle θ (theta), and azimuthal angle φ (phi) to quantize the 3D normal.

Finding the coordinates of points from distance matrix

I have a set of points (with unknow coordinates) and the distance matrix. I need to find the coordinates of these points in order to plot them and show the solution of my algorithm.
I can set one of these points in the coordinate (0,0) to simpify, and find the others. Can anyone tell me if it's possible to find the coordinates of the other points, and if yes, how?
Thanks in advance!
EDIT
Forgot to say that I need the coordinates on x-y only
The answers based on angles are cumbersome to implement and can't be easily generalized to data in higher dimensions. A better approach is that mentioned in my and WimC's answers here: given the distance matrix D(i, j), define
M(i, j) = 0.5*(D(1, j)^2 + D(i, 1)^2 - D(i, j)^2)
which should be a positive semi-definite matrix with rank equal to the minimal Euclidean dimension k in which the points can be embedded. The coordinates of the points can then be obtained from the k eigenvectors v(i) of M corresponding to non-zero eigenvalues q(i): place the vectors sqrt(q(i))*v(i) as columns in an n x k matrix X; then each row of X is a point. In other words, sqrt(q(i))*v(i) gives the ith component of all of the points.
The eigenvalues and eigenvectors of a matrix can be obtained easily in most programming languages (e.g., using GSL in C/C++, using the built-in function eig in Matlab, using Numpy in Python, etc.)
Note that this particular method always places the first point at the origin, but any rotation, reflection, or translation of the points will also satisfy the original distance matrix.
Step 1, arbitrarily assign one point P1 as (0,0).
Step 2, arbitrarily assign one point P2 along the positive x axis. (0, Dp1p2)
Step 3, find a point P3 such that
Dp1p2 ~= Dp1p3+Dp2p3
Dp1p3 ~= Dp1p2+Dp2p3
Dp2p3 ~= Dp1p3+Dp1p2
and set that point in the "positive" y domain (if it meets any of these criteria, the point should be placed on the P1P2 axis).
Use the cosine law to determine the distance:
cos (A) = (Dp1p2^2 + Dp1p3^2 - Dp2p3^2)/(2*Dp1p2* Dp1p3)
P3 = (Dp1p3 * cos (A), Dp1p3 * sin(A))
You have now successfully built an orthonormal space and placed three points in that space.
Step 4: To determine all the other points, repeat step 3, to give you a tentative y coordinate.
(Xn, Yn).
Compare the distance {(Xn, Yn), (X3, Y3)} to Dp3pn in your matrix. If it is identical, you have successfully identified the coordinate for point n. Otherwise, the point n is at (Xn, -Yn).
Note there is an alternative to step 4, but it is too much math for a Saturday afternoon
If for points p, q, and r you have pq, qr, and rp in your matrix, you have a triangle.
Wherever you have a triangle in your matrix you can compute one of two solutions for that triangle (independent of a euclidean transform of the triangle on the plane). That is, for each triangle you compute, it's mirror image is also a triangle that satisfies the distance constraints on p, q, and r. The fact that there are two solutions even for a triangle leads to the chirality problem: You have to choose the chirality (orientation) of each triangle, and not all choices may lead to a feasible solution to the problem.
Nevertheless, I have some suggestions. If the number entries is small, consider using simulated annealing. You could incorporate chirality into the annealing step. This will be slow for large systems, and it may not converge to a perfect solution, but for some problems it's the best you and do.
The second suggestion will not give you a perfect solution, but it will distribute the error: the method of least squares. In your case the objective function will be the error between the distances in your matrix, and actual distances between your points.
This is a math problem. To derive coordinate matrix X only given by its distance matrix.
However there is an efficient solution to this -- Multidimensional Scaling, that do some linear algebra. Simply put, it requires a pairwise Euclidean distance matrix D, and the output is the estimated coordinate Y (perhaps rotated), which is a proximation to X. For programming reason, just use SciKit.manifold.MDS in Python.
The "eigenvector" method given by the favourite replies above is very general and automatically outputs a set of coordinates as the OP requested, however I noticed that that algorithm does not even ask for a desired orientation (rotation angle) for the frame of the output points, the algorithm chooses that orientation all by itself!
People who use it might want to know at what angle the frame will be tipped before hand so I found an equation which gives the answer for the case of up to three input points, however I have not had time to generalize it to n-points and hope someone will do that and add it to this discussion. Here are the three angles the output sides will form with the x-axis as a function of the input side lengths:
angle side a = arcsin(sqrt(((c+b+a)*(c+b-a)*(c-b+a)*(-c+b+a)*(c^2-b^2)^2)/(a^4*((c^2+b^2-a^2)^2+(c^2-b^2)^2))))*180/Pi/2
angle side b = arcsin(sqrt(((c+b+a)*(c+b-a)*(c-b+a)*(-c+b+a)*(c^2+b^2-a^2)^2)/(4*b^4*((c^2+b^2-a^2)^2+(c^2-b^2)^2))))*180/Pi/2
angle side c = arcsin(sqrt(((c+b+a)*(c+b-a)*(c-b+a)*(-c+b+a)*(c^2+b^2-a^2)^2)/(4*c^4*((c^2+b^2-a^2)^2+(c^2-b^2)^2))))*180/Pi/2
Those equations also lead directly to a solution to the OP's problem of finding the coordinates for each point because: the side lengths are already given from the OP as the input, and my equations give the slope of each side versus the x-axis of the solution, thus revealing the vector for each side of the polygon answer, and summing those sides through vector addition up to a desired vertex will produce the coordinate of that vertex. So if anyone can extend my angle equations to handling beyond three input lengths (but I note: that might be impossible?), it might be a very fast way to the general solution of the OP's question, since slow parts of the algorithms that people gave above like "least square fitting" or "matrix equation solving" might be avoidable.

Scale-agnostic, differentiable, co-planarity measure

I am looking for an (almost everywhere) differentiable function f(p1, p2, p3, p4) that given four points will give me a scale-agnostic measure for co-planarity. It is zero if the four points lie on the same plane and positive otherwise. Scale-agnostic means that, when I uniformly scale all points the planarity measure will return the same.
I came up with something that is quite complex and not easy to optimize. Define u=p2-p1, v=p3-p1, w=p4-p1. Then the planarity measure is:
[(u x v) * w]² / (|u x v|² |w|²)
where x means cross product and '*' means dot product.
The numerator is simply (the square of) the volume of the tetrahedron defined by the four points, and the denominator is a normalizing factor that makes this measure become simply the cosine of an angle. Because angles do not changed under uniform scale, this function satisfies all my requirements.
Does anybody know of something simpler?
Alex.
Edit:
I eventually used an Augmented Lagrangian method to perform optimization, so I don't need it to be scale agnostic. Just using the constraint (u x v) * w = 0 is enough, as the optimization procedure finds the correct Lagrange multiplier to compensate for the scale.
Your methods seems ok, I'd do something like this for efficient implementation:
Take u, v, w as you did
Normalize them: various tricks exist to evaluate the inverse square root efficiently with whatever precision you want, like this jewel. Most modern processors have builtins for this operation.
Take f = |det(u, v, w)| ( = (u x v) . w ). There are fast direct implementations for 3x3 matrices; see #batty's answer to this question.
This amounts to what you do without the squares. It is still homogeneous and almost everywhere differentiable. Take the square of the determinant if you want something differentiable everywhere.
EDIT: #phkahler implicitly suggested using the ratio of the radius of the inscribed sphere to the radius of the circumscribed sphere as a measure of planarity. This is a bounded differentiable function of the points, invariant by scaling. However, this is at least as difficult to compute as what you (and I) suggest. Especially computing the radius of the circumscribed sphere is very sensitive to roundoff errors.
A measure that should be symmetric with respect to point reorderings is:
((u x v).w)^2/(|u||v||w||u-v||u-w||v-w|)
which is proportional to the volume of the tetrahedron squared divided by all 6 edge lengths. It is not simpler than your formula or Alexandre C.'s, but it is not much more complicated. However, it does become unnecessarily singular when any two points coincide.
A better-behaved, order-insensitive formula is:
let a = u x v
b = v x w
c = w x u
(a.w)^2/(|a| + |b| + |c| + |a+b+c|)^3
which is something like the volume of the tetrahedron divided by the surface area, but raised to appropriate powers to make the whole thing scale-insensitive. This is also a bit more complex than your formula, but it works unless all 4 points are collinear.
How about
|(u x v) * w| / |u|^3
(and you can change |x| to (x)^2 if you think it's simpler).

Zip Code Radius Search

I'm wondering if it's possible to find all points by longitude and latitude within X radius of one point?
So, if I provide a latitude/longitude of -76.0000, 38.0000, is it possible to simply find all the possible coordinates within (for example) a 10 mile radius of that?
I know that there's a way to calculate the distance between two points, which is why I'm not clear as to whether this is possible. Because, it seems like you need to know the center coordinates (-76 and 38 in this case) as well as the coordinates of every other point in order to determine whether it falls within the specified radius. Is that right?
#David's strategy is correct, his implementation is seriously flawed. I suggest that before you perform the calculations you transform your lat,long pair to UTM coordinates and work in distance, not angular, measurements. If you are not familiar with Universal Transverse Mercator, hit Google or Wikipedia.
I reckon that your point (-76,38) is at UTM 37C 472995 (Easting) 1564346 (Northing). So you want to do your calculations of distance from that point. You'll find it easier, working with UTM, to work in metres, so your distance is (if you are using statute miles of 5280 feet) 16040 metres.
Incidentally, (-76,38) is well outside the contintental US -- does the US Post Office define zip codes for Antarctica ?
If you accept that the Earth is a perfect sphere, you can obtain the spatial coordinates of a point by
x = R.cos(Lat).cos(Long)
y = R.cos(Lat).sin(Long)
z = R.sin(Lat)
Now, take two points and compute the angle they form with the center of the Earth (using a dot product):
cos(Phi) = (x'.x" + y'.y" + z'.z") / R²
(the value of R gets simplified).
In your case, the angular distance, Phi, equals 2Pi.D/R. (R=6 378.1 km).
A point P" is inside the ground distance (D) of P' when the dot product is larger than cos(Phi).
CAUTION: all angles must be in radians.
Depending on the precision, the data set of points within a certain distance may be extremely large or even infinite (impossible). In a given area of a circle with a positive radius you will have infinitely many points. Thus, it is trivial to determine if a point falls within a circle, however to enumerate over all the points is impossible.
If you do set a fixed precision (such as a single digit), you can loop over all possible latitude and longitude combinations and perform the distance test.
Kevin is correct. There is no reason to calculate every possible coordinate-pair in the radius.
If you start at the centerpoint pC = Point(-76.0000, 38.0000) and are testing to find out if arbitrary point pA = Point(Ax, Ay) is within a 10 mile radius... use the Pythagorean theorem:
xDist = abs( pCx - Ax )
yDist = abs ( pCy - Ay )
r^2 = (xDist)^2 + (yDist)^2
A reasonable approximation is to only query the points where
pAx >= (-76.0000 - 10.0000) && pAx <= (-76.0000 + 10.0000)
pAy >= ( 38.0000 - 10.0000) && pAy <= ( 38.0000 + 10.0000)
then perform the more intensive calculation above.

Resources