comparison pkg/imports/sr.go @ 972:17a03a84b0e8

Split out polygon code out of sounding result importer source file.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 18 Oct 2018 12:22:08 +0200
parents f9fb6c399f3f
children b6fec8f85599
comparison
equal deleted inserted replaced
971:f9fb6c399f3f 972:17a03a84b0e8
1 package imports 1 package imports
2 2
3 import ( 3 import (
4 "archive/zip" 4 "archive/zip"
5 "bufio" 5 "bufio"
6 "bytes"
7 "context" 6 "context"
8 "database/sql" 7 "database/sql"
9 "encoding/binary"
10 "encoding/json" 8 "encoding/json"
11 "errors" 9 "errors"
12 "fmt" 10 "fmt"
13 "io" 11 "io"
14 "log" 12 "log"
15 "math"
16 "os" 13 "os"
17 "path" 14 "path"
18 "strconv" 15 "strconv"
19 "strings" 16 "strings"
20 "time" 17 "time"
38 Date SoundingResultDate `json:"date"` 35 Date SoundingResultDate `json:"date"`
39 Bottleneck string `json:"bottleneck"` 36 Bottleneck string `json:"bottleneck"`
40 EPSG uint `json:"epsg"` 37 EPSG uint `json:"epsg"`
41 DepthReference string `json:"depth-reference"` 38 DepthReference string `json:"depth-reference"`
42 } 39 }
43
44 Point struct {
45 X float64
46 Y float64
47 }
48 LineString []Point
49 Polygon []LineString
50 )
51
52 const (
53 wkbNDR byte = 1
54 wkbPolygon uint32 = 3
55 ) 40 )
56 41
57 const ( 42 const (
58 insertPointsSQL = ` 43 insertPointsSQL = `
59 INSERT INTO waterway.sounding_results ( 44 INSERT INTO waterway.sounding_results (
204 } 189 }
205 defer r.Close() 190 defer r.Close()
206 return loadXYZReader(r) 191 return loadXYZReader(r)
207 } 192 }
208 193
209 func toPolygon(numParts int32, parts []int32, points []shp.Point) Polygon {
210 out := make(Polygon, numParts)
211 pos := 0
212 for i := range out {
213 ps := parts[i]
214 line := make(LineString, ps)
215 for j := int32(0); j < ps; j, pos = j+1, pos+1 {
216 p := &points[pos]
217 line[j] = Point{p.X, p.Y}
218 }
219 out[i] = line
220 }
221 return out
222 }
223
224 func loadBoundary(z *zip.ReadCloser) (Polygon, error) { 194 func loadBoundary(z *zip.ReadCloser) (Polygon, error) {
225 shpF := find(".shp", z.File) 195 shpF := find(".shp", z.File)
226 if shpF == nil { 196 if shpF == nil {
227 return nil, nil 197 return nil, nil
228 } 198 }
252 _, s := sr.Shape() 222 _, s := sr.Shape()
253 if s == nil { 223 if s == nil {
254 return nil, sr.Err() 224 return nil, sr.Err()
255 } 225 }
256 226
257 switch p := s.(type) { 227 return shapeToPolygon(s)
258 case *shp.Polygon:
259 return toPolygon(p.NumParts, p.Parts, p.Points), nil
260 case *shp.PolygonZ:
261 return toPolygon(p.NumParts, p.Parts, p.Points), nil
262 case *shp.PolygonM:
263 return toPolygon(p.NumParts, p.Parts, p.Points), nil
264 }
265 return nil, fmt.Errorf("Unsupported shape type %T", s)
266 } 228 }
267 229
268 func (sr *SoundingResult) Do(conn *sql.Conn) error { 230 func (sr *SoundingResult) Do(conn *sql.Conn) error {
269 231
270 z, err := zip.OpenReader(sr.zip) 232 z, err := zip.OpenReader(sr.zip)
332 // TODO: Build octree 294 // TODO: Build octree
333 // TODO: Generate iso-lines 295 // TODO: Generate iso-lines
334 296
335 return tx.Commit() 297 return tx.Commit()
336 } 298 }
337
338 func (p Polygon) AsWBK() []byte {
339 if p == nil {
340 return nil
341 }
342 // pre-calculate size to avoid reallocations.
343 size := 1 + 4 + 4
344 for _, ring := range p {
345 size += 4 + len(ring)*2*8
346 }
347
348 buf := bytes.NewBuffer(make([]byte, 0, size))
349
350 binary.Write(buf, binary.LittleEndian, wkbNDR)
351 binary.Write(buf, binary.LittleEndian, wkbPolygon)
352 binary.Write(buf, binary.LittleEndian, uint32(len(p)))
353
354 for _, ring := range p {
355 binary.Write(buf, binary.LittleEndian, uint32(len(ring)))
356 for _, v := range ring {
357 binary.Write(buf, binary.LittleEndian, math.Float64bits(v.X))
358 binary.Write(buf, binary.LittleEndian, math.Float64bits(v.Y))
359 }
360 }
361
362 return buf.Bytes()
363 }