1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package s2
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 import (
32 "bytes"
33 "fmt"
34 "io"
35 "strconv"
36 "strings"
37
38 "github.com/golang/geo/r3"
39 )
40
41
42 func writePoint(w io.Writer, p Point) {
43 ll := LatLngFromPoint(p)
44 fmt.Fprintf(w, "%.15g:%.15g", ll.Lat.Degrees(), ll.Lng.Degrees())
45 }
46
47
48 func writePoints(w io.Writer, pts []Point) {
49 for i, pt := range pts {
50 if i > 0 {
51 fmt.Fprint(w, ", ")
52 }
53 writePoint(w, pt)
54 }
55 }
56
57
58
59 func parsePoint(s string) Point {
60 p := parsePoints(s)
61 if len(p) > 0 {
62 return p[0]
63 }
64
65 return Point{r3.Vector{0, 0, 0}}
66 }
67
68
69
70 func pointToString(point Point) string {
71 var buf bytes.Buffer
72 writePoint(&buf, point)
73 return buf.String()
74 }
75
76
77 func parsePoints(s string) []Point {
78 lls := parseLatLngs(s)
79 if len(lls) == 0 {
80 return nil
81 }
82 points := make([]Point, len(lls))
83 for i, ll := range lls {
84 points[i] = PointFromLatLng(ll)
85 }
86 return points
87 }
88
89
90
91 func pointsToString(points []Point) string {
92 var buf bytes.Buffer
93 writePoints(&buf, points)
94 return buf.String()
95 }
96
97
98 func parseLatLngs(s string) []LatLng {
99 var lls []LatLng
100 if s == "" {
101 return lls
102 }
103
104 for _, piece := range strings.Split(s, ",") {
105 piece = strings.TrimSpace(piece)
106
107
108 if piece == "" {
109 continue
110 }
111
112 p := strings.Split(piece, ":")
113 if len(p) != 2 {
114 continue
115 }
116
117 lat, err := strconv.ParseFloat(p[0], 64)
118 if err != nil {
119 panic(fmt.Sprintf("invalid float in parseLatLngs: %q, err: %v", p[0], err))
120 }
121
122 lng, err := strconv.ParseFloat(p[1], 64)
123 if err != nil {
124 panic(fmt.Sprintf("invalid float in parseLatLngs: %q, err: %v", p[1], err))
125 }
126
127 lls = append(lls, LatLngFromDegrees(lat, lng))
128 }
129 return lls
130 }
131
132
133 func makeRect(s string) Rect {
134 var rect Rect
135 lls := parseLatLngs(s)
136 if len(lls) > 0 {
137 rect = RectFromLatLng(lls[0])
138 }
139
140 for _, ll := range lls[1:] {
141 rect = rect.AddPoint(ll)
142 }
143
144 return rect
145 }
146
147
148 func makeCellUnion(tokens ...string) CellUnion {
149 var cu CellUnion
150
151 for _, t := range tokens {
152 cu = append(cu, CellIDFromString(t))
153 }
154 return cu
155 }
156
157
158
159 func makeLoop(s string) *Loop {
160 if s == "full" {
161 return FullLoop()
162 }
163 if s == "empty" {
164 return EmptyLoop()
165 }
166
167 return LoopFromPoints(parsePoints(s))
168 }
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 func makePolygon(s string, normalize bool) *Polygon {
188 var loops []*Loop
189
190
191 if s == "empty" || s == "" {
192 return PolygonFromLoops(loops)
193 }
194
195 for _, str := range strings.Split(s, ";") {
196
197
198
199
200 if str == "" {
201 continue
202 }
203 loop := makeLoop(strings.TrimSpace(str))
204 if normalize && !loop.IsFull() {
205 loop.Normalize()
206 }
207 loops = append(loops, loop)
208 }
209 return PolygonFromLoops(loops)
210 }
211
212
213 func makePolyline(s string) *Polyline {
214 p := Polyline(parsePoints(s))
215 return &p
216 }
217
218
219 func makeLaxPolyline(s string) *LaxPolyline {
220 return LaxPolylineFromPoints(parsePoints(s))
221 }
222
223
224
225 func laxPolylineToString(l *LaxPolyline) string {
226 var buf bytes.Buffer
227 writePoints(&buf, l.vertices)
228 return buf.String()
229
230 }
231
232
233
234
235
236
237 func makeLaxPolygon(s string) *LaxPolygon {
238 var points [][]Point
239 if s == "" {
240 return LaxPolygonFromPoints(points)
241 }
242 for _, l := range strings.Split(s, ";") {
243 if l == "full" {
244 points = append(points, []Point{})
245 } else if l != "empty" {
246 points = append(points, parsePoints(l))
247 }
248 }
249 return LaxPolygonFromPoints(points)
250 }
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272 func makeShapeIndex(s string) *ShapeIndex {
273 fields := strings.Split(s, "#")
274 if len(fields) != 3 {
275 panic("shapeIndex debug string must contain 2 '#' characters")
276 }
277
278 index := NewShapeIndex()
279
280 var points []Point
281 for _, p := range strings.Split(fields[0], "|") {
282 p = strings.TrimSpace(p)
283 if p == "" {
284 continue
285 }
286 points = append(points, parsePoint(p))
287 }
288 if len(points) > 0 {
289 p := PointVector(points)
290 index.Add(&p)
291 }
292
293 for _, p := range strings.Split(fields[1], "|") {
294 p = strings.TrimSpace(p)
295 if p == "" {
296 continue
297 }
298 if polyline := makeLaxPolyline(p); polyline != nil {
299 index.Add(polyline)
300 }
301 }
302
303 for _, p := range strings.Split(fields[2], "|") {
304 p = strings.TrimSpace(p)
305 if p == "" {
306 continue
307 }
308 if polygon := makeLaxPolygon(p); polygon != nil {
309 index.Add(polygon)
310 }
311 }
312
313 return index
314 }
315
316
317
318
319
320 func shapeIndexDebugString(index *ShapeIndex) string {
321 var buf bytes.Buffer
322
323 for dim := 0; dim <= 2; dim++ {
324 if dim > 0 {
325 buf.WriteByte('#')
326 }
327
328 var count int
329
330
331
332
333 for i := int32(0); i < index.nextID; i++ {
334 shape := index.Shape(i)
335
336
337 if shape == nil || shape.Dimension() != dim {
338 continue
339 }
340 if count > 0 {
341 buf.WriteString(" | ")
342 } else {
343 if dim > 0 {
344 buf.WriteByte(' ')
345 }
346 }
347
348 for c := 0; c < shape.NumChains(); c++ {
349 if c > 0 {
350 if dim == 2 {
351 buf.WriteString("; ")
352 } else {
353 buf.WriteString(" | ")
354 }
355 }
356 chain := shape.Chain(c)
357 pts := []Point{shape.Edge(chain.Start).V0}
358 limit := chain.Start + chain.Length
359 if dim != 1 {
360 limit--
361 }
362
363 for e := chain.Start; e < limit; e++ {
364 pts = append(pts, shape.Edge(e).V1)
365 }
366 writePoints(&buf, pts)
367 count++
368 }
369 }
370
371 if dim == 1 || (dim == 0 && count > 0) {
372 buf.WriteByte(' ')
373 }
374 }
375
376 return buf.String()
377 }
378
379
380
381
382
View as plain text