view cmd/octree2contour/main.go @ 904:e4b72a199258

New default bottleneck colors Mainly to make the stroke color one actually selectable in the ui. In addition the pink does better match the collors used on the ECDIS layer.
author Sascha Wilde <wilde@intevation.de>
date Tue, 02 Oct 2018 13:34:59 +0200
parents 39b5cf9a6b8f
children 52cb0b82b490
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")
	bottleneck = flag.String("bottleneck", "", "bottleneck id")
	date       = flag.String("date", "", "date info")
)

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()

	if *bottleneck == "" || *date == "" {
		log.Fatalln("missing bottleneck or date option.")
	}

	dateInfo, err := time.Parse("2006-01-02", *date)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	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, *bottleneck, dateInfo); err != nil {
			log.Printf("error: %v\n", err)
		}
		log.Printf("storing took: %v\n", time.Since(start))
	}
}