Recently, I was studying spatialite.I can write 2D data(like this:POINT(1 1)) into the spatial data table,but I can't write 3D data(like this:POINT(1 1 1) ) into the spatial data table.
Who can tell me spatialite whether support 3D? If support ,how can I write a 3D data?
Yes, Spatialite supports 3D geometries (actually 2.5D geometries).
On why it does not work for you, probably your geometry column is not defined as XYZ. You can check geometry metadata with the query:
SELECT * FROM geometry_columns;
To add points with three 3 dimensions you have to use the correct WKT expression: POINTZ(x,y,z).
(see also: https://www.gaia-gis.it/gaia-sins/spatialite-cookbook/html/wkt-wkb.html)
You also have to make sure, that you geometry column is correctly defined as XYZ column. (see functions: Dimension CoordDimension Is3D). GeometryType should therefore return POINTZ
(see also: http://www.gaia-gis.it/gaia-sins/spatialite-sql-4.2.0.html)
Related
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.
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
I have been using the MBRWithin function for quite a lot of times. Suddenly I notice on google map this POINT(101.11857 4.34475) is out of the geo fence which I specify but it still give a value of 1 in mysql any reason or tweaking need to be done?
SELECT MBRWithin(GeomFromText('POINT(101.11857 4.34475)'),GeomFromText('POLYGON((101.12112522125244 4.3531723687957164,101.11846446990967 4.351417913665312,101.13138198852539 4.336397898951581,101.13477230072021 4.33211863778494,101.14065170288086 4.321933898868271,101.14992141723633 4.306699328215635,101.15455627441406 4.30978050198082,101.1397933959961 4.334600612212089,101.12112522125244 4.3531723687957164,101.12112522125244 4.3531723687957164))')) As geoFenceStatus
MySQL 5.6.1 and later have exact geometry algorithms in addition to the earlier functions that only operated on MBR.
You can use ST_WITHIN rather than MBR_WITHIN. See documentation. Like this
SELECT ST_Within(GeomFromText('POINT(101.11857 4.34475)'),
GeomFromText('POLYGON((101.12112522125244 4.3531723687957164,101.11846446990967
4.351417913665312,101.13138198852539 4.336397898951581,101.13477230072021
4.33211863778494,101.14065170288086 4.321933898868271,101.14992141723633
4.306699328215635,101.15455627441406 4.30978050198082,101.1397933959961
4.334600612212089,101.12112522125244 4.3531723687957164,101.12112522125244
4.3531723687957164))')) As geoFenceStatus
MBRWithin() will return results based on the minimum bounding rectangle of it's parameters. Your polygon contains both larger and smaller values for both coordinates than the point, so it will be within the polygon's MBR.
MySQL has no built-in point in polygon algorithm, so you'll either have to roll your own or find one elsewhere. This one seems to be a good candidate.
I found that some result of MBRContains(g1,g2) and other functions seems not right to me.
and I want to find out why. how to see the mbr?
The Envelope function is what you're looking for to get the MBR for an arbitrary Geometry. See: http://dev.mysql.com/doc/refman/5.5/en/gis-general-property-functions.html#function_envelope
could this be why:
http://forums.mysql.com/read.php?23,271928,271968
minimum bounding rectangles for a geometry always have edges parallel to the coordinate axes.
You can just construct them youself with min & max, too.
I agree with Steve0 PostGIS is the way to go...... or you could use the Java Topology Suite (JTS).. or Net Topology Suite (NTS) version... and use datastores such as the very common GIS format of Shapefiles rather than a full db. Guess it depends what you're doing.
As fastmultiplication said MBRs are parallel to coord axes... however you can also use the rotating caliper approach to find minimum bounding boxes which are aligned to the longest axis line of the shape... if you need that.
Check here for more info:
http://cgm.cs.mcgill.ca/~orm/rotcal.html
And in general - MySQL is not the database to use for spatial operations. Most of the spatial functions are not really implemented. I would reccomend PostGIS on Postgresql for a spatial FOSS db. You could also look at spatiallite, built on SQLIte