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.trimline / src / main / java / org / gvsig / vectorediting / lib / prov / trimline / TrimLineEditingProvider.java @ 3067

History | View | Annotate | Download (17.6 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2015 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.trimline;
26

    
27
import java.util.ArrayList;
28
import java.util.Collections;
29
import java.util.HashMap;
30
import java.util.List;
31
import java.util.Map;
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 static org.gvsig.fmap.geom.Geometry.TYPES.CURVE;
39
import static org.gvsig.fmap.geom.Geometry.TYPES.MULTICURVE;
40
import org.gvsig.fmap.geom.GeometryException;
41
import org.gvsig.fmap.geom.GeometryLocator;
42
import org.gvsig.fmap.geom.GeometryManager;
43
import org.gvsig.fmap.geom.aggregate.MultiCurve;
44
import org.gvsig.fmap.geom.exception.CreateGeometryException;
45
import org.gvsig.fmap.geom.operation.GeometryOperationException;
46
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
47
import org.gvsig.fmap.geom.primitive.Arc;
48
import org.gvsig.fmap.geom.primitive.Curve;
49
import org.gvsig.fmap.geom.primitive.Line;
50
import org.gvsig.fmap.geom.primitive.Point;
51
import org.gvsig.fmap.geom.primitive.Primitive;
52
import org.gvsig.fmap.geom.type.GeometryType;
53
import org.gvsig.fmap.mapcontext.MapContext;
54
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
55
import org.gvsig.tools.dynobject.DynObject;
56
import org.gvsig.tools.exception.BaseException;
57
import org.gvsig.tools.service.spi.ProviderServices;
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.trimline.operation.TrimLineOperation;
67
import org.gvsig.vectorediting.lib.prov.trimline.operation.TrimLineOperationUtils;
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 TrimLineEditingProvider extends AbstractEditingProvider implements
82
    EditingProvider {
83

    
84
    private final int TOLERANCE_PIXELS = 3;
85

    
86
    private final EditingServiceParameter selectionParameter;
87

    
88
    private final EditingServiceParameter geometryToTrimWithParameter;
89

    
90
    private final EditingServiceParameter shearingPointParameter;
91
    
92
    protected Map<EditingServiceParameter, Object> values;
93

    
94
    private final FeatureStore featureStore;
95

    
96
    private final MapContext mapContext;
97

    
98
    private List<Feature> selectedFeatures;
99
    
100
    /**
101
     * Default constructor.
102
     *
103
     * @param services
104
     *            available services for this provider
105
     * @param parameters
106
     *            of this provider
107
     */
108
    public TrimLineEditingProvider(ProviderServices services,
109
        DynObject parameters) {
110
        super(services);
111

    
112
        this.featureStore =
113
            (FeatureStore) parameters
114
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
115

    
116
        this.mapContext =
117
            (MapContext) parameters
118
                .getDynValue(EditingProviderFactory.MAPCONTEXT_FIELD);
119

    
120
        this.selectionParameter =
121
            new DefaultEditingServiceParameter("selection", "selection",
122
                TYPE.SELECTION);
123

    
124
        this.geometryToTrimWithParameter =
125
            new DefaultEditingServiceParameter("geometry_to_trim_with", "geometry_to_trim_with",
126
                TYPE.POSITION);
127
        
128
        this.shearingPointParameter
129
                = new DefaultEditingServiceParameter("shearing_point",
130
                        "shearing_point", TYPE.POSITION);
131

    
132
    }
133

    
134
    @Override
135
    public EditingServiceParameter next() {
136
        if (values.get(selectionParameter) == null) {
137
            return selectionParameter;
138
        } else if (values.get(geometryToTrimWithParameter) == null) {
139
            return geometryToTrimWithParameter;
140
        } else if (values.get(shearingPointParameter) == null) {
141
            return shearingPointParameter;
142
        }
143
        return null;
144
    }
145

    
146
    @Override
147
    public DrawingStatus getDrawingStatus(Point mousePosition)
148
        throws DrawServiceException {
149
        FeatureSelection selection = (FeatureSelection) values.get(selectionParameter);
150
        Geometry shears = (Geometry) values.get(geometryToTrimWithParameter);
151
        if (selection != null && shears != null) {
152
            DefaultDrawingStatus drawingStatus = new DefaultDrawingStatus();
153

    
154
            EditingProviderManager editingProviderManager =
155
                EditingProviderLocator.getProviderManager();
156
            ISymbol lineSymbolEditing =
157
                editingProviderManager.getSymbol("line-symbol-editing");
158

    
159
            try {
160
                for (Feature feature : selectedFeatures) {
161
                    if (feature != null) {
162
                        ISymbol previewSymbol = this.getPreviewSymbol(feature);
163
                        Geometry geometry = feature.getDefaultGeometry();
164
                        if(geometry != null && geometry.intersects(shears)) {
165
                            if (geometry instanceof MultiCurve) {
166
                                MultiCurve multiCurve = (MultiCurve) geometry;
167
                                for (int i = 0; i < multiCurve.getPrimitivesNumber(); i++) {
168
                                    Curve curve = multiCurve.getCurveAt(i);
169
                                    MultiCurve trimmedCurve = trimLine(mousePosition, curve, shears);
170
                                    for (int j = 0; j < trimmedCurve.getPrimitivesNumber(); j++) {
171
                                        final Curve primitive = trimmedCurve.getCurveAt(j);
172
                                        drawingStatus.addStatus(primitive, lineSymbolEditing, "");
173
                                        drawingStatus.addStatus(primitive, previewSymbol, "");
174
                                    }
175
                                }
176

    
177
                            } else if (geometry instanceof Curve) {
178
                                Curve curve = (Curve) geometry;
179
                                MultiCurve extendedCurve
180
                                        = trimLine(mousePosition, curve, shears);
181
                                for (int j = 0; j < extendedCurve
182
                                        .getPrimitivesNumber(); j++) {
183
                                    final Curve primitive = extendedCurve.getCurveAt(j);
184
                                    drawingStatus.addStatus(primitive, lineSymbolEditing, "");
185
                                    drawingStatus.addStatus(primitive, previewSymbol, "");
186
                                }
187
                            }
188
                        }
189
                    }
190
                }
191

    
192
                
193
            } catch (BaseException ex) {
194
                throw new DrawServiceException(ex);
195
            }
196
            
197
            return drawingStatus;
198
        }
199
        return null;
200
    }
201

    
202
    private MultiCurve trimLine(Point shearingPoint, Curve curve, Geometry shearsGeometry)
203
        throws GeometryOperationNotSupportedException,
204
        GeometryOperationException, DataException, CreateGeometryException {
205

    
206
        TrimLineOperation operation =
207
            TrimLineOperationUtils.getOperation((Primitive) curve);
208

    
209
        return operation.trimLine(curve, shearingPoint, shearsGeometry);
210
    }
211

    
212
    @Override
213
    public void stop() throws StopServiceException {
214
        values.clear();
215
        this.selectedFeatures = Collections.EMPTY_LIST;
216
    }
217

    
218
    @Override
219
    public List<EditingServiceParameter> getParameters() {
220
        List<EditingServiceParameter> parameters =
221
            new ArrayList<>();
222
        parameters.add(selectionParameter);
223
        parameters.add(geometryToTrimWithParameter);
224
        parameters.add(shearingPointParameter);
225
        return parameters;
226
    }
227

    
228
    @Override
229
    public void setValue(EditingServiceParameter parameter, Object value) throws InvalidEntryException {
230
        validateAndInsertValue(parameter, value);
231
    }
232

    
233
    @Override
234
    public void setValue(Object value) throws InvalidEntryException {
235
        EditingServiceParameter parameter = next();
236
        validateAndInsertValue(parameter, value);
237
    }
238

    
239
    private void validateAndInsertValue(
240
        final EditingServiceParameter parameter, Object value)
241
        throws InvalidEntryException {
242

    
243
        if (parameter == selectionParameter) {
244
            if (value instanceof FeatureSelection) {
245
                FeatureSelection featureSelection = (FeatureSelection) value;
246
                if (featureSelection.getSelectedCount() > 0) {
247
                    try {
248
                        featureSelection.accept((Object obj) -> {
249
                            Feature feature = (Feature) obj;
250
                            Geometry geometry
251
                                    = feature.getDefaultGeometry();
252
                            
253
                            if (!isValidGeometryToSelect(geometry)) {
254
                                throw new InvalidEntryException(null);
255
                            }
256
                        });
257
                        values.put(parameter, featureSelection);
258
                        return;
259
                    } catch (BaseException e) {
260
                        throw new InvalidEntryException(e);
261
                    }
262
                }
263
            }
264
        } else if (parameter == geometryToTrimWithParameter && value instanceof Point) {
265

    
266
            if (value instanceof Point) {
267
                Point point = (Point) value;
268

    
269
                Geometry geometry = getGeometry(point); //editingProviderServices.getGeometryOfVisibleLayers(point, featureStore, mapContext);
270
                if (geometry != null) {
271
                    try {
272
                        values.put(parameter, geometry.toLines());
273
                    } catch (GeometryException ex) {
274
                        throw new InvalidEntryException(ex);
275
                    }
276
                    return;
277
                }
278

    
279
            }
280
        } else if (parameter == shearingPointParameter && value instanceof Point) {
281

    
282
            if (value instanceof Point) {
283
                Point point = (Point) value;
284
                values.put(parameter, point);
285
                return;
286
            }
287
        }
288
        throw new InvalidEntryException(null);
289
    }
290
    
291
    private boolean isValidGeometryToSelect(Geometry geometry) {
292
        GeometryType geoType
293
                = geometry.getGeometryType();
294
        if (!geoType.isTypeOf(CURVE)
295
                && !geoType.isTypeOf(MULTICURVE)) {
296
            return false;
297
        }
298

    
299
        if (geoType.isTypeOf(CURVE)) {
300
            if (geometry instanceof Line ) {
301
                Line line = (Line) geometry;
302
                return !line.isClosed();
303
            }
304
            if (geometry instanceof Arc ) {
305
                Arc arc = (Arc) geometry;
306
                return !arc.getInitPoint().equals(arc.getEndPoint());
307
            }
308
            return false;
309
        }
310

    
311
        if (geoType.isTypeOf(MULTICURVE)) {
312
            MultiCurve multiCurve = (MultiCurve) geometry;
313
            for (Geometry geom : multiCurve) {
314
                if (!isValidGeometryToSelect(geom)) {
315
                    return false;
316
                }
317
            }
318
        }
319
        return true;
320

    
321
    }
322

    
323
    private Geometry getGeometry(Point point) {
324
        EditingProviderServices editingProviderServices = (EditingProviderServices) getProviderServices();
325
        Geometry geometry = editingProviderServices.getGeometryOfVisibleLayers(point, featureStore, mapContext);
326
        return geometry;
327
    }
328

    
329
    @Override
330
    public Geometry finish() throws FinishServiceException {
331
        return null;
332
    }
333

    
334
    @Override
335
    public void finishAndStore() throws FinishServiceException {
336

    
337
        FeatureSelection selection = (FeatureSelection) values.get(selectionParameter);
338
        Geometry shearsGeometry = (Geometry) values.get(geometryToTrimWithParameter);
339
        Point point = (Point) values.get(shearingPointParameter);
340

    
341
        if (selection != null && shearsGeometry != null && point != null) {
342
            try {
343
                for (Feature feature : selectedFeatures) {
344
                    Geometry geometry = feature.getDefaultGeometry();
345
                    EditableFeature eFeature = feature.getEditable();
346
                    if (geometry.intersects(shearsGeometry)) {
347
                        if (geometry instanceof Curve) {
348
                            Curve curveToTrim = (Curve) geometry;
349
                            MultiCurve result = trimLine(point, curveToTrim, shearsGeometry);
350
                            eFeature.setDefaultGeometry(result);
351
                            selection.update(eFeature);
352

    
353
                        } else if (geometry instanceof MultiCurve) {
354
                            int subType = geometry.getGeometryType().getSubType();
355
                            MultiCurve trimmedMultiCurve = createMultiCurve(subType);
356
                            MultiCurve multiCurveToTrim = (MultiCurve) geometry;
357

    
358
                            double minDistance = Double.POSITIVE_INFINITY;
359
                            int nearestCurveIndex = -1;
360

    
361
                            for (int i = 0; i < multiCurveToTrim .getPrimitivesNumber(); i++) {
362
                                Curve primitive = multiCurveToTrim.getCurveAt(i);
363
                                double distance = primitive.distance(point);
364
                                if (distance < minDistance) {
365
                                    nearestCurveIndex = i;
366
                                    minDistance = distance;
367
                                }
368
                            }
369
                            MultiCurve result = trimLine(
370
                                    point,
371
                                    multiCurveToTrim.getCurveAt(nearestCurveIndex),
372
                                    shearsGeometry
373
                            );
374
                            for (int i = 0; i < result.getPrimitivesNumber(); i++) {
375
                                trimmedMultiCurve.addCurve(result.getCurveAt(i));
376
                            }
377
                            for (int i = 0; i < multiCurveToTrim.getPrimitivesNumber(); i++) {
378
                                if (i != nearestCurveIndex) {
379
                                    trimmedMultiCurve.addCurve(
380
                                            multiCurveToTrim.getCurveAt(i)
381
                                    );
382
                                }
383
                            }
384
                            eFeature.setDefaultGeometry(trimmedMultiCurve);
385
                            selection.update(eFeature);
386
                        }
387
                    }
388
                }
389
            } catch (BaseException ex) {
390
                throw new FinishServiceException(ex);
391
            }
392
        }
393
    }
394

    
395
    private MultiCurve createMultiCurve(int subtype)
396
        throws FinishServiceException, CreateGeometryException {
397

    
398
        GeometryManager geoManager = GeometryLocator.getGeometryManager();
399
        MultiCurve extendedMultiCurve;
400

    
401
        extendedMultiCurve = geoManager.createMultiCurve(subtype);
402

    
403
        return extendedMultiCurve;
404
    }
405

    
406
    @Override
407
    public void start() throws StartServiceException, InvalidEntryException {
408

    
409
        this.values = new HashMap<>();
410
        this.selectedFeatures = Collections.EMPTY_LIST;
411
        if (featureStore != null) {
412
            FeatureSelection selected = null;
413
            try {
414
                selected = (FeatureSelection) featureStore.getFeatureSelection().clone();
415
            } catch (DataException e) {
416
                throw new StartServiceException(e);
417
            } catch (CloneNotSupportedException ex) {
418
                LOGGER.debug("Can't init selection",ex);
419
            }
420
            if ((selected != null) && (selected.getSelectedCount() > 0)) {
421
                values.put(selectionParameter, selected);
422
                this.selectedFeatures = this.getSelectedFeaturesCopy(selected);
423
            }
424
        }
425
    }
426

    
427
    @Override
428
    public String getName() {
429
        return TrimLineEditingProviderFactory.PROVIDER_NAME;
430
    }
431

    
432
    @Override
433
    public Object getValue(EditingServiceParameter parameter) {
434
        return values!=null?values.get(parameter):null;
435
    }
436
}