Statistics
| Revision:

root / trunk / extensions / extCAD / src / com / iver / cit / gvsig / gui / cad / tools / EquidistanceCADTool.java @ 27149

History | View | Annotate | Download (14.6 KB)

1 8937 caballero
/* 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.event.InputEvent;
45
import java.awt.geom.Point2D;
46
import java.util.ArrayList;
47
48
import com.iver.andami.PluginServices;
49
import com.iver.cit.gvsig.CADExtension;
50
import com.iver.cit.gvsig.fmap.core.DefaultFeature;
51
import com.iver.cit.gvsig.fmap.core.FShape;
52
import com.iver.cit.gvsig.fmap.core.IGeometry;
53
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
54
import com.iver.cit.gvsig.fmap.edition.DefaultRowEdited;
55
import com.iver.cit.gvsig.fmap.edition.UtilFunctions;
56
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
57
import com.iver.cit.gvsig.gui.cad.DefaultCADTool;
58
import com.iver.cit.gvsig.gui.cad.exception.CommandException;
59
import com.iver.cit.gvsig.gui.cad.tools.smc.EquidistanceCADToolContext;
60
import com.iver.cit.gvsig.gui.cad.tools.smc.EquidistanceCADToolContext.EquidistanceCADToolState;
61
import com.iver.cit.gvsig.layers.VectorialLayerEdited;
62
import com.vividsolutions.jts.algorithm.CGAlgorithms;
63
import com.vividsolutions.jts.geom.Coordinate;
64
import com.vividsolutions.jts.geom.Geometry;
65
import com.vividsolutions.jts.geom.GeometryFactory;
66
import com.vividsolutions.jts.geom.LineString;
67
import com.vividsolutions.jts.geom.LinearRing;
68
import com.vividsolutions.jts.geom.Point;
69
import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
70
71
72
/**
73
 * Herramienta para crear una geometr?a equidistante a otra.
74
 *
75
 * @author Vicente Caballero Navarro
76
 */
77
public class EquidistanceCADTool extends DefaultCADTool {
78 23993 vcaballero
    protected EquidistanceCADToolContext _fsm;
79
    protected Point2D firstPoint=new Point2D.Double(800000,4500000);
80
    protected Point2D secondPoint=new Point2D.Double(810000,4500000);
81
        protected double distance=10;
82 8937 caballero
        private double distancePos=java.lang.Double.MAX_VALUE;
83
        private LineString distanceLine;
84
        /**
85
     * Crea un nuevo EquidistanceCADTool.
86
     */
87
    public EquidistanceCADTool() {
88
    }
89
90
    /**
91
     * M?todo de inicio, para poner el c?digo de todo lo que se requiera de una
92
     * carga previa a la utilizaci?n de la herramienta.
93
     */
94
    public void init() {
95
        _fsm = new EquidistanceCADToolContext(this);
96
97
    }
98
99
    private Coordinate[] getParallel(Point2D[] points,double distance) {
100
            Point2D[] pper=new Point2D[2];
101
            double angle=Math.toRadians(90)+UtilFunctions.getAngle(points[0],points[1]);
102
            pper[0]=UtilFunctions.getPoint(points[0],angle,distance);
103
            pper[1]=UtilFunctions.getPoint(points[1],angle,distance);
104
            Coordinate[] result=new Coordinate[2];
105
            result[0]=new Coordinate(pper[0].getX(),pper[0].getY());
106
            result[1]=new Coordinate(pper[1].getX(),pper[1].getY());
107
            return result;
108
    }
109
   /* (non-Javadoc)
110
     * @see com.iver.cit.gvsig.gui.cad.CADTool#transition(com.iver.cit.gvsig.fmap.layers.FBitSet, double, double)
111
     */
112
    public void transition(double x, double y, InputEvent event) {
113
        _fsm.addPoint(x, y, event);
114
    }
115
116
    /* (non-Javadoc)
117
     * @see com.iver.cit.gvsig.gui.cad.CADTool#transition(com.iver.cit.gvsig.fmap.layers.FBitSet, double)
118
     */
119
    public void transition(double d) {
120
        _fsm.addValue(d);
121
    }
122
123
    /* (non-Javadoc)
124
     * @see com.iver.cit.gvsig.gui.cad.CADTool#transition(com.iver.cit.gvsig.fmap.layers.FBitSet, java.lang.String)
125
     */
126
    public void transition(String s) throws CommandException {
127
            if (!super.changeCommand(s)){
128
                    _fsm.addOption(s);
129
            }
130
    }
131
132
    /**
133
     * DOCUMENT ME!
134
     */
135
    public void selection() {
136
       ArrayList selectedRows=getSelectedRows();
137
        if (selectedRows.size() == 0 && !CADExtension.getCADTool().getClass().getName().equals("com.iver.cit.gvsig.gui.cad.tools.SelectionCADTool")) {
138
            CADExtension.setCADTool("_selection",false);
139
            ((SelectionCADTool) CADExtension.getCADTool()).setNextTool(
140
                "_Equidistance");
141
        }
142
    }
143
144
    /**
145
     * Equivale al transition del prototipo pero sin pasarle como par?metro el
146
     * editableFeatureSource que ya estar? creado.
147
     *
148
     * @param x par?metro x del punto que se pase en esta transici?n.
149
     * @param y par?metro y del punto que se pase en esta transici?n.
150
     */
151
    public void addPoint(double x, double y,InputEvent event) {
152 23993 vcaballero
            EquidistanceCADToolState actualState = (EquidistanceCADToolState) _fsm.getPreviousState();
153
            String status = actualState.getName();
154
            if (status.equals("Equidistance.Distance")) {
155
                    firstPoint = new Point2D.Double(x, y);
156 8937 caballero
            } else if (status.equals("Equidistance.SecondPointDistance")) {
157
                    secondPoint = new Point2D.Double(x,y);
158
                    distance=secondPoint.distance(firstPoint);
159
            } else if (status.equals("Equidistance.Position")) {
160
                    ArrayList selectedRow = getSelectedRows();
161 23993 vcaballero
                    ArrayList selectedRowAux=new ArrayList();
162
                    VectorialLayerEdited vle = getVLE();
163
                    VectorialEditableAdapter vea = vle.getVEA();
164
                    PluginServices.getMDIManager().setWaitCursor();
165
                    vea.startComplexRow();
166
                    for (int i = 0; i < selectedRow.size(); i++) {
167
                            DefaultRowEdited row = (DefaultRowEdited) selectedRow
168
                            .get(i);
169
                            DefaultFeature fea = (DefaultFeature) row.getLinkedRow()
170
                            .cloneRow();
171
172
                            IGeometry geometry=compute(fea,new Point2D.Double(x,y));
173
                            addGeometry(geometry);
174
                    }
175
176
                    vea.endComplexRow(getName());
177
                    vle.setSelectionCache(VectorialLayerEdited.SAVEPREVIOUS, selectedRowAux);
178
                    //clearSelection();
179
                    //selectedRow.addAll(selectedRowAux);
180 8937 caballero
                    PluginServices.getMDIManager().restoreCursor();
181
            }
182
    }
183
184 23993 vcaballero
    protected IGeometry compute(DefaultFeature fea, Point2D position){
185 8937 caballero
                IGeometry geometry = fea.getGeometry();
186
                int typeGeometry = geometry.getGeometryType();
187
                Geometry g = geometry.toJTSGeometry();
188
                GeometryFactory factory=g.getFactory();
189
            Coordinate[] c2 = new Coordinate[2];
190
                Geometry g2 = null;
191
                Coordinate coordinatePosition=new Coordinate(position.getX(),position.getY());
192
                Point pPos=factory.createPoint(coordinatePosition);
193
                switch (typeGeometry) {
194
                case FShape.LINE:
195
196
                        LineString lR =factory.createLineString(g.getCoordinates());
197
                        g = TopologyPreservingSimplifier.simplify(lR, 10d);
198
                        Geometry gLine = g.getGeometryN(0);
199
                        Coordinate[] coordinatesLine = gLine.getCoordinates();
200
                        int numPointsLine = gLine.getNumPoints();
201
                        if (numPointsLine < 1)
202
                                return null;
203
                        LineString[] lineStrings = new LineString[numPointsLine - 1];
204
205
                        for (int j = 1; j < numPointsLine; j = j + 1) {
206
                                c2[0] = coordinatesLine[j - 1];
207
                                c2[1] = coordinatesLine[j];
208
                                LineString lS=factory.createLineString(c2);
209
                                if (lS.distance(pPos)<distancePos) {
210
                                        distancePos=lS.distance(pPos);
211
                                        distanceLine=(LineString)factory.createGeometry(lS);
212
                                }
213
                        }
214
                        setDistanceLine(coordinatePosition);
215
216
                        for (int j = 1; j < numPointsLine; j = j + 1) {
217
                                c2[0] = coordinatesLine[j - 1];
218
                                c2[1] = coordinatesLine[j];
219
                                Point2D[] points = new Point2D[2];
220
                                points[0] = new Point2D.Double(c2[0].x, c2[0].y);
221
                                points[1] = new Point2D.Double(c2[1].x, c2[1].y);
222
                                lineStrings[j - 1] = factory.createLineString(
223
                                                getParallel(points, distance));
224
                        }
225
226
                        for (int i = 0; i < lineStrings.length - 1; i++) {
227
                                Coordinate coord = lineStrings[i].getCoordinateN(0);
228
                                Point2D p1 = new Point2D.Double(coord.x, coord.y);
229
                                coord = lineStrings[i].getCoordinateN(1);
230
                                Point2D p2 = new Point2D.Double(coord.x, coord.y);
231
                                coord = lineStrings[i + 1].getCoordinateN(0);
232
                                Point2D p3 = new Point2D.Double(coord.x, coord.y);
233
                                coord = lineStrings[i + 1].getCoordinateN(1);
234
                                Point2D p4 = new Point2D.Double(coord.x, coord.y);
235
                                Point2D intersection = UtilFunctions.getIntersection(p1, p2,
236
                                                p3, p4);
237
                                Coordinate[] coords1 = new Coordinate[2];
238
                                coords1[0] = lineStrings[i].getCoordinateN(0);
239
                                coords1[1] = new Coordinate(intersection.getX(), intersection
240
                                                .getY());
241
                                lineStrings[i] = factory.createLineString(coords1);
242
                                Coordinate[] coords2 = new Coordinate[2];
243
                                coords2[0] = coords1[1];
244
                                coords2[1] = lineStrings[i + 1].getCoordinateN(1);
245
                                lineStrings[i + 1] = factory.createLineString(
246
                                                coords2);
247
                        }
248
                        g2 = factory.createMultiLineString(lineStrings);
249
                        return FConverter.jts_to_igeometry(g2);
250
                case FShape.POLYGON:
251
                case FShape.CIRCLE:
252
                case FShape.ELLIPSE:
253
                        g = TopologyPreservingSimplifier.simplify(g, 10d);
254
                        Geometry gPolygon = g.getGeometryN(0);
255
                        setDistancePolygon(gPolygon,pPos);
256
                        Coordinate[] coordinates = gPolygon.getCoordinates();
257
                        int numPointsPolygon = gPolygon.getNumPoints();
258
                        if (numPointsPolygon < 2)
259
                                return null;
260
                        LineString[] polygonStrings = new LineString[numPointsPolygon];
261
                        for (int j = 1; j < numPointsPolygon; j = j + 1) {
262
                                c2[0] = coordinates[j - 1];
263
                                c2[1] = coordinates[j];
264
                                Point2D[] points = new Point2D[2];
265
                                points[0] = new Point2D.Double(c2[0].x, c2[0].y);
266
                                points[1] = new Point2D.Double(c2[1].x, c2[1].y);
267
                                polygonStrings[j - 1] = factory.createLineString(
268
                                                getParallel(points, distance));
269
                        }
270
                        for (int i = 0; i < polygonStrings.length - 2; i++) {
271
                                Coordinate coord = polygonStrings[i].getCoordinateN(0);
272
                                Point2D p1 = new Point2D.Double(coord.x, coord.y);
273
                                coord = polygonStrings[i].getCoordinateN(1);
274
                                Point2D p2 = new Point2D.Double(coord.x, coord.y);
275
                                coord = polygonStrings[i + 1].getCoordinateN(0);
276
                                Point2D p3 = new Point2D.Double(coord.x, coord.y);
277
                                coord = polygonStrings[i + 1].getCoordinateN(1);
278
                                Point2D p4 = new Point2D.Double(coord.x, coord.y);
279
                                Point2D intersection = UtilFunctions.getIntersection(p1, p2,
280
                                                p3, p4);
281
                                Coordinate[] coords1 = new Coordinate[2];
282
                                coords1[0] = polygonStrings[i].getCoordinateN(0);
283
                                coords1[1] = new Coordinate(intersection.getX(), intersection
284
                                                .getY());
285
                                polygonStrings[i] = factory.createLineString(
286
                                                coords1);
287
                                Coordinate[] coords2 = new Coordinate[2];
288
                                coords2[0] = coords1[1];
289
                                coords2[1] = polygonStrings[i + 1].getCoordinateN(1);
290
                                polygonStrings[i + 1] = factory.createLineString(
291
                                                coords2);
292
                        }
293
294
                        // /////////////
295
                        Coordinate coord = polygonStrings[0].getCoordinateN(0);
296
                        Point2D p1 = new Point2D.Double(coord.x, coord.y);
297
                        coord = polygonStrings[0].getCoordinateN(1);
298
                        Point2D p2 = new Point2D.Double(coord.x, coord.y);
299
                        coord = polygonStrings[polygonStrings.length - 2].getCoordinateN(0);
300
                        Point2D p3 = new Point2D.Double(coord.x, coord.y);
301
                        coord = polygonStrings[polygonStrings.length - 2].getCoordinateN(1);
302
                        Point2D p4 = new Point2D.Double(coord.x, coord.y);
303
304
                        Point2D intersection = UtilFunctions
305
                                        .getIntersection(p1, p2, p3, p4);
306
                        Coordinate[] coords1 = new Coordinate[2];
307
                        coords1[0] = polygonStrings[polygonStrings.length - 2]
308
                                        .getCoordinateN(1);
309
                        coords1[1] = new Coordinate(intersection.getX(), intersection
310
                                        .getY());
311
                        polygonStrings[polygonStrings.length - 1] = factory
312
                                        .createLineString(coords1);
313
//                        LineString[] pol=new LineString[polygonStrings.length-1];
314
//                        for (int i=0;i<pol.length;i++) {
315
//                                pol[i]=polygonStrings[i];
316
//                        }
317
                        Coordinate[] coords2 = new Coordinate[2];
318
                        coords2[0] = coords1[1];
319
                        coords2[1] = polygonStrings[0].getCoordinateN(1);
320
                        polygonStrings[0] = factory.createLineString(coords2);
321
                        // ////////////////////////////////
322
                        Geometry geometryCollection = factory
323
                                        .createGeometryCollection(polygonStrings);
324
                        LinearRing linearRing = factory.createLinearRing(
325
                                        geometryCollection.getCoordinates());
326
                        LinearRing[] holes = new LinearRing[1];
327
                        holes[0] = factory.createLinearRing(new Coordinate[0]);
328
                        g2 = factory.createPolygon(linearRing, holes);
329
                        return FConverter.jts_to_igeometry(g2);
330
331
                case FShape.MULTIPOINT:
332
                case FShape.POINT:
333
                        break;
334
                default:
335
                        break;
336
                }
337
                return null;
338
        }
339
340
    private void setDistanceLine(Coordinate position) {
341
            Coordinate pStart=distanceLine.getCoordinateN(0);
342
            Coordinate pEnd=distanceLine.getCoordinateN(distanceLine.getNumPoints()-1);
343
            int pos=CGAlgorithms.computeOrientation(pStart,pEnd,position);
344
                   if (pos>0)
345
                            distance=Math.abs(distance);
346
                    else
347
                            distance=-Math.abs(distance);
348
                   distancePos=java.lang.Double.MAX_VALUE;
349
                   distanceLine=null;
350
        }
351
352
        private void setDistancePolygon(Geometry polygon, Geometry position) {
353
                boolean intersects=polygon.intersects(position);
354
                if (intersects)
355
                        distance=-Math.abs(distance);
356
                else
357
                        distance=Math.abs(distance);
358
        }
359
360
        /**
361
     * M?todo para dibujar la lo necesario para el estado en el que nos
362
     * encontremos.
363
     *
364
     * @param g Graphics sobre el que dibujar.
365
     * @param x par?metro x del punto que se pase para dibujar.
366
     * @param y par?metro x del punto que se pase para dibujar.
367
     */
368
    public void drawOperation(Graphics g, double x, double y) {
369
370
    }
371
    /**
372
         * Add a diferent option.
373
         *
374
         * @param s
375
         *            Diferent option.
376
         */
377
    public void addOption(String s) {
378
//            EquidistanceCADToolState actualState = (EquidistanceCADToolState) _fsm
379
//                                .getPreviousState();
380
//                String status = actualState.getName();
381
//                if (status.equals("Equidistance.Distance")) {
382
//                        distance=java.lang.Double.parseDouble(s);
383
//                }
384
    }
385
386
    /*
387
         * (non-Javadoc)
388
         *
389
         * @see com.iver.cit.gvsig.gui.cad.CADTool#addvalue(double)
390
         */
391
    public void addValue(double d) {
392
            EquidistanceCADToolState actualState = (EquidistanceCADToolState) _fsm
393
                .getPreviousState();
394
            String status = actualState.getName();
395
            if (status.equals("Equidistance.Distance")) {
396
                    distance=d;
397
            }
398
    }
399
400
        public String getName() {
401
                return PluginServices.getText(this,"Equidistance_");
402
        }
403
404
        public String toString() {
405
                return "_Equidistance";
406
        }
407
408
        public boolean isApplicable(int shapeType) {
409
                if (shapeType==FShape.POINT ||
410
                                shapeType==FShape.MULTIPOINT) {
411
                        return false;
412
                }
413
                return true;
414
        }
415
}