view pkg/controllers/cross.go @ 676:bd215c4325ce

Cross sections: Only join point in x/y plane.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 19 Sep 2018 16:09:09 +0200
parents 288c496eca26
children bb0788567609
line wrap: on
line source

package controllers

import (
	"database/sql"
	"log"
	"net/http"
	"time"

	"gemma.intevation.de/gemma/pkg/models"
)

const crossSQL = `
WITH line AS (
SELECT ST_3DIntersection(
  ST_Translate(
    ST_Extrude(
      ST_GeomFromWKB($1, 4326),
    0, 0, 1000),
   0, 0, -500),
   geom) AS geom
FROM waterway.meshes m JOIN waterway.sounding_results sr ON m.sounding_result_id = sr.id
WHERE ST_Intersects(geom, ST_GeomFromWKB($1, 4326)) AND
  sr.bottleneck_id = $2 AND sr.date_info = $3
)
SELECT ST_AsBinary((ST_Dump(ST_Intersection(line.geom, sr.area::geometry))).geom)
  FROM line, waterway.sounding_results sr
  WHERE sr.bottleneck_id = $2 AND sr.date_info = $3
`

func crossSection(
	input interface{},
	req *http.Request,
	db *sql.Conn,
) (jr JSONResult, err error) {

	csi := input.(*models.CrossSectionInput)

	start := time.Now()

	var rows *sql.Rows
	if rows, err = db.QueryContext(
		req.Context(),
		crossSQL,
		csi.Geometry.Coordinates.AsWKB(),
		csi.Properties.Bottleneck,
		csi.Properties.Date.Time,
	); err != nil {
		return
	}
	defer rows.Close()

	var segments models.GeoJSONMultiLineCoordinatesZ

	for rows.Next() {
		var segment models.GeoJSONLineCoordinatesZ
		if err = rows.Scan(&segment); err != nil {
			return
		}
		segments = append(segments, segment)
	}

	if err = rows.Err(); err != nil {
		return
	}

	log.Printf("query took: %v\n", time.Since(start))

	start = time.Now()

	joined := segments.Join()

	log.Printf("joining took: %v\n", time.Since(start))
	log.Printf("segments before/after: %d %d\n", len(segments), len(joined))

	/*
		if err2 := dumpProfile(
			csi.Geometry.Coordinates[0],
			csi.Geometry.Coordinates[len(csi.Geometry.Coordinates)-1],
			joined,
		); err2 != nil {
			log.Printf("error: %v\n", err2)
		}
	*/

	jr = JSONResult{
		Result: &models.CrossSectionOutput{
			Type: "Feature",
			Geometry: models.CrossSectionOutputGeometry{
				Type:        "MultiLineString",
				Coordinates: joined,
			},
			Properties: map[string]interface{}{},
		},
	}

	return
}

/*
func dumpProfile(
	start models.GeoJSONCoordinate,
	stop models.GeoJSONCoordinate,
	segments models.GeoJSONMultiLineCoordinatesZ,
) error {

	w, err := os.Create("/tmp/cross.txt")
	if err != nil {
		return err
	}
	defer w.Close()

	begin := models.GeoJSONCoordinateZ{
		Lat: start.Lat,
		Lon: start.Lon,
	}
	end := models.GeoJSONCoordinateZ{
		Lat: stop.Lat,
		Lon: stop.Lon,
	}

	last := begin

	var total float64

	minz := 10000.0

	for _, line := range segments {
		for _, coord := range line {
			if coord.Z < minz {
				minz = coord.Z
			}
			total += last.Distance(coord)
			last = coord
		}
	}

	log.Printf("length: %.3f minz:  %f\n", total, minz)

	var pos float64

	for i, line := range segments {
		for j, coord := range line {
			if i == 0 && j == 0 {
				if !begin.Equals(coord) {
					pos = begin.Distance(coord)
					fmt.Fprintf(w, "%.3f %f\n", 0.0, 200.0)
					fmt.Fprintf(w, "%.3f %f\n", pos-0.0001, 200.0)
					fmt.Fprintf(w, "%.3f %f\n", pos, coord.Z-minz)
					continue
				}
			} else if j == 0 {
				fmt.Fprintf(w, "%.3f %f\n", pos+0.0001, 200.0)
				fmt.Fprintf(w, "%.3f %f\n", pos+last.Distance(coord)-0.0001, 200.0)
				continue
			}
			pos += last.Distance(coord)
			fmt.Fprintf(w, "%.3f %f\n", pos, coord.Z-minz)
			last = coord
		}
	}

	if !last.Equals(end) {
		fmt.Fprintf(w, "%.3f %f\n", pos+0.0001, 200.0)
		fmt.Fprintf(w, "%.3f %f\n", pos+last.Distance(end), 200.0)
	}

	return nil
}
*/