view client/src/components/layers/styles.js @ 5560:f2204f91d286

Join the log lines of imports to the log exports to recover data from them. Used in SR export to extract information that where in the meta json but now are only found in the log.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 09 Feb 2022 18:34:40 +0100
parents 96a544504818
children
line wrap: on
line source

import { Icon, Stroke, Style, Fill, Text, Circle } from "ol/style";
import Point from "ol/geom/Point";
import { getCenter } from "ol/extent";
import store from "@/store/index";
import classifications from "../../lib/classifications";

const styles = {
  blue1: new Style({
    stroke: new Stroke({
      color: [0, 0, 255, 0.8],
      lineDash: [2, 4],
      lineCap: "round",
      width: 2
    }),
    fill: new Fill({
      color: [240, 230, 0, 0.2]
    })
  }),
  blue2: new Style({
    stroke: new Stroke({
      color: [0, 0, 255, 0.9],
      lineDash: [3, 6],
      lineCap: "round",
      width: 2
    }),
    fill: new Fill({
      color: [240, 230, 0, 0.1]
    })
  }),
  blue3: new Style({
    stroke: new Stroke({
      color: [0, 0, 255, 1.0],
      width: 2
    }),
    fill: new Fill({
      color: [255, 255, 255, 0.4]
    })
  }),
  yellow1: new Style({
    stroke: new Stroke({
      color: "rgba(230, 230, 10, .8)",
      width: 4
    }),
    fill: new Fill({
      color: "rgba(230, 230, 10, .3)"
    })
  }),
  yellow2: new Style({
    stroke: new Stroke({
      color: "rgba(250, 200, 0, .8)",
      width: 2
    }),
    fill: new Fill({
      color: "rgba(250, 200, 10, .3)"
    })
  }),
  yellow3: new Style({
    stroke: new Stroke({
      color: "rgba(250, 240, 10, .9)",
      width: 5
    }),
    fill: new Fill({
      color: "rgba(250, 240, 0, .7)"
    })
  }),
  orange1: new Style({
    stroke: new Stroke({
      color: "rgba(255, 150, 10, .8)",
      width: 2
    }),
    fill: new Fill({
      color: "rgba(255, 150, 0, .3)"
    })
  }),
  orange2: new Style({
    stroke: new Stroke({
      color: "rgba(255, 166, 10, .9)",
      width: 5
    }),
    fill: new Fill({
      color: "rgba(255, 166, 0, .7)"
    })
  }),
  red1: new Style({
    stroke: new Stroke({
      color: "rgba(255, 0, 0, 1)",
      width: 4
    })
  }),
  circleBlue: new Style({
    image: new Circle({
      radius: 5,
      fill: new Fill({ color: "rgba(255, 0, 0, 0.1)" }),
      stroke: new Stroke({ color: "blue", width: 1 })
    })
  }),
  textFW1: new Style({
    text: new Text({
      font: 'bold 12px "Open Sans", "sans-serif"',
      placement: "line",
      fill: new Fill({
        color: "black"
      }),
      text: "LOS: 1"
      //, zIndex: 10
    })
  }),
  textFW2: new Style({
    text: new Text({
      font: 'bold 12px "Open Sans", "sans-serif"',
      placement: "line",
      fill: new Fill({
        color: "black"
      }),
      text: "LOS: 2"
      //, zIndex: 10
    })
  }),
  textFW3: new Style({
    text: new Text({
      font: 'bold 12px "Open Sans", "sans-serif"',
      placement: "line",
      fill: new Fill({
        color: "black"
      }),
      text: "LOS: 3"
      //, zIndex: 10
    })
  })
};

const styleFactory = function(mapId) {
  const recencyColorCodes = {
    OK: "lime",
    WARNING: "yellow",
    DANGER: "red",
    NEUTRAL: "white"
  };
  const gmAvailabilityColorCodes = {
    OK: "lime",
    WARNING: "yellow",
    DANGER: "red",
    NEUTRAL: "white"
  };
  const forecastAccuracyColorCodes = {
    OK: "lime",
    WARNING: "yellow",
    DANGER: "red",
    NEUTRAL: "white"
  };

  const forecastVsRealityColorCodes = {
    OK: "lime",
    WARNING: "yellow",
    DANGER: "red",
    NEUTRAL: "white"
  };
  return {
    recencyColorCodes: recencyColorCodes,
    gmAvailabilityColorCodes: gmAvailabilityColorCodes,
    forecastAccuracyColorCodes: forecastAccuracyColorCodes,
    forecastVsRealityColorCodes: forecastVsRealityColorCodes,
    stretches(feature) {
      let style = styles.yellow2;
      if (feature.get("highlighted")) {
        style = styles.yellow3;
      }
      return style;
    },
    sections(feature) {
      let style = styles.orange1;
      if (feature.get("highlighted")) {
        style = styles.orange2;
      }
      return style;
    },
    fwd1() {
      return [styles.blue1, styles.textFW1];
    },
    fwd2() {
      return [styles.blue2, styles.textFW2];
    },
    fwd3() {
      return [styles.blue3, styles.textFW3];
    },
    bottleneck() {
      return styles.yellow1;
    },
    bottleneckStatus(feature, resolution, isLegend) {
      let s = [];
      if ((feature.get("fa_critical") && resolution > 15) || isLegend) {
        let bnCenter = getCenter(feature.getGeometry().getExtent());
        s.push(
          new Style({
            geometry: new Point(bnCenter),
            image: new Icon({
              src: require("@/assets/marker-bottleneck-critical.png"),
              anchor: [0.5, 0.5],
              scale: isLegend ? 0.5 : 1
            })
          })
        );
      }
      if (feature.get("fa_critical") && !isLegend) {
        s.push(styles.red1);
      }
      return s;
    },
    bottleneckFairwayAvailability(feature, resolution, isLegend) {
      let s = [];
      if (isLegend) {
        s.push(
          new Style({
            image: new Icon({
              src: require("@/assets/fa-diagram.png"),
              anchor: [0.5, 0.5],
              scale: 1
            })
          })
        );
      }
      if (feature.get("fa_critical") && feature.get("fa_data")) {
        let data = feature.get("fa_data");
        const heightInPixel = 80;
        const relativeHeightInPercent = heightInPixel / 100;
        let lnwlHeight = relativeHeightInPercent * data.ldc;
        let belowThresholdHeight = relativeHeightInPercent * data.below;
        let betweenThresholdHeight = relativeHeightInPercent * data.between;
        let aboveThresholdHeight = relativeHeightInPercent * data.above;
        let lnwl = `<rect x='2' y='${2 +
          heightInPixel -
          lnwlHeight}' width='10' height='${lnwlHeight}' stroke-width='0' fill='aqua'/>`;
        let above = `<rect x='12' y='${2 +
          heightInPixel -
          aboveThresholdHeight}' width='18' height='${aboveThresholdHeight}' stroke-width='0' fill='blue'/>`;
        let between = `<rect x='12' y='${2 +
          heightInPixel -
          aboveThresholdHeight -
          betweenThresholdHeight}' width='18' height='${betweenThresholdHeight}' stroke-width='0' fill='darksalmon'/>`;
        let below = `<rect x='12' y='${2 +
          heightInPixel -
          aboveThresholdHeight -
          betweenThresholdHeight -
          belowThresholdHeight}' width='18' height='${belowThresholdHeight}' stroke-width='0' fill='hotpink'/>`;
        let frame = `<rect x='0' y='0' width='32' height='84' stroke-width='0' fill='white'/>`;
        let svg = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='84'><g>${frame}${lnwl}${above}${between}${below}</g></svg>`;
        let bnCenter = getCenter(feature.getGeometry().getExtent());
        s.push(
          new Style({
            geometry: new Point(bnCenter),
            image: new Icon({
              src: svg,
              anchor: [1.2, 1.2]
            })
          })
        );
      }
      return s;
    },
    dataAvailability(feature, resolution, isLegend) {
      let s = [];
      if (isLegend) {
        s.push(
          new Style({
            image: new Icon({
              src: require("@/assets/da-diagram.png"),
              anchor: [0.5, 0.5],
              scale: 1
            })
          })
        );
      } else {
        // TODO: Get information from feature and check the ranges according to #423, #424, #425
        let colorWaterlevel =
          gmAvailabilityColorCodes[classifications.gmAvailability(feature)];
        let colorComparison =
          forecastVsRealityColorCodes[
            classifications.forecastVsReality(feature)
          ];
        let colorAccuracy =
          forecastAccuracyColorCodes[classifications.forecastAccuracy(feature)];
        let map = store.getters["map/openLayersMap"](mapId);
        let geom = feature.getGeometry();
        if (!(geom instanceof Point)) {
          geom = new Point(getCenter(feature.getGeometry().getExtent()));
        }
        if (
          (map.getLayer("BOTTLENECKS").getVisible() &&
            feature.getId().indexOf("bottlenecks") > -1) ||
          (map.getLayer("SECTIONS").getVisible() &&
            feature.getId().indexOf("sections") > -1) ||
          (map.getLayer("STRETCHES").getVisible() &&
            feature.getId().indexOf("stretches") > -1) ||
          (map.getLayer("GAUGES").getVisible() &&
            feature.getId().indexOf("gauges") > -1)
        ) {
          let frame = `<polyline points='16,0 32,28 0,28 16,0' stroke='grey' stroke-width='1' fill='white'/>`;
          let waterlevel = `<polyline points="16,0 24,14 16,28 8,14 16,0" stroke='grey' stroke-width='1' fill='${colorWaterlevel}'/>`;
          let accuracy = `<polyline points="24,14 32,28 16,28 24,14" stroke='grey' stroke-width='1' fill='${colorAccuracy}'/>`;
          let comparison = `<polyline points="8,14 16,28 0,28 8,14" stroke='grey' stroke-width='1' fill='${colorComparison}'/>`;
          let svg = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='28'><g>${frame}${waterlevel}${comparison}${accuracy}</g></svg>`;
          s.push(
            new Style({
              geometry: geom,
              image: new Icon({
                src: svg,
                anchor: [-0.5, 1]
              })
            })
          );
        }

        if (
          map.getLayer("BOTTLENECKS").getVisible() &&
          feature.getId().indexOf("bottlenecks") > -1
        ) {
          let colorUniformTriangle =
            recencyColorCodes[classifications.surveyRecency(feature)];
          let frame = `<polyline points='16,0 32,28 0,28 16,0' stroke='grey' stroke-width='1' fill='${colorUniformTriangle}'/>`;
          let svg = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='28'><g>${frame}</g></svg>`;
          s.push(
            new Style({
              geometry: geom,
              image: new Icon({
                src: svg,
                anchor: [0.5, 1]
              })
            })
          );
        }
      }
      return s;
    },
    dma(feature, resolution) {
      if (resolution < 10) {
        var s = styles.circleBlue;
        if (resolution < 6) {
          s.setText(
            new Text({
              offsetY: 12,
              font: '10px "Open Sans", "sans-serif"',
              fill: new Fill({
                color: "black"
              }),
              text: (feature.get("hectometre") / 10).toString()
            })
          );
        }
        return s;
      }
      return [];
    },
    gauge(feature, resolution, isLegend) {
      let waterlevel = feature.get("gm_waterlevel");
      let text = feature.get("objname");
      let iconColor = "white";
      if (waterlevel) {
        text += "\n(" + waterlevel + " cm)";
        let refWaterlevels = JSON.parse(feature.get("reference_water_levels"));
        if (refWaterlevels) {
          const HDC =
            refWaterlevels[
              Object.keys(refWaterlevels).find(e => /HDC/.test(e))
            ];
          const LDC =
            refWaterlevels[
              Object.keys(refWaterlevels).find(e => /LDC/.test(e))
            ];
          if (waterlevel < LDC) iconColor = "brown";
          if (waterlevel > LDC && waterlevel < HDC) iconColor = "blue";
          if (waterlevel > HDC) iconColor = "red";
        }
      }

      return [
        new Style({
          image: new Icon({
            src: require("@/assets/marker-gauge-" + iconColor + ".png"),
            anchor: [0.5, isLegend ? 0.5 : 1],
            scale: isLegend ? 0.5 : 1
          }),
          text: new Text({
            font: '10px "Open Sans", "sans-serif"',
            offsetY: 15,
            fill: new Fill({
              color: "black"
            }),
            backgroundFill: new Fill({
              color: "rgba(255, 255, 255, 0.7)"
            }),
            padding: [2, 2, 2, 2],
            text
          })
        })
      ];
    }
  };
};

export { styles, styleFactory };