Statistics
| Revision:

gvsig-vectorediting / org.gvsig.vectorediting.offset / trunk / org.gvsig.vectorediting.offset / org.gvsig.vectorediting.offset.lib / org.gvsig.vectorediting.offset.lib.prov / org.gvsig.vectorediting.offset.lib.prov.offset / src / main / java / org / gvsig / vectorediting / offset / lib / prov / offset / OffsetEditingProvider.java @ 600

History | View | Annotate | Download (21.9 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.offset.lib.prov.offset;
26

    
27
import java.util.ArrayList;
28
import java.util.HashMap;
29
import java.util.LinkedHashMap;
30
import java.util.List;
31
import java.util.Map;
32

    
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 org.gvsig.fmap.geom.GeometryException;
40
import org.gvsig.fmap.geom.GeometryLocator;
41
import org.gvsig.fmap.geom.GeometryManager;
42
import org.gvsig.fmap.geom.aggregate.Aggregate;
43
import org.gvsig.fmap.geom.aggregate.MultiCurve;
44
import org.gvsig.fmap.geom.aggregate.MultiPoint;
45
import org.gvsig.fmap.geom.aggregate.MultiSurface;
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.Circle;
50
import org.gvsig.fmap.geom.primitive.Circumference;
51
import org.gvsig.fmap.geom.primitive.Curve;
52
import org.gvsig.fmap.geom.primitive.Ellipse;
53
import org.gvsig.fmap.geom.primitive.FilledSpline;
54
import org.gvsig.fmap.geom.primitive.Line;
55
import org.gvsig.fmap.geom.primitive.PeriEllipse;
56
import org.gvsig.fmap.geom.primitive.Point;
57
import org.gvsig.fmap.geom.primitive.Polygon;
58
import org.gvsig.fmap.geom.primitive.Spline;
59
import org.gvsig.fmap.geom.primitive.Surface;
60
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
61
import org.gvsig.tools.ToolsLocator;
62
import org.gvsig.tools.dispose.DisposableIterator;
63
import org.gvsig.tools.dynobject.DynObject;
64
import org.gvsig.tools.i18n.I18nManager;
65
import org.gvsig.tools.service.spi.ProviderServices;
66
import org.gvsig.vectorediting.lib.api.DrawingStatus;
67
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
68
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
69
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
70
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
71
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
72
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
73
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
74
import org.gvsig.vectorediting.lib.spi.DefaultDrawingStatus;
75
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
76
import org.gvsig.vectorediting.lib.spi.EditingProvider;
77
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
78
import org.gvsig.vectorediting.lib.spi.EditingProviderLocator;
79
import org.gvsig.vectorediting.lib.spi.EditingProviderManager;
80
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
81

    
82
public class OffsetEditingProvider extends AbstractEditingProvider implements
83
    EditingProvider {
84

    
85
    private final Double PRECISION = new Double(1.0e-5);
86

    
87
    private I18nManager i18nManager = ToolsLocator.getI18nManager();
88

    
89
    private EditingServiceParameter selectionParameter;
90

    
91
    private EditingServiceParameter offsetParameter;
92

    
93
    private EditingServiceParameter deleteOriginalGeometriesParameter;
94

    
95
    private boolean deleteOriginalGeometries = false;
96

    
97
    private Map<EditingServiceParameter, Object> values;
98

    
99
    private Map<String, String> options;
100

    
101
    private FeatureStore featureStore;
102

    
103
    public OffsetEditingProvider(ProviderServices providerServices, DynObject parameters) {
104
        super(providerServices);
105
        this.featureStore = (FeatureStore) parameters.getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
106

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

    
111
        this.offsetParameter =
112
            new DefaultEditingServiceParameter("offset_distance",
113
                i18nManager.getTranslation("offset_distance"),
114
                TYPE.POSITION, TYPE.VALUE);
115

    
116
        this.options = new LinkedHashMap<String, String>();
117
        options.put(i18nManager.getTranslation("short_yes"),
118
            "delete_original_geometries");
119
        options.put(i18nManager.getTranslation("short_no"),
120
            "keep_original_geometries");
121

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

    
125
        String consoleMsg =
126
            editingProviderServices.makeConsoleMessage(
127
                "delete_original_geometries_question", options);
128

    
129
        this.deleteOriginalGeometriesParameter =
130
            new DefaultEditingServiceParameter("Delete original geometries",
131
                consoleMsg, options, TYPE.OPTION);
132

    
133
    }
134

    
135
    public EditingServiceParameter next() {
136

    
137
        if (values.get(selectionParameter) == null) {
138
            return selectionParameter;
139
        } else if (values.get(offsetParameter) == null) {
140
            return offsetParameter;
141
        } else if (values.get(deleteOriginalGeometriesParameter) == null) {
142
            return this.deleteOriginalGeometriesParameter;
143
        }
144

    
145
        return null;
146
    }
147

    
148
    public DrawingStatus getDrawingStatus(Point mousePosition) throws DrawServiceException {
149
        DefaultDrawingStatus drawingStatus = new DefaultDrawingStatus();
150
        EditingProviderManager editingProviderManager =
151
            EditingProviderLocator.getProviderManager();
152
//        ISymbol auxiliaryLineSymbolEditing = editingProviderManager.getSymbol("auxiliary-line-symbol-editing");
153
        ISymbol auxiliaryPointSymbolEditing = editingProviderManager.getSymbol("auxiliary-point-symbol-editing");
154
        ISymbol lineSymbolEditing = editingProviderManager.getSymbol("line-symbol-editing");
155
        ISymbol polygonSymbolEditing = editingProviderManager.getSymbol("polygon-symbol-editing");
156

    
157

    
158
        FeatureSelection selected =
159
            (FeatureSelection) values.get(selectionParameter);
160
        try {
161
            if ((selected != null) && !selected.isEmpty()) {
162
                Point point = null;
163
                double distance = 0.0;
164
                Object offsetValue = values.get(offsetParameter);
165
                if (offsetValue != null){
166
                    if (offsetValue instanceof Point) {
167
                        point = (Point) offsetValue;
168
                    } else {
169
                        distance = (Double) offsetValue;
170
                    }
171
                } else {
172
                    point = mousePosition;
173
                    distance = getMinDistance(selected, point);
174
                }
175

    
176

    
177
                DisposableIterator it;
178
                it = selected.fastIterator();
179

    
180
                while (it.hasNext()) {
181
                    Feature feat = (Feature) it.next();
182
                    Geometry transformedGeometry = feat.getDefaultGeometry().offset(distance);
183

    
184
                    ISymbol symbol = null;
185
                    if (transformedGeometry instanceof Curve || transformedGeometry instanceof MultiCurve) {
186
                        symbol = lineSymbolEditing;
187
                    } else if (transformedGeometry instanceof Surface || transformedGeometry instanceof MultiSurface) {
188
                        symbol = polygonSymbolEditing;
189
                    } else if (transformedGeometry instanceof Point || transformedGeometry instanceof MultiPoint) {
190
                        symbol = auxiliaryPointSymbolEditing;
191
                    }
192
                    if (transformedGeometry instanceof Aggregate) {
193
                        int primitivesNumber = ((Aggregate) transformedGeometry).getPrimitivesNumber();
194
                        for (int i = 0; i < primitivesNumber; i++) {
195
                            drawingStatus.addStatus(((Aggregate) transformedGeometry).getPrimitiveAt(i), symbol, "");
196
                        }
197
                    } else {
198
                        drawingStatus.addStatus(transformedGeometry, symbol, "");
199
                    }
200
                }
201
                it.dispose();
202
            }
203
            return drawingStatus;
204
        } catch (Exception e) {
205
            throw new DrawServiceException(e);
206
        }
207
    }
208

    
209
    /**
210
     * @param selected
211
     * @param point
212
     * @return
213
     * @throws DataException
214
     * @throws GeometryOperationException
215
     * @throws GeometryOperationNotSupportedException
216
     * @throws GeometryException
217
     */
218
    private double getMinDistance(FeatureSelection selected, Point point) throws DataException, GeometryOperationNotSupportedException, GeometryOperationException, GeometryException {
219
        double minorDistance=Double.POSITIVE_INFINITY;
220
        DisposableIterator it;
221
        it = selected.fastIterator();
222
        while (it.hasNext()) {
223
            Feature feat = (Feature) it.next();
224
            Geometry geometry = feat.getDefaultGeometry();
225
            double distance = getDistance(geometry, point);
226
            if(distance < minorDistance){
227
                minorDistance = distance;
228
            }
229
        }
230
        it.dispose();
231
        return minorDistance;
232

    
233
    }
234

    
235
    /**
236
     * @param geometry
237
     * @param point
238
     * @return
239
     * @throws GeometryOperationException
240
     * @throws GeometryOperationNotSupportedException
241
     * @throws GeometryException
242
     */
243
    private double getDistance(Geometry geometry, Point point) throws GeometryOperationNotSupportedException, GeometryOperationException, GeometryException {
244
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
245
        if(geometry instanceof Arc){
246
            Arc arc = (Arc)geometry;
247
            Point center = arc.getCenterPoint();
248
            double radius = center.distance(arc.getInitPoint());
249
            double distance = center.distance(point)-radius;
250
            return distance;
251
        }
252

    
253
        if(geometry instanceof Circle){
254
            Circle circle = (Circle)geometry;
255
            return circle.getCenter().distance(point)-circle.getRadious();
256
        }
257
        if(geometry instanceof Circumference){
258
            Circumference circumference = (Circumference)geometry;
259
            return circumference.getCenter().distance(point)-circumference.getRadious();
260
        }
261
        if(geometry instanceof PeriEllipse){
262
            double minDistance = Double.POSITIVE_INFINITY;
263
            PeriEllipse ellipse = (PeriEllipse)geometry;
264
            Geometry[] closestPoints = point.closestPoints(ellipse);
265
            if (closestPoints!=null){
266
                for (int i = 0; i < closestPoints.length; i++) {
267
                    Geometry closestPoint = closestPoints[i];
268
                    if (!point.equals(closestPoint)) {
269
                        double distance = closestPoint.distance(point);
270
                        if (distance < minDistance) {
271
                            minDistance = distance;
272
                        }
273
                    }
274
                }
275
            }
276
            Ellipse auxEllipse = (Ellipse)geomManager.create(Geometry.TYPES.ELLIPSE, geometry.getGeometryType().getSubType());
277
            auxEllipse.setPoints(ellipse.getAxis1Start(), ellipse.getAxis1End(), ellipse.getAxis2Dist());
278
            if(auxEllipse.contains(point)){
279
                return -minDistance;
280
            }
281
            return minDistance;
282
        }
283
        if(geometry instanceof Ellipse){
284
            Ellipse ellipse = (Ellipse)geometry;
285
            PeriEllipse auxPeriEllipse = (PeriEllipse)geomManager.create(Geometry.TYPES.PERIELLIPSE, geometry.getGeometryType().getSubType());
286
            auxPeriEllipse.setPoints(ellipse.getAxis1Start(), ellipse.getAxis1End(), ellipse.getAxis2Dist());
287
            double distance = getDistance(auxPeriEllipse, point);
288
//            if(ellipse.contains(point)){
289
//                return -distance;
290
//            }
291

    
292
            return distance;
293
        }
294

    
295
        if(geometry instanceof Spline || geometry instanceof FilledSpline ){
296
            return getDistance(geometry.toLines().getPrimitiveAt(0), point);
297
        }
298

    
299
        if(geometry instanceof Line){
300
            Line line = (Line)geometry;
301
            double minDistance = Double.POSITIVE_INFINITY;
302
            Geometry[] closestPoints = point.closestPoints(line);
303
            Point closestPoint = null;
304
            if (closestPoints!=null){
305
                for (int i=0;i<closestPoints.length;i++){
306
                    Point p=(Point)closestPoints[i];
307
                    if (!point.equals(p)) {
308
                        double distance = p.distance(point);
309
                        if (distance < minDistance) {
310
                            minDistance = distance;
311
                            closestPoint = p;
312
                        }
313
                    }
314
                }
315
            }
316
            if(closestPoint != null){
317
                for(int i=0; i<line.getNumVertices()-1; i++){
318
                    Line segment = (Line) geomManager.create(Geometry.TYPES.LINE, geometry.getGeometryType().getSubType());
319
                    segment.addVertex(line.getVertex(i));
320
                    segment.addVertex(line.getVertex(i+1));
321
                    if(segment.isWithinDistance(closestPoint, PRECISION)){
322
                        if(line.getVertex(0).equals(line.getVertex(line.getNumVertices()-1))){ //isClosed
323
                            if(line.toPolygons().contains(point)){
324
                                return -minDistance;
325
                            };
326
                            return minDistance;
327
                        } else {
328
                            return getDirectedDistance(closestPoint, point, segment);
329
                        }
330
                    }
331
                }
332
            }
333
        }
334

    
335
        if(geometry instanceof Polygon){
336
            Polygon polygon = (Polygon)geometry;
337
            if(!polygon.contains(point)){
338
                double minDistance = Double.POSITIVE_INFINITY;
339
                Geometry[] closestPoints = point.closestPoints(polygon);
340
                Point closestPoint = null;
341
                if (closestPoints!=null){
342
                    for (int i=0;i<closestPoints.length;i++){
343
                        Point p=(Point)closestPoints[i];
344
                        if (!point.equals(p)) {
345
                            double distance = p.distance(point);
346
                            if (distance < minDistance) {
347
                                minDistance = distance;
348
                                closestPoint = p;
349
                            }
350
                        }
351
                    }
352
                }
353
                if(closestPoint != null){
354
                    return closestPoint.distance(point);
355
                }
356
            } else {
357
                Line auxLine = (Line) polygon.toLines().getPrimitiveAt(0);
358
                if(auxLine!=null){
359
                    return getDistance(auxLine, point);
360
                }
361
            }
362
        }
363

    
364
        if(geometry instanceof Aggregate){
365
            double minDistance = Double.POSITIVE_INFINITY;
366
            Aggregate aggregate2 = (Aggregate)geometry;
367
            for(int i=0; i<aggregate2.getPrimitivesNumber(); i++){
368
                double distance = getDistance(aggregate2.getPrimitiveAt(i),point);
369
                if(distance<minDistance){
370
                    minDistance = distance;
371
                }
372
            }
373
            return minDistance;
374
        }
375
        return 0.0;
376
    }
377

    
378
    public void stop() {
379
        values.clear();
380
    }
381

    
382
    private void validateAndInsertValue(EditingServiceParameter param,
383
        Object value) throws InvalidEntryException {
384
        if (param == selectionParameter) {
385
            if (value instanceof FeatureSelection) {
386
                values.put(param, value);
387
                return;
388
            }
389
        } else if (param == offsetParameter) {
390
            if (value instanceof Point) {
391
                try {
392
                    values.put(param, getMinDistance((FeatureSelection) values.get(selectionParameter), (Point) value));
393
                } catch (Exception e) {
394
                    throw new InvalidEntryException(e);
395
                }
396
                return;
397
            }
398
            if (value instanceof Double) {
399
                values.put(param, value);
400
            }
401
        } else if (param == deleteOriginalGeometriesParameter) {
402
            if (value instanceof String) {
403
                if (((String) value).trim().equalsIgnoreCase(
404
                    i18nManager.getTranslation("short_yes"))) {
405
                    deleteOriginalGeometries = true;
406
                } else if (((String) value).trim().equalsIgnoreCase(
407
                    i18nManager.getTranslation("short_no"))) {
408
                    deleteOriginalGeometries = false;
409
                } else {
410
                    throw new InvalidEntryException(null);
411
                }
412
                values.put(param, value);
413
            }
414
        }
415

    
416
    }
417

    
418
    public List<EditingServiceParameter> getParameters() {
419
        List<EditingServiceParameter> list =
420
            new ArrayList<EditingServiceParameter>();
421
        list.add(selectionParameter);
422
        list.add(offsetParameter);
423
        return list;
424
    }
425

    
426
    public void setValue(Object value) throws InvalidEntryException {
427
        EditingServiceParameter param = next();
428
        validateAndInsertValue(param, value);
429
    }
430

    
431
    public void finishAndStore() throws FinishServiceException {
432

    
433
        FeatureSelection selected =
434
            (FeatureSelection) values.get(selectionParameter);
435
        try {
436
            if (!selected.isEmpty()) {
437
                double distance = (Double) values.get(offsetParameter);
438
                    DisposableIterator it;
439
                    it = selected.fastIterator();
440

    
441
                    while (it.hasNext()) {
442
                        Feature feature = (Feature) it.next();
443
                        Geometry geom;
444
                        try {
445
                            geom = feature.getDefaultGeometry().offset(distance);
446
                        } catch (GeometryOperationNotSupportedException e) {
447
                            throw new FinishServiceException(e);
448
                        } catch (GeometryOperationException e) {
449
                            throw new FinishServiceException(e);
450
                        }
451

    
452
                        if (this.deleteOriginalGeometries) {
453
                            // Se sustituye la geometr?a original por la
454
                            // calculada
455
                            EditableFeature editableFeature =
456
                                feature.getEditable();
457
                            editableFeature.setDefaultGeometry(geom);
458
                            ((EditingProviderServices) getProviderServices())
459
                                .updateFeatureInFeatureStore(editableFeature,
460
                                    featureStore);
461
                        } else {
462
                            // Se crea una feature nueva copiando los valores de
463
                            // la feature original excepto aquellos que sean PK
464
                            EditingProviderServices editingProviderServices =
465
                                (EditingProviderServices) getProviderServices();
466
                            EditableFeature editableFeature =
467
                                editingProviderServices
468
                                    .getFeatureCopyWithoutPK(featureStore,
469
                                        feature);
470
                            editableFeature.setDefaultGeometry(geom);
471
                            editingProviderServices
472
                                .insertFeatureIntoFeatureStore(editableFeature,
473
                                    featureStore);
474
                        }
475

    
476
                    }
477
                    it.dispose();
478
                    featureStore.getFeatureSelection().deselectAll();
479
                }
480
        } catch (DataException e) {
481
            throw new FinishServiceException(e);
482
        }
483
    }
484

    
485
    private Double getDirectedDistance(Point pointInLine, Point distancePoint, Line line)
486
        throws GeometryOperationNotSupportedException, GeometryOperationException{
487
        Double distance=distancePoint.distance(pointInLine);
488
        EditingProviderServices editingProviderServices =
489
            (EditingProviderServices) getProviderServices();
490
        Double angle = editingProviderServices.getAngle(pointInLine, distancePoint);
491
        double angleLine = editingProviderServices.getAngle(line.getVertex(0), line.getVertex(1));
492

    
493
        Double angleDifference=angle - angleLine;
494
        if ( angleDifference<0 ){
495
            angleDifference+=2*Math.PI;
496
        }
497
        if (angleDifference > Math.PI ) {
498
            distance = -distance;
499
        }
500
        return distance;
501
    }
502

    
503
    public Geometry finish() throws FinishServiceException {
504
        return null;
505
    }
506

    
507
    public void start() throws StartServiceException {
508
        this.values = new HashMap<EditingServiceParameter, Object>();
509
        FeatureSelection selected = null;
510
        if (featureStore != null) {
511
            try {
512
                selected =
513
                    (FeatureSelection) featureStore.getFeatureSelection()
514
                        .clone();
515
            } catch (DataException e) {
516
                throw new StartServiceException(e);
517
            } catch (CloneNotSupportedException e) {
518
                // Do nothing
519
            }
520
            if ((selected != null) && (selected.getSelectedCount() > 0)) {
521
                values.put(selectionParameter, selected);
522
            }
523
        }
524
    }
525

    
526
    public String getName() {
527
        return OffsetEditingProviderFactory.PROVIDER_NAME;
528
    }
529
}