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

History | View | Annotate | Download (18.1 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.HashMap;
29
import java.util.List;
30
import java.util.Map;
31
import java.util.logging.Level;
32
import java.util.logging.Logger;
33
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.feature.EditableFeature;
35
import org.gvsig.fmap.dal.feature.Feature;
36
import org.gvsig.fmap.dal.feature.FeatureSelection;
37
import org.gvsig.fmap.dal.feature.FeatureStore;
38
import org.gvsig.fmap.geom.Geometry;
39
import static org.gvsig.fmap.geom.Geometry.TYPES.CURVE;
40
import static org.gvsig.fmap.geom.Geometry.TYPES.MULTICURVE;
41
import org.gvsig.fmap.geom.GeometryException;
42
import org.gvsig.fmap.geom.GeometryLocator;
43
import org.gvsig.fmap.geom.GeometryManager;
44
import org.gvsig.fmap.geom.aggregate.MultiCurve;
45
import org.gvsig.fmap.geom.exception.CreateGeometryException;
46
import org.gvsig.fmap.geom.operation.GeometryOperationException;
47
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
48
import org.gvsig.fmap.geom.primitive.Arc;
49
import org.gvsig.fmap.geom.primitive.Curve;
50
import org.gvsig.fmap.geom.primitive.Line;
51
import org.gvsig.fmap.geom.primitive.Point;
52
import org.gvsig.fmap.geom.primitive.Primitive;
53
import org.gvsig.fmap.geom.type.GeometryType;
54
import org.gvsig.fmap.mapcontext.MapContext;
55
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
56
import org.gvsig.tools.dispose.DisposableIterator;
57
import org.gvsig.tools.dynobject.DynObject;
58
import org.gvsig.tools.exception.BaseException;
59
import org.gvsig.tools.service.spi.ProviderServices;
60
import org.gvsig.tools.visitor.VisitCanceledException;
61
import org.gvsig.tools.visitor.Visitor;
62
import org.gvsig.vectorediting.lib.api.DrawingStatus;
63
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
64
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
65
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
66
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
67
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
68
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
69
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
70
import org.gvsig.vectorediting.lib.prov.trimline.operation.TrimLineOperation;
71
import org.gvsig.vectorediting.lib.prov.trimline.operation.TrimLineOperationUtils;
72
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
73
import org.gvsig.vectorediting.lib.spi.DefaultDrawingStatus;
74
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
75
import org.gvsig.vectorediting.lib.spi.EditingProvider;
76
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
77
import org.gvsig.vectorediting.lib.spi.EditingProviderLocator;
78
import org.gvsig.vectorediting.lib.spi.EditingProviderManager;
79
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
80

    
81
/**
82
 * @author llmarques
83
 *
84
 */
85
public class TrimLineEditingProvider extends AbstractEditingProvider implements
86
    EditingProvider {
87

    
88
    private final int TOLERANCE_PIXELS = 3;
89

    
90
    private final EditingServiceParameter selectionParameter;
91

    
92
    private final EditingServiceParameter geometryToTrimWithParameter;
93

    
94
    private final EditingServiceParameter shearingPointParameter;
95
    
96
    protected Map<EditingServiceParameter, Object> values;
97

    
98
    private final FeatureStore featureStore;
99

    
100
    private final MapContext mapContext;
101

    
102
    /**
103
     * Default constructor.
104
     *
105
     * @param services
106
     *            available services for this provider
107
     * @param parameters
108
     *            of this provider
109
     */
110
    public TrimLineEditingProvider(ProviderServices services,
111
        DynObject parameters) {
112
        super(services);
113

    
114
        this.featureStore =
115
            (FeatureStore) parameters
116
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
117

    
118
        this.mapContext =
119
            (MapContext) parameters
120
                .getDynValue(EditingProviderFactory.MAPCONTEXT_FIELD);
121

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

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

    
134
    }
135

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

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

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

    
161
            try {
162
                
163
                DisposableIterator selectionIterator = null;
164
                selectionIterator = selection.fastIterator();
165
                while (selectionIterator.hasNext()) {
166
                    Feature feature = (Feature) selectionIterator.next();
167
                    if (feature != null) {
168
                        Geometry geometry = feature.getDefaultGeometry();
169
                        if(geometry != null && geometry.intersects(shears)) {
170
                            if (geometry instanceof MultiCurve) {
171
                                MultiCurve multiCurve = (MultiCurve) geometry;
172

    
173
                                for (int i = 0; i < multiCurve
174
                                        .getPrimitivesNumber(); i++) {
175

    
176
                                    Curve curve = multiCurve.getCurveAt(i);
177
                                    MultiCurve trimmedCurve
178
                                            = trimLine(mousePosition, curve, shears);
179
                                    for (int j = 0; j < trimmedCurve
180
                                            .getPrimitivesNumber(); j++) {
181
                                        drawingStatus.addStatus(trimmedCurve.getCurveAt(j),
182
                                                lineSymbolEditing, "");
183
                                    }
184
                                }
185

    
186
                            } else if (geometry instanceof Curve) {
187
                                Curve curve = (Curve) geometry;
188
                                MultiCurve extendedCurve
189
                                        = trimLine(mousePosition, curve, shears);
190
                                for (int j = 0; j < extendedCurve
191
                                        .getPrimitivesNumber(); j++) {
192
                                    drawingStatus.addStatus(
193
                                            extendedCurve.getCurveAt(j),
194
                                            lineSymbolEditing, "");
195
                                }
196
                            }
197
                        }
198
                    }
199
                }
200

    
201
                
202
            } catch (BaseException ex) {
203
                throw new DrawServiceException(ex);
204
            }
205
            
206
            return drawingStatus;
207
        }
208
        return null;
209
    }
210

    
211
    private MultiCurve trimLine(Point shearingPoint, Curve curve, Geometry shearsGeometry)
212
        throws GeometryOperationNotSupportedException,
213
        GeometryOperationException, DataException, CreateGeometryException {
214

    
215
        TrimLineOperation operation =
216
            TrimLineOperationUtils.getOperation((Primitive) curve);
217

    
218
        return operation.trimLine(curve, shearingPoint, shearsGeometry);
219
    }
220

    
221
    @Override
222
    public void stop() throws StopServiceException {
223
        values.clear();
224
    }
225

    
226
    @Override
227
    public List<EditingServiceParameter> getParameters() {
228
        List<EditingServiceParameter> parameters =
229
            new ArrayList<>();
230
        parameters.add(selectionParameter);
231
        parameters.add(geometryToTrimWithParameter);
232
        parameters.add(shearingPointParameter);
233
        return parameters;
234
    }
235

    
236
    @Override
237
    public void setValue(EditingServiceParameter parameter, Object value) throws InvalidEntryException {
238
        validateAndInsertValue(parameter, value);
239
    }
240

    
241
    @Override
242
    public void setValue(Object value) throws InvalidEntryException {
243
        EditingServiceParameter parameter = next();
244
        validateAndInsertValue(parameter, value);
245
    }
246

    
247
    private void validateAndInsertValue(
248
        final EditingServiceParameter parameter, Object value)
249
        throws InvalidEntryException {
250

    
251
        if (parameter == selectionParameter) {
252
            if (value instanceof FeatureSelection) {
253
                FeatureSelection featureSelection = (FeatureSelection) value;
254
                if (featureSelection.getSelectedCount() > 0) {
255
                    try {
256
                        featureSelection.accept(new Visitor() {
257

    
258
                            public void visit(Object obj)
259
                                    throws VisitCanceledException, BaseException {
260
                                Feature feature = (Feature) obj;
261
                                Geometry geometry
262
                                        = feature.getDefaultGeometry();
263

    
264
                                if (!isValidGeometryToSelect(geometry)) {
265
                                    throw new InvalidEntryException(null);
266
                                }
267
                            }
268
                        });
269
                        values.put(parameter, featureSelection);
270
                        return;
271
                    } catch (BaseException e) {
272
                        throw new InvalidEntryException(e);
273
                    }
274
                }
275
            }
276
        } else if (parameter == geometryToTrimWithParameter && value instanceof Point) {
277

    
278
            if (value instanceof Point) {
279
                Point point = (Point) value;
280

    
281
                Geometry geometry = getGeometry(point); //editingProviderServices.getGeometryOfVisibleLayers(point, featureStore, mapContext);
282
                if (geometry != null) {
283
                    try {
284
                        values.put(parameter, geometry.toLines());
285
                    } catch (GeometryException ex) {
286
                        throw new InvalidEntryException(ex);
287
                    }
288
                    return;
289
                }
290

    
291
            }
292
        } else if (parameter == shearingPointParameter && value instanceof Point) {
293

    
294
            if (value instanceof Point) {
295
                Point point = (Point) value;
296
                values.put(parameter, point);
297
                return;
298
            }
299
        }
300
        throw new InvalidEntryException(null);
301
    }
302
    
303
    private boolean isValidGeometryToSelect(Geometry geometry) {
304
        GeometryType geoType
305
                = geometry.getGeometryType();
306
        if (!geoType.isTypeOf(CURVE)
307
                && !geoType.isTypeOf(MULTICURVE)) {
308
            return false;
309
        }
310

    
311
        if (geoType.isTypeOf(CURVE)) {
312
            if (geometry instanceof Line ) {
313
                Line line = (Line) geometry;
314
                return !line.isClosed();
315
            }
316
            if (geometry instanceof Arc ) {
317
                Arc arc = (Arc) geometry;
318
                return !arc.getInitPoint().equals(arc.getEndPoint());
319
            }
320
            return false;
321
        }
322

    
323
        if (geoType.isTypeOf(MULTICURVE)) {
324
            MultiCurve multiCurve = (MultiCurve) geometry;
325
            for (Geometry geom : multiCurve) {
326
                if (!isValidGeometryToSelect(geom)) {
327
                    return false;
328
                }
329
            }
330
        }
331
        return true;
332

    
333
    }
334

    
335
    private Geometry getGeometry(Point point) {
336
        EditingProviderServices editingProviderServices = (EditingProviderServices) getProviderServices();
337
        Geometry geometry = editingProviderServices.getGeometryOfVisibleLayers(point, featureStore, mapContext);
338
        return geometry;
339
    }
340

    
341
    @Override
342
    public Geometry finish() throws FinishServiceException {
343
        return null;
344
    }
345

    
346
    @Override
347
    public void finishAndStore() throws FinishServiceException {
348
        
349
        FeatureSelection selection = (FeatureSelection) values.get(selectionParameter);
350
        Geometry shearsGeometry = (Geometry) values.get(geometryToTrimWithParameter);
351
        Point point = (Point) values.get(shearingPointParameter);
352

    
353
        if (selection != null && shearsGeometry != null && point != null) {
354
            try {
355
                
356
                
357
                DisposableIterator selectionIterator = null;
358
                selectionIterator = selection.fastIterator();
359
                while (selectionIterator.hasNext()) {
360
                    Feature feature = (Feature) selectionIterator.next();
361

    
362
                    Geometry geometry = feature.getDefaultGeometry();
363
                    
364
                    EditableFeature eFeature = feature.getEditable();
365

    
366
                    if(geometry.intersects(shearsGeometry)){
367
                        if (geometry instanceof Curve) {
368

    
369
                            Curve curveToTrim = (Curve) geometry;
370
                            MultiCurve result =
371
                                trimLine(point, curveToTrim, shearsGeometry);
372
                            eFeature.setDefaultGeometry(result);
373
                            selection.update(eFeature);
374

    
375
                        } else if (geometry instanceof MultiCurve) {
376

    
377
                            int subType =
378
                                geometry.getGeometryType().getSubType();
379
                            MultiCurve trimmedMultiCurve =
380
                                createMultiCurve(subType);
381
                            MultiCurve multiCurveToTrim = (MultiCurve) geometry;
382

    
383
                            double minDistance = Double.POSITIVE_INFINITY;
384
                            int nearestCurveIndex = -1;
385

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

    
389
                                Curve primitive =
390
                                    multiCurveToTrim.getCurveAt(i);
391

    
392
                                double distance =
393
                                    primitive.distance(point);
394
                                if (distance < minDistance) {
395
                                    nearestCurveIndex = i;
396
                                    minDistance = distance;
397
                                }
398
                            }
399

    
400
                            MultiCurve result =
401
                                trimLine(point, multiCurveToTrim
402
                                    .getCurveAt(nearestCurveIndex), shearsGeometry);
403

    
404
                            for (int i = 0; i < result.getPrimitivesNumber(); i++) {
405
                                trimmedMultiCurve.addCurve(result.getCurveAt(i));
406
                            }
407

    
408
                            for (int i = 0; i < multiCurveToTrim
409
                                .getPrimitivesNumber(); i++) {
410
                                if (i != nearestCurveIndex) {
411
                                    trimmedMultiCurve.addCurve(multiCurveToTrim
412
                                        .getCurveAt(i));
413
                                }
414
                            }
415

    
416
                            eFeature.setDefaultGeometry(trimmedMultiCurve);
417
                            selection.update(eFeature);
418

    
419
                        }
420
                    }
421
                }  
422
            } catch (BaseException ex) {
423
                throw new FinishServiceException(ex);
424
            }
425
        }
426
    }
427

    
428
    private MultiCurve createMultiCurve(int subtype)
429
        throws FinishServiceException, CreateGeometryException {
430

    
431
        GeometryManager geoManager = GeometryLocator.getGeometryManager();
432
        MultiCurve extendedMultiCurve;
433

    
434
        extendedMultiCurve = geoManager.createMultiCurve(subtype);
435

    
436
        return extendedMultiCurve;
437
    }
438

    
439
    @Override
440
    public void start() throws StartServiceException, InvalidEntryException {
441

    
442
        this.values = new HashMap<>();
443
        FeatureSelection selected = null;
444
        if (featureStore != null && values.get(selectionParameter) == null) {
445
            try {
446
                selected = featureStore.getFeatureSelection();
447
            } catch (DataException e) {
448
                throw new StartServiceException(e);
449
            }
450
            if (selected.getSelectedCount() > 0) {
451
                try {
452
                    setValue(selected);
453
                } catch (InvalidEntryException e) {
454
                    throw new InvalidEntryException(e);
455
                }
456
            }
457
        }
458

    
459
    }
460

    
461
    @Override
462
    public String getName() {
463
        return TrimLineEditingProviderFactory.PROVIDER_NAME;
464
    }
465

    
466
    @Override
467
    public Object getValue(EditingServiceParameter parameter) {
468
        return values!=null?values.get(parameter):null;
469
    }
470
}