min(a, b) = (a + b - |a - b|)/2 et max(a, b) = (a + b + |b - a|)/2 |
{min} Calculate (0,0,' ','AB+AB-@abs_-2/')(a,b)[hidden]; {max} Calculate (0,0,' ','AB+AB-@abs_+2/')(a,b)[hidden]; |
Avec les variantes min(a, 0) et max(a, 0) :
{neg} Calculate (0,0,' ','AA@abs_-2/')(a)[hidden]; {pos} Calculate (0,0,' ','AA@abs_+2/')(a)[hidden]; |
Dans l'exemple, le point est limité au dessus de la droite x + 2y = 1 et de l'ellipse (5x - 4)² + 5y² - 1 = 0
C'est à dire y ≥ ymin = max(yd, ye), et finalement y = max(yA, ymin)
{A?} Point (105,105)[cyan]; {xyA?} Coordinates (A?,coord,0,0,'')[hidden]; { point variable } {OU} Segment (U,O)[hidden]; {u?} Point on object (OU, 0)[hidden]; {u} Ratio/Points (O,U,u?,0,0,'')[hidden]; {loc} Calculate (0,0,'','A@sgn_')(u)[hidden]; { point de controle u si != 0, A? sinon } {x} Calculate (0,0,'','CB* 1C-#A1* +')(xyA?,u,loc)[hidden]; { calcul et tracé ellipse } {y2} Calculate (0,0,'','A!25*40+A*15-5/')(x)[hidden]; {ye} Calculate (0,0,'','AA@abs_+2/@sqrt')(y2)[hidden]; {Pe?} PlotXY (ye,coord,x)[hidden]; {Pe} Dilation/MarkedRatio (Pe?,O,loc)[hidden]; {ellipse} Locus (Pe,u?,OU, 100)[layer(2)]; { droite } {yd} Calculate (0,0,'','1A-2/')(x)[hidden]; { restriction } {ymin} Calculate (0,0,'','AB+AB-@abs_+2/')(yd,ye)[hidden]; {Pmin} PlotXY (ymin,coord,x)[cyan]; {y} Calculate (0,0,'','#A2B+#A2B-@abs_+2/')(xyA?,ymin)[hidden]; {A} PlotXY (y,coord,x); { remplissage } {Pmax} Translation (Pmin,0,100)[hidden]; {yy} Ray (Pmax,Pmin)[hidden]; {area} Locus (yy,u?,OU, 201)[layer(1)]; |
Une astuce permet ici d'effectuer la limitation sur le point draggable et le tracé du Locus sans
dupliquer les calculs.
Le point de contrôle est soit le point draggable A?, soit le Point on object u? utilisé pour le tracé si celui-ci est non nul
On obtient ainsi à la fois la contrainte sur A? ( avec u = 0 par définition) soit le tracé (quand u ≠ 0 dans le Locus).
On obtient de même le remplissage de la zone par un simple Locus supplémentaire
Une autre astuce permet de répondre à la question en dehors du domaine de définition de l'ellipse.
L'ellipse est en fait définie par y = √(1 - (5x - 4)²)/5 si
1 - (5x - 4)² ≥ 0, et y = 0 sinon.
Pour x > 1 l'ellipse étant remplacée par la droite y = 0, c'est cette droite qui est prise ici.
Il faudrait ajouter un test supplémentaire pour restreindre x à [0,1]
Pour ne pas perturber le tracé par un segment joignant A à l'origine +ε (1er segment du locus),
le point du locus est un point conditionnel O si u = 0, le point calculé sinon.
Comme les min(a,b) et max(a,b) nécessitent plusieurs fois l'utilisation de a et b, ces opérandes sont calculés à part.
(ceci motive d'autant plus pour effectuer les calculs une seule fois !)
{delta} Calculate (0,0,' ','BB*4AC**-@abs_@sqrt')(a,b,c)[hidden]; {x1} Calculate (0,0,' ','B!delta-A2*/')(a,b,delta)[hidden]; {x1} Calculate (0,0,' ','B!delta+A2*/')(a,b,delta)[hidden]; |
Un exemple d'équation du second degré a été donné lors du tracé de la courbe
y4 - x2y2 + x4 - 1 = 0
Donnons ici le tracé propre d'une conique à centre dans tous les cas.
La conique étant définie ici par les points A,B,C et le centre O
Son équation est donc ax² + bxy + cy² = 1, et la direction des asymptotes obtenue comme solution de
ct² + bt + a = 0, qui est le but de cet exemple.
Si le discriminant Δ de cette équation est > 0 c'est ainsi une hyperbole.
On en profite aussi pour obtenir les axes par tan(2φ) = b/(c - a)
La construction directe par 5 points (les 3 donnés et leur symétriques) est connue,
mais provoque des tracés erratiques ici, dans le cas d'une hyperbole comme toujours avec les "fausses asymptotes",
mais même dans le cas d'une ellipse, car des intersections de droites parallèles sont inévitables,
provoquant parfois des "piquants" sur l'ellipse..
Ne parlons même pas du cas où la conique dégénère en deux droites parallèles (Δ = 0) ou perpendiculaires
(xy = 0, si C sur un axe)
Pour tracer proprement dans tous les cas, on est amené à effectuer une construction conditionnelle.
Le tracé propre de l'hyperbole est ainsi réalisé spécifiquement à partir de ses asymptotes (calculées) et d'un point.
{ coordonnées des points A,B,C } {xyA} Coordinates (A,grid,0,0,'')[hidden]; {xyB} Coordinates (B,grid,0,0,'')[hidden]; {xyC} Coordinates (C,grid,0,0,'')[hidden]; { calcul des coefficients } {a} Calculate (0,0,'','1#A1 2^/')(xyA)[hidden]; {c} Calculate (0,0,'','1#A2 2^/')(xyB)[hidden]; {b} Calculate (0,0,'','1 B#A1 2^*- C#A2 2^*-#A1/#A2/')(xyC,a,c)[hidden]; {delta} Calculate (0,0,'','BB*4AC**-')(a,b,c)[hidden]; {ifhyp} Calculate (0,0,'','A@sgn_1-@sqrt1+')(delta)[hidden]; { asymptotes } {as1} Calculate (0,0,'','A!C@sqrt+B/2/@atanD*')(b,c,delta,ifhyp)[hidden]; {Os1} Rotation/MeasuredAngle (Ox,O,as1); {as2} Calculate (0,0,'','A!C@sqrt-B/2/@atanD*')(b,c,delta,ifhyp)[hidden]; {Os2} Rotation/MeasuredAngle (Ox,O,as2); { axes } {az} Calculate (0,0,'','CA-B/@atan2/1@atan+')(a,b,c)[hidden]; {Oz} Rotation/MeasuredAngle (Ox,O,az); {Oz!} Perpendicular (Oz,O); { ... } |
Peti jeu : essayez d'obtenir un cercle exact (a = c, b = 0)...
Rappelons la solution à la règle et au compas d'une équation du second degré :
On se ramène à x² - sx + a.b = 0, où l'inconnue x, aussi bien que les données s, a, b sont des longueurs.
On peut alors effectuer la construction suivante :
Sur deux droites Ou et Ov, formant un repère qui n'a aucune raison d'être orthonormé,
U et V étant pris comme unités, soient
OA = a, OB = b sur Ou et
OS = S sur Ov
Tracer les perpendiculaires respectivement à Ou en le milieu de AB et à
Ov en le milieu de OS.
Elles se coupent en I, tracer le cercle de centre I passant par A (et B donc).
Il coupe Ov en X1 et X2 et OX1 = x1, OX2 = x2 sur Ov sont les solutions de l'équation.
Résolvons ainsi l'équation x³ + px + q = 0 avec 4p³ + 27q² ≥ 0. Selon les formules connues :
{delta} Calculate (0,0,' ','AAA**27/BB*4/+@sqrt')(p,q)[hidden]; {u3} Calculate (0,0,' ','A2/!B-')(q,delta)[hidden]; {v3} Calculate (0,0,' ','A2/!B+ ')(q,delta)[hidden]; {x} Calculate (0,0,' ','A@abs_1 3/^A@sgn_* B@abs_1 3/^B@sgn_* +')(u3,v3)[hidden]; |
Le discriminant intervenant deux fois dans la formule, il est calculé à part plutôt que dupliqué.
Le calcul de 3√ ne marche que pour des nombres ≥0, les radicandes u3 et v3 sont
donc eux aussi calculés à part plutôt que dupliqués
Lorsque Δ < 0, ce calcul échoue et répond "undefined",
alors qu'il y a précisément trois racines réelles dans ce cas !
Pour trouver les solutions réelles quand il y en a trois, il faut utiliser la méthode trigonométrique.
Bien entendu 4p³ + 27q² ne peut être <0 que si p<0.
Posons alors x = √-4p/3 cos(t), l'équation devient :
4 cos³(t) - 3 cos(t) = cos(3t) = 3q/p √-3/(4p) = cos(φ),
le second membre étant < 1 en valeur absolue puisque 4p³ + 27q² < 0.
Les trois solutions sont donc t = φ/3 et φ/3 ± 2 π/3
Inversement, cette méthode ne fonctionne que si |3q/p| √-3/(4p) ≤ 1
et le @acos répond undefined sinon.
Le seul cas "litigieux" est 4p³ + 27q² = 0 pour lequel chacune des deux méthodes renvoie une valeur.
On rajoute dans le calcul à la Cardan un test @sgn_1-@sqrt forçant undefined si Δ ≤ 0 pour avoir unicité du résultat.
{ solution Cardan si delta strictement >0 } {delta} Calculate (0,0,' ','AAA**27/BB*4/+')(p,q)[hidden]; {u3} Calculate (0,0,' ','B@sgn_1-@sqrtA+2/!B@sqrt-')(q,delta)[hidden]; { ... } { solution trigo si delta <=0 } {phi} Calculate (0,0,'','3A!4*/@sqrt3*B*A/@acos')(p,q)[hidden]; {x1} Calculate (0,0,'x = ','B3/@cos_A!4*3/@sqrt*')(p,phi)[hidden]; {x2} Calculate (0,0,'x'' = ','B3/1@atan8*3/+@cos_A!4*3/@sqrt*')(p,phi)[hidden]; {x3} Calculate (0,0,'x'''' = ','B3/1@atan8*3/-@cos_A!4*3/@sqrt*')(p,phi)[hidden]; |
L'applet trace la courbe y = x³ + px + q définie par les deux points de controles bleus. Le(s) point(s) d'intersection avec l'axe Ox est/sont calculés et marqués.
L'affichage de x ou (x1, x2, x3) est réalisé par une astuce d'affichage conditionnel
(pour ne pas voir s'afficher 'x = undefined') :
L'affichage n'est pas le Calculate lui même mais un PeggedText du Calculate sur un point tributaire
du point généré.
{ affiche point Cardan } {S} Dilation/MarkedRatio (U,O,x); { affichage conditionnel } {T} FixedPoint (5,85)[hidden]; {T!} Dilation (T,S,1)[hidden]; {txt} PeggedText (T!,x); { ... idem pour les 3 autres x1,x2,x3 - trigo - } |
{e} Parameter (2.718281828459045,0,0,'')[hidden]; {e^x} Calculate (0,0,'','AB^')(e,x); {cosh} Calculate (0,0,'','AB^AB!^+2/')(e,x); {sinh} Calculate (0,0,'','AB^AB!^-2/')(e,x); {tanh} Calculate (0,0,'','AB2*^1-AB2*^1+/')(e,x); {acosh} Calculate (0,0,'','AA*1-@sqrtA+@ln__')(x); {asinh} Calculate (0,0,'','AA*1+@sqrtA+@ln__')(x); {atanh} Calculate (0,0,'','A@abs_1-@sgn_@abs_1-@sqrt1+A+1A-/@ln__2/')(x); |
On peut remarquer que le point x reste sur place quand on modifie l'échelle
Ceci est un bug de JavaSketchpad : les axes sont indépendants du système de coordonnées !!
Le point X sur l'axe Ox (Point on object) est donc par rapport à cette échelle loufoque :
Quelle que soit l'unité du Origin&Unit, les AxisX/AxisY sont avec leur point
0 à -200 pixels de l'origine et le point 1 à +200 pixels de l'origine !
Le point '1' dragable définit l'unité du système de coordonnées, le point origine O est aussi dragable
Les points X0 à 0 et X1 à 1 sur l'axe Ox (AxisX) ainsi que Y0 à 0 et Y1 à 1 sur l'axe Oy (AxisY)
sont à distance constante = 200 pixels de O !
Pour obtenir un point sur l'axe Ox avec les mêmes unités que le Origin&Unit, il faut non pas
utiliser un AxisX mais une droite ordinaire Line (u, O) où u est le point unité du Origin&Unit
Pour l'axe oy, on opère de même avec une rotation du point unité de π/2
Bien entendu un point dans le système de coordonnées par un PlotXY est aux bonnes coordonnées, lui. (point 1,1)
Les axes sont ainsi inutilisables à quoi que ce soit avec jsp4, à part pour décorer !
Leur utilité apparait avec jsp5. Voir les exemples suivants.