# HG changeset patch # User Sascha L. Teichmann # Date 1260890061 0 # Node ID 25e4724aa5043797af85d90bf6881cb86a087920 # Parent 3eee1369c79bd56dd6b9b1a730ce296213caad2a Fill (i, j)-gaps when building index buffer. gnv-artifacts/trunk@430 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 3eee1369c79b -r 25e4724aa504 gnv-artifacts/ChangeLog --- a/gnv-artifacts/ChangeLog Tue Dec 15 14:55:42 2009 +0000 +++ b/gnv-artifacts/ChangeLog Tue Dec 15 15:14:21 2009 +0000 @@ -1,3 +1,17 @@ +2009-12-15 Sascha L. Teichmann + + * src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java: + If a few (i, j) values are not available (gaps in the grid) try + to fill the holes with guessing the values by the ones which could + be fetched. We are using a componentwise linear function here. + This is surely slightly wrong because world coordinates are + in WGS84 which is ellipsoid in nature. TODO: Look at the errors + and if needed compensate them by using cubic polynonial or ellipsoid + function terms. + + * src/main/java/de/intevation/gnv/math/LinearFunction.java: New. + Linear function to be used in curve fitting process. + 2009-12-15 Tim Englich * doc/conf/queries.properties: @@ -16,9 +30,11 @@ math api. 2009-12-15 Tim Englich -Added the Unit of the Parameter to the Query for Parameters in - TimeSeries. Now teh Unit will be displaied in the Combobox and - in the Diagramm-Axis-Description. + + Added the Unit of the Parameter to the Query for Parameters in + TimeSeries. Now teh Unit will be displaied in the Combobox and + in the Diagramm-Axis-Description. + * src/main/resources/lang/artifactMessages*.properties: Added the name Productname for "horizontale Schnittprofile". to the Resources so that it could be displaied properly in the GUI diff -r 3eee1369c79b -r 25e4724aa504 gnv-artifacts/src/main/java/de/intevation/gnv/math/LinearFunction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/math/LinearFunction.java Tue Dec 15 15:14:21 2009 +0000 @@ -0,0 +1,30 @@ +package de.intevation.gnv.math; + +import org.apache.commons.math.optimization.fitting.ParametricRealFunction; + +import org.apache.commons.math.FunctionEvaluationException; + +/** + * @author Sascha L. Teichmann + */ +public class LinearFunction +implements ParametricRealFunction +{ + public static final LinearFunction INSTANCE = new LinearFunction(); + + public LinearFunction() { + } + + public double value(double x, double [] parameters) + throws FunctionEvaluationException + { + return x*parameters[0] + parameters[1]; + } + + public double [] gradient(double x, double [] parameters) + throws FunctionEvaluationException + { + return new double [] { x, 1f }; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: diff -r 3eee1369c79b -r 25e4724aa504 gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java --- 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 * @@ -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) {