Statistics
| Revision:

root / trunk / extensions / extCAD / src / com / iver / cit / gvsig / gui / cad / tools / SplitGeometryCADTool.java @ 29723

History | View | Annotate | Download (15 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 com.iver.cit.gvsig.gui.cad.tools;
50

    
51
import java.awt.Graphics;
52
import java.awt.Graphics2D;
53
import java.awt.Image;
54
import java.awt.event.InputEvent;
55
import java.awt.event.MouseEvent;
56
import java.awt.geom.Point2D;
57
import java.awt.geom.Rectangle2D;
58
import java.util.ArrayList;
59
import java.util.List;
60

    
61
import org.apache.log4j.Logger;
62

    
63
import statemap.State;
64

    
65
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
66
import com.iver.andami.PluginServices;
67
import com.iver.andami.messages.NotificationManager;
68
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
69
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileWriteException;
70
import com.iver.cit.gvsig.exceptions.validate.ValidateRowException;
71
import com.iver.cit.gvsig.fmap.core.DefaultFeature;
72
import com.iver.cit.gvsig.fmap.core.FShape;
73
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
74
import com.iver.cit.gvsig.fmap.core.IFeature;
75
import com.iver.cit.gvsig.fmap.core.IGeometry;
76
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
77
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
78
import com.iver.cit.gvsig.fmap.edition.DefaultRowEdited;
79
import com.iver.cit.gvsig.fmap.edition.EditionEvent;
80
import com.iver.cit.gvsig.fmap.edition.IRowEdited;
81
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
82
import com.iver.cit.gvsig.fmap.layers.FBitSet;
83
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
84
import com.iver.cit.gvsig.fmap.layers.SpatialCache;
85
import com.iver.cit.gvsig.gui.cad.DefaultCADTool;
86
import com.iver.cit.gvsig.gui.cad.exception.CommandException;
87
import com.iver.cit.gvsig.gui.cad.tools.smc.SplitGeometryCADToolContext;
88
import com.iver.cit.gvsig.gui.cad.tools.split.SplitStrategy;
89
import com.iver.cit.gvsig.layers.VectorialLayerEdited;
90
import com.vividsolutions.jts.geom.Coordinate;
91
import com.vividsolutions.jts.geom.Geometry;
92
import com.vividsolutions.jts.geom.GeometryCollection;
93
import com.vividsolutions.jts.geom.GeometryFactory;
94
import com.vividsolutions.jts.geom.LineString;
95
import com.vividsolutions.jts.geom.MultiLineString;
96
import com.vividsolutions.jts.geom.MultiPoint;
97
import com.vividsolutions.jts.geom.MultiPolygon;
98
import com.vividsolutions.jts.geom.Point;
99
import com.vividsolutions.jts.geom.Polygon;
100
import com.vividsolutions.jts.geom.PrecisionModel;
101

    
102

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

    
113
        private static Logger logger = Logger.getLogger(SplitGeometryCADTool.class.getName());
114

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

    
121

    
122

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

    
128

    
129

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

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

    
140

    
141
        /**
142
         * Default Constructor
143
         */
144
        public SplitGeometryCADTool(){
145

    
146
        }
147

    
148

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

    
158

    
159

    
160
        public boolean isDigitizingFinished() {
161
                return digitizingFinished;
162
        }
163

    
164
        public String toString() {
165
                return SplitGeometryCADTool.SPLIT_GEOMETRY_TOOL_NAME;
166
        }
167

    
168

    
169

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

    
208
                ArrayList selectedRows = getSelectedRows();
209
                IRowEdited editedRow = null;
210
                VectorialLayerEdited vle = getVLE();
211
                VectorialEditableAdapter vea = vle.getVEA();
212
                getCadToolAdapter().getMapControl().getMapContext().beginAtomicEvent();
213
                vea.startComplexRow();
214
                List<Integer> indices = new ArrayList<Integer>();
215
                ArrayList auxSelectedRows=new ArrayList(selectedRows);
216
                try {
217
                        vle.clearSelection(false);
218
                } catch (ReadDriverException e1) {
219
                        e1.printStackTrace();
220
                }
221

    
222
                for (int i = 0; i < auxSelectedRows.size(); i++) {
223
                        editedRow = (IRowEdited) auxSelectedRows.get(i);
224
                        IFeature feat = (IFeature) editedRow.getLinkedRow().cloneRow();
225
                        IGeometry ig = feat.getGeometry();
226
                        Geometry jtsGeo = FConverter.java2d_to_jts((FShape)ig.getInternalShape());
227
                        if (jtsGeo==null)
228
                                return;
229
                        try {
230
                        Geometry splitGeo = SplitStrategy.splitOp(jtsGeo, splittingLs);
231
                        if(splitGeo instanceof GeometryCollection
232
                                        && ((GeometryCollection)splitGeo).getNumGeometries()>1){
233

    
234
                                //Saving originals polygons index
235
                                indices.add(new Integer(editedRow.getIndex()));
236
                                //and then, we add new features for each split geometry
237
                                GeometryCollection gc = (GeometryCollection)splitGeo;
238
                                ArrayList<Geometry> geoms0=new ArrayList<Geometry>();
239
                                ArrayList<Geometry> geoms1=new ArrayList<Geometry>();
240
                                if (gc.getNumGeometries()>2){
241
                                        Geometry[] splitGroups=createSplitGroups(jtsGeo,splittingLs);
242
                                        if (splitGroups.length==0){
243
                                                continue;
244
                                        }
245

    
246
                                        for(int j = 0; j < gc.getNumGeometries(); j++){
247
                                                Geometry g = gc.getGeometryN(j);
248
                                                if (splitGroups[0].contains(g)){
249
                                                        geoms0.add(g);
250
                                                }else{
251
                                                        geoms1.add(g);
252
                                                }
253
                                        }
254
                                }else if (gc.getNumGeometries()==2){
255
                                        geoms0.add(gc.getGeometryN(0));
256
                                        geoms1.add(gc.getGeometryN(1));
257
                                }else{
258
                                        continue;
259
                                }
260
                                GeometryCollection gc0=createMulti(geoms0,gc.getFactory());
261

    
262
                                        IGeometry fmapGeo = FConverter.jts_to_igeometry(gc0);
263
                                        DefaultFeature df = null;
264
                                        int newIdx = 0;
265
//                                        if (j==0){
266
                                                newIdx=editedRow.getIndex();
267
                                                try {
268
                                                        df = new DefaultFeature(fmapGeo, feat.getAttributes(),feat.getID());
269
                                                        vea.modifyRow(newIdx, df, getName(),
270
                                                                        EditionEvent.GRAPHIC);
271
                                                } catch (ValidateRowException e) {
272
                                                        NotificationManager.addError(e.getMessage(),e);
273
                                                } catch (ExpansionFileWriteException e) {
274
                                                        NotificationManager.addError(e.getMessage(),e);
275
                                                } catch (ReadDriverException e) {
276
                                                        NotificationManager.addError(e.getMessage(),e);
277
                                                }
278
//                                        }else{
279
                                                GeometryCollection gc1=createMulti(geoms1,gc.getFactory());
280
                                                fmapGeo = FConverter.jts_to_igeometry(gc1);
281
                                                try {
282
                                                        String newFID = vea.getNewFID();
283
                                                        df = new DefaultFeature(fmapGeo, feat.getAttributes(),newFID);
284
                                                        newIdx = vea.addRow(df, getName(), EditionEvent.GRAPHIC);
285
                                                        SpatialCache spatialCache=((FLyrVect)vle.getLayer()).getSpatialCache();
286
                                                        IGeometry geometry = df.getGeometry();
287
                                                        Rectangle2D r = geometry.getBounds2D();
288
                                                        if (geometry.getGeometryType() == FShape.POINT) {
289
                                                                r = new Rectangle2D.Double(r.getX(),r.getY(),1,1);
290
                                                        }
291
                                                        spatialCache.insert(r,geometry);
292
                                                } catch (ValidateRowException e) {
293
                                                        NotificationManager.addError(e);
294
                                                } catch (ReadDriverException e) {
295
                                                        NotificationManager.addError(e);
296
                                                }
297
//                                        }
298
                                        DefaultRowEdited newRowEdited = new DefaultRowEdited(df,
299
                                                                IRowEdited.STATUS_ADDED,
300
                                                                        newIdx);
301
                                        vle.addSelectionCache(newRowEdited);
302
//                                }//for j
303
                        }//if splitGeo
304
                        } catch (Exception ex) {
305
                                PluginServices.getLogger().error("Error splitting geom "+editedRow.getIndex(), ex);
306
                        }
307
                }
308
                vea.endComplexRow(getName());
309

    
310
                getCadToolAdapter().getMapControl().getMapContext().endAtomicEvent();
311
        }
312

    
313
        private GeometryCollection createMulti(ArrayList<Geometry> geoms,GeometryFactory factory) {
314
                if (geoms.size()==0)
315
                        return null;
316
                if (geoms.get(0) instanceof Polygon){
317
                        return new MultiPolygon((Polygon[])geoms.toArray(new Polygon[0]),factory);
318
                }else if (geoms.get(0) instanceof LineString){
319
                        return new MultiLineString((LineString[])geoms.toArray(new LineString[0]),factory);
320
                }else if (geoms.get(0) instanceof Point){
321
                        return new MultiPoint((Point[])geoms.toArray(new Point[0]),factory);
322
                }
323
                return null;
324
        }
325

    
326

    
327
        private Geometry[] createSplitGroups(Geometry splitGeo, LineString splittingLs) {
328
                try{
329
                Geometry[] geomsJTS=new Geometry[2];
330
                Geometry r=splitGeo.getEnvelope();
331
                Geometry splitG = SplitStrategy.splitOp(r, splittingLs);
332
                if(splitG instanceof GeometryCollection
333
                                && ((GeometryCollection)splitG).getNumGeometries()>1){
334
                        GeometryCollection gc = (GeometryCollection)splitG;
335
                        for(int j = 0; j < gc.getNumGeometries(); j++){
336
                                geomsJTS[j]=gc.getGeometryN(j);
337
                        }
338
                }
339
                return geomsJTS;
340
                }catch (Exception e) {
341
                        NotificationManager.showMessageError(PluginServices.getText(this, "line_not_cross_rectangle"), e);
342
                }
343
                return null;
344
        }
345

    
346
        public void end(){
347
                getCadToolAdapter().refreshEditedLayer();
348
                init();
349
        }
350

    
351
        public void addOption(String s) {
352
                State actualState = _fsm.getPreviousState();
353
                String status = actualState.getName();
354
                if (s.equals(PluginServices.getText(this, "cancel"))) {
355
                        init();
356
                        return;
357
                }
358
                if (status.equals("TopologicalEdition.FirstPoint")) {
359
                        return;
360
                }
361
                init();
362

    
363
        }
364

    
365
        public void addPoint(double x, double y, InputEvent event) {
366

    
367
                State actualState = _fsm.getPreviousState();
368
                String status = actualState.getName();
369
                if (status.equals("SplitGeometry.FirstPoint")) {
370
                        clickedPoints = new ArrayList<Point2D>();
371
                        clickedPoints.add(new Point2D.Double(x,y));
372
                } else if (status.equals("SplitGeometry.DigitizingLine")) {
373
                        clickedPoints.add(new Point2D.Double(x,y));
374
                        if (event != null && ((MouseEvent) event).getClickCount() == 2) {
375
                                digitizingFinished = true;
376
                                finishDigitizedLine();
377
                                splitSelectedGeometryWithDigitizedLine();
378
                                end();
379
                        }
380
                }
381
        }
382

    
383
        public void addValue(double d) {
384
        }
385

    
386

    
387
        /**
388
         * Draws a polyline with the clicked digitized points in the specified graphics.
389
         *
390
         * @param g2 graphics on to draw the polyline
391
         * @param x last x mouse pointer position
392
         * @param y last y mouse pointer position
393
         */
394
        protected void drawPolyLine(Graphics2D g, double x, double y) {
395
                GeneralPathX gpx =
396
                        new GeneralPathX(GeneralPathX.WIND_EVEN_ODD,
397
                                                                        clickedPoints.size());
398
                Point2D firstPoint = clickedPoints.get(0);
399
                gpx.moveTo(firstPoint.getX(), firstPoint.getY());
400
                for (int i = 1; i < clickedPoints.size(); i++) {
401
                        Point2D clickedPoint = clickedPoints.get(i);
402
                        gpx.lineTo(clickedPoint.getX(), clickedPoint.getY());
403

    
404
                }
405
                gpx.lineTo(x, y);
406
                ShapeFactory.createPolyline2D(gpx).draw((Graphics2D) g,
407
                                        getCadToolAdapter().getMapControl().getViewPort(),
408
                                        DefaultCADTool.geometrySelectSymbol);
409
        }
410

    
411

    
412

    
413

    
414
        public void drawOperation(Graphics g, double x, double y) {
415
                try{
416
                        State actualState = _fsm.getState();
417
                        String status = actualState.getName();
418
                        drawRectangleOfSplit((Graphics2D) g);
419
                        // draw splitting line
420
                        if ((status.equals("SplitGeometry.DigitizingLine"))) {
421
                                drawPolyLine((Graphics2D) g, x, y);
422
                        }
423
                }catch (Exception e) {
424
                        // TODO: handle exception
425
                }
426
                // draw selection
427
                try {
428
                        Image imgSel = getVLE().getSelectionImage();
429
                        if (imgSel != null)
430
                                g.drawImage(imgSel, 0, 0, null);
431
                } catch (Exception e) {
432
                        PluginServices.getLogger().error("Error drawing Editing Selection", e);
433
                }
434
        }
435

    
436
        private void drawRectangleOfSplit(Graphics2D g) {
437
                ArrayList selectedRows = getSelectedRows();
438
                for (int i = 0; i < selectedRows.size(); i++) {
439
                        IRowEdited editedRow = (IRowEdited) selectedRows.get(i);
440
                        IFeature feat = (IFeature) editedRow.getLinkedRow();
441
                        IGeometry ig = feat.getGeometry();
442
                        Geometry jtsG=ig.toJTSGeometry();
443
                        if (jtsG !=null && jtsG instanceof GeometryCollection && jtsG.getNumGeometries()>1){
444
                                Rectangle2D r=ig.getBounds2D();
445
                                GeneralPathX gpx = new GeneralPathX();
446
                                gpx.moveTo(r.getX(), r.getY());
447
                                gpx.lineTo(r.getMaxX(), r.getY());
448
                                gpx.lineTo(r.getMaxX(), r.getMaxY());
449
                                gpx.lineTo(r.getX(), r.getMaxY());
450
                                gpx.closePath();
451
                                ShapeFactory.createPolygon2D(gpx).draw((Graphics2D) g,
452
                                                getCadToolAdapter().getMapControl().getViewPort(),
453
                                                DefaultCADTool.axisReferencesSymbol);
454
                        }
455
                }
456

    
457
        }
458

    
459

    
460
        public String getName() {
461
                return PluginServices.getText(this, "split_geometry_shell");
462
        }
463

    
464

    
465
        public void transition(double x, double y, InputEvent event) {
466
                try {
467
                        _fsm.addPoint(x, y, event);
468
                } catch (Exception e) {
469
                        init();
470
                }
471

    
472
        }
473

    
474

    
475
        public void transition(double d) {
476
                _fsm.addValue(d);
477
        }
478

    
479
        public void transition(String s) throws CommandException {
480
                if (!super.changeCommand(s)) {
481
                        _fsm.addOption(s);
482
                }
483
        }
484
}