It seems like besides using WKT and the GeomFromText function, MySQL support an other method of creating geometries. The function POINT() is used in the examples in the documentation, but I can not find where the function itself is documented.
This one is pretty straightforward, but I wonder if there are any other functions which can be used as well, instead of parsing WKT strings.
MySQL has a spacial data type POINT. It's a type that encapsulates an x and y value pair to represent a coordinate in some space.
You can create a table with a column of that type via:
CREATE TABLE my_table (pt POINT);
For every spacial type there's a "constructor" function(s) to create a value of that type. For example, Point(x,y) - it returns a value of type POINT to be stored in the db, used in another function, etc:
INSERT INTO my_table (pt) VALUES (Point(1,2));
The docs that cover the functions for creating values of these types (incl. the Point() function) can be found at Creating spacial values and the section of the manual that it's in covers spacial types in general.
POINT is not a function, it's a data type.
You use it like POINT(100, 20) to give you a coordinate of x = 100, y = 20.
It is documented at 12.16.2.3 Class Point:
A Point is a geometry that represents a single location in coordinate space.
Point Examples
Imagine a large-scale map of the world with many cities. A Point object could represent each city.
On a city map, a Point object could represent a bus stop.
This is where MySQL documents Point class.
A Point is a geometry that represents a single location in coordinate space.
It is documented here under title 12.16.5 MySQL-Specific Functions That Create Geometry Values
If you need to understand this constructor function and other information on Spatial Type in MySQL, follow my article on Medium Playing with Geometry/Spatial Data Types in MySQL
Related
I am seeking information on how to create a MySQL Geometry type that accepts 3 coordinate values: Northing, Easting, and Elevation.
I can create a POINT data type (with SRID) and populate it with:
ST_SRID(POINT(Northing, Easting), SRID_value_Here)
but a POINT only accepts 2 arguments (based on my understanding).
The Elevation value I need to store is significant as these points will be linked to an AutoCad drawing and stored in a MySQL database.
I guess I am unclear on what Geospatial data type to use as I don't necessarily feel this is a Polygon since it is just a single point entity with 3 coordinate values and not 3 separate points that could close in an form a polygon.
While I am familiar with SQL, Geospatial is a new and opening world to me so any help and pointers are much appreciated.
Thank you.
MYSQL ver 5.7
Requirement:
I have a bunch of POINT geometries in MYSQL table and I have to find all the POINT geometries that are within 5km distance/radius of a GEOMETRYCOLLECTION object.
GEOMETRYCOLLECTION may contain more than one type of geometries like POINT, POLYGON etc.
Sample GEOMETRYCOLLECTION data:
SET #g1 = ST_GeomFromText('GEOMETRYCOLLECTION(POINT (-156.366489591715 66.913750389327),POLYGON ((-156.357608905242 66.906958164897, -156.360302383363 66.9066027336476, -156.361997104194 66.9067073607308, -156.363616093774 66.9066368440642, -156.365477697938 66.9065867326059, -156.368127298976 66.9065970034393, -156.370061891681 66.9066888794808, -156.37182258022 66.9068547305222, -156.373286981259 66.9070724523969, -156.374390675008 66.9072952721882, -156.376359777088 66.9077681138541, -156.377706173961 66.9080113180204, -156.379222192708 66.9081328753119, -156.380729601039 66.9081591586452, -156.382562289578 66.9081211961453, -156.387571662487 66.9099676951007, -156.389320598943 66.9125180930134, -156.389291120818 66.9145787836353, -156.384722634367 66.9167899596735, -156.37955035 66.9195246586276, -156.372520662511 66.9209119638337, -156.360432280238 66.9215118034161, -156.355776993787 66.9203754471679, -156.34906598338 66.9180659711298, -156.347941981299 66.9174007836309, -156.346853913592 66.9167568252985, -156.34605399901 66.9158971169665, -156.346982815675 66.9151925950926, -156.346794497967 66.9144321773854, -156.345642955261 66.9140107294695, -156.343831364638 66.9136152003034, -156.342996512556 66.9130307378043, -156.343113243806 66.9123137492637, -156.343498096931 66.9119029992644, -156.344661664637 66.9111819440571, -156.345080786511 66.9105884961414, -156.345524286511 66.9099605023924, -156.347168040675 66.9098486503092, -156.348952756297 66.9096090419763, -156.348689200048 66.9089614565606, -156.349495732338 66.908706844061, -156.350786711503 66.9082992794783, -156.352211271917 66.9083472388533, -156.353952768789 66.90829894302, -156.355389368787 66.9082072242701, -156.356512531285 66.9079768284371, -156.356677961493 66.9078075857291, -156.356422527119 66.907644261771, -156.355901372953 66.9072802273965, -156.357608905242 66.906958164897)))');
Sample POINT data:
SET #p1 = ST_GeomFromText('GEOMETRYCOLLECTION(POINT (-156.342840017 66.9320439348))');
I have tried ST_DISTANCE_SPHERE(#g1,#p1) spatial function (which returns the value in meters) but it seems it doesn't support geometry types other than POINT and MULTIPOINT.
Then I have used:
ST_DISTANCE(#g1,#p1)
'0.015301834064271899'
I am unable to understand the what is the UNIT of this returned value in MYSQL 5.7?
I have searched a lot on the internet and there is no proper documentation available regarding the same. In POSTGIS, this can be done but I am struggling to do this in MYSQL ver 5.7.
Any help is appreciated.
Thanks in advance!
ST_Distance returns "distance" in degrees here - i.e. the flat map view of the shortest distance between shapes. This value cannot be mapped to real distance, as real world distance of 1 degree along parallel is different from distance of 1 degree along meridian except near the equator.
Looks like MySQL cannot correctly compute distance here. You would be better served by systems with more geospatial support, like PostgreSQL + PostGIS, or Google BigQuery, etc. They give you correct answer, you just need to replace ST_GeomFromText with ST_GeogFromText to work with spherical geographies.
MSDN documentation just defines the return value as:
A double value that specifies the distance between the two closest
points in this geometry value and other.
What units are returned? When testing the values do not match to anything I recognise and does not work in a WHERE clause.
var results = db.Locations.Where(t => t.ItemPoint.Distance(targetPoint) <= 100); // 100km
Note: I am using MySQL with Entity Framework using the .NET Connector, which doesn't support using SRID values.
Whilst the MSDN documentation could do with a little more information, it doesn't specify the measurement of the value as it changes dependant on the SRID (or lack thereof).
Without an SRID, Geometry simply works on a flat grid (or planar) system (think old school square paper). Your distance answers are therefore simple pythagoras results of
a2 + b2 = c2 >>>>>> c = SqRt(a2 + b2).
For example:
using System.Data.Entity.Spatial;
DbGeometry geom1 = DbGeometry.FromText("POINT(0 0)");
DbGeometry geom2 = DbGeometry.FromText("POINT(50 50)");
Console.WriteLine(geom1.Distance(geom2));
//Returns 70.71067811 (the square root of (50 sq'd + 50 sq'd)).
You'll find this blog an interesting read, skip to halfway down the page and you'll find how to create a user-defined haversine calculation method which will allow you to convert the results to distances.
Be warned though, If you can't map Stored Procedures in EF for MySQL, then you'll need to resort to good old fashioned ADO to get the results. Make sure you use st_distance over mbr_distance as st_distance will be exact and mbr_distance will contain false positives. You will need MySQL 5.6.1 for st_distance.
Lastly, if at all possible, consider another database if Spatial data is important.
I am having trouble understanding ST_GeomFromText. It looks like there are 3 sets of 2 numbers. Why is that? Wouldn't coordinates just consist of a latitude and longitude?
Here is an example from http://postgis.net/docs/ST_GeomFromText.html:
SELECT ST_GeomFromText('LINESTRING(-71.160281 42.258729,-71.160837 42.259113,-71.161144 42.25932)');
ST_GeomFromText() takes a WKT expression of a geometry object and
Constructs a PostGIS ST_Geometry object from the OGC Well-Known text representation.
The WKT expression in the example is a LINESTRING which is
a one-dimensional object representing a sequence of points and the line segments connecting them.
You might think a linestring would be two-dimensional, but it's not, because a line has no width or height. (Points are 0-dimensional, polygons are 2-dimensional).
So, by definition, that would have more than one set of coordinates. A pair of coordinates would be a POINT, not a linestring, and would look something like this, in conjunction with the function in question:
ST_GeomFromText('POINT (30 10)');
You may want to read up on some GIS fundamentals:
http://www.cise.ufl.edu/~mschneid/Service/Tutorials/TutorialSDT.pdf - excellent tutorial
http://www.opengeospatial.org/standards/orm - OGC Reference Model
I have to discover if a given point is at least 500 meters (ou other distance) from a route line that exist in my database recorded using the MySQL Spatial.
I see there is no similar function in MySQL Spatial, and find a previous answer that doesn't work for me because the line is too big (more than 300km) to check with this solution point by point:
Find N Nearest LineString From A Point Using MySQL Spatial Extensions
I'm even can't create a buffer (a circle/polygon with a given radius) to the point to check if is even touch.
UPDATE - 12/7
I did it, but MySQL Spatial it is seams not trustable.
I made a createBuffer function, to create a 20 points Polygon around the given Point with a meters given distance for the radius: http://pastebin.com/xEFb8ZXi
I'm testing with the QGis the given results from this buffer, and everything is fine with the function (except the meters to decimal degress value that generate smaller then expected, but it is not the issue right now).
And made a few Intersects checks, and this is aways return true, even if the result polygon is not intersects the line.
I remade the same tests using just the center point, and the results is the same.
I discovery now that the INTERSECT doesn't check the LineString with the Point or Polygon, but the Bounding Box of the LineString, when a indicate a point OUTSIDE the Linestring BBox.
Intersects QUERY Where "rota" is the Linestring data:
SELECT Intersects(rota, createBuffer(GeomFromText('POINT(-19.7736 -43.7255)'),500))
FROM log_viagem WHERE rota IS NOT NULL;
How can I trust the MySQL Spatial now?
Or my concept about INTERSECTS is wrong?
SOLVED:
I didn't read the important note at 5.5 version of MySQL:
Note
Currently, MySQL does not implement these functions according to the specification. Those that are implemented return the same result as the corresponding MBR-based functions.
The Solution is taking with the server administrator to update to 5.6.1, there is an upgrade in the note
Note
MySQL originally implemented these functions such that they used
object bounding rectangles and returned the same result as the
corresponding MBR-based functions. As of MySQL 5.6.1, corresponding
versions are available that use precise object shapes. These versions
are named with an ST_ prefix. For example, Contains() uses object
bounding rectangles, whereas ST_Contains() uses object shapes.
As of MySQL 5.6.1, there are also ST_ aliases for existing spatial
functions that were already exact. For example, ST_IsEmpty() is an
alias for IsEmpty()