-
Notifications
You must be signed in to change notification settings - Fork 266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/1677 geo location #1801
Changes from 18 commits
f67a239
c7f2fef
6bcd211
4df9ca9
9a99d59
0f40c87
01ec8be
c4ddd77
566ec7c
d1364a6
ed83024
4095d69
869bae9
8f4dcf4
e84c1ea
92aaa61
f40a707
15ec2b1
367b713
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -299,7 +299,7 @@ Fields used as identifiers in the NGSIv2 API follow special rules regarding allo | |
|
||
The rules are: | ||
|
||
* Allowed characters are the ones in the plain ASCII set except the following ones: whitespace, `&`, ?`, `/` and `#`. | ||
* Allowed characters are the ones in the plain ASCII set except the following ones: whitespace, `&`, `?`, `/` and `#`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not actually related with this PR, but a small typo known time ago now being fixed. NTC |
||
* Maximum field length is 256 characters. | ||
|
||
In addition to the above rules, given NGSIv2 server implementations could add additional syntactical restrictions in those | ||
|
@@ -545,7 +545,7 @@ and the reference geometry must be exactly the same. | |
+ `geometry=polygon`, defines a polygon. | ||
+ `geometry=box`, defines a bounding box. | ||
|
||
**coords** must be a string containing a comma separated list of pairs of geographical coordinates | ||
**coords** must be a string containing a semicolon separated list of pairs of geographical coordinates | ||
in accordance with the geometry specified and the rules mandated by the Simple Location Format: | ||
|
||
* `geometry=point`. `coords` will contain a pair of WGS-84 geo-coordinates. | ||
|
@@ -561,7 +561,7 @@ Matching entities will be located, at a maximum, 1000 meters far away from the r | |
`georel=near;minDistance=5000&geometry=point&coords=-40.4,-3.5`. | ||
Matching entities will be at least 5000 meters far away from the reference point. | ||
|
||
`georel=coveredBy&geometry=polygon&coords=25.774,-80.190,18.466,-66.118,32.321,-64.757,25.774,-80.190` | ||
`georel=coveredBy&geometry=polygon&coords=25.774,-80.190;18.466,-66.118;32.321,-64.757;25.774,-80.190` | ||
Matching entities will be those located within the referred polygon. | ||
|
||
### Query Resolution | ||
|
@@ -651,7 +651,7 @@ Response code: | |
+ geometry: point (optional, string) - Geografical area to which the query is restricted. | ||
See [Geographical Queries](#geographical_queries). | ||
|
||
+ coords: 40.6391,-8.6533 (optional, string) - List of latitude-longitude pairs of coordinates separated by ','. | ||
+ coords: 40.6391,-8.6533 (optional, string) - List of latitude-longitude pairs of coordinates separated by ';'. | ||
See [Geographical Queries](#geographical_queries). | ||
|
||
+ limit: 20 (optional, number) - Limits the number of entities to be retrieved | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -898,6 +898,108 @@ static bool processAreaScope(const Scope* scoP, BSONObj &areaQuery) | |
} | ||
|
||
|
||
/* ***************************************************************************** | ||
* | ||
* processAreaScopeV2 - | ||
* | ||
* Returns true if areaQuery was filled, false otherwise | ||
* | ||
*/ | ||
static bool processAreaScopeV2(const Scope* scoP, BSONObj &areaQuery) | ||
{ | ||
if (!mongoLocationCapable()) | ||
{ | ||
std::string details = std::string("location scope was found but your MongoDB version doesn't support it. ") + | ||
"Please upgrade MongoDB server to 2.4 or newer)"; | ||
|
||
alarmMgr.badInput(clientIp, details); | ||
return false; | ||
} | ||
|
||
// Fill BSON corresponding to geometry | ||
BSONObj geometry; | ||
if (scoP->areaType == orion::PointType) | ||
{ | ||
geometry = BSON("type" << "Point" << "coordinates" << BSON_ARRAY(scoP->point.longitude() << scoP->point.latitude())); | ||
} | ||
else if (scoP->areaType == orion::LineType) | ||
{ | ||
// Arbitrary number of points | ||
BSONArrayBuilder ps; | ||
for (unsigned int ix = 0; ix < scoP->line.pointList.size(); ++ix) | ||
{ | ||
orion::Point* p = scoP->line.pointList[ix]; | ||
ps.append(BSON_ARRAY(p->longitude() << p->latitude())); | ||
} | ||
geometry = BSON("type" << "LineString" << "coordinates" << ps.arr()); | ||
} | ||
else if (scoP->areaType == orion::BoxType) | ||
{ | ||
BSONArrayBuilder ps; | ||
ps.append(BSON_ARRAY(scoP->box.lowerLeft.longitude() << scoP->box.lowerLeft.latitude())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In order this to work, lowerLeft has to be the real lower left corner and upperRight has to be the real upper right corner. Is the fill() method at Scope class ensuring this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As discussed over skype - no, there is no check/fix for that right now. Must be implemented. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 92aaa61 |
||
ps.append(BSON_ARRAY(scoP->box.upperRight.longitude() << scoP->box.lowerLeft.latitude())); | ||
ps.append(BSON_ARRAY(scoP->box.upperRight.longitude() << scoP->box.upperRight.latitude())); | ||
ps.append(BSON_ARRAY(scoP->box.lowerLeft.longitude() << scoP->box.upperRight.latitude())); | ||
ps.append(BSON_ARRAY(scoP->box.lowerLeft.longitude() << scoP->box.lowerLeft.latitude())); | ||
geometry = BSON("type" << "Polygon" << "coordinates" << BSON_ARRAY(ps.arr())); | ||
} | ||
else if (scoP->areaType == orion::PolygonType) | ||
{ | ||
// Arbitrary number of points | ||
BSONArrayBuilder ps; | ||
for (unsigned int ix = 0; ix < scoP->polygon.vertexList.size(); ++ix) | ||
{ | ||
orion::Point* p = scoP->polygon.vertexList[ix]; | ||
ps.append(BSON_ARRAY(p->longitude() << p->latitude())); | ||
} | ||
geometry = BSON("type" << "Polygon" << "coordinates" << BSON_ARRAY(ps.arr())); | ||
} | ||
else | ||
{ | ||
LM_E(("Runtime Error (unknown area type: %d)", scoP->areaType)); | ||
return false; | ||
} | ||
|
||
if (scoP->georel.type == "near") | ||
{ | ||
BSONObjBuilder near; | ||
near.append("$geometry", geometry); | ||
if (scoP->georel.maxDistance >= 0) | ||
{ | ||
near.append("$maxDistance", scoP->georel.maxDistance); | ||
} | ||
if (scoP->georel.minDistance >= 0) | ||
{ | ||
near.append("$minDistance", scoP->georel.minDistance); | ||
} | ||
areaQuery = BSON("$near" << near.obj()); | ||
} | ||
else if (scoP->georel.type == "coveredBy") | ||
{ | ||
areaQuery = BSON("$geoWithin" << BSON("$geometry" << geometry)); | ||
} | ||
else if (scoP->georel.type == "intersects") | ||
{ | ||
areaQuery = BSON("$geoIntersects" << BSON("$geometry" << geometry)); | ||
} | ||
else if (scoP->georel.type == "disjoint") | ||
{ | ||
areaQuery = BSON("$exists" << true << "$not" << BSON("$geoIntersects" << BSON("$geometry" << geometry))); | ||
} | ||
else if (scoP->georel.type == "equals") | ||
{ | ||
areaQuery = geometry; | ||
} | ||
else | ||
{ | ||
LM_E(("Runtime Error (unknown georel type: '%s')", scoP->georel.type.c_str())); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
|
||
#define OPR_EXIST "EXISTS" | ||
#define OPR_NOT_EXIST "NOT EXIST" | ||
|
||
|
@@ -1842,7 +1944,7 @@ bool entitiesQuery | |
// FIXME P5: NGSI "v1" filter, probably to be removed in the future | ||
addFilterScope(sco, filters); | ||
} | ||
else if (sco->type == FIWARE_LOCATION || sco->type == FIWARE_LOCATION_DEPRECATED) | ||
else if (sco->type == FIWARE_LOCATION || sco->type == FIWARE_LOCATION_DEPRECATED || sco->type == FIWARE_LOCATION_V2) | ||
{ | ||
geoScopes++; | ||
if (geoScopes > 1) | ||
|
@@ -1853,10 +1955,19 @@ bool entitiesQuery | |
{ | ||
BSONObj areaQuery; | ||
|
||
if (processAreaScope(sco, areaQuery)) | ||
bool result; | ||
if (sco->type == FIWARE_LOCATION_V2) | ||
{ | ||
std::string locCoords = ENT_LOCATION "." ENT_LOCATION_COORDS; | ||
result = processAreaScopeV2(sco, areaQuery); | ||
} | ||
else // FIWARE Location NGSIv1 (legacy) | ||
{ | ||
result = processAreaScope(sco, areaQuery); | ||
} | ||
|
||
if (result) | ||
{ | ||
std::string locCoords = ENT_LOCATION "." ENT_LOCATION_COORDS; | ||
finalQuery.append(locCoords, areaQuery); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This last line is not actually part of this PR, but soon to be added.
NTC