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.polarmatrix / src / main / java / org / gvsig / vectorediting / lib / prov / polarmatrix / PolarMatrixEditingProvider.java @ 491

History | View | Annotate | Download (22 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2015 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.polarmatrix;
26

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

    
34
import org.gvsig.fmap.dal.exception.DataException;
35
import org.gvsig.fmap.dal.feature.EditableFeature;
36
import org.gvsig.fmap.dal.feature.Feature;
37
import org.gvsig.fmap.dal.feature.FeatureSelection;
38
import org.gvsig.fmap.dal.feature.FeatureStore;
39
import org.gvsig.fmap.geom.Geometry;
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.exception.CreateGeometryException;
47
import org.gvsig.fmap.geom.operation.GeometryOperationException;
48
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
49
import org.gvsig.fmap.geom.primitive.Arc;
50
import org.gvsig.fmap.geom.primitive.Curve;
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.dispose.DisposableIterator;
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.tools.visitor.VisitCanceledException;
65
import org.gvsig.tools.visitor.Visitor;
66
import org.gvsig.vectorediting.lib.api.DrawingStatus;
67
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
68
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
69
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
70
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
71
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
72
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
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
/**
83
 * @author llmarques
84
 *
85
 */
86
public class PolarMatrixEditingProvider extends AbstractEditingProvider
87
    implements EditingProvider {
88

    
89
    private FeatureStore featureStore;
90

    
91
    private Map<EditingServiceParameter, Object> values;
92

    
93
    private EditingServiceParameter selection;
94

    
95
    private EditingServiceParameter elementsNumber;
96

    
97
    private EditingServiceParameter centerPoint;
98

    
99
    private EditingServiceParameter elementAngle;
100

    
101
    private EditingServiceParameter rotateElements;
102

    
103
    /**
104
     * Default constructor.
105
     *
106
     * @param providerServices
107
     *            available services for this provider
108
     * @param parameters
109
     *            of this provider
110
     */
111
    public PolarMatrixEditingProvider(DynObject parameters,
112
        ProviderServices services) {
113
        super(services);
114

    
115
        this.featureStore =
116
            (FeatureStore) parameters
117
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
118

    
119
        this.selection =
120
            new DefaultEditingServiceParameter("selection", "selection",
121
                EditingServiceParameter.TYPE.SELECTION);
122

    
123
        this.elementsNumber =
124
            new DefaultEditingServiceParameter("number_of_total_elements",
125
                "number_of_total_elements", EditingServiceParameter.TYPE.VALUE);
126

    
127
        I18nManager i18nManager = ToolsLocator.getI18nManager();
128
        Map<String, String> options = new LinkedHashMap<String, String>();
129
        options.put(i18nManager.getTranslation("key_yes"), "yes");
130
        options.put(i18nManager.getTranslation("key_no"), "no");
131

    
132
        EditingProviderServices editingProviderServices =
133
            (EditingProviderServices) getProviderServices();
134

    
135
        this.rotateElements =
136
            new DefaultEditingServiceParameter("rotate_elements",
137
                editingProviderServices.makeConsoleMessage("rotate_elements",
138
                    options), options, EditingServiceParameter.TYPE.OPTION);
139

    
140
        this.centerPoint =
141
            new DefaultEditingServiceParameter("center", "center",
142
                EditingServiceParameter.TYPE.POSITION);
143

    
144
        this.elementAngle =
145
            new DefaultEditingServiceParameter("angle_between_elements",
146
                "angle_between_elements", EditingServiceParameter.TYPE.VALUE,
147
                EditingServiceParameter.TYPE.POSITION);
148
    }
149

    
150
    public EditingServiceParameter next() {
151
        if (values.get(selection) == null) {
152
            return selection;
153
        } else if (values.get(elementsNumber) == null) {
154
            return elementsNumber;
155
        } else if (values.get(rotateElements) == null) {
156
            return rotateElements;
157
        } else if (values.get(centerPoint) == null) {
158
            return centerPoint;
159
        } else if (values.get(elementAngle) == null) {
160
            return elementAngle;
161
        }
162
        return null;
163
    }
164

    
165
    public DrawingStatus getDrawingStatus(Point mousePosition)
166
        throws DrawServiceException {
167

    
168
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
169
        DefaultDrawingStatus drawingStatus = new DefaultDrawingStatus();
170
        EditingProviderServices editingProviderServices =
171
            (EditingProviderServices) getProviderServices();
172

    
173
        FeatureSelection featureSelection =
174
            (FeatureSelection) values.get(selection);
175
        Integer elementsNumberValue = (Integer) values.get(elementsNumber);
176
        Boolean rotateElementsValue = (Boolean) values.get(rotateElements);
177
        Point centerPointValue = (Point) values.get(centerPoint);
178

    
179
        if (featureSelection != null && elementsNumberValue != null
180
            && rotateElementsValue != null && centerPointValue != null) {
181

    
182
            Double angle = (Double) values.get(elementAngle);
183
            if (angle == null) {
184
                try {
185
                    angle =
186
                        editingProviderServices.getAngle(centerPointValue,
187
                            mousePosition);
188
                } catch (BaseException e) {
189
                    throw new DrawServiceException(e);
190
                }
191
            }
192

    
193
            // Creation of symbology
194
            EditingProviderManager editingProviderManager =
195
                EditingProviderLocator.getProviderManager();
196
            ISymbol auxiliaryPointSymbolEditing =
197
                editingProviderManager
198
                    .getSymbol("auxiliary-point-symbol-editing");
199
            ISymbol ruleAxisSymbol =
200
                editingProviderManager.getSymbol("rule-axis-symbol");
201
            ISymbol auxiliaryLineSymbolEditing =
202
                editingProviderManager
203
                    .getSymbol("auxiliary-line-symbol-editing");
204

    
205
            try {
206

    
207
                drawingStatus.addStatus(centerPointValue,
208
                    auxiliaryPointSymbolEditing, "");
209

    
210
                // Grade indicator creation
211
                int subtype = centerPointValue.getGeometryType().getSubType();
212
                double textDistance =
213
                    3 * centerPointValue.distance(mousePosition) / 4;
214
                Geometry pointText =
215
                    geometryManager.createPoint(
216
                        centerPointValue.getX() + textDistance
217
                            * Math.cos(angle / 2),
218
                        centerPointValue.getY() + textDistance
219
                            * Math.sin(angle / 2), subtype);
220
                drawingStatus.addStatus(pointText, getTextSymbol(),
221
                    degToDms(Math.toDegrees(angle)));
222

    
223
                // Horizontal line of angle indicator creation
224
                Line horizontalLine = geometryManager.createLine(subtype);
225
                horizontalLine.setPoints(centerPointValue, geometryManager
226
                    .createPoint(
227
                        centerPointValue.getX()
228
                            + centerPointValue.distance(mousePosition),
229
                        centerPointValue.getY(), subtype));
230
                drawingStatus.addStatus(horizontalLine, ruleAxisSymbol, "");
231

    
232
                // Vertical line of angle indicator creation
233
                Line verticalLine = geometryManager.createLine(subtype);
234
                verticalLine.setPoints(centerPointValue, mousePosition);
235
                drawingStatus.addStatus(verticalLine, ruleAxisSymbol, "");
236

    
237
                // Arc angle indicator creation
238
                Double ext = (2 * Math.PI) - angle;
239
                Arc arc =
240
                    editingProviderServices.createArc(centerPointValue,
241
                        centerPointValue.distance(mousePosition) / 2, 0, ext,
242
                        subtype);
243
                drawingStatus.addStatus(arc, auxiliaryLineSymbolEditing, "");
244

    
245
            } catch (BaseException e) {
246
                throw new DrawServiceException(e);
247
            }
248

    
249
            DisposableIterator it = null;
250
            try {
251
                it = featureSelection.fastIterator();
252
                while (it.hasNext()) {
253
                    Feature feature = (Feature) it.next();
254
                    Geometry geometry = feature.getDefaultGeometry();
255
                    Geometry[] matrix =
256
                        createPolarMatrix(geometry, elementsNumberValue,
257
                            rotateElementsValue, centerPointValue, angle);
258

    
259
                    for (int i = 0; i < matrix.length; i++) {
260

    
261
                        ISymbol symbol = getSymbol(matrix[i]);
262

    
263
                        if (matrix[i] instanceof Aggregate) {
264
                            int primitivesNumber =
265
                                ((Aggregate) matrix[i]).getPrimitivesNumber();
266
                            for (int j = 0; j < primitivesNumber; j++) {
267
                                drawingStatus.addStatus(
268
                                    ((Aggregate) matrix[i]).getPrimitiveAt(j),
269
                                    symbol, "");
270
                            }
271
                        } else {
272
                            drawingStatus.addStatus(matrix[i], symbol, "");
273
                        }
274
                    }
275
                }
276
            } catch (BaseException e) {
277
                throw new DrawServiceException(e);
278
            } finally {
279
                it.dispose();
280
            }
281
        }
282
        return drawingStatus;
283
    }
284

    
285
    private ISymbol getSymbol(Geometry geometry) {
286

    
287
        EditingProviderManager editingProviderManager =
288
            EditingProviderLocator.getProviderManager();
289
        ISymbol auxiliaryPointSymbolEditing =
290
            editingProviderManager.getSymbol("auxiliary-point-symbol-editing");
291
        ISymbol lineSymbolEditing =
292
            editingProviderManager.getSymbol("line-symbol-editing");
293
        ISymbol polygonSymbolEditing =
294
            editingProviderManager.getSymbol("polygon-symbol-editing");
295

    
296
        if (geometry instanceof Curve || geometry instanceof MultiCurve) {
297
            return lineSymbolEditing;
298
        } else if (geometry instanceof Surface
299
            || geometry instanceof MultiSurface) {
300
            return polygonSymbolEditing;
301
        } else if (geometry instanceof Point || geometry instanceof MultiPoint) {
302
            return auxiliaryPointSymbolEditing;
303
        }
304
        return null;
305
    }
306

    
307
    private ISimpleTextSymbol getTextSymbol() {
308
        SymbologyManager symbologyManager =
309
            SymbologyLocator.getSymbologyManager();
310
        ISimpleTextSymbol textSymbol =
311
            symbologyManager.createSimpleTextSymbol();
312
        textSymbol.setFontSize(10);
313
        return textSymbol;
314
    }
315

    
316
    private String degToDms(double deg) {
317
        int d = (int) Math.floor(deg);
318
        double minfloat = (deg - d) * 60;
319
        int m = (int) Math.floor(minfloat);
320
        double secfloat = (minfloat - m) * 60;
321
        int s = (int) Math.round(secfloat);
322
        // After rounding, the seconds might become 60. These two
323
        // if-tests are not necessary if no rounding is done.
324
        if (s == 60) {
325
            m++;
326
            s = 0;
327
        }
328
        if (m == 60) {
329
            d++;
330
            m = 0;
331
        }
332
        return ("" + d + "\u00B0" + m + "\u2032" + s + "\u2033");
333
    }
334

    
335
    private Geometry[] createPolarMatrix(Geometry geometry,
336
        Integer elementsNumberValue, Boolean rotateElementsValue,
337
        Point centerPointValue, Double angle)
338
        throws GeometryOperationNotSupportedException,
339
        GeometryOperationException, CreateGeometryException {
340

    
341
        Geometry[] geometryMatrix = new Geometry[elementsNumberValue];
342

    
343
        for (int i = 0; i < elementsNumberValue; i++) {
344

    
345
            AffineTransform at = new AffineTransform();
346
            if (rotateElementsValue) {
347
                at = getRotateAffineTransform(centerPointValue, angle * i);
348
            } else {
349
                at = getRotateAffineTransform(centerPointValue, angle * i);
350
                
351
                double centerX = geometry.getEnvelope().getCenter(0);
352
                double centerY = geometry.getEnvelope().getCenter(1);
353
                GeometryManager geometryManager =
354
                    GeometryLocator.getGeometryManager();
355
                Point geometryCenter =
356
                    geometryManager.createPoint(centerX, centerY, GEOM2D);
357
                
358
                Point geometryCenterCloned = (Point) geometryCenter.cloneGeometry();
359
                geometryCenterCloned.transform(at);
360
                at = getMoveAffineTransform(geometryCenter, geometryCenterCloned);
361
            }
362

    
363
            Geometry clonedGeometry = geometry.cloneGeometry();
364
            clonedGeometry.transform(at);
365
            geometryMatrix[i] = clonedGeometry;
366
        }
367

    
368
        return geometryMatrix;
369
    }
370

    
371
    public void stop() throws StopServiceException {
372
        values.clear();
373
    }
374

    
375
    public List<EditingServiceParameter> getParameters() {
376
        List<EditingServiceParameter> parameters =
377
            new ArrayList<EditingServiceParameter>();
378
        parameters.add(selection);
379
        parameters.add(rotateElements);
380
        parameters.add(centerPoint);
381
        parameters.add(elementAngle);
382
        return parameters;
383
    }
384

    
385
    public void setValue(Object value) throws InvalidEntryException {
386
        EditingServiceParameter parameter = next();
387
        validateAndInsertValue(parameter, value);
388
    }
389

    
390
    private void validateAndInsertValue(EditingServiceParameter parameter,
391
        Object value) throws InvalidEntryException {
392

    
393
        boolean insertedValue = false;
394

    
395
        if (parameter.equals(selection) && value instanceof FeatureSelection) {
396
            FeatureSelection featureSelection = (FeatureSelection) value;
397

    
398
            if (featureSelection.getSelectedCount() > 0) {
399
                values.put(parameter, featureSelection);
400
                insertedValue = true;
401
            }
402

    
403
        } else if (parameter.equals(elementsNumber) && value instanceof Double) {
404

    
405
            if (value instanceof Double) {
406
                Double number = (Double) value;
407
                values.put(parameter, number.intValue());
408
                insertedValue = true;
409
            }
410

    
411
        } else if (parameter.equals(rotateElements) && value instanceof String) {
412

    
413
            String option = (String) value;
414
            I18nManager i18nManager = ToolsLocator.getI18nManager();
415
            if (option.equalsIgnoreCase(i18nManager.getTranslation("key_yes"))) {
416
                values.put(rotateElements, true);
417
                insertedValue = true;
418
            } else if (option.equalsIgnoreCase(i18nManager
419
                .getTranslation("key_no"))) {
420
                values.put(rotateElements, false);
421
                insertedValue = true;
422
            }
423

    
424
        } else if (parameter.equals(centerPoint) && value instanceof Point) {
425

    
426
            values.put(centerPoint, value);
427
            insertedValue = true;
428

    
429
        } else if (parameter.equals(elementAngle)) {
430

    
431
            if (value instanceof Double) {
432

    
433
                values.put(elementAngle, Math.toRadians((Double) value));
434
                insertedValue = true;
435

    
436
            } else if (value instanceof Point) {
437
                EditingProviderServices editingProviderServices =
438
                    (EditingProviderServices) getProviderServices();
439
                Point centerPointValue = (Point) values.get(centerPoint);
440
                Point valuePoint = (Point) value;
441
                try {
442
                    double angle =
443
                        editingProviderServices.getAngle(centerPointValue,
444
                            valuePoint);
445
                    values.put(elementAngle, angle);
446
                    insertedValue = true;
447
                } catch (BaseException e) {
448
                    throw new InvalidEntryException(e);
449
                }
450
            }
451
        }
452

    
453
        if (!insertedValue) {
454
            throw new InvalidEntryException(null);
455
        }
456
    }
457

    
458
    public Geometry finish() throws FinishServiceException {
459
        return null;
460
    }
461

    
462
    public void finishAndStore() throws FinishServiceException {
463

    
464
        final EditingProviderServices editingProviderServices =
465
            (EditingProviderServices) getProviderServices();
466

    
467
        FeatureSelection featureSelection =
468
            (FeatureSelection) values.get(selection);
469
        final Integer elementsNumberValue =
470
            (Integer) values.get(elementsNumber);
471
        final Boolean rotateElementsValue =
472
            (Boolean) values.get(rotateElements);
473
        final Point centerPointValue = (Point) values.get(centerPoint);
474
        final Double elementAngleValue = (Double) values.get(elementAngle);
475

    
476
        if (featureSelection != null && elementsNumberValue != null
477
            && rotateElementsValue != null && centerPointValue != null
478
            && elementAngleValue != null) {
479

    
480
            try {
481
                featureSelection.accept(new Visitor() {
482

    
483
                    public void visit(Object obj)
484
                        throws VisitCanceledException, BaseException {
485

    
486
                        Feature feature = (Feature) obj;
487
                        Geometry geometry = feature.getDefaultGeometry();
488
                        Geometry[] matrix =
489
                            createPolarMatrix(geometry, elementsNumberValue,
490
                                rotateElementsValue, centerPointValue,
491
                                elementAngleValue);
492

    
493
                        for (int i = 0; i < matrix.length; i++) {
494
                            EditableFeature eFeature =
495
                                editingProviderServices
496
                                    .getFeatureCopyWithoutPK(featureStore,
497
                                        feature);
498
                            eFeature.setDefaultGeometry(matrix[i]);
499
                            editingProviderServices
500
                                .insertFeatureIntoFeatureStore(eFeature,
501
                                    featureStore);
502
                        }
503
                    }
504
                });
505
            } catch (BaseException e) {
506
                throw new FinishServiceException(e);
507
            }
508
        }
509
    }
510

    
511
    public void start() throws StartServiceException, InvalidEntryException {
512
        values = new HashMap<EditingServiceParameter, Object>();
513
        FeatureSelection selected = null;
514
        if (featureStore != null && values.get(selection) == null) {
515
            try {
516
                selected = featureStore.getFeatureSelection();
517
            } catch (DataException e) {
518
                throw new StartServiceException(e);
519
            }
520
            if (selected.getSelectedCount() > 0) {
521
                try {
522
                    setValue(selected);
523
                } catch (InvalidEntryException e) {
524
                    throw new InvalidEntryException(e);
525
                }
526
            }
527
        }
528
    }
529

    
530
    public String getName() {
531
        return PolarMatrixEditingProviderFactory.PROVIDER_NAME;
532
    }
533

    
534
    private AffineTransform getMoveAffineTransform(Point p1, Point p2)
535
        throws GeometryOperationNotSupportedException,
536
        GeometryOperationException {
537

    
538
        AffineTransform translate =
539
            AffineTransform.getTranslateInstance(p2.getX() - p1.getX(),
540
                p2.getY() - p1.getY());
541

    
542
        return translate;
543
    }
544

    
545
    private AffineTransform getRotateAffineTransform(Point axisP1, Double angle)
546
        throws GeometryOperationNotSupportedException,
547
        GeometryOperationException {
548

    
549
        AffineTransform translate =
550
            AffineTransform
551
                .getTranslateInstance(-axisP1.getX(), -axisP1.getY());
552

    
553
        AffineTransform rotate = AffineTransform.getRotateInstance(angle);
554

    
555
        AffineTransform inverseTranslate =
556
            AffineTransform.getTranslateInstance(axisP1.getX(), axisP1.getY());
557
        AffineTransform at = new AffineTransform(translate);
558

    
559
        at.preConcatenate(rotate);
560
        at.preConcatenate(inverseTranslate);
561
        return at;
562
    }
563
}