I'm passing in some coordinates to mongo to do a geo search. It works fine if the coordinates don't intersect (for instance a figure eight). But when two lines intersect it gives the loop is not valid
. Is there any way to find the intersection and split all these loops up?
Note there could be many.
EDIT: I added the sample query and error. Note that I understand why it's happening, I'm just wondering if there is some known way to split those loops up into separate polygon's (some algorithm or within Mongo).
Query:
db.items.find({
"address.location": {
"$geoWithin": {
"$geometry": {
"type": "Polygon",
"coordinates": [[
[-97.209091, 49.905691],
[-97.206345, 49.918072],
[-97.178879, 49.919399],
[-97.165146, 49.907903],
[-97.164459, 49.892865],
[-97.180939, 49.889326],
[-97.197418, 49.895077],
[-97.200165, 49.902596],
[-97.203598, 49.919399],
[-97.216644, 49.928682],
[-97.244797, 49.927356],
[-97.255096, 49.913209],
[-97.209091, 49.905691]
]]
}
}
}
});
Error:
Error: error: {
"waitedMS" : NumberLong(0),
"ok" : 0,
"errmsg" : "Loop is not valid: [
[ -97.209091, 49.905691 ]
[ -97.206345, 49.918072 ],
[ -97.17887899999999, 49.919399 ],
[ -97.16514599999999, 49.907903 ],
[ -97.16445899999999, 49.892865 ],
[ -97.180939, 49.889326 ],
[ -97.197418, 49.895077 ],
[ -97.200165, 49.902596 ],
[ -97.203598, 49.919399 ],
[ -97.216644, 49.928682 ],
[ -97.24479700000001, 49.927356 ],
[ -97.25509599999999, 49.913209 ],
[ -97.209091, 49.905691 ]
]
Edges 1 and 7 cross.
Edge locations in degrees: [-97.2063450, 49.9180720]-[-97.1788790, 49.9193990]
and [-97.2001650, 49.9025960]-[-97.2035980, 49.9193990]
",
"code" : 2
}
UPDATE
I've added an image of a brute force approach.
Polygon Slicing
There are some issues with this though, it can get quite expensive going through all these loops. Say a max of 50 points would be about 1275 operations.
Also dealing with wrap around on 0/180 degreee coordinates could be a challenge.
Anyway, I didn't want to spend a whole day on this, I could even deal with a solution that does NOT deal with the wrap around condition.
Hoping there is a nice algorithm for this somewhere already I can just pop in (probably has some fancy technical term).
Also would be great if there was a more efficient approach then the brute force look-ahead.
It is because your coordinates are identical that creates an anomaly in the polygon shape: [-97.1788790, 49.9193990] and [-97.2035980, 49.9193990]. In your code remove or change any of the duplicate coordinate,
"coordinates": [[
[-97.209091, 49.905691],
[-97.206345, 49.918072],
[-97.178879, 49.919399], // this line
[-97.165146, 49.907903],
[-97.164459, 49.892865],
[-97.180939, 49.889326],
[-97.197418, 49.895077],
[-97.200165, 49.902596],
[-97.203598, 49.919399], // and this one
[-97.216644, 49.928682],
[-97.244797, 49.927356],
[-97.255096, 49.913209],
[-97.209091, 49.905691]
]]
As I mentioned in comments the better tool to query spatial data would be to use PostGIS.
For example PostGIS have the ST_validReason() to find the problem with polygon and a st_makevalid to fix but if this is not an option then I would create a service available to your PHP script with shapely
python library https://github.com/Toblerity/Shapely
http://toblerity.org/shapely/manual.html
The first premise of Shapely is that Python programmers should be able to perform PostGIS type geometry operations outside of an RDBMS
Certainly shapely
is a popular tool, and you should get future help with in on StackOverflow or gis.stackexchange.com from more experienced users
I think the problem you are trying to solve is not as trivial as it sounds.
So I would perform following steps:
1 Find how to do it with shapely
similar questions: Splitting self-intersecting polygon only returned one polygon in shapely in Python
2 create a simple php service which will pass query details to python script
3 Shapely will not prevent the creation of invalid polygon, but exceptions will be raised when they are operated on. So basically on such exception, I would call the script from step 1.
If this is just for one of query, I would just use QGIS software ( import points as CSV, create a new shapefile layer ( of type polygon ), and use Numerical vertex edit plugin )
update
I think the polygon should be fixed by the tool that created it so in this case, it should be a user. Maybe you fix that problem by looking from a different angle and if the shape is coming from the user and is drawn in GoogleMap in your app maybe enforce no intersection during drawing.
Found also this Drawing a Polygon ( sorting points and creating polygon with no intersection )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With