Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / extensions / extEditing / src / org / gvsig / editing / gui / cad / tools / PolylineCADTool.java @ 39075

History | View | Annotate | Download (19.7 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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
 */
22
package org.gvsig.editing.gui.cad.tools;
23

    
24
import java.awt.event.InputEvent;
25
import java.awt.event.MouseEvent;
26
import java.awt.geom.Point2D;
27
import java.util.ArrayList;
28

    
29
import org.gvsig.andami.PluginServices;
30
import org.gvsig.andami.messages.NotificationManager;
31
import org.gvsig.editing.gui.cad.exception.CommandException;
32
import org.gvsig.editing.gui.cad.tools.smc.PolylineCADToolContext;
33
import org.gvsig.editing.gui.cad.tools.smc.PolylineCADToolContext.PolylineCADToolState;
34
import org.gvsig.fmap.dal.exception.ReadException;
35
import org.gvsig.fmap.geom.Geometry;
36
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
37
import org.gvsig.fmap.geom.handler.Handler;
38
import org.gvsig.fmap.geom.primitive.Curve;
39
import org.gvsig.fmap.geom.primitive.GeneralPathX;
40
import org.gvsig.fmap.geom.util.UtilFunctions;
41
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
42
import org.gvsig.fmap.mapcontrol.MapControlDrawer;
43

    
44
/**
45
 * DOCUMENT ME!
46
 * 
47
 * @author Vicente Caballero Navarro
48
 */
49
public class PolylineCADTool extends AbstractCurveSurfaceCADTool {
50

    
51
    protected PolylineCADToolContext _fsm;
52
    protected Point2D firstPoint;
53
    protected Point2D antPoint;
54
    protected Point2D antantPoint;
55
    protected Point2D antCenter;
56
    protected Point2D antInter;
57
    protected ArrayList list = new ArrayList();
58
    protected boolean close = false;
59
    protected GeneralPathX gpx = null;
60

    
61
    /**
62
     * M?todo de incio, para poner el c?digo de todo lo que se requiera de una
63
     * carga previa a la utilizaci?n de la herramienta.
64
     */
65
    public void init() {
66
        _fsm = new PolylineCADToolContext(this);
67
    }
68

    
69
    public Geometry getGeometry() {
70
        Geometry[] geoms = (Geometry[]) list.toArray(new Geometry[0]);
71
        MultiPrimitive fgc = createMultiPrimitive(geoms);
72
        // No queremos guardar FGeometryCollections:
73
        GeneralPathX gp = new GeneralPathX();
74
        gp.append(fgc.getPathIterator(null, geomManager.getFlatness()), true);
75
        Geometry newGeom = createCurve(gp);
76
        return newGeom;
77
    }
78

    
79
    public int getLinesCount() {
80
        return list.size();
81
    }
82

    
83
    public boolean isPolygonLayer() {
84
        try {
85
            return (((FLyrVect) getVLE().getLayer()).getShapeType() == Geometry.TYPES.SURFACE);
86
        } catch (ReadException e) {
87
            return false;
88
        }
89
    }
90

    
91
    public void endGeometry() {
92
        if (gpx == null) {
93
            gpx = new GeneralPathX();
94
            Geometry[] geoms = (Geometry[]) list.toArray(new Geometry[0]);
95
            MultiPrimitive fgc = createMultiPrimitive(geoms);
96
            // No queremos guardar FGeometryCollections:
97
            gpx.append(fgc.getPathIterator(null, geomManager.getFlatness()),
98
                true);
99
        }
100
        try {
101
            if (((FLyrVect) getVLE().getLayer()).getShapeType() == Geometry.TYPES.SURFACE
102
                && !close) {
103
                closeGeometry();
104
            }
105
        } catch (ReadException e) {
106
            NotificationManager.addError(e.getMessage(), e);
107
        }
108

    
109
        Geometry newGeom = null;
110
        int type = getCadToolAdapter().getActiveLayerType();
111
        if ((type == Geometry.TYPES.SURFACE)
112
            || (type == Geometry.TYPES.MULTISURFACE)) {
113
            newGeom = createSurface(gpx);
114
        } else {
115
            newGeom = createCurve(gpx);
116
        }
117
        insertAndSelectGeometry(newGeom);
118
        _fsm = new PolylineCADToolContext(this);
119
        list.clear();
120
        clearTemporalCache();
121
        close = false;
122
        gpx = null;
123
        antantPoint = antCenter = antInter = antPoint = firstPoint = null;
124
    }
125

    
126
    public void closeGeometry() {
127
        if (gpx == null) {
128
            gpx = new GeneralPathX();
129
            Geometry[] geoms = (Geometry[]) list.toArray(new Geometry[0]);
130
            for (int i=0; i<geoms.length; i++) {
131
                gpx.append(
132
                    geoms[i].getPathIterator(null, geomManager.getFlatness()),
133
                    true);
134
            }
135
        }
136
        close = true;
137
        gpx.closePath();
138
    }
139

    
140
    public void transition(double x, double y, InputEvent event) {
141
        _fsm.addPoint(x, y, event);
142
    }
143

    
144
    public void transition(double d) {
145
        _fsm.addValue(d);
146
    }
147

    
148
    public void transition(String s) throws CommandException {
149
        if (!super.changeCommand(s)) {
150
            _fsm.addOption(s);
151
        }
152
    }
153

    
154
    /**
155
     * Equivale al transition del prototipo pero sin pasarle como par?metro el
156
     * editableFeatureSource que ya estar? creado.
157
     * 
158
     * @param sel
159
     *            Bitset con las geometr?as que est?n seleccionadas.
160
     * @param x
161
     *            par?metro x del punto que se pase en esta transici?n.
162
     * @param y
163
     *            par?metro y del punto que se pase en esta transici?n.
164
     */
165
    public void addPoint(double x, double y, InputEvent event) {
166
        PolylineCADToolState actualState =
167
            (PolylineCADToolState) _fsm.getPreviousState();
168
        String status = actualState.getName();
169
        if (status.equals("Polyline.NextPointOrArcOrClose")
170
            || status.equals("Polyline.FirstPoint")) {
171

    
172
            if (firstPoint == null) {
173
                firstPoint = new Point2D.Double(x, y);
174
            }
175
            Point2D point = new Point2D.Double(x, y);
176

    
177
            if (antPoint != null
178
                && (antPoint.getX() != point.getX() || antPoint.getY() != point
179
                    .getY())) {
180
                GeneralPathX elShape =
181
                    new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, 2);
182
                elShape.moveTo(antPoint.getX(), antPoint.getY());
183
                elShape.lineTo(point.getX(), point.getY());
184
                Geometry geom = createCurve(elShape);
185
                if (geom != null) {
186
                    list.add(geom);
187
                    addTemporalCache(geom);
188
                }
189
            }
190
            if (antPoint == null)
191
                antPoint = (Point2D) firstPoint.clone();
192

    
193
            if (antPoint != null) {
194
                antantPoint = antPoint;
195
            }
196

    
197
            antPoint = point;
198
        } else
199
            if (status.equals("Polyline.NextPointOrLineOrClose")) {
200
                Point2D point = new Point2D.Double(x, y);
201
                Point2D lastp = antPoint; // (Point2D)points.get(i-1);
202

    
203
                if (antantPoint == null) {
204
                    antantPoint =
205
                        new Point2D.Double(lastp.getX() + (point.getX() / 2),
206
                            lastp.getY() + (point.getY() / 2));
207
                }
208

    
209
                if (((point.getY() == lastp.getY()) && (point.getX() < lastp
210
                    .getX()))
211
                    || ((point.getX() == lastp.getX()) && (point.getY() < lastp
212
                        .getY()))) {
213
                } else {
214
                    if (point.getX() == lastp.getX()) {
215
                        point =
216
                            new Point2D.Double(point.getX() + 0.00000001,
217
                                point.getY());
218
                    } else
219
                        if (point.getY() == lastp.getY()) {
220
                            point =
221
                                new Point2D.Double(point.getX(),
222
                                    point.getY() + 0.00000001);
223
                        }
224

    
225
                    if (point.getX() == antantPoint.getX()) {
226
                        point =
227
                            new Point2D.Double(point.getX() + 0.00000001,
228
                                point.getY());
229
                    } else
230
                        if (point.getY() == antantPoint.getY()) {
231
                            point =
232
                                new Point2D.Double(point.getX(),
233
                                    point.getY() + 0.00000001);
234
                        }
235

    
236
                    if (!(list.size() > 0)
237
                        || (((Geometry) list.get(list.size() - 1)).getType() == Geometry.TYPES.CURVE)) {
238
                        Point2D[] ps1 =
239
                            UtilFunctions.getPerpendicular(antantPoint, lastp,
240
                                lastp);
241
                        Point2D mediop =
242
                            new Point2D.Double(
243
                                (point.getX() + lastp.getX()) / 2,
244
                                (point.getY() + lastp.getY()) / 2);
245
                        Point2D[] ps2 =
246
                            UtilFunctions
247
                                .getPerpendicular(lastp, point, mediop);
248
                        Point2D interp =
249
                            UtilFunctions.getIntersection(ps1[0], ps1[1],
250
                                ps2[0], ps2[1]);
251
                        antInter = interp;
252

    
253
                        double radio = interp.distance(lastp);
254

    
255
                        if (UtilFunctions.isLowAngle(antantPoint, lastp,
256
                            interp, point)) {
257
                            radio = -radio;
258
                        }
259

    
260
                        Point2D centerp =
261
                            UtilFunctions.getPoint(interp, mediop, radio);
262
                        antCenter = centerp;
263

    
264
                        Geometry ig = createArc(lastp, centerp, point);
265

    
266
                        if (ig != null) {
267
                            list.add(ig);
268
                            addTemporalCache(ig);
269
                        }
270
                    } else {
271
                        Point2D[] ps1 =
272
                            UtilFunctions.getPerpendicular(lastp, antInter,
273
                                lastp);
274
                        double a1 = UtilFunctions.getAngle(ps1[0], ps1[1]);
275
                        double a2 = UtilFunctions.getAngle(ps1[1], ps1[0]);
276
                        double angle = UtilFunctions.getAngle(antCenter, lastp);
277
                        Point2D ini1 = null;
278
                        Point2D ini2 = null;
279

    
280
                        if (UtilFunctions.absoluteAngleDistance(angle, a1) > UtilFunctions
281
                            .absoluteAngleDistance(angle, a2)) {
282
                            ini1 = ps1[0];
283
                            ini2 = ps1[1];
284
                        } else {
285
                            ini1 = ps1[1];
286
                            ini2 = ps1[0];
287
                        }
288

    
289
                        Point2D unit = UtilFunctions.getUnitVector(ini1, ini2);
290
                        Point2D correct =
291
                            new Point2D.Double(lastp.getX() + unit.getX(),
292
                                lastp.getY() + unit.getY());
293
                        Point2D[] ps =
294
                            UtilFunctions.getPerpendicular(lastp, correct,
295
                                lastp);
296
                        Point2D mediop =
297
                            new Point2D.Double(
298
                                (point.getX() + lastp.getX()) / 2,
299
                                (point.getY() + lastp.getY()) / 2);
300
                        Point2D[] ps2 =
301
                            UtilFunctions
302
                                .getPerpendicular(lastp, point, mediop);
303
                        Point2D interp =
304
                            UtilFunctions.getIntersection(ps[0], ps[1], ps2[0],
305
                                ps2[1]);
306
                        antInter = interp;
307

    
308
                        double radio = interp.distance(lastp);
309

    
310
                        if (UtilFunctions.isLowAngle(correct, lastp, interp,
311
                            point)) {
312
                            radio = -radio;
313
                        }
314

    
315
                        Point2D centerp =
316
                            UtilFunctions.getPoint(interp, mediop, radio);
317
                        antCenter = centerp;
318
                        Geometry geom = createArc(lastp, centerp, point);
319
                        
320
                        if (geom != null) {
321
                            list.add(geom);
322
                            addTemporalCache(geom);
323
                        }
324
                    }
325

    
326
                    antantPoint = antPoint;
327
                    antPoint = point;
328
                }
329
            }
330
    }
331

    
332
    /**
333
     * M?todo para dibujar la lo necesario para el estado en el que nos
334
     * encontremos.
335
     * 
336
     * @param g
337
     *            Graphics sobre el que dibujar.
338
     * @param selectedGeometries
339
     *            BitSet con las geometr?as seleccionadas.
340
     * @param x
341
     *            par?metro x del punto que se pase para dibujar.
342
     * @param y
343
     *            par?metro x del punto que se pase para dibujar.
344
     */
345
    public void drawOperation(MapControlDrawer renderer, double x, double y) {
346
        PolylineCADToolState actualState = _fsm.getState();
347
        String status = actualState.getName();
348

    
349
        if (status.equals("Polyline.NextPointOrArcOrClose")
350
            || status.equals("Polyline.FirstPoint")) {
351
            for (int i = 0; i < list.size(); i++) {
352
                renderer.draw((Geometry) list.get(i),
353
                    mapControlManager.getGeometrySelectionSymbol());
354
            }
355
            if (antPoint != null)
356
                renderer.drawLine(antPoint, new Point2D.Double(x, y),
357
                    mapControlManager.getGeometrySelectionSymbol());
358

    
359
        } else
360
            if ((status.equals("Polyline.NextPointOrLineOrClose"))) {
361
                for (int i = 0; i < list.size(); i++) {
362
                    renderer.draw((Geometry) list.get(i),
363
                        mapControlManager.getGeometrySelectionSymbol());
364
                }
365

    
366
                Point2D point = new Point2D.Double(x, y);
367
                Point2D lastp = antPoint;
368

    
369
                if (!(list.size() > 0)
370
                    || (((Geometry) list.get(list.size() - 1)).getType() == Geometry.TYPES.CURVE)) {
371
                    if (antantPoint == null) {
372
                        drawArc(point, lastp, new Point2D.Double(lastp.getX()
373
                            + (point.getX() / 2), lastp.getY()
374
                            + (point.getY() / 2)), renderer);
375
                    } else {
376
                        drawArc(point, lastp, antantPoint, renderer);
377
                    }
378
                } else {
379
                    if (antInter != null) {
380
                        Point2D[] ps1 =
381
                            UtilFunctions.getPerpendicular(lastp, antInter,
382
                                lastp);
383
                        double a1 = UtilFunctions.getAngle(ps1[0], ps1[1]);
384
                        double a2 = UtilFunctions.getAngle(ps1[1], ps1[0]);
385
                        double angle = UtilFunctions.getAngle(antCenter, lastp);
386
                        Point2D ini1 = null;
387
                        Point2D ini2 = null;
388

    
389
                        if (UtilFunctions.absoluteAngleDistance(angle, a1) > UtilFunctions
390
                            .absoluteAngleDistance(angle, a2)) {
391
                            ini1 = ps1[0];
392
                            ini2 = ps1[1];
393
                        } else {
394
                            ini1 = ps1[1];
395
                            ini2 = ps1[0];
396
                        }
397

    
398
                        Point2D unit = UtilFunctions.getUnitVector(ini1, ini2);
399
                        Point2D correct =
400
                            new Point2D.Double(lastp.getX() + unit.getX(),
401
                                lastp.getY() + unit.getY());
402
                        drawArc(point, lastp, correct, renderer);
403
                    }
404
                }
405
            }
406
        try {
407
            if (((FLyrVect) getVLE().getLayer()).getShapeType() == Geometry.TYPES.SURFACE
408
                && !list.isEmpty()) {
409
                Handler handler1 =
410
                    ((Geometry) list.get(0))
411
                        .getHandlers(Geometry.SELECTHANDLER)[0];
412
                GeneralPathX gpx = new GeneralPathX();
413
                gpx.moveTo(x, y);
414
                Point2D p1 = handler1.getPoint();
415
                gpx.lineTo(p1.getX(), p1.getY());
416
                Curve curve = createCurve(gpx);
417
                renderer.draw(curve,
418
                    mapControlManager.getGeometrySelectionSymbol());
419
            }
420
        } catch (ReadException e) {
421
            e.printStackTrace();
422
        }
423
    }
424

    
425
    /**
426
     * Dibuja el arco sobre el graphics.
427
     * 
428
     * @param point
429
     *            Puntero del rat?n.
430
     * @param lastp
431
     *            ?ltimo punto de la polilinea.
432
     * @param antp
433
     *            Punto antepenultimo.
434
     * @param g
435
     *            Graphics sobre el que se dibuja.
436
     */
437
    private void drawArc(Point2D point, Point2D lastp, Point2D antp,
438
        MapControlDrawer renderer) {
439
        if (((point.getY() == lastp.getY()) && (point.getX() < lastp.getX()))
440
            || ((point.getX() == lastp.getX()) && (point.getY() < lastp.getY()))) {
441
        } else {
442
            if (point.getX() == lastp.getX()) {
443
                point =
444
                    new Point2D.Double(point.getX() + 0.00000001, point.getY());
445
            } else
446
                if (point.getY() == lastp.getY()) {
447
                    point =
448
                        new Point2D.Double(point.getX(),
449
                            point.getY() + 0.00000001);
450
                }
451

    
452
            if (point.getX() == antp.getX()) {
453
                point =
454
                    new Point2D.Double(point.getX() + 0.00000001, point.getY());
455
            } else
456
                if (point.getY() == antp.getY()) {
457
                    point =
458
                        new Point2D.Double(point.getX(),
459
                            point.getY() + 0.00000001);
460
                }
461

    
462
            Point2D[] ps1 = UtilFunctions.getPerpendicular(lastp, antp, lastp);
463
            Point2D mediop =
464
                new Point2D.Double((point.getX() + lastp.getX()) / 2,
465
                    (point.getY() + lastp.getY()) / 2);
466
            Point2D[] ps2 =
467
                UtilFunctions.getPerpendicular(lastp, point, mediop);
468
            Point2D interp =
469
                UtilFunctions.getIntersection(ps1[0], ps1[1], ps2[0], ps2[1]);
470

    
471
            double radio = interp.distance(lastp);
472

    
473
            if (UtilFunctions.isLowAngle(antp, lastp, interp, point)) {
474
                radio = -radio;
475
            }
476

    
477
            Point2D centerp = UtilFunctions.getPoint(interp, mediop, radio);
478
            renderer.drawLine(lastp, point,
479
                mapControlManager.getGeometrySelectionSymbol());
480

    
481
            Geometry ig = createArc(lastp, centerp, point);
482

    
483
            if (ig != null) {
484
                renderer.draw(ig,
485
                    mapControlManager.getGeometrySelectionSymbol());
486
            }
487
        }
488
    }
489

    
490
    /**
491
     * Add a diferent option.
492
     * 
493
     * @param sel
494
     *            DOCUMENT ME!
495
     * @param s
496
     *            Diferent option.
497
     */
498
    public void addOption(String s) {
499
        // Nothing to do
500
    }
501

    
502
    public void addValue(double d) {
503
        // Nothing to do
504
    }
505

    
506
    public void cancel() {
507
        list.clear();
508
        clearTemporalCache();
509
        antantPoint = antCenter = antInter = antPoint = firstPoint = null;
510
    }
511

    
512
    public void end() {
513
        // Nothing to do
514
    }
515

    
516
    public String getName() {
517
        return PluginServices.getText(this, "polyline_");
518
    }
519

    
520
    public String toString() {
521
        return "_polyline";
522
    }
523

    
524
    public void endTransition(double x, double y, MouseEvent event) {
525
        _fsm.endPoint(x, y, event);
526
    }
527

    
528
}