-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathparser.go
More file actions
112 lines (87 loc) · 2.25 KB
/
Copy pathparser.go
File metadata and controls
112 lines (87 loc) · 2.25 KB
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
package osmtransit
import (
"context"
"os"
"github.com/paulmach/osm"
"github.com/paulmach/osm/osmpbf"
)
// Parser is the struct that contains all the options and data to parse OSM PBF files.
type Parser struct {
File *os.File
Stops bool
StopAreas bool
}
func NoStop(p *Parser) {
p.Stops = false
}
func NoStopArea(p *Parser) {
p.StopAreas = false
}
// ParserOption is a function that sets a certain config on a Parser.
//
// This is part of the self referential functions design.
// See more: https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html
type ParserOption func(*Parser)
// NewParser creates a new custom parser.
//
// Use self referential functions design to configure.
// See more: https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html
func NewParser(file string, opts ...ParserOption) (*Parser, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
parser := Parser{
File: f,
Stops: true,
StopAreas: true,
}
for _, opt := range opts {
opt(&parser)
}
return &parser, nil
}
// scan scans the OSM pbf file for each elements
func (p *Parser) scan(objects chan osm.Object) {
scanner := osmpbf.New(context.Background(), p.File, 5)
defer scanner.Close()
for scanner.Scan() {
o := scanner.Object()
objects <- o
}
scanErr := scanner.Err()
if scanErr != nil {
panic(scanErr)
}
close(objects)
}
// extractor selects OSM objects
func (p *Parser) extractor(transit chan TransitData, objects chan osm.Object) {
for o := range objects {
if o.ObjectID().Type() == osm.TypeNode {
obj := o.(*osm.Node)
if p.Stops && isStop(obj) {
transit <- StopFromNode(obj)
} else if p.StopAreas && isStopArea(obj) {
transit <- StopAreaFromNode(obj)
}
}
}
close(transit)
}
// Extract parses OSM data and extracts transit data
func (p *Parser) Extract(transit chan TransitData) {
objects := make(chan osm.Object, 100)
go p.scan(objects)
go p.extractor(transit, objects)
}
// Parse returns transit data in a slice from an OSM pbf file
func (p *Parser) TransitData() []TransitData {
result := []TransitData{}
transit := make(chan TransitData, 100)
p.Extract(transit)
for t := range transit {
result = append(result, t)
}
return result
}