Revision 10626 trunk/extensions/extGeoProcessing/src/com/iver/cit/gvsig/geoprocess/impl/dissolve/fmap/FeatureDissolver.java
FeatureDissolver.java | ||
---|---|---|
45 | 45 |
* |
46 | 46 |
* $Id$ |
47 | 47 |
* $Log$ |
48 |
* Revision 1.3 2006-08-11 16:27:46 azabala |
|
48 |
* Revision 1.4 2007-03-06 16:47:58 caballero |
|
49 |
* Exceptions |
|
50 |
* |
|
51 |
* Revision 1.3 2006/08/11 16:27:46 azabala |
|
49 | 52 |
* *** empty log message *** |
50 | 53 |
* |
51 | 54 |
* Revision 1.2 2006/07/27 17:21:06 azabala |
... | ... | |
75 | 78 |
|
76 | 79 |
import org.cresques.cts.ICoordTrans; |
77 | 80 |
|
78 |
import com.iver.cit.gvsig.fmap.DriverException; |
|
81 |
import com.hardcode.gdbms.driver.exceptions.ReadDriverException; |
|
82 |
import com.hardcode.gdbms.engine.data.driver.DriverException; |
|
83 |
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException; |
|
84 |
import com.iver.cit.gvsig.exceptions.visitors.ProcessVisitorException; |
|
85 |
import com.iver.cit.gvsig.exceptions.visitors.StartVisitorException; |
|
86 |
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException; |
|
87 |
import com.iver.cit.gvsig.exceptions.visitors.StopVisitorException; |
|
88 |
import com.iver.cit.gvsig.exceptions.visitors.VisitorException; |
|
79 | 89 |
import com.iver.cit.gvsig.fmap.core.IFeature; |
80 | 90 |
import com.iver.cit.gvsig.fmap.core.IGeometry; |
81 | 91 |
import com.iver.cit.gvsig.fmap.core.v02.FConverter; |
82 | 92 |
import com.iver.cit.gvsig.fmap.drivers.DriverIOException; |
83 |
import com.iver.cit.gvsig.fmap.edition.EditionException; |
|
84 | 93 |
import com.iver.cit.gvsig.fmap.layers.FBitSet; |
85 | 94 |
import com.iver.cit.gvsig.fmap.layers.FLayer; |
86 | 95 |
import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
... | ... | |
91 | 100 |
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor; |
92 | 101 |
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy; |
93 | 102 |
import com.iver.cit.gvsig.fmap.operations.strategies.StrategyManager; |
94 |
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException; |
|
95 | 103 |
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureProcessor; |
96 | 104 |
import com.iver.cit.gvsig.geoprocess.core.fmap.GeoprocessException; |
97 | 105 |
import com.iver.utiles.swing.threads.Cancellable; |
... | ... | |
105 | 113 |
* Dissolve features in base of a given dissolve criteria. |
106 | 114 |
* </p> |
107 | 115 |
* By 'dissolving' we understand the union of the geometry of many features |
108 |
*
|
|
116 |
* |
|
109 | 117 |
* @author azabala |
110 |
*
|
|
118 |
* |
|
111 | 119 |
*/ |
112 | 120 |
public class FeatureDissolver { |
113 | 121 |
|
... | ... | |
121 | 129 |
* Fetches attributes of disolved layer features |
122 | 130 |
*/ |
123 | 131 |
protected SelectableDataSource recordset; |
124 |
|
|
132 |
|
|
125 | 133 |
protected ICoordTrans ct; |
126 | 134 |
|
127 | 135 |
/** |
... | ... | |
133 | 141 |
/** |
134 | 142 |
* It marks all features that have already been dissolved (to avoid process |
135 | 143 |
* them in subsecuent steps) |
136 |
*
|
|
144 |
* |
|
137 | 145 |
*/ |
138 | 146 |
protected FBitSet dissolvedGeometries; |
139 | 147 |
|
... | ... | |
160 | 168 |
protected IDissolveCriteria dissolveCriteria; |
161 | 169 |
|
162 | 170 |
/** |
163 |
*
|
|
171 |
* |
|
164 | 172 |
* @param processor |
165 | 173 |
* @param layer |
166 | 174 |
* @throws GeoprocessException |
... | ... | |
181 | 189 |
recordset = ((AlphanumericData) layer).getRecordset(); |
182 | 190 |
ct = dissolvedLayer.getCoordTrans(); |
183 | 191 |
featureProcessor.start(); |
184 |
} catch (com.iver.cit.gvsig.fmap.DriverException e) {
|
|
192 |
} catch (ReadDriverException e) {
|
|
185 | 193 |
throw new GeoprocessException( |
186 | 194 |
"Error al acceder al recordset de la capa " |
187 | 195 |
+ layer.getName(), e); |
188 |
} catch (EditionException e) {
|
|
196 |
} catch (StartVisitorException e) {
|
|
189 | 197 |
throw new GeoprocessException( |
190 | 198 |
"Error al preparar donde se van a escribir los resultados del dissolve de la capa " |
191 | 199 |
+ layer.getName(), e); |
... | ... | |
217 | 225 |
this.featureProcessor.finish(); |
218 | 226 |
return; |
219 | 227 |
} |
220 |
|
|
228 |
|
|
221 | 229 |
//Ver si podemos optimizar esto de forma que solo |
222 | 230 |
//se procesasen los elementos no marcados en el bitset |
223 | 231 |
//(bitset de acceso aleatorio) |
224 |
|
|
232 |
|
|
225 | 233 |
if (!dissolvedGeometries.get(i)) { |
226 | 234 |
// if we havent processed this element yet |
227 | 235 |
try { |
... | ... | |
229 | 237 |
process( i, va, cancel); |
230 | 238 |
else if(dissolveType == ALPHANUMERIC_DISSOLVE) |
231 | 239 |
processAlphanumeric(i, va, cancel); |
232 |
} catch (DriverException e) { |
|
240 |
} catch (ReadDriverException e) {
|
|
233 | 241 |
throw new GeoprocessException( |
234 | 242 |
"Error accediendo a datos durante dissolve", e); |
235 |
} catch (VisitException e) {
|
|
243 |
} catch (ProcessVisitorException e) {
|
|
236 | 244 |
throw new GeoprocessException( |
237 | 245 |
"Error procesando datos durante dissolve", e); |
238 |
} catch (IOException e) {
|
|
246 |
} catch (ExpansionFileReadException e) {
|
|
239 | 247 |
throw new GeoprocessException( |
240 |
"Error de I/O durante dissolve", e); |
|
248 |
"Error accediendo a datos durante dissolve", e); |
|
249 |
} catch (VisitorException e) { |
|
250 |
throw new GeoprocessException( |
|
251 |
"Error accediendo a datos durante dissolve", e); |
|
241 | 252 |
} |
242 | 253 |
}// if |
243 | 254 |
}// for |
244 | 255 |
va.stop(); |
245 | 256 |
this.featureProcessor.finish(); |
246 |
} catch (DriverIOException e) { |
|
257 |
} catch (ReadDriverException e) { |
|
258 |
// TODO Auto-generated catch block |
|
247 | 259 |
e.printStackTrace(); |
260 |
} catch (StopVisitorException e) { |
|
261 |
// TODO Auto-generated catch block |
|
262 |
e.printStackTrace(); |
|
248 | 263 |
} |
249 | 264 |
} |
250 | 265 |
|
251 | 266 |
/** |
252 | 267 |
* Verifies cancelation events, and return a boolean flag if processes must |
253 | 268 |
* be stopped for this cancelations events. |
254 |
*
|
|
269 |
* |
|
255 | 270 |
* @param cancel |
256 | 271 |
* @param va |
257 | 272 |
* @param visitor |
... | ... | |
272 | 287 |
} |
273 | 288 |
|
274 | 289 |
class DissolveVisitor implements FeatureVisitor { |
275 |
|
|
290 |
|
|
276 | 291 |
IDissolveCriteria criteria; |
277 | 292 |
int index1; |
278 | 293 |
Stack stack; |
... | ... | |
293 | 308 |
this.cancel = cancel; |
294 | 309 |
} |
295 | 310 |
|
296 |
public void visit(IGeometry g, int index2) throws VisitException { |
|
311 |
public void visit(IGeometry g, int index2) throws VisitorException, ProcessVisitorException {
|
|
297 | 312 |
if(g == null) |
298 | 313 |
return; |
299 | 314 |
if (verifyCancelation(cancel, va)) { |
... | ... | |
302 | 317 |
featureProcessor.finish(); |
303 | 318 |
return; |
304 | 319 |
} |
305 |
|
|
320 |
|
|
306 | 321 |
if(index1 == index2){ |
307 | 322 |
//we dont want dissolve a feature with itself |
308 | 323 |
return; |
... | ... | |
320 | 335 |
stack.push(new Integer(index2)); |
321 | 336 |
try { |
322 | 337 |
if(criteria instanceof ISpatialDissolveCriteria){ |
323 |
//Para ver el criterio de disolucion ya se ha
|
|
338 |
//Para ver el criterio de disolucion ya se ha |
|
324 | 339 |
//leido la geometria |
325 | 340 |
geometries.add( |
326 | 341 |
((ISpatialDissolveCriteria)criteria). |
... | ... | |
332 | 347 |
geometries.add(g2.toJTSGeometry()); |
333 | 348 |
} |
334 | 349 |
sumarizer.applySumarizeFunction(index2); |
335 |
} catch (DriverIOException e) {
|
|
336 |
throw new VisitException(
|
|
337 |
"Error durante lectura de geometria en dissolve", e);
|
|
338 |
} catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
|
|
339 |
throw new VisitException(
|
|
340 |
"Error durante lectura de geometria en dissolve", e);
|
|
350 |
} catch (ReadDriverException e) {
|
|
351 |
throw new ProcessVisitorException(recordset.getName(),e,
|
|
352 |
"Error durante lectura de geometria en dissolve"); |
|
353 |
} catch (ExpansionFileReadException e) {
|
|
354 |
throw new ProcessVisitorException(recordset.getName(),e,
|
|
355 |
"Error durante lectura de geometria en dissolve");
|
|
341 | 356 |
} |
342 | 357 |
//Esto se debe hacer externamente |
343 | 358 |
if(stack == null) |
... | ... | |
349 | 364 |
return ""; |
350 | 365 |
} |
351 | 366 |
|
352 |
public void stop(FLayer layer) { |
|
367 |
public void stop(FLayer layer) throws VisitorException {
|
|
353 | 368 |
} |
354 | 369 |
|
355 |
public boolean start(FLayer layer) { |
|
370 |
public boolean start(FLayer layer) throws StartVisitorException {
|
|
356 | 371 |
return true; |
357 | 372 |
} |
358 | 373 |
} |
359 |
|
|
374 |
|
|
360 | 375 |
/** |
361 | 376 |
* @param index1 |
362 | 377 |
* @param va |
363 | 378 |
* @param cancel |
364 | 379 |
* @throws DriverException |
365 |
* @throws VisitException |
|
380 |
* @throws ExpansionFileReadException |
|
381 |
* @throws ReadDriverException |
|
382 |
* @throws VisitorException |
|
383 |
* @throws ProcessWriterException |
|
366 | 384 |
* @throws IOException |
367 | 385 |
* @throws DriverIOException |
368 | 386 |
*/ |
369 | 387 |
public void processAlphanumeric(int index1, |
370 |
ReadableVectorial va,
|
|
388 |
ReadableVectorial va, |
|
371 | 389 |
CancellableMonitorable cancel) |
372 |
throws DriverException, VisitException, IOException, |
|
373 |
DriverIOException{ |
|
374 |
|
|
390 |
throws ReadDriverException, ExpansionFileReadException, VisitorException{ |
|
391 |
|
|
375 | 392 |
dissolvedGeometries.set(index1); |
376 | 393 |
Strategy strategy = StrategyManager.getStrategy(dissolvedLayer); |
377 | 394 |
ArrayList geometries = new ArrayList(); |
... | ... | |
397 | 414 |
if(sumarizedValues != null || sumarizedValues.size() != 0){ |
398 | 415 |
dissolvedFeature = dissolveCriteria. |
399 | 416 |
getFeatureBuilder(). |
400 |
createFeature(newGeometry,
|
|
401 |
sumarizedValues,
|
|
402 |
fid,
|
|
417 |
createFeature(newGeometry, |
|
418 |
sumarizedValues, |
|
419 |
fid, |
|
403 | 420 |
index1); |
404 | 421 |
}else{ |
405 | 422 |
dissolvedFeature = dissolveCriteria. |
406 | 423 |
getFeatureBuilder(). |
407 | 424 |
createFeature(newGeometry, |
408 |
index1,
|
|
425 |
index1, |
|
409 | 426 |
fid); |
410 | 427 |
} |
411 | 428 |
fid++; |
412 | 429 |
featureProcessor.processFeature(dissolvedFeature); |
413 | 430 |
dissolveCriteria.clear(); |
414 | 431 |
} |
415 |
|
|
416 |
|
|
432 |
|
|
433 |
|
|
417 | 434 |
class SpatialDissolveVisitor implements FeatureVisitor { |
418 |
|
|
435 |
|
|
419 | 436 |
IDissolveCriteria criteria; |
420 | 437 |
Geometry geom1; |
421 | 438 |
StackEntry entry1; |
... | ... | |
425 | 442 |
FunctionSummarizer sumarizer; |
426 | 443 |
CancellableMonitorable cancel; |
427 | 444 |
|
428 |
SpatialDissolveVisitor(IDissolveCriteria criteria, Geometry geo1, StackEntry entry1,
|
|
445 |
SpatialDissolveVisitor(IDissolveCriteria criteria, Geometry geo1, StackEntry entry1, |
|
429 | 446 |
Stack stack, |
430 | 447 |
List geometries, ReadableVectorial va, |
431 | 448 |
FunctionSummarizer sumarizer, CancellableMonitorable cancel) { |
... | ... | |
438 | 455 |
this.sumarizer = sumarizer; |
439 | 456 |
this.cancel = cancel; |
440 | 457 |
} |
441 |
|
|
458 |
|
|
442 | 459 |
void setSeed(StackEntry entry, Geometry jtsGeo){ |
443 | 460 |
this.entry1 = entry; |
444 | 461 |
this.geom1 = jtsGeo; |
445 | 462 |
} |
446 |
|
|
447 |
|
|
448 | 463 |
|
449 |
public void visit(IGeometry g, int index2) throws VisitException { |
|
464 |
|
|
465 |
|
|
466 |
public void visit(IGeometry g, int index2) throws VisitorException, ProcessVisitorException { |
|
450 | 467 |
if(g == null) |
451 | 468 |
return; |
452 | 469 |
if (verifyCancelation(cancel, va)) { |
... | ... | |
455 | 472 |
featureProcessor.finish(); |
456 | 473 |
return; |
457 | 474 |
} |
458 |
|
|
475 |
|
|
459 | 476 |
if(entry1.index == index2){ |
460 | 477 |
//we dont want dissolve a feature with itself |
461 | 478 |
return; |
... | ... | |
483 | 500 |
geometries.add(g.toJTSGeometry()); |
484 | 501 |
try { |
485 | 502 |
sumarizer.applySumarizeFunction(index2); |
486 |
} catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
|
|
487 |
throw new VisitException("Error al aplicar la funcion de sumarizacion en dissolve", e);
|
|
503 |
} catch (ReadDriverException e) {
|
|
504 |
throw new ProcessVisitorException(recordset.getName(),e,"Error al aplicar la funcion de sumarizacion en dissolve");
|
|
488 | 505 |
} |
489 | 506 |
dissolvedGeometries.set(index2); |
490 | 507 |
} |
... | ... | |
494 | 511 |
return ""; |
495 | 512 |
} |
496 | 513 |
|
497 |
public void stop(FLayer layer) { |
|
514 |
public void stop(FLayer layer) throws VisitorException {
|
|
498 | 515 |
} |
499 | 516 |
|
500 |
public boolean start(FLayer layer) { |
|
517 |
public boolean start(FLayer layer) throws StartVisitorException {
|
|
501 | 518 |
return true; |
502 | 519 |
} |
503 | 520 |
} |
504 |
|
|
521 |
|
|
505 | 522 |
class StackEntry{ |
506 | 523 |
public IGeometry g; |
507 | 524 |
public int index; |
... | ... | |
510 | 527 |
* Processes the given feature looking for features to dissolve with. The |
511 | 528 |
* criteria to decide if dissolve two features is given by |
512 | 529 |
* IDissolveCriteria. |
513 |
*
|
|
530 |
* |
|
514 | 531 |
* @param criteria |
515 | 532 |
* decides if dissolve two features |
516 | 533 |
* @param index1 |
... | ... | |
519 | 536 |
* it reads geometry of features |
520 | 537 |
* @param cancel |
521 | 538 |
* listen cancelations |
522 |
* @throws VisitException |
|
539 |
* @throws ExpansionFileReadException |
|
540 |
* @throws ReadDriverException |
|
541 |
* @throws VisitorException |
|
542 |
* @throws ProcessWriterException |
|
523 | 543 |
* @throws DriverException |
524 | 544 |
* @throws IOException |
525 | 545 |
* @throws DriverIOException |
526 | 546 |
*/ |
527 | 547 |
public void process(int index1, |
528 |
ReadableVectorial va,
|
|
548 |
ReadableVectorial va, |
|
529 | 549 |
CancellableMonitorable cancel) |
530 |
throws DriverException, VisitException, IOException, |
|
531 |
DriverIOException { |
|
532 |
|
|
550 |
throws ReadDriverException, ExpansionFileReadException, VisitorException { |
|
551 |
|
|
533 | 552 |
if(dissolvedGeometries.get(index1)) |
534 | 553 |
return; |
535 |
Strategy strategy = StrategyManager.getStrategy(dissolvedLayer);
|
|
554 |
Strategy strategy = StrategyManager.getStrategy(dissolvedLayer); |
|
536 | 555 |
IGeometry g1 = va.getShape(index1); |
537 | 556 |
if(g1 == null) |
538 | 557 |
return; |
... | ... | |
544 | 563 |
Stack stack = new Stack();//it saves FMap geometries |
545 | 564 |
stack.push(entry); |
546 | 565 |
ArrayList geometries = new ArrayList(); |
547 |
|
|
566 |
|
|
548 | 567 |
Geometry jtsGeo = g1.toJTSGeometry(); |
549 | 568 |
geometries.add(jtsGeo);//it saves jts geometries |
550 |
|
|
569 |
|
|
551 | 570 |
if(dissolveCriteria instanceof ISpatialDissolveCriteria){ |
552 | 571 |
((ISpatialDissolveCriteria)dissolveCriteria).setCoordTrans(ct); |
553 | 572 |
((ISpatialDissolveCriteria)dissolveCriteria).setFirstGeometry(g1); |
554 | 573 |
} |
555 | 574 |
FunctionSummarizer sumarizer = new FunctionSummarizer( |
556 | 575 |
numericField_sumarizeFunction, recordset); |
557 |
SpatialDissolveVisitor visitor = new SpatialDissolveVisitor(dissolveCriteria,
|
|
558 |
jtsGeo,
|
|
559 |
entry,
|
|
576 |
SpatialDissolveVisitor visitor = new SpatialDissolveVisitor(dissolveCriteria, |
|
577 |
jtsGeo, |
|
578 |
entry, |
|
560 | 579 |
stack, |
561 |
geometries,
|
|
562 |
va,
|
|
563 |
sumarizer,
|
|
580 |
geometries, |
|
581 |
va, |
|
582 |
sumarizer, |
|
564 | 583 |
cancel); |
565 |
|
|
584 |
|
|
566 | 585 |
while (stack.size() != 0) { |
567 | 586 |
dumpStack(stack); |
568 | 587 |
StackEntry sEntry = (StackEntry) stack.pop(); |
569 | 588 |
dissolvedGeometries.set(sEntry.index); |
570 |
|
|
589 |
|
|
571 | 590 |
/*//TODO |
572 | 591 |
* Revisar si no deberiamos hacer |
573 | 592 |
* ct.getInverted().convert(rect); |
574 |
*
|
|
593 |
* |
|
575 | 594 |
* */ |
576 | 595 |
Rectangle2D rect = sEntry.g.getBounds2D(); |
577 | 596 |
if(ct != null) |
... | ... | |
587 | 606 |
visitor.setSeed(sEntry, jts); |
588 | 607 |
strategy.process(visitor, query); |
589 | 608 |
}// while |
590 |
|
|
591 |
|
|
609 |
|
|
610 |
|
|
592 | 611 |
IGeometry newGeometry = FConverter.jts_to_igeometry(union2(geometries)); |
593 | 612 |
List sumarizedValues = sumarizer.getValues(); |
594 | 613 |
IFeature dissolvedFeature = null; |
595 | 614 |
if(sumarizedValues != null || sumarizedValues.size() != 0){ |
596 | 615 |
dissolvedFeature = dissolveCriteria. |
597 | 616 |
getFeatureBuilder(). |
598 |
createFeature(newGeometry,
|
|
599 |
sumarizedValues,
|
|
600 |
fid,
|
|
617 |
createFeature(newGeometry, |
|
618 |
sumarizedValues, |
|
619 |
fid, |
|
601 | 620 |
index1); |
602 | 621 |
}else{ |
603 | 622 |
dissolvedFeature = dissolveCriteria. |
604 | 623 |
getFeatureBuilder(). |
605 | 624 |
createFeature(newGeometry, |
606 |
index1,
|
|
625 |
index1, |
|
607 | 626 |
fid); |
608 | 627 |
} |
609 | 628 |
fid++; |
... | ... | |
621 | 640 |
|
622 | 641 |
/** |
623 | 642 |
* Returns the union of all geometries of the list |
624 |
*
|
|
643 |
* |
|
625 | 644 |
* @param geometries |
626 | 645 |
* @return |
627 | 646 |
*/ |
628 |
protected Geometry union(List geometries) {
|
|
647 |
protected Geometry union(List geometries) { |
|
629 | 648 |
Geometry union = null; |
630 | 649 |
GeometryFactory fact = ((Geometry)geometries. |
631 | 650 |
get(0)).getFactory(); |
... | ... | |
636 | 655 |
union = g; |
637 | 656 |
else{ |
638 | 657 |
Geometry[] geomArray = {union, g}; |
639 |
GeometryCollection gCol =
|
|
658 |
GeometryCollection gCol = |
|
640 | 659 |
fact. |
641 | 660 |
createGeometryCollection(geomArray); |
642 | 661 |
union = gCol.buffer(0d); |
643 |
}
|
|
662 |
} |
|
644 | 663 |
} |
645 | 664 |
return union; |
646 | 665 |
} |
647 |
|
|
666 |
|
|
648 | 667 |
protected Geometry union3(List geometries) { |
649 |
long t0 = System.currentTimeMillis();
|
|
668 |
long t0 = System.currentTimeMillis(); |
|
650 | 669 |
Geometry union = null; |
651 | 670 |
Iterator geomIt = geometries.iterator(); |
652 | 671 |
while(geomIt.hasNext()){ |
... | ... | |
655 | 674 |
union = g; |
656 | 675 |
else{ |
657 | 676 |
union = union.union(g); |
658 |
}
|
|
677 |
} |
|
659 | 678 |
} |
660 | 679 |
long t1 = System.currentTimeMillis(); |
661 | 680 |
System.out.println((t1-t0)+ " en procesar union 3"); |
662 | 681 |
return union; |
663 | 682 |
} |
664 |
|
|
665 |
protected Geometry union2(List geometries){
|
|
683 |
|
|
684 |
protected Geometry union2(List geometries){ |
|
666 | 685 |
Geometry union = null; |
667 | 686 |
Geometry[] geom = new Geometry[geometries.size()]; |
668 | 687 |
geometries.toArray(geom); |
... | ... | |
672 | 691 |
union = geomColl.buffer(0); |
673 | 692 |
// System.out.println(union.toText()); |
674 | 693 |
return union; |
675 |
|
|
694 |
|
|
676 | 695 |
} |
677 | 696 |
} |
Also available in: Unified diff