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