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
+}