Mercurial > dive4elements > gnv-client
comparison 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 |
comparison
equal
deleted
inserted
replaced
1027:fca4b5eb8d2f | 1119:7c4f81f74c47 |
---|---|
1 /* | |
2 * Copyright (c) 2010 by Intevation GmbH | |
3 * | |
4 * This program is free software under the LGPL (>=v2.1) | |
5 * Read the file LGPL.txt coming with the software for details | |
6 * or visit http://www.gnu.org/licenses/ if it does not exist. | |
7 */ | |
8 | |
9 package de.intevation.gnv.raster; | |
10 | |
11 import de.intevation.gnv.math.IJKey; | |
12 | |
13 import de.intevation.gnv.raster.Vectorizer.Edge; | |
14 | |
15 import gnu.trove.TIntHashSet; | |
16 import gnu.trove.TIntObjectHashMap; | |
17 import gnu.trove.TObjectProcedure; | |
18 | |
19 import java.util.ArrayList; | |
20 import java.util.HashMap; | |
21 import java.util.HashSet; | |
22 import java.util.List; | |
23 | |
24 /** | |
25 * Vectorizer backend to generate iso lines as line strings | |
26 * and custom labels on the chart. | |
27 * | |
28 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> | |
29 */ | |
30 public class IsoProducer | |
31 extends AbstractProducer | |
32 { | |
33 /** | |
34 * Iso lines separate two neighbors. This interface decouples | |
35 * the generation of a suitable label for these to neighbors. | |
36 */ | |
37 public interface AttributeGenerator { | |
38 | |
39 /** | |
40 * Generate attribute show as label for two given neighbors. | |
41 * @param neighbor1 The first neighbor. | |
42 * @param neighbor2 The second neighbor. | |
43 * @return The label attribute. | |
44 */ | |
45 Object generateAttribute(int neighbor1, int neighbor2); | |
46 | |
47 } // interface AttributeGenerator | |
48 | |
49 /** | |
50 * Internal map of open edge to neighbor attributes. | |
51 */ | |
52 protected HashMap<Edge, Integer> open; | |
53 /** | |
54 * Internal map to associate neighbors with open edges. | |
55 */ | |
56 protected HashMap<IJKey, TIntObjectHashMap> commonOpen; | |
57 /** | |
58 * Internal map to associate neighbors with complete rings. | |
59 */ | |
60 protected HashMap<IJKey, ArrayList<Edge>> complete; | |
61 | |
62 /** | |
63 * Width of the index space. | |
64 */ | |
65 protected int width; | |
66 /** | |
67 * Height of the index space. | |
68 */ | |
69 protected int height; | |
70 | |
71 /** | |
72 * Constructor with a given world bounding box. | |
73 * @param minX Min x coord of the world. | |
74 * @param minY Min y coord of the world. | |
75 * @param maxX Max x coord of the world. | |
76 * @param maxY Max y coord of the world. | |
77 */ | |
78 public IsoProducer( | |
79 double minX, double minY, | |
80 double maxX, double maxY | |
81 ) { | |
82 super(minX, minY, maxX, maxY); | |
83 | |
84 open = new HashMap<Edge, Integer>(); | |
85 commonOpen = new HashMap<IJKey, TIntObjectHashMap>(); | |
86 complete = new HashMap<IJKey, ArrayList<Edge>>(); | |
87 } | |
88 | |
89 public void handleRings( | |
90 List<Edge> rings, | |
91 int value, | |
92 int width, | |
93 int height | |
94 ) { | |
95 if (value == -1) { | |
96 return; | |
97 } | |
98 this.width = width; | |
99 this.height = height; | |
100 | |
101 Integer v = Integer.valueOf(value); | |
102 | |
103 for (Edge head: rings) { | |
104 Edge current = head; | |
105 do { | |
106 Integer neighbor = open.remove(current); | |
107 | |
108 if (neighbor != null) { | |
109 IJKey pair = new IJKey(value, neighbor.intValue()); | |
110 pair.sort(); | |
111 | |
112 TIntObjectHashMap co = commonOpen.get(pair); | |
113 | |
114 if (co == null) { | |
115 commonOpen.put(pair, co = new TIntObjectHashMap()); | |
116 } | |
117 | |
118 Edge edge = new Edge(current); | |
119 | |
120 Edge otherA = (Edge)co.remove(edge.a); | |
121 if (otherA != null) { | |
122 otherA.chain(edge, edge.a); | |
123 } | |
124 | |
125 Edge otherB = (Edge)co.remove(edge.b); | |
126 if (otherB != null) { | |
127 otherB.chain(edge, edge.b); | |
128 } | |
129 | |
130 if (edge.isComplete()) { | |
131 ArrayList list = complete.get(pair); | |
132 if (list == null) { | |
133 complete.put(pair, list = new ArrayList()); | |
134 } | |
135 list.add(Vectorizer.simplify(edge, width)); | |
136 } | |
137 else { | |
138 if (otherA == null) { | |
139 co.put(edge.a, edge); | |
140 } | |
141 if (otherB == null) { | |
142 co.put(edge.b, edge); | |
143 } | |
144 } | |
145 } | |
146 else { | |
147 Edge edge = new Edge(current.b, current.a); | |
148 open.put(edge, v); | |
149 } | |
150 | |
151 current = current.next; | |
152 } | |
153 while (current != head); | |
154 } // for all rings | |
155 | |
156 } // handleRings | |
157 | |
158 /** | |
159 * Join the pairs of neighbors i,j to have a distinct set. | |
160 * @return The distinct pairs of neighbors. | |
161 */ | |
162 protected HashSet<IJKey> joinPairs() { | |
163 HashSet<IJKey> pairs = new HashSet<IJKey>(); | |
164 pairs.addAll(complete .keySet()); | |
165 pairs.addAll(commonOpen.keySet()); | |
166 return pairs; | |
167 } | |
168 | |
169 /** | |
170 * Filter out the head list from the open edge lists. | |
171 * @param map Map of end and head lists. | |
172 * @return list of only head lists. | |
173 */ | |
174 protected static ArrayList<Edge> headList(TIntObjectHashMap map) { | |
175 final ArrayList<Edge> headList = new ArrayList<Edge>(); | |
176 map.forEachValue(new TObjectProcedure() { | |
177 TIntHashSet headSet = new TIntHashSet(); | |
178 public boolean execute(Object value) { | |
179 Edge head = ((Edge)value).head(); | |
180 if (headSet.add(head.a)) { | |
181 headList.add(head); | |
182 } | |
183 return true; | |
184 } | |
185 }); | |
186 return headList; | |
187 } | |
188 | |
189 /** | |
190 * Reset internal data structures to save some memory. | |
191 */ | |
192 public void clear() { | |
193 open.clear(); | |
194 complete.clear(); | |
195 commonOpen.clear(); | |
196 } | |
197 } | |
198 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |