diff 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 diff
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java	Tue Dec 15 14:55:42 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java	Tue Dec 15 15:14:21 2009 +0000
@@ -17,14 +17,26 @@
 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>
  *
@@ -78,7 +90,7 @@
                 if (this.inputData.containsKey("mesh_linestring")){
                     
                     try {
-                        // 1. IJK Anfragen für Stützpunkte im Netz ausführen.
+                        // 1. IJK Anfragen für Stuetzpunkte im Netz ausführen.
                         LineString ls = (LineString)new WKTReader().read(this.inputData
                                                                          .get("mesh_linestring")
                                                                          .getValue());
@@ -90,7 +102,13 @@
                         QueryExecutor queryExecutor = QueryExecutorFactory
                                                         .getInstance()
                                                         .getQueryExecutor();
-                        for (int i = 0; i < coords.length; i++){
+
+                        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,
@@ -103,15 +121,72 @@
                                 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
                             }
                         }
-                        // TODO: Make Tablenames and Columns Configurable
-                        IndexBuffer ib = new IndexBuffer(points, "MEDIAN.MESHPOINT.IPOSITION", " MEDIAN.MESHPOINT.JPOSITION" );
-                        String additionWhere = ib.toWhereClause();
-                        log.debug("Additional Where Clause = "+additionWhere);
-                        // 2. Aus diesen Stützpunkten den Resultset generieren.
+
+                        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];
@@ -121,7 +196,6 @@
                         result = queryExecutor.executeQuery(this.queryID,
                                                             addedFilterValues);
                         
-                        
                     } catch (ParseException e) {
                         log.error(e,e);
                     }catch (QueryException e) {

http://dive4elements.wald.intevation.org