func (this *Index) GetWayInBBox(bb geo.Bbox, tag string) ([]int64, error) { var ret []int64 size := bb.Size() iter := this.db.NewIterator(util.BytesPrefix([]byte(tag+":")), nil) for iter.Next() { key := iter.Key() //log.Println(iter.Key()) if key[0] != byte('_') { tmp := Bboxfrombytes(iter.Value()) //TODO determine best ratio if bb.IntersectWith(tmp) && size < tmp.Size()*1000 && size*1000 > tmp.Size() { //log.Println(iter.Key()) // ret = append(ret, Int64frombytes(key)) k, _ := strconv.ParseInt(strings.Split(string(key[:]), ":")[1], 10, 64) ret = append(ret, k) } } } iter.Release() err := iter.Error() log.Printf("%d Ways found in %v", len(ret), bb) return ret, err }
// Scan before processing need to be call frist after start. func (this *Db) ParseWays() error { //Le dernier est un faux start := time.Now() //On pull les dernier et on sync in order to "close" database at the end. defer this.WayIndex.PullBatch(true) // defer this.WayIndex.db.Close() var bb geo.Bbox var ways []*osmpbf.Way wanted := treeset.NewWith(CompareInt64) //wanted := make(map[int64]*osmpbf.Node) var cw, cow, cn, last int64 cow = this.WayIndex.Size() last = this.WayIndex.Last() found := make(map[int64]*osmpbf.Node, 0) //TODO find nodes by block of wa in order to not redecode the start of a block for i := 0; i < len(this.Descriptor.Ways)-1; i++ { if this.Descriptor.WaysId[i+1] < last { //There always be i+1 since the for condition continue } //log.Printf("Parsing block : %d", i) objects, err := this.Decoder.DecodeBlocAt(this.Descriptor.Ways[i]) if err != nil { return err } for _, v := range objects { switch v := v.(type) { case *osmpbf.Way: //TODO better take to long and my be more slow that the little advatage it gave by resuming //if has, _ := this.WayIndex.db.Has(Int64bytes(v.ID), nil); has if v.ID <= last { //log.Printf("Passing %d", v.ID) //cow++ continue } cw++ //log.Printf("Adding to search %d", v.ID) ways = ExtendWays(ways, v) //TODO check ways with no nodes maybe ? //TODO used an ordered list (invert) for _, nodeId := range v.NodeIDs { /* for i := 0; i < len(wanted); i++ { if nodeId <= wanted[i] { break } } //We don't insert if nodeId == wanted[i] (duplicate) if i == len(wanted) || nodeId < wanted[i] { wanted = append(wanted[:i], append([]int64{nodeId}, wanted[i:]...)...) } //wanted = append(wanted, nodeId) //wanted[nodeId] = nil */ wanted.Add(nodeId) } break } } if wanted.Size() > CacheSize || i == len(this.Descriptor.Ways)-2 { log.Printf("On parse les points pour %d ways soit %d nodes recherchés", len(ways), wanted.Size()) //TODO reused allready found on previous round found, _ = this.GetNodes(wanted, found) //On reset wanted to save space (not obligated but in case it not clear by getNodes) wanted.Clear() for _, way := range ways { for id, nodeId := range way.NodeIDs { cn++ node := found[nodeId] p := geo.Point{node.Lon, node.Lat} if id == 0 { bb = geo.Bbox{p, p} } else { //TODO //Will enlarge bb if needed bb.AddInnerPoint(p) } } // environ 15% de temps en plus tag := "other" if _, ok := way.Tags["natural"]; ok { tag = "natural" } this.WayIndex.Add(way.ID, tag, bb) } //TODO check For update of file //this.WayIndex.db.Sync() //For testing purpose //log.Printf("%v %v", ways[0].ID, ways[0]) //a, e := this.WayIndex.Get(ways[0].ID) //log.Printf("%v %v", a, e) /* //TODO ajout par batch log.Println("Starting db insertion") this.WayIndex.AddBatch(ways, bb) log.Println("db insertion ended") */ ways = make([]*osmpbf.Way, 0) estimation := time.Since(start).Minutes() * (float64(this.Descriptor.TotalWay()-cow) / float64(cw)) time_esti, _ := time.ParseDuration(fmt.Sprintf("%.4fm", estimation)) log.Printf("%dk/%dk %.2f/100 TIME ELAPSED : %s ESTIMATION : %s\r", (cw+cow)/1000, this.Descriptor.TotalWay()/1000, float64((cw+cow)*100)/float64(this.Descriptor.TotalWay()), time.Since(start).String(), time_esti.String()) } } found = make(map[int64]*osmpbf.Node, 0) wanted.Clear() return nil }