Mercurial > gemma
view pkg/octree/areas.go @ 4570:4b3a298b94f8 iso-areas
Moved area tracing to octree package.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 06 Oct 2019 11:12:32 +0200 |
parents | |
children | 6415368c2c60 |
line wrap: on
line source
// This is Free Software under GNU Affero General Public License v >= 3.0 // without warranty, see README.md and license for details. // // SPDX-License-Identifier: AGPL-3.0-or-later // License-Filename: LICENSES/AGPL-3.0.txt // // Copyright (C) 2018 by via donau // – Österreichische Wasserstraßen-Gesellschaft mbH // Software engineering by Intevation GmbH // // Author(s): // * Sascha L. Teichmann <sascha.teichmann@intevation.de> package octree import ( "log" "math" "runtime" "sync" "time" "github.com/fogleman/contourmap" "gemma.intevation.de/gemma/pkg/common" "gemma.intevation.de/gemma/pkg/wkb" ) func (tree *Tree) TraceAreas( heights []float64, cellSize float64, ) []wkb.MultiPolygonGeom { min, max := tree.Min, tree.Max width := max.X - min.X height := max.Y - min.Y log.Printf("info: Width/Height: %.2f / %.2f\n", width, height) xcells := int(math.Ceil(width / cellSize)) ycells := int(math.Ceil(height / cellSize)) log.Printf("info: Raster size: (%d, %d)\n", xcells, ycells) start := time.Now() // Add border for closing raster := make([]float64, (xcells+2)*(ycells+2)) // prefill for no data const nodata = -math.MaxFloat64 for i := range raster { raster[i] = nodata } // rasterize the height model var wg sync.WaitGroup rows := make(chan int) rasterRow := func() { defer wg.Done() for i := range rows { pos := (i+1)*(xcells+2) + 1 row := raster[pos : pos+xcells] py := min.Y + float64(i)*cellSize + cellSize/2 px := min.X + cellSize/2 for j := range row { v, ok := tree.Value(px, py) if ok { row[j] = v } px += cellSize } } } for n := runtime.NumCPU(); n >= 1; n-- { wg.Add(1) go rasterRow() } for i := 0; i < ycells; i++ { rows <- i } close(rows) wg.Wait() log.Printf("info: Rastering took %v\n", time.Since(start)) start = time.Now() tracer := contourmap.FromFloat64s(xcells+2, ycells+2, raster) areas := make([]wkb.MultiPolygonGeom, len(heights)) // TODO: Check if this correct! reprojX := common.Linear(1, min.X, float64(xcells+1), max.X) reprojY := common.Linear(1, min.Y, float64(ycells+1), max.Y) cnts := make(chan int) doContours := func() { defer wg.Done() for hIdx := range cnts { c := tracer.Contours(heights[hIdx]) if len(c) == 0 { continue } // We need to bring it back to the // none raster coordinate system. a := make(wkb.MultiPolygonGeom, len(c)) for i, pl := range c { shell := make(wkb.LinearRingGeom, len(pl)) for j, pt := range pl { shell[j] = wkb.PointGeom{ X: reprojX(pt.X), Y: reprojY(pt.Y), } } a[i] = wkb.PolygonGeom{shell} } areas[hIdx] = a } } for n := runtime.NumCPU(); n >= 1; n-- { wg.Add(1) go doContours() } for i := range heights { cnts <- i } close(cnts) wg.Wait() log.Printf("info: Tracing areas took %v\n", time.Since(start)) return areas }