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 @ 575

History | View | Annotate | Download (17.9 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.GeometryException;
39
import org.gvsig.fmap.geom.GeometryLocator;
40
import org.gvsig.fmap.geom.aggregate.MultiCurve;
41
import org.gvsig.fmap.geom.operation.GeometryOperationException;
42
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
43
import org.gvsig.fmap.geom.primitive.Arc;
44
import org.gvsig.fmap.geom.primitive.Curve;
45
import org.gvsig.fmap.geom.primitive.Line;
46
import org.gvsig.fmap.geom.primitive.Point;
47
import org.gvsig.fmap.geom.primitive.Primitive;
48
import org.gvsig.fmap.geom.type.GeometryType;
49
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
50
import org.gvsig.tools.ToolsLocator;
51
import org.gvsig.tools.dispose.DisposableIterator;
52
import org.gvsig.tools.dynobject.DynObject;
53
import org.gvsig.tools.exception.BaseException;
54
import org.gvsig.tools.locator.LocatorException;
55
import org.gvsig.tools.service.spi.ProviderServices;
56
import org.gvsig.tools.visitor.VisitCanceledException;
57
import org.gvsig.tools.visitor.Visitor;
58
import org.gvsig.vectorediting.lib.api.DrawingStatus;
59
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
60
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
61
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
62
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
63
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
64
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
65
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
66
import org.gvsig.vectorediting.lib.prov.splitline.operation.SplitLineOperation;
67
import org.gvsig.vectorediting.lib.prov.splitline.operation.SplitLineOperationUtils;
68
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
69
import org.gvsig.vectorediting.lib.spi.DefaultDrawingStatus;
70
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
71
import org.gvsig.vectorediting.lib.spi.EditingProvider;
72
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
73
import org.gvsig.vectorediting.lib.spi.EditingProviderLocator;
74
import org.gvsig.vectorediting.lib.spi.EditingProviderManager;
75
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
76

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

    
84
    private EditingServiceParameter selection;
85

    
86
    private EditingServiceParameter point;
87

    
88
    private FeatureStore featureStore;
89

    
90
    private Map<EditingServiceParameter, Object> values;
91

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

    
104
        this.featureStore =
105
            (FeatureStore) parameters
106
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
107

    
108
        this.selection =
109
            new DefaultEditingServiceParameter("selection", "selection",
110
                TYPE.SELECTION);
111

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

    
117
    public EditingServiceParameter next() {
118

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

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

    
136
            FeatureSelection featureSelection =
137
                (FeatureSelection) values.get(selection);
138

    
139
            DisposableIterator it = null;
140
            try {
141

    
142
                EditingProviderServices editingProviderService =
143
                    (EditingProviderServices) getProviderServices();
144

    
145
                int subtype = editingProviderService.getSubType(featureStore);
146

    
147
                it = featureSelection.fastIterator();
148
                while (it.hasNext()) {
149

    
150
                    Feature feature = (Feature) it.next();
151

    
152
                    Geometry lineToSplit =
153
                        getLineToSplit(feature.getDefaultGeometry());
154

    
155
                    Point projectedPoint =
156
                        getNearestPoint(lineToSplit, mousePosition);
157

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

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

    
185
    private Point getNearestPoint(Geometry lineToSplit, Point point)
186
        throws GeometryOperationNotSupportedException,
187
        GeometryOperationException {
188

    
189
        return (Point) lineToSplit.closestPoints(point)[0];
190
    }
191

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

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

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

    
210
    }
211

    
212
    private void validateAndInsertValue(EditingServiceParameter parameter,
213
        final Object value) throws InvalidEntryException {
214

    
215
        if (values != null && value != null) {
216

    
217
            if (value instanceof FeatureSelection) {
218

    
219
                FeatureSelection feautureSelection = (FeatureSelection) value;
220
                if (feautureSelection.getSelectedCount() == 1) {
221

    
222
                    try {
223
                        feautureSelection.accept(new Visitor() {
224

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

    
233
                                if (geoType.isTypeOf(Geometry.TYPES.CURVE)) {
234

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

    
242
                                } else if (geoType
243
                                    .isTypeOf(Geometry.TYPES.MULTICURVE)) {
244

    
245
                                    MultiCurve multiCurve =
246
                                        (MultiCurve) geometry;
247

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

    
274
    private boolean isAnArcClosed(Curve curve) {
275

    
276
        if( curve instanceof Arc){
277
            Point firstPoint = curve.getVertex(0);
278
            Point lastPoint = curve.getVertex(curve.getNumVertices() - 1);
279

    
280
            if (firstPoint.equals(lastPoint)) {
281
                return true;
282
            }
283
        }
284
        return false;
285
    }
286

    
287
    public Geometry finish() throws FinishServiceException {
288
        return null;
289
    }
290

    
291
    public void finishAndStore() throws FinishServiceException {
292

    
293
        if (values != null) {
294

    
295
            final EditingProviderServices editingProviderService =
296
                (EditingProviderServices) getProviderServices();
297

    
298
            FeatureSelection featureSelection =
299
                (FeatureSelection) values.get(selection);
300
            ToolsLocator.getDisposableManager().bind(featureSelection);
301

    
302
            final Point pointValue = (Point) values.get(point);
303

    
304
            try {
305
                featureSelection.accept(new Visitor() {
306

    
307
                    public void visit(Object obj)
308
                        throws VisitCanceledException, BaseException {
309
                        Feature feature = (Feature) obj;
310

    
311
                        Geometry lineToSplit =
312
                            getLineToSplit(feature.getDefaultGeometry());
313
                        GeometryType geomType = lineToSplit.getGeometryType();
314

    
315
                        Point projectedPoint =
316
                            getNearestPoint(lineToSplit, pointValue);
317

    
318
                        if (geomType.isTypeOf(Geometry.TYPES.CURVE)) {
319

    
320
                            Curve[] splittedCurves =
321
                                splitCurve((Curve) lineToSplit, projectedPoint);
322

    
323
                            // Deletes old feature
324
                            editingProviderService
325
                                .deleteFeatureFromFeatureStore(feature,
326
                                    featureStore);
327

    
328
                            // Copy alfanumeric data and insert new feature
329
                            EditableFeature eFeature =
330
                                editingProviderService.getFeatureCopyWithoutPK(
331
                                    featureStore, feature);
332
                            eFeature.setDefaultGeometry(splittedCurves[0]);
333
                            editingProviderService
334
                                .insertFeatureIntoFeatureStore(eFeature,
335
                                    featureStore);
336

    
337
                            eFeature =
338
                                editingProviderService.getFeatureCopyWithoutPK(
339
                                    featureStore, feature);
340
                            eFeature.setDefaultGeometry(splittedCurves[1]);
341
                            editingProviderService
342
                                .insertFeatureIntoFeatureStore(eFeature,
343
                                    featureStore);
344

    
345
                        } else if (geomType.isTypeOf(Geometry.TYPES.MULTICURVE)) {
346

    
347
                            MultiCurve multiCurve = (MultiCurve) lineToSplit;
348

    
349
                            List<Geometry> result = splitMultiCurve(multiCurve, projectedPoint);
350

    
351
                            if (result != null && result.size() > 0) {
352

    
353
                                // Deletes old feature
354
                                editingProviderService
355
                                    .deleteFeatureFromFeatureStore(feature,
356
                                        featureStore);
357

    
358
                                for (Geometry geometry : result) {
359
                                    // Copy alfanumeric data and insert new feature
360
                                    EditableFeature eFeature =
361
                                        editingProviderService.getFeatureCopyWithoutPK(
362
                                            featureStore, feature);
363

    
364
                                    eFeature.setDefaultGeometry(geometry);
365
                                    editingProviderService
366
                                        .insertFeatureIntoFeatureStore(eFeature,
367
                                            featureStore);
368
                                }
369
                            }
370
                        }
371
                    }
372
                });
373

    
374
                featureStore.getFeatureSelection().deselectAll();
375
                featureSelection.dispose();
376

    
377
            } catch (BaseException e) {
378
                throw new FinishServiceException(e);
379
            }
380
        }
381
    }
382

    
383
    private List<Geometry> splitMultiCurve(MultiCurve multiCurveToSplit,
384
        Point projectedPoint) throws GeometryOperationNotSupportedException,
385
        GeometryOperationException, LocatorException,
386
        DataException, GeometryException {
387

    
388
        List<Geometry> result = new ArrayList<Geometry>();
389

    
390
        Curve curveToSplit = null;
391

    
392
        for (int i = 0; i < multiCurveToSplit.getPrimitivesNumber(); i++) {
393

    
394
            if (intersects(multiCurveToSplit.getCurveAt(i), projectedPoint)) {
395
                curveToSplit = multiCurveToSplit.getCurveAt(i);
396
            }
397
        }
398

    
399
        Curve[] splitedCurves = splitCurve(curveToSplit, projectedPoint);
400

    
401
        for(int i = 0; i < splitedCurves.length; i++){
402
            result.add(splitedCurves[i]);
403
        }
404

    
405
        EditingProviderServices editingProviderService =
406
            (EditingProviderServices) getProviderServices();
407
        int subtype = editingProviderService.getSubType(featureStore);
408
        MultiCurve multiCurve =
409
            GeometryLocator.getGeometryManager().createMultiCurve(subtype);
410

    
411
        for (int i = 0; i < multiCurveToSplit.getPrimitivesNumber(); i++) {
412

    
413
            if (!intersects(multiCurveToSplit.getCurveAt(i), projectedPoint)) {
414
                multiCurve.addCurve(multiCurveToSplit.getCurveAt(i));
415
            }
416
        }
417

    
418
        if(multiCurve.getPrimitivesNumber() > 0){
419
            result.add(multiCurve);
420
        }
421

    
422
        return result;
423
    }
424

    
425
    private Curve[] splitCurve(Curve curveToSplit, Point projectedPoint)
426
        throws DataException, LocatorException,
427
        GeometryOperationNotSupportedException, GeometryOperationException, GeometryException {
428

    
429
        SplitLineOperation operation =
430
            SplitLineOperationUtils.getOperation((Primitive) curveToSplit);
431

    
432
        if (operation != null) {
433
            return operation.split(curveToSplit, projectedPoint);
434
        }
435
        return null;
436
    }
437

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

    
453
        double tolerance = 1;
454

    
455
        return curve.buffer(tolerance).intersects(projectedPoint);
456
    }
457

    
458
    public void start() throws StartServiceException, InvalidEntryException {
459
        values = new HashMap<EditingServiceParameter, Object>();
460
        FeatureSelection selected = null;
461
        if (featureStore != null) {
462
            try {
463
                selected = featureStore.getFeatureSelection();
464
            } catch (DataException e) {
465
                throw new StartServiceException(e);
466
            }
467
            if (selected.getSelectedCount() > 0) {
468
                setValue(selected);
469
            }
470
        }
471
    }
472

    
473
    public String getName() {
474
        return SplitLineEditingProviderFactory.PROVIDER_NAME;
475
    }
476

    
477
}