Mercurial > gemma
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 } |