MySQL - Calculating a 3D Distance for stored data? - mysql

All-
I was just curious, I'm trying to basically calculate a distance to a multiple positions I have in a database, and was wondering if this is possible to do in a query?
I have maybe 7-9 million rows of positions (x, y, z, continent) and basically want to do a query like:
SELECT positions FROM my_table WHERE DISTANCE(x, y, z, new_x, new_y, new_z) < 500;
Does this even seem remotely possible? Or will I have to bring all the data down + do the calculations w/PHP? I've only seen it done w/GEO data vs. 3D coordinates.
Thanks in advance!
~ Josh

The distance between objects in x,y,z is the difference between each coordinate of the two objects.
Distance between (x₁, y₁, z₁) and (x₂, y₂, z₂)
(x₁-x₂, y₁-y₂, z₁-z₂)
The straight distance between the two points will be the root of the sum of the square of these values
√((x₁-x₂)²+(y₁-y₂)²+(z₁-z₂)²)
Given some (X,Y,Z) coordinate, table "stars" with coordinate columns x, y and z, this might work:
SELECT *
FROM stars
WHERE SQRT(POWER(x-X,2)+POWER(y-Y,2)+POWER(z-Z,2)) < 500

Related

Invalid result for calculating angles between triangle respective planes

I need to find the angle between two triangles' respective planes. I use triangles from an .stl file of different objects. I have followed the answer from this question. It works with some of the shapes, however, I recently encountered a problem, where the resulting cosine of the angle equals 2, thus it is not correct.
Neither of the two triangles in this case are degenerate, as their points respectively are A, B, C and B, C, D. The common edge is BC. The values:
A (50.3473, 2.03038, 50)
B (99.072, 10.6219, 50)
C (50.3473, 0.3038, 0)
D (99.072, 10.6219, 50)
When I calculate the cross products of BC X AB and BC X AD, they both have the same values. After normalizing them and finding the dot product, it results in 2.
Am I doing something wrong? What does this mean?
Any help is appreciated.
Cauchy-Schwarz inequality: the dot product of two normalized vectors cannot be greater than 1.
The problem must be in the normalisation of the vectors, or in the dot product calculation.

SQL needed to get a subset of locations based on lat/long with a min/max distance constraint

I have MySQL table with 500 location records that has a similar structure to:
id, name, lat, long
Lat & long are decimal (float) location values.
My need is to return a random 100 record set that are a minimum 200 meters and a maximum 500 meters away from each other. I'm familiar with using the great circle formula to get the distance between two points. However, I have no idea how to write a select statement to compare all locations against each other to ensure the distance requirements for the random 100 selected? Any thoughts or help would be greatly appreciated. My only tools are a MySQL database so the solution needs to be written in MySQL SQL. Thank you in advance.
SELECT *
FROM (
SELECT p.latitude1 AS latitude1, p.longitude1 AS longitude1, p.latitude2 AS latitude2, p.longitude2 AS longitude2,
(((ACOS(SIN((latitude2*PI()/180)) * SIN((latitude1*PI()/180))+COS((latitude2*PI()/180)) * COS((latitude1*PI()/180)) * COS(((longitude2- longitude1)* PI()/180))))*180/PI())*60*1.1515) AS distance
FROM places p
)
WHERE distance > 200 AND distance < 500
ORDER BY RAND()
LIMIT 100
If you are only looking at 500 metres then take some short cuts and pretend this is an xy space and use simple trigonometry. Can you even get away with a square instead of donut ?
You could use that as the first cut and then to proper maths on the remainder.
Your second cut will now be small enough. Assign a random no to each and take top X. Voila
edit For the first part, cheat and use Google maps. Find out what fraction of a degree equates to 500 metres at the equator. Use x +/- that value and the same for y. Quick and dirty first cut. **ok it won't work at the poles! **

SQL Finding the coordinates that belong to a circle

I have a SQL database set of places to which I am assigned coordinates (lat, long). I would like to ask those points that lie within a radius of 5km from my point inside. I wonder how to construct a query in a way that does not collect unnecessary records?
Since you are talking about small distances of about 5 km and we are probably not in the direct vicinity of the north or south pole we can work with an approximated grid system of longitude and latitude values. Each degree in latidude is equivalent to a distance of km_per_lat=6371km*2*pi/360degrees = 111.195km. The distance between two longitudinal lines that are 1 degree apart depends on the actual latitude:
km_per_long=km_per_lat * cos(lat)
For areas here in North Germany (51 degrees north) this value would be around 69.98km.
So, assuming we are interested in small distances around lat0 and long0 we can safely assume that the translation factors for longitudinal and latitudinal angles will stay the same and we can simply apply the formula
SELECT 111.195*sqrt(power(lat-#lat0,2)
+power(cos(pi()/180*#lat0)*(long-#long0),2)) dist_in_km FROM tbl
Since you want to use the formula in the WHERE clause of your select you could use the following:
SELECT * FROM tbl
WHERE 111.195*sqrt(power(lat-#lat0,2)
+power(cos(pi()/180*#lat0)*(long-#long0),2)) < 5
The select statement will work for latitude and longitude values given in degree (in a decimal notation). Because of that we have to convert the value inside the cos() function to radians by multiplying it with pi()/180.
If you have to work with larger distances (>500km) then it is probably better to apply the appropriate distance formula used in navigation like
cos(delta)=cos(lat0)*cos(lat)*cos(long-long0) + sin(lat0)*sin(lat)
After calculating the actual angle delta by applying acos() you simply multiply that value by the earth's radius R = 6371km = 180/pi()*111.195km and you have your desired distance (see here: Wiki: great circle distance)
Update (reply to comment):
Not sure what you intend to do. If there is only one reference position you want to compare against then you can of course precompile your distance calculation a bit like
SELECT #lat0:=51,#long0:=-9; -- assuming a base position of: 51°N 9°E
SELECT #rad:=PI()/180,#fx:=#rad*6371,#fy:=#fx*cos(#rad*#lat0);
Your distance calculation will then simplify to just
SELECT #dist:=sqrt(power(#fx*(lat-#lat0),2)+power(#fy*(long-#long0),2))
with current positions in lat and long (no more cosine functions necessary). It is up to you whether you want to store all incoming positions in the database first or whether you want to do the calculations somewhere outside in Spring, Java or whatever language you are using. The equations are there and easy to use.
I would go with Euklid. dist=sqrt(power(x1-x2,2)+power(y1-y2,2)) . It works everywhere. Maybe you have to add a conversion to the x/y-coordinates, if degrees can't be translated in km that easy.
Than you can go and select everything you like WHERE x IS BETWEEN (x-5) AND (x+5) AND y IS BETWEEN (y-5) AND (y+5) . Now you can check the results with Euklid.
With an optimisation of the result order, you can get better results at first. Maybe there's a way to take Euklid to SQL, too.

Selecting polar coordinates from cartesian coordinates in a database

In my MySQL database I have three fields, x,y,z representing a position.
I would like to transform these coordinates into polar coordinates az,el,r, and based on these, select the rows where (e.g.) az are within some region.
How would I go about doing this in MySQL?
EDIT:
This in not a question of how to actually do the coordinate transformation, but rather, if MySQL is capable of transforming the data based on some method, and then selecting data once it is transformed with a criterion based on a comparison of the transformed data.
Solve the Triangle ...
Cartesian = How far along and how far up
Polar = How far away and what angle
In order to convert you need to solve the right triangle for the two known sides
you need to use Pythagoras theorem to find the long side (hypotenuse)
you need the Tangent Function to find the angle
r = √ ( x2 + y2 ) = Pythagoras
θ = tan-1 ( y / x ) = Tangent Function
assuming there's no negative values - then you would have to take the inverse of tan function, or convert them to their positive counterpart
Mysql Pythagorus
SQRT((POWER(242-'EAST',2)) + (POWER(463-'NORT',2))) < 50
assuming your coordinates look like this.... here is an example
http://www.tek-tips.com/viewthread.cfm?qid=1397712
Tangent Function here
http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_tan
IMHO this is really a spherical coordinate system maths problem, not a MySQL-specific question.
MySQL just happens to be the data container in this instance.
For any solution you need to work out the maths first, then it becomes a matter of applying the equations to the data.
I can help with MySQL, but I'd have to Google solving these equations and my fingers are tired =)

What is the most efficient way to query based on 3D Euclidean distance?

I have a MySQL table with X, Y, and Z coordinates. Each row of this table corresponds to a specific point in three space. Currently, this data is stored as three separate integer columns, but I can change that if need be.
I want to query this table to find the closest point given the input point (x, y, z). One naive way to do this would be to select SQRT(POW((TableName.X - x), 2) + POW((TableName.Y - y), 2) + POW((TableName.Z - z), 2)) AS Distance for each row in the table, and then select the row that has the smallest Distance.
I know MySQL has a Point data type, but I'm not sure if that will help here. Does anyone know of an efficient way to calculate Euclidean distance? Thanks in advance.
Order by POW((TableName.X - x), 2) + POW((TableName.Y - y), 2) + POW((TableName.Z - z), 2) without the SQRT.
Since you only care about ordering, and the square root is monotone increasing, you can skip the square root. Without the SQRT, the math should be fast enough.