Index: SplitGeometryCADTool.java
===================================================================
--- SplitGeometryCADTool.java	(revision 38538)
+++ SplitGeometryCADTool.java	(revision 38539)
@@ -21,6 +21,8 @@
  */
 package org.gvsig.editing.gui.cad.tools;
 
+import java.awt.Color;
+import java.awt.Component;
 import java.awt.Image;
 import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
@@ -28,6 +30,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.swing.JOptionPane;
+
 import com.vividsolutions.jts.geom.Coordinate;
 import com.vividsolutions.jts.geom.Geometry;
 import com.vividsolutions.jts.geom.GeometryCollection;
@@ -40,8 +44,12 @@
 import com.vividsolutions.jts.geom.Polygon;
 import com.vividsolutions.jts.geom.PrecisionModel;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.gvsig.andami.PluginServices;
-import org.gvsig.andami.messages.NotificationManager;
+import org.gvsig.andami.ui.mdiManager.IWindow;
+import org.gvsig.app.ApplicationLocator;
 import org.gvsig.editing.gui.cad.DefaultCADTool;
 import org.gvsig.editing.gui.cad.exception.CommandException;
 import org.gvsig.editing.gui.cad.tools.smc.SplitGeometryCADToolContext;
@@ -62,12 +70,18 @@
 import org.gvsig.fmap.geom.util.Converter;
 import org.gvsig.fmap.mapcontext.layers.SpatialCache;
 import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
+import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
 import org.gvsig.fmap.mapcontrol.MapControlDrawer;
+import org.gvsig.i18n.Messages;
+import org.gvsig.symbology.SymbologyLocator;
+import org.gvsig.symbology.SymbologyManager;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.ISimpleFillSymbol;
 import org.gvsig.tools.dispose.DisposableIterator;
 import org.gvsig.tools.dispose.DisposeUtils;
 import org.gvsig.tools.locator.LocatorException;
 
 import statemap.State;
+import statemap.StateUndefinedException;
 
 /**
  * CAD Tool which splits the selected geometries of a vectorial editing
@@ -79,6 +93,8 @@
  */
 public class SplitGeometryCADTool extends DefaultCADTool {
 
+    private static Logger logger =
+        LoggerFactory.getLogger(SplitGeometryCADTool.class);
     /**
      * String representation of this tool (used for example to active the tool
      * in mapcontrol)
@@ -101,6 +117,10 @@
     protected List<Point2D> clickedPoints;
 
     /**
+     * used to draw helping rectangle (bbox)
+     */
+    protected ISymbol rectSymbol = null;
+    /**
      * Initialization method.
      */
     public void init() {
@@ -129,6 +149,8 @@
     }
 
     public void splitSelectedGeometryWithDigitizedLine() {
+        
+        // comprobar bucle, probar interseccion?
         Point2D[] clickedPts = new Point2D[this.clickedPoints.size()];
         clickedPoints.toArray(clickedPts);
         Coordinate[] digitizedCoords = getPoint2DAsCoordinates(clickedPts);
@@ -160,27 +182,42 @@
                     if (gc.getNumGeometries() > 2) {
                         Geometry[] splitGroups =
                             createSplitGroups(jtsGeo, splittingLs);
+                        
+                        if (splitGroups == null) {
+                            
+                            String _tit = Messages.getText("split_geometry");
+                            String _msg = Messages.getText("_Split_line_must_start_and_end_outside_bbox");
+                            Component parent = getCurrentWindow();
+                            JOptionPane.showMessageDialog(
+                                parent,
+                                _msg,
+                                _tit,
+                                JOptionPane.WARNING_MESSAGE);
+                            // cancel splitting
+                            break;
+                        }
+                        
                         if (splitGroups.length == 0) {
                             continue;
                         }
 
                         for (int j = 0; j < gc.getNumGeometries(); j++) {
                             Geometry g = gc.getGeometryN(j);
-                            for (int k=0 ; k<=splitGroups.length ; k++){
-                            if (splitGroups[k].contains(g)) {
-                                    geoms0.add(g);
-                                } else {
-                                    geoms1.add(g);
-                                }
+                            
+                            if (isRatherInside(g, splitGroups[0])) {
+                                geoms0.add(g);
+                            } else {
+                                geoms1.add(g);
                             }
                         }
-                    } else
+                    } else {
                         if (gc.getNumGeometries() == 2) {
                             geoms0.add(gc.getGeometryN(0));
                             geoms1.add(gc.getGeometryN(1));
                         } else {
                             continue;
                         }
+                    }
                     GeometryCollection gc0 =
                         createMulti(geoms0, gc.getFactory());
 
@@ -226,6 +263,19 @@
         }
     }
 
+    /**
+     * @return
+     */
+    private Component getCurrentWindow() {
+        
+        IWindow iw = PluginServices.getMDIManager().getActiveWindow();
+        if (iw instanceof Component) {
+            return (Component) iw;
+        } else {
+            return null;
+        }
+    }
+
     private GeometryCollection createMulti(ArrayList<Geometry> geoms,
         GeometryFactory factory) {
         if (geoms.size() == 0)
@@ -260,8 +310,7 @@
             }
             return geomsJTS;
         } catch (Exception e) {
-            NotificationManager.showMessageError(
-                PluginServices.getText(this, "line_not_cross_rectangle"), e);
+            logger.info("Warning: Found split line which does not leave bbox. User will be prompted.");
         }
         return null;
     }
@@ -370,8 +419,7 @@
                             ig.getEnvelope().getGeometry().getGeneralPath(),
                             SUBTYPES.GEOM2D);
                     
-                    renderer
-                        .draw(geom, mapControlManager.getAxisReferenceSymbol());
+                    renderer.draw(geom, getRectangleOfSplitSymbol());
                 }
             }
         } finally {
@@ -379,13 +427,46 @@
         }
     }
 
+    /**
+     * @return
+     */
+    private ISymbol getRectangleOfSplitSymbol() {
+        
+        if (rectSymbol == null) {
+            SymbologyManager sm = SymbologyLocator.getSymbologyManager();
+            ISimpleFillSymbol resp = sm.createSimpleFillSymbol();
+            resp.setColor(Color.RED);
+            resp.setFillColor(new Color(0,0,0, 100));
+            rectSymbol = resp;
+        }
+        return rectSymbol;
+    }
+
     public void drawOperation(MapControlDrawer renderer, double x, double y) {
-        State actualState = _fsm.getState();
-        String status = actualState.getName();
+        
+        // decide whether user line must be drawn
+        boolean draw_user_poly_line = false;
         try {
+            State currentState = _fsm.getState();
+            if (currentState != null) {
+                String status = currentState.getName();
+                if (status != null && status.equals("SplitGeometry.DigitizingLine")) {
+                    draw_user_poly_line = true;
+                }
+            }        
+        } catch (StateUndefinedException sue) {
+            // this happens when state is null
+            // because the line has been finished and we must not draw it
+            draw_user_poly_line = false;
+        }
+        
+        // =======================================================
+        
+        try {
             drawRectangleOfSplit(renderer);
-            // draw splitting line
-            if ((status.equals("SplitGeometry.DigitizingLine"))) {
+            
+            // possibly draw splitting line
+            if (draw_user_poly_line) {
                 drawPolyLine(renderer, x, y);
             }
 
@@ -393,8 +474,11 @@
             Image imgSel = getVLE().getSelectionImage();
             renderer.drawImage(imgSel, 0, 0);
         } catch (Exception e) {
-            PluginServices.getLogger().error("Error drawing Editing Selection",
-                e);
+            
+            logger.info("Error while drawing split tool.", e);
+            ApplicationLocator.getManager().message(
+                Messages.getText("_Drawing_error") + e.getMessage(),
+                JOptionPane.ERROR_MESSAGE);
         }
     }
 
@@ -430,4 +514,116 @@
     protected int[] getSupportedGeometryTypes() {
         return null;
     }
+
+    /**
+     * This method decides if geometrya  is inside geometry b 
+     * by more than 50%. This is useful because it will be
+     * used to assign each geometry to one of two possible containers
+     * 
+     * @param a
+     * @param b must be a multi(polygon)
+     * @return
+     */
+    private static boolean isRatherInside(Geometry a, Geometry b) {
+        
+        if (a instanceof Polygon || a instanceof MultiPolygon) {
+            return polygonIsRatherInside(a, b);
+        } else {
+            if (a instanceof LineString || a instanceof MultiLineString) {
+                return lineIsRatherInside(a, b);
+            } else {
+                if (a instanceof MultiPoint) {
+                    
+                    MultiPoint mp = (MultiPoint) a;
+                    int n = mp.getNumPoints();
+                    int inn = 0;
+                    Geometry itemg = null;
+                    for (int i=0; i<n; i++) {
+                        itemg = mp.getGeometryN(i);
+                        if (isRatherInside(itemg, b)) {
+                            inn++;
+                        }
+                    }
+                    return inn > (n/2);
+                } else {
+                    // last case: should be a point
+                    return b.contains(a);
+                }
+            }
+        }
+        
+    }
+
+    
+    
+    /**
+     * This method decides if a polygon is inside another
+     * by more than 50%. This is useful because it will be
+     * used to assign each polygon to one of two possible containers
+     * 
+     * @param a
+     * @param b
+     * @return whether a is 'rather' contained by b
+     */
+    private static boolean polygonIsRatherInside(Geometry a, Geometry b) {
+        
+        if (a == null || b == null || a.isEmpty() || b.isEmpty()) {
+            return false;
+        }
+        
+        double area_a = a.getArea();
+        
+        if (area_a == 0) {
+            return false;
+        }
+        
+        Geometry a_inters_b = null;
+        
+        a_inters_b = a.intersection(b);
+        if (a_inters_b == null || a_inters_b.isEmpty()) {
+            return false;
+        }
+
+        double area_aib = a_inters_b.getArea();
+        
+        if (area_aib == 0) {
+            return false;
+        }
+        
+        return area_aib > (0.5d * area_a);
+    }
+    
+    /**
+     * 
+     * @param a assumed to be a (multi)linestring
+     * @param b the (possibly) containing polygon
+     * @return
+     */
+    private static boolean lineIsRatherInside(Geometry a, Geometry b) {
+        
+        if (a == null || b == null || a.isEmpty() || b.isEmpty()) {
+            return false;
+        }
+        
+        double len_a = a.getLength();
+        
+        if (len_a == 0) {
+            return false;
+        }
+        
+        Geometry a_inters_b = null;
+        
+        a_inters_b = a.intersection(b);
+        if (a_inters_b == null || a_inters_b.isEmpty()) {
+            return false;
+        }
+
+        double len_aib = a_inters_b.getLength();
+        
+        if (len_aib == 0) {
+            return false;
+        }
+        
+        return len_aib > (0.5d * len_a);
+    }
 }
