view cmd/octree2contour/main.go @ 727:41c8dc61f38f

Moved octree loading stuff to octree package.
author Sascha L. Teichmann <teichmann@intevation.de>
date Sat, 22 Sep 2018 21:57:30 +0200
parents 5af9ab39e715
children 39b5cf9a6b8f
line wrap: on
line source

package main

import (
	"flag"
	"log"
	"runtime"
	"sort"
	"sync"
	"time"

	"gemma.intevation.de/gemma/pkg/octree"
)

var (
	one  = flag.Bool("o", false, "create only a single contour")
	step = flag.Float64("s", 0.5, "step with")
	max  = flag.Float64("m", 10, "max height from lowest point")
)

func processLevels(
	tree *octree.Tree,
	jobs <-chan float64,
	results chan<- result,
	wg *sync.WaitGroup,
) {
	defer wg.Done()
	for h := range jobs {
		var lines octree.MultiLineStringZ
		tree.Horizontal(h, func(t *octree.Triangle) {
			line := t.IntersectHorizontal(h)
			if len(line) > 1 {
				lines = append(lines, line)
			}
		})
		results <- result{h, lines}
	}
}

func process(tree *octree.Tree) []result {

	if *one {
		var lines octree.MultiLineStringZ
		tree.Horizontal(*step, func(t *octree.Triangle) {
			line := t.IntersectHorizontal(*step)
			if len(line) > 0 {
				lines = append(lines, line)
			}
		})
		return []result{{*step, lines}}
	}

	results := make(chan result)
	done := make(chan struct{})

	var all []result
	go func() {
		for {
			select {
			case r := <-results:
				all = append(all, r)
			case <-done:
				return
			}
		}
	}()

	var wg sync.WaitGroup
	jobs := make(chan float64)
	for i, n := 0, runtime.NumCPU(); i < n; i++ {
		wg.Add(1)
		go processLevels(tree, jobs, results, &wg)
	}
	for h := tree.Min.Z; h <= tree.Max.Z; h += *step {
		jobs <- h
	}
	close(jobs)
	wg.Wait()
	done <- struct{}{}

	sort.Slice(all, func(i, j int) bool {
		return all[i].h < all[j].h
	})

	return all
}

func main() {
	flag.Parse()

	for _, fname := range flag.Args() {
		log.Printf("processing %s\n", fname)
		start := time.Now()
		tree, err := octree.LoadTree(fname)
		if err != nil {
			log.Printf("error: %v\n", err)
			continue
		}
		log.Printf("loading took: %v\n", time.Since(start))
		start = time.Now()
		all := process(tree)
		log.Printf("processing took: %v\n", time.Since(start))
		start = time.Now()
		if err = store(all, tree.EPSG); err != nil {
			log.Printf("error: %v\n", err)
		}
		log.Printf("storing took: %v\n", time.Since(start))
	}
}