root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / vectorize / contourLines / ContourLinesAlgorithm.java @ 59
History | View | Annotate | Download (11.3 KB)
1 |
package es.unex.sextante.vectorize.contourLines; |
---|---|
2 |
|
3 |
import java.util.ArrayList; |
4 |
|
5 |
import com.vividsolutions.jts.geom.Coordinate; |
6 |
import com.vividsolutions.jts.geom.Geometry; |
7 |
import com.vividsolutions.jts.geom.GeometryFactory; |
8 |
|
9 |
import es.unex.sextante.additionalInfo.AdditionalInfoNumericalValue; |
10 |
import es.unex.sextante.core.GeoAlgorithm; |
11 |
import es.unex.sextante.core.Sextante; |
12 |
import es.unex.sextante.dataObjects.IRasterLayer; |
13 |
import es.unex.sextante.dataObjects.IVectorLayer; |
14 |
import es.unex.sextante.exceptions.RepeatedParameterNameException; |
15 |
import es.unex.sextante.outputs.OutputVectorLayer; |
16 |
|
17 |
public class ContourLinesAlgorithm |
18 |
extends
|
19 |
GeoAlgorithm { |
20 |
|
21 |
public static final String LAYER = "LAYER"; |
22 |
public static final String DISTANCE = "DISTANCE"; |
23 |
public static final String MIN = "MIN"; |
24 |
public static final String MAX = "MAX"; |
25 |
public static final String RESULT = "RESULT"; |
26 |
|
27 |
private IRasterLayer m_Window;
|
28 |
private IVectorLayer m_Contour;
|
29 |
private char[][] m_Row; |
30 |
private char[][] m_Col; |
31 |
private final GeometryFactory m_GF = new GeometryFactory(); |
32 |
|
33 |
|
34 |
@Override
|
35 |
public void defineCharacteristics() { |
36 |
|
37 |
setName(Sextante.getText("Contour_lines"));
|
38 |
setGroup(Sextante.getText("Vectorization"));
|
39 |
setUserCanDefineAnalysisExtent(false);
|
40 |
|
41 |
try {
|
42 |
m_Parameters.addInputRasterLayer(LAYER, Sextante.getText("Input_layer"), true); |
43 |
m_Parameters.addNumericalValue(DISTANCE, Sextante.getText("Equidistance"),
|
44 |
AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE, 100, 0, Double.MAX_VALUE); |
45 |
m_Parameters.addNumericalValue(MIN, Sextante.getText("Min_value"), 0, |
46 |
AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
47 |
m_Parameters.addNumericalValue(MAX, Sextante.getText("Max_value"), 10000., |
48 |
AdditionalInfoNumericalValue.NUMERICAL_VALUE_DOUBLE); |
49 |
addOutputVectorLayer(RESULT, Sextante.getText("Contour_lines"), OutputVectorLayer.SHAPE_TYPE_LINE);
|
50 |
} |
51 |
catch (final RepeatedParameterNameException e) { |
52 |
Sextante.addErrorToLog(e); |
53 |
} |
54 |
|
55 |
} |
56 |
|
57 |
|
58 |
@Override
|
59 |
public boolean processAlgorithm() { |
60 |
|
61 |
double dMin, dMax;
|
62 |
double dDistance;
|
63 |
final String sFields[] = new String[2]; |
64 |
final Class types[] = { Integer.class, Double.class }; |
65 |
|
66 |
try {
|
67 |
|
68 |
m_Window = m_Parameters.getParameterValueAsRasterLayer(LAYER); |
69 |
dMin = m_Parameters.getParameterValueAsDouble(MIN); |
70 |
dMax = m_Parameters.getParameterValueAsDouble(MAX); |
71 |
dDistance = m_Parameters.getParameterValueAsDouble(DISTANCE); |
72 |
|
73 |
m_Window.setFullExtent(); |
74 |
|
75 |
if ((dMin <= dMax) && (dDistance > 0)) { |
76 |
if (dMin < m_Window.getMinValue()) {
|
77 |
dMin += dDistance * (int) ((m_Window.getMinValue() - dMin) / dDistance);
|
78 |
} |
79 |
if (dMax > m_Window.getMaxValue()) {
|
80 |
dMax = m_Window.getMaxValue(); |
81 |
} |
82 |
|
83 |
sFields[0] = "ID"; |
84 |
sFields[1] = "Elevation"; |
85 |
|
86 |
m_Contour = getNewVectorLayer(RESULT, Sextante.getText("Contour_lines"), IVectorLayer.SHAPE_TYPE_LINE, types, sFields);
|
87 |
|
88 |
createContours(dMin, dMax, dDistance); |
89 |
|
90 |
return !m_Task.isCanceled();
|
91 |
} |
92 |
|
93 |
return false; |
94 |
|
95 |
} |
96 |
catch (final Exception e) { |
97 |
Sextante.addErrorToLog(e); |
98 |
return false; |
99 |
} |
100 |
|
101 |
} |
102 |
|
103 |
|
104 |
private void createContours(final double dMin, |
105 |
final double dMax, |
106 |
double dDistance) {
|
107 |
|
108 |
int x, y;
|
109 |
int i;
|
110 |
int ID;
|
111 |
int iNX, iNY;
|
112 |
double dZ;
|
113 |
double dValue = 0; |
114 |
|
115 |
iNX = m_Window.getNX(); |
116 |
iNY = m_Window.getNY(); |
117 |
|
118 |
m_Row = new char[iNY][iNX]; |
119 |
m_Col = new char[iNY][iNX]; |
120 |
|
121 |
if (dDistance <= 0) { |
122 |
dDistance = 1;
|
123 |
} |
124 |
|
125 |
for (dZ = dMin, ID = 0; (dZ <= dMax) && setProgress((int) (dZ - dMin), (int) (dMax - dMin)); dZ += dDistance) { |
126 |
for (y = 0; y < iNY - 1; y++) { |
127 |
for (x = 0; x < iNX - 1; x++) { |
128 |
dValue = m_Window.getCellValueAsDouble(x, y); |
129 |
if (dValue >= dZ) {
|
130 |
m_Row[y][x] = (char) (m_Window.getCellValueAsDouble(x + 1, y) < dZ ? 1 : 0); |
131 |
m_Col[y][x] = (char) (m_Window.getCellValueAsDouble(x, y + 1) < dZ ? 1 : 0); |
132 |
} |
133 |
else {
|
134 |
m_Row[y][x] = (char) (m_Window.getCellValueAsDouble(x + 1, y) >= dZ ? 1 : 0); |
135 |
m_Col[y][x] = (char) (m_Window.getCellValueAsDouble(x, y + 1) >= dZ ? 1 : 0); |
136 |
} |
137 |
} |
138 |
} |
139 |
|
140 |
for (y = 0; y < iNY - 1; y++) { |
141 |
for (x = 0; x < iNX - 1; x++) { |
142 |
if (m_Row[y][x] != 0) { |
143 |
for (i = 0; i < 2; i++) { |
144 |
findContour(x, y, dZ, true, ID++);
|
145 |
} |
146 |
m_Row[y][x] = 0;
|
147 |
} |
148 |
|
149 |
if (m_Col[y][x] != 0) { |
150 |
for (i = 0; i < 2; i++) { |
151 |
findContour(x, y, dZ, false, ID++);
|
152 |
} |
153 |
m_Col[y][x] = 0;
|
154 |
} |
155 |
} |
156 |
} |
157 |
|
158 |
} |
159 |
|
160 |
} |
161 |
|
162 |
|
163 |
private void findContour(final int x, |
164 |
final int y, |
165 |
final double z, |
166 |
final boolean doRow, |
167 |
final int ID) { |
168 |
|
169 |
boolean doContinue = true; |
170 |
final boolean bIsFirstPoint = true; |
171 |
int zx = doRow ? x + 1 : x; |
172 |
int zy = doRow ? y : y + 1; |
173 |
double d;
|
174 |
double xPos, yPos;
|
175 |
final double xMin = m_Window.getWindowGridExtent().getXMin(); |
176 |
final double yMax = m_Window.getWindowGridExtent().getYMax(); |
177 |
Geometry line; |
178 |
final Object values[] = new Object[2]; |
179 |
final NextContourInfo info = new NextContourInfo(); |
180 |
final ArrayList<Coordinate> coords = new ArrayList<Coordinate>(); |
181 |
|
182 |
info.x = x; |
183 |
info.y = y; |
184 |
info.iDir = 0;
|
185 |
info.doRow = doRow; |
186 |
|
187 |
do {
|
188 |
|
189 |
d = m_Window.getCellValueAsDouble(info.x, info.y); |
190 |
d = (d - z) / (d - m_Window.getCellValueAsDouble(zx, zy)); |
191 |
|
192 |
xPos = xMin + m_Window.getWindowCellSize() * (info.x + d * (zx - info.x) + 0.5);
|
193 |
yPos = yMax - m_Window.getWindowCellSize() * (info.y + d * (zy - info.y) + 0.5);
|
194 |
|
195 |
coords.add(new Coordinate(xPos, yPos));
|
196 |
|
197 |
if (!findNextContour(info)) {
|
198 |
doContinue = findNextContour(info); |
199 |
} |
200 |
|
201 |
info.iDir = (info.iDir + 5) % 8; |
202 |
|
203 |
if (info.doRow) {
|
204 |
m_Row[info.y][info.x] = 0;
|
205 |
zx = info.x + 1;
|
206 |
zy = info.y; |
207 |
} |
208 |
else {
|
209 |
m_Col[info.y][info.x] = 0;
|
210 |
zx = info.x; |
211 |
zy = info.y + 1;
|
212 |
} |
213 |
|
214 |
} |
215 |
while (doContinue);
|
216 |
|
217 |
values[0] = new Integer(ID); |
218 |
values[1] = new Double(z); |
219 |
|
220 |
final Coordinate[] coordinates = new Coordinate[coords.size()]; |
221 |
for (int i = 0; i < coordinates.length; i++) { |
222 |
coordinates[i] = coords.get(i); |
223 |
} |
224 |
|
225 |
if (coordinates.length > 1) { |
226 |
line = m_GF.createLineString(coordinates); |
227 |
m_Contour.addFeature(line, values); |
228 |
} |
229 |
|
230 |
} |
231 |
|
232 |
|
233 |
private boolean findNextContour(final NextContourInfo info) { |
234 |
|
235 |
boolean doContinue;
|
236 |
|
237 |
if (info.doRow) {
|
238 |
switch (info.iDir) {
|
239 |
case 0: |
240 |
if (m_Row[info.y + 1][info.x] != 0) { |
241 |
info.y++; |
242 |
info.iDir = 0;
|
243 |
doContinue = true;
|
244 |
break;
|
245 |
} |
246 |
case 1: |
247 |
if (m_Col[info.y][info.x + 1] != 0) { |
248 |
info.x++; |
249 |
info.iDir = 1;
|
250 |
info.doRow = false;
|
251 |
doContinue = true;
|
252 |
break;
|
253 |
} |
254 |
case 2: |
255 |
case 3: |
256 |
if (info.y - 1 >= 0) { |
257 |
if (m_Col[info.y - 1][info.x + 1] != 0) { |
258 |
info.x++; |
259 |
info.y--; |
260 |
info.doRow = false;
|
261 |
info.iDir = 3;
|
262 |
doContinue = true;
|
263 |
break;
|
264 |
} |
265 |
} |
266 |
case 4: |
267 |
if (info.y - 1 >= 0) { |
268 |
if (m_Row[info.y - 1][info.x] != 0) { |
269 |
info.y--; |
270 |
info.iDir = 4;
|
271 |
doContinue = true;
|
272 |
break;
|
273 |
} |
274 |
} |
275 |
case 5: |
276 |
if (info.y - 1 >= 0) { |
277 |
if (m_Col[info.y - 1][info.x] != 0) { |
278 |
info.y--; |
279 |
info.doRow = false;
|
280 |
info.iDir = 5;
|
281 |
doContinue = true;
|
282 |
break;
|
283 |
} |
284 |
} |
285 |
case 6: |
286 |
case 7: |
287 |
if (m_Col[info.y][info.x] != 0) { |
288 |
info.doRow = false;
|
289 |
info.iDir = 7;
|
290 |
doContinue = true;
|
291 |
break;
|
292 |
} |
293 |
default:
|
294 |
info.iDir = 0;
|
295 |
doContinue = false;
|
296 |
} |
297 |
} |
298 |
else {
|
299 |
switch (info.iDir) {
|
300 |
case 0: |
301 |
case 1: |
302 |
if (m_Row[info.y + 1][info.x] != 0) { |
303 |
info.y++; |
304 |
info.doRow = true;
|
305 |
info.iDir = 1;
|
306 |
doContinue = true;
|
307 |
break;
|
308 |
} |
309 |
case 2: |
310 |
if (m_Col[info.y][info.x + 1] != 0) { |
311 |
info.x++; |
312 |
info.iDir = 2;
|
313 |
doContinue = true;
|
314 |
break;
|
315 |
} |
316 |
case 3: |
317 |
if (m_Row[info.y][info.x] != 0) { |
318 |
info.doRow = true;
|
319 |
info.iDir = 3;
|
320 |
doContinue = true;
|
321 |
break;
|
322 |
} |
323 |
case 4: |
324 |
case 5: |
325 |
if (info.x - 1 >= 0) { |
326 |
if (m_Row[info.y][info.x - 1] != 0) { |
327 |
info.x--; |
328 |
info.doRow = true;
|
329 |
info.iDir = 5;
|
330 |
doContinue = true;
|
331 |
break;
|
332 |
} |
333 |
} |
334 |
case 6: |
335 |
if (info.x - 1 >= 0) { |
336 |
if (m_Col[info.y][info.x - 1] != 0) { |
337 |
info.x--; |
338 |
info.iDir = 6;
|
339 |
doContinue = true;
|
340 |
break;
|
341 |
} |
342 |
} |
343 |
case 7: |
344 |
if (info.x - 1 >= 0) { |
345 |
if (m_Row[info.y + 1][info.x - 1] != 0) { |
346 |
info.x--; |
347 |
info.y++; |
348 |
info.doRow = true;
|
349 |
info.iDir = 7;
|
350 |
doContinue = true;
|
351 |
break;
|
352 |
} |
353 |
} |
354 |
default:
|
355 |
info.iDir = 0;
|
356 |
doContinue = false;
|
357 |
} |
358 |
} |
359 |
|
360 |
return (doContinue);
|
361 |
} |
362 |
|
363 |
private class NextContourInfo { |
364 |
|
365 |
public int iDir; |
366 |
public int x; |
367 |
public int y; |
368 |
public boolean doRow; |
369 |
|
370 |
} |
371 |
|
372 |
} |