view pkg/octree/slice.go @ 4642:b5d9647c5bc1 stree-experiment

Fixed construction of clipped STRTree.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 11 Oct 2019 23:36:28 +0200
parents 7686c7c23506
children
line wrap: on
line source

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