Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extCAD / src / com / iver / cit / gvsig / gui / cad / tools / PolylineCADTool.java @ 13561

History | View | Annotate | Download (19.3 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package com.iver.cit.gvsig.gui.cad.tools;
42

    
43
import java.awt.Graphics;
44
import java.awt.Graphics2D;
45
import java.awt.event.InputEvent;
46
import java.awt.geom.Point2D;
47
import java.util.ArrayList;
48

    
49
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
50
import com.iver.andami.PluginServices;
51
import com.iver.andami.messages.NotificationManager;
52
import com.iver.cit.gvsig.fmap.core.FGeometryCollection;
53
import com.iver.cit.gvsig.fmap.core.FShape;
54
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
55
import com.iver.cit.gvsig.fmap.core.IGeometry;
56
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
57
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
58
import com.iver.cit.gvsig.fmap.edition.UtilFunctions;
59
import com.iver.cit.gvsig.gui.cad.DefaultCADTool;
60
import com.iver.cit.gvsig.gui.cad.exception.CommandException;
61
import com.iver.cit.gvsig.gui.cad.tools.smc.PolylineCADToolContext;
62
import com.iver.cit.gvsig.gui.cad.tools.smc.PolylineCADToolContext.PolylineCADToolState;
63

    
64

    
65
/**
66
 * DOCUMENT ME!
67
 *
68
 * @author Vicente Caballero Navarro
69
 */
70
public class PolylineCADTool extends DefaultCADTool {
71
        private PolylineCADToolContext _fsm;
72
    private Point2D firstPoint;
73
    private Point2D antPoint;
74
    private Point2D antantPoint;
75
    private Point2D antCenter;
76
    private Point2D antInter;
77
    private ArrayList list = new ArrayList();
78
        private boolean close=false;
79
        private GeneralPathX gpx = null;
80

    
81
    /**
82
     * Crea un nuevo PolylineCADTool.
83
     */
84
    public PolylineCADTool() {
85

    
86
    }
87

    
88
    /**
89
     * M?todo de incio, para poner el c?digo de todo lo que se requiera de una
90
     * carga previa a la utilizaci?n de la herramienta.
91
     */
92
    public void init() {
93
        _fsm = new PolylineCADToolContext(this);
94
    }
95
    public IGeometry getGeometry() {
96
                IGeometry[] geoms = (IGeometry[]) list.toArray(new IGeometry[0]);
97
                FGeometryCollection fgc = new FGeometryCollection(geoms);
98
                // No queremos guardar FGeometryCollections:
99
                GeneralPathX gp = new GeneralPathX();
100
                gp.append(fgc.getPathIterator(null, FConverter.FLATNESS), true);
101
                IGeometry newGeom = ShapeFactory.createPolyline2D(gp);
102
                return newGeom;
103
        }
104
    public int getLinesCount() {
105
            return list.size();
106
    }
107
    public void endGeometry() {
108
            if (gpx==null) {
109
                    gpx=new GeneralPathX();
110
                    IGeometry[] geoms = (IGeometry[]) list.toArray(new IGeometry[0]);
111
                    FGeometryCollection fgc = new FGeometryCollection(geoms);
112
                    // No queremos guardar FGeometryCollections:
113
                    gpx.append(fgc.getPathIterator(null,FConverter.FLATNESS), true);
114
            }
115
        try {
116
                         if (getVLE().getVEA().getShapeType()==FShape.POLYGON && !close){
117
                                 closeGeometry();
118
                         }
119
                 } catch (ReadDriverException e) {
120
                         NotificationManager.addError(e.getMessage(),e);
121
                }
122

    
123
        IGeometry newGeom = null;
124
        int type=getCadToolAdapter().getActiveLayerType();
125
        if (type==FShape.POLYGON){
126
                newGeom = ShapeFactory.createPolygon2D(gpx);
127
        }else{
128
                newGeom = ShapeFactory.createPolyline2D(gpx);
129
        }
130
        addGeometry(newGeom);
131
        _fsm = new PolylineCADToolContext(this);
132
        list.clear();
133
        clearTemporalCache();
134
        close=false;
135
        gpx=null;
136
        antantPoint=antCenter=antInter=antPoint=firstPoint=null;
137
    }
138
    public void closeGeometry(){
139
            if (gpx==null) {
140
                    gpx=new GeneralPathX();
141
                    IGeometry[] geoms = (IGeometry[]) list.toArray(new IGeometry[0]);
142
                    FGeometryCollection fgc = new FGeometryCollection(geoms);
143
                    // No queremos guardar FGeometryCollections:
144
                    gpx.append(fgc.getPathIterator(null,FConverter.FLATNESS), true);
145
            }
146
            close=true;
147
            gpx.closePath();
148
    }
149
    /* (non-Javadoc)
150
     * @see com.iver.cit.gvsig.gui.cad.CADTool#transition(com.iver.cit.gvsig.fmap.layers.FBitSet, double, double)
151
     */
152
    public void transition(double x, double y, InputEvent event) {
153
        _fsm.addPoint(x, y, event);
154
    }
155

    
156
    /* (non-Javadoc)
157
     * @see com.iver.cit.gvsig.gui.cad.CADTool#transition(com.iver.cit.gvsig.fmap.layers.FBitSet, double)
158
     */
159
    public void transition(double d) {
160
        _fsm.addValue(d);
161
    }
162

    
163
    /* (non-Javadoc)
164
     * @see com.iver.cit.gvsig.gui.cad.CADTool#transition(com.iver.cit.gvsig.fmap.layers.FBitSet, java.lang.String)
165
     */
166
    public void transition(String s) throws CommandException {
167
        if (!super.changeCommand(s)){
168
            _fsm.addOption(s);
169
        }
170
    }
171

    
172
    /**
173
     * Equivale al transition del prototipo pero sin pasarle como par?metro el
174
     * editableFeatureSource que ya estar? creado.
175
     *
176
     * @param sel Bitset con las geometr?as que est?n seleccionadas.
177
     * @param x par?metro x del punto que se pase en esta transici?n.
178
     * @param y par?metro y del punto que se pase en esta transici?n.
179
     */
180
    public void addPoint(double x, double y,InputEvent event) {
181
        PolylineCADToolState actualState = (PolylineCADToolState) _fsm.getPreviousState();
182
        String status = actualState.getName();
183
        if (status.equals("Polyline.NextPointOrArcOrClose") || status.equals("Polyline.FirstPoint")) {
184

    
185
           if (firstPoint == null) {
186
               firstPoint = new Point2D.Double(x, y);
187
           }
188
                Point2D point = new Point2D.Double(x, y);
189

    
190
            if (antPoint != null) {
191
                GeneralPathX elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD,
192
                        2);
193
                elShape.moveTo(antPoint.getX(), antPoint.getY());
194
                elShape.lineTo(point.getX(), point.getY());
195
                IGeometry geom=ShapeFactory.createPolyline2D(elShape);
196
                list.add(geom);
197
                addTemporalCache(geom);
198
            }
199
            if (antPoint==null)
200
                    antPoint = (Point2D)firstPoint.clone();
201

    
202
            if (antPoint != null) {
203
                antantPoint = antPoint;
204
            }
205

    
206
            antPoint = point;
207
        } else if (status.equals("Polyline.NextPointOrLineOrClose")) {
208
            Point2D point = new Point2D.Double(x, y);
209
            Point2D lastp = antPoint; //(Point2D)points.get(i-1);
210

    
211
            if (antantPoint == null) {
212
                antantPoint = new Point2D.Double(lastp.getX() +
213
                        (point.getX() / 2), lastp.getY() + (point.getY() / 2));
214
            }
215

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

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

    
237
                if (!(list.size() > 0) ||
238
                        (((IGeometry) list.get(list.size() - 1)).getGeometryType() == FShape.LINE)) {
239
                    Point2D[] ps1 = UtilFunctions.getPerpendicular(antantPoint,
240
                            lastp, lastp);
241
                    Point2D mediop = new Point2D.Double((point.getX() +
242
                            lastp.getX()) / 2, (point.getY() + lastp.getY()) / 2);
243
                    Point2D[] ps2 = UtilFunctions.getPerpendicular(lastp,
244
                            point, mediop);
245
                    Point2D interp = UtilFunctions.getIntersection(ps1[0],
246
                            ps1[1], ps2[0], ps2[1]);
247
                    antInter = interp;
248

    
249
                    double radio = interp.distance(lastp);
250

    
251
                    if (UtilFunctions.isLowAngle(antantPoint, lastp, interp,
252
                                point)) {
253
                        radio = -radio;
254
                    }
255

    
256
                    Point2D centerp = UtilFunctions.getPoint(interp, mediop,
257
                            radio);
258
                    antCenter = centerp;
259

    
260
                    IGeometry ig = ShapeFactory.createArc(lastp, centerp, point);
261

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

    
275
                    if (UtilFunctions.absoluteAngleDistance(angle, a1) > UtilFunctions.absoluteAngleDistance(
276
                                angle, a2)) {
277
                        ini1 = ps1[0];
278
                        ini2 = ps1[1];
279
                    } else {
280
                        ini1 = ps1[1];
281
                        ini2 = ps1[0];
282
                    }
283

    
284
                    Point2D unit = UtilFunctions.getUnitVector(ini1, ini2);
285
                    Point2D correct = new Point2D.Double(lastp.getX() +
286
                            unit.getX(), lastp.getY() + unit.getY());
287
                    Point2D[] ps = UtilFunctions.getPerpendicular(lastp,
288
                            correct, lastp);
289
                    Point2D mediop = new Point2D.Double((point.getX() +
290
                            lastp.getX()) / 2, (point.getY() + lastp.getY()) / 2);
291
                    Point2D[] ps2 = UtilFunctions.getPerpendicular(lastp,
292
                            point, mediop);
293
                    Point2D interp = UtilFunctions.getIntersection(ps[0],
294
                            ps[1], ps2[0], ps2[1]);
295
                    antInter = interp;
296

    
297
                    double radio = interp.distance(lastp);
298

    
299
                    if (UtilFunctions.isLowAngle(correct, lastp, interp, point)) {
300
                        radio = -radio;
301
                    }
302

    
303
                    Point2D centerp = UtilFunctions.getPoint(interp, mediop,
304
                            radio);
305
                    antCenter = centerp;
306
                    IGeometry geom=ShapeFactory.createArc(lastp, centerp, point);
307
                    list.add(geom);
308
                    addTemporalCache(geom);
309
                }
310

    
311
                antantPoint = antPoint;
312
                antPoint = point;
313
            }
314
        }
315
    }
316

    
317
    /**
318
     * M?todo para dibujar la lo necesario para el estado en el que nos
319
     * encontremos.
320
     *
321
     * @param g Graphics sobre el que dibujar.
322
     * @param selectedGeometries BitSet con las geometr?as seleccionadas.
323
     * @param x par?metro x del punto que se pase para dibujar.
324
     * @param y par?metro x del punto que se pase para dibujar.
325
     */
326
    public void drawOperation(Graphics g, double x,
327
        double y) {
328
        PolylineCADToolState actualState = _fsm.getState();
329
        String status = actualState.getName();
330

    
331
        if (status.equals("Polyline.NextPointOrArcOrClose") || status.equals("Polyline.FirstPoint")) {
332
            for (int i = 0; i < list.size(); i++) {
333
                ((IGeometry) list.get(i)).cloneGeometry().draw((Graphics2D) g,
334
                    getCadToolAdapter().getMapControl().getViewPort(),
335
                     DefaultCADTool.geometrySelectSymbol);
336
            }
337
            if (antPoint!=null)
338
                    drawLine((Graphics2D) g, antPoint, new Point2D.Double(x, y),DefaultCADTool.geometrySelectSymbol);
339

    
340
        } else if ((status.equals("Polyline.NextPointOrLineOrClose"))) {
341
            for (int i = 0; i < list.size(); i++) {
342
                ((IGeometry) list.get(i)).cloneGeometry().draw((Graphics2D) g,
343
                    getCadToolAdapter().getMapControl().getViewPort(),
344
                     DefaultCADTool.geometrySelectSymbol);
345
            }
346

    
347
            Point2D point = new Point2D.Double(x, y);
348
            Point2D lastp = antPoint;
349

    
350
            if (!(list.size() > 0) ||
351
                    (((IGeometry) list.get(list.size() - 1)).getGeometryType() == FShape.LINE)) {
352
                if (antantPoint == null) {
353
                    drawArc(point, lastp,
354
                        new Point2D.Double(lastp.getX() + (point.getX() / 2),
355
                            lastp.getY() + (point.getY() / 2)), g);
356
                } else {
357
                    drawArc(point, lastp, antantPoint, g);
358
                }
359
            } else {
360
                if (antInter != null) {
361
                    Point2D[] ps1 = UtilFunctions.getPerpendicular(lastp,
362
                            antInter, lastp);
363
                    double a1 = UtilFunctions.getAngle(ps1[0], ps1[1]);
364
                    double a2 = UtilFunctions.getAngle(ps1[1], ps1[0]);
365
                    double angle = UtilFunctions.getAngle(antCenter, lastp);
366
                    Point2D ini1 = null;
367
                    Point2D ini2 = null;
368

    
369
                    if (UtilFunctions.absoluteAngleDistance(angle, a1) > UtilFunctions.absoluteAngleDistance(
370
                                angle, a2)) {
371
                        ini1 = ps1[0];
372
                        ini2 = ps1[1];
373
                    } else {
374
                        ini1 = ps1[1];
375
                        ini2 = ps1[0];
376
                    }
377

    
378
                    Point2D unit = UtilFunctions.getUnitVector(ini1, ini2);
379
                    Point2D correct = new Point2D.Double(lastp.getX() +
380
                            unit.getX(), lastp.getY() + unit.getY());
381
                    drawArc(point, lastp, correct, g);
382
                }
383
            }
384
        }
385
    }
386

    
387
    /**
388
     * Dibuja el arco sobre el graphics.
389
     *
390
     * @param point Puntero del rat?n.
391
     * @param lastp ?ltimo punto de la polilinea.
392
     * @param antp Punto antepenultimo.
393
     * @param g Graphics sobre el que se dibuja.
394
     */
395
    private void drawArc(Point2D point, Point2D lastp, Point2D antp, Graphics g) {
396
        if (((point.getY() == lastp.getY()) && (point.getX() < lastp.getX())) ||
397
                ((point.getX() == lastp.getX()) &&
398
                (point.getY() < lastp.getY()))) {
399
        } else {
400
            if (point.getX() == lastp.getX()) {
401
                point = new Point2D.Double(point.getX() + 0.00000001,
402
                        point.getY());
403
            } else if (point.getY() == lastp.getY()) {
404
                point = new Point2D.Double(point.getX(),
405
                        point.getY() + 0.00000001);
406
            }
407

    
408
            if (point.getX() == antp.getX()) {
409
                point = new Point2D.Double(point.getX() + 0.00000001,
410
                        point.getY());
411
            } else if (point.getY() == antp.getY()) {
412
                point = new Point2D.Double(point.getX(),
413
                        point.getY() + 0.00000001);
414
            }
415

    
416
            Point2D[] ps1 = UtilFunctions.getPerpendicular(lastp, antp, lastp);
417
            Point2D mediop = new Point2D.Double((point.getX() + lastp.getX()) / 2,
418
                    (point.getY() + lastp.getY()) / 2);
419
            Point2D[] ps2 = UtilFunctions.getPerpendicular(lastp, point, mediop);
420
            Point2D interp = UtilFunctions.getIntersection(ps1[0], ps1[1],
421
                    ps2[0], ps2[1]);
422

    
423
            double radio = interp.distance(lastp);
424

    
425
            if (UtilFunctions.isLowAngle(antp, lastp, interp, point)) {
426
                radio = -radio;
427
            }
428

    
429
            Point2D centerp = UtilFunctions.getPoint(interp, mediop, radio);
430

    
431
            drawLine((Graphics2D) g, lastp, point,DefaultCADTool.geometrySelectSymbol);
432

    
433
            IGeometry ig = ShapeFactory.createArc(lastp, centerp, point);
434

    
435
            if (ig != null) {
436
                ig.draw((Graphics2D) g,
437
                    getCadToolAdapter().getMapControl().getViewPort(),
438
                      DefaultCADTool.axisReferencesSymbol);
439
            }
440
        }
441
    }
442

    
443
    /**
444
     * Add a diferent option.
445
     *
446
     * @param sel DOCUMENT ME!
447
     * @param s Diferent option.
448
     */
449
    public void addOption(String s) {
450
            /*       PolylineCADToolState actualState = (PolylineCADToolState) _fsm.getPreviousState();
451
        String status = actualState.getName();
452

453
        if (status.equals("Polyline.NextPointOrArcOrClose")) {
454
            if (s.equals("A") || s.equals("a") || s.equals(PluginServices.getText(this,"inter_arc"))) {
455
                //Arco
456
            } else if (s.equals("C") || s.equals("c")) {
457
                GeneralPathX elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, 2);
458
                elShape.moveTo(antPoint.getX(), antPoint.getY());
459
                elShape.lineTo(firstPoint.getX(), firstPoint.getY());
460
                list.add(ShapeFactory.createPolyline2D(elShape));
461
                //closeGeometry();
462
            }
463
        } else if (status.equals("Polyline.NextPointOrLineOrClose")) {
464
            if (s.equals("N") || s.equals("n") || s.equals(PluginServices.getText(this,"inter_line"))) {
465
                //L?nea
466
            } else if (s.equals("C") || s.equals("c")) {
467
                GeneralPathX elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, 2);
468
                elShape.moveTo(antPoint.getX(), antPoint.getY());
469
                elShape.lineTo(firstPoint.getX(), firstPoint.getY());
470
                list.add(ShapeFactory.createPolyline2D(elShape));
471
                //closeGeometry();
472
            }
473
        }
474
  */
475
    }
476

    
477
    /* (non-Javadoc)
478
     * @see com.iver.cit.gvsig.gui.cad.CADTool#addvalue(double)
479
     */
480
    public void addValue(double d) {
481
    }
482

    
483
    public void cancel(){
484
        //endGeometry();
485
        list.clear();
486
        clearTemporalCache();
487
        antantPoint=antCenter=antInter=antPoint=firstPoint=null;
488
    }
489

    
490
    public void end() {
491
        /* CADExtension.setCADTool("polyline");
492
        PluginServices.getMainFrame().setSelectedTool("POLYLINE"); */
493
    }
494

    
495
    public String getName() {
496
        return PluginServices.getText(this,"polyline_");
497
    }
498

    
499
    public String toString() {
500
        return "_polyline";
501
    }
502
    public boolean isApplicable(int shapeType) {
503
        switch (shapeType) {
504
        case FShape.POINT:
505
        case FShape.MULTIPOINT:
506
            return false;
507
        }
508
        return true;
509
    }
510
}