tim@352: /** tim@352: * tim@352: */ tim@352: package de.intevation.gnv.state.profile.horizontal; tim@352: tim@352: import java.util.ArrayList; tim@352: import java.util.Arrays; tim@352: import java.util.Collection; tim@352: import java.util.List; tim@352: tim@352: import org.apache.log4j.Logger; tim@352: import org.w3c.dom.Node; tim@352: tim@352: import com.vividsolutions.jts.geom.Coordinate; tim@352: import com.vividsolutions.jts.geom.LineString; tim@352: import com.vividsolutions.jts.io.ParseException; tim@352: import com.vividsolutions.jts.io.WKTReader; tim@352: tim@352: import de.intevation.artifactdatabase.Config; sascha@357: tim@352: import de.intevation.gnv.artifacts.cache.CacheFactory; sascha@357: tim@352: import de.intevation.gnv.geobackend.base.Result; tim@352: import de.intevation.gnv.geobackend.base.query.QueryExecutor; tim@352: import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory; tim@352: import de.intevation.gnv.geobackend.base.query.exception.QueryException; tim@352: import de.intevation.gnv.geobackend.sde.datasources.ResultSet; sascha@357: tim@352: import de.intevation.gnv.utils.IndexBuffer; tim@352: sascha@357: import de.intevation.gnv.math.LinearFunction; sascha@357: sascha@357: import org.apache.commons.math.optimization.fitting.CurveFitter; sascha@357: sascha@357: import org.apache.commons.math.optimization.general.GaussNewtonOptimizer; sascha@357: import org.apache.commons.math.optimization.OptimizationException; sascha@357: sascha@357: import org.apache.commons.math.FunctionEvaluationException; sascha@357: tim@352: /** tim@352: * @author Tim Englich tim@352: * tim@352: */ tim@352: public class HorizontalProfileMeshCrossOutputState extends tim@352: HorizontalProfileOutputState { tim@352: tim@352: /** tim@352: * tim@352: */ tim@352: private static final long serialVersionUID = 2205958041745637263L; tim@352: tim@352: /** tim@352: * the logger, used to log exceptions and additonaly information tim@352: */ tim@352: private static Logger log = tim@352: Logger.getLogger(HorizontalProfileMeshCrossOutputState.class); tim@352: tim@352: tim@352: private String ijkQueryID = null; tim@352: tim@352: /** tim@352: * Constructor tim@352: */ tim@352: public HorizontalProfileMeshCrossOutputState() { tim@352: super(); tim@352: } tim@352: tim@352: /** tim@352: * @see de.intevation.gnv.state.timeseries.TimeSeriesOutputState#setup(org.w3c.dom.Node) tim@352: */ tim@352: @Override tim@352: public void setup(Node configuration) { tim@352: super.setup(configuration); tim@352: this.ijkQueryID = Config.getStringXPath(configuration,"queryID-ijk"); tim@352: tim@352: } tim@352: tim@352: @Override tim@352: protected Collection getChartResult(String uuid) { tim@352: log.debug("OutputStateBase.getChartResult"); tim@352: Collection result = null; tim@352: if (CacheFactory.getInstance().isInitialized()) { tim@352: String key = uuid + super.getID(); tim@352: log.debug("Hash for Queryelements: " + key); tim@352: net.sf.ehcache.Element value = CacheFactory.getInstance().getCache().get(key); tim@352: if (value != null) { tim@352: result = (Collection) (value.getObjectValue()); tim@352: }else{ tim@352: tim@352: if (this.inputData.containsKey("mesh_linestring")){ tim@352: tim@352: try { sascha@357: // 1. IJK Anfragen für Stuetzpunkte im Netz ausführen. tim@352: LineString ls = (LineString)new WKTReader().read(this.inputData tim@352: .get("mesh_linestring") tim@352: .getValue()); tim@352: Coordinate[] coords = ls.getCoordinates(); tim@352: tim@352: List points = new ArrayList(coords.length); tim@352: tim@352: String meshid = this.inputData.get("meshid").getValue(); tim@352: QueryExecutor queryExecutor = QueryExecutorFactory tim@352: .getInstance() tim@352: .getQueryExecutor(); sascha@357: sascha@357: ArrayList missingPoints = new ArrayList(); sascha@357: sascha@357: String additionWhere = "TRUE"; sascha@357: sascha@357: for (int i = 0; i < coords.length; i++) { sascha@357: tim@352: String wkt = "POINT( "+coords[i].x+" "+coords[i].y+" )"; tim@352: tim@352: result = queryExecutor.executeQuery(this.ijkQueryID, tim@352: new String[]{meshid,wkt}); tim@352: if (!result.isEmpty()){ tim@352: Result resultValue = result.iterator().next(); tim@352: int iPos = resultValue.getInteger(1); tim@352: int jPos = resultValue.getInteger(0); tim@352: log.debug("Found Pos "+iPos+"/"+jPos +" for "+wkt); tim@352: points.add(i, new java.awt.Point(iPos,jPos)); tim@352: }else{ tim@352: log.debug("No i/j Pos found for "+wkt); sascha@357: missingPoints.add(new Object [] { Integer.valueOf(i), coords[i] }); tim@352: points.add(i, null); tim@352: // Special Case no i,j found for Coordinate tim@352: } tim@352: } sascha@357: sascha@357: if (missingPoints.size() == coords.length) { sascha@357: log.debug("cannot create index buffer"); sascha@357: } sascha@357: else { // generate index filter sascha@357: boolean remainsMissingPoints = !missingPoints.isEmpty(); sascha@357: sascha@357: if (remainsMissingPoints) { sascha@357: // try to guess the missing (i, j) sascha@357: CurveFitter iFitter = new CurveFitter(new GaussNewtonOptimizer(true)); sascha@357: CurveFitter jFitter = new CurveFitter(new GaussNewtonOptimizer(true)); sascha@357: sascha@357: for (int i = 0, N = points.size(); i < N; ++i) { sascha@357: java.awt.Point p = (java.awt.Point)points.get(i); sascha@357: if (p != null) { sascha@357: Coordinate coord = coords[i]; sascha@357: iFitter.addObservedPoint(coord.x, p.x); sascha@357: jFitter.addObservedPoint(coord.y, p.y); sascha@357: } sascha@357: } sascha@357: try { sascha@357: // XXX: Assumption: (i, j) are created by componentwise linear function. sascha@357: // This is surely not correct because (x, y) are in a ellipsoid projection. sascha@357: // TODO: use ellipsoid functions and fit with Levenberg Marquardt. sascha@357: double [] iParams = iFitter.fit( sascha@357: LinearFunction.INSTANCE, new double [] { 1d, 1d }); sascha@357: sascha@357: double [] jParams = jFitter.fit( sascha@357: LinearFunction.INSTANCE, new double [] { 1d, 1d }); sascha@357: sascha@357: for (int i = missingPoints.size()-1; i >= 0; --i) { sascha@357: Object [] a = (Object [])missingPoints.get(i); sascha@357: Coordinate coord = (Coordinate)a[1]; sascha@357: int pi = (int)Math.round(iParams[0]*coord.x + iParams[1]); sascha@357: int pj = (int)Math.round(jParams[0]*coord.y + jParams[1]); sascha@357: points.set( sascha@357: ((Integer)a[0]).intValue(), sascha@357: new java.awt.Point(pi, pj)); sascha@357: } sascha@357: sascha@357: remainsMissingPoints = false; // we filled the gaps sascha@357: } sascha@357: catch (FunctionEvaluationException fee) { sascha@357: log.error(fee); sascha@357: } sascha@357: catch (OptimizationException oe) { sascha@357: log.error(oe); sascha@357: } sascha@357: } sascha@357: sascha@357: if (!remainsMissingPoints) { sascha@357: // TODO: Make Tablenames and Columns Configurable sascha@357: IndexBuffer ib = new IndexBuffer( sascha@357: points, sascha@357: "MEDIAN.MESHPOINT.IPOSITION", sascha@357: "MEDIAN.MESHPOINT.JPOSITION" ); sascha@357: additionWhere = ib.toWhereClause(); sascha@357: log.debug("Additional Where Clause = "+additionWhere); sascha@357: // 2. Aus diesen Stuetzpunkten den Resultset generieren. sascha@357: } sascha@357: } // if generate index filter tim@352: tim@352: String[] filterValues = this.generateFilterValuesFromInputData(); tim@352: String[] addedFilterValues = new String[filterValues.length+1]; tim@352: System.arraycopy(filterValues, 0, addedFilterValues, 0, filterValues.length); tim@352: addedFilterValues[filterValues.length] = additionWhere; tim@352: tim@352: result = queryExecutor.executeQuery(this.queryID, tim@352: addedFilterValues); tim@352: tim@352: } catch (ParseException e) { tim@352: log.error(e,e); tim@352: }catch (QueryException e) { tim@352: log.error(e,e); tim@352: } tim@352: }else{ tim@352: // TODO: definieren was passiert wenn kein linestring vorhanden ist. tim@352: } tim@352: tim@352: if (CacheFactory.getInstance().isInitialized()) { tim@352: CacheFactory.getInstance().getCache().put(new net.sf.ehcache.Element(key, result)); tim@352: } tim@352: tim@352: } tim@352: } tim@352: return result; tim@352: } tim@352: tim@352: tim@352: tim@352: }