sascha@437: package de.intevation.gnv.raster; sascha@437: sascha@437: import java.util.List; sascha@437: import java.util.HashSet; sascha@437: import java.util.HashMap; sascha@437: import java.util.ArrayList; sascha@437: import java.util.Collection; sascha@437: sascha@437: import gnu.trove.TIntObjectHashMap; sascha@437: import gnu.trove.TDoubleArrayList; sascha@437: import gnu.trove.TIntObjectIterator; sascha@437: sascha@437: import de.intevation.gnv.raster.Vectorizer.RingsHandler; sascha@437: import de.intevation.gnv.raster.Vectorizer.Edge; sascha@437: sascha@437: import de.intevation.gnv.math.IJKey; sascha@437: sascha@437: import de.intevation.gnv.jfreechart.PolygonSeries; sascha@437: import de.intevation.gnv.jfreechart.CompactXYItems; sascha@437: sascha@437: /** sascha@437: * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) sascha@437: */ sascha@437: public class IsoPolygonSeriesProducer sascha@437: implements RingsHandler sascha@437: { sascha@437: public interface LabelGenerator { sascha@437: sascha@437: String generateLabel(int neighbor1, int neighbor2); sascha@437: sascha@437: } // interface LabelGenerator sascha@437: sascha@437: protected HashMap open; sascha@437: protected HashMap commonOpen; sascha@437: protected HashMap> complete; sascha@437: sascha@437: protected int width; sascha@437: protected int height; sascha@437: sascha@437: protected double minX; sascha@437: protected double minY; sascha@437: protected double maxX; sascha@437: protected double maxY; sascha@437: sascha@437: public IsoPolygonSeriesProducer( sascha@437: double minX, double minY, sascha@437: double maxX, double maxY sascha@437: ) { sascha@437: this.minX = minX; sascha@437: this.minY = minY; sascha@437: this.maxX = maxX; sascha@437: this.maxY = maxY; sascha@437: sascha@437: open = new HashMap(); sascha@437: commonOpen = new HashMap(); sascha@437: complete = new HashMap>(); sascha@437: } sascha@437: sascha@437: public void handleRings( sascha@437: List rings, sascha@437: int value, sascha@437: int width, sascha@437: int height sascha@437: ) { sascha@437: if (value == -1) { sascha@437: return; sascha@437: } sascha@437: this.width = width; sascha@437: this.height = height; sascha@437: sascha@437: Integer v = Integer.valueOf(value); sascha@437: sascha@437: for (Edge head: rings) { sascha@437: Edge current = head; sascha@437: do { sascha@437: Integer neighbor = open.remove(current); sascha@437: sascha@437: if (neighbor != null) { sascha@437: IJKey pair = new IJKey(value, neighbor.intValue()); sascha@437: pair.sort(); sascha@437: sascha@437: TIntObjectHashMap co = commonOpen.get(pair); sascha@437: sascha@437: if (co == null) { sascha@437: commonOpen.put(pair, co = new TIntObjectHashMap()); sascha@437: } sascha@437: sascha@437: Edge edge = new Edge(current); sascha@437: sascha@437: Edge otherA = (Edge)co.remove(edge.a); sascha@437: if (otherA != null) { sascha@437: otherA.chain(edge, edge.a); sascha@437: } sascha@437: sascha@437: Edge otherB = (Edge)co.remove(edge.b); sascha@437: if (otherB != null) { sascha@437: otherB.chain(edge, edge.b); sascha@437: } sascha@437: sascha@437: if (edge.isComplete()) { sascha@437: ArrayList list = complete.get(pair); sascha@437: if (list == null) { sascha@437: complete.put(pair, list = new ArrayList()); sascha@437: } sascha@437: list.add(Vectorizer.simplify(edge, width)); sascha@437: } sascha@437: else { sascha@437: if (otherA == null) { sascha@437: co.put(edge.a, edge); sascha@437: } sascha@437: if (otherB == null) { sascha@437: co.put(edge.b, edge); sascha@437: } sascha@437: } sascha@437: } sascha@437: else { sascha@437: Edge edge = new Edge(current.b, current.a); sascha@437: open.put(edge, v); sascha@437: } sascha@437: sascha@437: current = current.next; sascha@437: } sascha@437: while (current != head); sascha@437: } // for all rings sascha@437: sascha@437: } // handleRings sascha@437: sascha@437: public Collection getSeries() { sascha@437: return getSeries(null); sascha@437: } sascha@437: sascha@437: public Collection getSeries(LabelGenerator labelGenerator) { sascha@437: sascha@437: ArrayList series = new ArrayList(); sascha@437: double b1 = minX; sascha@437: double m1 = width != 1 sascha@437: ? (maxX - minX)/(width-1) sascha@437: : 0d; sascha@437: sascha@437: double b2 = minY; sascha@437: double m2 = height != 1 sascha@437: ? (maxY - minY)/(height-1) sascha@437: : 0d; sascha@437: sascha@437: // join keys of complete and open polygons sascha@437: HashSet pairs = new HashSet(); sascha@437: for (IJKey key: complete.keySet()) { sascha@437: pairs.add(key); sascha@437: } sascha@437: for (IJKey key: commonOpen.keySet()) { sascha@437: pairs.add(key); sascha@437: } sascha@437: sascha@437: TDoubleArrayList vertices = new TDoubleArrayList(); sascha@437: sascha@437: for (IJKey key: pairs) { sascha@437: PolygonSeries ps = new PolygonSeries(); sascha@437: series.add(ps); sascha@437: sascha@437: if (labelGenerator != null) { sascha@437: ps.setAttribute( sascha@437: "label", sascha@437: labelGenerator.generateLabel(key.i, key.j)); sascha@437: } sascha@437: sascha@437: // process complete sascha@437: ArrayList completeList = complete.get(key); sascha@437: if (completeList != null) { sascha@437: for (Edge head: completeList) { sascha@437: Edge current = head; sascha@437: do { sascha@437: vertices.add(m1*(current.a % width) + b1); sascha@437: vertices.add(m2*(current.a / width) + b2); sascha@437: } sascha@437: while ((current = current.next) != head); sascha@437: // TODO: Do we need to copy b of the tail? sascha@437: ps.addRing(new CompactXYItems(vertices.toNativeArray())); sascha@437: vertices.clear(); sascha@437: } sascha@437: } sascha@437: sascha@437: // process open sascha@437: TIntObjectHashMap map = commonOpen.get(key); sascha@437: if (map != null) { sascha@437: for (TIntObjectIterator it = map.iterator(); it.hasNext();) { sascha@437: it.advance(); sascha@437: int k = it.key(); sascha@437: Edge head = (Edge)it.value(); sascha@437: // ignore tails sascha@437: if ((head.next == null && head.prev != null) sascha@437: || (head.next == null && head.prev == null && head.b == k)) { sascha@437: continue; sascha@437: } sascha@437: head = Vectorizer.simplify(head, width); sascha@437: Edge current = head, last = head; sascha@437: do { sascha@437: vertices.add(m1*(current.a % width) + b1); sascha@437: vertices.add(m2*(current.a / width) + b2); sascha@437: last = current; sascha@437: } sascha@437: while ((current = current.next) != null); sascha@437: // add b from tail sascha@437: vertices.add(m1*(last.b % width) + b1); sascha@437: vertices.add(m2*(last.b / width) + b2); sascha@437: ps.addRing(new CompactXYItems(vertices.toNativeArray())); sascha@437: vertices.clear(); sascha@437: } // for all in common open sascha@437: } // if map defined for key sascha@437: } // for all pairs sascha@437: sascha@437: return series; sascha@437: } sascha@437: } sascha@437: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: