Query to calculate a percentage of a GEO surface in a radius - mongodb

I am GeoJSON unfortunately still a bloody beginner. Now I have to solve a problem and understand, unfortunately, no piece of systematics.
Can you please help me and explain how I can use MongoDB to evaluate GEO data for the following case.
We have three areas (for example, countries), these have a value (say base area) now I have a catchment area that covers all three countries in part. How do I get the percentage of each country?
Here is a graphic to visualize the problem:
It is needed here e.g. the areas of A (n), B (n) and C (n).
In the database (mongodb#3.2) I have corresponding document with GEO data. Example:
{
"type": "FeatureCollecton",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
13.6868862,
51.063946
],
[
13.6873401,
51.063999
],
[
13.6883277,
51.0640888
],
...
]
]
},
"properties": {
"name": "Land A",
"qkm": 65.866862
}
},
]
}, ...

Related

$geoWithin query fail to retrieve point included in the queried polygon

I'm trying to query a document using its location with two polygons that are quite similar. Both includes the location of the document but one finds it and the other not. I thought that this was related to "big polygons" but I managed to reduce the polygons enough to rule out this possibility. See previous post. Any idea explaining such a difference?
Playground: https://mongoplayground.net/p/sTEtYD3HU8m:
Document:
{
"_id": {
"$oid": "63ef9379e671073bfb963145"
},
"geometry": {
"type": "Point",
"coordinates": [
2.834,
47.264
]
},
"_class": "org.example.springdatamongodbgeowithinissue.model.SamplingGeometry"
}
Is not in search results for this polygon:
{
"geometry": {
"$geoWithin": {
"$geometry": {
"type": "Polygon",
"coordinates": [
[
[
-16.1,
49.12
],
[
-16.1,
46.156
],
[
16.1,
46.156
],
[
16.1,
49.12
],
[
-16.1,
49.12
]
]
]
}
}
}
}
Still the same issue with Earth's curvature. Your area is long enough to take it into account:
zooming in and's clearly outside:
The map: https://jsfiddle.net/blex18/w9g4bzyk/1/
var map = new google.maps.Map(document.body, {zoom:5,center:{lat:47.264,lng:2.834}});
new google.maps.Polygon({geodesic:true,map:map,geodesic:true,
path:[
{lat:49.12,lng:-16.1},
{lat:46.156,lng:-16.1},
{lat:46.156,lng:16.1},
{lat:49.12,lng:16.1},
{lat:49.12,lng:-16.1}]});
new google.maps.Marker({
position: {lat:47.264,lng:2.834},
map,
title: "Here",
});

OpenStreetMap distances between source and destination(s)

I'm trying to get the distances between one source point and one or more destination points, I'm using the OSRM API to accomplish this. However, the distances being returned are way off.
Source coordinates:
-2.2314725 | 53.4832925
Destination
-2.2315072 | 53.483238
Performing the following request:
http://router.project-osrm.org/table/v1/driving/-2.2314725,53.4832925;-2.2315072,53.483238?sources=0
The distance between the two points should be around 41km, but the result doesn't match at all.
Am I missing something blatantly obvious?
Below is the output from the above request:
{
"durations": [
[
0,
1.3
]
],
"destinations": [
{
"hint": "DBhtiw0YbYteAAAASwAAAAwAAAARAAAAQMh8QZccSEFqRAFARVYzQF4AAABLAAAADAAAABEAAABqpgAAg_Pd_0MXMANP893_HRcwAwEAXxOHnFES",
"distance": 5.459720867300434,
"name": "",
"location": [
-2.231421,
53.483331
]
},
{
"hint": "DBhtiw0YbYtRAAAAWAAAAAwAAAARAAAA27FaQUMzakFqRAFARVYzQFEAAABYAAAADAAAABEAAABqpgAAnPPd_zcXMAMt893_5hYwAwEAXxOHnFES",
"distance": 11.644459328154321,
"name": "",
"location": [
-2.231396,
53.483319
]
}
],
"sources": [
{
"hint": "DBhtiw0YbYteAAAASwAAAAwAAAARAAAAQMh8QZccSEFqRAFARVYzQF4AAABLAAAADAAAABEAAABqpgAAg_Pd_0MXMANP893_HRcwAwEAXxOHnFES",
"distance": 5.459720867300434,
"name": "",
"location": [
-2.231421,
53.483331
]
}
],
"code": "Ok"
}
There are two issues:
You probably mixed latitude and longitude. -2.2314725, 53.4832925 is somewhere in the ocean whereas 53.4832925,-2.2314725 is in Manchester. Sorry, I was wrong. OSRM expects lon,lat.
The two locations are almost identical. They are only 7 meters apart.

MongoDB: Swap values in array in sub document

I have a database with about 6 million documents where each looks like the following:
{
"_id": ObjectId("5d2327409ac8bc0085f3e733"),
"type": "Feature",
"properties": {
"osm_id": "2956281",
"code": 1500,
"fclass": "building",
"name": null,
"type": "tower"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-0.0154288,
51.4539007
],
[
-0.0153606,
51.4540789
],
[
-0.0150739,
51.4540339
],
[
-0.0151478,
51.4538517
],
[
-0.0154288,
51.4539007
]
]
]
}
}
The values in the coordinates array are pairs of lat/longs, but they're in the wrong order for my requirements so I need to switch them. I have written a script in JavaScript which iterates through the array and switches them but it's very slow as it operates on one document at a time.
Is there any way to do this with a more traditional bulk update call, which presumably would be much faster?

TSQL Ploygon Transformation

I'm new to using SQL server Geo-spatial functionality and I seem to have a formatting problem when I'm trying convert text to polygon. I have all the county ploygons from the US Census and when I do a geojson validation check they are displaying correctly. I tried to take those values and create tsql polyons but for some reason they are not valid. Here is what I have:
select geography::STPolyFromText('POLYGON((-95.388 42.909, -95.388 43.255, -94.913 43.255, -94.913 42.909, -95.388 42.909))', 4326);
The above should be a county in Iowa. I have the following example from MS that is working:
select geography::STPolyFromText('POLYGON((-122.358 47.653, -122.348 47.649, -122.348 47.658, -122.358 47.658, -122.358 47.653))', 4326);
Can anyone see what I'm doing wrong?
For reference here is the geojson for the Iowa county:
{ "type": "Feature", "properties": { "GEO_ID": "0500000US19041", "STATE": "19", "COUNTY": "041", "NAME": "Clay", "LSAD": "County", "CENSUSAREA": 567.238000 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -95.388182, 42.909897 ], [ -95.388078, 43.255221 ], [ -94.913723, 43.255054 ], [ -94.913890, 42.909700 ], [ -95.388182, 42.909897 ] ] ] } }

Query to Match a Polygon that contains a Point

The documents in my mongodb collection look like this:
{
"_id" : ObjectId("5562d6831683523f449e7d85")
"geometry" : {
"type" : "Polygon",
"coordinates" :
[[
[-122.4,37.81],
[-132.9, 39.9],
[-122.28, 37.80],
[-124.18, 39.81]
]]
}}
I have a point (lat long pair), which I'll call x and y. I need to see if the coordinates of the document create a polygon such that these coordinates are inside that polygon.
So, of course I need to compute the line describing each edge of the polygon, etc., and then see if the coordinates of the point are within that. However, for now, let's just assume we want to query documents that have x and y within the maximum and minimum lat long values of the entire array.
Here is how I tried to query this:
db.<collection-name>.find(
{'geometry.coordinates':
{$elemMatch:
{
[{$gt:-122.1}, {$lt:-122.0 }], [{$gt: 37.89 },{$lt: 37.91}]
}
}
}
)
however, the result is: Unexpected token [. I tried to follow the example here.
How do I query an array like this, where there are conditions on each element of the array in the document? thanks.
What you seem to be trying to do by matching array elements is actually "Finding a Polygon that contains a Point", which is why I changed your question title.
To accomplish this you are better off using the geoSpatail features of MongoDB rather than trying to work out the bounds yourself. With valid GeoJSON data the query is quite simple using the $geoIntersects operator.
To demonstrate, I'll first set up a collection, with some Polygon data:
db.areas.insert([
{
"name": "San Jose",
"geometry": {
"type": "Polygon",
"coordinates": [[
[ -122.20916748046876, 37.13404537126446 ],
[ -122.20916748046876, 37.496652341233364 ],
[ -121.65710449218749, 37.496652341233364 ],
[ -121.65710449218749, 37.13404537126446 ],
[ -122.20916748046876, 37.13404537126446 ]
]]
}
},
{
"name": "San Franciso",
"geometry": {
"type": "Polygon",
"coordinates": [[
[ -122.73651123046874, 37.58811876638322 ],
[ -122.73651123046874, 37.89219554724437 ],
[ -122.28332519531249, 37.89219554724437 ],
[ -122.28332519531249, 37.58811876638322 ],
[ -122.73651123046874, 37.58811876638322 ]
]]
}
}
])
Then ( though not required for $geoIntersects specifically ) when working with geoSpatial data it is best to have an "index" defined. The one that makes sense for real GeoJSON locations is "2dsphere". The index is created on the field that contains the "root" of the GeoJSON data, which is in this case called "geometry":
db.areas.createIndex({ "geometry": "2dsphere" })
Then all you need to do is supply a .find() query. I'm using the coordinates for "San Francisco city" here:
db.areas.find({
"geometry": {
"$geoIntersects": {
"$geometry": {
"type": "Point",
"coordinates": [
-122.45361328124999,
37.76420119453823
]
}
}
}
})
Which of course returns the "Polyon" defining the "San Franciso" area since that "Point" lies within that object.
{
"name": "San Franciso",
"geometry": {
"type": "Polygon",
"coordinates": [[
[ -122.73651123046874, 37.58811876638322 ],
[ -122.73651123046874, 37.89219554724437 ],
[ -122.28332519531249, 37.89219554724437 ],
[ -122.28332519531249, 37.58811876638322 ],
[ -122.73651123046874, 37.58811876638322 ]
]]
}
}
That is all there is to finding whether your "Point" lies within a "Polygon" you have stored in your collection.
Also look at tools such as geojsonlint.com and geojson.io (examples, not endorsements) in order to validate and visualise your data, which from your example does not provide a well formed Polygon.