Mercurial > gemma
changeset 976:c397fdd8c327
Generate the contour lines of the sounding result during the import, too.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Thu, 18 Oct 2018 17:05:54 +0200 |
parents | 3da707172772 |
children | 4a2ca0e20006 |
files | pkg/imports/sr.go pkg/octree/contours.go |
diffstat | 2 files changed, 123 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/pkg/imports/sr.go Thu Oct 18 16:47:17 2018 +0200 +++ b/pkg/imports/sr.go Thu Oct 18 17:05:54 2018 +0200 @@ -342,12 +342,15 @@ return err } - index := builder.Tree() + tree := builder.Tree() builder = nil // not needed from now on - // TODO: Generate iso-lines - - _ = index + start = time.Now() + err = generateContours(tree, tx, id) + log.Printf("generating and storing contour lines took %s\n", time.Since(start)) + if err != nil { + return err + } return tx.Commit() }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/octree/contours.go Thu Oct 18 17:05:54 2018 +0200 @@ -0,0 +1,116 @@ +package octree + +import ( + "database/sql" + "runtime" + "sync" +) + +const ( + contourStepWidth = 0.5 + contourTolerance = 0.1 +) + +type contourResult struct { + height float64 + lines MultiLineStringZ +} + +const ( + insertContourSQL = ` +INSERT INTO waterway.sounding_results_contour_lines ( + sounding_result_id, + height, + lines +) +SELECT + $1, + $2, + ST_Transform( + ST_Multi( + ST_CollectionExtract( + ST_Intersection( + ST_Transform(sr.area::geometry, $3::integer), + ST_SimplifyPreserveTopology( + ST_GeomFromWKB($4, $3::integer), + $5 + ) + ), + 2 + ) + ), + 4326 + ) +FROM waterway.sounding_results sr +WHERE id = $1 +` +) + +func generateContours(tree *Tree, tx *sql.Tx, id int64) error { + stmt, err := tx.Prepare(insertContourSQL) + if err != nil { + return err + } + defer stmt.Close() + + doContours(tree, contourStepWidth, func(res *contourResult) { + if err == nil { + _, err = stmt.Exec( + id, res.height, tree.EPSG, + res.lines.AsWKB2D(), + contourTolerance) + } + }) + + return err +} + +func doContours(tree *Tree, step float64, store func(*contourResult)) { + + results := make(chan *contourResult) + done := make(chan struct{}) + jobs := make(chan float64) + + go func() { + for { + select { + case r := <-results: + store(r) + case <-done: + return + } + } + }() + + var wg sync.WaitGroup + for i, n := 0, runtime.NumCPU(); i < n; i++ { + wg.Add(1) + go processLevels(tree, jobs, results, &wg) + } + for h := tree.Min.Z; h <= tree.Max.Z; h += step { + jobs <- h + } + close(jobs) + wg.Wait() + done <- struct{}{} +} + +func processLevels( + tree *Tree, + jobs <-chan float64, + results chan<- *contourResult, + wg *sync.WaitGroup, +) { + defer wg.Done() + for h := range jobs { + var lines MultiLineStringZ + tree.Horizontal(h, func(t *Triangle) { + line := t.IntersectHorizontal(h) + if len(line) > 1 { + lines = append(lines, line) + } + }) + lines = lines.Merge() + results <- &contourResult{h, lines} + } +}