# HG changeset patch # User Sascha L. Teichmann # Date 1262214130 0 # Node ID f42ed4f10b798325c686acb2e930006732084266 # Parent 85f48e287fb3fcd296097833c4c9d1f8ae4ba3af Fixed some bugs and create "Profilschnitt" polygons via configuration. gnv-artifacts/trunk@493 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 85f48e287fb3 -r f42ed4f10b79 gnv-artifacts/ChangeLog --- 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 + + * 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 * doc/conf/conf.xml: Added section gnv/vertical-cross-section diff -r 85f48e287fb3 -r f42ed4f10b79 gnv-artifacts/doc/conf/conf.xml --- 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 @@ - - + diff -r 85f48e287fb3 -r f42ed4f10b79 gnv-artifacts/src/main/java/de/intevation/gnv/math/ConstantXYDepth.java --- /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: diff -r 85f48e287fb3 -r f42ed4f10b79 gnv-artifacts/src/main/java/de/intevation/gnv/math/Interpolation2D.java --- 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 jList = jMap.get(p.j); - ArrayList iList = jMap.get(p.i); + ArrayList iList = iMap.get(p.i); if (jList == null) { - iMap.put(p.j, jList = new ArrayList()); + jMap.put(p.j, jList = new ArrayList()); } jList.add(p); if (iList == null) { - jMap.put(p.i, iList = new ArrayList()); + iMap.put(p.i, iList = new ArrayList()); } iList.add(p); } @@ -58,7 +58,7 @@ for (ArrayList 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; } diff -r 85f48e287fb3 -r f42ed4f10b79 gnv-artifacts/src/main/java/de/intevation/gnv/math/Interpolation3D.java --- 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 path, List 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); } diff -r 85f48e287fb3 -r f42ed4f10b79 gnv-artifacts/src/main/java/de/intevation/gnv/math/XYColumn.java --- 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; } diff -r 85f48e287fb3 -r f42ed4f10b79 gnv-artifacts/src/main/java/de/intevation/gnv/raster/PaletteManager.java --- 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; diff -r 85f48e287fb3 -r f42ed4f10b79 gnv-artifacts/src/main/java/de/intevation/gnv/raster/Vectorizer.java --- 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; } diff -r 85f48e287fb3 -r f42ed4f10b79 gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/verticalcrosssection/VerticalCrossSectionOutputState.java --- 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 - * + * @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 getFilterFactories(CallContext callContext) { + GNVArtifactContext context = + (GNVArtifactContext)callContext.globalContext(); + List factories = (List)context.get( + GNVArtifactContext.VERTICAL_CROSS_SECTION_FILTER_FACTORIES_KEY); + return factories != null + ? factories + : new ArrayList(); + } + + private static Map getPalettes( + CallContext callContext + ) { + GNVArtifactContext context = + (GNVArtifactContext)callContext.globalContext(); + Map palettes = + (Map)context.get( + GNVArtifactContext.PALETTES_KEY); + return palettes != null + ? palettes + : new HashMap(); + } + + public static final double EPSILON = 1e-5d; protected Object process( List 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 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 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); }