comparison pkg/octree/contours.go @ 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
children 4a2ca0e20006
comparison
equal deleted inserted replaced
975:3da707172772 976:c397fdd8c327
1 package octree
2
3 import (
4 "database/sql"
5 "runtime"
6 "sync"
7 )
8
9 const (
10 contourStepWidth = 0.5
11 contourTolerance = 0.1
12 )
13
14 type contourResult struct {
15 height float64
16 lines MultiLineStringZ
17 }
18
19 const (
20 insertContourSQL = `
21 INSERT INTO waterway.sounding_results_contour_lines (
22 sounding_result_id,
23 height,
24 lines
25 )
26 SELECT
27 $1,
28 $2,
29 ST_Transform(
30 ST_Multi(
31 ST_CollectionExtract(
32 ST_Intersection(
33 ST_Transform(sr.area::geometry, $3::integer),
34 ST_SimplifyPreserveTopology(
35 ST_GeomFromWKB($4, $3::integer),
36 $5
37 )
38 ),
39 2
40 )
41 ),
42 4326
43 )
44 FROM waterway.sounding_results sr
45 WHERE id = $1
46 `
47 )
48
49 func generateContours(tree *Tree, tx *sql.Tx, id int64) error {
50 stmt, err := tx.Prepare(insertContourSQL)
51 if err != nil {
52 return err
53 }
54 defer stmt.Close()
55
56 doContours(tree, contourStepWidth, func(res *contourResult) {
57 if err == nil {
58 _, err = stmt.Exec(
59 id, res.height, tree.EPSG,
60 res.lines.AsWKB2D(),
61 contourTolerance)
62 }
63 })
64
65 return err
66 }
67
68 func doContours(tree *Tree, step float64, store func(*contourResult)) {
69
70 results := make(chan *contourResult)
71 done := make(chan struct{})
72 jobs := make(chan float64)
73
74 go func() {
75 for {
76 select {
77 case r := <-results:
78 store(r)
79 case <-done:
80 return
81 }
82 }
83 }()
84
85 var wg sync.WaitGroup
86 for i, n := 0, runtime.NumCPU(); i < n; i++ {
87 wg.Add(1)
88 go processLevels(tree, jobs, results, &wg)
89 }
90 for h := tree.Min.Z; h <= tree.Max.Z; h += step {
91 jobs <- h
92 }
93 close(jobs)
94 wg.Wait()
95 done <- struct{}{}
96 }
97
98 func processLevels(
99 tree *Tree,
100 jobs <-chan float64,
101 results chan<- *contourResult,
102 wg *sync.WaitGroup,
103 ) {
104 defer wg.Done()
105 for h := range jobs {
106 var lines MultiLineStringZ
107 tree.Horizontal(h, func(t *Triangle) {
108 line := t.IntersectHorizontal(h)
109 if len(line) > 1 {
110 lines = append(lines, line)
111 }
112 })
113 lines = lines.Merge()
114 results <- &contourResult{h, lines}
115 }
116 }