Mercurial > gemma
changeset 4313:5da02dcc51f6
shape upload stretch import: Started to decode geometries and attributes from uploaded shape file.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Tue, 03 Sep 2019 16:54:33 +0200 |
parents | 8926fc81e4de |
children | c3b5cf2f200a |
files | pkg/imports/stsh.go pkg/imports/wkb.go pkg/wkb/data.go |
diffstat | 3 files changed, 119 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/pkg/imports/stsh.go Tue Sep 03 16:27:28 2019 +0200 +++ b/pkg/imports/stsh.go Tue Sep 03 16:54:33 2019 +0200 @@ -14,9 +14,20 @@ package imports import ( + "archive/zip" "context" "database/sql" + "errors" + "fmt" + "log" "os" + "path" + "path/filepath" + "strings" + + shp "github.com/jonas-p/go-shp" + + "gemma.intevation.de/gemma/pkg/common" ) type StretchShape struct { @@ -61,6 +72,71 @@ conn *sql.Conn, feedback Feedback, ) (interface{}, error) { - // TODO: Implement me! + + //start := time.Now() + zpath := filepath.Join(stsh.Dir, "stretch.zip") + + z, err := zip.OpenReader(zpath) + if err != nil { + return nil, err + } + defer z.Close() + + shpF := common.FindInZIP(z, ".shp") + if shpF == nil { + return nil, errors.New("no SHP file found in ZIP") + } + prefix := strings.TrimSuffix(shpF.Name, path.Ext(shpF.Name)) + dbfF := common.FindInZIP(z, prefix+".dbf") + if dbfF == nil { + return nil, fmt.Errorf("no DBF file found for %s", shpF.Name) + } + + shpR, err := shpF.Open() + if err != nil { + return nil, err + } + + dbfR, err := dbfF.Open() + if err != nil { + shpR.Close() + return nil, err + } + sr := shp.SequentialReaderFromExt(shpR, dbfR) + defer sr.Close() + + fields := sr.Fields() + + for sr.Next() { + + _, p := sr.Shape() + if p == nil { + feedback.Warn("Invalid NULL geometry found.") + continue + } + poly, err := shapeToPolygon(p) + if err != nil { + feedback.Warn("Invalid geometry found: %v.", err) + continue + } + + // Convert to a multi polygon. + mp := poly.MultiPolygonGeom() + + _ = mp + + for k, f := range fields { + name := f.String() + val := sr.Attribute(k) + log.Printf("info: \t%s = %v\n", name, val) + } + + // TODO: Implement me! + } + + if err := sr.Err(); err != nil { + return nil, err + } + return nil, nil }
--- a/pkg/imports/wkb.go Tue Sep 03 16:27:28 2019 +0200 +++ b/pkg/imports/wkb.go Tue Sep 03 16:54:33 2019 +0200 @@ -55,6 +55,15 @@ return buf.Bytes() } +func (ls lineSlice) LinearRingGeom() wkb.LinearRingGeom { + lr := make(wkb.LinearRingGeom, len(ls)) + for i, v := range ls { + lr[i].X = v[0] + lr[i].Y = v[1] + } + return lr +} + func (p pointSlice) asWKB() []byte { size := 1 + 4 + 2*8 @@ -147,3 +156,27 @@ } return out } + +func (ps polygonSlice) MultiPolygonGeom() wkb.MultiPolygonGeom { + + var mp wkb.MultiPolygonGeom + var curr wkb.PolygonGeom + + for _, r := range ps { + lr := lineSlice(r).LinearRingGeom() + // A counter clockwise ring starts a new polygon. + if lr.CCW() { + if len(curr) > 0 { + mp = append(mp, curr) + curr = wkb.PolygonGeom{} + } + } + curr = append(curr, lr) + } + + if len(curr) > 0 { + mp = append(mp, curr) + } + + return mp +}
--- a/pkg/wkb/data.go Tue Sep 03 16:27:28 2019 +0200 +++ b/pkg/wkb/data.go Tue Sep 03 16:54:33 2019 +0200 @@ -116,3 +116,12 @@ *mpg = polygons return nil } + +func (lr LinearRingGeom) CCW() bool { + var sum float64 + for i, v1 := range lr { + v2 := lr[(i+1)%len(lr)] + sum += (v2.X - v1.X) * (v2.Y + v1.Y) + } + return sum > 0 +}