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
+}