Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/math/GridCell.java @ 593:b248531fa20b
Added experimental support for extrapolation in "Horizontalschnitte"
gnv-artifacts/trunk@648 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 31 Jan 2010 21:50:15 +0000 |
parents | 4e347624ee7c |
children | c4156275c1e1 |
comparison
equal
deleted
inserted
replaced
592:3c939c95c477 | 593:b248531fa20b |
---|---|
1 package de.intevation.gnv.math; | 1 package de.intevation.gnv.math; |
2 | |
3 import com.vividsolutions.jts.algorithm.CGAlgorithms; | |
2 | 4 |
3 import com.vividsolutions.jts.geom.Coordinate; | 5 import com.vividsolutions.jts.geom.Coordinate; |
4 import com.vividsolutions.jts.geom.Envelope; | 6 import com.vividsolutions.jts.geom.Envelope; |
5 import com.vividsolutions.jts.geom.Geometry; | 7 import com.vividsolutions.jts.geom.Geometry; |
6 import com.vividsolutions.jts.geom.GeometryFactory; | 8 import com.vividsolutions.jts.geom.GeometryFactory; |
71 this.p4 = p4; | 73 this.p4 = p4; |
72 createPolygon(); | 74 createPolygon(); |
73 } | 75 } |
74 | 76 |
75 protected void createPolygon() { | 77 protected void createPolygon() { |
78 Coordinate [] coords = new Coordinate [] { p1, p2, p3, p4, p1 }; | |
79 if (!CGAlgorithms.isCCW(coords)) { | |
80 for (int i = 0, j = coords.length-1; i < j; ++i, --j) { | |
81 Coordinate c = coords[i]; | |
82 coords[i] = coords[j]; | |
83 coords[j] = c; | |
84 } | |
85 } | |
76 LinearRing shell = GEOMETRY_FACTORY | 86 LinearRing shell = GEOMETRY_FACTORY |
77 .createLinearRing(new Coordinate [] { p1, p2, p3, p4, p1 }); | 87 .createLinearRing(coords); |
88 | |
89 if (!shell.isValid()) { | |
90 log.warn("linear ring is not valid"); | |
91 } | |
92 | |
78 polygon = GEOMETRY_FACTORY.createPolygon(shell, null); | 93 polygon = GEOMETRY_FACTORY.createPolygon(shell, null); |
79 } | 94 } |
80 | 95 |
81 public Envelope getEnvelope() { | 96 public Envelope getEnvelope() { |
82 return polygon.getEnvelopeInternal(); | 97 return polygon.getEnvelopeInternal(); |
93 } | 108 } |
94 | 109 |
95 public static List<GridCell> pointsToGridCells( | 110 public static List<GridCell> pointsToGridCells( |
96 List<? extends Point2d> points, | 111 List<? extends Point2d> points, |
97 Envelope relevantArea | 112 Envelope relevantArea |
113 ) { | |
114 return pointsToGridCells(points, relevantArea, 0); | |
115 } | |
116 | |
117 private static final int NEIGHBORS [][] = { | |
118 { -1, -1 }, // 0 | |
119 { -1, 0 }, // 1 | |
120 { -1, +1 }, // 2 | |
121 { 0, +1 }, // 3 | |
122 { +1, +1 }, // 4 | |
123 { +1, 0 }, // 5 | |
124 { +1, -1 }, // 6 | |
125 { 0, -1 } // 7 | |
126 }; | |
127 | |
128 public static int extrapolate( | |
129 HashMap<Integer, HashMap<Integer, Point2d>> rows, | |
130 int minI, int maxI, | |
131 int minJ, int maxJ, | |
132 int rounds, | |
133 Envelope relevantArea | |
134 ) { | |
135 Point2d [] neighbors = new Point2d[NEIGHBORS.length]; | |
136 Point2d [] positions = new Point2d[NEIGHBORS.length]; | |
137 | |
138 int total = 0; | |
139 | |
140 ArrayList<ArrayList<IJKey>> prio = | |
141 new ArrayList<ArrayList<IJKey>>(NEIGHBORS.length); | |
142 | |
143 for (int i = 0; i < NEIGHBORS.length; ++i) { | |
144 prio.add(new ArrayList<IJKey>()); | |
145 } | |
146 | |
147 while (rounds-- > 0) { | |
148 for (int i = minI; i <= maxI; ++i) { | |
149 for (int j = minJ; j <= maxJ; ++j) { | |
150 Point2d p = get(rows, i, j); | |
151 if (p != null) { | |
152 continue; | |
153 } | |
154 | |
155 int count = 0; | |
156 | |
157 for (int k = 0; k < neighbors.length; ++k) { | |
158 neighbors[k] = positions[k] = null; | |
159 int dij [] = NEIGHBORS[k]; | |
160 Point2d n1 = get(rows, i+ dij[0], j+ dij[1]); | |
161 Point2d n2 = get(rows, i+2*dij[0], j+2*dij[1]); | |
162 if (n1 != null && n2 != null) { | |
163 ++count; | |
164 } | |
165 } | |
166 | |
167 if (count > 0) { | |
168 prio.get(count-1).add(new IJKey(i, j)); | |
169 } | |
170 } // for all columns | |
171 } // for all rows | |
172 | |
173 int N = 0; | |
174 | |
175 for (int l = NEIGHBORS.length-1; l >= 0; --l) { | |
176 ArrayList<IJKey> list = prio.get(l); | |
177 for (IJKey ij: list) { | |
178 int i = ij.i; | |
179 int j = ij.j; | |
180 for (int k = 0; k < neighbors.length; ++k) { | |
181 neighbors[k] = positions[k] = null; | |
182 int dij [] = NEIGHBORS[k]; | |
183 Point2d n1 = get(rows, i+ dij[0], j+ dij[1]); | |
184 Point2d n2 = get(rows, i+2*dij[0], j+2*dij[1]); | |
185 if (n1 != null && n2 != null) { | |
186 neighbors[k] = n1; | |
187 positions[k] = n1.extrapolate(-1d, n2); | |
188 } | |
189 } | |
190 | |
191 Point2d avg = Point2d.average(positions); | |
192 | |
193 if (avg != null && avg.near(positions) | |
194 && (relevantArea == null || relevantArea.contains(avg.x, avg.y))) { | |
195 avg.i = i; | |
196 avg.j = j; | |
197 avg.inverseDistanceWeighting(neighbors); | |
198 put(rows, avg, i, j); | |
199 } | |
200 } | |
201 N += list.size(); | |
202 list.clear(); | |
203 } | |
204 | |
205 if (N == 0) { | |
206 break; | |
207 } | |
208 total += N; | |
209 } // for all rounds | |
210 | |
211 return total; | |
212 } | |
213 | |
214 public static List<GridCell> pointsToGridCells( | |
215 List<? extends Point2d> points, | |
216 Envelope relevantArea, | |
217 int extrapolationRounds | |
98 ) { | 218 ) { |
99 int minI = Integer.MAX_VALUE; | 219 int minI = Integer.MAX_VALUE; |
100 int maxI = Integer.MIN_VALUE; | 220 int maxI = Integer.MIN_VALUE; |
101 int minJ = Integer.MAX_VALUE; | 221 int minJ = Integer.MAX_VALUE; |
102 int maxJ = Integer.MIN_VALUE; | 222 int maxJ = Integer.MIN_VALUE; |
127 row.put(p.j, p); | 247 row.put(p.j, p); |
128 } | 248 } |
129 | 249 |
130 ArrayList<GridCell> cells = new ArrayList<GridCell>(points.size()); | 250 ArrayList<GridCell> cells = new ArrayList<GridCell>(points.size()); |
131 | 251 |
252 int extrapolated = extrapolate( | |
253 rows, | |
254 minI, maxI, | |
255 minJ, maxJ, | |
256 extrapolationRounds, | |
257 relevantArea); | |
258 | |
132 for (int i = minI + 1; i <= maxI; ++i) { | 259 for (int i = minI + 1; i <= maxI; ++i) { |
133 HashMap<Integer, Point2d> row1 = rows.get(i-1); | 260 HashMap<Integer, Point2d> row1 = rows.get(i-1); |
134 HashMap<Integer, Point2d> row2 = rows.get(i); | 261 HashMap<Integer, Point2d> row2 = rows.get(i); |
135 if (row1 != null && row2 != null) { | 262 |
136 for (int j = minJ + 1; j < maxJ; ++j) { | 263 if (row1 == null || row2 == null) { |
137 Point2d p1 = row1.get(j-1); | 264 continue; |
138 Point2d p2 = row1.get(j); | 265 } |
139 Point2d p3 = row2.get(j); | 266 |
140 Point2d p4 = row2.get(j-1); | 267 for (int j = minJ + 1; j < maxJ; ++j) { |
141 | 268 Point2d p1 = row1.get(j-1); |
142 if (p1 != null && p2 != null && p3 != null && p4 != null) { | 269 Point2d p2 = row1.get(j); |
143 cells.add(new GridCell(p1, p2, p3, p4)); | 270 Point2d p3 = row2.get(j); |
144 } | 271 Point2d p4 = row2.get(j-1); |
145 } // for all columns in row | 272 |
273 if (p1 != null && p2 != null && p3 != null && p4 != null) { | |
274 cells.add(new GridCell(p1, p2, p3, p4)); | |
275 } | |
146 } | 276 } |
147 } // for all rows | 277 } // for all rows |
148 | 278 |
149 if (log.isDebugEnabled()) { | 279 if (log.isDebugEnabled()) { |
150 log.debug("culled points: " + culled); | 280 log.debug("culled points: " + culled); |
281 log.debug("extrapolated points: " + extrapolated); | |
151 log.debug("min/max i: " + minI + " / " + maxI); | 282 log.debug("min/max i: " + minI + " / " + maxI); |
152 log.debug("min/max j: " + minJ + " / " + maxJ); | 283 log.debug("min/max j: " + minJ + " / " + maxJ); |
153 log.debug("cells found: " + cells.size()); | 284 log.debug("cells found: " + cells.size()); |
154 } | 285 } |
155 | 286 |
156 return cells; | 287 return cells; |
157 } | 288 } |
289 | |
290 private static Point2d get( | |
291 HashMap<Integer, HashMap<Integer, Point2d>> rows, | |
292 int i, int j | |
293 ) { | |
294 HashMap<Integer, Point2d> row = rows.get(i); | |
295 return row != null ? row.get(j) : null; | |
296 } | |
297 | |
298 private static void put( | |
299 HashMap<Integer, HashMap<Integer, Point2d>> rows, | |
300 Point2d point, | |
301 int i, int j | |
302 ) { | |
303 Integer I = Integer.valueOf(i); | |
304 HashMap<Integer, Point2d> row = rows.get(I); | |
305 if (row == null) { | |
306 rows.put(I, row = new HashMap<Integer, Point2d>()); | |
307 } | |
308 row.put(j, point); | |
309 } | |
158 } | 310 } |
159 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : | 311 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |