forked from Project-OSRM/osrm-backend
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
12 changed files
with
588 additions
and
8 deletions.
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,65 @@ | ||
package connectivitymap | ||
|
||
import "github.com/Telenav/osrm-backend/integration/service/spatialindexer" | ||
|
||
type connectivityMapBuilder struct { | ||
iterator spatialindexer.PointsIterator | ||
finder spatialindexer.Finder | ||
ranker spatialindexer.Ranker | ||
distanceLimit float64 | ||
} | ||
|
||
func newConnectivityMapBuilder(iterator spatialindexer.PointsIterator, finder spatialindexer.Finder, | ||
ranker spatialindexer.Ranker, distanceLimit float64) *connectivityMapBuilder { | ||
return &connectivityMapBuilder{ | ||
iterator: iterator, | ||
finder: finder, | ||
ranker: ranker, | ||
distanceLimit: distanceLimit, | ||
} | ||
} | ||
|
||
type placeIDWithNearByPlaceIDs struct { | ||
id spatialindexer.PointID | ||
ids []IDAndDistance | ||
} | ||
|
||
// todo: use task pool | ||
func (builder *connectivityMapBuilder) build() ID2NearByIDsMap { | ||
internalResult := make(chan placeIDWithNearByPlaceIDs, 10000) | ||
m := make(ID2NearByIDsMap) | ||
|
||
go func() { | ||
for p := range builder.iterator.IteratePoints() { | ||
nearbyIDs := builder.finder.FindNearByPointIDs(p.Location, builder.distanceLimit, spatialindexer.UnlimitedCount) | ||
rankedResults := builder.ranker.RankPointIDsByGreatCircleDistance(p.Location, nearbyIDs) | ||
|
||
ids := make([]IDAndDistance, 0, len(rankedResults)) | ||
for _, r := range rankedResults { | ||
ids = append(ids, IDAndDistance{ | ||
ID: r.ID, | ||
Distance: r.Distance, | ||
}) | ||
} | ||
internalResult <- placeIDWithNearByPlaceIDs{ | ||
id: p.ID, | ||
ids: ids, | ||
} | ||
} | ||
close(internalResult) | ||
}() | ||
|
||
for item := range internalResult { | ||
m[item.id] = item.ids | ||
} | ||
|
||
return m | ||
} | ||
|
||
// func (builder *connectivityMapBuilder) dump(folderPath string, m ID2NearByIDsMap) { | ||
|
||
// } | ||
|
||
// func (builder *connectivityMapBuilder) load(folderPath string) (ID2NearByIDsMap, float64) { | ||
|
||
// } |
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,46 @@ | ||
package connectivitymap | ||
|
||
import ( | ||
"github.com/Telenav/osrm-backend/integration/service/spatialindexer" | ||
"github.com/golang/glog" | ||
) | ||
|
||
// IDAndDistance wraps ID and distance information | ||
type IDAndDistance struct { | ||
ID spatialindexer.PointID | ||
Distance float64 | ||
} | ||
|
||
// ID2NearByIDsMap is a mapping between ID and its nearby IDs | ||
type ID2NearByIDsMap map[spatialindexer.PointID][]IDAndDistance | ||
|
||
type ConnectivityMap struct { | ||
id2nearByIDs ID2NearByIDsMap | ||
distanceLimitation float64 | ||
statistic *statistic | ||
} | ||
|
||
func (cm *ConnectivityMap) DistanceLimitation() float64 { | ||
return cm.distanceLimitation | ||
} | ||
|
||
func NewPlaceConnectivityMap(distanceLimitation float64) *ConnectivityMap { | ||
return &ConnectivityMap{ | ||
distanceLimitation: distanceLimitation, | ||
statistic: newStatistic(), | ||
} | ||
} | ||
|
||
func (cm *ConnectivityMap) Build() { | ||
glog.Info("Successfully finished GenerateConnectivityMap\n") | ||
} | ||
|
||
func (cm *ConnectivityMap) Dump(folderPath string) { | ||
} | ||
|
||
func (cm *ConnectivityMap) Load(folderPath string) { | ||
} | ||
|
||
func (cm *ConnectivityMap) QueryConnectivity(placeInfo spatialindexer.PointInfo, limitDistance float64) { | ||
// for each everything recorded in data, apply limit option on that | ||
} |
66 changes: 66 additions & 0 deletions
66
integration/service/connectivitymap/connectivity_map_mock.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,66 @@ | ||
package connectivitymap | ||
|
||
var fakeID2NearByIDsMap1 = ID2NearByIDsMap{ | ||
1: []IDAndDistance{ | ||
IDAndDistance{ | ||
ID: 2, | ||
Distance: 3, | ||
}, | ||
IDAndDistance{ | ||
ID: 5, | ||
Distance: 4, | ||
}, | ||
IDAndDistance{ | ||
ID: 7, | ||
Distance: 6, | ||
}, | ||
IDAndDistance{ | ||
ID: 8, | ||
Distance: 12, | ||
}, | ||
}, | ||
|
||
2: []IDAndDistance{ | ||
IDAndDistance{ | ||
ID: 1, | ||
Distance: 3, | ||
}, | ||
IDAndDistance{ | ||
ID: 7, | ||
Distance: 23, | ||
}, | ||
}, | ||
|
||
5: []IDAndDistance{ | ||
IDAndDistance{ | ||
ID: 1, | ||
Distance: 4, | ||
}, | ||
IDAndDistance{ | ||
ID: 8, | ||
Distance: 5, | ||
}, | ||
}, | ||
|
||
7: []IDAndDistance{ | ||
IDAndDistance{ | ||
ID: 1, | ||
Distance: 6, | ||
}, | ||
IDAndDistance{ | ||
ID: 2, | ||
Distance: 23, | ||
}, | ||
}, | ||
|
||
8: []IDAndDistance{ | ||
IDAndDistance{ | ||
ID: 5, | ||
Distance: 5, | ||
}, | ||
IDAndDistance{ | ||
ID: 1, | ||
Distance: 12, | ||
}, | ||
}, | ||
} |
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,32 @@ | ||
/* | ||
package placeconnectivitymap provides connectivity information for place graphs. | ||
For example, given following graph | ||
- - - - 4 | ||
| | | | | | ||
- 2 - - - | ||
| | | | | | ||
- - - 3 - | ||
| | | | | | ||
1 - - - - | ||
Place connectivity map will pre-process each points and generate following result: | ||
While query connectivity for place 1, will return | ||
(place 2, 3), // the shortest path between place 1 and place 2 is 3 | ||
(place 3, 4), // the shortest path between place 1 and place 2 is 4 | ||
(place 4, 7), // the shortest path between place 1 and place 2 is 7 | ||
The result is sorted by shortest path distance(or other user defined strategy) | ||
When query for connectivity, user could also pass in limitation option, such as distance limitation. | ||
For example, when query connectivity for place 3 | ||
With limitation = -1, it will return | ||
(place 2, 3), // the shortest path between place 3 and place 2 is 3 | ||
(place 4, 3), // the shortest path between place 3 and place 4 is 3 | ||
(place 1, 4), // the shortest path between place 3 and place 1 is 4 | ||
With limitation = 3, it will return | ||
(place 2, 3), // the shortest path between place 3 and place 2 is 3 | ||
(place 4, 3), // the shortest path between place 3 and place 4 is 3 | ||
*/ | ||
package connectivitymap |
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,118 @@ | ||
package connectivitymap | ||
|
||
import ( | ||
"bytes" | ||
"encoding/gob" | ||
"io/ioutil" | ||
"os" | ||
"strings" | ||
|
||
"github.com/Telenav/osrm-backend/integration/pkg/api" | ||
"github.com/golang/glog" | ||
) | ||
|
||
const id2NearByIDsMapFileName = "id2nearbyidsmap.gob" | ||
|
||
func serializeConnectivityMap(cm *ConnectivityMap, folderPath string) error { | ||
if !strings.HasSuffix(folderPath, api.Slash) { | ||
folderPath += api.Slash | ||
} | ||
|
||
if err := serializeID2NearByIDsMap(cm, folderPath); err != nil { | ||
return err | ||
} | ||
|
||
if err := cm.statistic.dump(folderPath); err != nil { | ||
return err | ||
} | ||
|
||
glog.Infof("Successfully deserialize ConnectivityMap from folder %s.\n", folderPath) | ||
|
||
return nil | ||
} | ||
|
||
func deSerializeConnectivityMap(cm *ConnectivityMap, folderPath string) error { | ||
if !strings.HasSuffix(folderPath, api.Slash) { | ||
folderPath += api.Slash | ||
} | ||
|
||
if err := deSerializeID2NearByIDsMap(cm, folderPath); err != nil { | ||
return err | ||
} | ||
|
||
if err := cm.statistic.load(folderPath); err != nil { | ||
return err | ||
} | ||
cm.distanceLimitation = cm.statistic.DistanceLimitation | ||
|
||
return nil | ||
} | ||
|
||
func removeAllDumpFiles(folderPath string) error { | ||
if !strings.HasSuffix(folderPath, api.Slash) { | ||
folderPath += "/" | ||
} | ||
|
||
_, err := os.Stat(folderPath + id2NearByIDsMapFileName) | ||
if !os.IsNotExist(err) { | ||
err = os.Remove(folderPath + id2NearByIDsMapFileName) | ||
if err != nil { | ||
glog.Errorf("Remove file failed %s\n", folderPath+id2NearByIDsMapFileName) | ||
return err | ||
} | ||
} else { | ||
glog.Warningf("There is no %s file in folder %s\n", id2NearByIDsMapFileName, folderPath) | ||
} | ||
|
||
_, err = os.Stat(folderPath + statisticFileName) | ||
if !os.IsNotExist(err) { | ||
err = os.Remove(folderPath + statisticFileName) | ||
if err != nil { | ||
glog.Errorf("Remove file failed %s\n", folderPath+statisticFileName) | ||
return err | ||
} | ||
} else { | ||
glog.Warningf("There is no %s file in folder %s\n", statisticFileName, folderPath) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func serializeID2NearByIDsMap(cm *ConnectivityMap, folderPath string) error { | ||
buf := new(bytes.Buffer) | ||
encoder := gob.NewEncoder(buf) | ||
err := encoder.Encode(cm.id2nearByIDs) | ||
|
||
if err != nil { | ||
glog.Errorf("During encode ConnectivityMap's ID2NearByIDsMap met error %v", err) | ||
return err | ||
} | ||
|
||
if err = ioutil.WriteFile(folderPath+id2NearByIDsMapFileName, buf.Bytes(), 0644); err != nil { | ||
glog.Errorf("During dump ConnectivityMap's ID2NearByIDsMap to %s met error %v", folderPath+id2NearByIDsMapFileName, err) | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func deSerializeID2NearByIDsMap(cm *ConnectivityMap, folderPath string) error { | ||
byteArray, err := ioutil.ReadFile(folderPath + id2NearByIDsMapFileName) | ||
if err != nil { | ||
glog.Errorf("During load ConnectivityMap's ID2NearByIDsMap from %s met error %v", | ||
folderPath+id2NearByIDsMapFileName, err) | ||
return err | ||
} | ||
|
||
buf := bytes.NewBuffer(byteArray) | ||
decoder := gob.NewDecoder(buf) | ||
err = decoder.Decode(&cm.id2nearByIDs) | ||
|
||
if err != nil { | ||
glog.Errorf("During decode ConnectivityMap's ID2NearByIDsMap from %s met error %v", | ||
folderPath+id2NearByIDsMapFileName, err) | ||
return err | ||
} | ||
|
||
return nil | ||
} |
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,60 @@ | ||
package connectivitymap | ||
|
||
import ( | ||
"os" | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/golang/glog" | ||
) | ||
|
||
func TestDumper(t *testing.T) { | ||
cases := []ConnectivityMap{ | ||
ConnectivityMap{ | ||
id2nearByIDs: fakeID2NearByIDsMap1, | ||
distanceLimitation: fakeDistanceLimit, | ||
statistic: &fakeStatisticResult1, | ||
}, | ||
} | ||
|
||
// check whether curent folder is writeable | ||
path, _ := os.Getwd() | ||
_, err := os.OpenFile(path+"/tmp", os.O_RDONLY|os.O_CREATE, 0644) | ||
if err != nil { | ||
return | ||
} | ||
if err := os.Remove(path + "/tmp"); err != nil { | ||
glog.Errorf("During dumper test, remove path %s failed.\n", path+"/tmp") | ||
return | ||
} | ||
|
||
if err := removeAllDumpFiles(path); err != nil { | ||
t.Errorf("During running removeAllDumpFiles met error %v", err) | ||
} | ||
for _, c := range cases { | ||
if err := serializeConnectivityMap(&c, path); err != nil { | ||
t.Errorf("During running serializeConnectivityMap for case %v, met error %v", c, err) | ||
} | ||
|
||
actual := NewPlaceConnectivityMap(0.0) | ||
if err := deSerializeConnectivityMap(actual, path); err != nil { | ||
t.Errorf("During running deSerializeConnectivityMap for case %v, met error %v", c, err) | ||
} | ||
|
||
if !reflect.DeepEqual(actual.id2nearByIDs, c.id2nearByIDs) { | ||
t.Errorf("Expect result \n%+v but got \n%+v\n", c.id2nearByIDs, actual.id2nearByIDs) | ||
} | ||
|
||
if !reflect.DeepEqual(actual.distanceLimitation, c.distanceLimitation) { | ||
t.Errorf("Expect result \n%+v but got \n%+v\n", c.distanceLimitation, actual.distanceLimitation) | ||
} | ||
|
||
if !reflect.DeepEqual(actual.statistic, c.statistic) { | ||
t.Errorf("Expect result \n%+v but got \n%+v\n", c.statistic, actual.statistic) | ||
} | ||
|
||
if err := removeAllDumpFiles(path); err != nil { | ||
t.Errorf("During running removeAllDumpFiles met error %v", err) | ||
} | ||
} | ||
} |
Oops, something went wrong.