Mercurial > gemma
view pkg/octree/classbreaks.go @ 3837:92e9794ab62a sld-colors
Merged default into sld-color branch.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Fri, 05 Jul 2019 12:26:49 +0200 |
parents | 631f5eaf29de |
children | 37d5c4441c70 |
line wrap: on
line source
// 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 ( "context" "database/sql" "errors" "math" "sort" "strconv" "strings" ) const ( selectClassBreaksSQL = ` SELECT config_val FROM sys_admin.system_config WHERE config_key = $1` ) func SampleDiffHeights(min, max, step float64) []float64 { var heights []float64 switch { case min >= 0: // All values positive. for v := 0.0; v <= max; v += step { if v >= min { heights = append(heights, v) } } case max <= 0: // All values negative. for v := 0.0; v >= min; v -= step { if v <= max { heights = append(heights, v) } } default: // Positive and negative. for v := step; v <= max; v += step { heights = append(heights, v) } for i, j := 0, len(heights)-1; i < j; i, j = i+1, j-1 { heights[i], heights[j] = heights[j], heights[i] } for v := 0.0; v >= min; v -= step { heights = append(heights, v) } } return heights } func LoadClassBreaks(ctx context.Context, tx *sql.Tx, key string) ([]float64, error) { var config sql.NullString err := tx.QueryRowContext(ctx, selectClassBreaksSQL, key).Scan(&config) switch { case err == sql.ErrNoRows: return nil, nil case err != nil: return nil, err case !config.Valid: return nil, errors.New("Invalid config string") } parts := strings.Split(config.String, ",") classes := make([]float64, 0, len(parts)) for _, part := range parts { if idx := strings.IndexRune(part, ':'); idx >= 0 { part = part[idx+1:] } if part = strings.TrimSpace(part); part == "" { continue } v, err := strconv.ParseFloat(part, 64) if err != nil { return nil, err } classes = append(classes, v) } sort.Float64s(classes) return classes, nil } func InBetweenClassBreaks(cbs []float64, min float64, steps int) []float64 { if len(cbs) < 2 || steps < 2 { return cbs } out := make([]float64, 1, len(cbs)*steps) out[0] = cbs[0] _1steps := 1 / float64(steps) for i := 1; i < len(cbs); i++ { last, curr := cbs[i-1], cbs[i] // Gap already too small -> proceed with next gap. diff := curr - last if math.Abs(diff) < min { out = append(out, curr) continue } delta := diff * _1steps for p := last + delta; p < curr; p += delta { out = append(out, p) } out = append(out, curr) } return out }