Revision 38539 branches/v2_0_0_prep/extensions/extEditing/src/org/gvsig/editing/gui/cad/tools/SplitGeometryCADTool.java
SplitGeometryCADTool.java | ||
---|---|---|
21 | 21 |
*/ |
22 | 22 |
package org.gvsig.editing.gui.cad.tools; |
23 | 23 |
|
24 |
import java.awt.Color; |
|
25 |
import java.awt.Component; |
|
24 | 26 |
import java.awt.Image; |
25 | 27 |
import java.awt.event.InputEvent; |
26 | 28 |
import java.awt.event.MouseEvent; |
... | ... | |
28 | 30 |
import java.util.ArrayList; |
29 | 31 |
import java.util.List; |
30 | 32 |
|
33 |
import javax.swing.JOptionPane; |
|
34 |
|
|
31 | 35 |
import com.vividsolutions.jts.geom.Coordinate; |
32 | 36 |
import com.vividsolutions.jts.geom.Geometry; |
33 | 37 |
import com.vividsolutions.jts.geom.GeometryCollection; |
... | ... | |
40 | 44 |
import com.vividsolutions.jts.geom.Polygon; |
41 | 45 |
import com.vividsolutions.jts.geom.PrecisionModel; |
42 | 46 |
|
47 |
import org.slf4j.Logger; |
|
48 |
import org.slf4j.LoggerFactory; |
|
49 |
|
|
43 | 50 |
import org.gvsig.andami.PluginServices; |
44 |
import org.gvsig.andami.messages.NotificationManager; |
|
51 |
import org.gvsig.andami.ui.mdiManager.IWindow; |
|
52 |
import org.gvsig.app.ApplicationLocator; |
|
45 | 53 |
import org.gvsig.editing.gui.cad.DefaultCADTool; |
46 | 54 |
import org.gvsig.editing.gui.cad.exception.CommandException; |
47 | 55 |
import org.gvsig.editing.gui.cad.tools.smc.SplitGeometryCADToolContext; |
... | ... | |
62 | 70 |
import org.gvsig.fmap.geom.util.Converter; |
63 | 71 |
import org.gvsig.fmap.mapcontext.layers.SpatialCache; |
64 | 72 |
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect; |
73 |
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol; |
|
65 | 74 |
import org.gvsig.fmap.mapcontrol.MapControlDrawer; |
75 |
import org.gvsig.i18n.Messages; |
|
76 |
import org.gvsig.symbology.SymbologyLocator; |
|
77 |
import org.gvsig.symbology.SymbologyManager; |
|
78 |
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.ISimpleFillSymbol; |
|
66 | 79 |
import org.gvsig.tools.dispose.DisposableIterator; |
67 | 80 |
import org.gvsig.tools.dispose.DisposeUtils; |
68 | 81 |
import org.gvsig.tools.locator.LocatorException; |
69 | 82 |
|
70 | 83 |
import statemap.State; |
84 |
import statemap.StateUndefinedException; |
|
71 | 85 |
|
72 | 86 |
/** |
73 | 87 |
* CAD Tool which splits the selected geometries of a vectorial editing |
... | ... | |
79 | 93 |
*/ |
80 | 94 |
public class SplitGeometryCADTool extends DefaultCADTool { |
81 | 95 |
|
96 |
private static Logger logger = |
|
97 |
LoggerFactory.getLogger(SplitGeometryCADTool.class); |
|
82 | 98 |
/** |
83 | 99 |
* String representation of this tool (used for example to active the tool |
84 | 100 |
* in mapcontrol) |
... | ... | |
101 | 117 |
protected List<Point2D> clickedPoints; |
102 | 118 |
|
103 | 119 |
/** |
120 |
* used to draw helping rectangle (bbox) |
|
121 |
*/ |
|
122 |
protected ISymbol rectSymbol = null; |
|
123 |
/** |
|
104 | 124 |
* Initialization method. |
105 | 125 |
*/ |
106 | 126 |
public void init() { |
... | ... | |
129 | 149 |
} |
130 | 150 |
|
131 | 151 |
public void splitSelectedGeometryWithDigitizedLine() { |
152 |
|
|
153 |
// comprobar bucle, probar interseccion? |
|
132 | 154 |
Point2D[] clickedPts = new Point2D[this.clickedPoints.size()]; |
133 | 155 |
clickedPoints.toArray(clickedPts); |
134 | 156 |
Coordinate[] digitizedCoords = getPoint2DAsCoordinates(clickedPts); |
... | ... | |
160 | 182 |
if (gc.getNumGeometries() > 2) { |
161 | 183 |
Geometry[] splitGroups = |
162 | 184 |
createSplitGroups(jtsGeo, splittingLs); |
185 |
|
|
186 |
if (splitGroups == null) { |
|
187 |
|
|
188 |
String _tit = Messages.getText("split_geometry"); |
|
189 |
String _msg = Messages.getText("_Split_line_must_start_and_end_outside_bbox"); |
|
190 |
Component parent = getCurrentWindow(); |
|
191 |
JOptionPane.showMessageDialog( |
|
192 |
parent, |
|
193 |
_msg, |
|
194 |
_tit, |
|
195 |
JOptionPane.WARNING_MESSAGE); |
|
196 |
// cancel splitting |
|
197 |
break; |
|
198 |
} |
|
199 |
|
|
163 | 200 |
if (splitGroups.length == 0) { |
164 | 201 |
continue; |
165 | 202 |
} |
166 | 203 |
|
167 | 204 |
for (int j = 0; j < gc.getNumGeometries(); j++) { |
168 | 205 |
Geometry g = gc.getGeometryN(j); |
169 |
for (int k=0 ; k<=splitGroups.length ; k++){ |
|
170 |
if (splitGroups[k].contains(g)) { |
|
171 |
geoms0.add(g); |
|
172 |
} else { |
|
173 |
geoms1.add(g); |
|
174 |
} |
|
206 |
|
|
207 |
if (isRatherInside(g, splitGroups[0])) { |
|
208 |
geoms0.add(g); |
|
209 |
} else { |
|
210 |
geoms1.add(g); |
|
175 | 211 |
} |
176 | 212 |
} |
177 |
} else |
|
213 |
} else {
|
|
178 | 214 |
if (gc.getNumGeometries() == 2) { |
179 | 215 |
geoms0.add(gc.getGeometryN(0)); |
180 | 216 |
geoms1.add(gc.getGeometryN(1)); |
181 | 217 |
} else { |
182 | 218 |
continue; |
183 | 219 |
} |
220 |
} |
|
184 | 221 |
GeometryCollection gc0 = |
185 | 222 |
createMulti(geoms0, gc.getFactory()); |
186 | 223 |
|
... | ... | |
226 | 263 |
} |
227 | 264 |
} |
228 | 265 |
|
266 |
/** |
|
267 |
* @return |
|
268 |
*/ |
|
269 |
private Component getCurrentWindow() { |
|
270 |
|
|
271 |
IWindow iw = PluginServices.getMDIManager().getActiveWindow(); |
|
272 |
if (iw instanceof Component) { |
|
273 |
return (Component) iw; |
|
274 |
} else { |
|
275 |
return null; |
|
276 |
} |
|
277 |
} |
|
278 |
|
|
229 | 279 |
private GeometryCollection createMulti(ArrayList<Geometry> geoms, |
230 | 280 |
GeometryFactory factory) { |
231 | 281 |
if (geoms.size() == 0) |
... | ... | |
260 | 310 |
} |
261 | 311 |
return geomsJTS; |
262 | 312 |
} catch (Exception e) { |
263 |
NotificationManager.showMessageError( |
|
264 |
PluginServices.getText(this, "line_not_cross_rectangle"), e); |
|
313 |
logger.info("Warning: Found split line which does not leave bbox. User will be prompted."); |
|
265 | 314 |
} |
266 | 315 |
return null; |
267 | 316 |
} |
... | ... | |
370 | 419 |
ig.getEnvelope().getGeometry().getGeneralPath(), |
371 | 420 |
SUBTYPES.GEOM2D); |
372 | 421 |
|
373 |
renderer |
|
374 |
.draw(geom, mapControlManager.getAxisReferenceSymbol()); |
|
422 |
renderer.draw(geom, getRectangleOfSplitSymbol()); |
|
375 | 423 |
} |
376 | 424 |
} |
377 | 425 |
} finally { |
... | ... | |
379 | 427 |
} |
380 | 428 |
} |
381 | 429 |
|
430 |
/** |
|
431 |
* @return |
|
432 |
*/ |
|
433 |
private ISymbol getRectangleOfSplitSymbol() { |
|
434 |
|
|
435 |
if (rectSymbol == null) { |
|
436 |
SymbologyManager sm = SymbologyLocator.getSymbologyManager(); |
|
437 |
ISimpleFillSymbol resp = sm.createSimpleFillSymbol(); |
|
438 |
resp.setColor(Color.RED); |
|
439 |
resp.setFillColor(new Color(0,0,0, 100)); |
|
440 |
rectSymbol = resp; |
|
441 |
} |
|
442 |
return rectSymbol; |
|
443 |
} |
|
444 |
|
|
382 | 445 |
public void drawOperation(MapControlDrawer renderer, double x, double y) { |
383 |
State actualState = _fsm.getState(); |
|
384 |
String status = actualState.getName(); |
|
446 |
|
|
447 |
// decide whether user line must be drawn |
|
448 |
boolean draw_user_poly_line = false; |
|
385 | 449 |
try { |
450 |
State currentState = _fsm.getState(); |
|
451 |
if (currentState != null) { |
|
452 |
String status = currentState.getName(); |
|
453 |
if (status != null && status.equals("SplitGeometry.DigitizingLine")) { |
|
454 |
draw_user_poly_line = true; |
|
455 |
} |
|
456 |
} |
|
457 |
} catch (StateUndefinedException sue) { |
|
458 |
// this happens when state is null |
|
459 |
// because the line has been finished and we must not draw it |
|
460 |
draw_user_poly_line = false; |
|
461 |
} |
|
462 |
|
|
463 |
// ======================================================= |
|
464 |
|
|
465 |
try { |
|
386 | 466 |
drawRectangleOfSplit(renderer); |
387 |
// draw splitting line |
|
388 |
if ((status.equals("SplitGeometry.DigitizingLine"))) { |
|
467 |
|
|
468 |
// possibly draw splitting line |
|
469 |
if (draw_user_poly_line) { |
|
389 | 470 |
drawPolyLine(renderer, x, y); |
390 | 471 |
} |
391 | 472 |
|
... | ... | |
393 | 474 |
Image imgSel = getVLE().getSelectionImage(); |
394 | 475 |
renderer.drawImage(imgSel, 0, 0); |
395 | 476 |
} catch (Exception e) { |
396 |
PluginServices.getLogger().error("Error drawing Editing Selection", |
|
397 |
e); |
|
477 |
|
|
478 |
logger.info("Error while drawing split tool.", e); |
|
479 |
ApplicationLocator.getManager().message( |
|
480 |
Messages.getText("_Drawing_error") + e.getMessage(), |
|
481 |
JOptionPane.ERROR_MESSAGE); |
|
398 | 482 |
} |
399 | 483 |
} |
400 | 484 |
|
... | ... | |
430 | 514 |
protected int[] getSupportedGeometryTypes() { |
431 | 515 |
return null; |
432 | 516 |
} |
517 |
|
|
518 |
/** |
|
519 |
* This method decides if geometrya is inside geometry b |
|
520 |
* by more than 50%. This is useful because it will be |
|
521 |
* used to assign each geometry to one of two possible containers |
|
522 |
* |
|
523 |
* @param a |
|
524 |
* @param b must be a multi(polygon) |
|
525 |
* @return |
|
526 |
*/ |
|
527 |
private static boolean isRatherInside(Geometry a, Geometry b) { |
|
528 |
|
|
529 |
if (a instanceof Polygon || a instanceof MultiPolygon) { |
|
530 |
return polygonIsRatherInside(a, b); |
|
531 |
} else { |
|
532 |
if (a instanceof LineString || a instanceof MultiLineString) { |
|
533 |
return lineIsRatherInside(a, b); |
|
534 |
} else { |
|
535 |
if (a instanceof MultiPoint) { |
|
536 |
|
|
537 |
MultiPoint mp = (MultiPoint) a; |
|
538 |
int n = mp.getNumPoints(); |
|
539 |
int inn = 0; |
|
540 |
Geometry itemg = null; |
|
541 |
for (int i=0; i<n; i++) { |
|
542 |
itemg = mp.getGeometryN(i); |
|
543 |
if (isRatherInside(itemg, b)) { |
|
544 |
inn++; |
|
545 |
} |
|
546 |
} |
|
547 |
return inn > (n/2); |
|
548 |
} else { |
|
549 |
// last case: should be a point |
|
550 |
return b.contains(a); |
|
551 |
} |
|
552 |
} |
|
553 |
} |
|
554 |
|
|
555 |
} |
|
556 |
|
|
557 |
|
|
558 |
|
|
559 |
/** |
|
560 |
* This method decides if a polygon is inside another |
|
561 |
* by more than 50%. This is useful because it will be |
|
562 |
* used to assign each polygon to one of two possible containers |
|
563 |
* |
|
564 |
* @param a |
|
565 |
* @param b |
|
566 |
* @return whether a is 'rather' contained by b |
|
567 |
*/ |
|
568 |
private static boolean polygonIsRatherInside(Geometry a, Geometry b) { |
|
569 |
|
|
570 |
if (a == null || b == null || a.isEmpty() || b.isEmpty()) { |
|
571 |
return false; |
|
572 |
} |
|
573 |
|
|
574 |
double area_a = a.getArea(); |
|
575 |
|
|
576 |
if (area_a == 0) { |
|
577 |
return false; |
|
578 |
} |
|
579 |
|
|
580 |
Geometry a_inters_b = null; |
|
581 |
|
|
582 |
a_inters_b = a.intersection(b); |
|
583 |
if (a_inters_b == null || a_inters_b.isEmpty()) { |
|
584 |
return false; |
|
585 |
} |
|
586 |
|
|
587 |
double area_aib = a_inters_b.getArea(); |
|
588 |
|
|
589 |
if (area_aib == 0) { |
|
590 |
return false; |
|
591 |
} |
|
592 |
|
|
593 |
return area_aib > (0.5d * area_a); |
|
594 |
} |
|
595 |
|
|
596 |
/** |
|
597 |
* |
|
598 |
* @param a assumed to be a (multi)linestring |
|
599 |
* @param b the (possibly) containing polygon |
|
600 |
* @return |
|
601 |
*/ |
|
602 |
private static boolean lineIsRatherInside(Geometry a, Geometry b) { |
|
603 |
|
|
604 |
if (a == null || b == null || a.isEmpty() || b.isEmpty()) { |
|
605 |
return false; |
|
606 |
} |
|
607 |
|
|
608 |
double len_a = a.getLength(); |
|
609 |
|
|
610 |
if (len_a == 0) { |
|
611 |
return false; |
|
612 |
} |
|
613 |
|
|
614 |
Geometry a_inters_b = null; |
|
615 |
|
|
616 |
a_inters_b = a.intersection(b); |
|
617 |
if (a_inters_b == null || a_inters_b.isEmpty()) { |
|
618 |
return false; |
|
619 |
} |
|
620 |
|
|
621 |
double len_aib = a_inters_b.getLength(); |
|
622 |
|
|
623 |
if (len_aib == 0) { |
|
624 |
return false; |
|
625 |
} |
|
626 |
|
|
627 |
return len_aib > (0.5d * len_a); |
|
628 |
} |
|
433 | 629 |
} |
Also available in: Unified diff