forked from Project-OSRM/osrm-backend
-
Notifications
You must be signed in to change notification settings - Fork 7
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/Build spatial index based on google::s2 #248
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
8061068
feat: implement spartial index query based on google::s2
CodeBear801 8f9e868
fix: remove hard code value.
CodeBear801 459b170
fix: refactor code.
CodeBear801 cb08f93
fix: remove local changes.
CodeBear801 6de90a8
fix: update comments
CodeBear801 4dcf8f0
fix: add fake main to pass ci.
CodeBear801 240bb5b
fix: fix issue in unit test. Build()'s result no need to guarantee t…
CodeBear801 8270572
fix: adjust code based on review.
CodeBear801 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// package main contains the tool of chargestation-connectivity generator | ||
// stage 1: | ||
// inputs is json file | ||
// => convert to slice of [id:string,location: lat,lon] | ||
// => calculate cellids for each point(for all levels) | ||
// => build revese index for cellid -> ids | ||
// stage 2: | ||
// => iterate each point | ||
// => generate a circle(s2::cap), find all cellids intersect with that circle | ||
// => retrieve all ids | ||
// => generate result of id(from), ids(all ids in certain distance) | ||
// stage 3: | ||
// => load data from file | ||
// => for each line, its formid and all other ids | ||
// => calculate distance between fromid and all other ids | ||
// => sort result based on distance and write back to file | ||
package main | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
func main() { | ||
// @todo: add logic to generate connectivity for charge stations | ||
fmt.Print("Hello World!") | ||
CodeBear801 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// package spatialindexer answers query of nearest points(place, point of interest) for conditions | ||
CodeBear801 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// such as center location, radius, etc | ||
// | ||
// Sample Scenario 1: Build connectivity for charge stations during pro-processing | ||
// indexer := NewS2Indexer().Build(poiCsvFile) | ||
// for _, stationPoint := range chargeStations { | ||
// nearbyStations := indexer.FindNearByIDs(stationPoint, 800km, -1) | ||
// rankedStations := indexer.RankingIDsByShortestDistance(stationPoint, nearbyStations) | ||
// } | ||
// | ||
// | ||
// Sample Scenario 2: Dump S2Indexer's content to folder | ||
// indexer.Dump(folderPath) | ||
// | ||
// | ||
// Sample Scenario 3: Query reachable charge stations with current energy level | ||
// indexer := NewS2Indexer().Load(folderPath) | ||
// nearbyStations := indexer.FindNearByIDs(currentPoint, currentEnergyLevel, -1) | ||
// | ||
package spatialindexer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package spatialindexer | ||
|
||
// Location for poi point | ||
// @todo: will be replaced by the one in map | ||
type Location struct { | ||
Latitude float64 | ||
Longitude float64 | ||
} | ||
|
||
// PointInfo records point related information such as ID and location | ||
type PointInfo struct { | ||
ID PointID | ||
Location Location | ||
} | ||
|
||
// RankedPointInfo used to record ranking result, distance to specific point could be used for ranking | ||
type RankedPointInfo struct { | ||
PointInfo | ||
Distance float64 | ||
} | ||
|
||
// PointID defines ID for given point(location, point of interest) | ||
// Only the data used for pre-processing contains valid PointID | ||
type PointID int64 | ||
|
||
// Finder answers special query | ||
type Finder interface { | ||
|
||
// FindNearByPointIDs returns a group of points near to given center location | ||
FindNearByPointIDs(center Location, radius float64, limitCount int) []PointInfo | ||
} | ||
|
||
// Ranker used to ranking a group of points | ||
type Ranker interface { | ||
|
||
// RankPointIDsByGreatCircleDistance ranks a group of points based on great circle distance to given location | ||
RankPointIDsByGreatCircleDistance(center Location, nearByIDs []PointInfo) []RankedPointInfo | ||
|
||
// RankPointIDsByShortestDistance ranks a group of points based on shortest path distance to given location | ||
RankPointIDsByShortestDistance(center Location, nearByIDs []PointInfo) []RankedPointInfo | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package poiloader | ||
|
||
import ( | ||
"encoding/json" | ||
"io/ioutil" | ||
|
||
"github.com/golang/glog" | ||
) | ||
|
||
// LoadData accepts json file with points data and returns deserialized result | ||
func LoadData(filePath string) ([]Element, error) { | ||
var elements []Element | ||
|
||
file, err := ioutil.ReadFile(filePath) | ||
if err != nil { | ||
glog.Errorf("While load file %s, met error %v\n", filePath, err) | ||
return elements, err | ||
} | ||
|
||
err = json.Unmarshal(file, &elements) | ||
if err != nil { | ||
glog.Errorf("While unmarshal json file %s, met error %v\n", filePath, err) | ||
return elements, err | ||
} | ||
return elements, nil | ||
} |
70 changes: 70 additions & 0 deletions
70
integration/service/spatialindexer/poiloader/poi_format.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package poiloader | ||
|
||
// Element represent information loaded for point record | ||
type Element struct { | ||
ID int64 `json:"id"` | ||
VendorCode VendorCode `json:"vendor_code"` | ||
VendorPoiID string `json:"vendor_poi_id"` | ||
Lat float64 `json:"lat"` | ||
Lon float64 `json:"lon"` | ||
NavLat float64 `json:"nav_lat"` | ||
NavLon float64 `json:"nav_lon"` | ||
DisLat float64 `json:"dis_lat"` | ||
DisLon float64 `json:"dis_lon"` | ||
MapLinkID int64 `json:"map_link_id"` | ||
SideOfStreet string `json:"side_of_street"` | ||
Country Country `json:"country"` | ||
SpaceID SpaceID `json:"space_id"` | ||
AirportCode string `json:"airport_code"` | ||
IsNational bool `json:"is_national"` | ||
IsStateImportance bool `json:"is_state_importance"` | ||
IsCityImportance bool `json:"is_city_importance"` | ||
Fax string `json:"fax"` | ||
Phone *CategoryIDGather `json:"phone"` | ||
EncodedPhone string `json:"encoded_phone"` | ||
Email string `json:"email"` | ||
WebURL string `json:"web_url"` | ||
CategoryIDGather *CategoryIDGather `json:"category_id_gather"` | ||
ChainGather string `json:"chain_gather"` | ||
RawCategoryGather string `json:"raw_category_gather"` | ||
ChildGather string `json:"child_gather"` | ||
ParentGather string `json:"parent_gather"` | ||
Hilbert float64 `json:"hilbert"` | ||
Amenity Amenity `json:"amenity"` | ||
} | ||
|
||
// Amenity is defined by OSM format: https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dcharging_station | ||
type Amenity string | ||
|
||
const ( | ||
ChargingStation Amenity = "charging_station" | ||
) | ||
|
||
// Country records IOS code | ||
type Country string | ||
|
||
const ( | ||
Usa Country = "USA" | ||
CodeBear801 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
|
||
// SpaceID is used to define a code for political defined administrative area | ||
type SpaceID string | ||
|
||
const ( | ||
UsaCA SpaceID = "USA_CA" | ||
) | ||
|
||
// VendorCode defines data source provider | ||
type VendorCode string | ||
|
||
const ( | ||
Noel VendorCode = "NOEL" | ||
Noft VendorCode = "NOFT" | ||
Nolp VendorCode = "NOLP" | ||
) | ||
|
||
// CategoryIDGather records aggregate data for certain type of point | ||
type CategoryIDGather struct { | ||
Integer *int64 | ||
String *string | ||
} |
64 changes: 64 additions & 0 deletions
64
integration/service/spatialindexer/poiloader/sample_input.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
[ | ||
{ | ||
"id":12345, | ||
"vendor_code":"NOFT", | ||
"vendor_poi_id":"NOFT-10_NREL99930@-@NOCO-37145190@-@NOCO-996595530", | ||
"lat":0.48651, | ||
"lon":0.66526, | ||
"nav_lat":0.48651, | ||
"nav_lon":0.66526, | ||
"dis_lat":0.48651, | ||
"dis_lon":0.66526, | ||
"map_link_id":12345, | ||
"side_of_street":"+", | ||
"country":"USA", | ||
"space_id":"USA_CA", | ||
"airport_code":"NULL", | ||
"is_national":false, | ||
"is_state_importance":false, | ||
"is_city_importance":false, | ||
"fax":"NULL", | ||
"phone":123456789, | ||
"encoded_phone":"123456789", | ||
"email":"NULL", | ||
"web_url":"NULL", | ||
"category_id_gather":"771``794``915", | ||
"chain_gather":"1364@-@@-@", | ||
"raw_category_gather":"NT@-@3578``NT@-@6000``NAICS@-@522110``NT@-@5540", | ||
"child_gather":"NULL", | ||
"parent_gather":"1718449@-@1``2216423@-@1", | ||
"hilbert":2.32E+11, | ||
"amenity":"charging_station" | ||
}, | ||
{ | ||
"id":12346, | ||
"vendor_code":"NOFT", | ||
"vendor_poi_id":"NOFT-10_NREL99930@-@NOCO-37145190@-@NOCO-996595530", | ||
"lat":0.48651, | ||
"lon":0.66526, | ||
"nav_lat":0.48651, | ||
"nav_lon":0.66526, | ||
"dis_lat":0.48651, | ||
"dis_lon":0.66526, | ||
"map_link_id":12345, | ||
"side_of_street":"+", | ||
"country":"USA", | ||
"space_id":"USA_CA", | ||
"airport_code":"NULL", | ||
"is_national":false, | ||
"is_state_importance":false, | ||
"is_city_importance":false, | ||
"fax":"NULL", | ||
"phone":123456789, | ||
"encoded_phone":"123456789", | ||
"email":"NULL", | ||
"web_url":"NULL", | ||
"category_id_gather":"771``794``915", | ||
"chain_gather":"1364@-@@-@", | ||
"raw_category_gather":"NT@-@3578``NT@-@6000``NAICS@-@522110``NT@-@5540", | ||
"child_gather":"NULL", | ||
"parent_gather":"1718449@-@1``2216423@-@1", | ||
"hilbert":2.32E+11, | ||
"amenity":"charging_station" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package s2indexer | ||
|
||
import ( | ||
"github.com/Telenav/osrm-backend/integration/service/spatialindexer" | ||
"github.com/golang/geo/s2" | ||
) | ||
|
||
// https://s2geometry.io/resources/s2cell_statistics.html | ||
// Level = 6 means average area size is 20754.64km2 | ||
// Level = 9 means average area size is 324.29km2 | ||
const minS2Level = 9 | ||
|
||
// Level = 19 means average area size is 309.27km2 | ||
// Level = 20 means average area size is 77.32km2 | ||
const maxS2Level = 20 | ||
|
||
func build(points []spatialindexer.PointInfo, minLevel, maxLevel int) map[s2.CellID][]spatialindexer.PointID { | ||
pointID2CellIDs := make(map[spatialindexer.PointID][]s2.CellID) | ||
cellID2PointIDs := make(map[s2.CellID][]spatialindexer.PointID) | ||
|
||
for _, p := range points { | ||
leafCellID := s2.CellFromLatLng(s2.LatLngFromDegrees(p.Location.Latitude, p.Location.Longitude)).ID() | ||
|
||
var cellIDs []s2.CellID | ||
// For level = 30, its parent equal to current | ||
// So no need append leafCellID into cellIDs outside of for loop | ||
for i := leafCellID.Level(); i > minLevel; i-- { | ||
if i > maxLevel { | ||
continue | ||
} | ||
|
||
parentCellID := leafCellID.Parent(i) | ||
cellIDs = append(cellIDs, parentCellID) | ||
} | ||
|
||
pointID2CellIDs[p.ID] = cellIDs | ||
} | ||
|
||
for pointID, cellIDs := range pointID2CellIDs { | ||
for _, cellID := range cellIDs { | ||
if _, ok := cellID2PointIDs[cellID]; !ok { | ||
var pointIDs []spatialindexer.PointID | ||
cellID2PointIDs[cellID] = pointIDs | ||
} | ||
|
||
cellID2PointIDs[cellID] = append(cellID2PointIDs[cellID], pointID) | ||
} | ||
} | ||
|
||
return cellID2PointIDs | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Just put comments here, to be implemented.