changeset 445:f42ed4f10b79

Fixed some bugs and create "Profilschnitt" polygons via configuration. gnv-artifacts/trunk@493 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 30 Dec 2009 23:02:10 +0000
parents 85f48e287fb3
children f5a041000357
files gnv-artifacts/ChangeLog gnv-artifacts/doc/conf/conf.xml gnv-artifacts/src/main/java/de/intevation/gnv/math/ConstantXYDepth.java gnv-artifacts/src/main/java/de/intevation/gnv/math/Interpolation2D.java gnv-artifacts/src/main/java/de/intevation/gnv/math/Interpolation3D.java gnv-artifacts/src/main/java/de/intevation/gnv/math/XYColumn.java gnv-artifacts/src/main/java/de/intevation/gnv/raster/PaletteManager.java gnv-artifacts/src/main/java/de/intevation/gnv/raster/Vectorizer.java gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/verticalcrosssection/VerticalCrossSectionOutputState.java
diffstat 9 files changed, 248 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/gnv-artifacts/ChangeLog	Wed Dec 30 10:35:19 2009 +0000
+++ b/gnv-artifacts/ChangeLog	Wed Dec 30 23:02:10 2009 +0000
@@ -1,3 +1,28 @@
+2009-12-30	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
+
+	* doc/conf/conf.xml: Fixed defect XML
+
+	* src/main/java/de/intevation/gnv/state/profile/verticalcrosssection/VerticalCrossSectionOutputState.java:
+	  Use configuration to generate JFreeChart compatible polygons.
+
+	* src/main/java/de/intevation/gnv/raster/PaletteManager.java:
+	  Add method to access base palette.
+
+	* src/main/java/de/intevation/gnv/raster/Vectorizer.java:
+	  Added logging and new constructor.
+
+	* src/main/java/de/intevation/gnv/math/ConstantXYDepth.java:
+	  "Simulates" DEM with a constant depth.
+
+	* src/main/java/de/intevation/gnv/math/Interpolation2D.java:
+	  Fixed bug with construction of buffer size.
+
+	* src/main/java/de/intevation/gnv/math/Interpolation3D.java:
+	  Some clean ups. New method to calculate max depth.
+
+	* src/main/java/de/intevation/gnv/math/XYColumn.java:
+	  Fixed bug with extrapolation.
+
 2009-12-30	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
 
 	* doc/conf/conf.xml: Added section gnv/vertical-cross-section
--- a/gnv-artifacts/doc/conf/conf.xml	Wed Dec 30 10:35:19 2009 +0000
+++ b/gnv-artifacts/doc/conf/conf.xml	Wed Dec 30 23:02:10 2009 +0000
@@ -420,10 +420,10 @@
             <!-- This section configures the "Profilschnitt" -->
             <samples width="1024" height="768"/>
             <filters>
-                <filter factory="de.intevation.gnv.raster.KernelFilter.GaussFactory" 
+                <filter factory="de.intevation.gnv.raster.KernelFilter$GaussFactory" 
                         sigma="1"
                         radius="5"/>
-            <filters>
+            </filters>
         </vertical-cross-section>
     </gnv>
     <ehcache>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/math/ConstantXYDepth.java	Wed Dec 30 23:02:10 2009 +0000
@@ -0,0 +1,24 @@
+package de.intevation.gnv.math;
+
+import com.vividsolutions.jts.geom.Coordinate;
+
+/**
+ * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
+ */
+public class ConstantXYDepth
+implements   XYDepth
+{
+    protected double depth;
+
+    public ConstantXYDepth() {
+    }
+
+    public ConstantXYDepth(double depth) {
+        this.depth = depth;
+    }
+
+    public double depth(Coordinate coordinate) {
+        return depth;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/math/Interpolation2D.java	Wed Dec 30 10:35:19 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/math/Interpolation2D.java	Wed Dec 30 23:02:10 2009 +0000
@@ -39,15 +39,15 @@
             Point2d p = points.get(k);
 
             ArrayList<Point2d> jList = jMap.get(p.j);
-            ArrayList<Point2d> iList = jMap.get(p.i);
+            ArrayList<Point2d> iList = iMap.get(p.i);
 
             if (jList == null) {
-                iMap.put(p.j, jList = new ArrayList<Point2d>());
+                jMap.put(p.j, jList = new ArrayList<Point2d>());
             }
             jList.add(p);
 
             if (iList == null) {
-                jMap.put(p.i, iList = new ArrayList<Point2d>());
+                iMap.put(p.i, iList = new ArrayList<Point2d>());
             }
             iList.add(p);
         }
@@ -58,7 +58,7 @@
         for (ArrayList<Point2d> v: jMap.values()) {
             Collections.sort(v, Point2d.Y_COMPARATOR);
             for (int i = 1, L = v.size(); i < L; ++i) {
-                double dy = Math.abs(v.get(i).x - v.get(i-1).x);
+                double dy = Math.abs(v.get(i).y - v.get(i-1).y);
                 if (dy > dyMax) {
                     dyMax = dy;
                 }
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/math/Interpolation3D.java	Wed Dec 30 10:35:19 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/math/Interpolation3D.java	Wed Dec 30 23:02:10 2009 +0000
@@ -2,8 +2,13 @@
 
 import java.util.List;
 import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Collections;
 
+import java.io.Serializable;
+
+import java.awt.Dimension;
+
 import com.vividsolutions.jts.geom.Coordinate;
 import com.vividsolutions.jts.geom.Envelope;
 
@@ -11,7 +16,11 @@
 
 import org.apache.log4j.Logger;
 
+/**
+ * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
+ */
 public class Interpolation3D
+implements   Serializable
 {
     private static Logger log = Logger.getLogger(Interpolation3D.class);
 
@@ -28,6 +37,10 @@
         this(DEFAULT_WIDTH, DEFAULT_HEIGHT);
     }
 
+    public Interpolation3D(Dimension size) {
+        this(size.width, size.height);
+    }
+
     public Interpolation3D(int width, int height) {
         this.width  = width;
         this.height = height;
@@ -49,6 +62,16 @@
         return depths;
     }
 
+    public double getMaxDepth() {
+        double maxDepth = Double.MAX_VALUE;
+        for (int i = depths!=null?depths.length-1:0; i >= 0; --i) {
+            if (!Double.isNaN(depths[i]) && depths[i] < maxDepth) {
+                maxDepth = depths[i];
+            }
+        }
+        return maxDepth;
+    }
+
     public boolean interpolate(
         List<? extends Coordinate> path,
         List<? extends XYColumn>   points,
@@ -114,13 +137,10 @@
             return false;
         }
 
-        if (debug) {
-            log.debug("max depth found: " + maxDepth);
-        }
-
         double cellHeight = Math.abs(maxDepth)/height;
 
         if (debug) {
+            log.debug("max depth found: " + maxDepth);
             log.debug("cell size: " + cellWidth + " x " + cellHeight);
         }
 
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/math/XYColumn.java	Wed Dec 30 10:35:19 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/math/XYColumn.java	Wed Dec 30 23:02:10 2009 +0000
@@ -65,7 +65,12 @@
 
     public boolean prepare(XYDepth xyDepth) {
         int N = values.size();
-        if (curve == null && N > 0) {
+        if (curve == null) {
+            if (N == 0) {
+                log.error("no points for interpolation");
+                return false;
+            }
+
             if (N == 1) {
                 // only one value -> constant function
                 curve = new ConstantFunction(values.get(0).v);
@@ -78,12 +83,14 @@
                 HeightValue first = values.get(0);
                 if (first.z < 0d) {
                     values.add(0, new HeightValue(0d, first.z, first.k-1));
+                    ++N;
                 }
 
                 // if there is no value at depth repeat last value
                 HeightValue last = values.get(N-1);
                 if (last.z > depth) {
                     values.add(new HeightValue(depth, last.z, last.k+1));
+                    ++N;
                 }
                 N = values.size();
                 if (N < 3) { // interpolate linear
@@ -97,7 +104,7 @@
                     double [] z = new double[N];
                     double [] v = new double[N];
                     for (int i = 0; i < N; ++i) {
-                        HeightValue h = values.get(i);
+                        HeightValue h = values.get(N-1-i);
                         z[i] = h.z;
                         v[i] = h.v;
                     }
@@ -111,10 +118,6 @@
                 }
             }
         }
-        else {
-            log.error("no points for interpolation");
-            return false;
-        }
         return true;
     }
 
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/raster/PaletteManager.java	Wed Dec 30 10:35:19 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/raster/PaletteManager.java	Wed Dec 30 23:02:10 2009 +0000
@@ -34,6 +34,14 @@
         return description;
     }
 
+    public String getName() {
+        return name;
+    }
+
+    public Palette getBase() {
+        return base;
+    }
+
     public Palette getLevel(int n) {
         if (n < 2) {
             return base;
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/raster/Vectorizer.java	Wed Dec 30 10:35:19 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/raster/Vectorizer.java	Wed Dec 30 23:02:10 2009 +0000
@@ -7,11 +7,15 @@
 import gnu.trove.TIntStack;
 import gnu.trove.TIntObjectHashMap;
 
+import org.apache.log4j.Logger;
+
 /**
  * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
  */
 public class Vectorizer
 {
+    private static Logger log = Logger.getLogger(Vectorizer.class);
+
     public interface RingsHandler {
 
         void handleRings(
@@ -150,7 +154,11 @@
     }
 
     public Vectorizer(int [] raster, int width) {
-        this();
+        this(true, raster, width);
+    }
+
+    public Vectorizer(boolean simplify, int [] raster, int width) {
+        this(simplify);
         this.raster = raster;
         this.width  = width;
     }
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/verticalcrosssection/VerticalCrossSectionOutputState.java	Wed Dec 30 10:35:19 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/verticalcrosssection/VerticalCrossSectionOutputState.java	Wed Dec 30 23:02:10 2009 +0000
@@ -17,6 +17,8 @@
 import java.util.Arrays;
 import java.util.List;
 
+import java.awt.Dimension;
+
 import org.apache.log4j.Logger;
 
 import org.jfree.chart.ChartTheme;
@@ -30,6 +32,8 @@
 
 import de.intevation.artifacts.CallContext;
 
+import de.intevation.gnv.artifacts.context.GNVArtifactContext;
+
 import de.intevation.gnv.artifacts.cache.CacheFactory;
 
 import de.intevation.gnv.chart.Chart;
@@ -49,6 +53,9 @@
 import de.intevation.gnv.math.HeightValue;
 import de.intevation.gnv.math.XYColumn;
 import de.intevation.gnv.math.IJKey;
+import de.intevation.gnv.math.LinearMetrics;
+import de.intevation.gnv.math.Interpolation3D;
+import de.intevation.gnv.math.ConstantXYDepth;
 
 import de.intevation.gnv.state.InputData;
 
@@ -59,12 +66,23 @@
 import de.intevation.gnv.statistics.Statistics;
 import de.intevation.gnv.statistics.VerticalProfileStatistics;
 
+import de.intevation.gnv.utils.DistanceCalculator;
 import de.intevation.gnv.utils.WKTUtils;
 import de.intevation.gnv.utils.StringUtils;
 
+import de.intevation.gnv.raster.Filter;
+import de.intevation.gnv.raster.PaletteManager;
+import de.intevation.gnv.raster.Palette;
+import de.intevation.gnv.raster.Raster;
+import de.intevation.gnv.raster.PolygonDatasetProducer;
+import de.intevation.gnv.raster.Vectorizer;
+
+import de.intevation.gnv.jfreechart.PolygonDataset;
+
 /**
- * @author Tim Englich <tim.englich@intevation.de>
- * 
+ * @author Tim Englich         (tim.englich@intevation.de)
+ * @author Ingo Weinzierl      (iweinzierl@intevation.de)
+ * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
  */
 public class VerticalCrossSectionOutputState extends TimeSeriesOutputState {
 
@@ -159,14 +177,135 @@
         return obj;
     }
 
+    private static Dimension getRasterSize(CallContext callContext) {
+        GNVArtifactContext context = 
+            (GNVArtifactContext)callContext.globalContext();
+        Dimension size = (Dimension)context.get(
+            GNVArtifactContext.VERTICAL_CROSS_SECTION_SAMPLES_KEY);
+        return size != null
+            ? size
+            : GNVArtifactContext.DEFAULT_VERTICAL_CROSS_SECTION_SAMPLES;
+    }
+
+    private static List<Filter.Factory> getFilterFactories(CallContext callContext) {
+        GNVArtifactContext context = 
+            (GNVArtifactContext)callContext.globalContext();
+        List<Filter.Factory> factories = (List<Filter.Factory>)context.get(
+            GNVArtifactContext.VERTICAL_CROSS_SECTION_FILTER_FACTORIES_KEY);
+        return factories != null
+            ? factories
+            : new ArrayList<Filter.Factory>();
+    }
+
+    private static Map<Integer, PaletteManager> getPalettes(
+        CallContext callContext
+    ) {
+        GNVArtifactContext context = 
+            (GNVArtifactContext)callContext.globalContext();
+        Map<Integer, PaletteManager> palettes =
+            (Map<Integer, PaletteManager>)context.get(
+                GNVArtifactContext.PALETTES_KEY);
+        return palettes != null
+            ? palettes
+            : new HashMap<Integer, PaletteManager>();
+    }
+
+    public static final double EPSILON = 1e-5d;
 
     protected Object process(
         List<Coordinate>    path,
         AttributedXYColumns columns,
         CallContext         callContext
     ) {
+        Integer parameterId =
+            (Integer)columns.getAttribute("GROUP1"); // XXX: hardcoded
 
-        // TODO Implement me
+        if (parameterId == null) {
+            log.error("missing parameter id");
+            return null;
+        }
+
+        Map<Integer, PaletteManager> paletteManagers =
+            getPalettes(callContext);
+
+        PaletteManager paletteManager = paletteManagers.get(parameterId);
+
+        if (paletteManager == null) {
+            log.error("no palette found for parameter id " + parameterId);
+            return null;
+        }
+
+        boolean debug = log.isDebugEnabled();
+
+        if (debug) {
+            log.debug("using palette '" + paletteManager.getName() + "'");
+        }
+
+        Dimension            rasterSize      = getRasterSize(callContext);
+        List<Filter.Factory> filterFactories = getFilterFactories(callContext);
+        Interpolation3D      interpolation   = new Interpolation3D(rasterSize);
+
+        double distance = WKTUtils.toKM(
+            DistanceCalculator.calculateDistance(path));
+
+        if (distance < EPSILON) {
+            log.warn("distance too short for interpolation");
+            return null;
+        }
+
+        boolean success = interpolation.interpolate(
+            path,
+            columns.getXYColumns(),
+            0d,
+            distance,
+            LinearMetrics.INSTANCE,
+            new ConstantXYDepth(-42d)); // TODO: Use DEM here!!
+
+        if (!success) {
+            log.warn("interpolation failed");
+            return null;
+        }
+
+        // Do the post processing
+        Raster raster = new Raster(
+            interpolation.getRaster(),
+            rasterSize.width);
+
+        for (Filter.Factory factory: filterFactories) {
+            raster = factory.create().filter(raster);
+        }
+
+        if (debug) {
+            log.debug("to indexed raster");
+        }
+
+        // scan for regions with base palette
+        Palette base = paletteManager.getBase();
+
+        int [] intRaster = raster.toIndexed(base);
+
+        // produce JFreeChart compatible polygons
+
+        if (debug) {
+            log.debug("vectorize indexed raster");
+        }
+
+        PolygonDatasetProducer pdsp = new PolygonDatasetProducer(
+            0, 0,
+            distance, interpolation.getMaxDepth());
+
+        Vectorizer vectorizer = new Vectorizer(
+            intRaster, rasterSize.width);
+
+        int numRegions = vectorizer.process(pdsp);
+
+        PolygonDataset pds = pdsp.getPolygonDataset();
+
+        if (debug) {
+            log.debug("number of regions: " + numRegions);
+            log.debug("number of series: " + pds.getSeriesCount());
+        }
+
         return null;
     }
 
@@ -222,7 +361,7 @@
             if (col == null) {
                 Coordinate coord = WKTUtils.toCoordinate(result.getString(sIdx));
                 if (coord == null) coord = new Coordinate();
-                col = new XYColumn(coord.x, coord.z, i, j);
+                col = new XYColumn(coord.x, coord.y, i, j);
                 map.put(key, col);
             }
 

http://dive4elements.wald.intevation.org