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

History | View | Annotate | Download (17.1 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) || geoType
232
                                    .isTypeOf(Geometry.TYPES.MULTICURVE)) {
233

    
234
//                                    if (!isClosed((Curve) geometry)) {
235
                                        values.put(selection, value);
236
                                        return;
237
//                                    }
238

    
239
//                                } else if (geoType
240
//                                    .isTypeOf(Geometry.TYPES.MULTICURVE)) {
241
//
242
//                                    MultiCurve multiCurve =
243
//                                        (MultiCurve) geometry;
244
//
245
//                                    for (int i = 0; i < multiCurve
246
//                                        .getPrimitivesNumber(); i++) {
247
//                                        if (isClosed((Curve) multiCurve
248
//                                            .getPrimitiveAt(i))) {
249
//                                            throw new InvalidEntryException(
250
//                                                null);
251
//                                        }
252
//                                    }
253
//                                    values.put(selection, value);
254
//                                    return;
255
                                }
256
                            }
257
                        });
258
                        return;
259
                    } catch (BaseException e) {
260
                        throw new InvalidEntryException(e);
261
                    }
262
                }
263
            } else if (value instanceof Point) {
264
                values.put(parameter, value);
265
                return;
266
            }
267
        }
268
        throw new InvalidEntryException(null);
269
    }
270

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

    
275
        if (firstPoint.getX() == lastPoint.getX()
276
            && firstPoint.getY() == lastPoint.getY()) {
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
                            multiCurve =
345
                                splitMultiCurve(multiCurve, projectedPoint);
346

    
347
                            if (multiCurve != null) {
348
                                // Copy alfanumeric data and insert new feature
349
                                EditableFeature eFeature =
350
                                    feature.getEditable();
351
                                eFeature.setDefaultGeometry(multiCurve);
352

    
353
                                editingProviderService
354
                                    .updateFeatureInFeatureStore(eFeature,
355
                                        featureStore);
356
                            }
357
                        }
358
                    }
359
                });
360

    
361
                featureStore.getFeatureSelection().deselectAll();
362

    
363
            } catch (BaseException e) {
364
                throw new FinishServiceException(e);
365
            }
366
        }
367
    }
368

    
369
    private MultiCurve splitMultiCurve(MultiCurve multiCurveToSplit,
370
        Point projectedPoint) throws GeometryOperationNotSupportedException,
371
        GeometryOperationException, CreateGeometryException, LocatorException,
372
        DataException {
373

    
374
        Curve curveToSplit = null;
375

    
376
        for (int i = 0; i < multiCurveToSplit.getPrimitivesNumber(); i++) {
377

    
378
            if (intersects(multiCurveToSplit.getCurveAt(i), projectedPoint)) {
379
                curveToSplit = multiCurveToSplit.getCurveAt(i);
380
            }
381
        }
382

    
383
        Curve[] splitedCurves = splitCurve(curveToSplit, projectedPoint);
384

    
385
        EditingProviderServices editingProviderService =
386
            (EditingProviderServices) getProviderServices();
387
        int subtype = editingProviderService.getSubType(featureStore);
388
        MultiCurve multiCurve =
389
            GeometryLocator.getGeometryManager().createMultiCurve(subtype);
390

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

    
393
            if (intersects(multiCurveToSplit.getCurveAt(i), projectedPoint)) {
394
                multiCurve.addCurve(splitedCurves[0]);
395
                multiCurve.addCurve(splitedCurves[1]);
396
            } else {
397
                multiCurve.addCurve(multiCurveToSplit.getCurveAt(i));
398
            }
399
        }
400

    
401
        return multiCurve;
402
    }
403

    
404
    private Curve[] splitCurve(Curve curveToSplit, Point projectedPoint)
405
        throws DataException, CreateGeometryException, LocatorException,
406
        GeometryOperationNotSupportedException, GeometryOperationException {
407

    
408
        SplitLineOperation operation =
409
            SplitLineOperationUtils.getOperation((Primitive) curveToSplit);
410

    
411
        if (operation != null) {
412
            return operation.split(curveToSplit, projectedPoint);
413
        }
414
        return null;
415
    }
416

    
417
    /**
418
     * Method use to know what segment intersect with projected point. Due to
419
     * accuracy of doubles it is necessary to create a buffer of line to know if
420
     * it intersects.
421
     *
422
     * @param curve
423
     *            segment of line
424
     * @param projectedPoint
425
     *            of line
426
     * @return true if segment intersects with projected point, else false.
427
     */
428
    private boolean intersects(Curve curve, Point projectedPoint)
429
        throws GeometryOperationNotSupportedException,
430
        GeometryOperationException {
431

    
432
        double tolerance = 1;
433

    
434
        return curve.buffer(tolerance).intersects(projectedPoint);
435
    }
436

    
437
    public void start() throws StartServiceException, InvalidEntryException {
438
        values = new HashMap<EditingServiceParameter, Object>();
439
        FeatureSelection selected = null;
440
        if (featureStore != null) {
441
            try {
442
                selected = featureStore.getFeatureSelection();
443
            } catch (DataException e) {
444
                throw new StartServiceException(e);
445
            }
446
            if (selected.getSelectedCount() > 0) {
447
                setValue(selected);
448
            }
449
        }
450
    }
451

    
452
    public String getName() {
453
        return SplitLineEditingProviderFactory.PROVIDER_NAME;
454
    }
455

    
456
}