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.split / src / main / java / org / gvsig / vectorediting / lib / prov / split / SplitEditingProvider.java @ 2786

History | View | Annotate | Download (15.4 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.split;
26

    
27
import java.util.ArrayList;
28
import java.util.HashMap;
29
import java.util.List;
30
import java.util.Map;
31
import org.gvsig.fmap.dal.exception.DataException;
32
import org.gvsig.fmap.dal.feature.EditableFeature;
33
import org.gvsig.fmap.dal.feature.Feature;
34
import org.gvsig.fmap.dal.feature.FeatureSelection;
35
import org.gvsig.fmap.dal.feature.FeatureStore;
36
import org.gvsig.fmap.geom.Geometry;
37
import org.gvsig.fmap.geom.Geometry.TYPES;
38
import org.gvsig.fmap.geom.GeometryException;
39
import org.gvsig.fmap.geom.GeometryLocator;
40
import org.gvsig.fmap.geom.GeometryManager;
41
import org.gvsig.fmap.geom.aggregate.Aggregate;
42
import org.gvsig.fmap.geom.aggregate.MultiCurve;
43
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
44
import org.gvsig.fmap.geom.complex.Complex;
45
import org.gvsig.fmap.geom.operation.GeometryOperationException;
46
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
47
import org.gvsig.fmap.geom.primitive.Curve;
48
import org.gvsig.fmap.geom.primitive.Point;
49
import org.gvsig.fmap.geom.primitive.Primitive;
50
import org.gvsig.fmap.geom.type.GeometryType;
51
import org.gvsig.tools.ToolsLocator;
52
import org.gvsig.tools.dispose.DisposableIterator;
53
import org.gvsig.tools.dispose.DisposeUtils;
54
import org.gvsig.tools.dynobject.DynObject;
55
import org.gvsig.tools.exception.BaseException;
56
import org.gvsig.tools.service.spi.ProviderServices;
57
import org.gvsig.vectorediting.lib.api.DrawingStatus;
58
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
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.api.exceptions.VectorEditingException;
65
import org.gvsig.vectorediting.lib.prov.split.operation.SplitOperation;
66
import org.gvsig.vectorediting.lib.prov.split.operation.SplitOperationUtils;
67
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
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.EditingProviderServices;
72

    
73
/**
74
 * @author llmarques
75
 *
76
 */
77
public class SplitEditingProvider extends AbstractEditingProvider implements
78
    EditingProvider {
79

    
80
    private final EditingServiceParameter selection;
81

    
82
    private final EditingServiceParameter splitGeometry;
83

    
84
    private final FeatureStore featureStore;
85

    
86
    private Map<EditingServiceParameter, Object> values;
87

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

    
99
        this.featureStore =
100
            (FeatureStore) parameters
101
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
102

    
103
        this.selection =
104
            new DefaultEditingServiceParameter("selection", "selection",
105
                EditingServiceParameter.TYPE.SELECTION);
106

    
107
        this.splitGeometry =
108
            new DefaultEditingServiceParameter("draw_geometry_to_split",
109
                "draw_geometry_to_split", Geometry.TYPES.CURVE,
110
                EditingServiceParameter.TYPE.GEOMETRY);
111
    }
112

    
113
    @Override
114
    public EditingServiceParameter next() {
115
        if (values.get(selection) == null) {
116
            return selection;
117
        } else if (values.get(splitGeometry) == null) {
118
            return splitGeometry;
119
        }
120
        return null;
121
    }
122

    
123
    @Override
124
    public DrawingStatus getDrawingStatus(Point mousePosition)
125
        throws DrawServiceException {
126
        return null;
127
    }
128

    
129
    @Override
130
    public void stop() throws StopServiceException {
131
        if (values != null) {
132
            values.clear();
133
        }
134
    }
135

    
136
    @Override
137
    public List<EditingServiceParameter> getParameters() {
138
        List<EditingServiceParameter> parameters =
139
            new ArrayList<>();
140
        parameters.add(selection);
141
        parameters.add(splitGeometry);
142
        return parameters;
143
    }
144

    
145
    @Override
146
    public void setValue(EditingServiceParameter parameter, Object value) throws InvalidEntryException {
147
        validateAndInsertValue(parameter, value);
148
    }
149

    
150
    @Override
151
    public void setValue(Object value) throws InvalidEntryException {
152
        EditingServiceParameter parameter = next();
153
        validateAndInsertValue(parameter, value);
154
    }
155

    
156
    private void validateAndInsertValue(EditingServiceParameter parameter,
157
        Object value) throws InvalidEntryException {
158

    
159
        if (values != null && value != null) {
160

    
161
            if (value instanceof FeatureSelection) {
162

    
163
                FeatureSelection featureSelection = (FeatureSelection) value;
164

    
165
                try {
166
                    featureSelection.accept((Object obj) -> {
167
                        Feature feature = (Feature) obj;
168
                        Geometry geometry = feature.getDefaultGeometry();
169
                        GeometryType geoType = geometry.getGeometryType();
170
                        
171
                        if (geoType.isTypeOf(POINT)
172
                                || geoType.isTypeOf(MULTIPOINT)) {
173
                            throw new InvalidEntryException(null);
174
                        }
175
                    });
176

    
177
                    values.put(selection, value);
178
                    return;
179
                } catch (BaseException e) {
180
                    throw new InvalidEntryException(e);
181
                }
182

    
183
            } else if (value instanceof Geometry) {
184

    
185
                Geometry geometry = (Geometry) value;
186

    
187
                if (geometry instanceof MultiCurve) {
188
                    MultiCurve multiCurve = (MultiCurve) geometry;
189
                    for (int i = 0; i < multiCurve.getPrimitivesNumber(); i++) {
190
                        if (isValid((Curve) multiCurve.getPrimitiveAt(i))) {
191
                            values.put(splitGeometry, geometry);
192
                            return;
193
                        }
194
                    }
195

    
196
                } else if (geometry instanceof Curve) {
197
                    if (isValid((Curve) geometry)) {
198
                        values.put(splitGeometry, geometry);
199
                        return;
200
                    }
201
                }
202
            }
203
        }
204
        throw new InvalidEntryException(null);
205
    }
206

    
207
    private boolean isValid(final Curve curve) {
208
        FeatureSelection featureSelection =
209
            (FeatureSelection) values.get(selection);
210

    
211
        try {
212
            featureSelection.accept((Object obj) -> {
213
                Feature feature = (Feature) obj;
214
                Geometry geometry = feature.getDefaultGeometry();
215
                
216
                Geometry intersection = geometry.intersection(curve);
217

    
218
                if (intersection instanceof Complex) {
219
                    intersection = ((Complex) intersection).createAggregate(
220
                            Geometry.TYPES.MULTIPOLYGON,
221
                            (Geometry t) -> t.getGeometryType().getType() == Geometry.TYPES.MULTIPOLYGON || t.getGeometryType().getType() == Geometry.TYPES.POLYGON
222
                    );
223
                    if(  ((Aggregate) intersection).getPrimitivesNumber() == 0){
224
                        throw new VectorEditingException();
225
                    }
226
                } else {
227
                    if (intersection == null
228
                            || (!intersection.getGeometryType().isTypeOf(POINT)
229
                            && !intersection.getGeometryType().isTypeOf(MULTIPOINT)
230
                            && !intersection.getGeometryType().isTypeOf(CURVE)
231
                            && !intersection.getGeometryType().isTypeOf(MULTICURVE))) {
232
                        throw new VectorEditingException();
233
                    }
234
                }
235
            });
236
            return true;
237
        } catch (BaseException e) {
238
            return false;
239
        }
240
    }
241

    
242
    @Override
243
    public Geometry finish() throws FinishServiceException {
244
        return null;
245
    }
246

    
247
    @Override
248
    public void finishAndStore() throws FinishServiceException {
249

    
250
        if (values != null) {
251

    
252
            EditingProviderServices editingProviderServices =
253
                (EditingProviderServices) getProviderServices();
254

    
255
            FeatureSelection featureSelection =
256
                (FeatureSelection) values.get(selection);
257
            Geometry splitter = (Geometry) values.get(splitGeometry);
258
            ToolsLocator.getDisposableManager().bind(featureSelection);
259

    
260
            DisposableIterator it = null;
261
            try {
262
                it = featureSelection.fastIterator();
263

    
264
                while (it.hasNext()) {
265
                    Feature feature = (Feature) it.next();
266
                    Geometry geometryToBeSplitted =
267
                        feature.getDefaultGeometry();
268
                    GeometryType geoType =
269
                        geometryToBeSplitted.getGeometryType();
270

    
271
                    if (geoType.isTypeOf(TYPES.SURFACE)
272
                        || geoType.isTypeOf(TYPES.CURVE)) {
273

    
274
                        MultiPrimitive splittedGeometries =
275
                            (MultiPrimitive) split(
276
                                (Primitive) geometryToBeSplitted, splitter);
277

    
278
                        for (int j = 0; j < splittedGeometries
279
                            .getPrimitivesNumber(); j++) {
280
                            copyAlfanumericDataAndInsert(
281
                                splittedGeometries.getPrimitiveAt(j), feature);
282
                        }
283

    
284
                    } else if (geoType.isTypeOf(TYPES.MULTISURFACE)
285
                        || geoType.isTypeOf(TYPES.MULTICURVE)) {
286

    
287
                        MultiPrimitive multiPrimitive =
288
                            (MultiPrimitive) geometryToBeSplitted;
289

    
290
                        // Multigeometry composed by no splitted geometries.
291
                        GeometryManager geoManager = GeometryLocator.getGeometryManager();
292
                        MultiPrimitive multiNoSplitted;
293
                        if(geoType.isTypeOf(TYPES.MULTISURFACE)){
294
                            multiNoSplitted =
295
                                geoManager.createMultiSurface(editingProviderServices
296
                                    .getSubType(featureStore));
297
                        } else {
298
                            multiNoSplitted =
299
                                geoManager.createMultiCurve(editingProviderServices
300
                                    .getSubType(featureStore));
301
                        }
302

    
303
                        for (int i = 0; i < multiPrimitive
304
                            .getPrimitivesNumber(); i++) {
305

    
306
                            Geometry geoSplitted =
307
                                split(multiPrimitive.getPrimitiveAt(i),
308
                                    splitter);
309

    
310
                            if (geoSplitted instanceof MultiPrimitive) {
311
                                // If the result of split is a multiprimitive,
312
                                // it has splitted
313
                                MultiPrimitive multiSplitted = (MultiPrimitive) geoSplitted;
314
                                // Splitted geometries should be saved as
315
                                // primitives
316
                                for (int j = 0; j < multiSplitted
317
                                    .getPrimitivesNumber(); j++) {
318
                                    copyAlfanumericDataAndInsert(
319
                                        multiSplitted.getPrimitiveAt(j),
320
                                        feature);
321
                                }
322
                            } else {
323
                                // If the result of split is a primitive, it has
324
                                // not splitted. Add it to mulriNoSplitted to save it later.
325
                                multiNoSplitted
326
                                    .addPrimitive((Primitive) geoSplitted);
327
                            }
328
                        }
329

    
330
                        if(multiNoSplitted.getPrimitivesNumber() > 0){
331
                            // Not splitted geometries should be saved as multigeometry
332
                            copyAlfanumericDataAndInsert(multiNoSplitted,
333
                                feature);
334
                        }
335
                    }
336

    
337
                    editingProviderServices.deleteFeatureFromFeatureStore(
338
                        feature, featureStore);
339
                }
340

    
341
                featureSelection.deselectAll();
342
                featureStore.getFeatureSelection().deselectAll();
343

    
344

    
345
            } catch (BaseException e) {
346
                throw new FinishServiceException(e);
347
            } finally {
348
                DisposeUtils.disposeQuietly(it);
349
                DisposeUtils.disposeQuietly(featureSelection);
350
            }
351
        }
352
    }
353

    
354
    private void copyAlfanumericDataAndInsert(Geometry geometry, Feature feature)
355
        throws DataException {
356
        EditingProviderServices editingProviderServices =
357
            (EditingProviderServices) getProviderServices();
358

    
359
        EditableFeature eFeature =
360
            editingProviderServices.getFeatureCopyWithoutUniqueIndex(featureStore,
361
                feature);
362
        eFeature.setDefaultGeometry(geometry);
363
        editingProviderServices.insertFeatureIntoFeatureStore(eFeature,
364
            featureStore);
365
    }
366

    
367
    private Geometry split(Primitive geometry, Geometry splitter)
368
        throws GeometryOperationNotSupportedException,
369
        GeometryOperationException, GeometryException {
370
        SplitOperation operation = SplitOperationUtils.getOperation(geometry);
371

    
372
        if (operation != null) {
373
            return operation.split(geometry, splitter);
374
        }
375
        return null;
376
    }
377

    
378
    @Override
379
    public void start() throws StartServiceException, InvalidEntryException {
380
        values = new HashMap<>();
381
        FeatureSelection selected = null;
382
        if (featureStore != null) {
383
            try {
384
                selected = featureStore.getFeatureSelection();
385
            } catch (DataException e) {
386
                throw new StartServiceException(e);
387
            }
388
            if (selected.getSelectedCount() > 0) {
389
                setValue(selected);
390
            }
391
        }
392
    }
393

    
394
    @Override
395
    public String getName() {
396
        return SplitEditingProviderFactory.PROVIDER_NAME;
397
    }
398

    
399
    @Override
400
    public Object getValue(EditingServiceParameter parameter) {
401
        return values!=null?values.get(parameter):null;
402
    }
403
}