comparison gnv-artifacts/src/main/java/de/intevation/gnv/raster/IsoPolygonSeriesProducer.java @ 447:92b7ccbf6163

Improved generation of iso lines in vertical cross section. gnv-artifacts/trunk@495 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 01 Jan 2010 21:52:41 +0000
parents eb2ac62e853a
children 3cb2bea50456
comparison
equal deleted inserted replaced
446:f5a041000357 447:92b7ccbf6163
4 import java.util.HashSet; 4 import java.util.HashSet;
5 import java.util.HashMap; 5 import java.util.HashMap;
6 import java.util.ArrayList; 6 import java.util.ArrayList;
7 import java.util.Collection; 7 import java.util.Collection;
8 8
9 import org.apache.log4j.Logger;
10
11 import gnu.trove.TIntHashSet;
9 import gnu.trove.TIntObjectHashMap; 12 import gnu.trove.TIntObjectHashMap;
10 import gnu.trove.TDoubleArrayList; 13 import gnu.trove.TDoubleArrayList;
11 import gnu.trove.TIntObjectIterator; 14 import gnu.trove.TObjectProcedure;
12 15
13 import de.intevation.gnv.raster.Vectorizer.RingsHandler; 16 import de.intevation.gnv.raster.Vectorizer.RingsHandler;
14 import de.intevation.gnv.raster.Vectorizer.Edge; 17 import de.intevation.gnv.raster.Vectorizer.Edge;
15 18
16 import de.intevation.gnv.math.IJKey; 19 import de.intevation.gnv.math.IJKey;
22 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) 25 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
23 */ 26 */
24 public class IsoPolygonSeriesProducer 27 public class IsoPolygonSeriesProducer
25 implements RingsHandler 28 implements RingsHandler
26 { 29 {
30 private static Logger log = Logger.getLogger(
31 IsoPolygonSeriesProducer.class);
32
33 public static final Float LINE_WIDTH = Float.valueOf(0.1f);
34
27 public interface LabelGenerator { 35 public interface LabelGenerator {
28 36
29 String generateLabel(int neighbor1, int neighbor2); 37 String generateLabel(int neighbor1, int neighbor2);
30 38
31 } // interface LabelGenerator 39 } // interface LabelGenerator
130 } 138 }
131 139
132 public Collection<PolygonSeries> getSeries(LabelGenerator labelGenerator) { 140 public Collection<PolygonSeries> getSeries(LabelGenerator labelGenerator) {
133 141
134 ArrayList<PolygonSeries> series = new ArrayList<PolygonSeries>(); 142 ArrayList<PolygonSeries> series = new ArrayList<PolygonSeries>();
143
135 double b1 = minX; 144 double b1 = minX;
136 double m1 = width != 1 145 double m1 = width != 1
137 ? (maxX - minX)/(width-1) 146 ? (maxX - minX)/(width-1)
138 : 0d; 147 : 0d;
139 148
153 162
154 TDoubleArrayList vertices = new TDoubleArrayList(); 163 TDoubleArrayList vertices = new TDoubleArrayList();
155 164
156 for (IJKey key: pairs) { 165 for (IJKey key: pairs) {
157 PolygonSeries ps = new PolygonSeries(); 166 PolygonSeries ps = new PolygonSeries();
158 series.add(ps);
159
160 if (labelGenerator != null) {
161 ps.setAttribute(
162 "label",
163 labelGenerator.generateLabel(key.i, key.j));
164 }
165 167
166 // process complete 168 // process complete
167 ArrayList<Edge> completeList = complete.get(key); 169 ArrayList<Edge> completeList = complete.get(key);
168 if (completeList != null) { 170 if (completeList != null) {
169 for (Edge head: completeList) { 171 for (Edge head: completeList) {
171 do { 173 do {
172 vertices.add(m1*(current.a % width) + b1); 174 vertices.add(m1*(current.a % width) + b1);
173 vertices.add(m2*(current.a / width) + b2); 175 vertices.add(m2*(current.a / width) + b2);
174 } 176 }
175 while ((current = current.next) != head); 177 while ((current = current.next) != head);
176 // TODO: Do we need to copy b of the tail? 178 // add head again to close shape
179 vertices.add(m1*(head.a % width) + b1);
180 vertices.add(m2*(head.a / width) + b2);
177 ps.addRing(new CompactXYItems(vertices.toNativeArray())); 181 ps.addRing(new CompactXYItems(vertices.toNativeArray()));
178 vertices.clear(); 182 vertices.clear();
179 } 183 }
180 } 184 }
181 185
182 // process open 186 // process open
183 TIntObjectHashMap map = commonOpen.get(key); 187 TIntObjectHashMap map = commonOpen.get(key);
188
184 if (map != null) { 189 if (map != null) {
185 for (TIntObjectIterator it = map.iterator(); it.hasNext();) { 190 final ArrayList<Edge> headList = new ArrayList<Edge>();
186 it.advance(); 191 map.forEachValue(new TObjectProcedure() {
187 int k = it.key(); 192 TIntHashSet headSet = new TIntHashSet();
188 Edge head = (Edge)it.value(); 193 public boolean execute(Object value) {
189 // ignore tails 194 Edge head = ((Edge)value).head();
190 if ((head.next == null && head.prev != null) 195 if (headSet.add(head.a)) {
191 || (head.next == null && head.prev == null && head.b == k)) { 196 headList.add(head);
192 continue; 197 }
193 } 198 return true;
199 }
200 });
201
202 for (Edge head: headList) {
203
194 head = Vectorizer.simplify(head, width); 204 head = Vectorizer.simplify(head, width);
195 Edge current = head, last = head; 205 Edge current = head, last = head;
196 do { 206 do {
197 vertices.add(m1*(current.a % width) + b1); 207 vertices.add(m1*(current.a % width) + b1);
198 vertices.add(m2*(current.a / width) + b2); 208 vertices.add(m2*(current.a / width) + b2);
204 vertices.add(m2*(last.b / width) + b2); 214 vertices.add(m2*(last.b / width) + b2);
205 ps.addRing(new CompactXYItems(vertices.toNativeArray())); 215 ps.addRing(new CompactXYItems(vertices.toNativeArray()));
206 vertices.clear(); 216 vertices.clear();
207 } // for all in common open 217 } // for all in common open
208 } // if map defined for key 218 } // if map defined for key
219
220 int itemCount = ps.getItemCount();
221
222 if (itemCount > 0) {
223 series.add(ps);
224 if (labelGenerator != null) {
225 ps.setAttribute(
226 "label",
227 labelGenerator.generateLabel(key.i, key.j));
228 }
229 ps.setAttribute("line.width", LINE_WIDTH);
230 }
209 } // for all pairs 231 } // for all pairs
210 232
211 return series; 233 return series;
212 } 234 }
213 } 235 }

http://dive4elements.wald.intevation.org