Mercurial > gemma
diff pkg/controllers/cross.go @ 801:b6a1779ffb42
Removed old cross section controller.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Thu, 27 Sep 2018 13:18:50 +0200 |
parents | pkg/controllers/octreecross.go@0cc97135717c |
children | e10a8a682297 |
line wrap: on
line diff
--- a/pkg/controllers/cross.go Thu Sep 27 12:49:45 2018 +0200 +++ b/pkg/controllers/cross.go Thu Sep 27 13:18:50 2018 +0200 @@ -1,86 +1,141 @@ package controllers import ( + "context" "database/sql" "log" "net/http" "time" "gemma.intevation.de/gemma/pkg/models" + "gemma.intevation.de/gemma/pkg/octree" ) -const crossSQL = ` -WITH line AS ( -SELECT ST_LineMerge(ST_Union(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 -` +const WGS84 = 4326 + +func reproject( + rp *models.Reprojector, + src models.GeoJSONLineCoordinates, + ctx context.Context, +) (models.GeoJSONLineCoordinates, error) { + + dst := make(models.GeoJSONLineCoordinates, len(src)) + for i, s := range src { + var err error + if dst[i].Lat, dst[i].Lon, err = rp.Reproject( + s.Lat, s.Lon, ctx, + ); err != nil { + return nil, err + } + } + return dst, nil +} + +func projectBack( + rp *models.Reprojector, + lines octree.MultiLineStringZ, + ctx context.Context, +) (models.GeoJSONMultiLineCoordinatesZ, error) { + + out := make(models.GeoJSONMultiLineCoordinatesZ, len(lines)) + + for i, segment := range lines { + + coords := make(models.GeoJSONLineCoordinatesZ, len(segment)) + out[i] = coords + for j, v := range segment { + lat, lon, err := rp.Reproject(v.X, v.Y, ctx) + if err != nil { + return nil, err + } + coords[j] = models.GeoJSONCoordinateZ{Lat: lat, Lon: lon, Z: v.Z} + } + } + return out, nil +} func crossSection( input interface{}, req *http.Request, - db *sql.Conn, + conn *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, + tree, err := octree.Cache.Get( + csi.Properties.Bottleneck, csi.Properties.Date.Time, + conn, req.Context()) + + log.Printf("loading octree took: %s\n", time.Since(start)) + if err != nil { + return + } + + // The coordinate system of the octree is an UTM projection. + // The input coordinates are in WGS84. + // So we need to reproject them. + + start = time.Now() + + var rp *models.Reprojector + if rp, err = models.NewReprojector( + conn, req.Context(), + WGS84, tree.EPSG, ); err != nil { return } - defer rows.Close() - - var segments models.GeoJSONMultiLineCoordinatesZ + defer rp.Close() - for rows.Next() { - var segment models.GeoJSONLineCoordinatesZ - if err = rows.Scan(&segment); err != nil { - return - } - segments = append(segments, segment) - } + coords, err := reproject(rp, csi.Geometry.Coordinates, req.Context()) - if err = rows.Err(); err != nil { + log.Printf("transforming input coords took: %s\n", time.Since(start)) + if err != nil { return } - log.Printf("query took: %v\n", time.Since(start)) - start = time.Now() - joined := segments.Join() + var segments octree.MultiLineStringZ + + for i := 0; i < len(coords)-1; i++ { + c1 := &coords[i] + c2 := &coords[i+1] - log.Printf("joining took: %v\n", time.Since(start)) - log.Printf("segments before/after: %d %d\n", len(segments), len(joined)) + verticalLine := octree.NewVerticalLine(c1.Lat, c1.Lon, c2.Lat, c2.Lon) + + var line octree.MultiLineStringZ + tree.Vertical(c1.Lat, c1.Lon, c2.Lat, c2.Lon, func(t *octree.Triangle) { + if ls := verticalLine.Intersection(t); len(ls) > 0 { + line = append(line, ls) + } + }) - /* - if err2 := dumpProfile( - csi.Geometry.Coordinates[0], - csi.Geometry.Coordinates[len(csi.Geometry.Coordinates)-1], - joined, - ); err2 != nil { - log.Printf("error: %v\n", err2) + if len(line) > 0 { + log.Printf("line length: %d\n", len(line)) + // They are all on the segment (c1.Lat, c1.Lon) - (c2.Lat, c2.Lon). + // Sort them by project them on this line. + joined := line.JoinOnLine(c1.Lat, c1.Lon, c2.Lat, c2.Lon) + log.Printf("joined length: %d\n", len(joined)) + segments = append(segments, joined...) } - */ + + } + log.Printf("octree traversal took: %s\n", time.Since(start)) + + // The result have to be WGS84. So project the result back. + start = time.Now() + + rp.FromEPSG, rp.ToEPSG = tree.EPSG, WGS84 + + var joined models.GeoJSONMultiLineCoordinatesZ + joined, err = projectBack(rp, segments, req.Context()) + + log.Printf("projecting back took: %s\n", time.Since(start)) + if err != nil { + return + } jr = JSONResult{ Result: &models.CrossSectionOutput{ @@ -95,75 +150,3 @@ 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 -} -*/