Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/math/AreaInterpolation.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 | 05bf8534a35a |
children | f953c9a559d8 |
comparison
equal
deleted
inserted
replaced
722:bb3ffe7d719e | 875:5e9efdda6894 |
---|---|
1 package de.intevation.gnv.math; | |
2 | |
3 import com.vividsolutions.jts.geom.Coordinate; | |
4 import com.vividsolutions.jts.geom.Envelope; | |
5 | |
6 import com.vividsolutions.jts.index.strtree.STRtree; | |
7 | |
8 import java.awt.Dimension; | |
9 | |
10 import java.io.Serializable; | |
11 | |
12 import java.util.Arrays; | |
13 import java.util.List; | |
14 | |
15 import org.apache.log4j.Logger; | |
16 | |
17 /** | |
18 * Does an area interpolation for "Horizontalschnitte". | |
19 * | |
20 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> | |
21 */ | |
22 public class AreaInterpolation | |
23 implements Serializable | |
24 { | |
25 private static Logger log = Logger.getLogger(AreaInterpolation.class); | |
26 | |
27 /** | |
28 * The generated raster. | |
29 */ | |
30 protected double [] raster; | |
31 | |
32 /** | |
33 * The width of the raster. | |
34 */ | |
35 protected int width; | |
36 /** | |
37 * The height of the raster. | |
38 */ | |
39 protected int height; | |
40 | |
41 /** | |
42 * Default constructor. | |
43 */ | |
44 public AreaInterpolation() { | |
45 } | |
46 | |
47 /** | |
48 * Returns the width of the generated raster. | |
49 * @return the width of the raster. | |
50 */ | |
51 public int getWidth() { | |
52 return width; | |
53 } | |
54 | |
55 /** | |
56 * Returns the height of the raster. | |
57 * @return The height of the raster. | |
58 */ | |
59 public int getHeight() { | |
60 return height; | |
61 } | |
62 | |
63 /** | |
64 * The generated raster. | |
65 * @return the raster. | |
66 */ | |
67 public double [] getRaster() { | |
68 return raster; | |
69 } | |
70 | |
71 /** | |
72 * Epsilon for numerical stability. | |
73 */ | |
74 public static final double EPS = 1e-6d; | |
75 | |
76 | |
77 /** | |
78 * Fills a raster by interpolating the input values. | |
79 * @param points The attributed input values. | |
80 * @param boundingBox The world area where to interpolate. | |
81 * @param samples The width and height of the raster. | |
82 * @param depth The callback to query the depth at a given point. | |
83 * @param extrapolationRounds Number of extrapolation point layers | |
84 * to generate before doing the interpolation. | |
85 * @return true if the interpolation succeeds else false. | |
86 */ | |
87 public boolean interpolate( | |
88 List<? extends Point2d> points, | |
89 Envelope boundingBox, | |
90 Dimension samples, | |
91 XYDepth depth, | |
92 int extrapolationRounds | |
93 ) { | |
94 boolean debug = log.isDebugEnabled(); | |
95 | |
96 if (points == null || points.isEmpty()) { | |
97 log.warn("no points to interpolate"); | |
98 return false; | |
99 } | |
100 | |
101 List<GridCell> cells = GridCell.pointsToGridCells( | |
102 points, | |
103 Interpolation2D.relevantArea( | |
104 boundingBox, | |
105 points), | |
106 extrapolationRounds); | |
107 | |
108 if (cells.isEmpty()) { | |
109 log.warn("no cells to interpolate"); | |
110 return false; | |
111 } | |
112 | |
113 int W = samples.width; | |
114 int H = samples.height; | |
115 | |
116 double cellWidth = boundingBox.getWidth() / W; | |
117 double cellHeight = boundingBox.getHeight() / H; | |
118 | |
119 STRtree spatialIndex = new STRtree(); | |
120 | |
121 for (GridCell cell: cells) { | |
122 spatialIndex.insert(cell.getEnvelope(), cell); | |
123 } | |
124 | |
125 if (debug) { | |
126 log.debug("width: " + boundingBox.getWidth()); | |
127 log.debug("height: " + boundingBox.getHeight()); | |
128 log.debug("sample width: " + W); | |
129 log.debug("sample height: " + H); | |
130 log.debug("cell width: " + cellWidth); | |
131 log.debug("cell height: " + cellHeight); | |
132 } | |
133 | |
134 Envelope queryBuffer = new Envelope(); | |
135 Coordinate center = new Coordinate(); | |
136 GridCell.CellFinder finder = new GridCell.CellFinder(); | |
137 | |
138 double [] raster = new double[W*H]; | |
139 Arrays.fill(raster, Double.NaN); | |
140 | |
141 double minX = boundingBox.getMinX(); | |
142 double minY = boundingBox.getMinY(); | |
143 | |
144 long startTime = System.currentTimeMillis(); | |
145 | |
146 int pos = 0; | |
147 for (int j = 0; j < H; ++j) { | |
148 | |
149 double y = j*cellHeight + 0.5d*cellHeight + minY; | |
150 double x = 0.5d*cellWidth + minX; | |
151 | |
152 for (int end = pos + W; pos < end; ++pos, x += cellWidth) { | |
153 | |
154 queryBuffer.init(x - EPS, x + EPS, y - EPS, y + EPS); | |
155 center.x = x; center.y = y; | |
156 finder.prepare(center); | |
157 spatialIndex.query(queryBuffer, finder); | |
158 | |
159 GridCell found = finder.found; | |
160 | |
161 if (found == null || depth.depth(center) > 0d) { | |
162 continue; | |
163 } | |
164 | |
165 double z1 = Interpolation2D.interpolate( | |
166 found.p1.x, found.p1.z, | |
167 found.p2.x, found.p2.z, | |
168 center.x); | |
169 double z2 = Interpolation2D.interpolate( | |
170 found.p3.x, found.p3.z, | |
171 found.p4.x, found.p4.z, | |
172 center.x); | |
173 double y1 = Interpolation2D.interpolate( | |
174 found.p1.x, found.p1.y, | |
175 found.p2.x, found.p2.y, | |
176 center.x); | |
177 double y2 = Interpolation2D.interpolate( | |
178 found.p3.x, found.p3.y, | |
179 found.p4.x, found.p4.y, | |
180 center.x); | |
181 raster[pos] = Interpolation2D.interpolate( | |
182 y1, z1, | |
183 y2, z2, | |
184 center.y); | |
185 } | |
186 } | |
187 | |
188 long stopTime = System.currentTimeMillis(); | |
189 | |
190 if (debug) { | |
191 log.debug("interpolation took: " + | |
192 (stopTime - startTime)/1000f + " secs"); | |
193 } | |
194 | |
195 this.raster = raster; | |
196 this.width = W; | |
197 this.height = H; | |
198 | |
199 return true; | |
200 } | |
201 } | |
202 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |