# HG changeset patch # User Sascha L. Teichmann # Date 1260927139 0 # Node ID 1ab23cd6687078a69d75c0920a1c5848440da022 # Parent aec85d00d82caf0a73296c83ea614d2f1330960e Added result set handling. Needs some testing. gnv-artifacts/trunk@436 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r aec85d00d82c -r 1ab23cd66870 gnv-artifacts/ChangeLog --- a/gnv-artifacts/ChangeLog Tue Dec 15 22:25:53 2009 +0000 +++ b/gnv-artifacts/ChangeLog Wed Dec 16 01:32:19 2009 +0000 @@ -1,3 +1,25 @@ +2009-12-16 Sascha L. Teichmann + + * src/main/java/de/intevation/gnv/utils/DistanceCalculator.java: + Added method to calculate distance of path. + TODO: Move this class into math package and and add + an slerp interpolator so it can be used as a metric inside + the interpolation code. + + * src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java: + Added code to disassemble the incoming result set, interpolate + along a given path and returns an adjusted result set. + The (i, j) got lost on this track because we don't travel along + the main axis of the grid any more. The test for gaps has to be + adjusted because, because the dx/dy on the path depends on how + many steps are made on the way [*]. This is controlled by the system + property 'interpolation.step.width'. It is set in meters + and defaults to 100m. TODO: This should be configurable + in the conf.xml file. + + [*] I opt strongly for integration of the outlier test based gap + detection to overcome this problem. + 2009-12-15 Sascha L. Teichmann * src/main/java/de/intevation/gnv/math/LinearToMap.java: diff -r aec85d00d82c -r 1ab23cd66870 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 22:25:53 2009 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java Wed Dec 16 01:32:19 2009 +0000 @@ -12,7 +12,9 @@ import org.w3c.dom.Node; import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.LineString; + import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKTReader; @@ -20,15 +22,25 @@ import de.intevation.gnv.artifacts.cache.CacheFactory; +import de.intevation.gnv.geobackend.base.DefaultResultDescriptor; +import de.intevation.gnv.geobackend.base.ResultDescriptor; +import de.intevation.gnv.geobackend.base.DefaultResult; import de.intevation.gnv.geobackend.base.Result; + +import de.intevation.gnv.math.Point2d; +import de.intevation.gnv.math.Interpolation2D; + 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.utils.DistanceCalculator; import de.intevation.gnv.math.LinearFunction; +import de.intevation.gnv.math.LinearMetrics; import org.apache.commons.math.optimization.fitting.CurveFitter; @@ -194,6 +206,7 @@ addedFilterValues[filterValues.length] = additionWhere; result = process( + Arrays.asList(coords), queryExecutor.executeQuery( this.queryID, addedFilterValues)); @@ -216,11 +229,209 @@ return result; } - protected Collection process(Collection input) { - // TODO: split by additional parameters, interpolate the - // values, and create a new dummy result set. + private static final String [] COLUMN_BLACKLIST = { + "MEDIAN.MESHPOINT.JPOSITION", + "MEDIAN.MESHPOINT.IPOSITION" + }; - return input; + private static final boolean blacklisted(String column) { + for (int i = 0; i < COLUMN_BLACKLIST.length; ++i) { + if (COLUMN_BLACKLIST.equals(column)) { + return true; + } + } + return false; + } + private static boolean different(Result a, Result b, int [] indices) { + for (int i = 0; i < indices.length; ++i) { + Object oa = a.getObject(indices[i]); + Object ob = b.getObject(indices[i]); + if ((oa == null && ob != null) + || (oa != null && ob == null) + || (oa != null && !oa.equals(ob))) { + return true; + } + } + return false; + } + + private static final String [] DIFF_COLUMS = { + "GROUP1", + "GROUP2", + "GROUP3" + }; + + public static final class SectionHandler + implements Interpolation2D.Consumer + { + private ArrayList points; + private List path; + private Collection output; + private Result prototyp; + private ResultDescriptor descriptor; + + public SectionHandler() { + } + + public SectionHandler( + List path, + Collection output, + ResultDescriptor descriptor + ) { + this.path = path; + this.output = output; + this.descriptor = descriptor; + } + + public void finish() { + if (!points.isEmpty()) { + double distance = toKM( + DistanceCalculator.calculateDistance(path)); + + Interpolation2D.interpolate( + path, + points, + 0d, + distance, + steps(distance), + LinearMetrics.INSTANCE, // XXX: This wrong!!! + this); + + points.clear(); + } + } + + public void setPrototyp(Result prototyp) { + this.prototyp = prototyp; + } + + public void handle(Result result) { + Coordinate coordinate = + toCoordinate(result.getString("SHAPE")); + double value = result.getDouble("YORDINATE"); + int iPos = result.getInteger("MEDIAN.MESHPOINT.JPOSITION"); + int jPos = result.getInteger("MEDIAN.MESHPOINT.JPOSITION"); + Point2d p = new Point2d( + coordinate.x, + coordinate.y, + value, + iPos, jPos); + points.add(p); + } + + public void interpolated(Coordinate coordinate) { + DefaultResult result = new DefaultResult(descriptor); + ResultDescriptor pd = prototyp.getResultDescriptor(); + + int pcolums = pd.getColumnCount(); + for (int i = 0, j = 0; i < pcolums; ++i) { + String colname = pd.getColumnName(i); + if (blacklisted(colname)) { + continue; + } + if (colname.equals("SHAPE")) { + result.addColumnValue(j, toWKT(coordinate)); + } + else if (colname.equals("YORDINATE")) { + result.addColumnValue(j, Double.valueOf(coordinate.z)); + } + ++j; + } + output.add(result); + } + } // class SectionHandler + + public static final double NAUTICAL_MILE = 1852.216d; + public static final double KILOMETER = 1000d; + + public static final double toKM(double distance) { + return (distance * NAUTICAL_MILE) / KILOMETER; + } + + public static final double INTERPOLATION_STEP_WIDTH = + Double.parseDouble(System.getProperty( + "interpolation.step.width", "100")); + + public static int steps(double km) { + return (int)Math.ceil( + Math.max(1d, (km * KILOMETER)/INTERPOLATION_STEP_WIDTH)); + } + + public static Coordinate toCoordinate(String shape) { + try { + return ((Point)(new WKTReader().read(shape))).getCoordinate(); + } + catch (ParseException pe) { + log.error(pe); + } + return null; + } + + public static String toWKT(Coordinate coordinate) { + StringBuilder sb = new StringBuilder("POINT("); + sb.append(coordinate.x) + .append(' ') + .append(coordinate.y) + .append(')'); + return sb.toString(); + } + + protected Collection process( + List path, + Collection input + ) { + ArrayList output = new ArrayList(); + + + Result last = null; + + int [] diffColums = null; + + SectionHandler sectionHandler = null; + + for (Result result: input) { + + if (sectionHandler == null) { + + ResultDescriptor rd = result.getResultDescriptor(); + diffColums = rd.getColumnIndices(DIFF_COLUMS); + int columns = rd.getColumnCount(); + + DefaultResultDescriptor resultDescriptor = + new DefaultResultDescriptor(); + + for (int j = 0; j < columns; ++j) { + String columnName = rd.getColumnName(j); + if (!blacklisted(columnName)) { + resultDescriptor.addColumn( + columnName, + rd.getColumnClassName(j)); + } + } + + sectionHandler = new SectionHandler( + path, + output, + resultDescriptor); + + sectionHandler.setPrototyp(result); + } + + if (last != null && different(last, result, diffColums)) { + sectionHandler.finish(); + sectionHandler.setPrototyp(result); + } + + sectionHandler.handle(result); + + last = result; + } + + if (sectionHandler != null) { + sectionHandler.finish(); + } + + return output; } } diff -r aec85d00d82c -r 1ab23cd66870 gnv-artifacts/src/main/java/de/intevation/gnv/utils/DistanceCalculator.java --- a/gnv-artifacts/src/main/java/de/intevation/gnv/utils/DistanceCalculator.java Tue Dec 15 22:25:53 2009 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/utils/DistanceCalculator.java Wed Dec 16 01:32:19 2009 +0000 @@ -4,6 +4,9 @@ package de.intevation.gnv.utils; import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.geom.Coordinate; + +import java.util.List; /** * @author Tim Englich @@ -22,13 +25,17 @@ } public static double calculateDistance(Point p1, Point p2){ + return calculateDistance(p1.getCoordinate(), p2.getCoordinate()); + } + + public static double calculateDistance(Coordinate p1, Coordinate p2){ double resultValue = 0.0; - double b1 = p1.getY(); - double b2 = p2.getY(); + double b1 = p1.y; + double b2 = p2.y; - double l1 = p1.getX(); - double l2 = p2.getX(); + double l1 = p1.x; + double l2 = p2.x; double F = (b1 + b2) / 2.0; @@ -62,4 +69,16 @@ return resultValue; } + public static final double calculateDistance(List path) { + int N = path.size(); + if (N < 2) { + return 0d; + } + double sum = 0d; + for (int i = 1; i < N; ++i) { + sum += calculateDistance(path.get(i-1), path.get(i)); + } + return sum; + } + }