comparison pkg/imports/sr.go @ 960:e23ae2c83427

Load boundary polygon of sounding result from ZIP file.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 17 Oct 2018 12:23:39 +0200
parents 6ab012d0f0c2
children a4c92e0ef2e1
comparison
equal deleted inserted replaced
959:6ab012d0f0c2 960:e23ae2c83427
9 "errors" 9 "errors"
10 "fmt" 10 "fmt"
11 "io" 11 "io"
12 "log" 12 "log"
13 "os" 13 "os"
14 "path/filepath" 14 "path"
15 "strconv" 15 "strconv"
16 "strings" 16 "strings"
17 "time" 17 "time"
18 18
19 shp "github.com/jonas-p/go-shp"
20
19 "gemma.intevation.de/gemma/pkg/octree" 21 "gemma.intevation.de/gemma/pkg/octree"
20 ) 22 )
21 23
22 type SoundingResult struct { 24 type SoundingResult struct {
23 who string 25 who string
24 dir string 26 zip string
25 } 27 }
26 28
27 const SoundingResultDateFormat = "2006-01-02" 29 const SoundingResultDateFormat = "2006-01-02"
28 30
29 type SoundingResultDate struct{ time.Time } 31 type SoundingResultDate struct{ time.Time }
50 func (sr *SoundingResult) Who() string { 52 func (sr *SoundingResult) Who() string {
51 return sr.who 53 return sr.who
52 } 54 }
53 55
54 func (sr *SoundingResult) CleanUp() error { 56 func (sr *SoundingResult) CleanUp() error {
55 return os.RemoveAll(sr.dir) 57 return os.RemoveAll(sr.zip)
56 } 58 }
57 59
58 func find(needle string, haystack []*zip.File) *zip.File { 60 func find(needle string, haystack []*zip.File) *zip.File {
59 needle = strings.ToLower(needle) 61 needle = strings.ToLower(needle)
60 for _, straw := range haystack { 62 for _, straw := range haystack {
155 } 157 }
156 defer r.Close() 158 defer r.Close()
157 return loadXYZReader(r) 159 return loadXYZReader(r)
158 } 160 }
159 161
162 type (
163 Point struct {
164 X float64
165 Y float64
166 }
167 LineString []Point
168 Polygon []LineString
169 )
170
171 func toPolygon(numParts int32, parts []int32, points []shp.Point) Polygon {
172 out := make(Polygon, numParts)
173 pos := 0
174 for i := range out {
175 ps := parts[i]
176 line := make(LineString, ps)
177 for j := int32(0); j < ps; j, pos = j+1, pos+1 {
178 p := &points[pos]
179 line[j] = Point{p.X, p.Y}
180 }
181 out[i] = line
182 }
183 return out
184 }
185
186 func loadBoundary(z *zip.ReadCloser) (Polygon, error) {
187 shpF := find(".shp", z.File)
188 if shpF == nil {
189 return nil, nil
190 }
191 prefix := strings.TrimSuffix(shpF.Name, path.Ext(shpF.Name))
192 dbfF := find(prefix+".dbf", z.File)
193 if dbfF == nil {
194 return nil, fmt.Errorf("No DBF file found for %s", shpF.Name)
195 }
196
197 shpR, err := shpF.Open()
198 if err != nil {
199 return nil, err
200 }
201
202 dbfR, err := dbfF.Open()
203 if err != nil {
204 shpR.Close()
205 return nil, err
206 }
207 sr := shp.SequentialReaderFromExt(shpR, dbfR)
208 defer sr.Close()
209
210 if !sr.Next() {
211 return nil, sr.Err()
212 }
213
214 _, s := sr.Shape()
215 if s == nil {
216 return nil, sr.Err()
217 }
218
219 switch p := s.(type) {
220 case *shp.Polygon:
221 return toPolygon(p.NumParts, p.Parts, p.Points), nil
222 case *shp.PolygonZ:
223 return toPolygon(p.NumParts, p.Parts, p.Points), nil
224 case *shp.PolygonM:
225 return toPolygon(p.NumParts, p.Parts, p.Points), nil
226 }
227 return nil, fmt.Errorf("Unsupported shape type %T", s)
228 }
229
160 func (sr *SoundingResult) Do(conn *sql.Conn) error { 230 func (sr *SoundingResult) Do(conn *sql.Conn) error {
161 231
162 z, err := zip.OpenReader(filepath.Join(sr.dir, "upload.zip")) 232 z, err := zip.OpenReader(sr.zip)
163 if err != nil { 233 if err != nil {
164 return err 234 return err
165 } 235 }
166 defer z.Close() 236 defer z.Close()
167 237
191 261
192 if len(xyz) == 0 { 262 if len(xyz) == 0 {
193 return errors.New("XYZ does not contain any vertices.") 263 return errors.New("XYZ does not contain any vertices.")
194 } 264 }
195 265
196 // TODO: Implement more. 266 // Is there a boundary shapefile in the ZIP archive?
267 polygon, err := loadBoundary(z)
268 if err != nil {
269 return err
270 }
271
272 _ = polygon
273
274 // TODO: Send to database.
197 275
198 return nil 276 return nil
199 } 277 }