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.polyline / src / main / java / org / gvsig / vectorediting / lib / prov / polyline / PolylineEditingProvider.java @ 575

History | View | Annotate | Download (21.2 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2014 gvSIG Association
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

    
25
package org.gvsig.vectorediting.lib.prov.polyline;
26

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

    
32
import org.gvsig.fmap.dal.exception.DataException;
33
import org.gvsig.fmap.dal.feature.FeatureStore;
34
import org.gvsig.fmap.geom.Geometry;
35
import org.gvsig.fmap.geom.GeometryException;
36
import org.gvsig.fmap.geom.GeometryLocator;
37
import org.gvsig.fmap.geom.GeometryManager;
38
import org.gvsig.fmap.geom.aggregate.MultiCurve;
39
import org.gvsig.fmap.geom.aggregate.MultiLine;
40
import org.gvsig.fmap.geom.operation.GeometryOperationException;
41
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
42
import org.gvsig.fmap.geom.primitive.Arc;
43
import org.gvsig.fmap.geom.primitive.Curve;
44
import org.gvsig.fmap.geom.primitive.Line;
45
import org.gvsig.fmap.geom.primitive.OrientablePrimitive;
46
import org.gvsig.fmap.geom.primitive.Point;
47
import org.gvsig.fmap.geom.primitive.Surface;
48
import org.gvsig.fmap.geom.type.GeometryType;
49
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
50
import org.gvsig.tools.ToolsLocator;
51
import org.gvsig.tools.dynobject.DynObject;
52
import org.gvsig.tools.exception.BaseException;
53
import org.gvsig.tools.i18n.I18nManager;
54
import org.gvsig.tools.service.spi.ProviderServices;
55
import org.gvsig.vectorediting.lib.api.DrawingStatus;
56
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
57
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
58
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
59
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
60
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
61
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
62
import org.gvsig.vectorediting.lib.api.exceptions.VectorEditingException;
63
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
64
import org.gvsig.vectorediting.lib.spi.DefaultDrawingStatus;
65
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
66
import org.gvsig.vectorediting.lib.spi.EditingProvider;
67
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
68
import org.gvsig.vectorediting.lib.spi.EditingProviderLocator;
69
import org.gvsig.vectorediting.lib.spi.EditingProviderManager;
70
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
71

    
72
public class PolylineEditingProvider extends AbstractEditingProvider implements EditingProvider {
73

    
74
    protected EditingProviderServices editingProviderServices = (EditingProviderServices) getProviderServices();
75

    
76
    protected EditingServiceParameter points;
77

    
78
    protected Map<String, String> options;
79

    
80
    private boolean arcMode;
81

    
82
    private boolean finishPolyline;
83

    
84
    private boolean closeGeometry;
85

    
86
    private List<MyPolyLinePoint> values;
87

    
88
    protected FeatureStore featureStore;
89

    
90
    public PolylineEditingProvider(ProviderServices providerServices, DynObject parameters) {
91
        super(providerServices);
92

    
93
        // Initialize all provider variables.
94
        this.featureStore = (FeatureStore) parameters.getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
95

    
96
        I18nManager i18nManager = ToolsLocator.getI18nManager();
97

    
98
        options = new LinkedHashMap<String, String>();
99
        options.put(i18nManager.getTranslation("key_arc_mode"), "arc_mode");
100
        options.put(i18nManager.getTranslation("key_line_mode"), "line_mode");
101
        options.put(i18nManager.getTranslation("key_close"), "close_polyline");
102
        options.put(i18nManager.getTranslation("key_finish"), "finish");
103
        options.put(i18nManager.getTranslation("key_remove_last_point"), "remove_last_point");
104

    
105
        String consoleMsg = editingProviderServices.makeConsoleMessage("indicate_new_point", options);
106

    
107
        points =
108
            new DefaultEditingServiceParameter("insert_point", consoleMsg, options, TYPE.LIST_POSITIONS, TYPE.OPTION);
109

    
110
        arcMode = false;
111
        finishPolyline = false;
112
        closeGeometry = false;
113
    }
114

    
115
    /**
116
     * Calculates polyline with stored values and last position received as
117
     * parameter. If last position is null calculates only with stored values.
118
     *
119
     * @param lastPosition
120
     *            of polyline.
121
     * @return A drawing status value with a list of geometries. See
122
     *         {@link DrawingStatus#getGeometries()}.
123
     */
124
    private DrawingStatus calculatePolyline(Point lastPosition) throws VectorEditingException {
125
        DefaultDrawingStatus drawingStatus = new DefaultDrawingStatus();
126
        EditingProviderManager editingProviderManager = EditingProviderLocator.getProviderManager();
127
        ISymbol lineSymbolEditing = editingProviderManager.getSymbol("line-symbol-editing");
128
        ISymbol auxiliaryLineSymbolEditing = editingProviderManager.getSymbol("auxiliary-line-symbol-editing");
129
        ISymbol auxiliaryPointSymbolEditing = editingProviderManager.getSymbol("auxiliary-point-symbol-editing");
130

    
131
        Double antm = null;
132
        Double antb = null;
133
        Double m = null;
134
        Double b = null;
135
        Point center = null;
136
        double radius = 0.0;
137
        double startAngle = 0.0;
138
        double endAngle = 0.0;
139
        double angleExt = 0.0;
140
        boolean right = false;
141
        boolean addGeom = false;
142

    
143
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
144

    
145
        Curve lineAntPointToPoint = null;
146

    
147
        if (values.size() >= 1) {
148
            for (int i = 0; i < values.size(); i++) {
149

    
150
                MyPolyLinePoint polyLinePoint = values.get(i);
151
                MyPolyLinePoint polyLineNextPoint = getNextPoint(i);
152

    
153
                Point point = polyLinePoint.getPoint();
154
                Point nextPoint;
155

    
156
                if (polyLineNextPoint == null) {
157
                    nextPoint = lastPosition;
158
                    addGeom = true;
159
                } else {
160
                    nextPoint = polyLineNextPoint.getPoint();
161
                }
162

    
163
                if (nextPoint == null) {
164
                    return drawingStatus;
165
                }
166
                try {
167
                    if (polyLinePoint.isArcMode()) {
168
                        EditingProviderServices editingProviderServices =
169
                            ((EditingProviderServices) getProviderServices());
170
                        int subtype = editingProviderServices.getSubType(featureStore);
171

    
172
                        lineAntPointToPoint = editingProviderServices.createLine(point, nextPoint, subtype);
173

    
174
                        Double[] lineParams = editingProviderServices.getLineParams(point, nextPoint);
175
                        m = lineParams[0];
176
                        b = lineParams[1];
177

    
178
                        Point[] pointPerpendicular =
179
                            editingProviderServices.getPerpendicular(antm, antb, point, subtype);
180
                        Line linePointPerpendicular = geomManager.createLine(subtype);
181
                        linePointPerpendicular.setPoints(pointPerpendicular[0], pointPerpendicular[1]);
182

    
183
                        Point midPoint = editingProviderServices.getMidPoint(point, nextPoint, subtype);
184
                        Point[] bisector = editingProviderServices.getPerpendicular(m, b, midPoint, subtype);
185
                        Line lineBisector = geomManager.createLine(subtype);
186
                        lineBisector.setPoints(bisector[0], bisector[1]);
187

    
188
                        center = editingProviderServices.getIntersection(bisector, pointPerpendicular, subtype);
189

    
190
                        if (center != null) {
191
                            startAngle = editingProviderServices.getAngle(center, point);
192
                            endAngle = editingProviderServices.getAngle(center, nextPoint);
193

    
194
                            radius = center.distance(point);
195
                        } else {
196
                            String msg =
197
                                String.format("Can't get intersection between bisector" + " [(%1$s,%2$s),(%3$s,%4$s)]"
198
                                    + " and perperdicular" + " [(%5$s,%6$s),(%7$s,%8$s)]", bisector[0].getX(),
199
                                    bisector[0].getY(), bisector[1].getX(), bisector[1].getY(),
200
                                    pointPerpendicular[0].getX(), pointPerpendicular[0].getY(),
201
                                    pointPerpendicular[1].getX(), pointPerpendicular[1].getY());
202

    
203
                            throw new DrawServiceException(msg, null);
204
                        }
205

    
206
                        Double[] lineCenterNextParams = editingProviderServices.getLineParams(center, nextPoint);
207
                        double mcn = lineParams[0];
208
                        double bcn = lineParams[1];
209

    
210
                        if (right) {
211
                            if (m >= antm) {
212
                                    if(mcn >= antm){
213
                                        angleExt = -editingProviderServices.angleDistance(startAngle, endAngle);
214
                                    } else {
215
                                        angleExt = editingProviderServices.angleDistance(endAngle, startAngle);
216
                                    }
217
                                right = !(nextPoint.getY() >= center.getY());
218
                            } else {
219
                                angleExt = -editingProviderServices.angleDistance(startAngle, endAngle);
220
                                right = (nextPoint.getY() >= center.getY());
221
                            }
222
                        } else {
223
                            if (m >= antm) {
224
                                angleExt = editingProviderServices.angleDistance(endAngle, startAngle);
225
                                right = !(nextPoint.getY() >= center.getY());
226
                            } else {
227
                                angleExt = -editingProviderServices.angleDistance(startAngle, endAngle);
228
                                right = (nextPoint.getY() >= center.getY());
229
                            }
230
                        }
231

    
232
                        Arc arco = null;
233
                        arco = editingProviderServices.createArc(center, radius, startAngle, angleExt, Geometry.SUBTYPES.GEOM2D);
234
//                        Arc inverseArc = (Arc) geomManager.create(Geometry.TYPES.ARC, subtype);
235
//                        inverseArc.setPoints(arco.getEndPoint(), arco.getMiddlePoint(), arco.getInitPoint());
236
//                        arco = inverseArc;
237

    
238
                        antm = -(nextPoint.getX() - center.getX()) / (nextPoint.getY() - center.getY());
239
                        if (antm == Double.POSITIVE_INFINITY) {
240
                            antb = Double.NEGATIVE_INFINITY;
241
                            if (nextPoint.getX() == 0) {
242
                                antb = 0.0;
243
                            }
244
                        } else if (antm == Double.NEGATIVE_INFINITY) {
245
                            antb = Double.POSITIVE_INFINITY;
246
                            if (nextPoint.getX() == 0) {
247
                                antb = 0.0;
248
                            }
249
                        } else {
250
                            antb = nextPoint.getY() - (antm * nextPoint.getX());
251
                        }
252

    
253
                        // Draw geometries.
254
                        if (addGeom) {
255
                            drawingStatus.addStatus(point, auxiliaryPointSymbolEditing, "");
256
                            drawingStatus.addStatus(nextPoint, auxiliaryPointSymbolEditing, "");
257
                            drawingStatus.addStatus(center, auxiliaryPointSymbolEditing, "");
258
                            drawingStatus.addStatus(lineAntPointToPoint, auxiliaryLineSymbolEditing, "");
259

    
260
                        }
261
                        drawingStatus.addStatus(arco, lineSymbolEditing, "");
262

    
263
                    } else {
264
                        int subtype = editingProviderServices.getSubType(featureStore);
265
                        Curve geometry = editingProviderServices.createLine(point, nextPoint, subtype);
266
                        if (addGeom) {
267
                            drawingStatus.addStatus(point, auxiliaryPointSymbolEditing, "");
268
                            drawingStatus.addStatus(nextPoint, auxiliaryPointSymbolEditing, "");
269
                        }
270
                        drawingStatus.addStatus(geometry, lineSymbolEditing, "");
271

    
272
                        Double[] antLineParams = editingProviderServices.getLineParams(point, nextPoint);
273
                        antm = antLineParams[0];
274
                        antb = antLineParams[1];
275
                        right = (nextPoint.getX() >= point.getX());
276
                    }
277
                } catch (Exception e) {
278
                    throw new DrawServiceException(e);
279
                }
280
            }
281
            return drawingStatus;
282
        }
283
        return null;
284
    }
285

    
286
    protected Geometry closeGeometryIfNecessary(Geometry geometry) {
287
        if (!isClose(geometry) && (geometry != null)) {
288

    
289
            if (geometry instanceof Surface) {
290
                Surface surface = (Surface) geometry;
291
                Point firstp = surface.getVertex(0);
292
                firstp = (Point) firstp.cloneGeometry();
293
                surface.addVertex(firstp);
294
                return surface;
295
            } else if (geometry instanceof Curve) {
296
                Curve line = (Curve) geometry;
297
                Point firstp = line.getVertex(0);
298
                firstp = (Point) firstp.cloneGeometry();
299
                line.addVertex(firstp);
300
                return line;
301
            }
302
        }
303
        return geometry;
304
    }
305

    
306
    public DrawingStatus getDrawingStatus(Point mousePosition) throws DrawServiceException {
307

    
308
        try {
309
            return calculatePolyline(mousePosition);
310

    
311
        } catch (Exception e) {
312
            throw new DrawServiceException(e);
313
        }
314
    }
315

    
316
    public void finishAndStore() throws FinishServiceException {
317
        try {
318
            Geometry geometry = finish();
319
            if (geometry != null) {
320
                editingProviderServices.insertGeometryIntoFeatureStore(geometry, featureStore);
321
            }
322
        } catch (Exception e) {
323
            throw new FinishServiceException(e);
324
        }
325
    }
326

    
327
    public Geometry finish() throws FinishServiceException {
328
        try {
329
            GeometryManager geomManager = GeometryLocator.getGeometryManager();
330
            GeometryType storeGeomType = editingProviderServices.getGeomType(featureStore);
331
            Line line = geomManager.createLine(storeGeomType.getSubType());
332
            calculateFinalGeometry(storeGeomType, line);
333

    
334
            if (closeGeometry) {
335
                line = (Line) closeGeometryIfNecessary(line);
336
            }
337

    
338
            if (storeGeomType.isTypeOf(MULTICURVE)) {
339
                MultiCurve multiCurve = geomManager.createMultiCurve(storeGeomType.getSubType());
340
                multiCurve.addCurve(line);
341
                return multiCurve;
342
            } else {
343
                return line;
344
            }
345

    
346
        } catch (BaseException e) {
347
            throw new FinishServiceException(e);
348
        }
349
    }
350

    
351
    /**
352
     * Calculate the final geometry reversing the geometries of the
353
     * drawingStatus if needed.
354
     *
355
     * @param geometryType
356
     * @param orientablePrimitive
357
     * @throws DataException
358
     * @throws VectorEditingException
359
     * @throws GeometryException
360
     * @throws GeometryOperationException
361
     * @throws GeometryOperationNotSupportedException
362
     */
363
    protected void calculateFinalGeometry(GeometryType geometryType, OrientablePrimitive orientablePrimitive)
364
        throws DataException, VectorEditingException, GeometryException, GeometryOperationNotSupportedException, GeometryOperationException {
365
        DrawingStatus drawingStatus = calculatePolyline(null);
366
        Point vertexAnt = null;
367
        for (Geometry geometry : drawingStatus.getGeometries()) {
368
            if (geometry instanceof Line) {
369
                Line line = (Line) geometry;
370
                for (int i = 0; i < line.getNumVertices(); i++) {
371
                    if ((vertexAnt == null) || !vertexAnt.equals(line.getVertex(i))) {
372
                        orientablePrimitive.addVertex(line.getVertex(i));
373
                        vertexAnt = line.getVertex(i);
374
                    }
375
                }
376
            } else if(geometry instanceof Curve){
377
                MultiLine multiline = geometry.toLines();
378
                for(int i=0; i<multiline.getPrimitivesNumber(); i++){
379
                    Line line = (Line)multiline.getPrimitiveAt(i);
380
                    if(line.getNumVertices()>0 && vertexAnt!= null && line.getVertex(0)!=vertexAnt){
381
                        line.flip();
382
                    }
383
                    for (int j = 0; j < line.getNumVertices(); j++) {
384
                        if ((vertexAnt == null) || !vertexAnt.equals(line.getVertex(j))) {
385
                            orientablePrimitive.addVertex(line.getVertex(j));
386
                            vertexAnt = line.getVertex(j);
387
                        }
388
                    }
389
                }
390
            }
391
        }
392
    }
393

    
394
    public String getName() {
395
        return PolylineEditingProviderFactory.PROVIDER_NAME;
396
    }
397

    
398
    private MyPolyLinePoint getNextPoint(int i) {
399
        if (!values.isEmpty() && (i < (values.size() - 1))) {
400
            return values.get(i + 1);
401
        }
402
        return null;
403
    }
404

    
405
    public List<EditingServiceParameter> getParameters() {
406
        List<EditingServiceParameter> list = new ArrayList<EditingServiceParameter>();
407
        list.add(points);
408
        return list;
409
    }
410

    
411
    private boolean isClose(Geometry geometry) {
412

    
413
        if (geometry != null) {
414

    
415
            if (geometry instanceof OrientablePrimitive) {
416
                OrientablePrimitive orientablePrimitive = (OrientablePrimitive) geometry;
417
                Point firstPoint = orientablePrimitive.getVertex(0);
418
                Point lastPoint = orientablePrimitive.getVertex(orientablePrimitive.getNumVertices() - 1);
419
                if (firstPoint.equals(lastPoint)) {
420
                    return true;
421
                }
422
            }
423
        }
424
        return false;
425
    }
426

    
427
    public EditingServiceParameter next() {
428
        if (finishPolyline) {
429
            return null;
430
        } else {
431
            return points;
432
        }
433

    
434
    }
435

    
436
    public void start() throws StartServiceException {
437
        // Stop service;
438
        stop();
439

    
440
        values = new ArrayList<MyPolyLinePoint>();
441
    }
442

    
443
    public void stop() {
444
        if (values != null) {
445
            values.clear();
446
        }
447
        arcMode = false;
448
        finishPolyline = false;
449
        closeGeometry = false;
450
    }
451

    
452
    private void validateAndInsertValue(EditingServiceParameter param, Object value) throws InvalidEntryException {
453
        if (value instanceof String) {
454
            String option = (String) value;
455
            I18nManager i18nManager = ToolsLocator.getI18nManager();
456

    
457
            if (option.equalsIgnoreCase(i18nManager.getTranslation("key_finish"))) {
458
                finishPolyline = true;
459
                return;
460
            }
461

    
462
            if (values.size() > 0) {
463
                if (option.equalsIgnoreCase(i18nManager.getTranslation("key_remove_last_point"))) {
464
                    arcMode = values.get(values.size() - 1).isArcMode();
465
                    if (values.size() > 2) {
466
                        values.get(values.size() - 2).setArcMode(arcMode);
467
                    } else {
468
                        arcMode = false;
469
                    }
470
                    values.remove(values.size() - 1);
471
                    return;
472
                }
473
            }
474

    
475
            if (values.size() >= 2) {
476

    
477
                if (option.equalsIgnoreCase(i18nManager.getTranslation("key_arc_mode"))) {
478

    
479
                    arcMode = true;
480

    
481
                } else if (option.equalsIgnoreCase(i18nManager.getTranslation("key_line_mode"))) {
482

    
483
                    arcMode = false;
484

    
485
                } else if (option.equalsIgnoreCase(i18nManager.getTranslation("key_close"))) {
486

    
487
                    closeGeometry = true;
488
                    finishPolyline = true;
489
                }
490
            } else {
491
                throw new InvalidEntryException(null);
492
            }
493

    
494
            if (values.size() > 0) {
495
                values.get(values.size() - 1).setArcMode(arcMode);
496
                return;
497
            }
498

    
499
        } else if ((param == points) && (value instanceof Point)) {
500
            values.add(new MyPolyLinePoint((Point) value, arcMode));
501
            return;
502
        }
503
        throw new InvalidEntryException(null);
504
    }
505

    
506
    public void setValue(Object value) throws InvalidEntryException {
507
        EditingServiceParameter param = next();
508
        validateAndInsertValue(param, value);
509
    }
510

    
511
}