-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathfilter.go
115 lines (100 loc) · 2.38 KB
/
filter.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
package topojson
import (
geojson "github.com/paulmach/go.geojson"
)
// Filter topology into a new topology that only contains features with the given IDs
func (t *Topology) Filter(ids []string) *Topology {
result := &Topology{
Type: t.Type,
Transform: t.Transform,
BoundingBox: t.BoundingBox,
Objects: make(map[string]*Geometry),
}
arcMap := make(map[int]int)
for _, g := range t.Objects {
geom := remapGeometry(arcMap, ids, g)
if geom != nil {
result.Objects[geom.ID] = geom
}
}
result.Arcs = make([][][]float64, len(arcMap))
for k, v := range arcMap {
result.Arcs[v] = t.Arcs[k]
}
return result
}
func remapGeometry(arcMap map[int]int, ids []string, g *Geometry) *Geometry {
found := false
for _, id := range ids {
if g.ID == id {
found = true
break
}
}
if !found {
return nil
}
geom := &Geometry{
ID: g.ID,
Type: g.Type,
Properties: g.Properties,
BoundingBox: g.BoundingBox,
}
switch g.Type {
case geojson.GeometryPoint:
geom.Point = g.Point
case geojson.GeometryMultiPoint:
geom.MultiPoint = g.MultiPoint
case geojson.GeometryLineString:
geom.LineString = remapLineString(arcMap, g.LineString)
case geojson.GeometryMultiLineString:
geom.MultiLineString = remapMultiLineString(arcMap, g.MultiLineString)
case geojson.GeometryPolygon:
geom.Polygon = remapMultiLineString(arcMap, g.Polygon)
case geojson.GeometryMultiPolygon:
polygons := make([][][]int, len(g.MultiPolygon))
for i, poly := range g.MultiPolygon {
polygons[i] = remapMultiLineString(arcMap, poly)
}
geom.MultiPolygon = polygons
case geojson.GeometryCollection:
geometries := make([]*Geometry, 0)
for _, geometry := range g.Geometries {
out := remapGeometry(arcMap, ids, geometry)
if out != nil {
geometries = append(geometries, out)
}
}
geom.Geometries = geometries
}
return geom
}
func remapLineString(arcMap map[int]int, in []int) []int {
out := make([]int, len(in))
for i, arc := range in {
a := arc
reverse := false
if a < 0 {
a = ^a
reverse = true
}
idx, ok := arcMap[a]
if !ok {
idx = len(arcMap)
arcMap[a] = idx
}
if reverse {
out[i] = ^idx
} else {
out[i] = idx
}
}
return out
}
func remapMultiLineString(arcMap map[int]int, in [][]int) [][]int {
lines := make([][]int, len(in))
for i, line := range in {
lines[i] = remapLineString(arcMap, line)
}
return lines
}