[Dive4elements-commits] [PATCH] Added experimental Douglas Peuker simplification of cross sections
Wald Commits
scm-commit at wald.intevation.org
Sun Feb 24 17:32:43 CET 2013
# HG changeset patch
# User Sascha L. Teichmann <teichmann at intevation.de>
# Date 1361723392 -3600
# Branch slt-simplify-cross-sections
# Node ID 7bbee0cfc171f756da78b1cf1801869fe4a923c6
# Parent fb4d87274f28ccf3fab8c21704b716bf6e2ce2c8
Added experimental Douglas Peuker simplification of cross sections.
diff -r fb4d87274f28 -r 7bbee0cfc171 flys-backend/src/main/java/de/intevation/flys/importer/Config.java
--- a/flys-backend/src/main/java/de/intevation/flys/importer/Config.java Sun Feb 24 13:03:44 2013 +0100
+++ b/flys-backend/src/main/java/de/intevation/flys/importer/Config.java Sun Feb 24 17:29:52 2013 +0100
@@ -86,6 +86,9 @@
public static final String SKIP_SQ_RELATION =
"flys.backend.importer.skip.sq.relation";
+ public static final Double CROSS_SECTION_SIMPLIFICATION_EPSILON =
+ getDouble("flys.backend.importer.cross.section.simplification.epsilon");
+
public static final Config INSTANCE = new Config();
@@ -99,6 +102,21 @@
: Boolean.getBoolean(SKIP_DEFAULT);
}
+ public static final Double getDouble(String key) {
+ try {
+ String value = System.getProperty(key);
+ return value != null
+ ? Double.valueOf(value)
+ : null;
+ } catch (NumberFormatException nfe) {
+ return null;
+ }
+ }
+
+ public Double getCrossSectionSimplificationEpsilon() {
+ return CROSS_SECTION_SIMPLIFICATION_EPSILON;
+ }
+
public boolean dryRun() {
return getFlag(DRY_RUN);
}
diff -r fb4d87274f28 -r 7bbee0cfc171 flys-backend/src/main/java/de/intevation/flys/importer/ImportRiver.java
--- a/flys-backend/src/main/java/de/intevation/flys/importer/ImportRiver.java Sun Feb 24 13:03:44 2013 +0100
+++ b/flys-backend/src/main/java/de/intevation/flys/importer/ImportRiver.java Sun Feb 24 17:29:52 2013 +0100
@@ -1,23 +1,9 @@
package de.intevation.flys.importer;
-import java.io.File;
-import java.io.IOException;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.log4j.Logger;
-import org.hibernate.Query;
-import org.hibernate.Session;
-import org.hibernate.exception.ConstraintViolationException;
+import de.intevation.artifacts.common.utils.FileTools.HashedFile;
import de.intevation.artifacts.common.utils.FileTools;
-import de.intevation.artifacts.common.utils.FileTools.HashedFile;
+
import de.intevation.flys.importer.parsers.AnnotationClassifier;
import de.intevation.flys.importer.parsers.AnnotationsParser;
import de.intevation.flys.importer.parsers.BedHeightEpochParser;
@@ -39,9 +25,32 @@
import de.intevation.flys.importer.parsers.WaterlevelDifferencesParser;
import de.intevation.flys.importer.parsers.WaterlevelParser;
import de.intevation.flys.importer.parsers.WstParser;
+
import de.intevation.flys.model.River;
import de.intevation.flys.model.Unit;
+import de.intevation.flys.utils.DouglasPeuker;
+
+import java.io.File;
+import java.io.IOException;
+
+import java.sql.SQLException;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+import org.hibernate.exception.ConstraintViolationException;
+
/** Import all river-related data (files) that can be found. */
public class ImportRiver
@@ -159,9 +168,11 @@
/** Callback-implementation for CrossSectionParsers. */
- class ImportRiverCrossSectionParserCallback implements CrossSectionParser.Callback {
- Set<HashedFile> files = new HashSet<HashedFile>();
- String type;
+ private class ImportRiverCrossSectionParserCallback
+ implements CrossSectionParser.Callback {
+
+ private Set<HashedFile> files = new HashSet<HashedFile>();
+ private String type;
/**
@@ -185,7 +196,7 @@
/** Add crosssection. */
- public void parsed(CrossSectionParser parser) {
+ public void parsed(CrossSectionParser parser) {
log.debug("callback from " + type + " parser");
addCrossSections(parser);
@@ -941,14 +952,20 @@
List<ImportCrossSectionLine> lines =
new ArrayList<ImportCrossSectionLine>(data.size());
+ Double simplificationEpsilon =
+ Config.INSTANCE.getCrossSectionSimplificationEpsilon();
+
for (Map.Entry<Double, List<XY>> entry: data.entrySet()) {
Double km = entry.getKey();
List<XY> points = entry.getValue();
+ if (simplificationEpsilon != null) {
+ points = DouglasPeuker.simplify(points, simplificationEpsilon);
+ }
lines.add(new ImportCrossSectionLine(km, points));
}
crossSections.add(new ImportCrossSection(
- ImportRiver.this, description, ti, lines));
+ this, description, ti, lines));
}
/** Create a W80 Parser and parse w80 files found. */
@@ -1080,7 +1097,10 @@
}
public void storeCrossSections() {
- if (!Config.INSTANCE.skipPRFs() || !Config.INSTANCE.skipDA66s() || !Config.INSTANCE.skipDA50s() || !Config.INSTANCE.skipW80s()) {
+ if (!Config.INSTANCE.skipPRFs()
+ || !Config.INSTANCE.skipDA66s()
+ || !Config.INSTANCE.skipDA50s()
+ || !Config.INSTANCE.skipW80s()) {
log.info("store cross sections");
getPeer();
for (ImportCrossSection crossSection: crossSections) {
diff -r fb4d87274f28 -r 7bbee0cfc171 flys-backend/src/main/java/de/intevation/flys/importer/XY.java
--- a/flys-backend/src/main/java/de/intevation/flys/importer/XY.java Sun Feb 24 13:03:44 2013 +0100
+++ b/flys-backend/src/main/java/de/intevation/flys/importer/XY.java Sun Feb 24 17:29:52 2013 +0100
@@ -14,6 +14,10 @@
public XY() {
}
+ public XY(XY other) {
+ this(other.x, other.y, other.index);
+ }
+
public XY(double x, double y, int index) {
this.x = x;
this.y = y;
@@ -52,5 +56,43 @@
public void setIndex(int index) {
this.index = index;
}
+
+ public double dot(double ox, double oy) {
+ return x*ox + y*oy;
+ }
+
+ public double dot(XY other) {
+ return dot(other.x, other.y);
+ }
+
+ public XY sub(XY other) {
+ x -= other.x;
+ y -= other.y;
+ return this;
+ }
+
+ public XY ortho() {
+ double z = x;
+ x = y;
+ y = -z;
+ return this;
+ }
+
+ public XY normalize() {
+ double len = dot(this);
+
+ if (len > 1e-6) {
+ len = 1d/Math.sqrt(len);
+ x *= len;
+ y *= len;
+ }
+
+ return this;
+ }
+
+ // x*nx + y*ny + d = 0 <=> d = -x*nx -y*ny
+ public double lineOffset(XY p) {
+ return -x*p.x -y*p.y;
+ }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
diff -r fb4d87274f28 -r 7bbee0cfc171 flys-backend/src/main/java/de/intevation/flys/utils/DouglasPeuker.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-backend/src/main/java/de/intevation/flys/utils/DouglasPeuker.java Sun Feb 24 17:29:52 2013 +0100
@@ -0,0 +1,81 @@
+package de.intevation.flys.utils;
+
+import de.intevation.flys.importer.XY; // TODO: Move to a more common package.
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public final class DouglasPeuker
+{
+ public static final double EPSILON = 1e-4;
+
+ private DouglasPeuker() {
+ }
+
+ public static List<XY> simplify(List<XY> input) {
+ return simplify(input, EPSILON);
+ }
+
+ public static List<XY> simplify(List<XY> input, double epsilon) {
+
+ int N = input.size();
+
+ if (N < 3) {
+ return new ArrayList<XY>(input);
+ }
+
+ List<XY> simplified = recursiveSimplify(input, 0, N-1, epsilon);
+
+ List<XY> output = new ArrayList<XY>(simplified.size()+2);
+ output.add(input.get(0));
+ output.addAll(simplified);
+ output.add(input.get(N-1));
+
+ return output;
+ }
+
+ private static List recursiveSimplify(
+ List<XY> input,
+ int start,
+ int end,
+ double epsilon
+ ) {
+ XY a = input.get(start);
+ XY b = input.get(end);
+
+ // Normal of hesse normal form.
+ XY n = new XY(b).sub(a).ortho().normalize();
+
+ // distance offset of the hesse normal form.
+ double d = n.lineOffset(a);
+
+ double maxDist = -Double.MAX_VALUE;
+ int maxIdx = -1;
+
+ for (int i = start+1; i < end; ++i) {
+ double dist = Math.abs(n.dot(input.get(i)) + d);
+ if (dist > maxDist) {
+ maxDist = dist;
+ maxIdx = i;
+ }
+ }
+
+ if (maxDist < epsilon) {
+ // All points between a and b can be ignored.
+ return Collections.<XY>emptyList();
+ }
+
+ // Split by input[maxIdx].
+ List<XY> before = recursiveSimplify(input, start, maxIdx, epsilon);
+ List<XY> after = recursiveSimplify(input, maxIdx, end, epsilon);
+
+ List<XY> output = new ArrayList<XY>(before.size()+1+after.size());
+ output.addAll(before);
+ output.add(input.get(maxIdx));
+ output.addAll(after);
+
+ return output;
+ }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
More information about the Dive4elements-commits
mailing list