comparison pkg/octree/slice.go @ 2572:7686c7c23506

Morphological differences: Moved some code into octree package.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 11 Mar 2019 14:00:49 +0100
parents
children
comparison
equal deleted inserted replaced
2571:eec11d3d74f9 2572:7686c7c23506
1 // This is Free Software under GNU Affero General Public License v >= 3.0
2 // without warranty, see README.md and license for details.
3 //
4 // SPDX-License-Identifier: AGPL-3.0-or-later
5 // License-Filename: LICENSES/AGPL-3.0.txt
6 //
7 // Copyright (C) 2018, 2019 by via donau
8 // – Österreichische Wasserstraßen-Gesellschaft mbH
9 // Software engineering by Intevation GmbH
10 //
11 // Author(s):
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de>
13
14 package octree
15
16 import (
17 "runtime"
18 "sync"
19 )
20
21 type PointMap map[Point]float64
22
23 func (pm PointMap) Triangulate() (*Triangulation, error) {
24 vertices := make([]Vertex, len(pm))
25 var i int
26 for p, z := range pm {
27 vertices[i] = Vertex{X: p.X, Y: p.Y, Z: z}
28 i++
29 }
30 return Triangulate(vertices)
31 }
32
33 func sliceWork(
34 vs []Vertex,
35 dst PointMap,
36 fn func([]Vertex, func([]Vertex) []Vertex),
37 ) {
38 n := runtime.NumCPU()
39
40 wg := new(sync.WaitGroup)
41
42 slices := make(chan []Vertex)
43 out := make(chan []Vertex)
44
45 pool := make(chan []Vertex, n)
46
47 const pageSize = 2048
48
49 turn := func(p []Vertex) []Vertex {
50 if p != nil {
51 out <- p
52 }
53 select {
54 case p = <-pool:
55 default:
56 p = make([]Vertex, 0, pageSize)
57 }
58 return p
59 }
60
61 for i := 0; i < n; i++ {
62 wg.Add(1)
63 go func() {
64 defer wg.Done()
65 for slice := range slices {
66 fn(slice, turn)
67 }
68 }()
69 }
70 done := make(chan struct{})
71 go func() {
72 defer close(done)
73 for s := range out {
74 for i := range s {
75 v := &s[i]
76 key := Point{X: v.X, Y: v.Y}
77 if z, found := dst[key]; found {
78 dst[key] = (z + v.Z) * 0.5
79 } else {
80 dst[key] = v.Z
81 }
82 }
83 select {
84 case pool <- s[:0:pageSize]:
85 default:
86 }
87 }
88 }()
89
90 size := len(vs)/n + 1
91 for len(vs) > 0 {
92 var l int
93 if len(vs) < size {
94 l = len(vs)
95 } else {
96 l = size
97 }
98 slices <- vs[:l]
99 vs = vs[l:]
100 }
101 close(slices)
102 wg.Wait()
103 close(out)
104 <-done
105 }