Mercurial > dive4elements > gnv-client
diff gnv-artifacts/src/main/java/de/intevation/gnv/raster/IsoPolygonSeriesProducer.java @ 437:b624879d2902
Added vectorizer rings callback to generate iso lines.
gnv-artifacts/trunk@485 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 27 Dec 2009 05:25:40 +0000 |
parents | |
children | eb2ac62e853a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/raster/IsoPolygonSeriesProducer.java Sun Dec 27 05:25:40 2009 +0000 @@ -0,0 +1,215 @@ +package de.intevation.gnv.raster; + +import java.util.List; +import java.util.Map; +import java.util.HashSet; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.Collection; + +import gnu.trove.TIntObjectHashMap; +import gnu.trove.TDoubleArrayList; +import gnu.trove.TIntObjectIterator; + +import de.intevation.gnv.raster.Vectorizer.RingsHandler; +import de.intevation.gnv.raster.Vectorizer.Edge; + +import de.intevation.gnv.math.IJKey; + +import de.intevation.gnv.jfreechart.PolygonSeries; +import de.intevation.gnv.jfreechart.CompactXYItems; + +/** + * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) + */ +public class IsoPolygonSeriesProducer +implements RingsHandler +{ + public interface LabelGenerator { + + String generateLabel(int neighbor1, int neighbor2); + + } // interface LabelGenerator + + protected HashMap<Edge, Integer> open; + protected HashMap<IJKey, TIntObjectHashMap> commonOpen; + protected HashMap<IJKey, ArrayList<Edge>> complete; + + protected int width; + protected int height; + + protected double minX; + protected double minY; + protected double maxX; + protected double maxY; + + public IsoPolygonSeriesProducer( + double minX, double minY, + double maxX, double maxY + ) { + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + + open = new HashMap<Edge, Integer>(); + commonOpen = new HashMap<IJKey, TIntObjectHashMap>(); + complete = new HashMap<IJKey, ArrayList<Edge>>(); + } + + public void handleRings( + List<Edge> rings, + int value, + int width, + int height + ) { + if (value == -1) { + return; + } + this.width = width; + this.height = height; + + Integer v = Integer.valueOf(value); + + for (Edge head: rings) { + Edge current = head; + do { + Integer neighbor = open.remove(current); + + if (neighbor != null) { + IJKey pair = new IJKey(value, neighbor.intValue()); + pair.sort(); + + TIntObjectHashMap co = commonOpen.get(pair); + + if (co == null) { + commonOpen.put(pair, co = new TIntObjectHashMap()); + } + + Edge edge = new Edge(current); + + Edge otherA = (Edge)co.remove(edge.a); + if (otherA != null) { + otherA.chain(edge, edge.a); + } + + Edge otherB = (Edge)co.remove(edge.b); + if (otherB != null) { + otherB.chain(edge, edge.b); + } + + if (edge.isComplete()) { + ArrayList list = complete.get(pair); + if (list == null) { + complete.put(pair, list = new ArrayList()); + } + list.add(Vectorizer.simplify(edge, width)); + } + else { + if (otherA == null) { + co.put(edge.a, edge); + } + if (otherB == null) { + co.put(edge.b, edge); + } + } + } + else { + Edge edge = new Edge(current.b, current.a); + open.put(edge, v); + } + + current = current.next; + } + while (current != head); + } // for all rings + + } // handleRings + + public Collection<PolygonSeries> getSeries() { + return getSeries(null); + } + + public Collection<PolygonSeries> getSeries(LabelGenerator labelGenerator) { + + ArrayList<PolygonSeries> series = new ArrayList<PolygonSeries>(); + double b1 = minX; + double m1 = width != 1 + ? (maxX - minX)/(width-1) + : 0d; + + double b2 = minY; + double m2 = height != 1 + ? (maxY - minY)/(height-1) + : 0d; + + // join keys of complete and open polygons + HashSet<IJKey> pairs = new HashSet<IJKey>(); + for (IJKey key: complete.keySet()) { + pairs.add(key); + } + for (IJKey key: commonOpen.keySet()) { + pairs.add(key); + } + + TDoubleArrayList vertices = new TDoubleArrayList(); + + for (IJKey key: pairs) { + PolygonSeries ps = new PolygonSeries(); + series.add(ps); + + if (labelGenerator != null) { + ps.setAttribute( + "label", + labelGenerator.generateLabel(key.i, key.j)); + } + + // process complete + ArrayList<Edge> completeList = complete.get(key); + if (completeList != null) { + for (Edge head: completeList) { + Edge current = head; + do { + vertices.add(m1*(current.a % width) + b1); + vertices.add(m2*(current.a / width) + b2); + } + while ((current = current.next) != head); + // TODO: Do we need to copy b of the tail? + ps.addRing(new CompactXYItems(vertices.toNativeArray())); + vertices.clear(); + } + } + + // process open + TIntObjectHashMap map = commonOpen.get(key); + if (map != null) { + for (TIntObjectIterator it = map.iterator(); it.hasNext();) { + it.advance(); + int k = it.key(); + Edge head = (Edge)it.value(); + // ignore tails + if ((head.next == null && head.prev != null) + || (head.next == null && head.prev == null && head.b == k)) { + continue; + } + head = Vectorizer.simplify(head, width); + Edge current = head, last = head; + do { + vertices.add(m1*(current.a % width) + b1); + vertices.add(m2*(current.a / width) + b2); + last = current; + } + while ((current = current.next) != null); + // add b from tail + vertices.add(m1*(last.b % width) + b1); + vertices.add(m2*(last.b / width) + b2); + ps.addRing(new CompactXYItems(vertices.toNativeArray())); + vertices.clear(); + } // for all in common open + } // if map defined for key + } // for all pairs + + return series; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: