Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / edition / UtilFunctions.java @ 3768

History | View | Annotate | Download (14.8 KB)

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

    
46
import java.awt.Color;
47
import java.awt.Graphics;
48
import java.awt.Graphics2D;
49
import java.awt.geom.Arc2D;
50
import java.awt.geom.Line2D;
51
import java.awt.geom.Point2D;
52
import java.awt.geom.Rectangle2D;
53

    
54
import com.vividsolutions.jts.algorithm.RobustCGAlgorithms;
55
import com.vividsolutions.jts.geom.Coordinate;
56

    
57
/**
58
 * @author FJP
59
 *
60
 * TODO To change the template for this generated type comment go to
61
 * Window - Preferences - Java - Code Generation - Code and Comments
62
 */
63
public class UtilFunctions {
64
    static public Arc2D createCircle(Point2D p1, Point2D p2, Point2D p3) //, Graphics g)
65
    {
66
        double xC, yC, w, h;
67

    
68
        // Calculamos 2 secantes, tiramos perpendiculares por sus puntos
69
        // medios y obtenemos el centro. Luego calculamos el radio.
70
        // Puntos medios de los segmentos.
71
        double xm1, ym1, xm2, ym2;
72
        xm1 = (p1.getX() + p2.getX())/ 2.0;
73
        ym1 = (p1.getY() + p2.getY())/ 2.0;
74
        xm2 = (p2.getX() + p3.getX())/ 2.0;
75
        ym2 = (p2.getY() + p3.getY())/ 2.0;
76

    
77
        /* g.setColor(Color.GRAY);
78
        g.draw3DRect((int)xm1, (int) ym1, 1, 1, true);
79
        g.draw3DRect((int)xm2, (int) ym2, 1, 1, true); */
80
        // Pendientes de las perpendiculares y constantes
81
        double mP1=0, mP2=0, A1, A2;
82
        boolean bPerp1 = false, bPerp2 = false;
83
        if (p2.getY() - p1.getY() == 0)
84
        {
85
            A1 = ym1;
86
            bPerp1 = true;
87
        }
88
        else
89
        {
90
            mP1 = (p2.getX() - p1.getX()) /(p1.getY() - p2.getY());
91
            A1 = ym1 - xm1 * mP1;
92
        }
93
        if (p2.getY() - p3.getY() == 0)
94
        {
95
            A2 = ym2;
96
            bPerp2 = true;
97
        }
98
        else
99
        {
100
            mP2 = (p3.getX() - p2.getX()) /(p2.getY() - p3.getY());
101
            A2 = ym2 - xm2 * mP2;
102
        }
103
        if (mP2 == mP1)
104
        {
105
            return null; // Error, 3 puntos alineados. No puede pasar un arco
106
        }
107
        else
108
        {
109
            xC = (A2 - A1)/(mP1-mP2);
110
            if (!bPerp1)
111
                yC = xC * mP1 + A1;
112
            else
113
                yC = xC * mP2 + A2;
114
        }
115
        double Radio = p1.distance(xC, yC);
116
        double xR = xC - Radio ;
117
        double yR = yC - Radio ;
118
        w = 2.0* Radio;
119
        h = w;
120
        Rectangle2D.Double rBounds = new Rectangle2D.Double(xR,yR, w,h);
121
        Arc2D.Double resul = new Arc2D.Double(rBounds, 0.0, 360.0, Arc2D.OPEN);
122
                /* g.setColor(Color.RED);
123
                ((Graphics2D) g).draw(resul);
124
                g.setColor(Color.BLUE);
125
                ((Graphics2D) g).draw(rBounds);
126
                g.draw3DRect((int)p1.getX(), (int) p1.getY(), 1, 1, true);
127
                g.draw3DRect((int)p2.getX(), (int) p2.getY(), 2, 2, true);
128
                g.draw3DRect((int)p3.getX(), (int) p3.getY(), 1, 1, true);
129
                g.drawString("1", (int) p1.getX(), (int) p1.getY());
130
                g.drawString("2", (int) p2.getX(), (int) p2.getY());
131
                g.drawString("3", (int) p3.getX(), (int) p3.getY());
132
                g.drawString("C", (int) xC, (int) yC);
133
                g.draw3DRect((int)xC, (int) yC, 2, 2, true); */
134

    
135
        return resul;
136
    }
137
    /**
138
         * Obtiene un par de puntos que definen la recta perpendicular a p1-p2 que
139
         * pasa por el punto perp
140
         *
141
         * @param p1 punto de la recta p1-p2
142
         * @param p2 punto de la recta p1-p2
143
         * @param perp Punto por el que pasa la recta perpendicular, debe ser
144
         *                   distinto a p2
145
         *
146
         * @return Array con dos puntos que definen la recta resultante
147
         */
148
        public static Point2D[] getPerpendicular(Point2D p1, Point2D p2,
149
                Point2D perp) {
150
                if ((p2.getY() - p1.getY()) == 0) {
151
                        return new Point2D[] {
152
                                new Point2D.Double(perp.getX(), 0),
153
                                new Point2D.Double(perp.getX(), 1)
154
                        };
155
                }
156

    
157
                //Pendiente de la recta perpendicular
158
                double m = (p1.getX() - p2.getX()) / (p2.getY() - p1.getY());
159

    
160
                //b de la funcion de la recta perpendicular
161
                double b = perp.getY() - (m * perp.getX());
162

    
163
                //Obtenemos un par de puntos
164
                Point2D[] res = new Point2D[2];
165

    
166
                res[0] = new Point2D.Double(0, (m * 0) + b);
167
                res[1] = new Point2D.Double(1000, (m * 1000) + b);
168

    
169
                return res;
170
        }
171
        /**
172
         * Obtiene el punto que se encuentra a una distancia 'dist' de la recta
173
         * p1-p2 y se encuentra en la recta perpendicular que pasa por perpPoint
174
         *
175
         * @param p1 Punto de la recta p1-p2
176
         * @param p2 Punto de la recta p1-p2
177
         * @param perpPoint Punto de la recta perpendicular
178
         * @param dist Distancia del punto que se quiere obtener a la recta p1-p2
179
         *
180
         * @return DOCUMENT ME!
181
         */
182
        public static Point2D getPerpendicularPoint(Point2D p1, Point2D p2,
183
                Point2D perpPoint, double dist) {
184
                Point2D[] p = getPerpendicular(p1, p2, perpPoint);
185
                Point2D unit = getUnitVector(p[0], p[1]);
186

    
187
                return new Point2D.Double(perpPoint.getX() + (unit.getX() * dist),
188
                        perpPoint.getY() + (unit.getY() * dist));
189
        }
190

    
191
        /**
192
         * Devuelve un vector unitario en forma de punto a partir de dos puntos.
193
         *
194
         * @param p1 punto origen.
195
         * @param p2 punto destino.
196
         *
197
         * @return vector unitario.
198
         */
199
        public static Point2D getUnitVector(Point2D p1, Point2D p2) {
200
                Point2D paux = new Point2D.Double(p2.getX() - p1.getX(),
201
                                p2.getY() - p1.getY());
202
                double v = Math.sqrt(Math.pow((double) paux.getX(), (double) 2) +
203
                                Math.pow((double) paux.getY(), (double) 2));
204
                paux = new Point2D.Double(paux.getX() / v, paux.getY() / v);
205

    
206
                return paux;
207
        }
208
        /**
209
         * Obtiene el centro del c?rculo que pasa por los tres puntos que se pasan
210
         * como  par?metro
211
         *
212
         * @param p1 primer punto del c?rculo cuyo centro se quiere obtener
213
         * @param p2 segundo punto del c?rculo cuyo centro se quiere obtener
214
         * @param p3 tercer punto del c?rculo cuyo centro se quiere obtener
215
         *
216
         * @return Devuelve null si los puntos est?n alineados o no son 3 puntos
217
         *                    distintos
218
         */
219
        public static Point2D getCenter(Point2D p1, Point2D p2, Point2D p3) {
220
                if (p1.equals(p2) || p2.equals(p3) || p1.equals(p3)) {
221
                        return null;
222
                }
223

    
224
                Point2D[] perp1 = getPerpendicular(p1, p2,
225
                                new Point2D.Double((p1.getX() + p2.getX()) / 2,
226
                                        (p1.getY() + p2.getY()) / 2));
227
                Point2D[] perp2 = getPerpendicular(p2, p3,
228
                                new Point2D.Double((p2.getX() + p3.getX()) / 2,
229
                                        (p2.getY() + p3.getY()) / 2));
230

    
231
                return getIntersection(perp1[0], perp1[1], perp2[0], perp2[1]);
232
        }
233
        /**
234
         * Devuelve el punto de la intersecci?n entre las lineas p1-p2 y p3-p4.
235
         *
236
         * @param p1 punto de la recta p1-p2
237
         * @param p2 punto de la recta p1-p2
238
         * @param p3 punto de la recta p3-p4
239
         * @param p4 punto de la recta p3-p4
240
         *
241
         * @return DOCUMENT ME!
242
         *
243
         * @throws RuntimeException DOCUMENT ME!
244
         */
245
        public static Point2D getIntersection(Point2D p1, Point2D p2, Point2D p3,
246
                Point2D p4) {
247
                double m1 = Double.POSITIVE_INFINITY;
248

    
249
                if ((p2.getX() - p1.getX()) != 0) {
250
                        m1 = (p2.getY() - p1.getY()) / (p2.getX() - p1.getX());
251
                }
252

    
253
                double m2 = Double.POSITIVE_INFINITY;
254

    
255
                if ((p4.getX() - p3.getX()) != 0) {
256
                        m2 = (p4.getY() - p3.getY()) / (p4.getX() - p3.getX());
257
                }
258

    
259
                if ((m1 == Double.POSITIVE_INFINITY) &&
260
                                (m2 == Double.POSITIVE_INFINITY)) {
261
                        return null;
262
                }
263

    
264
                double b1 = p2.getY() - (m1 * p2.getX());
265

    
266
                double b2 = p4.getY() - (m2 * p4.getX());
267

    
268
                if ((m1 != Double.POSITIVE_INFINITY) &&
269
                                (m2 != Double.POSITIVE_INFINITY)) {
270
                        if (m1 == m2) {
271
                                return null;
272
                        }
273

    
274
                        double x = (b2 - b1) / (m1 - m2);
275

    
276
                        return new Point2D.Double(x, (m1 * x) + b1);
277
                } else if (m1 == Double.POSITIVE_INFINITY) {
278
                        double x = p1.getX();
279

    
280
                        return new Point2D.Double(x, (m2 * x) + b2);
281
                } else if (m2 == Double.POSITIVE_INFINITY) {
282
                        double x = p3.getX();
283

    
284
                        return new Point2D.Double(x, (m1 * x) + b1);
285
                }
286

    
287
                //no llega nunca
288
                throw new RuntimeException("BUG!");
289
        }
290
        /**
291
         * Obtiene el ?ngulo del vector que se pasa como par?metro con el vector
292
         * horizontal de izquierda a derecha
293
         *
294
         * @param start punto origen del vector
295
         * @param end punto destino del vector
296
         *
297
         * @return angulo en radianes
298
         */
299
        public static double getAngle(Point2D start, Point2D end) {
300
                double angle = Math.acos((end.getX() - start.getX()) / start.distance(
301
                                        end));
302

    
303
                if (start.getY() > end.getY()) {
304
                        angle = -angle;
305
                }
306

    
307
                if (angle < 0) {
308
                        angle += (2 * Math.PI);
309
                }
310

    
311
                return angle;
312
        }
313
        /**
314
         * Devuelve la distancia desde angle1 a angle2. Angulo en radianes de
315
         * diferencia entre angle1 y angle2 en sentido antihorario
316
         *
317
         * @param angle1 angulo en radianes. Debe ser positivo y no dar ninguna
318
         *                   vuelta a la circunferencia
319
         * @param angle2 angulo en radianes. Debe ser positivo y no dar ninguna
320
         *                   vuelta a la circunferencia
321
         *
322
         * @return distancia entre los ?ngulos
323
         */
324
        public static double angleDistance(double angle1, double angle2) {
325
                if (angle1 < angle2) {
326
                        return angle2 - angle1;
327
                } else {
328
                        return ((Math.PI * 2) - angle1) + angle2;
329
                }
330
        }
331
        /**
332
         * Devuelve el punto de la recta que viene dada por los puntos p1 y p2 a
333
         * una distancia radio de p1.
334
         *
335
         * @param p1 DOCUMENT ME!
336
         * @param p2 DOCUMENT ME!
337
         * @param radio DOCUMENT ME!
338
         *
339
         * @return DOCUMENT ME!
340
         */
341
        public static Point2D getPoint(Point2D p1, Point2D p2, double radio) {
342
                Point2D paux = new Point2D.Double(p2.getX() - p1.getX(),
343
                                p2.getY() - p1.getY());
344
                double v = Math.sqrt(Math.pow((double) paux.getX(), (double) 2) +
345
                                Math.pow((double) paux.getY(), (double) 2));
346
                paux = new Point2D.Double(paux.getX() / v, paux.getY() / v);
347

    
348
                Point2D aux1 = new Point2D.Double(p1.getX() + (radio * paux.getX()),
349
                                p1.getY() + (radio * paux.getY()));
350

    
351
                return aux1;
352
        }
353
        /**
354
         * Devuelve la menor distancia desde angle1 a angle2.
355
         *
356
         * @param angle1 angulo en radianes. Debe ser positivo y no dar ninguna
357
         *                   vuelta a la circunferencia
358
         * @param angle2 angulo en radianes. Debe ser positivo y no dar ninguna
359
         *                   vuelta a la circunferencia
360
         *
361
         * @return distancia entre los ?ngulos
362
         */
363
        public static double absoluteAngleDistance(double angle1, double angle2) {
364
                double d = Math.abs(angle1 - angle2);
365

    
366
                if (d < Math.PI) {
367
                        return d;
368
                } else {
369
                        if (angle1 < angle2) {
370
                                angle2 -= (Math.PI * 2);
371
                        } else {
372
                                angle1 -= (Math.PI * 2);
373
                        }
374

    
375
                        return Math.abs(angle1 - angle2);
376
                }
377
        }
378
        /**
379
         * Obtiene un arco a partir de 3 puntos. Devuelve null si no se puede crear
380
         * el arco porque los puntos est?n alineados o los 3 puntos no son
381
         * distintos
382
         *
383
         * @param p1
384
         * @param p2
385
         * @param p3
386
         *
387
         * @return Arco
388
         */
389
        public static Arc2D createArc(Point2D p1, Point2D p2, Point2D p3) {
390
                Point2D center = getCenter(p1, p2, p3);
391

    
392
                if (center == null) {
393
                        return null;
394
                }
395

    
396
                double angle1 = getAngle(center, p1);
397
                double angle2 = getAngle(center, p3);
398
                double extent = angleDistance(angle1, angle2);
399

    
400
                Coordinate[] coords = new Coordinate[4];
401
                coords[0] = new Coordinate(p1.getX(), p1.getY());
402
                coords[1] = new Coordinate(p2.getX(), p2.getY());
403
                coords[2] = new Coordinate(p3.getX(), p3.getY());
404
                coords[3] = new Coordinate(p1.getX(), p1.getY());
405

    
406
                if (!RobustCGAlgorithms.isCCW(coords)) {
407
                        extent = (Math.PI * 2) - extent;
408
                } else {
409
                        extent = -extent;
410
                }
411

    
412
                //System.err.println("angle1:" + angle1);
413
                //System.err.println("angle2:" + getAngle(center, p2));
414
                //System.err.println("angle3:" + angle2);
415
                //System.err.println("extent:" + extent);
416
                double Radio = p1.distance(center);
417
                double xR = center.getX() - Radio;
418
                double yR = center.getY() - Radio;
419
                double w = 2.0 * Radio;
420
                double h = w;
421

    
422
                Rectangle2D.Double rBounds = new Rectangle2D.Double(xR, yR, w, h);
423
                Arc2D.Double resul = new Arc2D.Double(rBounds,
424
                                Math.toDegrees((Math.PI * 2) - angle1), Math.toDegrees(extent),
425
                                Arc2D.OPEN);
426

    
427
                return resul;
428
        }
429
        /**
430
         * DOCUMENT ME!
431
         *
432
         * @param antp DOCUMENT ME!
433
         * @param lastp DOCUMENT ME!
434
         * @param interp DOCUMENT ME!
435
         * @param point DOCUMENT ME!
436
         *
437
         * @return DOCUMENT ME!
438
         */
439
        public static boolean isLowAngle(Point2D antp, Point2D lastp,
440
                Point2D interp, Point2D point) {
441
                ///double ob=lastp.distance(point);
442
                ///Point2D[] aux=getPerpendicular(lastp,interp,point);
443
                ///Point2D intersect=getIntersection(aux[0],aux[1],lastp,interp);
444
                ///double pb=intersect.distance(point);
445
                ///double a=Math.asin(pb/ob);
446
                Coordinate[] coords = new Coordinate[4];
447
                coords[0] = new Coordinate(lastp.getX(), lastp.getY());
448
                coords[1] = new Coordinate(interp.getX(), interp.getY());
449
                coords[2] = new Coordinate(point.getX(), point.getY());
450
                coords[3] = new Coordinate(lastp.getX(), lastp.getY());
451

    
452
                try {
453
                        double angle1 = getAngle(antp, lastp);
454
                        System.out.println("angle1= " + angle1);
455

    
456
                        double angle2 = getAngle(lastp, point);
457
                        System.out.println("angle2= " + angle2);
458

    
459
                        /*if (lastp.getX()<antp.getX()){
460
                           System.out.println("angleDiff 2 1= "+angleDistance(angle2,angle1));
461
                           System.out.println("angleDiff 1 2= "+angleDistance(angle1,angle2));
462
                           if (angleDistance(angle2,angle1)>Math.PI){
463

464
                           if (RobustCGAlgorithms.isCCW(coords)) {
465
                                   System.out.println("izquierda,arriba,true");
466
                                   return true;
467
                           } else{
468
                                   System.out.println("izquierda,arriba,false");
469
                           }
470
                           }else {
471
                                   if (!RobustCGAlgorithms.isCCW(coords)) {
472
                                           System.out.println("izquierda,abajo,true");
473
                                           return true;
474
                                   } else{
475
                                           System.out.println("izquierda,abajo,false");
476
                                   }
477
                           }
478
                           }else if (lastp.getX()>antp.getX()){
479
                         */
480
                        System.out.println("angleDifl 2 1= " +
481
                                angleDistance(angle2, angle1));
482
                        System.out.println("angleDifl 1 2= " +
483
                                angleDistance(angle1, angle2));
484

    
485
                        if (angleDistance(angle2, angle1) > Math.PI) {
486
                                if (RobustCGAlgorithms.isCCW(coords)) {
487
                                        System.out.println("derecha,arriba,true");
488

    
489
                                        return true;
490
                                } else {
491
                                        System.out.println("derecha,arriba,false");
492
                                }
493
                        } else {
494
                                if (!RobustCGAlgorithms.isCCW(coords)) {
495
                                        System.out.println("derecha,abajo,true");
496

    
497
                                        return true;
498
                                } else {
499
                                        System.out.println("derecha,abajo,false");
500
                                }
501
                        }
502

    
503
                        //}
504
                } catch (Exception e) {
505
                        System.out.println("false");
506

    
507
                        return true;
508
                }
509

    
510
                return false;
511
        }
512

    
513
}