source: pyromaths/trunk/fuentes/src/pyromaths/ex/lycee/CercleTrigo.py @ 423

Last change on this file since 423 was 423, checked in by mabarracus, 4 years ago

add sources from pyromaths 15.10

File size: 12.2 KB
Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#
4# Pyromaths
5# Un programme en Python qui permet de créer des fiches d'exercices types de
6# mathématiques niveau collège ainsi que leur corrigé en LaTeX.
7# Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org)
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22#
23import random
24from math import cos, sin, radians, pi
25from pyromaths.outils.decimaux import decimaux
26from pyromaths.outils.Arithmetique import pgcd
27
28div180 = [[1,180],[2,90],[3,60],[4,45],[5,36],[6,30],[9,20],[10,18],[12,15]]
29
30# Radians représentés en fait par des fractions
31
32def deg2rad(n):
33    """Effectue la conversion de degrés entre 0 et 360° vers radians."""
34    p = pgcd(n,180)
35    return [n/p,180/p]
36
37def simprad(liste):
38    """Simplifie la fraction d'un angle en radians. Le paramètre est une liste d'entiers, pour représenter une fraction."""
39    p = pgcd(liste[0],liste[1])
40    return [f/p for f in liste]
41
42def rad2deg(liste):
43    """Effectue la conversion de radians entre 0 et 2pi vers degrés. Le paramètre est une liste d'entiers, pour représenter une fraction."""
44    return liste[0]*180/liste[1] # Attention résultat entier, donc faux si liste[1] ne divise pas 180
45
46def rad2tex(liste):
47    """Prépare l'écriture de radians en latex."""
48    if liste[0]==0:
49        frac =  "$0$"
50    elif liste[0]==liste[1]:
51        frac = "$\\pi$"
52    elif liste[0]==-liste[1]:
53        frac = "$-\\pi$"
54    elif liste[0]==1:
55        frac = "$\\dfrac{\\pi}{"+str(liste[1])+"}$"
56    elif liste[0]==-1:
57        frac = "$\\dfrac{-\\pi}{"+str(liste[1])+"}$"
58    elif liste[1]==-1: # Probablement inutile
59        frac = "$"+str(-liste[0])+"\\pi$"
60    elif liste[1]==1:
61        frac = "$"+str(liste[0])+"\\pi$"
62    else:
63        frac = "$\\dfrac{"+str(liste[0])+"\\pi}{"+str(liste[1])+"}$"
64    return frac
65
66def mes_princ(liste):
67    """Calcule la mesure principale d'un angle en radians ( entre -pi et pi )."""
68    num = liste[0] % (2*liste[1])
69    if num > liste[1]:
70        num -= 2*liste[1]
71    return simprad([num,liste[1]])
72
73def mes_02pi(liste):
74    """Calcule la mesure d'un angle en radians dans l'intervalle [0,2pi]."""
75    num = liste[0] % (2*liste[1])
76    return [num,liste[1]]
77
78def cercle_trigo(code=0,*args):
79    """Dessine le cercle trigonométrique avec un nombre indéfini d'angles en degrés ou radians, en codant ou non les angles."""
80    figure = """\\psset{xunit=3cm,yunit=3cm,dotstyle=+}
81    \\begin{pspicture}(-1.4,-1.4)(1.4,1.4)
82    \\psframe(-1.4,-1.4)(1.4,1.4)
83    \\psaxes[linewidth=0.5pt,Dx=2,Dy=2]{->}(0,0)(-1.1,-1.1)(1.1,1.1)
84    \\pscircle[linecolor=gray](0,0){3}
85    \\definecolor{grisclair}{gray}{0.20}
86    \\colorlet{bleuclair}{blue!40!white}\n"""
87    idx = 0
88    if not code:
89        for a in range(11):
90            if (a+1)/6.0 not in [0.5,1,1.5]:
91                figure += "\\psline[linecolor=LightSkyBlue,linestyle=dashed](0,0)("+str(round(cos((a+1)*pi/6),2))+","+str(round(sin((a+1)*pi/6),2))+")\n"
92        for a in range(9):
93            if (a+1)/5.0 not in [0.5,1,1.5]:
94                figure += "\\psline[linecolor=LightSlateGray,linestyle=dashed](0,0)("+str(round(cos((a+1)*pi/5),2))+","+str(round(sin((a+1)*pi/5),2))+")\n"
95        for a in range(4):
96            figure += "\\psline[linecolor=LightGreen,linestyle=dashed](0,0)("+str(round(cos((2*a+1)*pi/4),2))+","+str(round(sin((2*a+1)*pi/4),2))+")\n"
97    for f in args:
98        if isinstance(f,list): # mesure en radians
99            rad = simprad(f)
100        else: # mesure en degrés
101            rad = simprad(deg2rad(f))
102        f = rad[0]*pi/rad[1] # Le dénominateur ne devrait pas être nul...
103        frac = rad2tex(rad)
104
105        figure += "\\psline[linecolor=red,linestyle=dashed](0,0)("+str(round(cos(f),2))+","+str(round(sin(f),2))+")\n"
106        if code:
107            figure += "\\rput("+str(round(1.25*cos(f),2))+","+str(round(1.25*sin(f),2))+"){"+frac+"}\n"
108        else:
109            figure += "\\rput("+str(round(1.25*cos(f),2))+","+str(round(1.25*sin(f),2))+"){$M_"+str(idx)+"$}\n"
110            idx += 1
111    figure += """\\uput[dl](0,0){$O$}
112    \uput[dr](1,0){$I$}
113    \uput[ul](0,1){$J$}"""
114    figure += "\n\\end{pspicture}"
115    return figure
116
117def findrad(itv=1, neg=0, denom_simple=1):
118    """Génère un angle en radians sous certaines conditions :
119    itv ( intervalle ): 0 ( quelconque ), 1 ( mesure principale ), 2 ( entre 0 et 2 pi )
120    neg : 0 ( positif ), 1 ( négatif )
121    denom_simple : 0 ( quelconque ), 1 ( simple, càd 1, 2, 3, 4, 5, ou 6 ), 2 ( diviseur de 180 )"""
122
123    global div180
124
125    if denom_simple==1:
126        denom = random.randint(2,6)
127    elif denom_simple == 0:
128        denom = random.randint(2,30)
129    else:
130        random.shuffle(div180)
131        random.shuffle(div180[0])
132        denom = div180[0][0]
133
134    if itv == 1:
135        sgn = (-1)**(random.randint(1,2))
136        num = sgn * random.randint(1,denom) # pas grave si -pi sort
137    elif itv == 2:
138        num = random.randint(1,2*denom)
139    else:
140        numliste = [random.randint(2*denom, 120),random.randint(-2*denom, -denom)]
141        random.shuffle(numliste)
142        num = numliste[0]
143
144    if (neg and (num > 0)) or ((not neg) and (num < 0)):
145        num = -num
146
147    return [num,denom] # FIX Simplifier ?
148
149def cercle_trigonometrique():
150    """Exercice de la fiche."""
151
152    exo = ["\\exercice"]
153    cor = ["\\exercice*"]
154
155    mes_deg = [] # Question 1
156    while len(mes_deg)<5:
157        tmp = random.randint(0,360) # FIX trop complexes parfois
158        if tmp not in mes_deg:
159            mes_deg.append(tmp)
160    mes_deg_tex = [_(u"$%s\\degres$") %(d) for d in mes_deg]
161
162    radq2 = [] # Question 2
163    while len(radq2)<5:
164        tmp = findrad(2,0,2) # Dénominateur est un diviseur de 180
165        if tmp not in radq2:
166            radq2.append(tmp)
167
168    radq3 = [] # Question 3
169    while len(radq3)<5:
170        while len(radq3)<4:
171            tmp = findrad(0,0,0)
172            if tmp not in radq3:
173                radq3.append(tmp)
174        tmp = findrad(0,1,0) # dernier négatif
175        if tmp not in radq3:
176            radq3.append(tmp)
177
178    radq4 = [] # Question 4
179    while len(radq4)<4:
180        tmp = mes_princ(findrad(0,0,1))
181        if tmp not in radq4:
182            radq4.append(tmp)
183
184    radq5 = [] # Question 5
185    radq5_princ = []
186    while len(radq5)<4:
187        while len(radq5)<2:
188            tmp = findrad(1,0,1)
189            tmp_princ = mes_princ(tmp)
190            if tmp_princ not in radq5_princ:
191                radq5.append(tmp)
192                radq5_princ.append(tmp_princ)
193        while len(radq5)<3:
194            tmp = findrad(1,1,1) # avant-dernier négatif
195            tmp_princ = mes_princ(tmp)
196            if tmp_princ not in radq5_princ:
197                radq5.append(tmp)
198                radq5_princ.append(tmp_princ)
199        tmp = findrad(0,0,1) # dernier non principal
200        tmp_princ = mes_princ(tmp)
201        if tmp_princ not in radq5_princ:
202            radq5.append(tmp)
203
204    mes_rad = radq2 + radq3 + radq4 + radq5
205    mes_rad_tex = [rad2tex(r)for r in mes_rad]
206
207    mes_deg_en_rad = [deg2rad(d) for d in mes_deg]
208    mes_deg_en_rad_tex = [rad2tex(r) for r in mes_deg_en_rad]
209
210    exo.append(u"\\begin{enumerate}")
211    exo.append(_(u"\\item Convertir les cinq mesures suivantes en radians : %s, %s, %s, %s et %s.") %(tuple(mes_deg_tex)))
212    exo.append(_(u"\\item Convertir les cinq mesures suivantes en degrés : %s, %s, %s, %s et %s~rad.") %(tuple(mes_rad_tex[0:5])))
213    exo.append(_(u"\\item Déterminer les mesures principales des angles suivants en radians : %s, %s, %s, %s et %s~rad.") %(tuple(mes_rad_tex[5:10])))
214    exo.append(_(u"\\item Des angles ont été placés sur le cercle trigonométrique ci-dessous, représentés en rouge par les points $M_0$, $M_1$, $M_2$ et $M_3$. Lire leurs mesures principales en radians"))
215    exo.append(_(u"( les lignes vertes, grises et bleues représentent des angles multiples de $\\dfrac{\\pi}{3}$, de $\\dfrac{\\pi}{4}$ et de $\\dfrac{\\pi}{5}$ ).\\par"))
216    exo.append(cercle_trigo(0,radq4[0],radq4[1],radq4[2],radq4[3]))
217    exo.append(_(u"\\item Placer les angles suivants sur le cercle trigonométrique : %s, %s, %s et %s~rad.\\par") %(tuple(mes_rad_tex[14:])))
218    exo.append(cercle_trigo())
219    exo.append(u"\\end{enumerate}\\par")
220
221    cor.append(u"\\begin{enumerate}")
222    cor.append(_(u"\\item Convertir les cinq mesures suivantes en radians : %s, %s, %s, %s et %s.\\par") %(tuple(mes_deg_tex)))
223
224    cor.append(_(u"La conversion est en fait une simple règle de proportionnalité : il faut multiplier par $\\dfrac{\\pi}{180}$.\\par"))
225    cor.append(_(u"Par exemple pour la première mesure, on obtient avec simplification : $"+str(mes_deg[0])+"\\times\\dfrac{\\pi}{180}$ = ")+mes_deg_en_rad_tex[0]+"~rad.\\par")
226    cor.append(_(u"De même pour les autres mesures, on trouve alors respectivement : %s~rad, %s~rad, %s~rad, %s~rad et %s~rad.") %(tuple(mes_deg_en_rad_tex)))
227
228    cor.append(_(u"\\item Convertir les cinq mesures suivantes en degrés : %s, %s, %s, %s et %s~rad.\\par") %(tuple(mes_rad_tex[0:5])))
229
230    cor.append(_(u"On effectue alors la proportionnalité inverse : il faut multiplier par $\\dfrac{180}{\\pi}$.\\par"))
231    cor.append(_(u"Après simplification, voici les résultats : %s\\degres, %s\\degres, %s\\degres, %s\\degres et %s\\degres.") %(tuple([rad2deg(r) for r in radq2])))
232
233    cor.append(_(u"\\item Déterminer les mesures principales des angles suivants en radians : %s, %s, %s, %s et %s~rad.\\par") %(tuple(mes_rad_tex[5:10])))
234
235    rep = mes_princ(radq3[0])
236    nb_tours = (radq3[0][0]-rep[0])/(2*radq3[0][1])
237
238    cor.append(_(u"Une mesure d'angle en radians est définie modulo $2\\pi$, c'est-à-dire que l'ajout ou la suppression d'un tour ( qui vaut $2\\pi$ ou 360\\degres ) ne change pas un angle.\\par"))
239    cor.append(_(u"Concrètement, avec le premier angle de la question, on remarque que :\\par"))
240    cor.append(rad2tex(radq3[0])[:-1]+"\\equiv"+rad2tex(rep)[1:-1]+"+"+rad2tex([2*nb_tours*rep[1],rep[1]])[1:-1]+"\\equiv"+rad2tex(rep)[1:-1]+"+"+rad2tex([2*nb_tours,1])[1:-1]+"\\equiv"+rad2tex(rep)[1:-1]+u"~(2\\pi)$.\\par")
241    cor.append(_(u"De même pour les autres mesures, on trouve alors respectivement : %s~rad, %s~rad, %s~rad, %s~rad et %s~rad.") %(tuple([rad2tex(mes_princ(r)) for r in radq3])))
242
243    cor.append(_(u"\\item Des angles ont été placés sur le cercle trigonométrique ci-dessous, représentés en rouge par les points $M_0$, $M_1$, $M_2$ et $M_3$. Lire leurs mesures principales en radians"))
244    cor.append(_(u"( les lignes vertes, grises et bleues représentent des angles multiples de $\\dfrac{\\pi}{3}$, de $\\dfrac{\\pi}{4}$ et de $\\dfrac{\\pi}{5}$ ).\\par"))
245
246    cor.append(_(u"Les réponses sont directement données sur le cercle trigonométrique ci-dessous :\\par"))
247    cor.append(cercle_trigo(1,mes_princ(radq4[0]),mes_princ(radq4[1]),mes_princ(radq4[2]),mes_princ(radq4[3])))
248    cor.append(u"\\par")
249    cor.append(_(u"Les points $M_0$, $M_1$, $M_2$ et $M_3$ définissent alors respectivement les angles %s, %s, %s et %s~rad.") %(tuple(mes_rad_tex[10:14])))
250    cor.append(_(u"\\item Placer les angles suivants sur le cercle trigonométrique : %s, %s, %s et %s~rad.\\par") %(tuple(mes_rad_tex[14:])))
251
252    cor.append(_(u"Les réponses sont directement données sur le cercle trigonométrique ci-dessous :\\par"))
253    cor.append(cercle_trigo(1,radq5[0],radq5[1],radq5[2],radq5[3]))
254    cor.append(u"\\par")
255    cor.append(_(u"Ajoutons une simple remarque pour la dernière mesure, qui n'est pas principale : il faut effectuer en premier lieu une simplification, comme à la question 3. On obtient alors :\\par"))
256    cor.append(rad2tex(radq5[3])[:-1]+"\\equiv"+rad2tex(mes_princ(radq5[3]))[1:-1]+"~(2\\pi)$.")
257    cor.append(u"\\end{enumerate}\\par")
258
259    return exo, cor
260
261cercle_trigonometrique.description = _(u"Cercle trigonométrique")
262cercle_trigonometrique.level = _(u"2.Seconde")
Note: See TracBrowser for help on using the repository browser.