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