Mercurial > gemma
view pkg/controllers/octreecross.go @ 790:1b82ae5e637e
client: add bottleneck layer with first styling
author | Bernhard Reiter <bernhard@intevation.de> |
---|---|
date | Thu, 27 Sep 2018 08:52:17 +0200 |
parents | 3d927e06b92c |
children | 0cc97135717c |
line wrap: on
line source
package controllers import ( "context" "database/sql" "log" "net/http" "time" "gemma.intevation.de/gemma/pkg/models" "gemma.intevation.de/gemma/pkg/octree" ) 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 octreeCrossSection( input interface{}, req *http.Request, conn *sql.Conn, ) (jr JSONResult, err error) { csi := input.(*models.CrossSectionInput) start := time.Now() 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 rp.Close() coords, err := reproject(rp, csi.Geometry.Coordinates, req.Context()) log.Printf("transforming input coords took: %s\n", time.Since(start)) if err != nil { return } start = time.Now() var segments octree.MultiLineStringZ for i := 0; i < len(coords)-1; i++ { c1 := &coords[i] c2 := &coords[i+1] 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) } }) if len(line) > 0 { // They are all on the segment (c1.Lat, c1.Lon) - (c2.Lat, c2.Lon). // Sort them by project them on this line. segments = append(segments, line.JoinOnLine(c1.Lat, c1.Lon, c2.Lat, c2.Lon)...) } } 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{ Type: "Feature", Geometry: models.CrossSectionOutputGeometry{ Type: "MultiLineString", Coordinates: joined, }, Properties: map[string]interface{}{}, }, } return }