-
Notifications
You must be signed in to change notification settings - Fork 0
/
pbfreader.go
150 lines (127 loc) · 3.38 KB
/
pbfreader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package ownmapdal
import (
"context"
"io"
"runtime"
"github.com/jamesrr39/goutil/errorsx"
"github.com/jamesrr39/goutil/gofs"
"github.com/jamesrr39/ownmap-app/ownmap"
"github.com/paulmach/osm"
"github.com/paulmach/osm/osmpbf"
)
type PBFReader interface {
Header() (*osmpbf.Header, error)
Scan() bool
Object() osm.Object
Err() error
Reset() errorsx.Error
FullyScannedBytes() int64
TotalSize() int64
}
type DefaultPBFReader struct {
file gofs.File
*osmpbf.Scanner
totalSize int64
}
func NewDefaultPBFReader(file gofs.File) (*DefaultPBFReader, errorsx.Error) {
fileInfo, err := file.Stat()
if err != nil {
return nil, errorsx.Wrap(err)
}
osmPBFReader := osmpbf.New(context.Background(), file, runtime.NumCPU())
return &DefaultPBFReader{file, osmPBFReader, fileInfo.Size()}, nil
}
func (r *DefaultPBFReader) TotalSize() int64 {
return r.totalSize
}
func (r *DefaultPBFReader) Reset() errorsx.Error {
err := r.Scanner.Close()
if err != nil {
return errorsx.Wrap(err)
}
_, err = r.file.Seek(0, io.SeekStart)
if err != nil {
return errorsx.Wrap(err)
}
r.Scanner = osmpbf.New(context.Background(), r.file, runtime.NumCPU())
return nil
}
type ImportRunType struct {
Bounds osm.Bounds
RequiredTagKeysMap map[string]bool
Rescan *Rescan
MaxItemsPerBatch uint64
}
func (importRun *ImportRunType) Validate() errorsx.Error {
if importRun.MaxItemsPerBatch == 0 {
return errorsx.Errorf("no MaxItemsPerBatch specified")
}
zeroBounds := osm.Bounds{}
if importRun.Bounds == zeroBounds {
return errorsx.Errorf("bounds not set")
}
return nil
}
type OnNodeReceivedFuncType func(node *ownmap.OSMNode) errorsx.Error
type OnWayReceivedFuncType func(way *ownmap.OSMWay, nodes []*ownmap.OSMNode) errorsx.Error
type OnRelationReceivedFuncType func(relation *ownmap.OSMRelation, nodes []*ownmap.OSMNode) errorsx.Error
type GetNodeByIDType func(id int64) (*ownmap.OSMNode, errorsx.Error)
type GetWayByIDType func(id int64) (*ownmap.OSMWay, errorsx.Error)
type GetRelationByIDType func(id int64) (*ownmap.OSMRelation, errorsx.Error)
// scanBatch returns (reader has more objects to scan, error)
func scanBatch(
pbfReader PBFReader,
importRun *ImportRunType,
scanObject scanObjectFunc,
) (bool, errorsx.Error) {
var err error
// scan batch
for i := uint64(0); i < importRun.MaxItemsPerBatch; i++ {
cont := pbfReader.Scan()
if !cont {
return false, nil
}
err = scanObject(pbfReader.Object())
if err != nil {
return false, errorsx.Wrap(err)
}
}
if pbfReader.Err() != nil {
return false, errorsx.Wrap(pbfReader.Err())
}
return true, nil
}
func calcBoundsForWay(points []*ownmap.Location) osm.Bounds {
objBounds := osm.Bounds{
MaxLat: -90,
MinLat: 90,
MaxLon: -180,
MinLon: 180,
}
for _, point := range points {
if point.Lat < objBounds.MinLat {
objBounds.MinLat = point.Lat
}
if point.Lat > objBounds.MaxLat {
objBounds.MaxLat = point.Lat
}
if point.Lon < objBounds.MinLon {
objBounds.MinLon = point.Lon
}
if point.Lon > objBounds.MaxLon {
objBounds.MaxLon = point.Lon
}
}
return objBounds
}
func atLeastOneNodeInBounds(points []*ownmap.Location, bounds osm.Bounds) bool {
if len(points) == 0 {
// none of the nodes are within the specified bounds for the import. Ignore this way.
return false
}
boundsForWay := calcBoundsForWay(points)
if !ownmap.Overlaps(boundsForWay, bounds) {
return false
}
return true
}