# HG changeset patch # User Ingo Weinzierl # Date 1261411024 0 # Node ID c6a287398379548bdf9acd3a48df819d226b233f # Parent 1e192ea34e80eb8adb97aef0dbb69964a80db683 Outsourcing of some methods for preparing results for chart creation. gnv-artifacts/trunk@468 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 1e192ea34e80 -r c6a287398379 gnv-artifacts/ChangeLog --- a/gnv-artifacts/ChangeLog Mon Dec 21 15:28:33 2009 +0000 +++ b/gnv-artifacts/ChangeLog Mon Dec 21 15:57:04 2009 +0000 @@ -1,3 +1,9 @@ +2009-12-21 Ingo Weinzierl + + * src/main/java/de/intevation/gnv/utils/WKTUtils.java + src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java: + Outsourcing of some methods to prepare results for chart creation. + 2009-12-21 Sascha L. Teichmann * doc/conf/palette/flow-velocity.xml: diff -r 1e192ea34e80 -r c6a287398379 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 Mon Dec 21 15:28:33 2009 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontal/HorizontalProfileMeshCrossOutputState.java Mon Dec 21 15:57:04 2009 +0000 @@ -3,21 +3,13 @@ */ package de.intevation.gnv.state.profile.horizontal; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.List; import java.util.Locale; import org.apache.log4j.Logger; 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; import de.intevation.artifactdatabase.Config; @@ -27,32 +19,11 @@ import de.intevation.gnv.chart.ChartLabels; import de.intevation.gnv.chart.HorizontalCrossProfileChart; -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; - -import org.apache.commons.math.optimization.general.GaussNewtonOptimizer; -import org.apache.commons.math.optimization.OptimizationException; - -import org.apache.commons.math.FunctionEvaluationException; +import de.intevation.gnv.utils.WKTUtils; import org.jfree.chart.ChartTheme; @@ -155,115 +126,13 @@ 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 points = new ArrayList(coords.length); - - String meshid = this.inputData.get("meshid").getValue(); - QueryExecutor queryExecutor = QueryExecutorFactory - .getInstance() - .getQueryExecutor(); - - ArrayList missingPoints = new ArrayList(); - - String additionWhere = "FEATUREID=FEATUREID"; - - for (int i = 0; i < coords.length; i++) { - - String wkt = toWKT(coords[i]); - - 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 = process( - Arrays.asList(coords), - queryExecutor.executeQuery( - this.queryID, - addedFilterValues)); - + result = WKTUtils.worldCoordinatesToIndex( + result, + inputData, + ijkQueryID, + queryID, + generateFilterValuesFromInputData() + ); } catch (ParseException e) { log.error(e,e); }catch (QueryException e) { @@ -290,238 +159,4 @@ return subtitle; } - - private static final String [] COLUMN_BLACKLIST = { - "MEDIAN.MESHPOINT.JPOSITION", - "MEDIAN.MESHPOINT.IPOSITION" - }; - - 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) { - String oa = a.getString(indices[i]); - String ob = b.getString(indices[i]); - - if (oa == null && ob == null) { - continue; - } - - if (oa == null || ob == null) { - return true; - } - - if (!oa.equals(ob)) { - if (log.isDebugEnabled()) { - log.debug("+++++++++++++++ differs ++++++++++++++"); - log.debug(" " + oa + " != " + 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; - private boolean lastWasSuccess; - - public SectionHandler() { - } - - public SectionHandler( - List path, - Collection output, - ResultDescriptor descriptor - ) { - this.path = path; - this.output = output; - this.descriptor = descriptor; - points = new ArrayList(); - lastWasSuccess = true; - } - - public void finish() { - if (!points.isEmpty()) { - double distance = toKM( - DistanceCalculator.calculateDistance(path)); - - if (distance > EPSILON) { - - Interpolation2D.interpolate( - path, - points, - 0d, - distance, - INTERPOLATION_STEPS, - LinearMetrics.INSTANCE, - this); - } - - points.clear(); - } - lastWasSuccess = true; - } - - 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, boolean success) { - 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")) { - if (success) { - result.addColumnValue(j, Double.valueOf(coordinate.z)); - } - else if (lastWasSuccess) { - // only insert null if last was valid. - // This prevents flooding the result set with nulls - // if interpolating over a large gap. - result.addColumnValue(j, null); - } - } - else { - result.addColumnValue(j, prototyp.getObject(i)); - } - ++j; - } - output.add(result); - lastWasSuccess = success; - } - } // 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 EPSILON = 1e-5d; - public static final int INTERPOLATION_STEPS = - Integer.getInteger("interpolation.steps", 500).intValue(); - - 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 - ) { - log.debug("------ number of points before processing: " + input.size()); - 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(); - } - - log.debug("------ number of points after processing: " + output.size()); - - return output; - } } diff -r 1e192ea34e80 -r c6a287398379 gnv-artifacts/src/main/java/de/intevation/gnv/utils/WKTUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/utils/WKTUtils.java Mon Dec 21 15:57:04 2009 +0000 @@ -0,0 +1,396 @@ +package de.intevation.gnv.utils; + +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; + +import de.intevation.gnv.geobackend.base.DefaultResult; +import de.intevation.gnv.geobackend.base.DefaultResultDescriptor; +import de.intevation.gnv.geobackend.base.Result; +import de.intevation.gnv.geobackend.base.ResultDescriptor; +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.math.Interpolation2D; +import de.intevation.gnv.math.LinearFunction; +import de.intevation.gnv.math.LinearMetrics; +import de.intevation.gnv.math.Point2d; +import de.intevation.gnv.state.InputData; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.apache.commons.math.optimization.OptimizationException; +import org.apache.commons.math.optimization.fitting.CurveFitter; +import org.apache.commons.math.optimization.general.GaussNewtonOptimizer; +import org.apache.commons.math.FunctionEvaluationException; + +import org.apache.log4j.Logger; + +public abstract class WKTUtils { + + private static Logger log = Logger.getLogger(WKTUtils.class); + + private static final String [] DIFF_COLUMS = { + "GROUP1", + "GROUP2", + "GROUP3" + }; + + private static final String [] COLUMN_BLACKLIST = { + "MEDIAN.MESHPOINT.JPOSITION", + "MEDIAN.MESHPOINT.IPOSITION" + }; + + public static final double NAUTICAL_MILE = 1852.216d; + public static final double KILOMETER = 1000d; + + public static final double EPSILON = 1e-5d; + public static final int INTERPOLATION_STEPS = + Integer.getInteger("interpolation.steps", 500).intValue(); + + + public static final class SectionHandler + implements Interpolation2D.Consumer + { + private ArrayList points; + private List path; + private Collection output; + private Result prototyp; + private ResultDescriptor descriptor; + private boolean lastWasSuccess; + + public SectionHandler() { + } + + public SectionHandler( + List path, + Collection output, + ResultDescriptor descriptor + ) { + this.path = path; + this.output = output; + this.descriptor = descriptor; + points = new ArrayList(); + lastWasSuccess = true; + } + + public void finish() { + if (!points.isEmpty()) { + double distance = toKM( + DistanceCalculator.calculateDistance(path)); + + if (distance > EPSILON) { + + Interpolation2D.interpolate( + path, + points, + 0d, + distance, + INTERPOLATION_STEPS, + LinearMetrics.INSTANCE, + this); + } + + points.clear(); + } + lastWasSuccess = true; + } + + 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, boolean success) { + 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, OutputUtils.toWKT(coordinate)); + } + else if (colname.equals("YORDINATE")) { + if (success) { + result.addColumnValue(j, Double.valueOf(coordinate.z)); + } + else if (lastWasSuccess) { + // only insert null if last was valid. + // This prevents flooding the result set with nulls + // if interpolating over a large gap. + result.addColumnValue(j, null); + } + } + else { + result.addColumnValue(j, prototyp.getObject(i)); + } + ++j; + } + output.add(result); + lastWasSuccess = success; + } + } + + + 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) { + String oa = a.getString(indices[i]); + String ob = b.getString(indices[i]); + + if (oa == null && ob == null) { + continue; + } + + if (oa == null || ob == null) { + return true; + } + + if (!oa.equals(ob)) { + if (log.isDebugEnabled()) { + log.debug("+++++++++++++++ differs ++++++++++++++"); + log.debug(" " + oa + " != " + ob); + } + return true; + } + } + return false; + } + + public static Collection process( + List path, + Collection input + ) { + log.debug("------ number of points before processing: " + input.size()); + 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(); + } + + log.debug("------ number of points after processing: " + output.size()); + + return output; + } + + + public static Coordinate toCoordinate(String shape) { + try { + return ((Point)(new WKTReader().read(shape))).getCoordinate(); + } + catch (ParseException pe) { + log.error(pe); + } + return null; + } + + + public static final double toKM(double distance) { + return (distance * NAUTICAL_MILE) / KILOMETER; + } + + + public static String toWKT(Coordinate coordinate) { + StringBuilder sb = new StringBuilder("POINT("); + sb.append(coordinate.x) + .append(' ') + .append(coordinate.y) + .append(')'); + return sb.toString(); + } + + + public static Collection worldCoordinatesToIndex( + Collection result, + Map inputData, + String ijkQueryID, + String queryID, + String[] filterValues + ) throws ParseException, QueryException + { + // 1. IJK Anfragen für Stuetzpunkte im Netz ausführen. + LineString ls = (LineString)new WKTReader().read( + inputData.get("mesh_linestring").getValue()); + + Coordinate[] coords = ls.getCoordinates(); + + List points = new ArrayList(coords.length); + + String meshid = inputData.get("meshid").getValue(); + QueryExecutor queryExecutor = QueryExecutorFactory + .getInstance() + .getQueryExecutor(); + + ArrayList missingPoints = new ArrayList(); + + String additionWhere = "FEATUREID=FEATUREID"; + + for (int i = 0; i < coords.length; i++) { + + String wkt = toWKT(coords[i]); + + result = queryExecutor.executeQuery(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[] addedFilterValues = new String[filterValues.length+1]; + System.arraycopy(filterValues, 0, addedFilterValues, 0, filterValues.length); + addedFilterValues[filterValues.length] = additionWhere; + + result = process( + Arrays.asList(coords), + queryExecutor.executeQuery( + queryID, + addedFilterValues)); + + return result; + } +}