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.smoothline / src / main / java / org / gvsig / vectorediting / lib / prov / smoothline / SmoothLineEditingProvider.java @ 2616

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
package org.gvsig.vectorediting.lib.prov.smoothline;
25

    
26
import java.util.ArrayList;
27
import java.util.HashMap;
28
import java.util.LinkedHashMap;
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.GeometryLocator;
38
import org.gvsig.fmap.geom.GeometryManager;
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.Arc;
44
import org.gvsig.fmap.geom.primitive.Curve;
45
import org.gvsig.fmap.geom.primitive.Line;
46
import org.gvsig.fmap.geom.primitive.Point;
47
import org.gvsig.fmap.geom.primitive.Spline;
48
import org.gvsig.fmap.geom.type.GeometryType;
49
import org.gvsig.tools.ToolsLocator;
50
import org.gvsig.tools.dynobject.DynObject;
51
import org.gvsig.tools.exception.BaseException;
52
import org.gvsig.tools.i18n.I18nManager;
53
import org.gvsig.tools.service.spi.ProviderServices;
54
import org.gvsig.vectorediting.lib.api.DrawingStatus;
55
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
56
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
57
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
58
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
59
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
60
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
61
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
62
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
63
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
64
import org.gvsig.vectorediting.lib.spi.EditingProvider;
65
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
66
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
67

    
68
/**
69
 * @author fdiaz
70
 *
71
 */
72
public class SmoothLineEditingProvider extends AbstractEditingProvider implements
73
    EditingProvider {
74

    
75
    private final EditingServiceParameter selection;
76

    
77
    private final EditingServiceParameter steps;
78

    
79
    private final EditingServiceParameter algorithm;
80

    
81
    private final FeatureStore featureStore;
82

    
83
    private Map<EditingServiceParameter, Object> values;
84

    
85
    protected Map<String, String> options;
86

    
87
    public static final String    NATURAL_CUBIC_SPLINES = "natural_cubic_splines";
88
    public static final String    BEZIER_CURVES         = "bezier_curves";
89
    public static final String    BSPLINES              = "b_splines";
90

    
91
    /**
92
     * Default constructor.
93
     *
94
     * @param services
95
     *            available services for this provider
96
     * @param parameters
97
     *            of this provider
98
     */
99
    public SmoothLineEditingProvider(DynObject parameters,
100
        ProviderServices services) {
101
        super(services);
102

    
103
        this.featureStore =
104
            (FeatureStore) parameters
105
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
106

    
107
        this.selection =
108
            new DefaultEditingServiceParameter("selection", "selection",
109
                TYPE.SELECTION);
110

    
111
        this.steps =
112
            new DefaultEditingServiceParameter("steps", "intermediate_steps_1_9",
113
                TYPE.VALUE);
114

    
115
        I18nManager i18nManager = ToolsLocator.getI18nManager();
116

    
117
        options = new LinkedHashMap<>();
118
        options.put(i18nManager.getTranslation("key_natural_cubic_splines"), NATURAL_CUBIC_SPLINES);
119
        options.put(i18nManager.getTranslation("key_bezier_curves"),BEZIER_CURVES);
120
        options.put(i18nManager.getTranslation("key_b_splines"),BSPLINES);
121

    
122

    
123
        EditingProviderServices editingProviderServices =
124
            (EditingProviderServices) getProviderServices();
125

    
126
        String consoleMsg =
127
            editingProviderServices.makeConsoleMessage(null, options);
128

    
129
        this.algorithm =
130
            new DefaultEditingServiceParameter("algorithm", consoleMsg, options,
131
                EditingServiceParameter.TYPE.OPTION);
132
}
133

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

    
146
    @Override
147
    public DrawingStatus getDrawingStatus(Point mousePosition)
148
        throws DrawServiceException {
149
        return null;
150
    }
151

    
152
    @Override
153
    public void stop() throws StopServiceException {
154
        if (values != null) {
155
            values.clear();
156
        }
157
    }
158

    
159
    @Override
160
    public List<EditingServiceParameter> getParameters() {
161
        List<EditingServiceParameter> parameters =
162
            new ArrayList<>();
163
        parameters.add(selection);
164
        parameters.add(steps);
165
        parameters.add(algorithm);
166
        return parameters;
167
    }
168

    
169
    @Override
170
    public void setValue(EditingServiceParameter parameter, Object value) throws InvalidEntryException {
171
        validateAndInsertValue(parameter, value);
172
    }
173

    
174
    @Override
175
    public void setValue(Object value) throws InvalidEntryException {
176
        EditingServiceParameter parameter = next();
177
        validateAndInsertValue(parameter, value);
178
    }
179

    
180
    private void validateAndInsertValue(EditingServiceParameter parameter,
181
        Object value) throws InvalidEntryException {
182

    
183
        if (parameter == selection) {
184

    
185
            FeatureSelection featureSelection = (FeatureSelection) value;
186

    
187
            if (featureSelection.getSelectedCount() > 0) {
188
                try {
189
                    featureSelection.accept((Object obj) -> {
190
                        Feature feature = (Feature) obj;
191
                        Geometry geometry = feature.getDefaultGeometry();
192
                        GeometryType geometryType =
193
                                geometry.getGeometryType();
194
                        
195
                        if (!geometryType.isTypeOf(Geometry.TYPES.CURVE)
196
                                && !geometryType.isTypeOf(Geometry.TYPES.MULTICURVE)) {
197
                            
198
                            throw new InvalidEntryException(null);
199
                        }
200
                    });
201

    
202
                    values.put(selection, value);
203
                    return;
204
                } catch (BaseException e) {
205
                    throw new InvalidEntryException(e);
206
                }
207
            }
208
        } else if (parameter == steps) {
209
            if (value instanceof Double) {
210
                Integer stepsValue = ((Double) value).intValue();
211
                if (stepsValue > 0 && stepsValue < 10 ) {
212
                    values.put(steps, stepsValue);
213
                    return;
214
                }
215
            }
216
        }  else if (parameter == algorithm) {
217

    
218
            if (value instanceof String) {
219

    
220
                I18nManager i18nManager = ToolsLocator.getI18nManager();
221
                String option = (String) value;
222

    
223
                if (option.equalsIgnoreCase(i18nManager.getTranslation("key_natural_cubic_splines"))){
224
                    values.put(parameter, "key_natural_cubic_splines");
225
                    return;
226
                }
227
                if (option.equalsIgnoreCase(i18nManager.getTranslation("key_bezier_curves"))){
228
                    values.put(parameter, "key_bezier_curves");
229
                    return;
230
                }
231
                if (option.equalsIgnoreCase(i18nManager.getTranslation("key_b_splines"))){
232
                    values.put(parameter, "key_b_splines");
233
                    return;
234
                }
235
            }
236
            throw new InvalidEntryException(null);
237

    
238
        }
239
        throw new InvalidEntryException(null);
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
            FeatureSelection featureSelection =
253
                (FeatureSelection) values.get(selection);
254
            ToolsLocator.getDisposableManager().bind(featureSelection);
255

    
256

    
257
            final Integer stepsValue = (Integer) values.get(steps);
258

    
259
            final String algorithmValue = (String)values.get(algorithm);
260

    
261
            final EditingProviderServices editingProviderServices =
262
                (EditingProviderServices) getProviderServices();
263

    
264
            try {
265
                final int subtype =
266
                    editingProviderServices.getSubType(featureStore);
267

    
268
                featureSelection.accept((Object obj) -> {
269
                    Feature feature = (Feature) obj;
270
                    Geometry geometry = feature.getDefaultGeometry();
271
                    GeometryType geoType = geometry.getGeometryType();
272
                    
273
                    if (geoType.isTypeOf(AGGREGATE)) {
274
                        
275
                        MultiCurve multiCurveToSmooth =
276
                                (MultiCurve) geometry;
277
                        
278
                        MultiCurve multiCurveSmoothed =
279
                                GeometryLocator.getGeometryManager()
280
                                        .createMultiCurve(subtype);
281
                        
282
                        for (int i = 0; i < multiCurveToSmooth
283
                                .getPrimitivesNumber(); i++) {
284
                            
285
                            Curve curveToSmooth =
286
                                    (Curve) multiCurveToSmooth
287
                                            .getPrimitiveAt(i);
288
                            curveToSmooth =
289
                                    smoothLine(curveToSmooth, stepsValue, algorithmValue);
290
                            multiCurveSmoothed.addCurve(curveToSmooth);
291
                            geometry = multiCurveSmoothed;
292
                        }
293
                    } else {
294
                        Curve curveToSmooth = (Curve) geometry;
295
                        curveToSmooth =
296
                                smoothLine(curveToSmooth, stepsValue, algorithmValue);
297
                        geometry = curveToSmooth;
298
                    }
299
                    
300
                    EditableFeature eFeature = feature.getEditable();
301
                    eFeature.setDefaultGeometry(geometry);
302
                    editingProviderServices.updateFeatureInFeatureStore(
303
                            eFeature, featureStore);
304
                });
305

    
306
                featureStore.getFeatureSelection().deselectAll();
307
                featureSelection.dispose();
308

    
309
            } catch (BaseException e) {
310
                throw new FinishServiceException(e);
311
            }
312
        }
313
    }
314

    
315
    private Line smoothLine(Curve curveToSmooth, Integer steps, String algorithm) throws DataException, CreateGeometryException{
316

    
317
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
318
        EditingProviderServices editingProviderServices =
319
            (EditingProviderServices) getProviderServices();
320

    
321
        int subtype = editingProviderServices.getSubType(featureStore);
322
        Line lineToSmooth;
323

    
324
        if (curveToSmooth instanceof Arc || curveToSmooth instanceof Spline) {
325
            lineToSmooth = geometryManager.createLine(curveToSmooth.getGeometryType().getSubType());
326
            lineToSmooth.setGeneralPath(curveToSmooth.getGeneralPath());
327

    
328
        } else {
329
            lineToSmooth = (Line)curveToSmooth;
330
        }
331

    
332
        ControlCurve operation;
333
        if (algorithm.equalsIgnoreCase("key_natural_cubic_splines")){
334
            operation = new NatCubic(lineToSmooth);
335
        } else if (algorithm.equalsIgnoreCase("key_bezier_curves")){
336
            operation = new Bezier(lineToSmooth);
337
        } else if (algorithm.equalsIgnoreCase("key_b_splines")){
338
            operation = new BSpline(lineToSmooth);
339
        } else {
340
            return null;
341
        }
342
        return operation.getSmoothedLine(steps, subtype);
343

    
344
    }
345

    
346

    
347
    private Line simplifyLine(Curve curveToSimplify, Double toleranceValue)
348
        throws DataException, CreateGeometryException,
349
        GeometryOperationNotSupportedException, GeometryOperationException {
350

    
351
        EditingProviderServices editingProviderServices =
352
            (EditingProviderServices) getProviderServices();
353

    
354
        int subtype = editingProviderServices.getSubType(featureStore);
355

    
356
        Line simplifiedLine =
357
            (Line) GeometryLocator.getGeometryManager().createLine(subtype);
358

    
359
        // Add first vertex
360
        simplifiedLine.addVertex(curveToSimplify.getVertex(0));
361

    
362
        // Iterate over vertices
363
        for (int i = 0; i < curveToSimplify.getNumVertices() - 2; i++) {
364

    
365
            Point vertex = curveToSimplify.getVertex(i);
366
            Point nextVertex = curveToSimplify.getVertex(i + 1);
367
            Point nextNextVertex = curveToSimplify.getVertex(i + 2);
368

    
369
            // Creates line between i vertex and i+2 vertex
370
            Line tmpLine =
371
                editingProviderServices.createLine(vertex, nextNextVertex,
372
                    subtype);
373

    
374
            // If distance between line and i+1 vertex is bigger than tolerance
375
            // add point to simplifiedLine, else skip vertex
376
            if (tmpLine.distance(nextVertex) > toleranceValue) {
377
                simplifiedLine.addVertex(nextVertex);
378
            } else {
379
                i++;
380
            }
381
        }
382

    
383
        // Add last vertex
384
        simplifiedLine.addVertex(curveToSimplify.getVertex(curveToSimplify
385
            .getNumVertices() - 1));
386

    
387
        return simplifiedLine;
388
    }
389

    
390
    @Override
391
    public void start() throws StartServiceException, InvalidEntryException {
392
        values = new HashMap<>();
393

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

    
411
    @Override
412
    public String getName() {
413
        return SmoothLineEditingProviderFactory.PROVIDER_NAME;
414
    }
415

    
416
    @Override
417
    public Object getValue(EditingServiceParameter parameter) {
418
        return values!=null?values.get(parameter):null;
419
    }
420
}