changeset 971:f9fb6c399f3f

Moved generating of tins to octree package.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 18 Oct 2018 11:52:13 +0200
parents 166782ebab96
children 17a03a84b0e8
files cmd/tin2octree/main.go pkg/imports/sr.go pkg/octree/tin.go
diffstat 3 files changed, 101 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/cmd/tin2octree/main.go	Thu Oct 18 10:14:46 2018 +0200
+++ b/cmd/tin2octree/main.go	Thu Oct 18 11:52:13 2018 +0200
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"context"
 	"crypto/sha1"
 	"database/sql"
 	"encoding/base64"
@@ -54,23 +55,6 @@
 }
 
 const (
-	tinUTMSQL = `
-WITH trans AS (
-  SELECT
-	ST_Buffer(ST_Transform(area::geometry, $3::int), 0.001) AS area,
-	ST_Transform(point_cloud::geometry, $3::int) AS point_cloud
-  FROM waterway.sounding_results
-  WHERE bottleneck_id = $1 AND date_info = $2
-),
-triangles AS (
-  SELECT t.geom AS geom, ST_MakePolygon(ST_ExteriorRing(t.geom)) AS poly FROM (
-    SELECT (st_dump(
-      ST_DelaunayTriangles(point_cloud, 0, 2))).geom
-    FROM trans) t
-)
-SELECT ST_AsBinary(ST_Collect(triangles.geom)) FROM triangles, trans
-WHERE st_covers(trans.area, triangles.poly)`
-
 	centroidSQL = `
 SELECT ST_X(ST_Centroid(point_cloud::geometry)), ST_Y(ST_Centroid(point_cloud::geometry))
 FROM waterway.sounding_results
@@ -78,14 +62,14 @@
 `
 )
 
-func utmZone(x, y float64) int {
-	var pref int
+func utmZone(x, y float64) uint32 {
+	var pref uint32
 	if y > 0 {
 		pref = 32600
 	} else {
 		pref = 32700
 	}
-	zone := int(math.Floor((x+180)/6)) + 1
+	zone := uint32(math.Floor((x+180)/6)) + 1
 	return zone + pref
 }
 
@@ -101,13 +85,21 @@
 		log.Fatalf("error: %v\n", err)
 	}
 
-	var t octree.Tin
+	var t *octree.Tin
+
+	ctx := context.Background()
 
 	if err := run(func(db *sql.DB) error {
-		var utmZ int
+		conn, err := db.Conn(ctx)
+		if err != nil {
+			return err
+		}
+		defer conn.Close()
 
+		var utmZ uint32
 		var cx, cy float64
-		err := db.QueryRow(centroidSQL, *bottleneck, dateInfo).Scan(&cx, &cy)
+
+		conn.QueryRowContext(ctx, centroidSQL, *bottleneck, dateInfo).Scan(&cx, &cy)
 		switch {
 		case err == sql.ErrNoRows:
 			return nil
@@ -119,23 +111,19 @@
 		log.Printf("UTM zone: %d\n", utmZ)
 
 		start := time.Now()
-		err = db.QueryRow(tinUTMSQL, *bottleneck, dateInfo, utmZ).Scan(&t)
-		switch {
-		case err == sql.ErrNoRows:
-			return nil
-		case err != nil:
-			return err
-		}
+		t, err = octree.GenerateTin(conn, ctx, *bottleneck, dateInfo, utmZ)
 		log.Printf("query took: %s\n", time.Since(start))
-
-		t.EPSG = uint32(utmZ)
-
-		return nil
+		return err
 	}); err != nil {
 		log.Fatalf("error: %v\n", err)
 	}
 
-	tb := octree.NewBuilder(&t)
+	if t == nil {
+		log.Fatalf("error: No such sounding result (%s, %s)\n",
+			*bottleneck, dateInfo)
+	}
+
+	tb := octree.NewBuilder(t)
 	tb.Build()
 
 	if *insert {
--- a/pkg/imports/sr.go	Thu Oct 18 10:14:46 2018 +0200
+++ b/pkg/imports/sr.go	Thu Oct 18 11:52:13 2018 +0200
@@ -75,7 +75,13 @@
     ST_Transform(ST_GeomFromWKB($5, $6::integer), 4326)::geography
   END)
 )
-RETURNING id`
+RETURNING
+  id,
+  CASE WHEN ST_Y(ST_Centroid(point_cloud::geometry)) > 0 THEN
+    32600
+  ELSE
+    32700
+  END + floor((ST_X(ST_Centroid(point_cloud::geometry))+180)/6)::int + 1`
 )
 
 func (srd *SoundingResultDate) UnmarshalJSON(data []byte) error {
@@ -308,19 +314,21 @@
 	defer tx.Rollback()
 
 	var id int64
+	var epsg uint32
 
-	err = tx.QueryRow(insertPointsSQL,
+	if err := tx.QueryRow(insertPointsSQL,
 		m.Bottleneck,
 		m.Date.Time,
 		m.DepthReference,
 		xyz.AsWKB(),
 		polygon.AsWBK(),
-		m.EPSG).Scan(&id)
-
-	if err != nil {
+		m.EPSG,
+	).Scan(&id, &epsg); err != nil {
 		return err
 	}
 
+	log.Printf("EPSG: %d\n", epsg)
+
 	// TODO: Build octree
 	// TODO: Generate iso-lines
 
--- a/pkg/octree/tin.go	Thu Oct 18 10:14:46 2018 +0200
+++ b/pkg/octree/tin.go	Thu Oct 18 11:52:13 2018 +0200
@@ -2,12 +2,15 @@
 
 import (
 	"bytes"
+	"context"
+	"database/sql"
 	"encoding/binary"
 	"errors"
 	"fmt"
 	"io"
 	"log"
 	"math"
+	"time"
 )
 
 var (
@@ -165,8 +168,69 @@
 	return nil
 }
 
+const (
+	tinSQLPrefix = `WITH trans AS (
+  SELECT
+	ST_Buffer(ST_Transform(area::geometry, $1::int), 0.001) AS area,
+	ST_Transform(point_cloud::geometry, $1::int) AS point_cloud
+  FROM waterway.sounding_results
+`
+	tinSQLSuffix = `
+),
+triangles AS (
+  SELECT t.geom AS geom, ST_MakePolygon(ST_ExteriorRing(t.geom)) AS poly FROM (
+    SELECT (ST_Dump(
+      ST_DelaunayTriangles(point_cloud, 0, 2))).geom
+    FROM trans) t
+)
+SELECT ST_AsBinary(ST_Collect(triangles.geom)) FROM triangles, trans
+WHERE ST_Covers(trans.area, triangles.poly)`
+
+	loadTinSQL     = tinSQLPrefix + `WHERE bottleneck_id = $2 AND date_info = $3` + tinSQLSuffix
+	loadTinByIDSQL = tinSQLPrefix + `WHERE id = $2` + tinSQLSuffix
+)
+
+func GenerateTin(
+	conn *sql.Conn,
+	ctx context.Context,
+	bottleneck string,
+	date time.Time,
+	epsg uint32,
+) (*Tin, error) {
+	var tin Tin
+	err := conn.QueryRowContext(ctx, loadTinSQL, epsg, bottleneck, date).Scan(&tin)
+	switch {
+	case err == sql.ErrNoRows:
+		return nil, nil
+	case err != nil:
+		return nil, err
+	}
+	tin.EPSG = epsg
+	return &tin, nil
+}
+
+func GenerateTinByID(
+	conn *sql.Conn,
+	ctx context.Context,
+	id int64,
+	epsg uint32,
+) (*Tin, error) {
+	var tin Tin
+	err := conn.QueryRowContext(ctx, loadTinByIDSQL, epsg, id).Scan(&tin)
+	switch {
+	case err == sql.ErrNoRows:
+		return nil, nil
+	case err != nil:
+		return nil, err
+	}
+	tin.EPSG = epsg
+	return &tin, nil
+}
+
 func (t *Tin) Scan(raw interface{}) error {
-
+	if raw == nil {
+		return nil
+	}
 	data, ok := raw.([]byte)
 	if !ok {
 		return errNoByteSlice