Mercurial > gemma
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/octree/slice.go Mon Mar 11 14:00:49 2019 +0100 @@ -0,0 +1,105 @@ +// 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, 2019 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 ( + "runtime" + "sync" +) + +type PointMap map[Point]float64 + +func (pm PointMap) Triangulate() (*Triangulation, error) { + vertices := make([]Vertex, len(pm)) + var i int + for p, z := range pm { + vertices[i] = Vertex{X: p.X, Y: p.Y, Z: z} + i++ + } + return Triangulate(vertices) +} + +func sliceWork( + vs []Vertex, + dst PointMap, + fn func([]Vertex, func([]Vertex) []Vertex), +) { + n := runtime.NumCPU() + + wg := new(sync.WaitGroup) + + slices := make(chan []Vertex) + out := make(chan []Vertex) + + pool := make(chan []Vertex, n) + + const pageSize = 2048 + + turn := func(p []Vertex) []Vertex { + if p != nil { + out <- p + } + select { + case p = <-pool: + default: + p = make([]Vertex, 0, pageSize) + } + return p + } + + for i := 0; i < n; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for slice := range slices { + fn(slice, turn) + } + }() + } + done := make(chan struct{}) + go func() { + defer close(done) + for s := range out { + for i := range s { + v := &s[i] + key := Point{X: v.X, Y: v.Y} + if z, found := dst[key]; found { + dst[key] = (z + v.Z) * 0.5 + } else { + dst[key] = v.Z + } + } + select { + case pool <- s[:0:pageSize]: + default: + } + } + }() + + size := len(vs)/n + 1 + for len(vs) > 0 { + var l int + if len(vs) < size { + l = len(vs) + } else { + l = size + } + slices <- vs[:l] + vs = vs[l:] + } + close(slices) + wg.Wait() + close(out) + <-done +}