Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / extensions / extEditing / src / org / gvsig / editing / gui / cad / tools / SplitGeometryCADTool.java @ 30335

History | View | Annotate | Download (13.8 KB)

1
/*
2
 * Created on 10-abr-2006
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
*
46
* $Id:
47
* $Log:
48
*/
49
package org.gvsig.editing.gui.cad.tools;
50

    
51
import java.awt.Image;
52
import java.awt.event.InputEvent;
53
import java.awt.event.MouseEvent;
54
import java.awt.geom.Point2D;
55
import java.util.ArrayList;
56
import java.util.Iterator;
57
import java.util.List;
58

    
59
import org.apache.log4j.Logger;
60
import org.gvsig.andami.PluginServices;
61
import org.gvsig.andami.messages.NotificationManager;
62
import org.gvsig.editing.gui.cad.DefaultCADTool;
63
import org.gvsig.editing.gui.cad.exception.CommandException;
64
import org.gvsig.editing.gui.cad.tools.smc.SplitGeometryCADToolContext;
65
import org.gvsig.editing.gui.cad.tools.split.SplitStrategy;
66
import org.gvsig.editing.layers.VectorialLayerEdited;
67
import org.gvsig.fmap.dal.exception.DataException;
68
import org.gvsig.fmap.dal.feature.EditableFeature;
69
import org.gvsig.fmap.dal.feature.Feature;
70
import org.gvsig.fmap.dal.feature.FeatureStore;
71
import org.gvsig.fmap.geom.GeometryLocator;
72
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
73
import org.gvsig.fmap.geom.exception.CreateGeometryException;
74
import org.gvsig.fmap.geom.operation.Draw;
75
import org.gvsig.fmap.geom.operation.DrawOperationContext;
76
import org.gvsig.fmap.geom.operation.GeometryOperationException;
77
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
78
import org.gvsig.fmap.geom.primitive.Envelope;
79
import org.gvsig.fmap.geom.primitive.GeneralPathX;
80
import org.gvsig.fmap.geom.util.Converter;
81
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
82
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
83
import org.gvsig.fmap.mapcontrol.MapControlDrawer;
84
import org.gvsig.tools.locator.LocatorException;
85

    
86
import statemap.State;
87

    
88
import com.vividsolutions.jts.geom.Coordinate;
89
import com.vividsolutions.jts.geom.Geometry;
90
import com.vividsolutions.jts.geom.GeometryCollection;
91
import com.vividsolutions.jts.geom.GeometryFactory;
92
import com.vividsolutions.jts.geom.LineString;
93
import com.vividsolutions.jts.geom.MultiLineString;
94
import com.vividsolutions.jts.geom.MultiPoint;
95
import com.vividsolutions.jts.geom.MultiPolygon;
96
import com.vividsolutions.jts.geom.Point;
97
import com.vividsolutions.jts.geom.Polygon;
98
import com.vividsolutions.jts.geom.PrecisionModel;
99

    
100

    
101
/**
102
 * CAD Tool which splits the selected geometries of a vectorial editing
103
 * layer with a digitized polyline.
104
 *
105
 *
106
 * @author Alvaro Zabala
107
 *
108
 */
109
public class SplitGeometryCADTool extends DefaultCADTool {
110

    
111
        private static Logger logger = Logger.getLogger(SplitGeometryCADTool.class.getName());
112

    
113
        /**
114
         * String representation of this tool (used for example to active the tool
115
         * in mapcontrol)
116
         */
117
        public static final String SPLIT_GEOMETRY_TOOL_NAME = "_split_geometry";
118

    
119

    
120

    
121
        /**
122
         * finite state machine for this CAD tool
123
         */
124
        protected SplitGeometryCADToolContext _fsm;
125

    
126

    
127

    
128
        /**
129
         * Flag to mark if the digitized line has been finished.
130
         */
131
        protected boolean digitizingFinished = false;
132

    
133
        /**
134
         * Collection of digitized geometries
135
         */
136
        protected List<Point2D> clickedPoints;
137

    
138

    
139
        /**
140
         * Default Constructor
141
         */
142
        public SplitGeometryCADTool(){
143

    
144
        }
145

    
146

    
147
        /**
148
         * Initialization method.
149
         */
150
        public void init() {
151
                digitizingFinished = false;
152
                _fsm = new SplitGeometryCADToolContext(this);
153
                setNextTool(SplitGeometryCADTool.SPLIT_GEOMETRY_TOOL_NAME);
154
        }
155

    
156

    
157

    
158
        public boolean isDigitizingFinished() {
159
                return digitizingFinished;
160
        }
161

    
162
        public String toString() {
163
                return SplitGeometryCADTool.SPLIT_GEOMETRY_TOOL_NAME;
164
        }
165

    
166

    
167

    
168
        public void finishDigitizedLine(){
169
        }
170
//        public ArrayList getSelectedRows(){
171
//                VectorialLayerEdited vle = getVLE();
172
//                ArrayList selection = vle.getSelectedRow();
173
//                if( selection.size() == 0){
174
//                        VectorialEditableAdapter vea = vle.getVEA();
175
//                        try {
176
//                                FBitSet bitset = vea.getSelection();
177
//                                for (int j = bitset.nextSetBit(0);j >= 0;j = bitset.nextSetBit(j + 1)){
178
//                                        IRowEdited rowEd = vea.getRow(j);
179
//                                        selection.add(rowEd);
180
//                                }
181
//                        } catch (ExpansionFileReadException e) {
182
//                                e.printStackTrace();
183
//                        } catch (ReadDriverException e) {
184
//                                e.printStackTrace();
185
//                        }
186
//                }//selection size
187
//                return selection;
188
//        }
189
//        public ArrayList getSelectedRows(){
190
//                return (ArrayList) CADUtil.getSelectedFeatures(getVLE());
191
//        }
192
        public Coordinate[] getPoint2DAsCoordinates(Point2D[] point2d) {
193
                Coordinate[] solution = new Coordinate[point2d.length];
194
                for (int i = 0; i < point2d.length; i++) {
195
                        solution[i] = new Coordinate(point2d[i].getX(), point2d[i].getY());
196
                }
197
                return solution;
198
        }
199
        public void splitSelectedGeometryWithDigitizedLine(){
200
                Point2D[] clickedPts = new Point2D[this.clickedPoints.size()];
201
                clickedPoints.toArray(clickedPts);
202
                Coordinate[] digitizedCoords = getPoint2DAsCoordinates(clickedPts);
203
                LineString splittingLs = new GeometryFactory(
204
                                new PrecisionModel(10000)).createLineString(digitizedCoords);
205
                try {
206
                        VectorialLayerEdited vle = getVLE();
207
                        FeatureStore store=vle.getFeatureStore();
208
                        Iterator<Feature> selected = store.getFeatureSelection().iterator();
209

    
210
                        getCadToolAdapter().getMapControl().getMapContext().beginAtomicEvent();
211
                        store.beginEditingGroup(getName());
212
                        while (selected.hasNext()) {
213
                                Feature feature = (Feature) selected.next();
214
                                org.gvsig.fmap.geom.Geometry ig = feature.getDefaultGeometry();
215
                                Geometry jtsGeo = Converter.geometryToJts(ig);
216
                                if (jtsGeo==null)
217
                                        return;
218
                                Geometry splitGeo = SplitStrategy.splitOp(jtsGeo, splittingLs);
219
                                if(splitGeo instanceof GeometryCollection
220
                                                && ((GeometryCollection)splitGeo).getNumGeometries()>1){
221

    
222
                                        GeometryCollection gc = (GeometryCollection)splitGeo;
223
                                        ArrayList<Geometry> geoms0=new ArrayList<Geometry>();
224
                                        ArrayList<Geometry> geoms1=new ArrayList<Geometry>();
225
                                        if (gc.getNumGeometries()>2){
226
                                                Geometry[] splitGroups=createSplitGroups(jtsGeo,splittingLs);
227
                                                if (splitGroups.length==0){
228
                                                        continue;
229
                                                }
230

    
231
                                                for(int j = 0; j < gc.getNumGeometries(); j++){
232
                                                        Geometry g = gc.getGeometryN(j);
233
                                                        if (splitGroups[0].contains(g)){
234
                                                                geoms0.add(g);
235
                                                        }else{
236
                                                                geoms1.add(g);
237
                                                        }
238
                                                }
239
                                        }else if (gc.getNumGeometries()==2){
240
                                                geoms0.add(gc.getGeometryN(0));
241
                                                geoms1.add(gc.getGeometryN(1));
242
                                        }else{
243
                                                continue;
244
                                        }
245
                                        GeometryCollection gc0=createMulti(geoms0,gc.getFactory());
246

    
247

    
248
//                                        for(int j = 0; j < gc.getNumGeometries(); j++){
249
//                                                Geometry g = gc.getGeometryN(j);
250
                                                org.gvsig.fmap.geom.Geometry fmapGeo = Converter.jtsToGeometry(gc0);
251

    
252
//                                                if (j==0){
253
                                                        EditableFeature eFeature=feature.getEditable();
254
                                                        eFeature.setGeometry(store.getDefaultFeatureType().getDefaultGeometryAttributeName(), fmapGeo);
255
                                                        store.update(eFeature);
256
//                                                }else{
257
                                                        GeometryCollection gc1=createMulti(geoms1,gc.getFactory());
258
                                                        fmapGeo = Converter.jtsToGeometry(gc1);
259

    
260
                                                        EditableFeature newFeature=store.createNewFeature(store.getDefaultFeatureType(), feature);
261
                                                        newFeature.setGeometry(store.getDefaultFeatureType().getDefaultGeometryAttributeName(), fmapGeo);
262
                                                        store.insert(newFeature);
263
                                                        SpatialCache spatialCache=((FLyrVect)vle.getLayer()).getSpatialCache();
264
                                                        Envelope envelope = fmapGeo.getEnvelope();
265
                                                        spatialCache.insert(envelope,fmapGeo);
266
//                                                }
267
//                                        }//for j
268
                                }//if splitGeo
269

    
270
                        }
271

    
272
                        store.endEditingGroup();
273

    
274
                        getCadToolAdapter().getMapControl().getMapContext().endAtomicEvent();
275
                } catch (Exception ex) {
276
                        PluginServices.getLogger().error("Error splitting geom", ex);
277
                }
278
        }
279
        private GeometryCollection createMulti(ArrayList<Geometry> geoms,GeometryFactory factory) {
280
                if (geoms.size()==0)
281
                        return null;
282
                if (geoms.get(0) instanceof Polygon){
283
                        return new MultiPolygon((Polygon[])geoms.toArray(new Polygon[0]),factory);
284
                }else if (geoms.get(0) instanceof LineString){
285
                        return new MultiLineString((LineString[])geoms.toArray(new LineString[0]),factory);
286
                }else if (geoms.get(0) instanceof Point){
287
                        return new MultiPoint((Point[])geoms.toArray(new Point[0]),factory);
288
                }
289
                return null;
290
        }
291
        private Geometry[] createSplitGroups(Geometry splitGeo, LineString splittingLs) {
292
                try{
293
                Geometry[] geomsJTS=new Geometry[2];
294
                Geometry r=splitGeo.getEnvelope();
295
                Geometry splitG = SplitStrategy.splitOp(r, splittingLs);
296
                if(splitG instanceof GeometryCollection
297
                                && ((GeometryCollection)splitG).getNumGeometries()>1){
298
                        GeometryCollection gc = (GeometryCollection)splitG;
299
                        for(int j = 0; j < gc.getNumGeometries(); j++){
300
                                geomsJTS[j]=gc.getGeometryN(j);
301
                        }
302
                }
303
                return geomsJTS;
304
                }catch (Exception e) {
305
                        NotificationManager.showMessageError(PluginServices.getText(this, "line_not_cross_rectangle"), e);
306
                }
307
                return null;
308
        }
309
        public void end(){
310
                getCadToolAdapter().refreshEditedLayer();
311
                init();
312
        }
313

    
314

    
315
        public void addOption(String s) {
316
                State actualState = _fsm.getPreviousState();
317
                String status = actualState.getName();
318
                if (s.equals(PluginServices.getText(this, "cancel"))) {
319
                        init();
320
                        return;
321
                }
322
                if (status.equals("TopologicalEdition.FirstPoint")) {
323
                        return;
324
                }
325
                init();
326

    
327
        }
328

    
329
        public void addPoint(double x, double y, InputEvent event) {
330

    
331
                State actualState = _fsm.getPreviousState();
332
                String status = actualState.getName();
333
                if (status.equals("SplitGeometry.FirstPoint")) {
334
                        clickedPoints = new ArrayList<Point2D>();
335
                        clickedPoints.add(new Point2D.Double(x,y));
336
                } else if (status.equals("SplitGeometry.DigitizingLine")) {
337
                        clickedPoints.add(new Point2D.Double(x,y));
338
                        if (event != null && ((MouseEvent) event).getClickCount() == 2) {
339
                                digitizingFinished = true;
340
                                finishDigitizedLine();
341
                                splitSelectedGeometryWithDigitizedLine();
342
                                end();
343
                        }
344
                }
345
        }
346

    
347
        public void addValue(double d) {
348
        }
349

    
350

    
351
        /**
352
         * Draws a polyline with the clicked digitized points in the specified graphics.
353
         *
354
         * @param g2 graphics on to draw the polyline
355
         * @param x last x mouse pointer position
356
         * @param y last y mouse pointer position
357
         */
358
        protected void drawPolyLine(MapControlDrawer renderer, double x, double y) {
359
                GeneralPathX gpx =
360
                        new GeneralPathX(GeneralPathX.WIND_EVEN_ODD,
361
                                                                        clickedPoints.size());
362
                Point2D firstPoint = clickedPoints.get(0);
363
                gpx.moveTo(firstPoint.getX(), firstPoint.getY());
364
                for (int i = 1; i < clickedPoints.size(); i++) {
365
                        Point2D clickedPoint = clickedPoints.get(i);
366
                        gpx.lineTo(clickedPoint.getX(), clickedPoint.getY());
367

    
368
                }
369
                gpx.lineTo(x, y);
370
                org.gvsig.fmap.geom.Geometry geom;
371
                try {
372
                        geom = GeometryLocator.getGeometryManager().createCurve(gpx, SUBTYPES.GEOM2D);
373
                        renderer.draw(geom, mapControlManager.getGeometrySelectionSymbol());
374
                } catch (LocatorException e) {
375
                        e.printStackTrace();
376
                } catch (CreateGeometryException e) {
377
                        e.printStackTrace();
378
                }
379
        }
380

    
381
        private void drawRectangleOfSplit(MapControlDrawer renderer) throws GeometryOperationNotSupportedException, GeometryOperationException, DataException {
382
                VectorialLayerEdited vle = getVLE();
383
                FeatureStore store=vle.getFeatureStore();
384
                Iterator<Feature> selected = store.getFeatureSelection().iterator();
385
                while (selected.hasNext()) {
386
                        Feature feature = (Feature) selected.next();
387
                        org.gvsig.fmap.geom.Geometry ig = feature.getDefaultGeometry();
388
                        Geometry jtsG = Converter.geometryToJts(ig);
389
                        if (jtsG !=null && jtsG instanceof GeometryCollection && jtsG.getNumGeometries()>1){
390
                                org.gvsig.fmap.geom.Geometry r=ig.getEnvelope().getGeometry();
391
                                renderer.draw(r, mapControlManager.getAxisReferenceSymbol());
392
                        }
393
                }
394
        }
395

    
396
        public void drawOperation(MapControlDrawer renderer, double x, double y) {
397
                State actualState = _fsm.getState();
398
        String status = actualState.getName();
399
        try {
400
                drawRectangleOfSplit(renderer);
401
            // draw splitting line
402
            if ((status.equals("SplitGeometry.DigitizingLine"))) {
403
                    drawPolyLine(renderer, x, y);
404
             }
405

    
406
            // draw selection
407
                Image imgSel = getVLE().getSelectionImage();
408
                renderer.drawImage(imgSel, 0, 0);
409
        } catch (Exception e) {
410
                PluginServices.getLogger().error("Error drawing Editing Selection", e);
411
        }
412
        }
413

    
414
        public String getName() {
415
                return PluginServices.getText(this, "split_geometry_shell");
416
        }
417

    
418

    
419
        public void transition(double x, double y, InputEvent event) {
420
                try {
421
                        _fsm.addPoint(x, y, event);
422
                } catch (Exception e) {
423
                        init();
424
                }
425

    
426
        }
427

    
428

    
429
        public void transition(double d) {
430
                _fsm.addValue(d);
431
        }
432

    
433
        public void transition(String s) throws CommandException {
434
                if (!super.changeCommand(s)) {
435
                        _fsm.addOption(s);
436
                }
437
        }
438

    
439
}