teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.artifacts.model; felix@1085: ingo@1679: import java.util.ArrayList; ingo@1679: import java.util.List; ingo@1679: felix@2775: import org.apache.log4j.Logger; felix@2775: teichmann@5831: import org.dive4elements.artifacts.Artifact; teichmann@5831: import org.dive4elements.artifacts.CallContext; teichmann@5831: import org.dive4elements.artifacts.DataProvider; ingo@1679: teichmann@5831: import org.dive4elements.artifactdatabase.state.DefaultFacet; ingo@1679: teichmann@5831: import org.dive4elements.river.artifacts.MainValuesArtifact; teichmann@5831: import org.dive4elements.river.artifacts.math.Linear; teichmann@5864: import org.dive4elements.river.jfree.RiverAnnotation; teichmann@5831: import org.dive4elements.river.jfree.StickyAxisAnnotation; felix@6525: import org.dive4elements.river.exports.fixings.FixChartGenerator; felix@1085: felix@2161: felix@1085: /** felix@1085: * Facet to show Main W Values. felix@1085: */ felix@1085: public class MainValuesWFacet felix@1085: extends DefaultFacet felix@1085: implements FacetTypes { felix@1085: felix@2775: /** Own logger. */ sascha@3778: private static Logger logger = Logger.getLogger(MainValuesWFacet.class); felix@2775: felix@1957: /** Do we want MainValues at Gauge (not interpolated)? */ felix@1957: protected boolean isAtGauge; felix@1957: felix@1085: /** Trivial Constructor. */ felix@1957: public MainValuesWFacet(String name, String description, boolean atGauge) { felix@1112: this.description = description; felix@1809: this.name = name; felix@1957: this.index = 0; felix@1957: this.isAtGauge = atGauge; felix@1085: } felix@1085: felix@1085: felix@1085: /** felix@2775: * Set the hit-point in W where a line drawn from the axis would hit the felix@2775: * curve in WQDay (if hit). felix@2775: * Employ linear interpolation. felix@2775: */ felix@2775: protected static void setHitPoint(WQDay wqday, StickyAxisAnnotation annotation) { felix@2775: int idx = 0; felix@2775: float w = annotation.getPos(); felix@2775: boolean wIncreases = wqday.getW(0) < wqday.getW(wqday.size()-1); felix@2775: if (wIncreases) { felix@2775: while (idx < wqday.size() && wqday.getW(idx) < w) { felix@2775: idx++; felix@2775: } felix@2775: } felix@2775: else { felix@2775: idx = wqday.size() -1; felix@2775: while (idx > 0 && wqday.getW(idx) > w) { felix@2775: idx--; felix@2775: } felix@2775: } felix@2775: felix@2775: double day = 0d; felix@2775: int mod = (wIncreases) ? -1 : +1; felix@2780: if (idx != 0 && idx < wqday.size()-1-mod) { felix@2775: day = Linear.linear(w, wqday.getW(idx +mod), wqday.getW(idx), felix@2775: wqday.getDay(idx+mod), wqday.getDay(idx)); felix@2775: annotation.setHitPoint((float)day); felix@2775: } felix@2775: else { felix@2775: logger.debug("StickyAnnotation does not hit wqday curve"); felix@2775: } felix@2775: } felix@2775: felix@2775: felix@2775: /** felix@4235: * Returns the data this facet provides. felix@1085: * felix@1085: * @param artifact the owner artifact. felix@6574: * @param context the CallContext (can be used to find out if in felix@6574: * navigable fixation-setting, or durationcurve). felix@1085: * felix@1085: * @return the data. felix@1085: */ felix@1085: @Override felix@1085: public Object getData(Artifact artifact, CallContext context) { felix@1085: MainValuesArtifact mvArtifact = (MainValuesArtifact) artifact; ingo@1679: felix@4235: List ws = mvArtifact.getMainValuesW(isAtGauge); felix@2161: List xy = new ArrayList(); ingo@1679: felix@2780: // Find whether a duration curve is on the blackboard. felix@2775: WQDay wqdays = null; felix@2775: List providers = context. felix@2775: getDataProvider(DurationCurveFacet.BB_DURATIONCURVE); felix@2775: if (providers.size() < 1) { felix@2775: logger.warn("Could not find durationcurve data provider."); felix@6525: // Do we have a current km in context? felix@6525: // If so, we are likely fetching data for a navigable felix@6525: // diagram (i.e. in fixation branch). felix@6525: if (context.getContextValue(FixChartGenerator.CURRENT_KM) != null) { felix@6525: Double ckm = (Double) context.getContextValue(FixChartGenerator.CURRENT_KM); felix@6525: // Return linearly interpolated values, in m if not at gauge, aheinecke@6687: // in cm over datum if at gauge. felix@6525: ws = mvArtifact.getMainValuesW(new double[] {ckm}); felix@6525: } felix@2775: } felix@2775: else { felix@2775: wqdays = (WQDay) providers.get(0).provideData( felix@2775: DurationCurveFacet.BB_DURATIONCURVE, felix@2775: null, felix@2775: context); felix@2775: } felix@2775: ingo@1679: for (NamedDouble w: ws) { felix@6695: logger.debug("W Annotation at " + w.getValue() + " ("+w.getName()+")"+ wqdays); felix@6695: if (Double.isNaN(w.getValue())) { felix@6695: logger.warn("NaN MainValue " + w.getName()); felix@6695: continue; felix@6695: } felix@2775: StickyAxisAnnotation annotation = felix@2775: new StickyAxisAnnotation( felix@2775: w.getName(), felix@2775: (float) w.getValue(), felix@2775: StickyAxisAnnotation.SimpleAxis.Y_AXIS); felix@2775: xy.add(annotation); felix@2775: if (wqdays != null) { felix@2775: setHitPoint(wqdays, annotation); felix@2775: } ingo@1679: } ingo@1679: teichmann@5864: return new RiverAnnotation(description, xy); felix@1085: } felix@1085: felix@1085: felix@1085: /** felix@1085: * Create a deep copy of this Facet. felix@1085: * @return a deep copy. felix@1085: */ felix@1085: @Override felix@1085: public MainValuesWFacet deepCopy() { felix@1957: MainValuesWFacet copy = new MainValuesWFacet(this.name, felix@1957: description, this.isAtGauge); felix@1085: copy.set(this); felix@1085: return copy; felix@1085: } felix@1085: } felix@1809: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :