Skip to content
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

Merged
merged 19 commits into from
Feb 17, 2016
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@
- Add: detect forbidden chars in entity ids and attr names in URI (Issue #1793)
- Add: dates support in attribute values (Issue #1038)
- Add: implemented new operation: POST /v2/op/query (Issue #1080)
- Fix: NGSIv2 URI param 'georel' (along with 'geometry' and 'coords') proper support (Issue #1677)
- Add: scope FIWARE::Location::NGSIv2 to allow using NGSIv2 geo-queries also with NGSIv1 (Issue #1677)
Copy link
Member

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

- Fix: segfault caused by parameter without value in query string (Issue #1805)
8 changes: 4 additions & 4 deletions doc/apiary/v2/fiware-ngsiv2-reference.apib
Original file line number Diff line number Diff line change
Expand Up @@ -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 `#`.
Copy link
Member

Choose a reason for hiding this comment

The 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
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/lib/common/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
*/
#define FIWARE_LOCATION "FIWARE::Location"
#define FIWARE_LOCATION_DEPRECATED "FIWARE_Location" // Deprecated (but still supported) in Orion 0.16.0
#define FIWARE_LOCATION_V2 "FIWARE::Location::NGSIv2"

#define EARTH_RADIUS_METERS 6371000

Expand Down
117 changes: 114 additions & 3 deletions src/lib/mongoBackend/MongoGlobal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Member Author

Choose a reason for hiding this comment

The 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.

Copy link
Member

Choose a reason for hiding this comment

The 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"

Expand Down Expand Up @@ -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)
Expand All @@ -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);
}
}
Expand Down
Loading