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 :

http://dive4elements.wald.intevation.org