view artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCrossSectionProcessor.java @ 9661:9b8ba3b83a15

Importer (s/u-info) vegetation zones: new database column in vegetation_type table for german type name, localized vegetation type names by querying the database instead of translating by resource property, detecting and cancelling the import of a second vegetation zone file for a river, detecting, logging, cancelling in case of wrong column titles, detecting, logging and ignoring lines with missing (color) values, comparing vegetation zone name and class with the database and logging+ignoring in case of inconsistencies, starting the most elevated zone with 0 instead of -1 overflow days
author mschaefer
date Mon, 23 Mar 2020 16:38:12 +0100
parents 8f4e300b5f79
children
line wrap: on
line source
/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
 * Software engineering by
 *  Björnsen Beratende Ingenieure GmbH
 *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */
package org.dive4elements.river.artifacts.uinfo.vegetationzones;

import java.awt.Color;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
import org.dive4elements.artifactdatabase.state.Facet;
import org.dive4elements.artifacts.Artifact;
import org.dive4elements.artifacts.CallContext;
import org.dive4elements.artifacts.CallMeta;
import org.dive4elements.artifacts.DataProvider;
import org.dive4elements.river.artifacts.D4EArtifact;
import org.dive4elements.river.artifacts.access.RiverAccess;
import org.dive4elements.river.artifacts.model.CrossSectionFacetUtils;
import org.dive4elements.river.artifacts.model.river.MainWstValues;
import org.dive4elements.river.artifacts.resources.Resources;
import org.dive4elements.river.exports.CrossSectionGenerator;
import org.dive4elements.river.jfree.StripedAreaDataset;
import org.dive4elements.river.jfree.StripedAreaDataset.Stripe;
import org.dive4elements.river.model.FastCrossSectionLine;
import org.dive4elements.river.model.River;
import org.dive4elements.river.themes.ThemeDocument;

/**
 * @author Domenico Nardi Tironi
 *
 */
public final class VegetationZonesCrossSectionProcessor {

    private static final String MAIN_VALUE_MQ = "mq";

    private static final String FACET_VEGETATION_ZONES_CROSS_SECTION = "uinfo_facet_vegetation_zones_cross_section";

    private static final String FACET_DEFAULT_VEGETATION_ZONES_CROSS_SECTION = "uinfo_facet_default_vegetation_zones_cross_section";

    private static final String DEFAULT_VEGZONES_DESCRIPTION = "uinfo_facet_vegetation_default_zones_cross_section.description";

    private static final Set<String> HANDLED_FACET_TYPES = new HashSet<>();

    static {
        HANDLED_FACET_TYPES.add(FACET_VEGETATION_ZONES_CROSS_SECTION);
        HANDLED_FACET_TYPES.add(FACET_DEFAULT_VEGETATION_ZONES_CROSS_SECTION);
    }

    public static final boolean canHandle(final String facettype) {
        return HANDLED_FACET_TYPES.contains(facettype);
    }

    public static Facet createVegetationZonesCrossSectionFacet(final String description) {

        return new VegetationZonesCrossSectionFacet(FACET_VEGETATION_ZONES_CROSS_SECTION, description);
    }

    public static Facet createDefaultVegetationZonesCrossSectionFacet(final CallMeta callMeta) {

        final String description = Resources.getMsg(callMeta, DEFAULT_VEGZONES_DESCRIPTION);

        return new VegetationZonesCrossSectionFacet(FACET_DEFAULT_VEGETATION_ZONES_CROSS_SECTION, description);
    }

    public static void generateSeries(final CrossSectionGenerator generator, final ArtifactAndFacet bundle, final CallContext context,
            final ThemeDocument theme, final boolean visible) {

        final DataProvider provider = CrossSectionFacetUtils.getDataProvider(context);
        final FastCrossSectionLine crossSection = CrossSectionFacetUtils.getCrossSection(provider, context);
        if (crossSection == null)
            return;
        final double currentStation = crossSection.getKm();

        final RiverAccess rAccess = new RiverAccess((D4EArtifact) bundle.getArtifact());
        final River river = rAccess.getRiver();

        final List<VegetationZoneServerClientXChange> zones = findZonesData(bundle, context, river);

        final StripedAreaDataset dataset = new StripedAreaDataset(bundle.getFacetName(), theme);

        for (int i = 0; i < zones.size(); i++) {
            final VegetationZoneServerClientXChange zone = zones.get(i);
            final Integer lowerFromTo = zone.getLowerFromTo();

            final double lower = uefdToHeight(river, currentStation, lowerFromTo);
            final double upper = uefdToHeight(river, currentStation, zone.getUpperFromTo());

            final Color color = Color.decode(zone.getHexColor());
            final String label = String.format("%s (%dd-%dd)", zone.getZoneName(), lowerFromTo, zone.getUpperFromTo());
            dataset.addStripe(new Stripe(label, color, lower, upper));
        }

        generator.addAxisDataset(dataset, 0, visible);
        return;
    }

    private static List<VegetationZoneServerClientXChange> findZonesData(final ArtifactAndFacet bundle, final CallContext context, final River river) {

        if (bundle.getFacetName().equals(FACET_VEGETATION_ZONES_CROSS_SECTION)) {

            final Artifact artifact = bundle.getArtifact();
            final VegetationzonesAccess vAccess = new VegetationzonesAccess((D4EArtifact) artifact);
            return VegetationZoneServerClientXChange.parse(vAccess.getVegZones());
        }

        if (bundle.getFacetName().equals(FACET_DEFAULT_VEGETATION_ZONES_CROSS_SECTION)) {

            return VegetationZoneServerClientXChange.getStandardList(river, context);
        }

        throw new UnsupportedOperationException();
    }

    private static double uefdToHeight(final River river, final double station, final int uefd) {

        final MainWstValues mainWstValues = MainWstValues.forRiver(river);
        final double mw = mainWstValues.getW(river, MAIN_VALUE_MQ, station);

        // Üfd = -70,559 ∗ ln((DGM - MW) + 0,5) + 88,711
        final double f1 = -70.559;
        final double f2 = 88.711;

        final double dgm = Math.exp((uefd - f2) / f1) + mw - 0.5;
        return dgm;
    }
}

http://dive4elements.wald.intevation.org