ingo@696: package de.intevation.flys.artifacts.model;
ingo@696: 
sascha@2196: import de.intevation.artifactdatabase.state.Facet;
ingo@696: import de.intevation.artifacts.Artifact;
ingo@696: import de.intevation.artifacts.CallContext;
felix@2122: import de.intevation.flys.artifacts.FLYSArtifact;
christian@4045: import de.intevation.flys.artifacts.math.Linear;
sascha@697: import de.intevation.flys.artifacts.states.DefaultState.ComputeType;
felix@4303: import de.intevation.flys.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: 
ingo@696:     private static Logger logger = 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@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 {
felix@5444:             logger.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: 
sascha@2196:         if (logger.isDebugEnabled()) {
sascha@2196:             logger.debug("Get data for waterlevels at index: " + index +
sascha@2196:                 " /stateId: " + stateId);
sascha@2196:         }
ingo@696: 
christian@4045:         if (artifact == null) {
christian@4045:             logger.error("WaterlevelFacet.getData: artifact is null");
christian@4045:             return null;
christian@4045:         }
christian@4045: 
felix@3455:         FLYSArtifact winfo = (FLYSArtifact) artifact;
ingo@696: 
sascha@709:         CalculationResult res = (CalculationResult)
felix@2122:             winfo.compute(context, hash, stateId, type, false);
sascha@709: 
felix@3455:         if (res == null) {
felix@3455:             logger.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 {
felix@5445:             logger.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) {
felix@5445:         logger.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 {
felix@5445:             logger.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 :