Statistics
| Revision:

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

History | View | Annotate | Download (8.56 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.vividsolutions.jts.algorithm.RobustCGAlgorithms;
47
import com.vividsolutions.jts.geom.Coordinate;
48

    
49
import java.awt.geom.Arc2D;
50
import java.awt.geom.Point2D;
51
import java.awt.geom.Rectangle2D;
52

    
53

    
54
/**
55
 * Funciones de utilidad relacionadas con trigonometr?a
56
 */
57
public class TrigonometricalFunctions {
58
        /**
59
         * Obtiene un par de puntos que definen la recta perpendicular a
60
         * p1-p2 que pasa por el punto perp
61
         *
62
         * @param p1 punto de la recta p1-p2
63
         * @param p2 punto de la recta p1-p2
64
         * @param perp Punto por el que pasa la recta perpendicular
65
         *
66
         * @return Array con dos puntos que definen la recta resultante
67
         */
68
        public static Point2D[] getPerpendicular(Point2D p1, Point2D p2,
69
                Point2D perp) {
70
                //Pendiente de la recta perpendicular
71
                double m = (p1.getX() - p2.getX()) / (p2.getY() - p1.getY());
72

    
73
                //b de la funcion de la recta perpendicular
74
                double b = p2.getY() -
75
                        (m * ((perp.getX() - p2.getX()) / (p2.getY() - perp.getY())));
76

    
77
                //Obtenemos un par de puntos
78
                Point2D[] res = new Point2D[2];
79
                res[0] = new Point2D.Double(0, (m * 0) + b);
80
                res[1] = new Point2D.Double(1, (m * 1) + b);
81

    
82
                return res;
83
        }
84

    
85
        /**
86
         * Obtiene un arco a partir de 3 puntos. Devuelve null si no se puede crear
87
         * el arco porque los puntos est?n alineados
88
         *
89
         * @param p1
90
         * @param p2
91
         * @param p3
92
         *
93
         * @return Arco
94
         */
95
        public static Arc2D createArc(Point2D p1, Point2D p2, Point2D p3) {
96
                Coordinate[] coords = new Coordinate[4];
97
                coords[0] = new Coordinate(p1.getX(), p1.getY());
98
                coords[1] = new Coordinate(p2.getX(), p2.getY());
99
                coords[2] = new Coordinate(p3.getX(), p3.getY());
100
                coords[3] = new Coordinate(p1.getX(), p1.getY());
101

    
102
                Point2D center = getCircleCenter(p1, p2, p3);
103
                double angle1 = getAngle(center, p1);
104
                double angle2 = getAngle(center, p3);
105
                double extent = angleDistance(angle1, angle2);
106

    
107
                if (!RobustCGAlgorithms.isCCW(coords)) {
108
                        extent = (Math.PI * 2) - extent;
109
                } else {
110
                        extent = -extent;
111
                }
112

    
113
                System.err.println("angle1:" + angle1);
114
                System.err.println("angle2:" + getAngle(center, p2));
115
                System.err.println("angle3:" + angle2);
116
                System.err.println("extent:" + extent);
117

    
118
                double Radio = p1.distance(center);
119
                double xR = center.getX() - Radio;
120
                double yR = center.getY() - Radio;
121
                double w = 2.0 * Radio;
122
                double h = w;
123

    
124
                Rectangle2D.Double rBounds = new Rectangle2D.Double(xR, yR, w, h);
125
                Arc2D.Double resul = new Arc2D.Double(rBounds,
126
                                Math.toDegrees((Math.PI * 2) - angle1), Math.toDegrees(extent),
127
                                Arc2D.OPEN);
128

    
129
                return resul;
130
        }
131

    
132
        /**
133
         * Obtiene el punto que se encuentra a una distancia 'dist' de la recta
134
         * p1-p2 y se encuentra en la recta perpendicular que pasa por perpPoint
135
         *
136
         * @param p1 Punto de la recta p1-p2
137
         * @param p2 Punto de la recta p1-p2
138
         * @param perpPoint Punto de la recta perpendicular
139
         * @param dist Distancia del punto que se quiere obtener a la recta p1-p2
140
         *
141
         * @return DOCUMENT ME!
142
         */
143
        public static Point2D getPerpendicularPoint(Point2D p1, Point2D p2,
144
                Point2D perpPoint, double dist) {
145
                return null;
146
        }
147

    
148
        /**
149
         * Obtiene el centro del circulo que pasa por los puntos p1, p2 y p3
150
         *
151
         * @param p1
152
         * @param p2
153
         * @param p3
154
         *
155
         * @return Devuelve el punto o null si no hay ning?n c?rculo (puntos
156
         *                    alineados)
157
         */
158
        public static Point2D getCircleCenter(Point2D p1, Point2D p2, Point2D p3) {
159
                double xC;
160
                double yC;
161
                double w;
162
                double h;
163

    
164
                // Calculamos 2 secantes, tiramos perpendiculares por sus puntos
165
                // medios y obtenemos el centro. Luego calculamos el radio.
166
                // Puntos medios de los segmentos.
167
                double xm1;
168

    
169
                // Calculamos 2 secantes, tiramos perpendiculares por sus puntos
170
                // medios y obtenemos el centro. Luego calculamos el radio.
171
                // Puntos medios de los segmentos.
172
                double ym1;
173

    
174
                // Calculamos 2 secantes, tiramos perpendiculares por sus puntos
175
                // medios y obtenemos el centro. Luego calculamos el radio.
176
                // Puntos medios de los segmentos.
177
                double xm2;
178

    
179
                // Calculamos 2 secantes, tiramos perpendiculares por sus puntos
180
                // medios y obtenemos el centro. Luego calculamos el radio.
181
                // Puntos medios de los segmentos.
182
                double ym2;
183
                xm1 = (p1.getX() + p2.getX()) / 2.0;
184
                ym1 = (p1.getY() + p2.getY()) / 2.0;
185
                xm2 = (p2.getX() + p3.getX()) / 2.0;
186
                ym2 = (p2.getY() + p3.getY()) / 2.0;
187

    
188
                /* g.setColor(Color.GRAY);
189
                   g.draw3DRect((int)xm1, (int) ym1, 1, 1, true);
190
                   g.draw3DRect((int)xm2, (int) ym2, 1, 1, true); */
191

    
192
                // Pendientes de las perpendiculares y constantes       
193
                double mP1 = 0;
194

    
195
                /* g.setColor(Color.GRAY);
196
                   g.draw3DRect((int)xm1, (int) ym1, 1, 1, true);
197
                   g.draw3DRect((int)xm2, (int) ym2, 1, 1, true); */
198

    
199
                // Pendientes de las perpendiculares y constantes       
200
                double mP2 = 0;
201

    
202
                /* g.setColor(Color.GRAY);
203
                   g.draw3DRect((int)xm1, (int) ym1, 1, 1, true);
204
                   g.draw3DRect((int)xm2, (int) ym2, 1, 1, true); */
205

    
206
                // Pendientes de las perpendiculares y constantes       
207
                double A1;
208

    
209
                /* g.setColor(Color.GRAY);
210
                   g.draw3DRect((int)xm1, (int) ym1, 1, 1, true);
211
                   g.draw3DRect((int)xm2, (int) ym2, 1, 1, true); */
212

    
213
                // Pendientes de las perpendiculares y constantes       
214
                double A2;
215
                boolean bPerp1 = false;
216
                boolean bPerp2 = false;
217

    
218
                if ((p2.getY() - p1.getY()) == 0) {
219
                        A1 = ym1;
220
                        bPerp1 = true;
221
                } else {
222
                        mP1 = (p2.getX() - p1.getX()) / (p1.getY() - p2.getY());
223
                        A1 = ym1 - (xm1 * mP1);
224
                }
225

    
226
                if ((p2.getY() - p3.getY()) == 0) {
227
                        A2 = ym2;
228
                        bPerp2 = true;
229
                } else {
230
                        mP2 = (p3.getX() - p2.getX()) / (p2.getY() - p3.getY());
231
                        A2 = ym2 - (xm2 * mP2);
232
                }
233

    
234
                if (mP2 == mP1) {
235
                        return null; // Error, 3 puntos alineados. No puede pasar un arco
236
                } else {
237
                        xC = (A2 - A1) / (mP1 - mP2);
238

    
239
                        if (!bPerp1) {
240
                                yC = (xC * mP1) + A1;
241
                        } else {
242
                                yC = (xC * mP2) + A2;
243
                        }
244
                }
245

    
246
                return new Point2D.Double(xC, yC);
247
        }
248

    
249
        /**
250
         * Obtiene un c?rculo a partir de 3 puntos. Devuelve null si no se puede
251
         * crear el c?ruclo porque los puntos est?n alineados
252
         *
253
         * @param p1
254
         * @param p2
255
         * @param p3
256
         *
257
         * @return C?rculo
258
         */
259
        static public Arc2D createCircle(Point2D p1, Point2D p2, Point2D p3) //, Graphics g)
260
         {
261
                Point2D center = getCircleCenter(p1, p2, p3);
262

    
263
                double Radio = p1.distance(center);
264
                double xR = center.getX() - Radio;
265
                double yR = center.getY() - Radio;
266
                double w = 2.0 * Radio;
267
                double h = w;
268

    
269
                Rectangle2D.Double rBounds = new Rectangle2D.Double(xR, yR, w, h);
270
                Arc2D.Double resul = new Arc2D.Double(rBounds, 0.0, 360.0, Arc2D.OPEN);
271

    
272
                return resul;
273
        }
274

    
275
        /**
276
         * Obtiene el ?ngulo del vector que se pasa como par?metro con el vector
277
         * horizontal de izquierda a derecha
278
         *
279
         * @param start punto origen del vector
280
         * @param end punto destino del vector
281
         *
282
         * @return angulo en radianes
283
         */
284
        public static double getAngle(Point2D start, Point2D end) {
285
                double angle = Math.acos((end.getX() - start.getX()) / start.distance(
286
                                        end));
287

    
288
                if (start.getY() > end.getY()) {
289
                        angle = -angle;
290
                }
291

    
292
                if (angle < 0) {
293
                        angle += (2 * Math.PI);
294
                }
295

    
296
                return angle;
297
        }
298

    
299
        /**
300
         * Devuelve la distancia desde angle1 a angle2
301
         *
302
         * @param angle1 angulo en radianes. Debe ser positivo y no dar ninguna
303
         *                   vuelta a la circunferencia
304
         * @param angle2 angulo en radianes. Debe ser positivo y no dar ninguna
305
         *                   vuelta a la circunferencia
306
         *
307
         * @return distancia entre los ?ngulos
308
         */
309
        public static double angleDistance(double angle1, double angle2) {
310
                if (angle1 < angle2) {
311
                        return angle2 - angle1;
312
                } else {
313
                        return ((Math.PI * 2) - angle1) + angle2;
314
                }
315
        }
316
}