gernotbelger@9499: /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde gernotbelger@9499: * Software engineering by gernotbelger@9499: * Björnsen Beratende Ingenieure GmbH gernotbelger@9499: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt gernotbelger@9499: * gernotbelger@9499: * This file is Free Software under the GNU AGPL (>=v3) gernotbelger@9499: * and comes with ABSOLUTELY NO WARRANTY! Check out the gernotbelger@9499: * documentation coming with Dive4Elements River for details. gernotbelger@9499: */ gernotbelger@9499: package org.dive4elements.river.artifacts.uinfo.vegetationzones; gernotbelger@9499: gernotbelger@9499: import java.awt.Color; gernotbelger@9499: import java.util.HashSet; gernotbelger@9499: import java.util.List; gernotbelger@9499: import java.util.Set; gernotbelger@9499: gernotbelger@9499: import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; gernotbelger@9499: import org.dive4elements.artifactdatabase.state.Facet; gernotbelger@9499: import org.dive4elements.artifacts.Artifact; gernotbelger@9499: import org.dive4elements.artifacts.CallContext; gernotbelger@9514: import org.dive4elements.artifacts.CallMeta; gernotbelger@9499: import org.dive4elements.artifacts.DataProvider; gernotbelger@9506: import org.dive4elements.river.artifacts.D4EArtifact; gernotbelger@9514: import org.dive4elements.river.artifacts.access.RiverAccess; gernotbelger@9499: import org.dive4elements.river.artifacts.model.CrossSectionFacetUtils; gernotbelger@9527: import org.dive4elements.river.artifacts.model.river.MainWstValues; gernotbelger@9514: import org.dive4elements.river.artifacts.resources.Resources; gernotbelger@9499: import org.dive4elements.river.exports.CrossSectionGenerator; gernotbelger@9499: import org.dive4elements.river.jfree.StripedAreaDataset; gernotbelger@9499: import org.dive4elements.river.jfree.StripedAreaDataset.Stripe; gernotbelger@9499: import org.dive4elements.river.model.FastCrossSectionLine; gernotbelger@9499: import org.dive4elements.river.model.River; gernotbelger@9499: import org.dive4elements.river.themes.ThemeDocument; gernotbelger@9499: gernotbelger@9499: /** gernotbelger@9499: * @author Domenico Nardi Tironi gernotbelger@9499: * gernotbelger@9499: */ gernotbelger@9514: public final class VegetationZonesCrossSectionProcessor { gernotbelger@9499: gernotbelger@9499: private static final String MAIN_VALUE_MQ = "mq"; gernotbelger@9499: gernotbelger@9514: private static final String FACET_VEGETATION_ZONES_CROSS_SECTION = "uinfo_facet_vegetation_zones_cross_section"; gernotbelger@9499: gernotbelger@9514: private static final String FACET_DEFAULT_VEGETATION_ZONES_CROSS_SECTION = "uinfo_facet_default_vegetation_zones_cross_section"; gernotbelger@9514: gernotbelger@9514: private static final String DEFAULT_VEGZONES_DESCRIPTION = "uinfo_facet_vegetation_default_zones_cross_section.description"; gernotbelger@9499: gernotbelger@9499: private static final Set HANDLED_FACET_TYPES = new HashSet<>(); gernotbelger@9499: gernotbelger@9499: static { gernotbelger@9499: HANDLED_FACET_TYPES.add(FACET_VEGETATION_ZONES_CROSS_SECTION); gernotbelger@9514: HANDLED_FACET_TYPES.add(FACET_DEFAULT_VEGETATION_ZONES_CROSS_SECTION); gernotbelger@9514: } gernotbelger@9514: gernotbelger@9514: public static final boolean canHandle(final String facettype) { gernotbelger@9514: return HANDLED_FACET_TYPES.contains(facettype); gernotbelger@9499: } gernotbelger@9499: gernotbelger@9506: public static Facet createVegetationZonesCrossSectionFacet(final String description) { gernotbelger@9506: gernotbelger@9506: return new VegetationZonesCrossSectionFacet(FACET_VEGETATION_ZONES_CROSS_SECTION, description); gernotbelger@9499: } gernotbelger@9499: gernotbelger@9514: public static Facet createDefaultVegetationZonesCrossSectionFacet(final CallMeta callMeta) { gernotbelger@9514: gernotbelger@9514: final String description = Resources.getMsg(callMeta, DEFAULT_VEGZONES_DESCRIPTION); gernotbelger@9514: gernotbelger@9514: return new VegetationZonesCrossSectionFacet(FACET_DEFAULT_VEGETATION_ZONES_CROSS_SECTION, description); gernotbelger@9514: } gernotbelger@9514: gernotbelger@9499: public static void generateSeries(final CrossSectionGenerator generator, final ArtifactAndFacet bundle, final CallContext context, gernotbelger@9499: final ThemeDocument theme, final boolean visible) { gernotbelger@9499: gernotbelger@9499: final DataProvider provider = CrossSectionFacetUtils.getDataProvider(context); gernotbelger@9499: final FastCrossSectionLine crossSection = CrossSectionFacetUtils.getCrossSection(provider, context); gernotbelger@9499: if (crossSection == null) gernotbelger@9499: return; gernotbelger@9499: final double currentStation = crossSection.getKm(); gernotbelger@9499: gernotbelger@9514: final RiverAccess rAccess = new RiverAccess((D4EArtifact) bundle.getArtifact()); gernotbelger@9514: final River river = rAccess.getRiver(); gernotbelger@9514: gernotbelger@9514: final List zones = findZonesData(bundle, context, river); gernotbelger@9514: gernotbelger@9556: final StripedAreaDataset dataset = new StripedAreaDataset(bundle.getFacetName(), theme); gernotbelger@9514: gernotbelger@9593: for (int i = 0; i < zones.size(); i++) { gernotbelger@9593: final VegetationZoneServerClientXChange zone = zones.get(i); gernotbelger@9593: Integer lowerFromTo = zone.getLowerFromTo(); gernotbelger@9593: if (i == 0) // Hack; turning "-1" invisible gernotbelger@9593: lowerFromTo = 0; gernotbelger@9514: gernotbelger@9593: final double lower = uefdToHeight(river, currentStation, lowerFromTo); gernotbelger@9527: final double upper = uefdToHeight(river, currentStation, zone.getUpperFromTo()); gernotbelger@9514: gernotbelger@9514: final Color color = Color.decode(zone.getHexColor()); gernotbelger@9593: final String label = String.format("%s (%dd-%dd)", zone.getZoneName(), lowerFromTo, zone.getUpperFromTo()); gernotbelger@9514: dataset.addStripe(new Stripe(label, color, lower, upper)); gernotbelger@9514: } gernotbelger@9514: gernotbelger@9514: generator.addAxisDataset(dataset, 0, visible); gernotbelger@9514: return; gernotbelger@9514: } gernotbelger@9514: gernotbelger@9514: private static List findZonesData(final ArtifactAndFacet bundle, final CallContext context, final River river) { gernotbelger@9514: gernotbelger@9499: if (bundle.getFacetName().equals(FACET_VEGETATION_ZONES_CROSS_SECTION)) { gernotbelger@9499: gernotbelger@9499: final Artifact artifact = bundle.getArtifact(); gernotbelger@9506: final VegetationzonesAccess vAccess = new VegetationzonesAccess((D4EArtifact) artifact); gernotbelger@9514: return VegetationZoneServerClientXChange.parse(vAccess.getVegZones()); gernotbelger@9514: } gernotbelger@9499: gernotbelger@9514: if (bundle.getFacetName().equals(FACET_DEFAULT_VEGETATION_ZONES_CROSS_SECTION)) { gernotbelger@9499: gernotbelger@9514: return VegetationZoneServerClientXChange.getStandardList(river, context); gernotbelger@9499: } gernotbelger@9499: gernotbelger@9499: throw new UnsupportedOperationException(); gernotbelger@9499: } gernotbelger@9499: gernotbelger@9527: private static double uefdToHeight(final River river, final double station, final int uefd) { gernotbelger@9499: gernotbelger@9527: final MainWstValues mainWstValues = MainWstValues.forRiver(river); gernotbelger@9527: final double mw = mainWstValues.getW(river, MAIN_VALUE_MQ, station); gernotbelger@9499: mschaefer@9533: // Üfd = -70,559 ∗ ln((DGM - MW) + 0,5) + 88,711 gernotbelger@9499: final double f1 = -70.559; mschaefer@9509: final double f2 = 88.711; gernotbelger@9499: gernotbelger@9499: final double dgm = Math.exp((uefd - f2) / f1) + mw - 0.5; gernotbelger@9499: return dgm; gernotbelger@9499: } gernotbelger@9499: }