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; ingo@696: teichmann@5831: import org.dive4elements.artifactdatabase.state.Facet; teichmann@5831: import org.dive4elements.artifacts.Artifact; teichmann@5831: import org.dive4elements.artifacts.CallContext; teichmann@5867: import org.dive4elements.river.artifacts.D4EArtifact; teichmann@5831: import org.dive4elements.river.artifacts.math.Linear; teichmann@5831: import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; teichmann@5831: import org.dive4elements.river.artifacts.model.extreme.ExtremeResult; ingo@696: sascha@2196: import org.apache.log4j.Logger; felix@2017: felix@1721: /** felix@1721: * Facet of a Waterlevel (WQKms). felix@1721: */ felix@2122: public class WaterlevelFacet extends DataFacet { ingo@696: teichmann@8202: private static Logger log = Logger.getLogger(WaterlevelFacet.class); ingo@696: ingo@696: public WaterlevelFacet(int index, String name, String description) { felix@2122: super(index, name, description, ComputeType.ADVANCE, null, null); ingo@696: } ingo@696: sascha@722: public WaterlevelFacet( sascha@742: int index, sascha@742: String name, sascha@722: String description, sascha@722: ComputeType type, sascha@722: String stateID, sascha@722: String hash sascha@722: ) { felix@6485: // Pretty weird to change order of the two String params felix@6485: // hash and stateID in comparison to parent. Its difficult to fix, now. felix@2125: super(index, name, description, type, hash, stateID); felix@2122: } felix@2122: felix@2122: public WaterlevelFacet() { sascha@722: } ingo@696: sascha@3461: protected WQKms [] getWQKms(CalculationResult res) { felix@4303: if (res.getData() instanceof ExtremeResult) felix@4303: return ((ExtremeResult) res.getData()).getWQKms(); felix@5444: else if (res.getData() instanceof WQKms[]) { felix@5444: return (WQKms []) res.getData(); felix@5444: } felix@5444: else { teichmann@8202: log.error("WaterlevelFacet got wrong data type " + res.getData()); felix@5444: return null; felix@5444: } sascha@3461: } felix@1136: felix@1136: /** felix@1136: * Get waterlevel data. felix@1136: * @return a WQKms at given index. felix@1136: */ christian@4045: @Override ingo@696: public Object getData(Artifact artifact, CallContext context) { sascha@2196: teichmann@8202: if (log.isDebugEnabled()) { teichmann@8202: log.debug("Get data for waterlevels at index: " + index + sascha@2196: " /stateId: " + stateId); sascha@2196: } ingo@696: christian@4045: if (artifact == null) { teichmann@8202: log.error("WaterlevelFacet.getData: artifact is null"); christian@4045: return null; christian@4045: } christian@4045: teichmann@5867: D4EArtifact winfo = (D4EArtifact) artifact; ingo@696: sascha@709: CalculationResult res = (CalculationResult) felix@2122: winfo.compute(context, hash, stateId, type, false); sascha@709: felix@3455: if (res == null) { teichmann@8202: log.error("WaterlevelFacet.getData: null result"); felix@3455: return null; felix@3455: } felix@3455: sascha@3461: WQKms [] wqkms = getWQKms(res); sascha@3597: Object KM = context.getContextValue("currentKm"); felix@3596: felix@5445: // Interpolation. felix@5445: if (KM != null) { felix@5445: linearInterpolate(wqkms[index], (Double) KM); felix@5445: } felix@5445: else { teichmann@8202: log.debug("Do not interpolate."); felix@5445: } felix@5445: felix@5445: return wqkms != null ? wqkms[index] : null; felix@5445: } felix@5445: felix@5445: felix@5445: /** felix@5445: * Linear interpolation of WQKms. felix@5445: * TODO rewrite. felix@5445: * @return [w, q, km] felix@5445: */ felix@5445: public WQKms linearInterpolate(WQKms wqkms, double km) { teichmann@8202: log.debug("interpolate at given km (" + km + ")"); felix@5445: felix@5445: WQKms resultWQKms = new WQKms(); felix@5445: int size = wqkms.size(); felix@5445: boolean kmIncreasing = wqkms.getKm(0) < wqkms.getKm(size-1); felix@5445: int mod = kmIncreasing ? +1 : -1; felix@5445: int idx = 0; felix@5445: // Move idx to closest from one direction, check for match. felix@5445: if (!kmIncreasing) { felix@5445: while (idx < size && wqkms.getKm(idx) < km) { felix@5445: if (Math.abs(wqkms.getKm(idx) - km) < 0.01d) { felix@5445: resultWQKms.add(wqkms.getW(idx), wqkms.getQ(idx), wqkms.getKm(idx)); felix@5445: return resultWQKms; felix@3596: } felix@5445: idx++; felix@3596: } felix@5445: } felix@5445: else { felix@5445: idx = size-1; felix@5445: while (idx > 0 && wqkms.getKm(idx) > km) { felix@5445: if (Math.abs(wqkms.getKm(idx) - km) < 0.01d) { felix@5445: resultWQKms.add(wqkms.getW(idx), wqkms.getQ(idx), wqkms.getKm(idx)); felix@5445: return resultWQKms; felix@3596: } felix@5445: idx--; felix@3596: } felix@5445: } felix@5445: if (Math.abs(wqkms.getKm(idx) - km) < 0.01d) { felix@5445: resultWQKms.add(wqkms.getW(idx), wqkms.getQ(idx), wqkms.getKm(idx)); felix@3596: return resultWQKms; felix@3596: } felix@3455: felix@5445: if ((idx != -1) && (idx < size) && (idx - mod != -1) && (idx - mod < size)) { felix@5445: double inW = Linear.linear( felix@5445: km, felix@5445: wqkms.getKm(idx), wqkms.getKm(idx - mod), felix@5445: wqkms.getW(idx), wqkms.getW(idx - mod)); felix@5445: double inQ = Linear.linear( felix@5445: km, felix@5445: wqkms.getKm(idx), wqkms.getKm(idx - mod), felix@5445: wqkms.getQ(idx), wqkms.getQ(idx - mod)); felix@5445: resultWQKms.add(inW, inQ, km); felix@5445: } felix@5445: else { teichmann@8202: log.debug("waterlevelfacet stuff " + idx + " size " + size + " mod: " + mod); felix@5445: } felix@5445: felix@5445: return resultWQKms; ingo@696: } sascha@1061: felix@1136: felix@1136: /** Copy deeply. */ felix@1136: @Override sascha@1061: public Facet deepCopy() { sascha@1061: WaterlevelFacet copy = new WaterlevelFacet(); sascha@1061: copy.set(this); sascha@1061: copy.type = type; felix@2125: copy.hash = hash; felix@2122: copy.stateId = stateId; sascha@1061: return copy; sascha@1061: } ingo@696: } ingo@696: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :