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.rotate / src / main / java / org / gvsig / vectorediting / lib / prov / rotate / RotateEditingProvider.java @ 3067

History | View | Annotate | Download (35.3 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.rotate;
25

    
26
import java.awt.geom.AffineTransform;
27
import java.util.ArrayList;
28
import java.util.Collections;
29
import java.util.HashMap;
30
import java.util.List;
31
import java.util.Map;
32
import org.apache.commons.collections4.CollectionUtils;
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.GeometryLocator;
40
import org.gvsig.fmap.geom.GeometryManager;
41
import org.gvsig.fmap.geom.GeometryUtils;
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.Curve;
50
import org.gvsig.fmap.geom.primitive.Envelope;
51
import org.gvsig.fmap.geom.primitive.Line;
52
import org.gvsig.fmap.geom.primitive.Point;
53
import org.gvsig.fmap.geom.primitive.Surface;
54
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
55
import org.gvsig.symbology.SymbologyLocator;
56
import org.gvsig.symbology.SymbologyManager;
57
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.ISimpleTextSymbol;
58
import org.gvsig.tools.ToolsLocator;
59
import org.gvsig.tools.dataTypes.DataTypes;
60
import org.gvsig.tools.dynobject.DynObject;
61
import org.gvsig.tools.exception.BaseException;
62
import org.gvsig.tools.i18n.I18nManager;
63
import org.gvsig.tools.service.spi.ProviderServices;
64
import org.gvsig.vectorediting.lib.api.DrawingStatus;
65
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
66
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
67
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
68
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
69
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
70
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
71
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
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.DefaultEditingServiceParameterOptions;
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
@SuppressWarnings("UseSpecificCatch")
83
public class RotateEditingProvider extends AbstractEditingProvider implements
84
        EditingProvider {
85

    
86
    public static final String KEY_PIVOT_CENTER_ENVELOPE = "_Key_pivot_center_envelope";
87

    
88
    public static final String PIVOT_CENTER_ENVELOPE = "_Pivot_center_envelope";
89

    
90
    public static final String KEY_PIVOT_CENTROID = "_Key_pivot_centroid";
91

    
92
    public static final String PIVOT_CENTROID = "_Pivot_centroid";
93

    
94
    public static final String ROTATE_MODE = "_Rotate_mode";
95

    
96
    public static final String ROTATE_ACTIVE_ANGLE_MODE = "_Rotate_active_angle_mode";
97

    
98
    public static final String ROTATE_TWO_POINTS_MODE = "_Rotate_two_points_mode";
99

    
100
    public static final String ROTATE_THREE_POINTS_MODE = "_Rotate_three_points_mode";
101

    
102
    public static final String KEY_ROTATE_ACTIVE_ANGLE_MODE = "_Key_rotate_active_angle_mode";
103

    
104
    public static final String KEY_ROTATE_TWO_POINTS_MODE = "_Key_rotate_two_points_mode";
105

    
106
    public static final String KEY_ROTATE_THREE_POINTS_MODE = "_Key_rotate_three_points_mode";
107
    
108
    private static final String SEPARATE_ELEMENTS_QUESTION = "_Separate_elements_question";
109
    
110
    private static final String ELEMENT_ROTATION = "_Element_rotation";
111

    
112
    private static final String INDIVIDUALLY = "_Individually";
113
    private static final String TOGETHER = "_Together";
114

    
115
    private static final String SHORT_YES = "_short_yes";
116
    private static final String SHORT_NO = "_short_no";
117

    
118

    
119
    //Variable est?tica para guardarnos el rotate_mode
120
    private static String savedRotateMode;
121
    private static Boolean savedSeparateElements;
122

    
123
    private final EditingServiceParameter selectionParameter;
124

    
125
    private final EditingServiceParameter pivotPointParameter;
126

    
127
    private String center;
128

    
129
    private final EditingServiceParameter modeParameter;
130
    
131
    private final EditingServiceParameter separateElementsParameter;
132

    
133
    private final EditingServiceParameter angleParameter;
134

    
135
    private final EditingServiceParameter firstPointParameter;
136

    
137
    private final EditingServiceParameter secondPointParameter;
138

    
139
    private Map<EditingServiceParameter, Object> values;
140

    
141
    private final FeatureStore featureStore;
142

    
143
    private List<Feature> selectedFeatures;
144

    
145
    public RotateEditingProvider(ProviderServices providerServices,
146
            DynObject parameters) {
147
        super(providerServices);
148
        this.featureStore
149
                = (FeatureStore) parameters
150
                        .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
151

    
152
        I18nManager i18nManager = ToolsLocator.getI18nManager();
153

    
154
        this.selectionParameter
155
                = new DefaultEditingServiceParameter("selection",
156
                        i18nManager.getTranslation("selection"), TYPE.SELECTION);
157

    
158
        DefaultEditingServiceParameterOptions options = new DefaultEditingServiceParameterOptions()
159
                .add(i18nManager.getTranslation(PIVOT_CENTER_ENVELOPE), PIVOT_CENTER_ENVELOPE, i18nManager.getTranslation(KEY_PIVOT_CENTER_ENVELOPE))
160
                .add(i18nManager.getTranslation(PIVOT_CENTROID), PIVOT_CENTROID, i18nManager.getTranslation(KEY_PIVOT_CENTROID))
161
                ;
162

    
163
        String consoleMsg
164
                = ((EditingProviderServices) providerServices).makeConsoleMessage(
165
                        "_Pivot_point", options);
166

    
167
        this.pivotPointParameter
168
                = new DefaultEditingServiceParameter(
169
                        "_Pivot_point",
170
                        consoleMsg,
171
                        options,
172
                        null,
173
                        TYPE.POSITION, TYPE.OPTION
174
                );
175
        
176
        DefaultEditingServiceParameterOptions modeOptions = new DefaultEditingServiceParameterOptions()
177
                .add(i18nManager.getTranslation(ROTATE_ACTIVE_ANGLE_MODE), ROTATE_ACTIVE_ANGLE_MODE, i18nManager.getTranslation(KEY_ROTATE_ACTIVE_ANGLE_MODE))
178
                .add(i18nManager.getTranslation(ROTATE_TWO_POINTS_MODE), ROTATE_TWO_POINTS_MODE, i18nManager.getTranslation(KEY_ROTATE_TWO_POINTS_MODE))
179
                .add(i18nManager.getTranslation(ROTATE_THREE_POINTS_MODE), ROTATE_THREE_POINTS_MODE, i18nManager.getTranslation(KEY_ROTATE_THREE_POINTS_MODE));
180

    
181
        String modeConsoleMsg
182
                = ((EditingProviderServices) providerServices).makeConsoleMessage(
183
                        ROTATE_MODE, options);
184

    
185
        this.modeParameter
186
                = new DefaultEditingServiceParameter(
187
                        ROTATE_MODE,
188
                        modeConsoleMsg,
189
                        modeOptions,
190
                        i18nManager.getTranslation(ROTATE_TWO_POINTS_MODE),
191
                        true, //Optional
192
                        TYPE.OPTION
193
                );
194
        
195
        DefaultEditingServiceParameterOptions separateElementsOptions=  new DefaultEditingServiceParameterOptions()
196
                .add(INDIVIDUALLY, true, i18nManager.getTranslation(SHORT_YES))
197
                .add(TOGETHER, false, i18nManager.getTranslation(SHORT_NO));
198

    
199
        String separateElementsConsoleMsg
200
                = ((EditingProviderServices) providerServices).makeConsoleMessage(
201
                        SEPARATE_ELEMENTS_QUESTION, separateElementsOptions);
202

    
203
        
204
        this.separateElementsParameter
205
                = new DefaultEditingServiceParameter(
206
                        ELEMENT_ROTATION,
207
                        separateElementsConsoleMsg, 
208
                        separateElementsOptions, 
209
                        i18nManager.getTranslation(SHORT_NO), 
210
                        true, 
211
                        TYPE.OPTION).setDataType(DataTypes.BOOLEAN);
212

    
213

    
214
        this.angleParameter
215
                = new DefaultEditingServiceParameter(
216
                        "_Angle",
217
                        i18nManager.getTranslation("_Angle"),
218
                        TYPE.VALUE
219
                );
220

    
221
        this.firstPointParameter
222
                = new DefaultEditingServiceParameter(
223
                        "Start_of_rotation",
224
                        i18nManager.getTranslation("_Start_of_rotation"),
225
                        TYPE.POSITION);
226

    
227
        this.secondPointParameter
228
                = new DefaultEditingServiceParameter(
229
                        "_End_of_rotation",
230
                        i18nManager.getTranslation("_End_of_rotation"),
231
                        TYPE.POSITION
232
                );
233

    
234
        this.values = new HashMap<>();
235

    
236
    }
237

    
238
    private ISimpleTextSymbol getTextSymbol() {
239
        SymbologyManager symbologyManager = SymbologyLocator.getSymbologyManager();
240
        ISimpleTextSymbol textSymbol = symbologyManager.createSimpleTextSymbol();
241
        textSymbol.setFontSize(10);
242
        return textSymbol;
243
    }
244

    
245
    @Override
246
    public DrawingStatus getDrawingStatus(Point mousePosition)
247
            throws DrawServiceException {
248
        DefaultDrawingStatus drawingStatus = new DefaultDrawingStatus();
249
        EditingProviderManager editingProviderManager
250
                = EditingProviderLocator.getProviderManager();
251
        ISymbol auxiliaryPointSymbolEditing = editingProviderManager.getSymbol("auxiliary-point-symbol-editing");
252
        ISymbol auxiliaryLineSymbolEditing = editingProviderManager.getSymbol("auxiliary-line-symbol-editing");
253
        ISymbol ruleAxisSymbol = editingProviderManager.getSymbol("rule-axis-symbol");
254
        ISymbol lineSymbolEditing = editingProviderManager.getSymbol("line-symbol-editing");
255
        ISymbol polygonSymbolEditing = editingProviderManager.getSymbol("polygon-symbol-editing");
256

    
257
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
258

    
259
        EditingProviderServices editingProviderServices = (EditingProviderServices) getProviderServices();
260

    
261
        try {
262
            int subType
263
                    = editingProviderServices.getSubType(featureStore);
264
            if ( !CollectionUtils.isEmpty(selectedFeatures) ) {
265
                Point p1 = (Point) values.get(pivotPointParameter);
266
                Point p2;
267
                Point p3;
268
                Double angle = null;
269
                if (p1 != null) {
270
                    drawingStatus.addStatus(p1, auxiliaryPointSymbolEditing, "");
271

    
272
                    switch ((String) values.get(modeParameter)) {
273
                        case ROTATE_ACTIVE_ANGLE_MODE:
274
                            return drawingStatus;
275
                        case ROTATE_TWO_POINTS_MODE:
276
                            p3 = (Point) values.get(secondPointParameter);
277
                            if (p3 == null) {
278
                                angle = GeometryUtils.calculateAngle(
279
                                        (Point) values.get(pivotPointParameter),
280
                                        mousePosition);
281

    
282
                                Line line;
283
                                line = geometryManager.createLine(subType);
284
                                line.addVertex(p1);
285
                                p3 = geometryManager.createPoint(
286
                                        p1.getX() + p1.distance(mousePosition),
287
                                        p1.getY(), subType);
288
                                line.addVertex(p3);
289
                                drawingStatus.addStatus(line, ruleAxisSymbol, "");
290
                                Line line2;
291
                                line2 = geometryManager.createLine(subType);
292
                                line2.addVertex(p1);
293
                                line2.addVertex(mousePosition);
294
                                drawingStatus.addStatus(line2, ruleAxisSymbol, "");
295
                                Double ext = (2 * Math.PI) - angle;
296
                                Arc arc = GeometryUtils.createArc(
297
                                        p1,
298
                                        p1.distance(mousePosition) / 2,
299
                                        0,
300
                                        angle,
301
                                        Geometry.SUBTYPES.GEOM2D);
302
                                drawingStatus.addStatus(arc, auxiliaryLineSymbolEditing, "");
303
                                double textDistance = 3 * p1.distance(mousePosition) / 4;
304
                                Point pointText = geometryManager.createPoint(p1.getX() + textDistance * Math.cos(angle / 2), p1.getY() + textDistance * Math.sin(angle / 2), subType);
305
                                ISimpleTextSymbol textSymbol = getTextSymbol();
306
                                drawingStatus.addStatus(pointText, textSymbol, degToDms(Math.toDegrees(angle)));
307
                            }
308
                            break;
309
                        case ROTATE_THREE_POINTS_MODE:
310
                            p2 = (Point) values.get(firstPointParameter);
311
                            p3 = (Point) values.get(secondPointParameter);
312
                            if (p2 == null) {
313
                                Line line;
314
                                line = geometryManager.createLine(subType);
315
                                line.addVertex(p1);
316
                                line.addVertex(mousePosition);
317
                                drawingStatus.addStatus(line, ruleAxisSymbol, "");
318
                            } else {
319
                                if (p3 == null) {
320
                                    angle = GeometryUtils.calculateAngle(
321
                                            (Point) values.get(pivotPointParameter),
322
                                            p2,
323
                                            mousePosition);
324

    
325
                                    double startAngle = GeometryUtils.calculateAngle(
326
                                            (Point) values.get(pivotPointParameter),
327
                                            p2);
328

    
329
                                    Line line;
330
                                    line = geometryManager.createLine(subType);
331
                                    line.addVertex(p1);
332
                                    line.addVertex(p2);
333
                                    drawingStatus.addStatus(line, ruleAxisSymbol, "");
334
                                    Line line2;
335
                                    line2 = geometryManager.createLine(subType);
336
                                    line2.addVertex(p1);
337
                                    line2.addVertex(mousePosition);
338
                                    drawingStatus.addStatus(line2, ruleAxisSymbol, "");
339
                                    Double ext = (2 * Math.PI) - angle;
340
                                    double minDistance = Math.min(p1.distance(p2), p1.distance(mousePosition));
341
                                    Arc arc = GeometryUtils.createArc(
342
                                            p1,
343
                                            minDistance/2,
344
                                            GeometryUtils.calculateAngle(p1, p2),
345
                                            GeometryUtils.calculateAngle(p1, p2, mousePosition),
346
                                            subType);
347
                                    drawingStatus.addStatus(arc, auxiliaryLineSymbolEditing, "");
348
                                    double textDistance = 3 * minDistance / 4;
349
                                    Point pointText = geometryManager.createPoint(p1.getX() + textDistance * Math.cos(startAngle+(angle / 2)), p1.getY() + textDistance * Math.sin(startAngle+(angle / 2)), subType);
350
                                    ISimpleTextSymbol textSymbol = getTextSymbol();
351
                                    drawingStatus.addStatus(pointText, textSymbol, degToDms(Math.toDegrees(angle)));
352
                                }
353
                            }
354
                            break;
355
                    }
356

    
357
                    if (angle != null) {
358
                        AffineTransform at;
359
                        try {
360
                            at = getRotateAffineTransform(p1, angle);
361
                        } catch (Exception e) {
362
                            throw new DrawServiceException(e);
363
                        }
364

    
365
                        Boolean separateElements = (Boolean) getValue(separateElementsParameter);
366
                        for (Feature feat : selectedFeatures) {
367
                            ISymbol previewSymbol = this.getPreviewSymbol(feat);
368

    
369
                            Geometry transformedGeometry = feat.getDefaultGeometry().cloneGeometry();
370
                            if(separateElements){
371
                                Point pivot = null;
372
                                //Si es cualquier punto y separamos elementos tambi?n pivotamos sobre el centro de la envoltura
373
                                if (center == null || PIVOT_CENTER_ENVELOPE.equalsIgnoreCase(center)) {
374
                                    Envelope featEnv = feat.getDefaultEnvelope();
375
                                    if (!featEnv.isEmpty()) {
376
                                        pivot = geometryManager.createPoint(featEnv.getCenter(0), featEnv.getCenter(1), subType);
377
                                    }
378
                                } else if (PIVOT_CENTROID.equalsIgnoreCase(center)) {
379
                                    pivot = feat.getDefaultGeometry().centroid();
380
                                }
381
                                if(pivot != null){
382
                                    try {
383
                                        at = getRotateAffineTransform(pivot, angle);
384
                                    } catch (Exception e) {
385
                                        throw new DrawServiceException(e);
386
                                    }
387
                                }
388
                            }
389
                            transformedGeometry.transform(at);
390

    
391
                            ISymbol symbol = null;
392
                            if (transformedGeometry instanceof Curve || transformedGeometry instanceof MultiCurve) {
393
                                symbol = lineSymbolEditing;
394
                            } else if (transformedGeometry instanceof Surface || transformedGeometry instanceof MultiSurface) {
395
                                symbol = polygonSymbolEditing;
396
                            } else if (transformedGeometry instanceof Point || transformedGeometry instanceof MultiPoint) {
397
                                symbol = auxiliaryPointSymbolEditing;
398
                            }
399
                            if (transformedGeometry instanceof Aggregate) {
400
                                int primitivesNumber = ((Aggregate) transformedGeometry).getPrimitivesNumber();
401
                                for (int i = 0; i < primitivesNumber; i++) {
402
                                    drawingStatus.addStatus(((Aggregate) transformedGeometry).getPrimitiveAt(i), symbol, "");
403
                                    drawingStatus.addStatus(((Aggregate) transformedGeometry).getPrimitiveAt(i), previewSymbol, "");
404
                                }
405
                            } else {
406
                                drawingStatus.addStatus(transformedGeometry, symbol, "");
407
                                drawingStatus.addStatus(transformedGeometry, previewSymbol, "");
408
                            }
409

    
410
                        }
411
                    }
412
                }
413
                return drawingStatus;
414
            }
415
        } catch (Exception e) {
416
            throw new DrawServiceException(e);
417
        }
418

    
419
        return null;
420

    
421
    }
422

    
423
    private String degToDms(double deg) {
424
        int d = (int) Math.floor(deg);
425
        double minfloat = (deg - d) * 60;
426
        int m = (int) Math.floor(minfloat);
427
        double secfloat = (minfloat - m) * 60;
428
        int s = (int) Math.round(secfloat);
429
        // After rounding, the seconds might become 60. These two
430
        // if-tests are not necessary if no rounding is done.
431
        if (s == 60) {
432
            m++;
433
            s = 0;
434
        }
435
        if (m == 60) {
436
            d++;
437
            m = 0;
438
        }
439
        return ("" + d + "\u00B0" + m + "\u2032" + s + "\u2033");
440
    }
441

    
442
    private AffineTransform getRotateAffineTransform(Point axisP1, Double angle)
443
            throws GeometryOperationNotSupportedException,
444
            GeometryOperationException {
445

    
446
        AffineTransform translate
447
                = AffineTransform
448
                        .getTranslateInstance(-axisP1.getX(), -axisP1.getY());
449

    
450
        AffineTransform rotate = AffineTransform.getRotateInstance(angle);
451

    
452
        AffineTransform inverseTranslate
453
                = AffineTransform.getTranslateInstance(axisP1.getX(), axisP1.getY());
454
        AffineTransform at = new AffineTransform(translate);
455

    
456
        at.preConcatenate(rotate);
457
        at.preConcatenate(inverseTranslate);
458
        return at;
459
    }
460

    
461
    @Override
462
    public EditingServiceParameter next() {
463
        if (values.get(selectionParameter) == null) {
464
            return this.selectionParameter;
465
        } else if (values.get(pivotPointParameter) == null) {
466
            return this.pivotPointParameter;
467
        } else if (((String) values.get(modeParameter)).equalsIgnoreCase(ROTATE_ACTIVE_ANGLE_MODE)) {
468
            if (values.get(angleParameter) == null) {
469
                return angleParameter;
470
            }
471
        } else if (((String) values.get(modeParameter)).equalsIgnoreCase(ROTATE_TWO_POINTS_MODE)) {
472
            if (values.get(secondPointParameter) == null) {
473
                return secondPointParameter;
474
            }
475
        } else if (((String) values.get(modeParameter)).equalsIgnoreCase(ROTATE_THREE_POINTS_MODE)) {
476
            if (values.get(firstPointParameter) == null) {
477
                return firstPointParameter;
478
            }
479
            if (values.get(secondPointParameter) == null) {
480
                return secondPointParameter;
481
            }
482
        }
483
        return null;
484
    }
485

    
486
    public void stop() {
487
        values.clear();
488
        this.selectedFeatures = Collections.EMPTY_LIST;
489
    }
490

    
491
    private void validateAndInsertValue(EditingServiceParameter param,
492
            Object value) throws InvalidEntryException {
493
        if (param == selectionParameter) {
494
            if (value instanceof FeatureSelection) {
495
                values.put(param, value);
496
                this.selectedFeatures = this.getSelectedFeaturesCopy((FeatureSelection) value);
497
            } else {
498
                throw new InvalidEntryException(null);
499
            }
500

    
501
        } else if (param == modeParameter) {
502
            savedRotateMode = (String) param.getOptions2().getValue(value, param.getDefaultValue());
503
            values.put(param, savedRotateMode);
504
        } else if (param == separateElementsParameter) {
505
            savedSeparateElements = (Boolean) param.getOptions2().getValue(value, param.getDefaultValue());
506
            values.put(param, savedSeparateElements);
507
        } else if (param == pivotPointParameter) {
508
            if (value == null) {
509
                center = null;
510
                values.remove(param);
511
            } else if (value instanceof Point) {
512
                values.put(param, value);
513
                center = null;
514
            } else if (value instanceof String) {
515
                String pivotMode = (String) param.getOptions2().getValue(value, param.getDefaultValue());
516
                if (PIVOT_CENTER_ENVELOPE.equalsIgnoreCase(pivotMode) || PIVOT_CENTROID.equalsIgnoreCase(pivotMode)) {
517
                    center = pivotMode;
518
                    FeatureSelection selected
519
                            = (FeatureSelection) values.get(this.selectionParameter);
520
                    values.put(param, calculatePivot(selected, pivotMode));
521
                } else {
522
                    center = null;
523
                    values.remove(param);
524
                }
525
            } else {
526
                throw new InvalidEntryException(null);
527
            }
528
        } else if (param == firstPointParameter) {
529
            if (value instanceof Point) {
530
                if (((Point) value).equals((Point) values.get(pivotPointParameter))) {
531
                    throw new InvalidEntryException(null);
532
                }
533
                values.put(param, value);
534
            } else {
535
                throw new InvalidEntryException(null);
536
            }
537
        } else if (param == secondPointParameter) {
538
            if (value instanceof Point) {
539
                if (((Point) value).equals((Point) values.get(firstPointParameter))
540
                        || ((Point) value).equals((Point) values.get(pivotPointParameter))) {
541
                    throw new InvalidEntryException(null);
542
                }
543
                values.put(param, value);
544
            } else {
545
                throw new InvalidEntryException(null);
546
            }
547
        } else if (param == angleParameter) {
548
            if (value instanceof Double) {
549
                if ((Double)value == 0.0){
550
                    throw new InvalidEntryException(null);
551
                }
552
                values.put(param, value);
553
            } else {
554
                throw new InvalidEntryException(null);
555
            }
556
        }
557
    }
558

    
559
    @Override
560
    public List<EditingServiceParameter> getParameters() {
561
        List<EditingServiceParameter> list
562
                = new ArrayList<>();
563
        list.add(selectionParameter);
564
        list.add(modeParameter);
565
        list.add(pivotPointParameter);
566
        list.add(separateElementsParameter);
567
        list.add(angleParameter);
568
        list.add(firstPointParameter);
569
        list.add(secondPointParameter);
570
        return list;
571
    }
572

    
573
    @Override
574
    public void setValue(EditingServiceParameter parameter, Object value) throws InvalidEntryException {
575
        validateAndInsertValue(parameter, value);
576
    }
577

    
578
    @Override
579
    public void setValue(Object value) throws InvalidEntryException {
580
        EditingServiceParameter param = next();
581
        validateAndInsertValue(param, value);
582
    }
583

    
584
    @Override
585
    public void finishAndStore() throws FinishServiceException {
586

    
587
        EditingProviderServices editingProviderServices = (EditingProviderServices) getProviderServices();
588

    
589
        try {
590
            int subType = editingProviderServices.getSubType(featureStore);
591
            if (CollectionUtils.isNotEmpty(selectedFeatures)) {
592
                Point p0 = (Point) values.get(pivotPointParameter);
593
                Point p1;
594
                Object p2;
595
                Double angle = null;
596
                if(values.get(angleParameter) != null){
597
                    angle = Math.toRadians((Double) values.get(angleParameter));
598
                }
599
                switch ((String) values.get(modeParameter)) {
600
                    case ROTATE_ACTIVE_ANGLE_MODE:
601
                        break;
602
                    case ROTATE_TWO_POINTS_MODE:
603
                        p2 = values.get(secondPointParameter);
604
                        angle = GeometryUtils.calculateAngle(p0, (Point)p2);
605
                        break;
606
                    case ROTATE_THREE_POINTS_MODE:
607
                        p1 = (Point) values.get(firstPointParameter);
608
                        p2 = values.get(secondPointParameter);
609
                        angle = GeometryUtils.calculateAngle(p0, p1, (Point)p2);
610
                        break;
611
                }
612
                
613
                if(angle != null){
614
                    final Double finalAngle = angle;
615

    
616
                    final AffineTransform at;
617
                    try {
618
                        at = getRotateAffineTransform(p0, finalAngle);
619
                    } catch (GeometryOperationNotSupportedException | GeometryOperationException e) {
620
                        throw new FinishServiceException(e);
621
                    }
622

    
623
                    Boolean separateElements = (Boolean) getValue(separateElementsParameter);
624
                    GeometryManager geometryManager = GeometryLocator.getGeometryManager();
625

    
626
                    try {
627
                        for (Feature feature : selectedFeatures) {
628
                            AffineTransform individualAt = at;
629
                            Geometry geom
630
                                    = feature.getDefaultGeometry()
631
                                            .cloneGeometry();
632
                            if(separateElements){
633
                                Point pivot = null;
634
                                //Si es cualquier punto y separamos elementos tambi?n pivotamos sobre el centro de la envoltura
635
                                if (center == null || PIVOT_CENTER_ENVELOPE.equalsIgnoreCase(center)) {
636
                                    Envelope featEnv = feature.getDefaultEnvelope();
637
                                    if (!featEnv.isEmpty()) {
638
                                        pivot = geometryManager.createPoint(featEnv.getCenter(0), featEnv.getCenter(1), subType);
639
                                    }
640
                                } else if (PIVOT_CENTROID.equalsIgnoreCase(center)) {
641
                                    pivot = feature.getDefaultGeometry().centroid();
642
                                }
643
                                if(pivot != null){
644
                                    try {
645
                                        individualAt = getRotateAffineTransform(pivot, finalAngle);
646
                                    } catch (Exception e) {
647
                                        throw new DrawServiceException(e);
648
                                    }
649
                                }
650
                            }
651

    
652
                            
653
                            geom.transform(individualAt);
654
                            // Se sustituye la geometr?a original por la
655
                            // calculada
656
                            EditableFeature editableFeature
657
                                    = feature.getEditable();
658
                            editableFeature.setDefaultGeometry(geom);
659
                            ((EditingProviderServices) getProviderServices())
660
                                    .updateFeatureInFeatureStore(
661
                                            editableFeature, featureStore);
662
                        }
663
                    } catch (BaseException e) {
664
                        throw new FinishServiceException(e);
665
                    }
666
                    featureStore.getFeatureSelection().deselectAll();
667
                }
668
            }
669
        } catch (DataException e) {
670
            throw new FinishServiceException(e);
671
        }
672
    }
673

    
674
    @Override
675
    public Geometry finish() throws FinishServiceException {
676
        return null;
677
    }
678

    
679
    @Override
680
    public void start() throws StartServiceException {
681
        this.values = new HashMap<>();        
682
        this.selectedFeatures = Collections.EMPTY_LIST;
683
        if (featureStore != null) {
684
            FeatureSelection selected = null;
685
            try {
686
                selected = (FeatureSelection) featureStore.getFeatureSelection().clone();
687
            } catch (DataException e) {
688
                throw new StartServiceException(e);
689
            } catch (CloneNotSupportedException ex) {
690
                LOGGER.debug("Can't init selection",ex);
691
            }
692
            if ((selected != null) && (selected.getSelectedCount() > 0)) {
693
                values.put(selectionParameter, selected);
694
                this.selectedFeatures = this.getSelectedFeaturesCopy(selected);
695
            }
696
        }
697
        if (savedRotateMode != null) {
698
            this.values.put(modeParameter, savedRotateMode);
699
        }
700
    }
701

    
702
    @Override
703
    public void restart() throws StartServiceException, InvalidEntryException, StopServiceException {
704
        values.put(selectionParameter, null);
705
        this.selectedFeatures = Collections.EMPTY_LIST;
706
        values.put(pivotPointParameter, null);
707
        center = null;
708
        values.put(angleParameter, null);
709
        values.put(firstPointParameter, null);
710
        values.put(secondPointParameter, null);
711
    }
712

    
713
    @Override
714
    public String getName() {
715
        return RotateEditingProviderFactory.PROVIDER_NAME;
716
    }
717

    
718
    @Override
719
    public Object getValue(EditingServiceParameter parameter) {
720
        return values != null ? values.get(parameter) : null;
721
    }
722

    
723
    @Override
724
    public Object getValue(EditingServiceParameter parameter, EditingServiceParameter.TYPE type) {
725
        if(values == null){
726
            return null;
727
        }
728
        if(parameter == pivotPointParameter){
729
            if (type == TYPE.OPTION) {
730
                return center;
731
            }
732
        }
733
        return values != null ? values.get(parameter) : null;
734
    }
735

    
736
    @Override
737
    public boolean isEnabled(EditingServiceParameter parameter) {
738
        return true;
739
    }
740

    
741
    private Point calculatePivot(FeatureSelection selection, String mode) throws InvalidEntryException {
742
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
743
        Point pivot = null;
744
        FeatureSelection selected
745
                = (FeatureSelection) values.get(this.selectionParameter);
746
        try {
747
            int subType = this.getProviderServices().getSubType(featureStore);
748
            if ((selected != null) && !selected.isEmpty()) {
749
                if (PIVOT_CENTER_ENVELOPE.equalsIgnoreCase(mode)) {
750
                    Envelope envelope = geomManager.createEnvelope(subType);
751
                    for (Feature feature : selected) {
752
                        Envelope featEnv = feature.getDefaultEnvelope();
753
                        envelope.add(featEnv);
754
                    }
755
                    if (!envelope.isEmpty()) {
756
                        pivot = geomManager.createPoint(envelope.getCenter(0), envelope.getCenter(1), subType);
757
                    }
758
                } else if (PIVOT_CENTROID.equalsIgnoreCase(mode)) {
759
                    Geometry geometry = null;
760
                    for (Feature feature : selected) {
761
                        if (geometry == null) {
762
                            geometry = feature.getDefaultGeometry().clone();
763
                        } else {
764
                            geometry = geometry.union(feature.getDefaultGeometry().clone());
765
                        }
766
                    }
767
                    if (geometry != null) {
768
                        pivot = geometry.centroid();
769
                    }
770
                }
771
            }
772
        } catch (Exception ex) {
773
            throw new InvalidEntryException(ex);
774
        }
775

    
776
        return pivot;
777
    }
778

    
779
}