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

Related

trying to see if a point is within 50ft of a linestring

I have a database with a bunch of LineString's and I want to see if a Point is within, say, 50ft of that line.
Since it's a LineString, expecting ST_CONTAINS to return true for a point that's even 1ft away from the LineString seems unlikely BUT if there was a way to add an accepted error margin that'd be cool.
Here's the query I did:
SELECT *
FROM railroads
WHERE ST_CONTAINS(SHAPE, ST_GeomFromText('POINT(-10874300.116373 3537642.0497826)', 3857));
Unsurprisingly, it returns no results.
Any ideas? I'm running MySQL 8.0.22.
You need a condition like
ST_Distance(shape, geo_constant) < distance.
Another pattern to do it is
ST_Intersect(shape, ST_Buffer(geo_constant, distance)).
Buffer is expensive, so make sure you buffer a single constant, not the table column.
But there is another issue here, you are using projection 3857, so the distance is in projection units, not feet or meters. If you care about precision, transform Geometry to Geography type.

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

How to find point along line defined by two points?

There is a function in google maps geometry library
interpolate(from:LatLng, to:LatLng, fraction:number)
which finds a point between two other points:
A--X--B
I need something very similar, find a point further along the line:
A--B--X
Interpolate does not accept fraction>1 so I cannot use it. Is there some simple way to calculate the point?
I want to achieve given distance between A and X points.
EDIT: In my application the distance was really small so I used fromLatLngToPoint conversion and linear interpolation, which get good enough results on small area.
You can calculate bearing, then find destination point with code from this excellent page

Mysql Distance from test point to a polygon

I have stored some map zones to a table using Geometry type field.
So the inserts are like this:
INSERT INTO zones (zoneName, coords) VALUES ('name',
PolygonFromText('POLYGON((
41.11396418691335 1.2562662363052368,
41.11370552595821 1.2560248374938965,
41.11851079510035 1.2459397315979004,
41.11880984984478 1.2461864948272705,
41.11396418691335 1.2562662363052368))'));
Then I have the user position, and I need to know if he is inside some zone. This works well with this:
SELECT id
FROM zones
WHERE MBRContains(coords,GeomFromText('POINT(41.117783 1.260590)'))
But sometimes, user position is not perfect, so I think its better to know wich zone is closest to user position.
That is the part that I don't have any idea about... I found some queries to get distance between two points, but not a point and polygons.
The MBR series of functions (like MBRContains) are unsuitable for what you're trying to do; they only test bounding rectangle inclusion.
You may wish to jump forward to MySQL 5.6.1, and use the ST_ functions, like ST_Contains. These functions actually test the geometry.
The problem you're working on can be defined as an uncertainty in the position of your POINT when you go to compare it to your collection of boundary POLYGON items.
Try this: create a POLYGON from your point that is a square with the size of your uncertainty. You can think of this square as a "fuzzy" point. (You could also use an octagon or another closer approximation of a circle in place of a rectangle, but your querying speed will slow.)
Then use ST_Within to see if you have a unique polygon that entirely contains your fuzzy point. If you get just one polygon, you're done.
If you get multiple polygons that entirely contain your fuzzy point, that means some of your boundary polygons overlap other ones. You need to figure out what this means in your problem space. If your data is intended to be properly structured cartographic boundary data, it means you have a data mistake. (NOTE: This is not unheard of :-)
If you get no polygons that entirely contain your fuzzy point, then your fuzzy point may or may not overlap the boundary of at least one polygon. Use ST_Overlaps to find those polygons.
If you get just one, you're done -- your fuzzy point is near the boundary of just one polygon.
If you get none, you're done -- your fuzzy point is away from the boundaries of all your polygons.
If you get more than one hit, you have an ambiguity -- your fuzzy point is near the boundary of more than one polygon.
This is the hard case to sort out. You could reduce the size of the fuzzy point and try again. This MIGHT yield just one polygon result. But, you could deceive yourself into thinking that your points are more accurate than they are by doing this.
MySQL doesn't have the geometric operator Area(Intersection(Polygon, FuzzyPoint)). If it did you could choose the polygon with the biggest area of intersection with your fuzzy point, and that would be a good disambiguator. But it would still be as inaccurate as the position of your point.
Maybe your application should handle the category of result "too near the boundary of A, B, and C to be sure."

Is there a function in mysql to get the MBR(Minimal Bounding Rectangles) of Geometry?

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