Statistics
| Revision:

gvsig-vectorediting / org.gvsig.vectorediting / trunk / org.gvsig.vectorediting / org.gvsig.vectorediting.lib / org.gvsig.vectorediting.lib.impl / src / main / java / org / gvsig / vectorediting / lib / impl / DefaultEditingProviderServices.java @ 3680

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

    
26
import java.util.Iterator;
27
import java.util.List;
28
import java.util.Map;
29
import java.util.Objects;
30
import org.gvsig.euclidean.EuclideanLine2D;
31
import org.gvsig.expressionevaluator.Expression;
32
import org.gvsig.expressionevaluator.ExpressionUtils;
33
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
34
import org.gvsig.fmap.dal.DALLocator;
35
import org.gvsig.fmap.dal.DataManager;
36
import org.gvsig.fmap.dal.EditingNotification;
37
import org.gvsig.fmap.dal.EditingNotificationManager;
38
import org.gvsig.fmap.dal.exception.DataException;
39
import org.gvsig.fmap.dal.expressionevaluator.DALExpressionBuilder;
40
import org.gvsig.fmap.dal.feature.EditableFeature;
41
import org.gvsig.fmap.dal.feature.Feature;
42
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
43
import org.gvsig.fmap.dal.feature.FeatureSet;
44
import org.gvsig.fmap.dal.feature.FeatureStore;
45
import org.gvsig.fmap.dal.feature.FeatureType;
46
import org.gvsig.fmap.dal.swing.DALSwingLocator;
47
import org.gvsig.fmap.geom.Geometry;
48
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
49
import org.gvsig.fmap.geom.GeometryLocator;
50
import org.gvsig.fmap.geom.GeometryManager;
51
import org.gvsig.fmap.geom.GeometryUtils;
52
import org.gvsig.fmap.geom.exception.CreateGeometryException;
53
import org.gvsig.fmap.geom.operation.GeometryOperationException;
54
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
55
import org.gvsig.fmap.geom.primitive.Arc;
56
import org.gvsig.fmap.geom.primitive.Circle;
57
import org.gvsig.fmap.geom.primitive.Ellipse;
58
import org.gvsig.fmap.geom.primitive.Line;
59
import org.gvsig.fmap.geom.primitive.Point;
60
import org.gvsig.fmap.geom.primitive.Spline;
61
import org.gvsig.fmap.geom.type.GeometryType;
62
import org.gvsig.fmap.mapcontext.MapContext;
63
import org.gvsig.fmap.mapcontext.layers.CancelationException;
64
import org.gvsig.fmap.mapcontext.layers.FLayer;
65
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
66
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
67
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
68
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
69
import org.gvsig.tools.ToolsLocator;
70
import org.gvsig.tools.exception.BaseException;
71
import org.gvsig.tools.i18n.I18nManager;
72
import org.gvsig.tools.lang.CloneableUtils;
73
import org.gvsig.tools.service.spi.AbstractProviderServices;
74
import org.gvsig.tools.swing.api.TransparencySupport;
75
import org.gvsig.vectorediting.lib.api.EditingService;
76
import org.gvsig.vectorediting.lib.api.EditingServiceParameterOptions;
77
import org.gvsig.vectorediting.lib.api.EditingServiceParameterOptions.ParameterOption;
78
import org.gvsig.vectorediting.lib.spi.DefaultDrawingStatus;
79
import org.gvsig.vectorediting.lib.spi.EditingProviderLocator;
80
import org.gvsig.vectorediting.lib.spi.EditingProviderManager;
81
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
82
import org.slf4j.Logger;
83
import org.slf4j.LoggerFactory;
84

    
85
public class DefaultEditingProviderServices extends AbstractProviderServices
86
        implements EditingProviderServices {
87

    
88
    private static final Logger LOGGER = LoggerFactory
89
            .getLogger(DefaultEditingProviderServices.class);
90

    
91
    public DefaultEditingProviderServices() {
92
        super();
93
    }
94

    
95
    @Override
96
    public void insertFeatureIntoFeatureStore(Feature feature,
97
            FeatureStore featureStore) {
98
        EditableFeature eFeature = null;
99
        try {
100

    
101
            if (feature instanceof EditableFeature) {
102
                eFeature = (EditableFeature) feature;
103
            } else {
104
                eFeature = feature.getEditable();
105
            }
106

    
107
            EditingNotificationManager editingNotificationManager
108
                    = DALSwingLocator.getEditingNotificationManager();
109

    
110
            EditingNotification notification
111
                    = editingNotificationManager.notifyObservers(this, // source
112
                            EditingNotification.BEFORE_INSERT_FEATURE, // type
113
                            null,// document
114
                            null,// layer
115
                            featureStore,// store
116
                            eFeature// feature
117
                    );
118

    
119
            if (notification.isCanceled()) {
120
                String msg
121
                        = String
122
                                .format(
123
                                        "Can't insert feature into %1$s, canceled by some observer.",
124
                                        featureStore.getName());
125
                throw new CancelationException(msg, null);
126
            }
127

    
128
            if (notification.shouldValidateTheFeature()) {
129
                if (!editingNotificationManager.validateFeature(eFeature)) {
130
                    String msg
131
                            = String.format("%1$s is not valid", eFeature.toString());
132
                    throw new Exception(msg);
133
                }
134
            }
135

    
136
            featureStore.insert(eFeature);
137

    
138
            editingNotificationManager.notifyObservers(this,
139
                    EditingNotification.AFTER_INSERT_FEATURE, null, null,
140
                    featureStore, eFeature);
141

    
142
        } catch (Exception e) {
143
            String msg
144
                    = String.format("Can't insert %1$s into %2$s",
145
                            eFeature.toString(), featureStore.getName());
146
            LOGGER.info(msg, e);
147
        }
148
    }
149

    
150
    @Override
151
    public EditableFeature createNewFeature(FeatureStore store){
152
        try {
153
            EditableFeature f = store.createNewFeature();
154
            //FIXME: ?Deber?amos saltarnos la geometr?a?
155
            f.copyFrom(this.getDefaultFeatureValues(),(FeatureAttributeDescriptor t) -> !(t.isPrimaryKey() || (t.isIndexed() && !t.allowIndexDuplicateds())));
156
            return f;
157
        } catch (DataException ex) {
158
            throw new RuntimeException("Can't create feature", ex);
159
        }
160
    }
161

    
162
    @Override
163
    public void insertGeometryIntoFeatureStore(Geometry geometry,
164
            FeatureStore featureStore) {
165
        EditableFeature eFeature = null;
166

    
167
        try {
168
            eFeature = this.createNewFeature(featureStore);
169

    
170
            eFeature.setGeometry(featureStore.getDefaultFeatureType()
171
                    .getDefaultGeometryAttributeName(), geometry);
172

    
173
            EditingNotificationManager editingNotificationManager
174
                    = DALSwingLocator.getEditingNotificationManager();
175

    
176
            EditingNotification notification
177
                    = editingNotificationManager.notifyObservers(this, // source
178
                            EditingNotification.BEFORE_INSERT_FEATURE, // type
179
                            null,// document
180
                            null,// layer
181
                            featureStore,// store
182
                            eFeature// feature
183
                    );
184

    
185
            if (notification.isCanceled()) {
186
                String msg
187
                        = String
188
                                .format(
189
                                        "Can't insert geometry into %1$s, canceled by some observer.",
190
                                        featureStore.getName());
191
                throw new CancelationException(msg, null);
192
            }
193

    
194
            if (notification.shouldValidateTheFeature()) {
195
                if (!editingNotificationManager.validateFeature(eFeature)) {
196
                    String msg
197
                            = String.format("%1$s is not valid", eFeature.toString());
198
                    throw new Exception(msg);
199
                }
200
            }
201

    
202
            featureStore.insert(eFeature);
203

    
204
            editingNotificationManager.notifyObservers(this,
205
                    EditingNotification.AFTER_INSERT_FEATURE, null, null,
206
                    featureStore, eFeature);
207

    
208
        } catch (Exception e) {
209
            String msg
210
                    = String.format("Can't insert %1$s into %2$s",
211
                            Objects.toString(eFeature), featureStore.getName());
212
            LOGGER.info(msg, e);
213
        }
214
    }
215

    
216
    @Override
217
    public void deleteFeatureFromFeatureSet(Feature feature,
218
            FeatureStore featureStore, FeatureSet set) {
219

    
220
        try {
221
            EditingNotificationManager editingNotificationManager
222
                    = DALSwingLocator.getEditingNotificationManager();
223

    
224
            EditingNotification notification
225
                    = editingNotificationManager.notifyObservers(this, // source
226
                            EditingNotification.BEFORE_REMOVE_FEATURE, // type
227
                            null,// document
228
                            null,// layer
229
                            featureStore,// store
230
                            feature// feature
231
                    );
232

    
233
            if (notification.isCanceled()) {
234
                String msg
235
                        = String
236
                                .format(
237
                                        "Can't delete feature from %1$s, canceled by some observer.",
238
                                        featureStore.getName());
239
                throw new CancelationException(msg, null);
240
            }
241

    
242
            set.delete(feature);
243

    
244
            editingNotificationManager.notifyObservers(this,
245
                    EditingNotification.AFTER_REMOVE_FEATURE, null, null,
246
                    featureStore, feature);
247

    
248
        } catch (Exception e) {
249
            LOGGER.warn(e.getMessage(), e);
250
        }
251
    }
252

    
253
    @Override
254
    public void deleteFeatureFromFeatureStore(Feature feature,
255
            FeatureStore featureStore) {
256

    
257
        try {
258
            EditingNotificationManager editingNotificationManager
259
                    = DALSwingLocator.getEditingNotificationManager();
260

    
261
            EditingNotification notification
262
                    = editingNotificationManager.notifyObservers(this, // source
263
                            EditingNotification.BEFORE_REMOVE_FEATURE, // type
264
                            null,// document
265
                            null,// layer
266
                            featureStore,// store
267
                            feature// feature
268
                    );
269

    
270
            if (notification.isCanceled()) {
271
                String msg
272
                        = String
273
                                .format(
274
                                        "Can't delete feature from %1$s, canceled by some observer.",
275
                                        featureStore.getName());
276
                throw new CancelationException(msg, null);
277
            }
278

    
279
            featureStore.delete(feature);
280

    
281
            editingNotificationManager.notifyObservers(this,
282
                    EditingNotification.AFTER_REMOVE_FEATURE, null, null,
283
                    featureStore, feature);
284

    
285
        } catch (Exception e) {
286
            LOGGER.warn(e.getMessage(), e);
287
        }
288
    }
289

    
290
    @Override
291
    public void updateFeatureInFeatureStore(Feature feature,
292
            FeatureStore featureStore) {
293
        EditableFeature eFeature = null;
294

    
295
        try {
296

    
297
            if (feature instanceof EditableFeature) {
298
                eFeature = (EditableFeature) feature;
299
            } else {
300
                eFeature = feature.getEditable();
301
            }
302

    
303
            EditingNotificationManager editingNotificationManager
304
                    = DALSwingLocator.getEditingNotificationManager();
305

    
306
            EditingNotification notification
307
                    = editingNotificationManager.notifyObservers(this, // source
308
                            EditingNotification.BEFORE_UPDATE_FEATURE, // type
309
                            null,// document
310
                            null,// layer
311
                            featureStore,// store
312
                            eFeature// feature
313
                    );
314

    
315
            if (notification.isCanceled()) {
316
                String msg
317
                        = String
318
                                .format(
319
                                        "Can't update feature in %1$s, canceled by some observer.",
320
                                        featureStore.getName());
321
                throw new CancelationException(msg, null);
322
            }
323

    
324
            if (notification.shouldValidateTheFeature()) {
325
                if (!editingNotificationManager.validateFeature(eFeature)) {
326
                    String msg
327
                            = String.format("%1$s is not valid", eFeature.toString());
328
                    throw new Exception(msg);
329
                }
330
            }
331

    
332
            featureStore.update(eFeature);
333
            editingNotificationManager.notifyObservers(this,
334
                    EditingNotification.AFTER_UPDATE_FEATURE, null, null,
335
                    featureStore, eFeature);
336

    
337
        } catch (Exception e) {
338
            String msg
339
                    = String.format("Can't update %1$s in %2$s", eFeature.toString(),
340
                            featureStore.getName());
341
            LOGGER.info(msg, e);
342
        }
343
    }
344

    
345
    @Override
346
    public Circle createCircle(Point center, double radius, int subtype)
347
            throws CreateGeometryException {
348
        return GeometryUtils.createCircle(center, radius, subtype);
349
    }
350

    
351
    @Override
352
    public Circle createCircle(Point firstPoint, Point secondPoint,
353
            Point thridPoint, int subtype) throws CreateGeometryException {
354
        return GeometryUtils.createCircle(firstPoint, secondPoint, thridPoint, subtype);
355
    }
356

    
357
    @Override
358
    public Arc createArc(Point center, double radius, double startAngle,
359
            double angleExt, int subtype) throws CreateGeometryException {
360
        return GeometryUtils.createArc(center, radius, startAngle, angleExt, subtype);
361
    }
362

    
363
    @Override
364
    public Ellipse createFilledEllipse(Point firstPointAxisA,
365
            Point secondPointAxisA, double halfLengthAxisB, int subtype)
366
            throws CreateGeometryException {
367
        return GeometryUtils.createFilledEllipse(firstPointAxisA, secondPointAxisA, halfLengthAxisB, subtype);
368
    }
369

    
370
    @Override
371
    public Arc createArc(Point start, Point middle, Point end, int subtype)
372
            throws BaseException {
373
        return GeometryUtils.createArc(start, middle, end, subtype);
374
    }
375

    
376
    @Override
377
    public Point createPoint(double x, double y, int subtype)
378
            throws CreateGeometryException {
379
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
380
        return geomManager.createPoint(x, y, subtype);
381
    }
382

    
383
    @Override
384
    public Line createLine(double x1, double y1, double x2, double y2,
385
            int subtype) throws CreateGeometryException {
386
        return GeometryUtils.createLine(x1, y1, x2, y2, subtype);
387
    }
388

    
389
    @Override
390
    public int getSubType(FeatureStore featureStore) throws DataException {
391

    
392
        GeometryType geomType = getGeomType(featureStore);
393
        if (geomType != null) {
394
            return geomType.getSubType();
395
        }
396
        return SUBTYPES.UNKNOWN;
397
    }
398

    
399
    @Override
400
    public GeometryType getGeomType(FeatureStore featureStore)
401
            throws DataException {
402
        return featureStore.getDefaultFeatureType()
403
                .getDefaultGeometryAttribute().getGeomType();
404
    }
405

    
406
    @Override
407
    public EditableFeature getFeatureCopyWithoutUniqueIndex(FeatureStore featureStore,
408
            Feature feature) throws DataException {
409
        EditableFeature editableFeature
410
                = featureStore.createNewFeature(feature.getType(), true);
411
        editableFeature.copyFrom(this.getDefaultFeatureValues(), (FeatureAttributeDescriptor t) -> !(t.isPrimaryKey() || (t.isIndexed() && !t.allowIndexDuplicateds())));
412
        
413
        editableFeature.copyFrom(feature, (FeatureAttributeDescriptor t) -> !(t.isPrimaryKey() || (t.isIndexed() && !t.allowIndexDuplicateds())));
414
        return editableFeature;
415
    }
416

    
417
    @Override
418
    public Point getCenter(Point a, Point b, Point c, int subtype)
419
            throws CreateGeometryException {
420
        return GeometryUtils.getCenter(a, b, c, subtype);
421
    }
422

    
423
    @Override
424
    public Point getMidPoint(Point a, Point b, int subtype)
425
            throws CreateGeometryException {
426
        return GeometryUtils.getMidPoint(a, b, subtype);
427
    }
428

    
429
    @Override
430
    public Double[] getLineParams(Point point, Point nextPoint) {
431
        Double[] lineParams = new Double[2];
432
        double denom = nextPoint.getX() - point.getX();
433
        if (denom != 0) {
434
            lineParams[0] = (nextPoint.getY() - point.getY()) / denom;
435
            lineParams[1] = point.getY() - (lineParams[0] * point.getX());
436
        } else {
437
            if (nextPoint.getY() >= point.getY()) {
438
                lineParams[0] = Double.POSITIVE_INFINITY;
439
                lineParams[1] = Double.NEGATIVE_INFINITY;
440
                if (point.getX() == 0) {
441
                    lineParams[1] = 0.0;
442
                }
443
            } else {
444
                lineParams[0] = Double.NEGATIVE_INFINITY;
445
                lineParams[1] = Double.POSITIVE_INFINITY;
446
                if (point.getX() == 0) {
447
                    lineParams[1] = 0.0;
448
                }
449
            }
450
        }
451
        return lineParams;
452
    }
453

    
454
    @Override
455
    public Point[] getPerpendicular(Double m, Double b, Point point, int subtype)
456
            throws CreateGeometryException {
457
        // Pendiente de la recta perpendicular
458
        Double m1 = -1 / m;
459

    
460
        // b de la funcion de la recta perpendicular
461
        Double b1 = point.getY() - (m1 * point.getX());
462

    
463
        // Obtenemos un par de puntos
464
        Point[] res = new Point[2];
465

    
466
        if (Double.isInfinite(m1)) {
467
            if (m1 > 0) {
468
                //return the director vector of the line
469
                res[0] = createPoint(point.getX(), 0.0, subtype);
470
                res[1] = createPoint(point.getX(), 1.0, subtype);
471
            } else {
472
                res[0] = createPoint(point.getX(), 0.0, subtype);
473
                res[1] = createPoint(point.getX(), -1.0, subtype);
474
            }
475
        } else {
476
            //return the director vector of the line
477
            res[0] = createPoint(0.0, b1, subtype);
478
            Double mod = Math.sqrt(1 + Math.pow(m1, 2));
479
            Double x = 1 / mod;
480
            Double y = m1 * x + b1;
481
            res[1] = createPoint(x, y, subtype);
482
        }
483

    
484
        return res;
485
    }
486

    
487
    @Override
488
    public Point getIntersection(Point[] lineA, Point[] lineB, int subtype)
489
            throws CreateGeometryException {
490
        Point p1 = lineA[0];
491
        Point p2 = lineA[1];
492
        Point p3 = lineB[0];
493
        Point p4 = lineB[1];
494

    
495
        double m1 = Double.POSITIVE_INFINITY;
496

    
497
        if ((p2.getX() - p1.getX()) != 0) {
498
            m1 = (p2.getY() - p1.getY()) / (p2.getX() - p1.getX());
499
        }
500

    
501
        double m2 = Double.POSITIVE_INFINITY;
502

    
503
        if ((p4.getX() - p3.getX()) != 0) {
504
            m2 = (p4.getY() - p3.getY()) / (p4.getX() - p3.getX());
505
        }
506

    
507
        if ((m1 == Double.POSITIVE_INFINITY)
508
                && (m2 == Double.POSITIVE_INFINITY)) {
509
            return null;
510
        }
511

    
512
        double b1 = p2.getY() - (m1 * p2.getX());
513

    
514
        double b2 = p4.getY() - (m2 * p4.getX());
515

    
516
        if ((m1 != Double.POSITIVE_INFINITY)
517
                && (m2 != Double.POSITIVE_INFINITY)) {
518
            if (m1 == m2) {
519
                return null;
520
            }
521

    
522
            double x = (b2 - b1) / (m1 - m2);
523

    
524
            return createPoint(x, (m1 * x) + b1, subtype);
525
        } else if (m1 == Double.POSITIVE_INFINITY) {
526
            double x = p1.getX();
527

    
528
            return createPoint(x, (m2 * x) + b2, subtype);
529
        } else if (m2 == Double.POSITIVE_INFINITY) {
530
            double x = p3.getX();
531

    
532
            return createPoint(x, (m1 * x) + b1, subtype);
533
        }
534

    
535
        return null;
536
    }
537

    
538
    @Override
539
    public double getAngle(Point start, Point end)
540
            throws GeometryOperationNotSupportedException,
541
            GeometryOperationException {
542
        double angle
543
                = Math.acos((end.getX() - start.getX()) / start.distance(end));
544

    
545
        if (start.getY() > end.getY()) {
546
            angle = -angle;
547
        }
548

    
549
        if (angle < 0) {
550
            angle += (2 * Math.PI);
551
        }
552

    
553
        return angle;
554
    }
555

    
556
    @Override
557
    public double angleDistance(double angle1, double angle2) {
558
        double result = angle2 - angle1;
559
        if (result < 0) {
560
            result = (Math.PI * 2) + result;
561
        }
562
        return result;
563
    }
564

    
565
    @Override
566
    public Line createLine(Point p1, Point p2, int subtype)
567
            throws CreateGeometryException {
568
        return GeometryUtils.createLine(p1, p2, subtype);
569
    }
570

    
571
    @Override
572
    public Spline createSpline(List<Point> points, int subtype)
573
            throws CreateGeometryException {
574
        return GeometryUtils.createSpline(points, subtype);
575
    }
576

    
577
    @Override
578
    public String makeConsoleMessage(String preText, Map<String, String> options) {
579

    
580
        I18nManager i18nManager = ToolsLocator.getI18nManager();
581

    
582
        StringBuilder stb = new StringBuilder();
583

    
584
        if (preText != null) {
585
            stb.append(i18nManager.getTranslation(preText));
586
            stb.append(" ");
587
        }
588

    
589
        for (String option : options.keySet()) {
590
            stb.append("[");
591
            stb.append(option);
592
            stb.append("]");
593
            stb.append(i18nManager.getTranslation(options.get(option)));
594
            stb.append(" ");
595
        }
596

    
597
        return stb.toString();
598
    }
599

    
600
    @Override
601
    public String makeConsoleMessage(String preText, EditingServiceParameterOptions options) {
602

    
603
        I18nManager i18nManager = ToolsLocator.getI18nManager();
604

    
605
        StringBuilder stb = new StringBuilder();
606

    
607
        if (preText != null) {
608
            stb.append(i18nManager.getTranslation(preText));
609
            stb.append(" ");
610
        }
611
        
612
        for (ParameterOption option : options) {
613
            stb.append("[");
614
            stb.append(option.getConsoleValue());
615
            stb.append("]");
616
            stb.append(i18nManager.getTranslation(option.getLabel()));
617
            stb.append(" ");
618
        }
619

    
620
        return stb.toString();
621
    }
622

    
623
    @Override
624
    public Arc createEllipse(Point firstPointAxisA, Point secondPointAxisA,
625
            double halfLengthAxisB, int subtype) throws CreateGeometryException {
626
        return GeometryUtils.createEllipse(firstPointAxisA, secondPointAxisA, halfLengthAxisB, subtype);
627
    }
628

    
629
    @Override
630
    public Circle createCircle(Point firstPoint, Point secondPoint, Point thirdPoint, Point fourthPoint, Point fifthPoint, int subtype) throws CreateGeometryException {
631
        return GeometryUtils.createCircle(firstPoint, secondPoint, thirdPoint, fourthPoint, fifthPoint, subtype);
632
    }
633

    
634
    @Override
635
    public Circle createCircle(EuclideanLine2D line1, EuclideanLine2D line2, Point point, int subtype) throws CreateGeometryException {
636
        return GeometryUtils.createCircle(line1, line2, point, subtype);
637
    }
638

    
639
    @Override
640
    public Circle createCircle(Geometry geometry1, Geometry geometry2, double radius, Point firstPoint, Point secondPoint, int subtype) throws CreateGeometryException {
641
        return GeometryUtils.createCircle(geometry1, geometry2, radius, firstPoint, secondPoint, subtype);
642
    }
643

    
644
    @Override
645
    public Feature getFeature(Point point, FeatureStore store, MapContext mapContext) {
646
        Feature feature = null;
647
        try {
648
            double tolerance = mapContext.getViewPort().toMapDistance(mapContext.getLayers().getDefaultTolerance());
649
            Geometry buffer = point.buffer(tolerance);
650

    
651
            DataManager dataManager = DALLocator.getDataManager();
652
            DALExpressionBuilder dalBuilder = dataManager.createDALExpressionBuilder();
653
            GeometryExpressionBuilder builder = dalBuilder.expression();
654

    
655
            FeatureType featureType = store.getDefaultFeatureType();
656
            
657
            String filter = builder.ST_Intersects(
658
                    builder.geometry(
659
                            buffer, mapContext.getProjection()
660
                    ), 
661
                    builder.column(featureType.getDefaultGeometryAttributeName())
662
            ).toString();
663
            String sortBy = builder.ST_Distance(
664
                    builder.geometry(buffer), 
665
                    builder.column(featureType.getDefaultGeometryAttributeName())
666
            ).toString();
667
            Expression sortByExpression = ExpressionUtils.createExpression(sortBy);
668

    
669
            feature = store.findFirst(filter, sortByExpression, true);
670

    
671
        } catch (Exception ex) {
672
            LOGGER.warn("Can't get feature on point (" + point.getX() + "," + point.getY(), ex);
673
        }
674

    
675
        return feature;
676
    }
677

    
678
    @Override
679
    public Geometry getGeometry(Point point, FeatureStore store, MapContext mapContext) {
680
        return getGeometryOfVisibleLayers(point, store, mapContext, null);
681
    }
682
    
683
    @Override
684
    public Geometry getGeometry(Point point, FeatureStore store, MapContext mapContext, List<Feature> excludeFeatures) {
685
        Geometry geometry = null;
686
        try {
687
//            Feature f = getFeature(point, store, mapContext);
688
//            if (f != null) {
689
//                geometry = f.getDefaultGeometry();
690
//            }
691

    
692
            double tolerance = mapContext.getViewPort().toMapDistance(mapContext.getLayers().getDefaultTolerance());
693
            Geometry buffer = point.buffer(tolerance);
694
            FLyrVect layer = (FLyrVect) mapContext.getLayers().getLayer(store);
695
            SpatialCache sc = layer.getSpatialCache();
696
            if(sc.isOverflown()){
697
                LOGGER.warn("Spatial Cache overflown. Limit = "+sc.getMaxFeatures()+". You must increase limit or zoom in.");
698
            }
699
                
700
            List<Geometry> geometries = sc.query(buffer.getEnvelope());
701
            if( geometries!=null ) {
702
                double minDistance = Double.POSITIVE_INFINITY;
703
                for (Geometry geom : geometries) {
704
                    boolean found = false;
705
                    if( excludeFeatures!=null ) {
706
                        for (Feature excludeFeature : excludeFeatures) {
707
                            if (excludeFeature.getStore() == store) {
708
                                if(excludeFeature.getDefaultGeometry().equals(geom)){
709
                                    found = true;
710
                                }
711
                            }
712
                        }
713
                    }
714
                    if(found){
715
                        continue;
716
                    }
717
                    if(geom.intersects(buffer)){
718
                        double distance = geom.distance(point);
719
                        if(distance<minDistance){
720
                            minDistance = distance;
721
                            geometry = geom;
722
                        }
723
                    }
724
                }
725
            }
726
        } catch (Exception ex) {
727
            LOGGER.warn("Can't get geometry on point (" + point.getX() + "," + point.getY(), ex);
728
        }
729

    
730
        return geometry;
731
    }
732

    
733
    @Override
734
    public Geometry getGeometryOfVisibleLayers(Point point, FeatureStore store, MapContext mapContext) {
735
        return getGeometryOfVisibleLayers(point, store, mapContext, null);
736
    }
737
    
738
    @Override
739
    public Geometry getGeometryOfVisibleLayers(Point point, FeatureStore store, MapContext mapContext, List<Feature> excludeFeatures) {
740

    
741
        // Search in the store itself
742
        Geometry geometry = this.getGeometry(point, store, mapContext, excludeFeatures);
743
        // Search in the store for the layers that are in edit
744
        if (geometry == null) {
745
            for (Iterator<FLayer> iterator = mapContext.getLayers().deepiterator(); iterator.hasNext();) {
746
                FLayer layer = iterator.next();
747
                if (layer instanceof FLyrVect) {
748
                    FLyrVect vectLayer = (FLyrVect) layer;
749
                    if (vectLayer.getFeatureStore() != store && vectLayer.isEditing()) {
750
                        geometry = this.getGeometry(point, vectLayer.getFeatureStore(), mapContext, excludeFeatures);
751
                        if (geometry != null) {
752
                            break;
753
                        }
754
                    }
755
                }
756
            }
757
        }
758
        // Search in the store for the active layers
759
        if (geometry == null) {
760
            FLayer[] activeLayers = mapContext.getLayers().getActives();
761
            for (FLayer activeLayer : activeLayers) {
762
                if (activeLayer instanceof FLyrVect) {
763
                    FLyrVect activeVectLayer = (FLyrVect) activeLayer;
764
                    if (activeVectLayer.getFeatureStore() != store && !activeVectLayer.isEditing()) {
765
                        geometry = this.getGeometry(point, activeVectLayer.getFeatureStore(), mapContext, excludeFeatures);
766
                        if (geometry != null) {
767
                            break;
768
                        }
769
                    }
770
                }
771
            }
772
        }
773
        return geometry;
774
    }
775

    
776
    @Override
777
    public void addAngleToDrawingStatus(DefaultDrawingStatus drawingStatus, ISymbol textSymbol, Point vertex, Point ray1, Point ray2, int subtype) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException {
778
        EditingProviderManager editingProviderManager
779
                = EditingProviderLocator.getProviderManager();
780
        ISymbol auxiliaryLineSymbolEditing = editingProviderManager.getSymbol("auxiliary-line-symbol-editing");
781

    
782
        double angleRay1 = GeometryUtils.calculateAngle(vertex, ray1);
783
        double angle = GeometryUtils.calculateAngle(vertex, ray1, ray2);
784
        double radius = vertex.distance(ray1) / 4;
785
        Arc auxArc = GeometryUtils.createArc(
786
                vertex,
787
                radius,
788
                GeometryUtils.calculateAngle(vertex, ray1),
789
                angle,
790
                subtype
791
        );
792
        drawingStatus.addStatus(auxArc, auxiliaryLineSymbolEditing, "");
793

    
794
        Point measurePoint = GeometryUtils.createPoint(vertex, radius, angleRay1 + angle / 2);
795

    
796
//        drawingStatus.addStatus(measurePoint, textSymbol, GeometryUtils.formatAngle("%2d\u00B0 %2m\u2032", Math.toDegrees(angle)));
797
        drawingStatus.addStatus(measurePoint, textSymbol, GeometryUtils.formatAngle("%5.3D\u00B0", Math.toDegrees(angle)));
798

    
799
    }
800
    
801
    private EditableFeature defaultFeatureValues;
802
    
803
    @Override
804
    public void setDefaultFeatureValues(EditableFeature feature) {
805
        this.defaultFeatureValues = feature;
806
    }
807

    
808
    @Override
809
    public EditableFeature getDefaultFeatureValues() {
810
        if(defaultFeatureValues == null){
811
            try {
812
                FeatureStore store = this.getService().getStore();
813
                this.defaultFeatureValues = store.createNewFeature(true);
814
//                Feature f = store.getSampleFeature();
815
//                this.defaultFeatureValues.copyFrom(f,
816
//                        (FeatureAttributeDescriptor t) -> t.isPrimaryKey() 
817
//                                ||  t.isReadOnly() 
818
//                                || (t.isIndexed() && !t.allowIndexDuplicateds())
819
//                );
820
            } catch (DataException ex) {
821
                throw new RuntimeException("Can't create default feature values.", ex);
822
            }
823
        }
824
        return this.defaultFeatureValues;
825
    }
826

    
827
    @Override
828
    public ISymbol getPreviewSymbol() {
829
        try {
830
            IVectorLegend legend = this.getService().getLegend();
831
            ISymbol symbol = legend.getSymbolByFeature(getDefaultFeatureValues());
832
            if(!(symbol instanceof TransparencySupport)) {
833
                return null;
834
            }
835
            symbol = (ISymbol) CloneableUtils.cloneQuietly(symbol);
836
            ((TransparencySupport) symbol).setTransparency(0.5);
837
            return symbol;
838
        } catch (Exception e) {
839
            return null;
840
        }
841
    }
842

    
843
    @Override
844
    public ISymbol getPreviewSymbol(Feature feature) {
845
        try {
846
            IVectorLegend legend = this.getService().getLegend();
847
            ISymbol symbol = legend.getSymbolByFeature(feature);
848
            if(!(symbol instanceof TransparencySupport)) {
849
                return null;
850
            }
851
            symbol = (ISymbol) CloneableUtils.cloneQuietly(symbol);
852
            ((TransparencySupport) symbol).setTransparency(0.5);
853
            return symbol;
854
        } catch (Exception e) {
855
            return null;
856
        }
857
    }
858

    
859
    @Override
860
    public EditingService getService() {
861
        return (EditingService) super.getService();
862
    }
863
    
864
}