teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5863: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5863: * 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@2778: import org.apache.log4j.Logger; felix@2778: 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; felix@1085: teichmann@5831: import org.dive4elements.river.artifacts.MainValuesArtifact; teichmann@5831: import org.dive4elements.river.artifacts.math.Linear; teichmann@5831: import org.dive4elements.river.jfree.FLYSAnnotation; teichmann@5831: import org.dive4elements.river.jfree.StickyAxisAnnotation; teichmann@5831: teichmann@5831: import org.dive4elements.river.exports.DurationCurveGenerator; felix@2163: felix@2778: felix@1085: /** felix@1085: * Facet to show Main Q Values. felix@2161: * TODO Join with W implementation. felix@1085: */ felix@1085: public class MainValuesQFacet felix@1085: extends DefaultFacet felix@1085: implements FacetTypes { felix@1085: felix@2778: /** Own logger. */ sascha@3778: private static Logger logger = Logger.getLogger(MainValuesQFacet.class); felix@2778: felix@1957: /** Do we want MainValues at Gauge (not interpolated)? */ felix@1957: protected boolean isAtGauge; felix@1957: felix@3442: felix@1085: /** Trivial Constructor. */ felix@1957: public MainValuesQFacet(String name, String description, boolean atGauge) { felix@1112: this.description = description; felix@2163: this.name = name; felix@2163: this.index = 0; felix@2163: this.isAtGauge = atGauge; felix@1085: } felix@1085: felix@3442: felix@2778: /** felix@2778: * Set the hit-point in Q where a line drawn from the axis would hit the felix@2778: * curve in WQDay (if hit). felix@2778: * Employ linear interpolation. felix@2778: */ felix@2778: protected static void setHitPoint(WQDay wqday, StickyAxisAnnotation annotation) { felix@2778: int idx = 0; felix@2778: float q = annotation.getPos(); felix@2778: boolean qIncreases = wqday.getQ(0) < wqday.getQ(wqday.size()-1); felix@2778: if (qIncreases) { felix@2778: while (idx < wqday.size() && wqday.getQ(idx) < q) { felix@2778: idx++; felix@2778: } felix@2778: } felix@2778: else { felix@2778: idx = wqday.size() -1; felix@2778: while (idx > 0 && wqday.getQ(idx) > q) { felix@2778: idx--; felix@2778: } felix@2778: } felix@2778: felix@2778: double day = 0d; felix@2778: int mod = (qIncreases) ? -1 : +1; felix@2778: if (idx != 0 && idx <= wqday.size()-1) { felix@2778: day = Linear.linear(q, wqday.getQ(idx +mod), wqday.getQ(idx), felix@2778: wqday.getDay(idx+mod), wqday.getDay(idx)); felix@2778: annotation.setHitPoint((float)day); felix@2778: } felix@2778: else { felix@2778: logger.debug("StickyAnnotation does not hit wqday curve"); felix@2778: } felix@2778: } felix@2778: felix@1085: felix@1085: /** felix@1085: * Returns the data this facet requires. felix@1085: * felix@1085: * @param artifact the owner artifact. felix@1085: * @param context the CallContext (ignored). 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@2163: List qs = mvArtifact.getMainValuesQ(isAtGauge); felix@2161: List xy = new ArrayList(); ingo@1679: felix@2778: WQDay wqdays = null; felix@2778: List providers = context. felix@2778: getDataProvider(DurationCurveFacet.BB_DURATIONCURVE); felix@2778: if (providers.size() < 1) { felix@2778: logger.warn("Could not find durationcurve data provider."); felix@2778: } felix@2778: else { felix@2778: wqdays = (WQDay) providers.get(0).provideData( felix@2778: DurationCurveFacet.BB_DURATIONCURVE, felix@2778: null, felix@2778: context); felix@2778: } felix@2778: felix@2163: // Rather specific case, Q-Annotations at a maybe second yaxis. felix@2778: StickyAxisAnnotation annotation = null; felix@2163: if (this.name.equals(DURATION_MAINVALUES_Q)) { felix@2163: for (NamedDouble q: qs) { felix@2778: annotation = felix@2778: new StickyAxisAnnotation( felix@2778: q.getName(), felix@2778: (float) q.getValue(), felix@2778: StickyAxisAnnotation.SimpleAxis.Y_AXIS, felix@2778: DurationCurveGenerator.YAXIS.Q.idx); felix@2778: xy.add(annotation); felix@2778: if (wqdays != null) { felix@2778: setHitPoint(wqdays, annotation); felix@2778: } felix@2163: } felix@2163: } felix@2163: else { felix@2163: for (NamedDouble q: qs) { felix@2778: annotation = felix@2778: new StickyAxisAnnotation( felix@2778: q.getName(), felix@2778: (float) q.getValue(), felix@2778: StickyAxisAnnotation.SimpleAxis.X_AXIS); felix@2778: xy.add(annotation); felix@2778: if (wqdays != null) { felix@2778: setHitPoint(wqdays, annotation); felix@2778: } felix@2163: } ingo@1679: } ingo@1679: ingo@1679: return new FLYSAnnotation(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 MainValuesQFacet deepCopy() { felix@1957: MainValuesQFacet copy = new MainValuesQFacet(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 :