tidwall / tile38

Real-time Geospatial and Geofencing
https://tile38.com
MIT License
9k stars 563 forks source link

Filter with distance #537

Open vuchau opened 4 years ago

vuchau commented 4 years ago

I have a list of offers with format

    "offers": [
    {
      "lat": "33.66209712",
      "lng": "-84.1817986",
      "name": "offer_1",
      "allow_distance": 10
    },
    {
        "lat": "33.69103912",
        "lng": "-84.24225095",
        "name": "offer_2",
        "allow_distance": 5
      },

    ....
  ]
}

User need to filter the offers within radius on current location. eg. 6km. The big problem is to see the offers, the distance from user to offers must be lest than or equal with value of field allow_distance. I can combine multiple query and code to filter, but I want to know tile38 has any query statement to solve this case. Currently, I put data with command:

SET offers offer_n FIELD allow_distance n POINT x y

Filter command

NEARBY offers DISTANCE POINT lat long radius

Thanks,

ghost commented 4 years ago

You could represent your offers as GeoJSON objects that approximate the offers range as a polygon then use the INTERSECTS command with a point.

e.g.

> SET offers offer_1 OBJECT {"type":"Polygon","coordinates":[[[-84.1817986,33.75192864841195],[-84.22314112812471,33.74508375080194],[-84.25817229604576,33.72559412355786],[-84.28155178555076,33.69643409967211],[-84.28972750872953,33.6620502220315],[-84.28147210031605,33.627680080450254],[-84.25805960392128,33.59855321839846],[-84.22306144262863,33.57909675306351],[-84.1817986,33.57226559158804],[-84.14053575737135,33.57909675306351],[-84.1055375960787,33.59855321839846],[-84.08212509968394,33.627680080450254],[-84.07386969127045,33.6620502220315],[-84.08204541444923,33.69643409967211],[-84.10542490395423,33.72559412355786],[-84.14045607187526,33.74508375080194],[-84.1817986,33.75192864841195]]]}
{"ok":true,"elapsed":"68.6µs"}
> SET offers offer_2 OBJECT {"type":"Polygon","coordinates":[[[-84.24225095,33.73595488420598],[-84.26291919527999,33.73253415489009],[-84.28043655529918,33.72279348898564],[-84.2921343812964,33.70821761686156],[-84.29623358567402,33.6910273826622],[-84.29211443143649,33.67384058624713],[-84.28040834192508,33.65927301367186],[-84.26289924540367,33.64954064732091],[-84.24225095,33.646123355794025],[-84.22160265459632,33.64954064732091],[-84.2040935580749,33.65927301367186],[-84.19238746856352,33.67384058624713],[-84.18826831432597,33.6910273826622],[-84.19236751870358,33.70821761686156],[-84.20406534470084,33.72279348898564],[-84.22158270472,33.73253415489009],[-84.24225095,33.73595488420598]]]}
{"ok":true,"elapsed":"20µs"}
> INTERSECTS offers OBJECT {"type":"Point","coordinates":[-84.28075790405273,33.70320652139349]
{"ok":true,"objects":[{"id":"offer_2","object":{"type":"Polygon","coordinates":[[[-84.24225095,33.73595488420598],[-84.26291919527999,33.73253415489009],[-84.28043655529918,33.72279348898564],[-84.2921343812964,33.70821761686156],[-84.29623358567402,33.6910273826622],[-84.29211443143649,33.67384058624713],[-84.28040834192508,33.65927301367186],[-84.26289924540367,33.64954064732091],[-84.24225095,33.646123355794025],[-84.22160265459632,33.64954064732091],[-84.2040935580749,33.65927301367186],[-84.19238746856352,33.67384058624713],[-84.18826831432597,33.6910273826622],[-84.19236751870358,33.70821761686156],[-84.20406534470084,33.72279348898564],[-84.22158270472,33.73253415489009],[-84.24225095,33.73595488420598]]]}}],"count":1,"cursor":0,"elapsed":"33µs"}
vuchauthanh-agilityio commented 4 years ago

{"ok":true,"objects":[{"id":"offer_2","object":{"type":"Polygon","coordinates":[[[-84.24225095,33.73595488420598],[-84.26291919527999,33.73253415489009],[-84.28043655529918,33.72279348898564],[-84.2921343812964,33.70821761686156],[-84.29623358567402,33.6910273826622],[-84.29211443143649,33.67384058624713],[-84.28040834192508,33.65927301367186],[-84.26289924540367,33.64954064732091],[-84.24225095,33.646123355794025],[-84.22160265459632,33.64954064732091],[-84.2040935580749,33.65927301367186],[-84.19238746856352,33.67384058624713],[-84.18826831432597,33.6910273826622],[-84.19236751870358,33.70821761686156],[-84.20406534470084,33.72279348898564],[-84.22158270472,33.73253415489009],[-84.24225095,33.73595488420598]]]}}],"count":1,"cursor":0,"elapsed":"33µs"}

Thanks for your help. It's means, need to generate Polygon base on location and allow_distance for each offer when saving to tile38? Could you help explain more?. Thanks

ghost commented 4 years ago

For this example I just used the JS library 'circle-to-polygon'

The algorithm is pretty straight forward, as long as your circles don't cross the poles or the meridian. You find the points that are 'allowed_distance' away, going counter-clockwise in the number of steps that you want in your polygon.

The few things to keep in mind is: