Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2057 / extensions / extEditing / src / org / gvsig / editing / gui / cad / tools / PolylineCADTool.java @ 39154

History | View | Annotate | Download (20 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 javax.swing.JOptionPane;
30

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

    
48
/**
49
 * DOCUMENT ME!
50
 * 
51
 * @author Vicente Caballero Navarro
52
 */
53
public class PolylineCADTool extends AbstractCurveSurfaceCADTool {
54

    
55
    protected PolylineCADToolContext _fsm;
56
    protected Point2D firstPoint;
57
    protected Point2D antPoint;
58
    protected Point2D antantPoint;
59
    protected Point2D antCenter;
60
    protected Point2D antInter;
61
    protected ArrayList list = new ArrayList();
62
    protected boolean close = false;
63
    protected GeneralPathX gpx = null;
64

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

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

    
83
    public int getLinesCount() {
84
        return list.size();
85
    }
86

    
87
    public boolean isPolygonLayer() {
88
        try {
89
            return (((FLyrVect) getVLE().getLayer()).getShapeType() == Geometry.TYPES.SURFACE);
90
        } catch (ReadException e) {
91
            return false;
92
        }
93
    }
94

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

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

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

    
144
    public void transition(double x, double y, InputEvent event) {
145
        _fsm.addPoint(x, y, event);
146
    }
147

    
148
    public void transition(double d) {
149
        _fsm.addValue(d);
150
    }
151

    
152
    public void transition(String s) throws CommandException {
153
        if (!super.changeCommand(s)) {
154
            _fsm.addOption(s);
155
        }
156
    }
157

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

    
176
            if (firstPoint == null) {
177
                firstPoint = new Point2D.Double(x, y);
178
            }
179
            Point2D point = new Point2D.Double(x, y);
180

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

    
197
            if (antPoint != null) {
198
                antantPoint = antPoint;
199
            }
200

    
201
            antPoint = point;
202
        } else
203
            if (status.equals("Polyline.NextPointOrLineOrClose")) {
204
                Point2D point = new Point2D.Double(x, y);
205
                Point2D lastp = antPoint; // (Point2D)points.get(i-1);
206

    
207
                if (antantPoint == null) {
208
                    antantPoint =
209
                        new Point2D.Double(lastp.getX() + (point.getX() / 2),
210
                            lastp.getY() + (point.getY() / 2));
211
                }
212

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

    
229
                    if (point.getX() == antantPoint.getX()) {
230
                        point =
231
                            new Point2D.Double(point.getX() + 0.00000001,
232
                                point.getY());
233
                    } else
234
                        if (point.getY() == antantPoint.getY()) {
235
                            point =
236
                                new Point2D.Double(point.getX(),
237
                                    point.getY() + 0.00000001);
238
                        }
239

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

    
257
                        double radio = interp.distance(lastp);
258

    
259
                        if (UtilFunctions.isLowAngle(antantPoint, lastp,
260
                            interp, point)) {
261
                            radio = -radio;
262
                        }
263

    
264
                        Point2D centerp =
265
                            UtilFunctions.getPoint(interp, mediop, radio);
266
                        antCenter = centerp;
267

    
268
                        Geometry ig = createArc(lastp, centerp, point);
269

    
270
                        if (ig != null) {
271
                            list.add(ig);
272
                            addTemporalCache(ig);
273
                        } else {
274
                            
275
                            ApplicationLocator.getManager().message(
276
                                Messages.getText("_Unable_to_create_arc"),
277
                                JOptionPane.ERROR_MESSAGE);
278

    
279
                        }
280
                    } else {
281
                        Point2D[] ps1 =
282
                            UtilFunctions.getPerpendicular(lastp, antInter,
283
                                lastp);
284
                        double a1 = UtilFunctions.getAngle(ps1[0], ps1[1]);
285
                        double a2 = UtilFunctions.getAngle(ps1[1], ps1[0]);
286
                        double angle = UtilFunctions.getAngle(antCenter, lastp);
287
                        Point2D ini1 = null;
288
                        Point2D ini2 = null;
289

    
290
                        if (UtilFunctions.absoluteAngleDistance(angle, a1) > UtilFunctions
291
                            .absoluteAngleDistance(angle, a2)) {
292
                            ini1 = ps1[0];
293
                            ini2 = ps1[1];
294
                        } else {
295
                            ini1 = ps1[1];
296
                            ini2 = ps1[0];
297
                        }
298

    
299
                        Point2D unit = UtilFunctions.getUnitVector(ini1, ini2);
300
                        Point2D correct =
301
                            new Point2D.Double(lastp.getX() + unit.getX(),
302
                                lastp.getY() + unit.getY());
303
                        Point2D[] ps =
304
                            UtilFunctions.getPerpendicular(lastp, correct,
305
                                lastp);
306
                        Point2D mediop =
307
                            new Point2D.Double(
308
                                (point.getX() + lastp.getX()) / 2,
309
                                (point.getY() + lastp.getY()) / 2);
310
                        Point2D[] ps2 =
311
                            UtilFunctions
312
                                .getPerpendicular(lastp, point, mediop);
313
                        Point2D interp =
314
                            UtilFunctions.getIntersection(ps[0], ps[1], ps2[0],
315
                                ps2[1]);
316
                        antInter = interp;
317

    
318
                        double radio = interp.distance(lastp);
319

    
320
                        if (UtilFunctions.isLowAngle(correct, lastp, interp,
321
                            point)) {
322
                            radio = -radio;
323
                        }
324

    
325
                        Point2D centerp =
326
                            UtilFunctions.getPoint(interp, mediop, radio);
327
                        antCenter = centerp;
328
                        Geometry geom = createArc(lastp, centerp, point);
329
                        
330
                        if (geom != null) {
331
                            list.add(geom);
332
                            addTemporalCache(geom);
333
                        }
334
                    }
335

    
336
                    antantPoint = antPoint;
337
                    antPoint = point;
338
                }
339
            }
340
    }
341

    
342
    /**
343
     * M?todo para dibujar la lo necesario para el estado en el que nos
344
     * encontremos.
345
     * 
346
     * @param g
347
     *            Graphics sobre el que dibujar.
348
     * @param selectedGeometries
349
     *            BitSet con las geometr?as seleccionadas.
350
     * @param x
351
     *            par?metro x del punto que se pase para dibujar.
352
     * @param y
353
     *            par?metro x del punto que se pase para dibujar.
354
     */
355
    public void drawOperation(MapControlDrawer renderer, double x, double y) {
356
        PolylineCADToolState actualState = _fsm.getState();
357
        String status = actualState.getName();
358

    
359
        if (status.equals("Polyline.NextPointOrArcOrClose")
360
            || status.equals("Polyline.FirstPoint")) {
361
            for (int i = 0; i < list.size(); i++) {
362
                renderer.draw((Geometry) list.get(i),
363
                    mapControlManager.getGeometrySelectionSymbol());
364
            }
365
            if (antPoint != null)
366
                renderer.drawLine(antPoint, new Point2D.Double(x, y),
367
                    mapControlManager.getGeometrySelectionSymbol());
368

    
369
        } else
370
            if ((status.equals("Polyline.NextPointOrLineOrClose"))) {
371
                for (int i = 0; i < list.size(); i++) {
372
                    renderer.draw((Geometry) list.get(i),
373
                        mapControlManager.getGeometrySelectionSymbol());
374
                }
375

    
376
                Point2D point = new Point2D.Double(x, y);
377
                Point2D lastp = antPoint;
378

    
379
                if (!(list.size() > 0)
380
                    || (((Geometry) list.get(list.size() - 1)).getType() == Geometry.TYPES.CURVE)) {
381
                    if (antantPoint == null) {
382
                        drawArc(point, lastp, new Point2D.Double(lastp.getX()
383
                            + (point.getX() / 2), lastp.getY()
384
                            + (point.getY() / 2)), renderer);
385
                    } else {
386
                        drawArc(point, lastp, antantPoint, renderer);
387
                    }
388
                } else {
389
                    if (antInter != null) {
390
                        Point2D[] ps1 =
391
                            UtilFunctions.getPerpendicular(lastp, antInter,
392
                                lastp);
393
                        double a1 = UtilFunctions.getAngle(ps1[0], ps1[1]);
394
                        double a2 = UtilFunctions.getAngle(ps1[1], ps1[0]);
395
                        double angle = UtilFunctions.getAngle(antCenter, lastp);
396
                        Point2D ini1 = null;
397
                        Point2D ini2 = null;
398

    
399
                        if (UtilFunctions.absoluteAngleDistance(angle, a1) > UtilFunctions
400
                            .absoluteAngleDistance(angle, a2)) {
401
                            ini1 = ps1[0];
402
                            ini2 = ps1[1];
403
                        } else {
404
                            ini1 = ps1[1];
405
                            ini2 = ps1[0];
406
                        }
407

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

    
435
    /**
436
     * Dibuja el arco sobre el graphics.
437
     * 
438
     * @param point
439
     *            Puntero del rat?n.
440
     * @param lastp
441
     *            ?ltimo punto de la polilinea.
442
     * @param antp
443
     *            Punto antepenultimo.
444
     * @param g
445
     *            Graphics sobre el que se dibuja.
446
     */
447
    private void drawArc(Point2D point, Point2D lastp, Point2D antp,
448
        MapControlDrawer renderer) {
449
        if (((point.getY() == lastp.getY()) && (point.getX() < lastp.getX()))
450
            || ((point.getX() == lastp.getX()) && (point.getY() < lastp.getY()))) {
451
        } else {
452
            if (point.getX() == lastp.getX()) {
453
                point =
454
                    new Point2D.Double(point.getX() + 0.00000001, point.getY());
455
            } else
456
                if (point.getY() == lastp.getY()) {
457
                    point =
458
                        new Point2D.Double(point.getX(),
459
                            point.getY() + 0.00000001);
460
                }
461

    
462
            if (point.getX() == antp.getX()) {
463
                point =
464
                    new Point2D.Double(point.getX() + 0.00000001, point.getY());
465
            } else
466
                if (point.getY() == antp.getY()) {
467
                    point =
468
                        new Point2D.Double(point.getX(),
469
                            point.getY() + 0.00000001);
470
                }
471

    
472
            Point2D[] ps1 = UtilFunctions.getPerpendicular(lastp, antp, lastp);
473
            Point2D mediop =
474
                new Point2D.Double((point.getX() + lastp.getX()) / 2,
475
                    (point.getY() + lastp.getY()) / 2);
476
            Point2D[] ps2 =
477
                UtilFunctions.getPerpendicular(lastp, point, mediop);
478
            Point2D interp =
479
                UtilFunctions.getIntersection(ps1[0], ps1[1], ps2[0], ps2[1]);
480

    
481
            double radio = interp.distance(lastp);
482

    
483
            if (UtilFunctions.isLowAngle(antp, lastp, interp, point)) {
484
                radio = -radio;
485
            }
486

    
487
            Point2D centerp = UtilFunctions.getPoint(interp, mediop, radio);
488
            renderer.drawLine(lastp, point,
489
                mapControlManager.getGeometrySelectionSymbol());
490

    
491
            Geometry ig = createArc(lastp, centerp, point);
492

    
493
            if (ig != null) {
494
                renderer.draw(ig,
495
                    mapControlManager.getGeometrySelectionSymbol());
496
            }
497
        }
498
    }
499

    
500
    /**
501
     * Add a diferent option.
502
     * 
503
     * @param sel
504
     *            DOCUMENT ME!
505
     * @param s
506
     *            Diferent option.
507
     */
508
    public void addOption(String s) {
509
        // Nothing to do
510
    }
511

    
512
    public void addValue(double d) {
513
        // Nothing to do
514
    }
515

    
516
    public void cancel() {
517
        list.clear();
518
        clearTemporalCache();
519
        antantPoint = antCenter = antInter = antPoint = firstPoint = null;
520
    }
521

    
522
    public void end() {
523
        // Nothing to do
524
    }
525

    
526
    public String getName() {
527
        return PluginServices.getText(this, "polyline_");
528
    }
529

    
530
    public String toString() {
531
        return "_polyline";
532
    }
533

    
534
    public void endTransition(double x, double y, MouseEvent event) {
535
        _fsm.endPoint(x, y, event);
536
    }
537

    
538
}