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