view cmd/octree2contour/main.go @ 942:912d016275ee

client: add arrow to drawn linesegment * Add styling function that will place an icon png image at the end of each drawn line segment, in the right rotation. Note that this does not look perfectly centered, see comment in the code.
author Bernhard Reiter <bernhard@intevation.de>
date Tue, 09 Oct 2018 18:39:01 +0200
parents ae1531e00344
children
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 width")
	tol        = flag.Float64("t", 0.1, "tolerance for simplification")
	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)
			}
		})
		lines = lines.Merge()
		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)
			}
		})
		lines = lines.Merge()
		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, *tol); err != nil {
			log.Printf("error: %v\n", err)
		}
		log.Printf("storing took: %v\n", time.Since(start))
	}
}