Mercurial > gemma
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 } |