Statistics
| Revision:

svn-gvsig-desktop / branches / pilotoDWG / libraries / libFMap / src / com / iver / cit / gvsig / fmap / edition / cad / TrigonometricalFunctions.java @ 1548

History | View | Annotate | Download (16.5 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.cad;
45

    
46
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
47

    
48
import com.vividsolutions.jts.algorithm.LineIntersector;
49
import com.vividsolutions.jts.algorithm.RobustCGAlgorithms;
50
import com.vividsolutions.jts.geom.Coordinate;
51
import com.vividsolutions.jts.geom.GeometryFactory;
52
import com.vividsolutions.jts.geom.LineString;
53
import com.vividsolutions.jts.operation.linemerge.LineMerger;
54

    
55
import java.awt.geom.Arc2D;
56
import java.awt.geom.Line2D;
57
import java.awt.geom.Point2D;
58
import java.awt.geom.Rectangle2D;
59

    
60

    
61
/**
62
 * Funciones de utilidad relacionadas con trigonometr?a
63
 */
64
public class TrigonometricalFunctions {
65
        /**
66
         * Obtiene un par de puntos que definen la recta perpendicular a p1-p2 que
67
         * pasa por el punto perp
68
         *
69
         * @param p1 punto de la recta p1-p2
70
         * @param p2 punto de la recta p1-p2
71
         * @param perp Punto por el que pasa la recta perpendicular, debe ser
72
         *                   distinto a p2
73
         *
74
         * @return Array con dos puntos que definen la recta resultante
75
         */
76
        public static Point2D[] getPerpendicular(Point2D p1, Point2D p2,
77
                Point2D perp) {
78
                if ((p2.getY() - p1.getY()) == 0) {
79
                        return new Point2D[] {
80
                                new Point2D.Double(perp.getX(), 0),
81
                                new Point2D.Double(perp.getX(), 1)
82
                        };
83
                }
84

    
85
                //Pendiente de la recta perpendicular
86
                double m = (p1.getX() - p2.getX()) / (p2.getY() - p1.getY());
87

    
88
                //b de la funcion de la recta perpendicular
89
                double b = perp.getY() - (m * perp.getX());
90

    
91
                //Obtenemos un par de puntos
92
                Point2D[] res = new Point2D[2];
93

    
94
                res[0] = new Point2D.Double(0, (m * 0) + b);
95
                res[1] = new Point2D.Double(1000, (m * 1000) + b);
96

    
97
                return res;
98
        }
99

    
100
        /**
101
         * Obtiene un arco a partir de 3 puntos. Devuelve null si no se puede crear
102
         * el arco porque los puntos est?n alineados o los 3 puntos no son distintos
103
         *
104
         * @param p1
105
         * @param p2
106
         * @param p3
107
         *
108
         * @return Arco
109
         */
110
        public static Arc2D createArc(Point2D p1, Point2D p2, Point2D p3) {
111
                Point2D center = getCenter(p1, p2, p3);
112
                if (center == null) return null;
113
                double angle1 = getAngle(center, p1);
114
                double angle2 = getAngle(center, p3);
115
                double extent = angleDistance(angle1, angle2);
116

    
117
                Coordinate[] coords = new Coordinate[4];
118
                coords[0] = new Coordinate(p1.getX(), p1.getY());
119
                coords[1] = new Coordinate(p2.getX(), p2.getY());
120
                coords[2] = new Coordinate(p3.getX(), p3.getY());
121
                coords[3] = new Coordinate(p1.getX(), p1.getY());
122

    
123
                if (!RobustCGAlgorithms.isCCW(coords)) {
124
                        extent = (Math.PI * 2) - extent;
125
                } else {
126
                        extent = -extent;
127
                }
128

    
129
                //System.err.println("angle1:" + angle1);
130
                //System.err.println("angle2:" + getAngle(center, p2));
131
                //System.err.println("angle3:" + angle2);
132
                //System.err.println("extent:" + extent);
133
                double Radio = p1.distance(center);
134
                double xR = center.getX() - Radio;
135
                double yR = center.getY() - Radio;
136
                double w = 2.0 * Radio;
137
                double h = w;
138

    
139
                Rectangle2D.Double rBounds = new Rectangle2D.Double(xR, yR, w, h);
140
                Arc2D.Double resul = new Arc2D.Double(rBounds,
141
                                Math.toDegrees((Math.PI * 2) - angle1), Math.toDegrees(extent),
142
                                Arc2D.OPEN);
143

    
144
                return resul;
145
        }
146

    
147
        /**
148
         * Obtiene el punto que se encuentra a una distancia 'dist' de la recta
149
         * p1-p2 y se encuentra en la recta perpendicular que pasa por perpPoint
150
         *
151
         * @param p1 Punto de la recta p1-p2
152
         * @param p2 Punto de la recta p1-p2
153
         * @param perpPoint Punto de la recta perpendicular
154
         * @param dist Distancia del punto que se quiere obtener a la recta p1-p2
155
         *
156
         * @return DOCUMENT ME!
157
         */
158
        public static Point2D getPerpendicularPoint(Point2D p1, Point2D p2,
159
                Point2D perpPoint, double dist) {
160
                Point2D[] p=getPerpendicular(p1,p2,perpPoint);
161
                Point2D unit=getUnitVector(p[0],p[1]);
162
                return new Point2D.Double(perpPoint.getX()+unit.getX()*dist,perpPoint.getY()+unit.getY()*dist);
163
        }
164

    
165
        /**
166
         * Obtiene el centro del c?rculo que pasa por los tres puntos que se pasan como 
167
         * par?metro
168
         *
169
         * @param p1 primer punto del c?rculo cuyo centro se quiere obtener
170
         * @param p2 segundo punto del c?rculo cuyo centro se quiere obtener
171
         * @param p3 tercer punto del c?rculo cuyo centro se quiere obtener
172
         *
173
         * @return Devuelve null si los puntos est?n alineados o no son 3 puntos distintos
174
         */
175
        public static Point2D getCenter(Point2D p1, Point2D p2, Point2D p3) {
176
                if (p1.equals(p2) || p2.equals(p3) || p1.equals(p3)) {
177
                        return null;
178
                }
179

    
180
                Point2D[] perp1 = getPerpendicular(p1, p2,
181
                                new Point2D.Double((p1.getX() + p2.getX()) / 2,
182
                                        (p1.getY() + p2.getY()) / 2));
183
                Point2D[] perp2 = getPerpendicular(p2, p3,
184
                                new Point2D.Double((p2.getX() + p3.getX()) / 2,
185
                                        (p2.getY() + p3.getY()) / 2));
186

    
187
                return getIntersection(perp1[0], perp1[1], perp2[0], perp2[1]);
188
        }
189

    
190
        /**
191
         * Obtiene el centro del circulo que pasa por los puntos p1, p2 y p3
192
         *
193
         * @param p1
194
         * @param p2
195
         * @param p3
196
         *
197
         * @return Devuelve el punto o null si no hay ning?n c?rculo (puntos
198
         *                    alineados)
199
         */
200
        public static Point2D getCircleCenter(Point2D p1, Point2D p2, Point2D p3) {
201
                double xC;
202
                double yC;
203
                double w;
204
                double h;
205

    
206
                // Calculamos 2 secantes, tiramos perpendiculares por sus puntos
207
                // medios y obtenemos el centro. Luego calculamos el radio.
208
                // Puntos medios de los segmentos.
209
                double xm1;
210

    
211
                // Calculamos 2 secantes, tiramos perpendiculares por sus puntos
212
                // medios y obtenemos el centro. Luego calculamos el radio.
213
                // Puntos medios de los segmentos.
214
                double ym1;
215

    
216
                // Calculamos 2 secantes, tiramos perpendiculares por sus puntos
217
                // medios y obtenemos el centro. Luego calculamos el radio.
218
                // Puntos medios de los segmentos.
219
                double xm2;
220

    
221
                // Calculamos 2 secantes, tiramos perpendiculares por sus puntos
222
                // medios y obtenemos el centro. Luego calculamos el radio.
223
                // Puntos medios de los segmentos.
224
                double ym2;
225
                xm1 = (p1.getX() + p2.getX()) / 2.0;
226
                ym1 = (p1.getY() + p2.getY()) / 2.0;
227
                xm2 = (p2.getX() + p3.getX()) / 2.0;
228
                ym2 = (p2.getY() + p3.getY()) / 2.0;
229

    
230
                /*
231
                 * g.setColor(Color.GRAY); g.draw3DRect((int)xm1, (int) ym1, 1, 1,
232
                 * true); g.draw3DRect((int)xm2, (int) ym2, 1, 1, true);
233
                 */
234

    
235
                // Pendientes de las perpendiculares y constantes
236
                double mP1 = 0;
237

    
238
                /*
239
                 * g.setColor(Color.GRAY); g.draw3DRect((int)xm1, (int) ym1, 1, 1,
240
                 * true); g.draw3DRect((int)xm2, (int) ym2, 1, 1, true);
241
                 */
242

    
243
                // Pendientes de las perpendiculares y constantes
244
                double mP2 = 0;
245

    
246
                /*
247
                 * g.setColor(Color.GRAY); g.draw3DRect((int)xm1, (int) ym1, 1, 1,
248
                 * true); g.draw3DRect((int)xm2, (int) ym2, 1, 1, true);
249
                 */
250

    
251
                // Pendientes de las perpendiculares y constantes
252
                double A1;
253

    
254
                /*
255
                 * g.setColor(Color.GRAY); g.draw3DRect((int)xm1, (int) ym1, 1, 1,
256
                 * true); g.draw3DRect((int)xm2, (int) ym2, 1, 1, true);
257
                 */
258

    
259
                // Pendientes de las perpendiculares y constantes
260
                double A2;
261
                boolean bPerp1 = false;
262
                boolean bPerp2 = false;
263

    
264
                if ((p2.getY() - p1.getY()) == 0) {
265
                        A1 = ym1;
266
                        bPerp1 = true;
267
                } else {
268
                        mP1 = (p2.getX() - p1.getX()) / (p1.getY() - p2.getY());
269
                        A1 = ym1 - (xm1 * mP1);
270
                }
271

    
272
                if ((p2.getY() - p3.getY()) == 0) {
273
                        A2 = ym2;
274
                        bPerp2 = true;
275
                } else {
276
                        mP2 = (p3.getX() - p2.getX()) / (p2.getY() - p3.getY());
277
                        A2 = ym2 - (xm2 * mP2);
278
                }
279

    
280
                if (mP2 == mP1) {
281
                        return null; // Error, 3 puntos alineados. No puede pasar un arco
282
                } else {
283
                        xC = (A2 - A1) / (mP1 - mP2);
284

    
285
                        if (!bPerp1) {
286
                                yC = (xC * mP1) + A1;
287
                        } else {
288
                                yC = (xC * mP2) + A2;
289
                        }
290
                }
291

    
292
                return new Point2D.Double(xC, yC);
293
        }
294

    
295
        /**
296
         * Obtiene un c?rculo a partir de 3 puntos. Devuelve null si no se puede
297
         * crear el c?ruclo porque los puntos est?n alineados
298
         *
299
         * @param p1
300
         * @param p2
301
         * @param p3
302
         *
303
         * @return C?rculo
304
         */
305
        static public Arc2D createCircle(Point2D p1, Point2D p2, Point2D p3) //,
306
        // Graphics
307
        // g)
308
         {
309
                Point2D center = getCircleCenter(p1, p2, p3);
310

    
311
                double Radio = p1.distance(center);
312
                double xR = center.getX() - Radio;
313
                double yR = center.getY() - Radio;
314
                double w = 2.0 * Radio;
315
                double h = w;
316

    
317
                Rectangle2D.Double rBounds = new Rectangle2D.Double(xR, yR, w, h);
318
                Arc2D.Double resul = new Arc2D.Double(rBounds, 0.0, 360.0, Arc2D.OPEN);
319

    
320
                return resul;
321
        }
322

    
323
        /**
324
         * Obtiene el ?ngulo del vector que se pasa como par?metro con el vector
325
         * horizontal de izquierda a derecha
326
         *
327
         * @param start punto origen del vector
328
         * @param end punto destino del vector
329
         *
330
         * @return angulo en radianes
331
         */
332
        public static double getAngle(Point2D start, Point2D end) {
333
                double angle = Math.acos((end.getX() - start.getX()) / start.distance(
334
                                        end));
335

    
336
                if (start.getY() > end.getY()) {
337
                        angle = -angle;
338
                }
339

    
340
                if (angle < 0) {
341
                        angle += (2 * Math.PI);
342
                }
343

    
344
                return angle;
345
        }
346

    
347
        /**
348
         * Devuelve la distancia desde angle1 a angle2. Angulo en radianes de
349
         * diferencia entre angle1 y angle2 en sentido antihorario
350
         *
351
         * @param angle1 angulo en radianes. Debe ser positivo y no dar ninguna
352
         *                   vuelta a la circunferencia
353
         * @param angle2 angulo en radianes. Debe ser positivo y no dar ninguna
354
         *                   vuelta a la circunferencia
355
         *
356
         * @return distancia entre los ?ngulos
357
         */
358
        public static double angleDistance(double angle1, double angle2) {
359
                if (angle1 < angle2) {
360
                        return angle2 - angle1;
361
                } else {
362
                        return ((Math.PI * 2) - angle1) + angle2;
363
                }
364
        }
365

    
366
        /**
367
         * Devuelve el punto de la recta que viene dada por los puntos p1 y p2 a
368
         * una distancia radio de p1.
369
         *
370
         * @param p1 DOCUMENT ME!
371
         * @param p2 DOCUMENT ME!
372
         * @param radio DOCUMENT ME!
373
         *
374
         * @return DOCUMENT ME!
375
         */
376
        public static Point2D getPoint(Point2D p1, Point2D p2, double radio) {
377
                Point2D paux = new Point2D.Double(p2.getX() - p1.getX(),
378
                                p2.getY() - p1.getY());
379
                double v = Math.sqrt(Math.pow((double) paux.getX(), (double) 2) +
380
                                Math.pow((double) paux.getY(), (double) 2));
381
                paux = new Point2D.Double(paux.getX() / v, paux.getY() / v);
382

    
383
                Point2D aux1 = new Point2D.Double(p1.getX() + (radio * paux.getX()),
384
                                p1.getY() + (radio * paux.getY()));
385

    
386
                return aux1;
387
        }
388

    
389
        /**
390
         * Devuelve la menor distancia desde angle1 a angle2.
391
         *
392
         * @param angle1 angulo en radianes. Debe ser positivo y no dar ninguna
393
         *                   vuelta a la circunferencia
394
         * @param angle2 angulo en radianes. Debe ser positivo y no dar ninguna
395
         *                   vuelta a la circunferencia
396
         *
397
         * @return distancia entre los ?ngulos
398
         */
399
        public static double absoluteAngleDistance(double angle1, double angle2) {
400
                double d = Math.abs(angle1 - angle2);
401

    
402
                if (d < Math.PI) {
403
                        return d;
404
                } else {
405
                        if (angle1 < angle2) {
406
                                angle2 -= (Math.PI * 2);
407
                        } else {
408
                                angle1 -= (Math.PI * 2);
409
                        }
410

    
411
                        return Math.abs(angle1 - angle2);
412
                }
413
        }
414

    
415
        /**
416
         * Devuelve el punto de la intersecci?n entre las lineas p1-p2 y p3-p4.
417
         *
418
         * @param p1 punto de la recta p1-p2
419
         * @param p2 punto de la recta p1-p2
420
         * @param p3 punto de la recta p3-p4
421
         * @param p4 punto de la recta p3-p4
422
         *
423
         * @return DOCUMENT ME!
424
         *
425
         * @throws RuntimeException DOCUMENT ME!
426
         */
427
        public static Point2D getIntersection(Point2D p1, Point2D p2, Point2D p3,
428
                Point2D p4) {
429
                double m1 = Double.POSITIVE_INFINITY;
430

    
431
                if ((p2.getX() - p1.getX()) != 0) {
432
                        m1 = (p2.getY() - p1.getY()) / (p2.getX() - p1.getX());
433
                }
434

    
435
                double m2 = Double.POSITIVE_INFINITY;
436

    
437
                if ((p4.getX() - p3.getX()) != 0) {
438
                        m2 = (p4.getY() - p3.getY()) / (p4.getX() - p3.getX());
439
                }
440

    
441
                if ((m1 == Double.POSITIVE_INFINITY) &&
442
                                (m2 == Double.POSITIVE_INFINITY)) {
443
                        return null;
444
                }
445

    
446
                double b1 = p2.getY() - (m1 * p2.getX());
447

    
448
                double b2 = p4.getY() - (m2 * p4.getX());
449

    
450
                if ((m1 != Double.POSITIVE_INFINITY) &&
451
                                (m2 != Double.POSITIVE_INFINITY)) {
452
                        if (m1 == m2) {
453
                                return null;
454
                        }
455

    
456
                        double x = (b2 - b1) / (m1 - m2);
457

    
458
                        return new Point2D.Double(x, (m1 * x) + b1);
459
                } else if (m1 == Double.POSITIVE_INFINITY) {
460
                        double x = p1.getX();
461

    
462
                        return new Point2D.Double(x, (m2 * x) + b2);
463
                } else if (m2 == Double.POSITIVE_INFINITY) {
464
                        double x = p3.getX();
465

    
466
                        return new Point2D.Double(x, (m1 * x) + b1);
467
                }
468

    
469
                //no llega nunca
470
                throw new RuntimeException("BUG!");
471
        }
472

    
473
        /**
474
         * Devuelve un vector unitario en forma de punto a partir de dos puntos.
475
         *
476
         * @param p1 punto origen.
477
         * @param p2 punto destino.
478
         *
479
         * @return vector unitario.
480
         */
481
        public static Point2D getUnitVector(Point2D p1, Point2D p2) {
482
                Point2D paux = new Point2D.Double(p2.getX() - p1.getX(),
483
                                p2.getY() - p1.getY());
484
                double v = Math.sqrt(Math.pow((double) paux.getX(), (double) 2) +
485
                                Math.pow((double) paux.getY(), (double) 2));
486
                paux = new Point2D.Double(paux.getX() / v, paux.getY() / v);
487

    
488
                return paux;
489
        }
490

    
491
        /**
492
         * DOCUMENT ME!
493
         *
494
         * @param antp DOCUMENT ME!
495
         * @param lastp DOCUMENT ME!
496
         * @param interp DOCUMENT ME!
497
         * @param point DOCUMENT ME!
498
         *
499
         * @return DOCUMENT ME!
500
         */
501
        public static boolean isLowAngle(Point2D antp, Point2D lastp,
502
                Point2D interp, Point2D point) {
503
                ///double ob=lastp.distance(point);
504
                ///Point2D[] aux=getPerpendicular(lastp,interp,point);
505
                ///Point2D intersect=getIntersection(aux[0],aux[1],lastp,interp);
506
                ///double pb=intersect.distance(point);
507
                ///double a=Math.asin(pb/ob);
508
                Coordinate[] coords = new Coordinate[4];
509
                coords[0] = new Coordinate(lastp.getX(), lastp.getY());
510
                coords[1] = new Coordinate(interp.getX(), interp.getY());
511
                coords[2] = new Coordinate(point.getX(), point.getY());
512
                coords[3] = new Coordinate(lastp.getX(), lastp.getY());
513

    
514
                try {
515
                        double angle1 = getAngle(antp, lastp);
516
                        System.out.println("angle1= " + angle1);
517

    
518
                        double angle2 = getAngle(lastp, point);
519
                        System.out.println("angle2= " + angle2);
520

    
521
                        /*if (lastp.getX()<antp.getX()){
522
                           System.out.println("angleDiff 2 1= "+angleDistance(angle2,angle1));
523
                           System.out.println("angleDiff 1 2= "+angleDistance(angle1,angle2));
524
                           if (angleDistance(angle2,angle1)>Math.PI){
525
                        
526
                           if (RobustCGAlgorithms.isCCW(coords)) {
527
                                   System.out.println("izquierda,arriba,true");
528
                                   return true;
529
                           } else{
530
                                   System.out.println("izquierda,arriba,false");
531
                           }
532
                           }else {
533
                                   if (!RobustCGAlgorithms.isCCW(coords)) {
534
                                           System.out.println("izquierda,abajo,true");
535
                                           return true;
536
                                   } else{
537
                                           System.out.println("izquierda,abajo,false");
538
                                   }
539
                           }
540
                           }else if (lastp.getX()>antp.getX()){
541
                         */
542
                        System.out.println("angleDifl 2 1= " +
543
                                angleDistance(angle2, angle1));
544
                        System.out.println("angleDifl 1 2= " +
545
                                angleDistance(angle1, angle2));
546

    
547
                        if (angleDistance(angle2, angle1) > Math.PI) {
548
                                if (RobustCGAlgorithms.isCCW(coords)) {
549
                                        System.out.println("derecha,arriba,true");
550

    
551
                                        return true;
552
                                } else {
553
                                        System.out.println("derecha,arriba,false");
554
                                }
555
                        } else {
556
                                if (!RobustCGAlgorithms.isCCW(coords)) {
557
                                        System.out.println("derecha,abajo,true");
558

    
559
                                        return true;
560
                                } else {
561
                                        System.out.println("derecha,abajo,false");
562
                                }
563
                        }
564

    
565
                        //}
566
                } catch (Exception e) {
567
                        System.out.println("false");
568

    
569
                        return true;
570
                }
571

    
572
                return false;
573
        }
574

    
575
        /**
576
         * DOCUMENT ME!
577
         *
578
         * @param args DOCUMENT ME!
579
         */
580
        public static void main(String[] args) {
581
                System.out.println(getIntersection(new Point2D.Double(0, 0),
582
                                new Point2D.Double(2, 2), new Point2D.Double(3, 3),
583
                                new Point2D.Double(3, 4)));
584
                System.out.println(getIntersection(new Point2D.Double(2, 3),
585
                                new Point2D.Double(2, 2), new Point2D.Double(3, 3),
586
                                new Point2D.Double(3, 4)));
587
                System.out.println(getIntersection(new Point2D.Double(0, 0),
588
                                new Point2D.Double(2, 2), new Point2D.Double(1, 0),
589
                                new Point2D.Double(2, 3)));
590
                System.out.println(getIntersection(new Point2D.Double(0, 4),
591
                                new Point2D.Double(2, 4), new Point2D.Double(3, 3),
592
                                new Point2D.Double(0, 0)));
593
        }
594
}