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.simplify / src / main / java / org / gvsig / vectorediting / lib / prov / simplify / SimplifyEditingProvider.java @ 493

History | View | Annotate | Download (15.5 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.simplify;
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.aggregate.MultiSurface;
42
import org.gvsig.fmap.geom.exception.CreateGeometryException;
43
import org.gvsig.fmap.geom.operation.GeometryOperationException;
44
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
45
import org.gvsig.fmap.geom.primitive.Curve;
46
import org.gvsig.fmap.geom.primitive.Line;
47
import org.gvsig.fmap.geom.primitive.Point;
48
import org.gvsig.fmap.geom.primitive.Polygon;
49
import org.gvsig.fmap.geom.primitive.Surface;
50
import org.gvsig.fmap.geom.type.GeometryType;
51
import org.gvsig.tools.dynobject.DynObject;
52
import org.gvsig.tools.exception.BaseException;
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.spi.AbstractEditingProvider;
65
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
66
import org.gvsig.vectorediting.lib.spi.EditingProvider;
67
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
68
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
69

    
70
/**
71
 * @author llmarques
72
 *
73
 */
74
public class SimplifyEditingProvider extends AbstractEditingProvider implements
75
    EditingProvider {
76

    
77
    private EditingServiceParameter selection;
78

    
79
    private EditingServiceParameter tolerance;
80

    
81
    private FeatureStore featureStore;
82

    
83
    private Map<EditingServiceParameter, Object> values;
84

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

    
97
        this.featureStore =
98
            (FeatureStore) parameters
99
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
100

    
101
        this.selection =
102
            new DefaultEditingServiceParameter("selection", "selection",
103
                TYPE.SELECTION);
104

    
105
        this.tolerance =
106
            new DefaultEditingServiceParameter("tolerance", "tolerance",
107
                TYPE.VALUE);
108
    }
109

    
110
    public EditingServiceParameter next() {
111
        if (values.get(selection) == null) {
112
            return selection;
113
        } else if (values.get(tolerance) == null) {
114
            return tolerance;
115
        }
116
        return null;
117
    }
118

    
119
    public DrawingStatus getDrawingStatus(Point mousePosition)
120
        throws DrawServiceException {
121
        return null;
122
    }
123

    
124
    public void stop() throws StopServiceException {
125
        if (values != null) {
126
            values.clear();
127
        }
128
    }
129

    
130
    public List<EditingServiceParameter> getParameters() {
131
        List<EditingServiceParameter> parameters =
132
            new ArrayList<EditingServiceParameter>();
133
        parameters.add(selection);
134
        parameters.add(tolerance);
135
        return parameters;
136
    }
137

    
138
    public void setValue(Object value) throws InvalidEntryException {
139
        EditingServiceParameter parameter = next();
140
        validateAndInsertValue(parameter, value);
141
    }
142

    
143
    private void validateAndInsertValue(EditingServiceParameter parameter,
144
        Object value) throws InvalidEntryException {
145

    
146
        if (parameter == selection) {
147

    
148
            FeatureSelection featureSelection = (FeatureSelection) value;
149

    
150
            if (featureSelection.getSelectedCount() > 0) {
151
                try {
152
                    featureSelection.accept(new Visitor() {
153

    
154
                        public void visit(Object obj)
155
                            throws VisitCanceledException, BaseException {
156

    
157
                            Feature feature = (Feature) obj;
158
                            Geometry geometry = feature.getDefaultGeometry();
159
                            GeometryType geometryType =
160
                                geometry.getGeometryType();
161

    
162
                            if (!geometryType
163
                                .isTypeOf(Geometry.TYPES.MULTISURFACE)
164
                                && !geometryType
165
                                    .isTypeOf(Geometry.TYPES.SURFACE)
166
                                && !geometryType.isTypeOf(Geometry.TYPES.CURVE)
167
                                && !geometryType
168
                                    .isTypeOf(Geometry.TYPES.MULTICURVE)) {
169

    
170
                                throw new InvalidEntryException(null);
171
                            }
172
                        }
173
                    });
174

    
175
                    values.put(selection, value);
176
                    return;
177
                } catch (BaseException e) {
178
                    throw new InvalidEntryException(e);
179
                }
180
            }
181
        } else if (parameter == tolerance) {
182
            if (value instanceof Double) {
183
                Double toleranceValue = (Double) value;
184
                if (toleranceValue >= 0) {
185
                    values.put(tolerance, value);
186
                    return;
187
                }
188
            }
189
        }
190
        throw new InvalidEntryException(null);
191
    }
192

    
193
    public Geometry finish() throws FinishServiceException {
194
        return null;
195
    }
196

    
197
    public void finishAndStore() throws FinishServiceException {
198

    
199
        if (values != null) {
200

    
201
            FeatureSelection featureSelection =
202
                (FeatureSelection) values.get(selection);
203

    
204
            final Double toleranceValue = (Double) values.get(tolerance);
205

    
206
            final EditingProviderServices editingProviderServices =
207
                (EditingProviderServices) getProviderServices();
208

    
209
            try {
210
                final int subtype =
211
                    editingProviderServices.getSubType(featureStore);
212

    
213
                featureSelection.accept(new Visitor() {
214

    
215
                    public void visit(Object obj)
216
                        throws VisitCanceledException, BaseException {
217

    
218
                        Feature feature = (Feature) obj;
219
                        Geometry geometry = feature.getDefaultGeometry();
220
                        GeometryType geoType = geometry.getGeometryType();
221

    
222
                        if (geoType.isTypeOf(CURVE)
223
                            || (geoType.isTypeOf(SURFACE))) {
224

    
225
                            if (geoType.isTypeOf(CURVE)) {
226

    
227
                                Curve curveToSimplify = (Curve) geometry;
228
                                curveToSimplify =
229
                                    simplifyLine(curveToSimplify,
230
                                        toleranceValue);
231
                                geometry = curveToSimplify;
232

    
233
                            } else {
234

    
235
                                Surface surfaceToSimplify = (Surface) geometry;
236
                                surfaceToSimplify =
237
                                    simplifySurface(surfaceToSimplify,
238
                                        toleranceValue);
239
                                geometry = surfaceToSimplify;
240

    
241
                            }
242

    
243
                            EditableFeature eFeature = feature.getEditable();
244
                            eFeature.setDefaultGeometry(geometry);
245
                            editingProviderServices
246
                                .updateFeatureInFeatureStore(eFeature,
247
                                    featureStore);
248

    
249
                        } else if (geoType.isTypeOf(MULTICURVE)
250
                            || geoType.isTypeOf(MULTISURFACE)) {
251

    
252
                            if (geoType.isTypeOf(MULTICURVE)) {
253

    
254
                                MultiCurve multiCurveToSimplify =
255
                                    (MultiCurve) geometry;
256

    
257
                                MultiCurve multiCurveSimplified =
258
                                    GeometryLocator.getGeometryManager()
259
                                        .createMultiCurve(subtype);
260

    
261
                                for (int i = 0; i < multiCurveToSimplify
262
                                    .getPrimitivesNumber(); i++) {
263

    
264
                                    Curve curveToSimplify =
265
                                        (Curve) multiCurveToSimplify
266
                                            .getPrimitiveAt(i);
267

    
268
                                    curveToSimplify =
269
                                        simplifyLine(curveToSimplify,
270
                                            toleranceValue);
271

    
272
                                    multiCurveSimplified
273
                                        .addCurve(curveToSimplify);
274

    
275
                                    geometry = multiCurveSimplified;
276
                                }
277

    
278
                            } else {
279

    
280
                                MultiSurface multiSurfaceToSimplify =
281
                                    (MultiSurface) geometry;
282

    
283
                                MultiSurface multiSurfaceSimplified =
284
                                    GeometryLocator.getGeometryManager()
285
                                        .createMultiSurface(subtype);
286

    
287
                                for (int i = 0; i < multiSurfaceToSimplify
288
                                    .getPrimitivesNumber(); i++) {
289

    
290
                                    Surface surfaceToSimplify =
291
                                        (Surface) multiSurfaceToSimplify
292
                                            .getPrimitiveAt(i);
293

    
294
                                    surfaceToSimplify =
295
                                        simplifySurface(surfaceToSimplify,
296
                                            toleranceValue);
297

    
298
                                    multiSurfaceSimplified
299
                                        .addSurface(surfaceToSimplify);
300

    
301
                                    geometry = multiSurfaceSimplified;
302
                                }
303
                            }
304

    
305
                            EditableFeature eFeature = feature.getEditable();
306
                            eFeature.setDefaultGeometry(geometry);
307
                            editingProviderServices
308
                                .updateFeatureInFeatureStore(eFeature,
309
                                    featureStore);
310
                        }
311
                    }
312
                });
313

    
314
                featureStore.getFeatureSelection().deselectAll();
315

    
316
            } catch (BaseException e) {
317
                throw new FinishServiceException(e);
318
            }
319
        }
320
    }
321

    
322
    private Surface simplifySurface(Surface surfaceToSimplify,
323
        Double toleranceValue) throws GeometryException, DataException,
324
        GeometryOperationNotSupportedException, GeometryOperationException {
325

    
326
        EditingProviderServices editingProviderServices =
327
            (EditingProviderServices) getProviderServices();
328

    
329
        int subtype = editingProviderServices.getSubType(featureStore);
330

    
331
        Line lineToSimplify =
332
            GeometryLocator.getGeometryManager().createLine(subtype);
333

    
334
        for (int i = 0; i < surfaceToSimplify.getNumVertices(); i++) {
335
            lineToSimplify.addVertex(surfaceToSimplify.getVertex(i));
336
        }
337

    
338
        Line simplifiedLine = simplifyLine(lineToSimplify, toleranceValue);
339
        Polygon simplifiedPolygon =
340
            GeometryLocator.getGeometryManager().createPolygon(subtype);
341

    
342
        for (int i = 0; i < simplifiedLine.getNumVertices(); i++) {
343
            simplifiedPolygon.addVertex(simplifiedLine.getVertex(i));
344
        }
345

    
346
        // Close polygon
347
        simplifiedPolygon.addVertex(simplifiedLine.getVertex(0));
348

    
349
        return simplifiedPolygon;
350
    }
351

    
352
    private Line simplifyLine(Curve curveToSimplify, Double toleranceValue)
353
        throws DataException, CreateGeometryException,
354
        GeometryOperationNotSupportedException, GeometryOperationException {
355

    
356
        EditingProviderServices editingProviderServices =
357
            (EditingProviderServices) getProviderServices();
358

    
359
        int subtype = editingProviderServices.getSubType(featureStore);
360

    
361
        Line simplifiedLine =
362
            (Line) GeometryLocator.getGeometryManager().createLine(subtype);
363

    
364
        // Add first vertex
365
        simplifiedLine.addVertex(curveToSimplify.getVertex(0));
366

    
367
        // Iterate over vertices
368
        for (int i = 0; i < curveToSimplify.getNumVertices() - 2; i++) {
369

    
370
            Point vertex = curveToSimplify.getVertex(i);
371
            Point nextVertex = curveToSimplify.getVertex(i + 1);
372
            Point nextNextVertex = curveToSimplify.getVertex(i + 2);
373

    
374
            // Creates line between i vertex and i+2 vertex
375
            Line tmpLine =
376
                editingProviderServices.createLine(vertex, nextNextVertex,
377
                    subtype);
378

    
379
            // If distance between line and i+1 vertex is bigger than tolerance
380
            // add point to simplifiedLine, else skip vertex
381
            if (tmpLine.distance(nextVertex) > toleranceValue) {
382
                simplifiedLine.addVertex(nextVertex);
383
            } else {
384
                i++;
385
            }
386
        }
387

    
388
        // Add last vertex
389
        simplifiedLine.addVertex(curveToSimplify.getVertex(curveToSimplify
390
            .getNumVertices() - 1));
391

    
392
        return simplifiedLine;
393
    }
394

    
395
    public void start() throws StartServiceException, InvalidEntryException {
396
        values = new HashMap<EditingServiceParameter, Object>();
397

    
398
        FeatureSelection selected = null;
399
        if (featureStore != null) {
400
            try {
401
                selected = featureStore.getFeatureSelection();
402
            } catch (DataException e) {
403
                throw new StartServiceException(e);
404
            }
405
            if (selected.getSelectedCount() > 0) {
406
                try {
407
                    setValue(selected);
408
                } catch (InvalidEntryException e) {
409
                    throw new InvalidEntryException(e);
410
                }
411
            }
412
        }
413
    }
414

    
415
    public String getName() {
416
        return SimplifyEditingProviderFactory.PROVIDER_NAME;
417
    }
418

    
419
}