Revision 38539 branches/v2_0_0_prep/extensions/extEditing/src/org/gvsig/editing/gui/cad/tools/SplitGeometryCADTool.java

View differences:

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