Statistics
| Revision:

gvsig-vectorediting / org.gvsig.vectorediting / trunk / org.gvsig.vectorediting / org.gvsig.vectorediting.lib / org.gvsig.vectorediting.lib.prov / org.gvsig.vectorediting.lib.prov.splitline / src / main / java / org / gvsig / vectorediting / lib / prov / splitline / SplitLineEditingProvider.java @ 498

History | View | Annotate | Download (17.8 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2014 gvSIG Association
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

    
25
package org.gvsig.vectorediting.lib.prov.splitline;
26

    
27
import java.util.ArrayList;
28
import java.util.HashMap;
29
import java.util.List;
30
import java.util.Map;
31

    
32
import org.gvsig.fmap.dal.exception.DataException;
33
import org.gvsig.fmap.dal.feature.EditableFeature;
34
import org.gvsig.fmap.dal.feature.Feature;
35
import org.gvsig.fmap.dal.feature.FeatureSelection;
36
import org.gvsig.fmap.dal.feature.FeatureStore;
37
import org.gvsig.fmap.geom.Geometry;
38
import org.gvsig.fmap.geom.GeometryLocator;
39
import org.gvsig.fmap.geom.aggregate.MultiCurve;
40
import org.gvsig.fmap.geom.exception.CreateGeometryException;
41
import org.gvsig.fmap.geom.operation.GeometryOperationException;
42
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
43
import org.gvsig.fmap.geom.primitive.Curve;
44
import org.gvsig.fmap.geom.primitive.Line;
45
import org.gvsig.fmap.geom.primitive.Point;
46
import org.gvsig.fmap.geom.primitive.Primitive;
47
import org.gvsig.fmap.geom.type.GeometryType;
48
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
49
import org.gvsig.tools.dispose.DisposableIterator;
50
import org.gvsig.tools.dynobject.DynObject;
51
import org.gvsig.tools.exception.BaseException;
52
import org.gvsig.tools.locator.LocatorException;
53
import org.gvsig.tools.service.spi.ProviderServices;
54
import org.gvsig.tools.visitor.VisitCanceledException;
55
import org.gvsig.tools.visitor.Visitor;
56
import org.gvsig.vectorediting.lib.api.DrawingStatus;
57
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
58
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
59
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
60
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
61
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
62
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
63
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
64
import org.gvsig.vectorediting.lib.prov.splitline.operation.SplitLineOperation;
65
import org.gvsig.vectorediting.lib.prov.splitline.operation.SplitLineOperationUtils;
66
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
67
import org.gvsig.vectorediting.lib.spi.DefaultDrawingStatus;
68
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
69
import org.gvsig.vectorediting.lib.spi.EditingProvider;
70
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
71
import org.gvsig.vectorediting.lib.spi.EditingProviderLocator;
72
import org.gvsig.vectorediting.lib.spi.EditingProviderManager;
73
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
74

    
75
/**
76
 * @author llmarques
77
 *
78
 */
79
public class SplitLineEditingProvider extends AbstractEditingProvider implements
80
    EditingProvider {
81

    
82
    private EditingServiceParameter selection;
83

    
84
    private EditingServiceParameter point;
85

    
86
    private FeatureStore featureStore;
87

    
88
    private Map<EditingServiceParameter, Object> values;
89

    
90
    /**
91
     * Default constructor.
92
     *
93
     * @param providerServices
94
     *            available services for this provider
95
     * @param parameters
96
     *            of this provider
97
     */
98
    public SplitLineEditingProvider(DynObject parameters,
99
        ProviderServices services) {
100
        super(services);
101

    
102
        this.featureStore =
103
            (FeatureStore) parameters
104
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
105

    
106
        this.selection =
107
            new DefaultEditingServiceParameter("selection", "selection",
108
                TYPE.SELECTION);
109

    
110
        this.point =
111
            new DefaultEditingServiceParameter("indicate_point",
112
                "indicate_point", TYPE.POSITION);
113
    }
114

    
115
    public EditingServiceParameter next() {
116

    
117
        if (values.get(selection) == null) {
118
            return selection;
119
        } else if (values.get(point) == null) {
120
            return point;
121
        }
122
        return null;
123
    }
124

    
125
    public DrawingStatus getDrawingStatus(Point mousePosition)
126
        throws DrawServiceException {
127
        if (values != null) {
128
            DefaultDrawingStatus drawingStatus = new DefaultDrawingStatus();
129
            EditingProviderManager editingProviderManager =
130
                EditingProviderLocator.getProviderManager();
131
            ISymbol auxiliaryPointSymbolEditing = editingProviderManager.getSymbol("auxiliary-point-symbol-editing");
132
            ISymbol auxiliaryLineSymbolEditing = editingProviderManager.getSymbol("auxiliary-line-symbol-editing");
133

    
134
            FeatureSelection featureSelection =
135
                (FeatureSelection) values.get(selection);
136

    
137
            DisposableIterator it = null;
138
            try {
139

    
140
                EditingProviderServices editingProviderService =
141
                    (EditingProviderServices) getProviderServices();
142

    
143
                int subtype = editingProviderService.getSubType(featureStore);
144

    
145
                it = featureSelection.fastIterator();
146
                while (it.hasNext()) {
147

    
148
                    Feature feature = (Feature) it.next();
149

    
150
                    Geometry lineToSplit =
151
                        getLineToSplit(feature.getDefaultGeometry());
152

    
153
                    Point projectedPoint =
154
                        getNearestPoint(lineToSplit, mousePosition);
155

    
156
                    Line line =
157
                        editingProviderService.createLine(mousePosition,
158
                            projectedPoint, subtype);
159
                    drawingStatus.addStatus(projectedPoint, auxiliaryPointSymbolEditing, "");
160
                    drawingStatus.addStatus(line, auxiliaryLineSymbolEditing, "");
161
                }
162
            } catch (Exception e) {
163
                throw new DrawServiceException(e);
164
            } finally {
165
                it.dispose();
166
            }
167
            return drawingStatus;
168
        }
169
        return null;
170
    }
171

    
172
    private Geometry getLineToSplit(Geometry geometry) {
173
        Geometry line = null;
174
        GeometryType geoType = geometry.getGeometryType();
175
        if (geoType.isTypeOf(Geometry.TYPES.CURVE)) {
176
            line = (Curve) geometry;
177
        } else if (geoType.isTypeOf(Geometry.TYPES.MULTICURVE)) {
178
            line = (MultiCurve) geometry;
179
        }
180
        return line;
181
    }
182

    
183
    private Point getNearestPoint(Geometry lineToSplit, Point point)
184
        throws GeometryOperationNotSupportedException,
185
        GeometryOperationException {
186

    
187
        return (Point) lineToSplit.closestPoints(point)[0];
188
    }
189

    
190
    public void stop() throws StopServiceException {
191
        if (values != null) {
192
            values.clear();
193
        }
194
    }
195

    
196
    public List<EditingServiceParameter> getParameters() {
197
        List<EditingServiceParameter> parameters =
198
            new ArrayList<EditingServiceParameter>();
199
        parameters.add(selection);
200
        parameters.add(point);
201
        return parameters;
202
    }
203

    
204
    public void setValue(Object value) throws InvalidEntryException {
205
        EditingServiceParameter parameter = next();
206
        validateAndInsertValue(parameter, value);
207

    
208
    }
209

    
210
    private void validateAndInsertValue(EditingServiceParameter parameter,
211
        final Object value) throws InvalidEntryException {
212

    
213
        if (values != null && value != null) {
214

    
215
            if (value instanceof FeatureSelection) {
216

    
217
                FeatureSelection feautureSelection = (FeatureSelection) value;
218
                if (feautureSelection.getSelectedCount() == 1) {
219

    
220
                    try {
221
                        feautureSelection.accept(new Visitor() {
222

    
223
                            public void visit(Object obj)
224
                                throws VisitCanceledException, BaseException {
225
                                Feature feature = (Feature) obj;
226
                                Geometry geometry =
227
                                    feature.getDefaultGeometry();
228
                                GeometryType geoType =
229
                                    geometry.getGeometryType();
230

    
231
                                if (geoType.isTypeOf(Geometry.TYPES.CURVE)) {
232

    
233
                                    if (isClosed((Curve) geometry)) {
234
                                        throw new InvalidEntryException(null);
235
                                    } else {
236
                                        values.put(selection, value);
237
                                        return;
238
                                    }
239

    
240
                                } else if (geoType
241
                                    .isTypeOf(Geometry.TYPES.MULTICURVE)) {
242

    
243
                                    MultiCurve multiCurve =
244
                                        (MultiCurve) geometry;
245

    
246
                                    for (int i = 0; i < multiCurve
247
                                        .getPrimitivesNumber(); i++) {
248
                                        if (isClosed((Curve) multiCurve
249
                                            .getPrimitiveAt(i))) {
250
                                            throw new InvalidEntryException(
251
                                                null);
252
                                        }
253
                                    }
254
                                    values.put(selection, value);
255
                                    return;
256
                                }
257
                            }
258
                        });
259
                        return;
260
                    } catch (BaseException e) {
261
                        throw new InvalidEntryException(e);
262
                    }
263
                }
264
            } else if (value instanceof Point) {
265
                values.put(parameter, value);
266
                return;
267
            }
268
        }
269
        throw new InvalidEntryException(null);
270
    }
271

    
272
    private boolean isClosed(Curve curve) {
273
        Point firstPoint = curve.getVertex(0);
274
        Point lastPoint = curve.getVertex(curve.getNumVertices() - 1);
275

    
276
        if (firstPoint.equals(lastPoint)) {
277
            return true;
278
        }
279

    
280
        return false;
281
    }
282

    
283
    public Geometry finish() throws FinishServiceException {
284
        return null;
285
    }
286

    
287
    public void finishAndStore() throws FinishServiceException {
288

    
289
        if (values != null) {
290

    
291
            final EditingProviderServices editingProviderService =
292
                (EditingProviderServices) getProviderServices();
293

    
294
            FeatureSelection featureSelection =
295
                (FeatureSelection) values.get(selection);
296

    
297
            final Point pointValue = (Point) values.get(point);
298

    
299
            try {
300
                featureSelection.accept(new Visitor() {
301

    
302
                    public void visit(Object obj)
303
                        throws VisitCanceledException, BaseException {
304
                        Feature feature = (Feature) obj;
305

    
306
                        Geometry lineToSplit =
307
                            getLineToSplit(feature.getDefaultGeometry());
308
                        GeometryType geomType = lineToSplit.getGeometryType();
309

    
310
                        Point projectedPoint =
311
                            getNearestPoint(lineToSplit, pointValue);
312

    
313
                        if (geomType.isTypeOf(Geometry.TYPES.CURVE)) {
314

    
315
                            Curve[] splittedCurves =
316
                                splitCurve((Curve) lineToSplit, projectedPoint);
317

    
318
                            // Deletes old feature
319
                            editingProviderService
320
                                .deleteFeatureFromFeatureStore(feature,
321
                                    featureStore);
322

    
323
                            // Copy alfanumeric data and insert new feature
324
                            EditableFeature eFeature =
325
                                editingProviderService.getFeatureCopyWithoutPK(
326
                                    featureStore, feature);
327
                            eFeature.setDefaultGeometry(splittedCurves[0]);
328
                            editingProviderService
329
                                .insertFeatureIntoFeatureStore(eFeature,
330
                                    featureStore);
331

    
332
                            eFeature =
333
                                editingProviderService.getFeatureCopyWithoutPK(
334
                                    featureStore, feature);
335
                            eFeature.setDefaultGeometry(splittedCurves[1]);
336
                            editingProviderService
337
                                .insertFeatureIntoFeatureStore(eFeature,
338
                                    featureStore);
339

    
340
                        } else if (geomType.isTypeOf(Geometry.TYPES.MULTICURVE)) {
341

    
342
                            MultiCurve multiCurve = (MultiCurve) lineToSplit;
343

    
344
                            List<Geometry> result = splitMultiCurve(multiCurve, projectedPoint);
345

    
346
                            if (result != null && result.size() > 0) {
347
                                
348
                                // Deletes old feature
349
                                editingProviderService
350
                                    .deleteFeatureFromFeatureStore(feature,
351
                                        featureStore);
352
                                
353
                                for (Geometry geometry : result) {
354
                                    // Copy alfanumeric data and insert new feature
355
                                    EditableFeature eFeature =
356
                                        editingProviderService.getFeatureCopyWithoutPK(
357
                                            featureStore, feature);
358
                                    
359
                                    eFeature.setDefaultGeometry(geometry);
360
                                    editingProviderService
361
                                        .insertFeatureIntoFeatureStore(eFeature,
362
                                            featureStore);
363
                                }
364
                            }
365
                        }
366
                    }
367
                });
368

    
369
                featureStore.getFeatureSelection().deselectAll();
370

    
371
            } catch (BaseException e) {
372
                throw new FinishServiceException(e);
373
            }
374
        }
375
    }
376

    
377
    private List<Geometry> splitMultiCurve(MultiCurve multiCurveToSplit,
378
        Point projectedPoint) throws GeometryOperationNotSupportedException,
379
        GeometryOperationException, CreateGeometryException, LocatorException,
380
        DataException {
381
        
382
        List<Geometry> result = new ArrayList<Geometry>();
383
        
384
        Curve curveToSplit = null;
385

    
386
        for (int i = 0; i < multiCurveToSplit.getPrimitivesNumber(); i++) {
387

    
388
            if (intersects(multiCurveToSplit.getCurveAt(i), projectedPoint)) {
389
                curveToSplit = multiCurveToSplit.getCurveAt(i);
390
            }
391
        }
392

    
393
        Curve[] splitedCurves = splitCurve(curveToSplit, projectedPoint);
394
            
395
        for(int i = 0; i < splitedCurves.length; i++){
396
            result.add(splitedCurves[i]);
397
        }
398

    
399
        EditingProviderServices editingProviderService =
400
            (EditingProviderServices) getProviderServices();
401
        int subtype = editingProviderService.getSubType(featureStore);
402
        MultiCurve multiCurve =
403
            GeometryLocator.getGeometryManager().createMultiCurve(subtype);
404

    
405
        for (int i = 0; i < multiCurveToSplit.getPrimitivesNumber(); i++) {
406

    
407
            if (!intersects(multiCurveToSplit.getCurveAt(i), projectedPoint)) {
408
                multiCurve.addCurve(multiCurveToSplit.getCurveAt(i));
409
            }
410
        }
411
        
412
        if(multiCurve.getPrimitivesNumber() > 0){
413
            result.add(multiCurve);
414
        }
415
        
416
        return result;
417
    }
418

    
419
    private Curve[] splitCurve(Curve curveToSplit, Point projectedPoint)
420
        throws DataException, CreateGeometryException, LocatorException,
421
        GeometryOperationNotSupportedException, GeometryOperationException {
422

    
423
        SplitLineOperation operation =
424
            SplitLineOperationUtils.getOperation((Primitive) curveToSplit);
425

    
426
        if (operation != null) {
427
            return operation.split(curveToSplit, projectedPoint);
428
        }
429
        return null;
430
    }
431

    
432
    /**
433
     * Method use to know what segment intersect with projected point. Due to
434
     * accuracy of doubles it is necessary to create a buffer of line to know if
435
     * it intersects.
436
     *
437
     * @param curve
438
     *            segment of line
439
     * @param projectedPoint
440
     *            of line
441
     * @return true if segment intersects with projected point, else false.
442
     */
443
    private boolean intersects(Curve curve, Point projectedPoint)
444
        throws GeometryOperationNotSupportedException,
445
        GeometryOperationException {
446

    
447
        double tolerance = 1;
448

    
449
        return curve.buffer(tolerance).intersects(projectedPoint);
450
    }
451

    
452
    public void start() throws StartServiceException, InvalidEntryException {
453
        values = new HashMap<EditingServiceParameter, Object>();
454
        FeatureSelection selected = null;
455
        if (featureStore != null) {
456
            try {
457
                selected = featureStore.getFeatureSelection();
458
            } catch (DataException e) {
459
                throw new StartServiceException(e);
460
            }
461
            if (selected.getSelectedCount() > 0) {
462
                setValue(selected);
463
            }
464
        }
465
    }
466

    
467
    public String getName() {
468
        return SplitLineEditingProviderFactory.PROVIDER_NAME;
469
    }
470

    
471
}