#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import outils import math from random import randrange import gettext import locale locale.setlocale(locale.LC_ALL, "") locale.textdomain("pyromaths") gettext.textdomain("pyromaths") _=locale.gettext def eq_droites(A, B): (xA, yA) = A (xB, yB) = B a = ((yB - yA) * 1.0) / (xB - xA) b = ((xB * yA - xA * yB) * 1.0) / (xB - xA) return (a, b) def inter_droites(A, B, C, D): """ Calcule les coordonn\xc3(C)es du point d'intersection des droites (AB) et (CD) """ (a1, b1) = eq_droites(A, B) (a2, b2) = eq_droites(C, D) if a1 == a2: #droites parallèles xI = A[0] yI = A[1] else: xI = ((b2 - b1) * 1.0) / (a1 - a2) yI = ((a1 * b2 - a2 * b1) * 1.0) / (a1 - a2) return (xI, yI) def dist_pt_droite(A, B, C): """ calcule la distance du point C \xc3\xa0 la droite (AB) """ (a, b) = eq_droites(A, B) (xC, yC) = C d = (abs(a * xC - yC + b) * 1.0) / math.sqrt(a ** 2 + 1) return d def dist_points(A, B): """ Calcul la distance entre deux points""" (xA, yA) = A (xB, yB) = B d = math.sqrt((xB - xA) ** 2 + (yB - yA) ** 2) return d def coord_projete(A, B, C): """ Calcule les coordonn\xc3(C)es du projet\xc3(C) orthogonal de C sur la droite (AB) """ (xA, yA) = A (xB, yB) = B (xC, yC) = C n = dist_points(A, B) p = (xB - xA) / n q = (yB - yA) / n s = p * (xC - xA) + q * (yC - yA) return (xA + s * p, yA + s * q) def verifie_distance_mini(A, B, C, D): """ V\xc3(C)rifie que la distance minimale entre [AB] et [AC] est sup\xc3(C)rieure \xc3\xa0 dmin """ dmin = 1.2 (xA, yA) = A (xB, yB) = B if xA > xB: (xA, yA, xB, yB) = (xB, yB, xA, yA) (xC, yC) = C (xD, yD) = D if xC > xD: (xC, yC, xD, yD) = (xD, yD, xC, yC) (xI, yI) = inter_droites(A, B, C, D) if xA <= xI <= xB and xC <= xI <= xD or xA <= coord_projete(A, B, C)[0] <= \ xB and dist_pt_droite(A, B, C) < dmin or xA <= coord_projete(A, B, D)[0] <= xB and dist_pt_droite(A, B, D) < dmin or xC <= \ coord_projete(C, D, A)[0] <= xD and dist_pt_droite(C, D, A) < \ dmin or xC <= coord_projete(C, D, B)[0] <= xD and dist_pt_droite(C, D, B) < dmin or dist_points(A, C) < dmin or dist_points(A, D) < \ dmin or dist_points(B, C) < dmin or dist_points(B, D) < dmin: isValid = False else: isValid = True return isValid def verifie_angle(lpoints, A, B, C): """ V\xc3(C)rifie que l'angle BAC ne coupe pas les autres angles d\xc3(C)j\xc3\xa0 trac\xc3(C)s """ if len(lpoints) == 0: #Premier angle créé isValid = True else: for i in xrange(len(lpoints)): (A1, B1, C1) = (lpoints[i])[:3] isValid = verifie_distance_mini(A, B, A1, B1) and \ verifie_distance_mini(A, B, A1, C1) and \ verifie_distance_mini(A, C, A1, B1) and \ verifie_distance_mini(A, C, A1, C1) if not isValid: break return isValid def cree_angles(nb_angles, xmax, ymax): ''' cr\xc3(C)e une s\xc3(C)rie d\'angles "non s\xc3(C)quents" ''' (xmax, ymax) = (xmax - .5, ymax - .5) #taille de l'image en cm lg_seg = 6 #longueur des côtés des angles lpoints = [] cpt = 0 #evite une boucle infinie while len(lpoints) < nb_angles and cpt < 1000: (xA, yA) = (randrange(5, xmax * 10) / 10.0, randrange(5, ymax * 10) / 10.0) alpha = randrange(360) #angle entre un côté et l'horizontal if len(lpoints) < nb_angles / 2: beta = randrange(90, 180) #crée un angle droit ou obtus else: beta = randrange(0, 75) + 15 #crée un angle aigu (entre 15° et 89°) xB = xA + lg_seg * math.cos((alpha * math.pi) / 180) yB = yA + lg_seg * math.sin((alpha * math.pi) / 180) xC = xA + lg_seg * math.cos(((alpha + beta) * math.pi) / 180) yC = yA + lg_seg * math.sin(((alpha + beta) * math.pi) / 180) (A, B, C) = ((xA, yA), (xB, yB), (xC, yC)) if xA != xB and xA != xC and .5 < xB < xmax and .5 < yB < ymax and \ .5 < xC < xmax and .5 < yC < ymax and verifie_angle(lpoints, A, B, C): lpoints.append((A, B, C, alpha, beta)) else: cpt = cpt + 1 #print len(lpoints) return lpoints def PosAngle(alpha, beta): """retourne les angles pour placer les points sur la figure""" A = (alpha + beta / 2.0 + 180) % 360 B = (alpha - 90) % 360 C = (alpha + beta + 90) % 360 return (A, B, C) def PointName(l3noms, indice): list = [] for i in xrange(3): list.append(l3noms[i]) return tuple(list) def figure(f0, f1, lpoints, lnoms, xmax, ymax): text = [] text.append("\\begin{pspicture}(%s,%s)\n" % (xmax, ymax)) text.append(" \\psframe(0,0)(%s,%s)\n" % (xmax, ymax)) for i in xrange(len(lnoms)): text.append(" \\pstGeonode[PointName={%s,%s,%s}," % lnoms[i]) text.append("PosAngle={%s,%s,%s}]\n " % PosAngle(lpoints[i][3], lpoints[i][4])) for j in xrange(3): text.append("(%.2f,%.2f)" % lpoints[i][j]) text.append("{a%s%s}" % (j, i)) text.append(""" \\pstLineAB[nodesepB=-.5]{a0%s}{a1%s} """ % (i, i)) text.append(" \\pstLineAB[nodesepB=-.5]{a0%s}{a2%s}\n" % (i, i)) text.append("\\end{pspicture}\\par\n") for i in xrange(len(text)): f0.write(text[i]) f1.write(text[i]) def reponses(f0, f1, lpoints, lnoms): f1.write("\\begin{multicols}{4}\n") for i in xrange(len(lnoms)): f1.write(" $\\widehat{%s%s%s}=%s\degres$\\par\n" % (lnoms[i][1], lnoms[i][0], lnoms[i][2], lpoints[i][4])) if lpoints[i][4] < 90: f1.write(_(" angle aigu\\par\n")) elif lpoints[i][4] > 90: f1.write(_(" angle obtus\\par\n")) else: f1.write(_(" angle droit\\par\n")) f1.write("\\end{multicols}\n") f0.write("\\begin{tabularx}{\\textwidth}{|*{4}{X|}}\n") f0.write(" \\hline angle 1 : & angle 2 : & angle 3 : & angle 4 : \\\\\n") f0.write(" \\hline &&& \\\\ &&& \\\\ &&& \\\\ \\hline\n") f0.write("\\end{tabularx}\n") def mesure_angles(f0, f1): nb_angles = 4 (xmax, ymax) = (18, 8) #taille de l'image en cm lnoms = [] lpoints = [] cpt = 0 while len(lpoints) < nb_angles: if cpt > 1000: lpoints = [] cpt = 0 lpoints = cree_angles(nb_angles, xmax, ymax) cpt = cpt + 1 tmpl = outils.choix_points(3 * nb_angles) for i in xrange(nb_angles): lnoms.append(tuple(tmpl[3 * i:3 * i + 3])) figure(f0, f1, lpoints, lnoms, xmax, ymax) reponses(f0, f1, lpoints, lnoms)