view gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java @ 357:25e4724aa504

Fill (i, j)-gaps when building index buffer. gnv-artifacts/trunk@430 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 15 Dec 2009 15:14:21 +0000
parents 24c21a720aa5
children aec85d00d82c
line wrap: on
line source
/**
 *
 */
package de.intevation.gnv.state.profile.horizontal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.apache.log4j.Logger;
import org.w3c.dom.Node;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

import de.intevation.artifactdatabase.Config;

import de.intevation.gnv.artifacts.cache.CacheFactory;

import de.intevation.gnv.geobackend.base.Result;
import de.intevation.gnv.geobackend.base.query.QueryExecutor;
import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory;
import de.intevation.gnv.geobackend.base.query.exception.QueryException;
import de.intevation.gnv.geobackend.sde.datasources.ResultSet;

import de.intevation.gnv.utils.IndexBuffer;

import de.intevation.gnv.math.LinearFunction;

import org.apache.commons.math.optimization.fitting.CurveFitter;

import org.apache.commons.math.optimization.general.GaussNewtonOptimizer;
import org.apache.commons.math.optimization.OptimizationException;

import org.apache.commons.math.FunctionEvaluationException;

/**
 * @author Tim Englich <tim.englich@intevation.de>
 *
 */
public class HorizontalProfileMeshCrossOutputState extends
                                                  HorizontalProfileOutputState {

    /**
     *
     */
    private static final long serialVersionUID = 2205958041745637263L;
    
    /**
     * the logger, used to log exceptions and additonaly information
     */
    private static Logger log = 
                  Logger.getLogger(HorizontalProfileMeshCrossOutputState.class);
    

    private String ijkQueryID = null;
   
    /**
     * Constructor
     */
    public HorizontalProfileMeshCrossOutputState() {
        super();
    }
    
    /**
     * @see de.intevation.gnv.state.timeseries.TimeSeriesOutputState#setup(org.w3c.dom.Node)
     */
    @Override
    public void setup(Node configuration) {
        super.setup(configuration);
        this.ijkQueryID = Config.getStringXPath(configuration,"queryID-ijk");
        
    }

    @Override
    protected Collection<Result> getChartResult(String uuid) {
        log.debug("OutputStateBase.getChartResult");
        Collection<Result> result = null;
        if (CacheFactory.getInstance().isInitialized()) {
            String key = uuid + super.getID();
            log.debug("Hash for Queryelements: " + key);
            net.sf.ehcache.Element value = CacheFactory.getInstance().getCache().get(key);
            if (value != null) {
                result = (Collection<Result>) (value.getObjectValue());
            }else{
                
                if (this.inputData.containsKey("mesh_linestring")){
                    
                    try {
                        // 1. IJK Anfragen f�r Stuetzpunkte im Netz ausf�hren.
                        LineString ls = (LineString)new WKTReader().read(this.inputData
                                                                         .get("mesh_linestring")
                                                                         .getValue());
                        Coordinate[] coords = ls.getCoordinates();
                        
                        List<java.awt.Point> points = new ArrayList<java.awt.Point>(coords.length);
                        
                        String meshid = this.inputData.get("meshid").getValue();
                        QueryExecutor queryExecutor = QueryExecutorFactory
                                                        .getInstance()
                                                        .getQueryExecutor();

                        ArrayList missingPoints = new ArrayList();

                        String additionWhere = "TRUE";

                        for (int i = 0; i < coords.length; i++) {

                            String wkt = "POINT( "+coords[i].x+" "+coords[i].y+" )";

                            result = queryExecutor.executeQuery(this.ijkQueryID,
                                                               new String[]{meshid,wkt});
                            if (!result.isEmpty()){
                                Result resultValue = result.iterator().next();
                                int iPos = resultValue.getInteger(1);
                                int jPos = resultValue.getInteger(0);
                                log.debug("Found Pos "+iPos+"/"+jPos +" for "+wkt);
                                points.add(i, new java.awt.Point(iPos,jPos));
                            }else{
                                log.debug("No i/j Pos found for "+wkt);
                                missingPoints.add(new Object [] { Integer.valueOf(i), coords[i] });
                                points.add(i, null);
                                // Special Case no i,j found for Coordinate
                            }
                        }

                        if (missingPoints.size() == coords.length) {
                            log.debug("cannot create index buffer");
                        }
                        else { // generate index filter
                            boolean remainsMissingPoints = !missingPoints.isEmpty();

                            if (remainsMissingPoints) {
                                // try to guess the missing (i, j)
                                CurveFitter iFitter = new CurveFitter(new GaussNewtonOptimizer(true));
                                CurveFitter jFitter = new CurveFitter(new GaussNewtonOptimizer(true));

                                for (int i = 0, N = points.size(); i < N; ++i) {
                                    java.awt.Point p = (java.awt.Point)points.get(i);
                                    if (p != null) {
                                        Coordinate coord = coords[i];
                                        iFitter.addObservedPoint(coord.x, p.x);
                                        jFitter.addObservedPoint(coord.y, p.y);
                                    }
                                }
                                try {
                                    // XXX: Assumption: (i, j) are created by componentwise linear function.
                                    // This is surely not correct because (x, y) are in a ellipsoid projection.
                                    // TODO: use ellipsoid functions and fit with Levenberg Marquardt.
                                    double [] iParams = iFitter.fit(
                                        LinearFunction.INSTANCE, new double [] { 1d, 1d });

                                    double [] jParams = jFitter.fit(
                                        LinearFunction.INSTANCE, new double [] { 1d, 1d });

                                    for (int i = missingPoints.size()-1; i >= 0; --i) {
                                        Object [] a = (Object [])missingPoints.get(i);
                                        Coordinate coord = (Coordinate)a[1];
                                        int pi = (int)Math.round(iParams[0]*coord.x + iParams[1]);
                                        int pj = (int)Math.round(jParams[0]*coord.y + jParams[1]);
                                        points.set(
                                            ((Integer)a[0]).intValue(),
                                            new java.awt.Point(pi, pj));
                                    }

                                    remainsMissingPoints = false; // we filled the gaps
                                }
                                catch (FunctionEvaluationException fee) {
                                    log.error(fee);
                                }
                                catch (OptimizationException oe) {
                                    log.error(oe);
                                }
                            }

                            if (!remainsMissingPoints) {
                                // TODO: Make Tablenames and Columns Configurable
                                IndexBuffer ib = new IndexBuffer(
                                    points, 
                                    "MEDIAN.MESHPOINT.IPOSITION", 
                                    "MEDIAN.MESHPOINT.JPOSITION" );
                                additionWhere = ib.toWhereClause();
                                log.debug("Additional Where Clause = "+additionWhere);
                                // 2. Aus diesen Stuetzpunkten den Resultset generieren.
                            }
                        } // if generate index filter
                        
                        String[] filterValues = this.generateFilterValuesFromInputData();
                        String[] addedFilterValues = new String[filterValues.length+1];
                        System.arraycopy(filterValues, 0, addedFilterValues, 0, filterValues.length);
                        addedFilterValues[filterValues.length] = additionWhere;
                        
                        result = queryExecutor.executeQuery(this.queryID,
                                                            addedFilterValues);
                        
                    } catch (ParseException e) {
                        log.error(e,e);
                    }catch (QueryException e) {
                        log.error(e,e);
                    }
                }else{
                    // TODO: definieren was passiert wenn kein linestring vorhanden ist.
                }
                
                if (CacheFactory.getInstance().isInitialized()) {
                    CacheFactory.getInstance().getCache().put(new net.sf.ehcache.Element(key, result));
                }
                
            }
        }
        return result;
    }
    
    

}

http://dive4elements.wald.intevation.org