changeset 3882:37d5c4441c70

Use custom morpho class breaks in sounding result contour generation.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 10 Jul 2019 11:45:55 +0200
parents 7db6999962db
children 0b382767b5ab
files pkg/imports/sr.go pkg/octree/classbreaks.go
diffstat 2 files changed, 64 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/imports/sr.go	Wed Jul 10 09:47:02 2019 +0200
+++ b/pkg/imports/sr.go	Wed Jul 10 11:45:55 2019 +0200
@@ -614,7 +614,7 @@
 	feedback.Info("Generate contour lines")
 
 	start = time.Now()
-	err = generateContours(ctx, tx, builder.Tree(), id)
+	err = generateContours(ctx, tx, feedback, builder.Tree(), id)
 	if err != nil {
 		return nil, err
 	}
@@ -817,6 +817,7 @@
 func generateContours(
 	ctx context.Context,
 	tx *sql.Tx,
+	feedback Feedback,
 	tree *octree.Tree,
 	id int64,
 ) error {
@@ -826,13 +827,30 @@
 	}
 	defer stmt.Close()
 
-	// Adjust contour lines heights to multiples of contourStepWidth
-	var heights []float64
-	h := contourStepWidth * math.Ceil(tree.Min.Z/contourStepWidth)
-	for ; h <= tree.Max.Z; h += contourStepWidth {
-		heights = append(heights, h)
+	heights, err := octree.LoadClassBreaks(
+		ctx, tx,
+		"morphology_classbreaks",
+	)
+	if err != nil {
+		feedback.Warn("Loading class breaks failed: %v", err)
+		feedback.Info("Using default class breaks")
+		heights = nil
+		h := contourStepWidth * math.Ceil(tree.Min.Z/contourStepWidth)
+		for ; h <= tree.Max.Z; h += contourStepWidth {
+			heights = append(heights, h)
+		}
+	} else {
+		heights = octree.ExtrapolateClassBreaks(heights, tree.Min.Z, tree.Max.Z)
+		heights = octree.InBetweenClassBreaks(heights, 0.05, 2)
 	}
 
+	/*
+		for i, v := range heights {
+			fmt.Printf("%d %.2f\n", i, v)
+		}
+		log.Printf("%.2f - %.2f\n", tree.Min.Z, tree.Max.Z)
+	*/
+
 	octree.DoContours(tree, heights, func(res *octree.ContourResult) {
 		if err == nil && len(res.Lines) > 0 {
 			_, err = stmt.ExecContext(
--- a/pkg/octree/classbreaks.go	Wed Jul 10 09:47:02 2019 +0200
+++ b/pkg/octree/classbreaks.go	Wed Jul 10 11:45:55 2019 +0200
@@ -77,7 +77,7 @@
 	classes := make([]float64, 0, len(parts))
 	for _, part := range parts {
 		if idx := strings.IndexRune(part, ':'); idx >= 0 {
-			part = part[idx+1:]
+			part = part[:idx]
 		}
 		if part = strings.TrimSpace(part); part == "" {
 			continue
@@ -93,6 +93,45 @@
 	return classes, nil
 }
 
+func ExtrapolateClassBreaks(cbs []float64, min, max float64) []float64 {
+	if min > max {
+		min, max = max, min
+	}
+
+	if len(cbs) < 2 {
+		return cbs
+	}
+
+	if min >= cbs[0] && max <= cbs[len(cbs)-1] {
+		return cbs
+	}
+
+	n := make([]float64, len(cbs))
+	copy(n, cbs)
+	sort.Float64s(n)
+
+	for min < n[0] {
+		diff := n[1] - n[0]
+		if diff == 0 {
+			break
+		}
+		m := make([]float64, len(n)+1)
+		m[0] = n[0] - diff
+		copy(m[1:], n)
+		n = m
+	}
+
+	for max > n[len(n)-1] {
+		diff := n[len(n)-1] - n[len(n)-2]
+		if diff == 0 {
+			break
+		}
+		n = append(n, n[len(n)-1]+diff)
+	}
+
+	return n
+}
+
 func InBetweenClassBreaks(cbs []float64, min float64, steps int) []float64 {
 	if len(cbs) < 2 || steps < 2 {
 		return cbs