svn-gvsig-desktop / branches / v2_0_0_prep / extensions / extRasterTools-SE / src / org / gvsig / rastertools / vectorizacion / process / ContourLinesProcess.java @ 28155
History | View | Annotate | Download (13.9 KB)
1 |
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
---|---|
2 |
*
|
3 |
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
|
4 |
*
|
5 |
* This program is free software; you can redistribute it and/or
|
6 |
* modify it under the terms of the GNU General Public License
|
7 |
* as published by the Free Software Foundation; either version 2
|
8 |
* of the License, or (at your option) any later version.
|
9 |
*
|
10 |
* This program is distributed in the hope that it will be useful,
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
* GNU General Public License for more details.
|
14 |
*
|
15 |
* You should have received a copy of the GNU General Public License
|
16 |
* along with this program; if not, write to the Free Software
|
17 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
18 |
*/
|
19 |
package org.gvsig.rastertools.vectorizacion.process; |
20 |
|
21 |
import java.io.File; |
22 |
import java.sql.Types; |
23 |
|
24 |
import org.gvsig.fmap.crs.CRSFactory; |
25 |
import org.gvsig.fmap.dal.DALLocator; |
26 |
import org.gvsig.fmap.dal.DataManager; |
27 |
import org.gvsig.fmap.dal.DataTypes; |
28 |
import org.gvsig.fmap.dal.exception.DataException; |
29 |
import org.gvsig.fmap.dal.exception.ValidateDataParametersException; |
30 |
import org.gvsig.fmap.dal.feature.EditableFeature; |
31 |
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor; |
32 |
import org.gvsig.fmap.dal.feature.EditableFeatureType; |
33 |
import org.gvsig.fmap.dal.feature.FeatureStore; |
34 |
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters; |
35 |
import org.gvsig.fmap.dal.feature.impl.DefaultEditableFeatureType; |
36 |
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer; |
37 |
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters; |
38 |
import org.gvsig.fmap.geom.Geometry; |
39 |
import org.gvsig.fmap.geom.GeometryLocator; |
40 |
import org.gvsig.fmap.geom.GeometryManager; |
41 |
import org.gvsig.fmap.geom.Geometry.SUBTYPES; |
42 |
import org.gvsig.fmap.geom.exception.CreateGeometryException; |
43 |
import org.gvsig.fmap.geom.primitive.GeneralPathX; |
44 |
import org.gvsig.fmap.raster.layers.FLyrRasterSE; |
45 |
import org.gvsig.raster.RasterProcess; |
46 |
import org.gvsig.raster.buffer.RasterBufferInvalidException; |
47 |
import org.gvsig.raster.datastruct.Extent; |
48 |
import org.gvsig.raster.grid.Grid; |
49 |
import org.gvsig.raster.grid.GridException; |
50 |
import org.gvsig.raster.grid.GridExtent; |
51 |
import org.gvsig.raster.process.RasterTask; |
52 |
import org.gvsig.raster.process.RasterTaskQueue; |
53 |
import org.gvsig.raster.util.RasterToolsUtil; |
54 |
|
55 |
/**
|
56 |
* Este proceso vectoriza la capa de entrada que debe estar ya preprocesada.
|
57 |
* 03/07/2008
|
58 |
* @author Victor Olaya (volaya@ya.com)
|
59 |
* @author Nacho Brodin nachobrodin@gmail.com
|
60 |
*/
|
61 |
public class ContourLinesProcess extends RasterProcess { |
62 |
private static final GeometryManager geomManager = GeometryLocator.getGeometryManager(); |
63 |
private FLyrRasterSE lyr = null; |
64 |
private double min = 0; |
65 |
private double max = 0; |
66 |
private double distance = 0; |
67 |
private Extent extent = null; |
68 |
private String fileName = null; |
69 |
|
70 |
private char[][] m_Row = null; |
71 |
private char[][] m_Col = null; |
72 |
private Grid grid = null; |
73 |
private FeatureStore fsWriter = null; |
74 |
private int m_iGeometry = 0; |
75 |
private double percent = 0; |
76 |
|
77 |
private class NextContourInfo { |
78 |
public int iDir; |
79 |
public int x; |
80 |
public int y; |
81 |
public boolean doRow; |
82 |
} |
83 |
|
84 |
/**
|
85 |
* Par?metros obligatorios al proceso:
|
86 |
* <UL>
|
87 |
* <LI></LI>
|
88 |
* <LI>filename: Nombre del fichero de salida</LI>
|
89 |
* <LI></LI>
|
90 |
* <LI></LI>
|
91 |
* <LI></LI>
|
92 |
* <LI></LI>
|
93 |
* </UL>
|
94 |
*/
|
95 |
public void init() { |
96 |
lyr = getLayerParam("layer");
|
97 |
fileName = getStringParam("filename");
|
98 |
min = getDoubleParam("min");
|
99 |
max = getDoubleParam("max");
|
100 |
distance = getDoubleParam("distance");
|
101 |
extent = getExtentParam("extent");
|
102 |
|
103 |
try{
|
104 |
EditableFeatureType featureType = getFeatureType(); |
105 |
|
106 |
EditableFeatureAttributeDescriptor efad = featureType.add("GEOMETRY", DataTypes.GEOMETRY);
|
107 |
efad.setGeometryType(Geometry.TYPES.CURVE); |
108 |
efad.setSRS(CRSFactory.getCRS("EPSG:23030"));
|
109 |
featureType.setDefaultGeometryAttributeName("GEOMETRY");
|
110 |
|
111 |
DataManager datamanager = DALLocator.getDataManager(); |
112 |
FilesystemServerExplorerParameters explorerParams; |
113 |
|
114 |
explorerParams = (FilesystemServerExplorerParameters) datamanager.createServerExplorerParameters(FilesystemServerExplorer.NAME); |
115 |
|
116 |
explorerParams.setRoot(new File(fileName).getParent()); |
117 |
FilesystemServerExplorer explorer = (FilesystemServerExplorer) datamanager.createServerExplorer(explorerParams); |
118 |
NewFeatureStoreParameters newParams = (NewFeatureStoreParameters) explorer.getAddParameters(new File(fileName)); |
119 |
|
120 |
newParams.setDefaultFeatureType(featureType); |
121 |
newParams.setDynValue("srs", CRSFactory.getCRS("EPSG:23030")); |
122 |
explorer.add(newParams, true);
|
123 |
DataManager manager = DALLocator.getDataManager(); |
124 |
|
125 |
fsWriter = (FeatureStore)manager.createStore(newParams); |
126 |
fsWriter.edit(FeatureStore.MODE_APPEND); |
127 |
} catch (DataException e) {
|
128 |
RasterToolsUtil.messageBoxError("error_loading_store", this, e); |
129 |
} catch (ValidateDataParametersException e) {
|
130 |
RasterToolsUtil.messageBoxError("error_loading_store", this, e); |
131 |
} |
132 |
} |
133 |
|
134 |
/**
|
135 |
* Tarea de recorte
|
136 |
*/
|
137 |
public void process() throws InterruptedException { |
138 |
GridExtent ge = null;
|
139 |
insertLineLog("Contour Lines");
|
140 |
if(extent != null) |
141 |
ge = new GridExtent(extent, lyr.getCellSize());
|
142 |
try {
|
143 |
grid = new Grid(lyr.getDataSource(), new int[]{0}, ge); |
144 |
|
145 |
if( min <= max && distance > 0 ) { |
146 |
if( min < grid.getMinValue() )
|
147 |
min += distance * (int)((grid.getMinValue() - min) / distance);
|
148 |
|
149 |
if( max > grid.getMaxValue() )
|
150 |
max = grid.getMaxValue(); |
151 |
|
152 |
createContours(min, max, distance); |
153 |
fsWriter.finishEditing(); |
154 |
} |
155 |
} catch (RasterBufferInvalidException e) {
|
156 |
RasterToolsUtil.messageBoxError("error_loading_grid", this, e); |
157 |
} catch (GridException e) {
|
158 |
RasterToolsUtil.messageBoxError("error_loading_grid", this, e); |
159 |
} catch (DataException e) {
|
160 |
RasterToolsUtil.messageBoxError("", this, e); |
161 |
} catch (CreateGeometryException e) {
|
162 |
RasterToolsUtil.messageBoxError("", this, e); |
163 |
} finally {
|
164 |
if (incrementableTask != null) { |
165 |
incrementableTask.processFinalize(); |
166 |
incrementableTask = null;
|
167 |
} |
168 |
} |
169 |
if(externalActions != null) |
170 |
externalActions.end(fileName); |
171 |
} |
172 |
|
173 |
private void createContours(double dMin, double dMax, double dDistance) throws InterruptedException, GridException, DataException, CreateGeometryException { |
174 |
int x, y;
|
175 |
int i;
|
176 |
int ID;
|
177 |
int iNX,iNY;
|
178 |
double dZ;
|
179 |
double dValue = 0; |
180 |
RasterTask task = RasterTaskQueue.get(Thread.currentThread().toString());
|
181 |
|
182 |
iNX = grid.getNX(); |
183 |
iNY = grid.getNY(); |
184 |
|
185 |
m_Row = new char[iNY][iNX]; |
186 |
m_Col = new char[iNY][iNX]; |
187 |
|
188 |
if( dDistance <= 0 ) |
189 |
dDistance= 1;
|
190 |
|
191 |
percent = 0;
|
192 |
for(dZ = dMin, ID = 0; dZ <= dMax; dZ += dDistance) { |
193 |
double increment = (25 / (iNY * (((dMax - dMin) / dDistance) + 1))); |
194 |
for(y = 0; y < iNY - 1; y++) { |
195 |
percent += increment; |
196 |
for(x = 0; x < iNX - 1; x++) { |
197 |
dValue = grid.getCellValue(y, x); |
198 |
if( dValue >= dZ ) {
|
199 |
m_Row[y][x] = (char) (grid.getCellValue(y, x + 1) < dZ ? 1 : 0); |
200 |
m_Col[y][x] = (char) (grid.getCellValue(y + 1, x) < dZ ? 1 : 0); |
201 |
} |
202 |
else {
|
203 |
m_Row[y][x] = (char) (grid.getCellValue(y, x + 1) >= dZ ? 1 : 0); |
204 |
m_Col[y][x] = (char) (grid.getCellValue(y + 1, x) >= dZ ? 1 : 0); |
205 |
} |
206 |
} |
207 |
if(task.getEvent() != null) |
208 |
task.manageEvent(task.getEvent()); |
209 |
} |
210 |
|
211 |
increment = (75 / (iNY * (((dMax - dMin) / dDistance) + 1))); |
212 |
for(y = 0; y < iNY - 1; y++) { |
213 |
percent += increment; |
214 |
for(x = 0; x < iNX - 1; x++) { |
215 |
if(m_Row[y][x] != 0) { |
216 |
for(i = 0; i < 2; i++) |
217 |
findContour(x, y, dZ, true, ID++);
|
218 |
m_Row[y][x] = 0;
|
219 |
} |
220 |
|
221 |
if(m_Col[y][x] != 0) { |
222 |
for(i=0; i<2; i++) |
223 |
findContour(x, y, dZ, false, ID++);
|
224 |
m_Col[y][x] = 0;
|
225 |
} |
226 |
} |
227 |
if(task.getEvent() != null) |
228 |
task.manageEvent(task.getEvent()); |
229 |
} |
230 |
} |
231 |
} |
232 |
|
233 |
private void findContour(int x, int y, double z, boolean doRow, int ID) throws GridException, InterruptedException, DataException, CreateGeometryException { |
234 |
boolean doContinue = true; |
235 |
boolean bIsFirstPoint = true; |
236 |
int zx = doRow ? x + 1 : x; |
237 |
int zy = doRow ? y : y + 1; |
238 |
double d = 0; |
239 |
double xPos, yPos;
|
240 |
double xMin = grid.getGridExtent().getMin().getX();
|
241 |
double yMax = grid.getGridExtent().getMax().getY();
|
242 |
Geometry line; |
243 |
Object values[] = new Object[2]; |
244 |
NextContourInfo info = new NextContourInfo();
|
245 |
GeneralPathX genPathX = new GeneralPathX();
|
246 |
|
247 |
info.x = x; |
248 |
info.y = y; |
249 |
info.iDir = 0;
|
250 |
info.doRow = doRow; |
251 |
|
252 |
do{
|
253 |
d = grid.getCellValue(info.y, info.x); |
254 |
d = (d - z) / (d - grid.getCellValue(zy, zx)); |
255 |
|
256 |
xPos = xMin + grid.getCellSize() * (info.x + d * (zx - info.x) + 0.5);
|
257 |
yPos = yMax - grid.getCellSize() * (info.y + d * (zy - info.y) + 0.5);
|
258 |
|
259 |
if (bIsFirstPoint) {
|
260 |
genPathX.moveTo(xPos, yPos); |
261 |
bIsFirstPoint = false;
|
262 |
} else
|
263 |
genPathX.lineTo(xPos, yPos); |
264 |
|
265 |
if( !findNextContour(info) )
|
266 |
doContinue = findNextContour(info); |
267 |
|
268 |
info.iDir = (info.iDir + 5) % 8; |
269 |
|
270 |
if(info.doRow) {
|
271 |
m_Row[info.y][info.x] = 0;
|
272 |
zx = info.x + 1;
|
273 |
zy = info.y; |
274 |
} else {
|
275 |
m_Col[info.y][info.x] = 0;
|
276 |
zx = info.x; |
277 |
zy = info.y + 1;
|
278 |
} |
279 |
|
280 |
} |
281 |
while(doContinue);
|
282 |
|
283 |
values[0] = new Double(ID); |
284 |
values[1] = new Double(z); |
285 |
|
286 |
line = geomManager.createCurve(genPathX, SUBTYPES.GEOM2D); |
287 |
addGeometry(line, values); |
288 |
} |
289 |
|
290 |
private boolean findNextContour(NextContourInfo info) { |
291 |
boolean doContinue;
|
292 |
|
293 |
if(info.doRow)
|
294 |
switch(info.iDir) {
|
295 |
case 0: |
296 |
if(m_Row[info.y + 1][info.x] != 0) { |
297 |
info.y++; |
298 |
info.iDir = 0;
|
299 |
doContinue = true;
|
300 |
break;
|
301 |
} |
302 |
case 1: |
303 |
if(m_Col[info.y][info.x + 1] != 0) { |
304 |
info.x++; |
305 |
info.iDir = 1;
|
306 |
info.doRow = false;
|
307 |
doContinue = true;
|
308 |
break;
|
309 |
} |
310 |
case 2: |
311 |
case 3: |
312 |
if(info.y-1 >= 0) |
313 |
if(m_Col[info.y - 1][info.x + 1] != 0) { |
314 |
info.x++; |
315 |
info.y--; |
316 |
info.doRow = false;
|
317 |
info.iDir = 3;
|
318 |
doContinue = true;
|
319 |
break;
|
320 |
} |
321 |
case 4: |
322 |
if(info.y-1>=0) |
323 |
if(m_Row[info.y - 1][info.x]!= 0) { |
324 |
info.y--; |
325 |
info.iDir = 4;
|
326 |
doContinue = true;
|
327 |
break;
|
328 |
} |
329 |
case 5: |
330 |
if(info.y-1>=0) |
331 |
if(m_Col[info.y - 1][info.x] != 0) { |
332 |
info.y--; |
333 |
info.doRow = false;
|
334 |
info.iDir = 5 ;
|
335 |
doContinue = true;
|
336 |
break;
|
337 |
} |
338 |
case 6: |
339 |
case 7: |
340 |
if(m_Col[info.y][info.x]!= 0) { |
341 |
info.doRow = false;
|
342 |
info.iDir = 7;
|
343 |
doContinue = true;
|
344 |
break;
|
345 |
} |
346 |
default:
|
347 |
info.iDir = 0;
|
348 |
doContinue = false;
|
349 |
} |
350 |
else
|
351 |
switch(info.iDir) {
|
352 |
case 0: |
353 |
case 1: |
354 |
if(m_Row[info.y + 1][info.x] != 0) { |
355 |
info.y++; |
356 |
info.doRow = true;
|
357 |
info.iDir = 1;
|
358 |
doContinue = true;
|
359 |
break;
|
360 |
} |
361 |
case 2: |
362 |
if(m_Col[info.y][info.x + 1] != 0) { |
363 |
info.x++; |
364 |
info.iDir = 2;
|
365 |
doContinue = true;
|
366 |
break;
|
367 |
} |
368 |
case 3: |
369 |
if(m_Row[info.y][info.x] != 0) { |
370 |
info.doRow = true;
|
371 |
info.iDir = 3;
|
372 |
doContinue = true;
|
373 |
break;
|
374 |
} |
375 |
case 4: |
376 |
case 5: |
377 |
if(info.x-1>=0) |
378 |
if(m_Row[info.y][info.x - 1] != 0) { |
379 |
info.x--; |
380 |
info.doRow = true;
|
381 |
info.iDir = 5;
|
382 |
doContinue = true;
|
383 |
break;
|
384 |
} |
385 |
case 6: |
386 |
if(info.x-1>=0) |
387 |
if(m_Col[info.y][info.x - 1] != 0) { |
388 |
info.x--; |
389 |
info.iDir = 6;
|
390 |
doContinue = true;
|
391 |
break;
|
392 |
} |
393 |
case 7: |
394 |
if(info.x-1 >= 0) |
395 |
if(m_Row[info.y + 1][info.x - 1] != 0) { |
396 |
info.x--; |
397 |
info.y++; |
398 |
info.doRow = true;
|
399 |
info.iDir = 7;
|
400 |
doContinue = true;
|
401 |
break;
|
402 |
} |
403 |
default:
|
404 |
info.iDir = 0;
|
405 |
doContinue = false;
|
406 |
} |
407 |
|
408 |
return(doContinue);
|
409 |
} |
410 |
|
411 |
/*
|
412 |
* (non-Javadoc)
|
413 |
* @see org.gvsig.gui.beans.incrementabletask.IIncrementable#getPercent()
|
414 |
*/
|
415 |
public int getPercent() { |
416 |
return (int)percent; |
417 |
} |
418 |
|
419 |
/*
|
420 |
* (non-Javadoc)
|
421 |
* @see org.gvsig.gui.beans.incrementabletask.IIncrementable#getTitle()
|
422 |
*/
|
423 |
public String getTitle() { |
424 |
return RasterToolsUtil.getText(this, "vectorization"); |
425 |
} |
426 |
|
427 |
// public void addShape(FShape shape, Value[] value) throws Exception {
|
428 |
// if (shape == null)
|
429 |
// return;
|
430 |
// IGeometry geom = ShapeFactory.createGeometry(shape);
|
431 |
// addGeometry(geom, value);
|
432 |
// }
|
433 |
|
434 |
public void addGeometry(Geometry geom, Object[] value) throws DataException { |
435 |
m_iGeometry++; |
436 |
EditableFeature ef = fsWriter.createNewFeature(); |
437 |
ef.set("ID", value[0]); |
438 |
ef.set("NAME", value[1]); |
439 |
ef.setGeometry("GEOMETRY", geom);
|
440 |
fsWriter.insert(ef); |
441 |
} |
442 |
private EditableFeatureType getFeatureType(){
|
443 |
EditableFeatureType eft=new DefaultEditableFeatureType();
|
444 |
|
445 |
EditableFeatureAttributeDescriptor efad1=eft.add("ID", DataTypes.DOUBLE);
|
446 |
efad1.setPrecision(5);
|
447 |
EditableFeatureAttributeDescriptor efad2=eft.add("NAME", DataTypes.DOUBLE);
|
448 |
efad2.setPrecision(5);
|
449 |
|
450 |
return eft;
|
451 |
} |
452 |
/**
|
453 |
* Returns the length of field
|
454 |
* @param dataType
|
455 |
* @return length of field
|
456 |
*/
|
457 |
public int getDataTypeLength(int dataType) { |
458 |
switch (dataType) {
|
459 |
case Types.NUMERIC: |
460 |
case Types.DOUBLE: |
461 |
case Types.REAL: |
462 |
case Types.FLOAT: |
463 |
case Types.BIGINT: |
464 |
case Types.INTEGER: |
465 |
case Types.DECIMAL: |
466 |
return 20; |
467 |
case Types.CHAR: |
468 |
case Types.VARCHAR: |
469 |
case Types.LONGVARCHAR: |
470 |
return 254; |
471 |
case Types.DATE: |
472 |
return 8; |
473 |
case Types.BOOLEAN: |
474 |
case Types.BIT: |
475 |
return 1; |
476 |
} |
477 |
return 0; |
478 |
} |
479 |
} |