comparison 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
comparison
equal deleted inserted replaced
436:6642ab6c583c 437:b624879d2902
1 package de.intevation.gnv.raster;
2
3 import java.util.List;
4 import java.util.Map;
5 import java.util.HashSet;
6 import java.util.HashMap;
7 import java.util.ArrayList;
8 import java.util.Collection;
9
10 import gnu.trove.TIntObjectHashMap;
11 import gnu.trove.TDoubleArrayList;
12 import gnu.trove.TIntObjectIterator;
13
14 import de.intevation.gnv.raster.Vectorizer.RingsHandler;
15 import de.intevation.gnv.raster.Vectorizer.Edge;
16
17 import de.intevation.gnv.math.IJKey;
18
19 import de.intevation.gnv.jfreechart.PolygonSeries;
20 import de.intevation.gnv.jfreechart.CompactXYItems;
21
22 /**
23 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
24 */
25 public class IsoPolygonSeriesProducer
26 implements RingsHandler
27 {
28 public interface LabelGenerator {
29
30 String generateLabel(int neighbor1, int neighbor2);
31
32 } // interface LabelGenerator
33
34 protected HashMap<Edge, Integer> open;
35 protected HashMap<IJKey, TIntObjectHashMap> commonOpen;
36 protected HashMap<IJKey, ArrayList<Edge>> complete;
37
38 protected int width;
39 protected int height;
40
41 protected double minX;
42 protected double minY;
43 protected double maxX;
44 protected double maxY;
45
46 public IsoPolygonSeriesProducer(
47 double minX, double minY,
48 double maxX, double maxY
49 ) {
50 this.minX = minX;
51 this.minY = minY;
52 this.maxX = maxX;
53 this.maxY = maxY;
54
55 open = new HashMap<Edge, Integer>();
56 commonOpen = new HashMap<IJKey, TIntObjectHashMap>();
57 complete = new HashMap<IJKey, ArrayList<Edge>>();
58 }
59
60 public void handleRings(
61 List<Edge> rings,
62 int value,
63 int width,
64 int height
65 ) {
66 if (value == -1) {
67 return;
68 }
69 this.width = width;
70 this.height = height;
71
72 Integer v = Integer.valueOf(value);
73
74 for (Edge head: rings) {
75 Edge current = head;
76 do {
77 Integer neighbor = open.remove(current);
78
79 if (neighbor != null) {
80 IJKey pair = new IJKey(value, neighbor.intValue());
81 pair.sort();
82
83 TIntObjectHashMap co = commonOpen.get(pair);
84
85 if (co == null) {
86 commonOpen.put(pair, co = new TIntObjectHashMap());
87 }
88
89 Edge edge = new Edge(current);
90
91 Edge otherA = (Edge)co.remove(edge.a);
92 if (otherA != null) {
93 otherA.chain(edge, edge.a);
94 }
95
96 Edge otherB = (Edge)co.remove(edge.b);
97 if (otherB != null) {
98 otherB.chain(edge, edge.b);
99 }
100
101 if (edge.isComplete()) {
102 ArrayList list = complete.get(pair);
103 if (list == null) {
104 complete.put(pair, list = new ArrayList());
105 }
106 list.add(Vectorizer.simplify(edge, width));
107 }
108 else {
109 if (otherA == null) {
110 co.put(edge.a, edge);
111 }
112 if (otherB == null) {
113 co.put(edge.b, edge);
114 }
115 }
116 }
117 else {
118 Edge edge = new Edge(current.b, current.a);
119 open.put(edge, v);
120 }
121
122 current = current.next;
123 }
124 while (current != head);
125 } // for all rings
126
127 } // handleRings
128
129 public Collection<PolygonSeries> getSeries() {
130 return getSeries(null);
131 }
132
133 public Collection<PolygonSeries> getSeries(LabelGenerator labelGenerator) {
134
135 ArrayList<PolygonSeries> series = new ArrayList<PolygonSeries>();
136 double b1 = minX;
137 double m1 = width != 1
138 ? (maxX - minX)/(width-1)
139 : 0d;
140
141 double b2 = minY;
142 double m2 = height != 1
143 ? (maxY - minY)/(height-1)
144 : 0d;
145
146 // join keys of complete and open polygons
147 HashSet<IJKey> pairs = new HashSet<IJKey>();
148 for (IJKey key: complete.keySet()) {
149 pairs.add(key);
150 }
151 for (IJKey key: commonOpen.keySet()) {
152 pairs.add(key);
153 }
154
155 TDoubleArrayList vertices = new TDoubleArrayList();
156
157 for (IJKey key: pairs) {
158 PolygonSeries ps = new PolygonSeries();
159 series.add(ps);
160
161 if (labelGenerator != null) {
162 ps.setAttribute(
163 "label",
164 labelGenerator.generateLabel(key.i, key.j));
165 }
166
167 // process complete
168 ArrayList<Edge> completeList = complete.get(key);
169 if (completeList != null) {
170 for (Edge head: completeList) {
171 Edge current = head;
172 do {
173 vertices.add(m1*(current.a % width) + b1);
174 vertices.add(m2*(current.a / width) + b2);
175 }
176 while ((current = current.next) != head);
177 // TODO: Do we need to copy b of the tail?
178 ps.addRing(new CompactXYItems(vertices.toNativeArray()));
179 vertices.clear();
180 }
181 }
182
183 // process open
184 TIntObjectHashMap map = commonOpen.get(key);
185 if (map != null) {
186 for (TIntObjectIterator it = map.iterator(); it.hasNext();) {
187 it.advance();
188 int k = it.key();
189 Edge head = (Edge)it.value();
190 // ignore tails
191 if ((head.next == null && head.prev != null)
192 || (head.next == null && head.prev == null && head.b == k)) {
193 continue;
194 }
195 head = Vectorizer.simplify(head, width);
196 Edge current = head, last = head;
197 do {
198 vertices.add(m1*(current.a % width) + b1);
199 vertices.add(m2*(current.a / width) + b2);
200 last = current;
201 }
202 while ((current = current.next) != null);
203 // add b from tail
204 vertices.add(m1*(last.b % width) + b1);
205 vertices.add(m2*(last.b / width) + b2);
206 ps.addRing(new CompactXYItems(vertices.toNativeArray()));
207 vertices.clear();
208 } // for all in common open
209 } // if map defined for key
210 } // for all pairs
211
212 return series;
213 }
214 }
215 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:

http://dive4elements.wald.intevation.org