changeset 3829:c1be6beafb54 sld-colors

Merged default into sld-colors branch.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 04 Jul 2019 10:37:42 +0200
parents 885eb90255ff (current diff) 6521c962a7b6 (diff)
children 464a6a6e05e6
files
diffstat 9 files changed, 474 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed Jul 03 18:26:41 2019 +0200
+++ b/.hgtags	Thu Jul 04 10:37:42 2019 +0200
@@ -7,3 +7,4 @@
 4d69b79e9df6e2b646ac60f75f6655bb3c64f6c6 v2.1.0
 4d7b481e1d392cd68c48a4ad19fc2865110e724e v3-uat2
 d4a5d11e23a043026a747c626d133b45047d17df v3
+ad93adaeb68827534b1b3dd96c50096b3fa9a24c v3.1-preview20190626
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/components/importoverview/AGMLogItem.vue	Thu Jul 04 10:37:42 2019 +0200
@@ -0,0 +1,113 @@
+<template>
+  <div class="d-flex flex-column">
+    <div class="px-2 d-flex justify-content-between">
+      <div class="d-flex">
+        <div @click="toggleShow(index)" class="my-auto text-left">
+          <UISpinnerButton
+            :state="show"
+            :icons="['angle-right', 'angle-down']"
+            classes="text-info"
+          />
+        </div>
+        <div>
+          {{ line["fk-gauge-id"] }}
+          <sup v-if="isNew(line)" class="text-success">
+            (<translate>New</translate>)
+          </sup>
+        </div>
+      </div>
+      <div>{{ line["measure-date"] | dateTime }}</div>
+    </div>
+    <div v-if="show" class="compare-table">
+      <div class="row no-gutters px-4 text-left font-weight-bold">
+        <div :class="isNew(line) ? 'col-6' : 'col-4'">
+          <translate>Value</translate>
+        </div>
+        <div v-if="isOld(line)" class="col-4">
+          <translate>Old</translate>
+        </div>
+        <div :class="isNew(line) ? 'col-6' : 'col-4'">
+          <translate>New</translate>
+        </div>
+      </div>
+      <div
+        class="row no-gutters px-4 text-left"
+        v-for="(entry, index) in Object.keys(line.versions[0])"
+        :key="index"
+        v-if="isNew(line) || isDifferent(line, entry)"
+      >
+        <div :class="isNew(line) ? 'col-6' : 'col-4'">
+          {{ entry }}
+        </div>
+        <div :class="isNew(line) ? 'col-6' : 'col-4'">
+          {{ line.versions[0][entry] }}
+        </div>
+        <div
+          v-if="isOld(line) && isDifferent(line, entry)"
+          :class="isNew(line) ? 'col-6' : 'col-4'"
+        >
+          {{ line.versions[1][entry] }}
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: ["line", "index", "showDiff"],
+  computed: {
+    show() {
+      return this.index === this.showDiff;
+    }
+  },
+  methods: {
+    toggleShow(index) {
+      this.$emit("openDiff", index);
+    },
+    isNew(result) {
+      return result && result.versions && result.versions.length === 1;
+    },
+    isOld(result) {
+      return !this.isNew(result);
+    },
+    isDifferent(result, entry) {
+      return (
+        this.isOld(result) &&
+        result.versions[0][entry] != result.versions[1][entry]
+      );
+    }
+  }
+};
+</script>
+
+<style lang="sass" scoped>
+.diffs
+  width: 100%
+  overflow-y: auto
+  > div
+    border-top: dashed 1px #dee2e6
+    &:first-child
+      border-top: none
+    .compare-table
+      position: relative
+      overflow: hidden
+      &::after
+        content: ''
+        position: absolute
+        top: 0
+        right: -5px
+        bottom: 0
+        left: -5px
+        box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.4)
+      > div
+        font-size: 0.7rem
+        &:nth-child(odd)
+          background-color: #f8f9fa
+
+.split
+  max-height: 35vh
+
+.full
+  max-height: 70vh
+</style>
--- a/client/src/components/importoverview/ApprovedGaugeMeasurementDetail.vue	Wed Jul 03 18:26:41 2019 +0200
+++ b/client/src/components/importoverview/ApprovedGaugeMeasurementDetail.vue	Thu Jul 04 10:37:42 2019 +0200
@@ -6,58 +6,17 @@
       split: showLogs
     }"
   >
-    <div v-for="(result, index) in details.summary" :key="index">
-      <div class="px-2 d-flex justify-content-between">
-        <div class="d-flex">
-          <div @click="toggleDiff(index)" class="my-auto text-left">
-            <UISpinnerButton
-              :state="showDiff === index"
-              :icons="['angle-right', 'angle-down']"
-              classes="text-info"
-            />
-          </div>
-          <div>
-            {{ result["fk-gauge-id"] }}
-            <sup v-if="isNew(result)" class="text-success">
-              (<translate>New</translate>)
-            </sup>
-          </div>
-        </div>
-        <div>{{ result["measure-date"] | dateTime }}</div>
-      </div>
-      <div v-if="showDiff === index" class="compare-table">
-        <div class="row no-gutters px-4 text-left font-weight-bold">
-          <div :class="isNew(result) ? 'col-6' : 'col-4'">
-            <translate>Value</translate>
-          </div>
-          <div v-if="isOld(result)" class="col-4">
-            <translate>Old</translate>
-          </div>
-          <div :class="isNew(result) ? 'col-6' : 'col-4'">
-            <translate>New</translate>
-          </div>
-        </div>
-        <div
-          class="row no-gutters px-4 text-left"
-          v-for="(entry, index) in Object.keys(result.versions[0])"
-          :key="index"
-          v-if="isNew(result) || isDifferent(result, entry)"
-        >
-          <div :class="isNew(result) ? 'col-6' : 'col-4'">
-            {{ entry }}
-          </div>
-          <div :class="isNew(result) ? 'col-6' : 'col-4'">
-            {{ result.versions[0][entry] }}
-          </div>
-          <div
-            v-if="isOld(result) && isDifferent(result, entry)"
-            :class="isNew(result) ? 'col-6' : 'col-4'"
-          >
-            {{ result.versions[1][entry] }}
-          </div>
-        </div>
-      </div>
-    </div>
+    <virtual-list :size="scrollistConfig.size" :remain="scrollistConfig.remain">
+      <Item
+        class="d-flex flex-row px-2 border-top"
+        v-for="(item, index) in details.summary"
+        @openDiff="toggleDiff"
+        :key="index"
+        :line="item"
+        :index="index"
+        :showDiff="showDiff"
+      />
+    </virtual-list>
   </div>
 </template>
 
@@ -107,6 +66,7 @@
  * Thomas Junk <thomas.junk@intevation.de>
  */
 import { mapState } from "vuex";
+import virtualList from "vue-virtual-scroll-list";
 
 export default {
   data() {
@@ -114,28 +74,33 @@
       showDiff: 0 // open first item by default
     };
   },
+  components: {
+    "virtual-list": virtualList,
+    Item: () => import("./AGMLogItem")
+  },
   computed: {
-    ...mapState("imports", ["showLogs", "details"])
+    ...mapState("imports", ["showLogs", "details"]),
+    scrollistConfig() {
+      const smallLayout = {
+        size: 10,
+        remain: 20
+      };
+      const largeLayout = {
+        size: 12,
+        remain: 22
+      };
+      if (this.showAdditional) return smallLayout;
+      return largeLayout;
+    }
   },
   methods: {
     toggleDiff(number) {
+      console.log(number);
       if (this.showDiff !== number) {
         this.showDiff = number;
       } else {
         this.showDiff = false;
       }
-    },
-    isNew(result) {
-      return result && result.versions && result.versions.length === 1;
-    },
-    isOld(result) {
-      return !this.isNew(result);
-    },
-    isDifferent(result, entry) {
-      return (
-        this.isOld(result) &&
-        result.versions[0][entry] != result.versions[1][entry]
-      );
     }
   }
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/srsimplify/main.go	Thu Jul 04 10:37:42 2019 +0200
@@ -0,0 +1,91 @@
+// This is Free Software under GNU Affero General Public License v >= 3.0
+// without warranty, see README.md and license for details.
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// License-Filename: LICENSES/AGPL-3.0.txt
+//
+// Copyright (C) 2019 by via donau
+//   – Österreichische Wasserstraßen-Gesellschaft mbH
+// Software engineering by Intevation GmbH
+//
+// Author(s):
+//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>
+
+package main
+
+import (
+	"bufio"
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"strconv"
+	"strings"
+
+	"gemma.intevation.de/gemma/pkg/octree"
+)
+
+func loadXYZ(r io.Reader) (octree.MultiPointZ, error) {
+
+	scanner := bufio.NewScanner(r)
+
+	points := make(octree.MultiPointZ, 0, 2000000)
+
+	var x, y, z float64
+	var err error
+
+	for scanner.Scan() {
+		line := strings.TrimSpace(scanner.Text())
+		if len(line) == 0 || strings.HasPrefix(line, "#") {
+			continue
+		}
+		parts := strings.SplitN(line, " ", 3)
+		if len(parts) != 3 {
+			continue
+		}
+
+		if x, err = strconv.ParseFloat(parts[0], 64); err != nil {
+			return nil, err
+		}
+		if y, err = strconv.ParseFloat(parts[1], 64); err != nil {
+			return nil, err
+		}
+		if z, err = strconv.ParseFloat(parts[2], 64); err != nil {
+			return nil, err
+		}
+		points = append(points, octree.Vertex{X: x, Y: y, Z: z})
+	}
+
+	return points, nil
+}
+
+func storeXYZ(points octree.MultiPointZ, w io.Writer) error {
+	out := bufio.NewWriter(w)
+	for i := range points {
+		fmt.Fprintf(out, "%.5f,%.5f,%.5f\n",
+			points[i].X, points[i].Y, points[i].Z)
+	}
+	return out.Flush()
+}
+
+func main() {
+
+	var tolerance float64
+
+	flag.Float64Var(&tolerance, "t", 0.1, "accepted tolerance (shorthand)")
+	flag.Float64Var(&tolerance, "tolerance", 0.1, "accepted tolerance")
+
+	flag.Parse()
+
+	points, err := loadXYZ(os.Stdin)
+	if err != nil {
+		log.Fatalf("err: %v\n", err)
+	}
+
+	points = points.Simplify(tolerance)
+
+	if err := storeXYZ(points, os.Stdout); err != nil {
+		log.Fatalf("err: %v\n", err)
+	}
+}
--- a/pkg/controllers/common.go	Wed Jul 03 18:26:41 2019 +0200
+++ b/pkg/controllers/common.go	Thu Jul 04 10:37:42 2019 +0200
@@ -100,6 +100,18 @@
 	return &ia
 }
 
+func sliceToTextArray(s []string) *pgtype.TextArray {
+	if len(s) == 0 {
+		return nil
+	}
+	var ta pgtype.TextArray
+	if err := ta.Set(s); err != nil {
+		log.Printf("warn: %v\n", err)
+		return nil
+	}
+	return &ta
+}
+
 func toTextArray(txt string, allowed []string) *pgtype.TextArray {
 	parts := strings.Split(txt, ",")
 	var accepted []string
@@ -114,13 +126,15 @@
 			}
 		}
 	}
-	if len(accepted) == 0 {
-		return nil
-	}
-	var ta pgtype.TextArray
-	if err := ta.Set(accepted); err != nil {
-		log.Printf("warn: %v\n", err)
-		return nil
-	}
-	return &ta
+	return sliceToTextArray(accepted)
 }
+
+func splitUpper(s string) []string {
+	s = strings.Map(func(r rune) rune {
+		if ('A' <= r && r <= 'Z') || r == ',' {
+			return r
+		}
+		return -1
+	}, strings.ToUpper(s))
+	return strings.FieldsFunc(s, func(r rune) bool { return r != ',' })
+}
--- a/pkg/controllers/importqueue.go	Wed Jul 03 18:26:41 2019 +0200
+++ b/pkg/controllers/importqueue.go	Thu Jul 04 10:37:42 2019 +0200
@@ -112,6 +112,14 @@
 			query, query, query, query)
 	}
 
+	if cc := req.FormValue("cc"); cc != "" {
+		codes := sliceToTextArray(splitUpper(cc))
+		cond(" username IN "+
+			"(SELECT username FROM internal.user_profiles "+
+			"WHERE country = ANY($%d)) ",
+			codes)
+	}
+
 	if st := req.FormValue("states"); st != "" {
 		states := toTextArray(st, imports.ImportStateNames)
 		cond(" state = ANY($%d) ", states)
--- a/pkg/controllers/stretches.go	Wed Jul 03 18:26:41 2019 +0200
+++ b/pkg/controllers/stretches.go	Thu Jul 04 10:37:42 2019 +0200
@@ -540,13 +540,13 @@
 
 				for _, bn := range loaded {
 					l := bn.measurements.classify(
-						from, to,
+						res.from, res.to,
 						bn.ldc,
 						(*availMeasurement).getValue,
 					)
 
 					b := bn.measurements.classify(
-						from, to,
+						res.from, res.to,
 						bn.breaks,
 						bn.access,
 					)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkg/octree/simplify.go	Thu Jul 04 10:37:42 2019 +0200
@@ -0,0 +1,202 @@
+// This is Free Software under GNU Affero General Public License v >= 3.0
+// without warranty, see README.md and license for details.
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// License-Filename: LICENSES/AGPL-3.0.txt
+//
+// Copyright (C) 2019 by via donau
+//   – Österreichische Wasserstraßen-Gesellschaft mbH
+// Software engineering by Intevation GmbH
+//
+// Author(s):
+//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>
+
+package octree
+
+import (
+	"math"
+)
+
+func handleTriangle(
+	t *Triangle,
+	maxDist, tolerance float64,
+	maxIdx int,
+	points MultiPointZ,
+	result *MultiPointZ,
+) bool {
+	if maxDist <= tolerance {
+		return false
+	}
+
+	if len(points) == 1 {
+		*result = append(*result, points[0])
+		return true
+	}
+
+	var (
+		tris     [3]Triangle
+		planes   [3]Plane3D
+		maxDists [3]float64
+		maxIdxs  [3]int
+		parts    [3]MultiPointZ
+	)
+
+	top := points[maxIdx]
+	for i := 0; i < 3; i++ {
+		tris[i] = Triangle{t[i], t[(i+1)%3], top}
+		planes[i] = tris[i].Plane3D()
+	}
+
+nextPoint:
+	for i, v := range points {
+		if i == maxIdx {
+			continue
+		}
+
+		for j := range tris {
+			if tris[j].Contains(v.X, v.Y) {
+				if dist := math.Abs(planes[j].Eval(v)); dist > maxDists[j] {
+					maxDists[j] = dist
+					maxIdxs[j] = len(parts[j])
+				}
+				parts[j] = append(parts[j], v)
+				continue nextPoint
+			}
+		}
+	}
+
+	var found bool
+	for i, part := range parts {
+		if len(part) > 0 && handleTriangle(
+			&tris[i],
+			maxDists[i], tolerance,
+			maxIdxs[i],
+			part,
+			result,
+		) {
+			found = true
+		}
+	}
+
+	if found {
+		*result = append(*result, top)
+	}
+
+	return found
+}
+
+func (points MultiPointZ) Simplify(tolerance float64) MultiPointZ {
+
+	if len(points) < 2 {
+		return points
+	}
+
+	if tolerance < 0 {
+		tolerance = -tolerance
+	}
+
+	min := Vertex{X: math.MaxFloat64, Y: math.MaxFloat64, Z: math.MaxFloat64}
+	max := Vertex{X: -math.MaxFloat64, Y: -math.MaxFloat64, Z: -math.MaxFloat64}
+
+	var maxIdx int
+
+	for i, v := range points {
+		min.Minimize(v)
+
+		if v.X < min.X {
+			min.X = v.X
+		}
+		if v.X > max.X {
+			max.X = v.X
+		}
+		if v.Y < min.Y {
+			min.Y = v.Y
+		}
+		if v.Y > max.Y {
+			max.Y = v.Y
+		}
+		if v.Z < min.Z {
+			min.Z = v.Z
+		}
+		if v.Z > max.Z {
+			max.Z = v.Z
+			maxIdx = i
+		}
+
+		max.Maximize(v)
+	}
+
+	/*
+		log.Printf("(%.5f, %.5f, %.5f) - (%.5f, %.5f, %.5f)\n",
+			min.X, min.Y, min.Z,
+			max.X, max.Y, max.Z)
+	*/
+
+	below := min.Z - 3*tolerance
+	xMin := min.X - tolerance
+	xMax := max.X + tolerance
+	yMin := min.Y - tolerance
+	yMax := max.Y + tolerance
+
+	corners := []Vertex{
+		{xMin, yMin, below},
+		{xMax, yMin, below},
+		{xMax, yMax, below},
+		{xMin, yMax, below},
+	}
+
+	top := points[maxIdx]
+
+	tris := make([]Triangle, len(corners))
+	planes := make([]Plane3D, len(corners))
+
+	for i, v1 := range corners {
+		v2 := corners[(i+1)%len(corners)]
+		tris[i] = Triangle{v1, v2, top}
+		planes[i] = tris[i].Plane3D()
+	}
+
+	parts := make([][]Vertex, len(tris))
+
+	maxDists := make([]float64, len(planes))
+	maxIdxs := make([]int, len(planes))
+
+nextPoint:
+	for i, v := range points {
+		if i == maxIdx {
+			continue
+		}
+
+		for j := range tris {
+			if tris[j].Contains(v.X, v.Y) {
+				if dist := math.Abs(planes[j].Eval(v)); dist > maxDists[j] {
+					maxDists[j] = dist
+					maxIdxs[j] = len(parts[j])
+				}
+				parts[j] = append(parts[j], v)
+				continue nextPoint
+			}
+		}
+	}
+
+	result := make(MultiPointZ, 0, len(points))
+
+	var found bool
+	for i, part := range parts {
+		if len(part) > 0 && handleTriangle(
+			&tris[i],
+			maxDists[i], tolerance,
+			maxIdxs[i],
+			part,
+			&result,
+		) {
+			found = true
+		}
+	}
+
+	if found {
+		result = append(result, top)
+	}
+
+	return result
+}
--- a/pkg/octree/vertex.go	Wed Jul 03 18:26:41 2019 +0200
+++ b/pkg/octree/vertex.go	Thu Jul 04 10:37:42 2019 +0200
@@ -110,6 +110,10 @@
 	return -(p.A*x + p.B*y + p.D) / p.C
 }
 
+func (p Plane3D) Eval(v Vertex) float64 {
+	return p.A*v.X + p.B*v.Y + p.C*v.Z + p.D
+}
+
 func (v Vertex) Normalize() Vertex {
 	s := 1 / v.Length()
 	return Vertex{