Mercurial > gemma
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{