Orbite.java
001 package fr.isae.orbit;
002 
003 import fr.isae.geometry.Point;
004 
005 /**
006  <code>Orbite</code> represente une orbite elliptique autour de
007  * la Terre avec lancement a l'equateur (argument du perigee nul).
008  * Sur cette orbite sont positionnes trois satellites separes par
009  * 120 degres possedant chacun un instrument faisant un angle de 45
010  * degres avec le vecteur tangent a la trajectoire du satellite.
011  * L'ouverture de l'instrument est de 45 degres. On peut verifier
012  * si un satellite a une position angulaire donnee voit le satellite
013  * le precedant.
014  *
015  @author <a href="mailto:garion@isae.fr">Christophe Garion</a>
016  @version 1.0
017  */
018 public class Orbite {
019 
020     private double e;
021     private double a;
022     private Point foyer;
023     private double b;
024 
025     /**
026      * La valeur de l'ouverture de l'appareil, consideree comme constante.
027      */
028     public static final double OUVERTURE = Math.PI / 4.0;
029 
030     /**
031      * L'angle de visee de l'appareil par rapport a la tangente a la trajectoire.
032      */
033     public static final double ANGLE_VISEE = Math.PI / 4.0;
034 
035     /**
036      * Une constante pour comparer des valeurs reelles.
037      */
038     public static final double EPS = 1E-6;
039 
040     /**
041      * Creer une nouvelle instance de <code>Orbite</code>.
042      *
043      @param e valeur de l'excentricite de l'orbite. <b>Doit etre comprise
044      *          entre 0 et 1</b>
045      @param a valeur du demi-grand axe de l'ellipse. <b>Doit etre positive</b>
046      @param foyer un point representant le foyer de l'ellipse sur
047      *              lequel est situe la Terre. Attention, ce point n'est pas copie.
048      */
049     public Orbite(double e, double a, Point foyer) {
050         this.e = e;
051         this.a = a;
052         this.foyer = foyer.clone();
053         this.calculerB();
054     }
055 
056     /**
057      * Creer une nouvelle instance de <code>Orbite</code>. On considere
058      * que la Terre a pour coordonnees <code>(0, 0)</code>.
059      *
060      @param e valeur de l'excentricite de l'orbite. <b>Doit etre comprise
061      *          entre 0 et 1</b>
062      @param a valeur du demi-grand axe de l'ellipse. <b>Doit etre positive</b>
063      */
064     public Orbite(double e, double a) {
065         this.e = e;
066         this.a = a;
067         this.foyer = Point.ORIGINE;
068         this.calculerB();
069     }
070 
071     /**
072      * La valeur de l'excentricite de l'orbite.
073      *
074      @return la valeur de l'exentricite (comprise
075      *         entre 0 et 1)
076      */
077     public double getE() {
078         return this.e;
079     }
080 
081     /**
082      * Changer la valeur de l'excentricite de l'orbite.
083      *
084      @param e la nouvelle valeur de l'excentricite. <b>Doit etre comprise
085      *          entre 0 et 1</b>
086      */
087     public void setE(double e) {
088         this.e = e;
089         this.calculerB();
090     }
091 
092     /**
093      * La valeur du demi-grand axe de l'orbite.
094      *
095      @return la valeur du demi-grand axe (positive)
096      */
097     public double getA() {
098         return this.a;
099     }
100 
101     /**
102      * Changer la valeur du demi-grand axe de l'orbite.
103      *
104      @param a la nouvelle valeur du demi-grand axe.<b>Doit etre positive</b>
105      */
106     public void setA(double a) {
107         this.a = a;
108         this.calculerB();
109     }
110 
111     /**
112      * La valeur du demi-petit axe de l'orbite.
113      *
114      @return la valeur du demi-petit axe (positive)
115      */
116     public double getB() {
117         return this.b;
118     }
119 
120     /**
121      * Changer la valeur du demi-petit axe de l'orbite. On considere
122      * que la valeur du demi-grand axe ne change pas et que c'est l'
123      * excentricite qui est modifiee.
124      *
125      @param b la nouvelle valeur du demi-petit axe.<b>Doit etre positive</b>
126      */
127     public void setB(double b) {
128         this.b = b;
129         this.e = Math.sqrt(a * a - b * b/ a;
130     }
131 
132     /**
133      * Le point ou est situe la Terre.
134      *
135      @return une reference vers le point representant la Terre. Attention,
136      *         le point n'est pas copie.
137      */
138     public Point getFoyer() {
139         return this.foyer.clone();
140     }
141 
142     /**
143      * Changer le point representant la Terre.
144      *
145      @param foyer le nouveau point representant la Terre
146      */
147     public void setFoyer(Point foyer) {
148         this.foyer = foyer.clone();
149     }
150 
151     /**
152      * La distance entre le centre de l'ellipse et un foyer.
153      *
154      @return la valeur de la distance entre le centre de l'ellipse et un foyer
155      */
156     public double getC() {
157         return this.a * this.e;
158     }
159 
160     /**
161      <code>equals</code> permet de verifier si deux orbites sont egales, i.e.
162      * s'ils ont les memes parametres.
163      *
164      <p> Nous verrons plus tard que cette methode est en fait heritee de la
165      * classe <code>Object</code>
166      *
167      @param o une <code>Orbite</code> qui est l'orbite dont on veut verifier si
168      *          elle est egale a <code>this</code>
169      @return un <code>boolean</code> qui est <code>true</code> si les deux
170      *         orbites sont egales
171      */
172 
173     public boolean equals(Orbite o) {
174         return ((o != null&&
175                 (this.e == o.e&&
176                 (this.a == o.a&&
177                 (this.foyer.equals(o.foyer)));
178     }
179 
180     /**
181      <code>clone</code> permet d'obtenir une copie de <code>this</code>. On obtient
182      * une nouvelle orbite avec des parametres identiques.
183      *
184      <p> Nous verrons plus tard que cette methode est en fait heritee de la
185      * classe <code>Object</code>
186      *
187      @return une <code>Orbite o</code> tel que <code>this != o</code> et
188      *         <code>this.equals(o)</code>
189      */
190     public Orbite clone() {
191         return new Orbite(this.e, this.a, this.foyer);
192     }
193 
194     /**
195      * Renvoyer une chaine de caracteres representant l'orbite sous la forme
196      <code>[Orbite e=... a=... foyer=(...,...)]</code>
197      *
198      @return la representation de l'orbite
199      */
200     public String toString() {
201         return "[Orbite" +
202             " e=" this.e +
203             " a=" this.a +
204             " foyer=" this.foyer +
205             "]";
206     }
207 
208     /**
209      * Calculer les coordonnes d'un point sur l'orbite en fonction d'un angle
210      * pris par rapport a l'origine de l'ellipse (anomalie excentrique).
211      * On suppose que si l'angle vaut 0, le point est le perigee.
212      *
213      @param theta l'anomalie excentrique decrivant la position du point
214      @return le point sur l'orbite correspondant a l'angle
215      */
216     public Point calculerPointSurOrbite(double theta) {
217         return new Point(this.foyer.getX() this.getC() +
218                          this.a * Math.cos(theta),
219                          this.b * Math.sin(thetathis.foyer.getY());
220     }
221 
222     /**
223      * Calculer les coordonnes d'un point sur l'orbite en fonction d'un angle
224      * pris par rapport au foyer de l'ellipse.
225      * On suppose que si l'angle vaut 0, le point est le perigee.
226      *
227      @param v l'angle decrivant la position du point
228      @return le point sur l'orbite correspondant a l'angle
229      */
230     public Point calculerPointSurOrbiteFoyer(double v) {
231         return this.calculerPointSurOrbite(this.calculerTheta(v));
232     }
233 
234     /**
235      * Renvoie un point representant un vecteur tangent a l'ellipse au point
236      * defini par <code>theta</code>. Le vecteur tangent va dans la direction
237      * de la vitesse du satellite.
238      *
239      @param theta l'anomalie excentrique situant le point
240      @return un vecteur tangent a l'ellipse au point defini par theta.
241      */
242     public Point calculerVecteurTangent(double theta) {
243         // on s'occupe des cas aux limites
244         if (Math.abs(theta % (2.0 * Math.PI)) < EPS) {
245             return new Point(0.01.0);
246         }
247 
248         if (Math.abs(theta % Math.PI< EPS) {
249             return new Point(0.0, -1.0);
250         }
251 
252         // calcul dans les autres cas
253         Point centre = new Point(this.foyer.getX() this.getC(),
254                                  this.foyer.getY());
255 
256         Point p = this.calculerPointSurOrbite(theta);
257 
258         // on se ramene a un centre a l'origine
259         p.translater(-centre.getX(), -centre.getY());
260 
261         // on choisit un vecteur avec une abscisse qui vaut celle du
262         // demi-grand axe. Comme on sait que theta via atan2 sera
263         // compris entre -PI et PI, c'est facile...
264         double x = ((theta < 0.01.0 : -1.0this.a + p.getX();
265 
266         double y = (1.0 (x * p.getX()) (this.a * this.a)) *
267             (this.b * this.b/ p.getY();
268 
269         // on normalise le vecteur
270         Point vec = new Point(x - p.getX(), y - p.getY());
271 
272         double lvec = vec.distance(Point.ORIGINE);
273 
274         return new Point(vec.getX() / lvec, vec.getY() / lvec);
275     }
276 
277     /**
278      * Permet de verifier si un satellite a une position angulaire donnee voit via
279      * son instrument de bord le satellite suivant situe a 120 degres. Les angles sont
280      * donnes par rapport au foyer.
281      *
282      @param v l'angle definissant la position du satellite par rapport au foyer
283      @return <code>true</code> si le satellite suivant est visible
284      */
285     public boolean voitSatelliteSuivant(double v) {
286         Point sat = this.calculerPointSurOrbiteFoyer(v);
287         Point satSuivant = this.calculerPointSurOrbiteFoyer(v + Math.PI * 2.0 3.0);
288 
289         // calcul vecteur tangent
290         // on assimile les vecteurs a des points...
291         Point vTangent = this.calculerVecteurTangent(this.calculerTheta(v));
292         double lvTangent = vTangent.distance(Point.ORIGINE);
293 
294         // vecteur vers prochain satellite (normalise)
295         Point vSat = new Point(satSuivant.getX() - sat.getX(),
296                                satSuivant.getY() - sat.getY());
297         double lvSat = vSat.distance(Point.ORIGINE);
298         vSat = new Point(vSat.getX() / lvSat, vSat.getY() / lvSat);
299         lvSat = vSat.distance(Point.ORIGINE);
300 
301         double cosVSatTangent = (vTangent.getX() * vSat.getX() +
302                                  vTangent.getY() * vSat.getY()) /
303             (lvTangent * lvSat);
304 
305         return ((cosVSatTangent >= Math.cos(ANGLE_VISEE + OUVERTURE / 2.0)) &&
306                 (cosVSatTangent <= Math.cos(ANGLE_VISEE - OUVERTURE / 2.0)));
307     }
308 
309 
310     private void calculerB() {
311         this.b = this.a * Math.sqrt(1.0 this.e * this.e);
312     }
313 
314     private double calculerTheta(double v) {
315         return Math.atan2(Math.sqrt(1.0 - Math.pow(this.e, 2)) * Math.sin(v),
316                           this.e + Math.cos(v));
317     }
318 }