diff cmd/tin2octree/main.go @ 661:af1d4d44a88a octree

Experimental tin octree indexer.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 18 Sep 2018 00:11:32 +0200
parents
children a3d722e1f593
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/tin2octree/main.go	Tue Sep 18 00:11:32 2018 +0200
@@ -0,0 +1,121 @@
+package main
+
+import (
+	"bufio"
+	"database/sql"
+	"flag"
+	"io"
+	"log"
+	"os"
+	"time"
+
+	"github.com/golang/snappy"
+	"github.com/jackc/pgx"
+	"github.com/jackc/pgx/stdlib"
+)
+
+var (
+	bottleneck = flag.String("bottleneck", "", "bottleneck id")
+	date       = flag.String("date", "", "date info")
+	file       = flag.String("file", "", "save to file")
+
+	snap       = flag.Bool("snappy", false, "use snappy compression")
+	dbhost     = flag.String("dbhost", "localhost", "database host")
+	dbport     = flag.Uint("dbport", 5432, "database port")
+	dbname     = flag.String("dbname", "gemma", "database user")
+	dbuser     = flag.String("dbuser", "scott", "database user")
+	dbpassword = flag.String("dbpw", "tiger", "database password")
+	dbssl      = flag.String("dbssl", "prefer", "database SSL mode")
+)
+
+func run(fn func(*sql.DB) error) error {
+
+	// To ease SSL config ride a bit on parsing.
+	cc, err := pgx.ParseConnectionString("sslmode=" + *dbssl)
+	if err != nil {
+		return err
+	}
+
+	// Do the rest manually to allow whitespace in user/password.
+	cc.Host = *dbhost
+	cc.Port = uint16(*dbport)
+	cc.User = *dbuser
+	cc.Password = *dbpassword
+	cc.Database = *dbname
+
+	db := stdlib.OpenDB(cc)
+	defer db.Close()
+
+	return fn(db)
+}
+
+const tinSQL = `
+SELECT ST_AsBinary(ST_DelaunayTriangles(point_cloud::geometry, 0, 2))
+FROM waterway.sounding_results
+WHERE bottleneck_id = $1 AND date_info = $2
+`
+
+func main() {
+	flag.Parse()
+
+	if *bottleneck == "" || *date == "" {
+		log.Fatalln("missing bottleneck or date option.")
+	}
+
+	dateInfo, err := time.Parse("2006-01-02", *date)
+	if err != nil {
+		log.Fatalf("error: %v\n", err)
+	}
+
+	var t tin
+
+	if err := run(func(db *sql.DB) error {
+		start := time.Now()
+		err := db.QueryRow(tinSQL, *bottleneck, dateInfo).Scan(&t)
+		switch {
+		case err == sql.ErrNoRows:
+			return nil
+		case err != nil:
+			return err
+		}
+		log.Printf("query took: %s\n", time.Since(start))
+		return nil
+	}); err != nil {
+		log.Fatalf("error: %v\n", err)
+	}
+
+	tb := &treeBuilder{t: &t}
+	tb.build()
+
+	if *file != "" {
+		f, err := os.Create(*file)
+		if err != nil {
+			log.Printf("error: %v\n", err)
+		}
+		type flusher interface {
+			io.Writer
+			Flush() error
+		}
+		var out flusher
+		if *snap {
+			out = snappy.NewBufferedWriter(f)
+		} else {
+			out = bufio.NewWriter(f)
+		}
+		if err := t.Serialize(out); err != nil {
+			f.Close()
+			log.Fatalf("error: %v\n", err)
+		}
+		if err := tb.Serialize(out); err != nil {
+			f.Close()
+			log.Fatalf("error: %v\n", err)
+		}
+		if err := out.Flush(); err != nil {
+			f.Close()
+			log.Fatalf("error: %v\n", err)
+		}
+		if err := f.Close(); err != nil {
+			log.Fatalf("error: %v\n", err)
+		}
+	}
+}