Mercurial > dive4elements > gnv-client
diff gnv-artifacts/src/main/java/de/intevation/gnv/raster/IsoProducer.java @ 1119:7c4f81f74c47
merged gnv-artifacts
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:00 +0200 |
parents | f953c9a559d8 |
children |
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/IsoProducer.java Fri Sep 28 12:14:00 2012 +0200 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2010 by Intevation GmbH + * + * This program is free software under the LGPL (>=v2.1) + * Read the file LGPL.txt coming with the software for details + * or visit http://www.gnu.org/licenses/ if it does not exist. + */ + +package de.intevation.gnv.raster; + +import de.intevation.gnv.math.IJKey; + +import de.intevation.gnv.raster.Vectorizer.Edge; + +import gnu.trove.TIntHashSet; +import gnu.trove.TIntObjectHashMap; +import gnu.trove.TObjectProcedure; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +/** + * Vectorizer backend to generate iso lines as line strings + * and custom labels on the chart. + * + * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> + */ +public class IsoProducer +extends AbstractProducer +{ + /** + * Iso lines separate two neighbors. This interface decouples + * the generation of a suitable label for these to neighbors. + */ + public interface AttributeGenerator { + + /** + * Generate attribute show as label for two given neighbors. + * @param neighbor1 The first neighbor. + * @param neighbor2 The second neighbor. + * @return The label attribute. + */ + Object generateAttribute(int neighbor1, int neighbor2); + + } // interface AttributeGenerator + + /** + * Internal map of open edge to neighbor attributes. + */ + protected HashMap<Edge, Integer> open; + /** + * Internal map to associate neighbors with open edges. + */ + protected HashMap<IJKey, TIntObjectHashMap> commonOpen; + /** + * Internal map to associate neighbors with complete rings. + */ + protected HashMap<IJKey, ArrayList<Edge>> complete; + + /** + * Width of the index space. + */ + protected int width; + /** + * Height of the index space. + */ + protected int height; + + /** + * Constructor with a given world bounding box. + * @param minX Min x coord of the world. + * @param minY Min y coord of the world. + * @param maxX Max x coord of the world. + * @param maxY Max y coord of the world. + */ + public IsoProducer( + double minX, double minY, + double maxX, double maxY + ) { + super(minX, minY, maxX, 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 + + /** + * Join the pairs of neighbors i,j to have a distinct set. + * @return The distinct pairs of neighbors. + */ + protected HashSet<IJKey> joinPairs() { + HashSet<IJKey> pairs = new HashSet<IJKey>(); + pairs.addAll(complete .keySet()); + pairs.addAll(commonOpen.keySet()); + return pairs; + } + + /** + * Filter out the head list from the open edge lists. + * @param map Map of end and head lists. + * @return list of only head lists. + */ + protected static ArrayList<Edge> headList(TIntObjectHashMap map) { + final ArrayList<Edge> headList = new ArrayList<Edge>(); + map.forEachValue(new TObjectProcedure() { + TIntHashSet headSet = new TIntHashSet(); + public boolean execute(Object value) { + Edge head = ((Edge)value).head(); + if (headSet.add(head.a)) { + headList.add(head); + } + return true; + } + }); + return headList; + } + + /** + * Reset internal data structures to save some memory. + */ + public void clear() { + open.clear(); + complete.clear(); + commonOpen.clear(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :