Mysql: ST_Contains with borders to detect if multipolygon contains point - mysql

I use mysql spatial functions.
I have to understand if points lies withing multipolygon.
Initially I used MBRContains but it works in a strange way, so I faced the following error: Mysql function MBRContains is not accurate
My next step was switching to the functions ST_Contains. But I found out that if I use polygon(from multipolygon) vertex as argument - function returns false but I want to unclude all multipolygon borders.
P.S.
I found that where are function:
ST_Touches(g1, g2)
Two geometries spatially touch if their interiors do not intersect,
but the boundary of one of the geometries intersects either the
boundary or the interior of the other
Looks like it works like I want(in OR conditions with ST_contains) but documentation is not clear for me. Can you explain how can 2 conditions be truth together
1. Interiors do not intersects
2. Boundary intersects the interrior.
?
Question:
How can I achieve the behaviour I want?

This looks like a working solution:
ST_Contains(g1,g2) || ST_Touches(g1, g2)

Looks like ST_Distance(AREA, #point)) = 0 includes border

Related

Mysql: find polygon within certain radius

In my database I have polygons stored. Now I need to search all the polygons that are within a certain radius.
Even if the polygon is only a small part inside the region, then it should be included inside the results (so once there is a minimal match, there is a match).
What is the best way to do this? I have been thinking about creating another polygon and search everything that intersects this, but don't know if this is a valid method?
Yes, I think it is the best approach. You can create a polygon using ST_BUFFER and then you can use ST_INTERSECT to find if polygons will intersect your polygon.
May be you can also do it using ST_DISTANCE. It will calculate minimum distance of a point from polygon.
Select ST_DISTANCE(polygons,POINT(x, y)) as distance, polygon_id from your_polygon_table WHERE distance <= 10
I struggled with the same issue and came up with the following that works well.
select this.poly, other.poly
from table this, table other
where this.name = 'name of subject polygon'
and ST_Distance(ST_Centroid(this.polygon),ST_Centroid(other.polygon)) < 'desired distance';
This will work with the initial point is in the same table as the other polygons. If you have a fixed initial point you can simplify the query as follows:
select poly from table
where ST_Distance('26.36, -81.07',ST_Centroid(other.polygon)) < 'desired distance';

Circle intersect MySQL

I have two circle on a map with Longitude, Latitude (point()) and Radius and now I would know if there is a SQL function that return true if those circle intersect ?
Thx for help.
Try:
If(ST_Distance(POINT(Long1, Lat1),POINT(Long2, Lat2))<=Radius1+Radius2, "INTERSECT","NO INTERSECTION")
Which is basically asking if the distance between the centers of the circles is <= the sum of their radii. If it is - they intersect.
Try ST_***() functions available in MySQL 5.6.
More information.
https://dev.mysql.com/doc/refman/5.6/en/spatial-relation-functions-object-shapes.html
https://www.percona.com/blog/2013/10/21/using-the-new-mysql-spatial-functions-5-6-for-geo-enabled-applications/
You indeed need to use the ST_*() functions and spatial operator functions, but Zamrony's answer is rather vague. So, what you need to do is to convert your circles into geometry data types and then you can use st_intersect() to see if the 2 circles intersect:
Use ST_Buffer() function to convert point and radius into geometry data type:
Returns a geometry that represents all points whose distance from the
geometry value g is less than or equal to a distance of d, or NULL if
any argument is NULL.
Pls read the description of ST_Buffer_Strategy() as well on how points making up the circle geometries are determined.
Use ST_Intersects() function to determine if the two geometries intersect each other.

Check if a point is near a linestring with MySQL Spatial Extension (untrustable)

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()

Calculating the outer boundary of several Geometry objects in SQL Server 2008

I have lots of Polygons of datatype Geometry in SQL Server 2008. The image below shows how a select of all these Geometrys looks visualized.
What I need to do is create a Polygon which represents the outer boundary of all these polygons. So I used the response given to a previous spatial question I asked to create the following code:
DECLARE #test TABLE(geom GEOMETRY);
INSERT INTO #test SELECT geom FROM ForceBoundary
DECLARE #geom GEOMETRY
SELECT #geom = (SELECT TOP 1 geom FROM #test)
SELECT #geom = #geom.STUnion(geom) FROM #test
SELECT #geom
This produced the following result, which has cracks in it due to holes between the polygons:
So I updated my query with the following change:
INSERT INTO #test SELECT geom.Reduce(0.001).STBuffer(100) FROM ForceBoundary
Which improved the result, however it's not solving the issue completely and it also damages the outer boundary accuracy.
What is the correct way to achieve this? From looking through a list of the STxxxx functions I couldn't see one that seemed to provide the results I need?
Answer provided by geographika at GIS StackExchange:
It sounds like you want to remove slivers. There is a function for this in the SQL Server Spatial Tools project - FilterArtifactsGeometry.
A blog post on using the function can be found here.
This has an option for filtering out small poylgons using the ringTolerance parameter:
Remove all polygon rings thinner than provided tolerance (e.g. ring.STArea < ringTolerance x ring.STLength). A value of 0 will not remove any rings.
In practice, this allows very thin polygon rings (slivers) to be
detected and removed while leaving more typically shaped polygon rings
alone. The presumption is, of course, that slivers are undesirable
but non-sliver rings are desirable.
Have you tried the [geom].STExteriorRing() command?

MBR Within not accurate 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.