Mercurial > gemma
changeset 1134:0420761c1c3f
Store contour lines in deterministic order.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 07 Nov 2018 21:45:10 +0100 |
parents | dd4071019676 |
children | 19a04b150b6c |
files | pkg/octree/contours.go |
diffstat | 1 files changed, 56 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/pkg/octree/contours.go Wed Nov 07 18:13:02 2018 +0100 +++ b/pkg/octree/contours.go Wed Nov 07 21:45:10 2018 +0100 @@ -21,54 +21,88 @@ type ContourResult struct { Height float64 Lines MultiLineStringZ + + done bool + mu sync.Mutex + cond *sync.Cond +} + +func NewContorResult(height float64) *ContourResult { + cr := ContourResult{Height: height} + cr.cond = sync.NewCond(&cr.mu) + return &cr +} + +func (cr *ContourResult) wait() { + cr.cond.L.Lock() + for !cr.done { + cr.cond.Wait() + } + cr.cond.L.Unlock() +} + +func (cr *ContourResult) get() float64 { + cr.cond.L.Lock() + defer cr.cond.L.Unlock() + return cr.Height +} + +func (cr *ContourResult) set(lines MultiLineStringZ) { + cr.cond.L.Lock() + defer cr.cond.L.Unlock() + cr.Lines = lines + cr.done = true + cr.cond.Signal() } func DoContours(tree *Tree, step float64, store func(*ContourResult)) { - results := make(chan *ContourResult) - done := make(chan struct{}) - jobs := make(chan float64) + var contours []*ContourResult + for h := tree.Min.Z; h <= tree.Max.Z; h += step { + contours = append(contours, NewContorResult(h)) + } - go func() { - for { - select { - case r := <-results: - store(r) - case <-done: - return - } - } - }() + jobs := make(chan *ContourResult) var wg sync.WaitGroup for i, n := 0, runtime.NumCPU(); i < n; i++ { wg.Add(1) - go processLevels(tree, jobs, results, &wg) + go processLevels(tree, jobs, &wg) } - for h := tree.Min.Z; h <= tree.Max.Z; h += step { - jobs <- h + + done := make(chan struct{}) + go func() { + defer close(done) + for _, cr := range contours { + cr.wait() + store(cr) + } + }() + + for _, cr := range contours { + jobs <- cr } close(jobs) + wg.Wait() - done <- struct{}{} + <-done } func processLevels( tree *Tree, - jobs <-chan float64, - results chan<- *ContourResult, + jobs <-chan *ContourResult, wg *sync.WaitGroup, ) { defer wg.Done() - for h := range jobs { + for cr := range jobs { var lines MultiLineStringZ + h := cr.get() tree.Horizontal(h, func(t *Triangle) { line := t.IntersectHorizontal(h) if len(line) > 1 { lines = append(lines, line) } }) - lines = lines.Merge() - results <- &ContourResult{h, lines} + cr.set(lines.Merge()) } }