/***********************************CONSTANTES***********************************/ pi = 3.1415926535; /***********************************ARITHMÉTIQUE***********************************/ function PGCD(a,b) = a > b ? PGCD(b , a-b) : a < b ? PGCD(a, b-a) : a; /**********************************************************************************/ /***********************************GEOMETRIE***********************************/ /**********************************************************************************/ /***********************************FONCTIONS 2D***********************************/ //CONVERSION function rad(angle = 0) = pi * angle / 180; function degre(angle = 0) = angle * 180 / pi; function calcule_distance_2d(x, y) = sqrt(pow(x, 2) + pow(y, 2)); function milieu( A, B) = [ (A[0] + B[0])/2, (A[1] + B[1])/2 ]; /*************************************************************************************** calcul de l'angle formé par la droite OA avec A[x, y] et l'axe des abscisses pour connaitre le sens de l'angle il faut vérifier si y est positif ou négatif pour éviter les divisions par 0 il faut vérifier si y == 0 ***************************************************************************************/ //function calcule_angle_2d(x, y) = y < 0 ? 360-acos(x/calcule_distance_2d(x, y)) : y == 0 && x>=0 ? 0 : acos(x/calcule_distance_2d(x, y)); function calcule_angle_2d(x, y) = y < 0 ? 360-acos(x/calcule_distance_2d(x, y)) : y > 0 ? acos(x/calcule_distance_2d(x, y)) : x>=0 ? 0 : 180; /******************************DEVELOPPANTE DE CERCLE******************************/ function developpante_x(r = 1, t = 0) = r*(cos(t)+rad(t)*sin(t)); function developpante_y(r = 1, t = 0) = r*(sin(t)-rad(t)*cos(t)); //INTERSECTION /*On cherche à calculer le point d'intersection d'une développante de cercle et d'un cercle. Pour se faire il faut chercher la valeur du paramètre a dans les équations : x(a) = r*(cos(a) + a*sin(a)) y(a) = r*(sin(a) - a*cos(a)) En utilisant pythagore on conclue que le paramètre doit satisfaire : tel que x(a)² + y(a)² = R² avec R le rayon du cercle que coupe la développante. [r*(cos(a) + a*sin(a))]² + [r*(sin(a) - a*cos(a))]² = R² r² * (cos(a) + a*sin(a))² + r² * (sin(a) - a*cos(a))² = R² On peut factoriser par r² r² * [ (cos(a) + a*sin(a))² + (sin(a) - a*cos(a))² ] = R² (cos(a) + a*sin(a))² + (sin(a) - a*cos(a))² = R²/r² On utilise les identitées remarquables : cos(a)² + 2a*cos(a)*sin(a) + a²*sin(a)² + sin(a)² - 2a*cos(a)*sin(a) + a²*cos(a)² = R²/r² cos(a)² + a²*sin(a)² + sin(a)² + a²*cos(a)² = R²/r² cos(a)² + sin(a)² + a²*sin(a)² + a²*cos(a)² = R²/r² cos(a)² + sin(a)² + a²*( sin(a)² + cos(a)² ) = R²/r² Sachant que cos² + sin² = 1 on obtient : 1 + a² = R²/r² a² = R²/r² - 1 a = sqrt(R²/r² - 1) */ function intersect_rad(r=1, R=2) = sqrt( (R*R)/(r*r) - 1); function intersect(r=1, R=2) = degre(intersect_rad(r, R)); /***********************************FONCTIONS 3D***********************************/ function projection_xy(vecteur) = [vecteur[0], vecteur[1], 0]; function conversion_cartesien_spherique(vecteur) = [norm(vecteur), norm(projection_xy(vecteur)) == 0 ? 0 : vecteur[1] < 0 ? 360-acos(vecteur[0]/norm(projection_xy(vecteur))) : acos(vecteur[0]/norm(projection_xy(vecteur))), acos(vecteur[2]/norm(vecteur))]; /***********************************MODULES***********************************/ /*************************************************************************************** Modules pour créer une spirale spirale_coord prend en arguments : x1 l'abscisse du point de départ y1 l'ordonnée du point de départ x2 l'abscisse du point d'arrivé y2 l'ordonnée du point d'arrivé tour désigne le nombre de tour qui devront être effectué pour passer du point de départ au point d'arrivé largeur désigne la largeur du bras de la spirale spirale_point prend en arguments: A un vecteur représentant le point de départ B un vecteur représentant le point d'arrivé tour désigne le nombre de tour qui devront être effectué pour passer du point de départ au point d'arrivé largeur désigne la largeur du bras de la spirale **********************************************************************************/ module spirale_coord(x1 = 10, y1 = 0, x2 = 10, y2 = 10, tours = 2, largeur = 1) { //calcule des distances par rapport à l'origine d1 = calcule_distance_2d(x1, y1); d2 = calcule_distance_2d(x2, y2); //calcule des angles entre les vecteur OA et Ox theta1 = calcule_angle_2d(x1, y1); theta2 = calcule_angle_2d(x2, y2); //calcule de l'angle à balayer pour effectuer le nombre de tour voulu //pour lier le point de départ et le point d'arrivé angle = tours * 360 + (theta2 - theta1); //la spirale est de type linéaire, cela signifie que le rayon de la courbe va croitre de manière proportionnelle à l'angle coeff_dir = (d2 - d1)/angle; //création des points extérieur de la spirale du point de départ vers le point d'arrivé A = [for(i=[0:1:angle]) [(coeff_dir * i + d1 + largeur/2) * cos(i + theta1), (coeff_dir * i + d1 + largeur/2) * sin(i + theta1)]]; //création des points interieur de la spirale du point d'arrivé vers le point de départ B = [for(i=[angle:-1:0]) [(coeff_dir * i + d1 - largeur/2) * cos(i + theta1), (coeff_dir * i + d1 - largeur/2) * sin(i + theta1)]]; //combinaison des 2 séries de points C = concat(A,B); //tracé de la courbe finale polygon(C); } module spirale_coord2(x1 = 0, y1 = 0, x2 = 0, y2 = 10, tours = 2, largeur = 1) { /*pour une spirale linéaire, ou d'Archimède, la relation est la suivante : r = a + b*theta cela signifie que les coordonnées cartésiennes sont : x(theta) = r*cos(theta) = (a + b*theta)*cos(theta) y(theta) = r*sin(theta) = (a + b*theta)*sin(theta) */ function delta_x(t = 0) = cos(t) - rad(t)*sin(t); function delta_y(t = 0) = sin(t) + rad(t)*cos(t); //calcule des distances par rapport à l'origine d1 = calcule_distance_2d(x1, y1); d2 = calcule_distance_2d(x2, y2); //calcule des angles entre les vecteur OA et Ox theta1 = calcule_angle_2d(x1, y1); theta2 = calcule_angle_2d(x2, y2); //calcule de l'angle à balayer pour effectuer le nombre de tour voulu //pour lier le point de départ et le point d'arrivé angle = tours * 360 + abs(theta2 - theta1); //la spirale est de type linéaire, cela signifie que le rayon de la courbe va croitre de manière proportionnelle à l'angle coeff_dir = (d2 - d1)/angle; function vecteur(t = 0) = [[0, -1],[1, 0]]*[delta_x(t = t), delta_y(t = t)]/norm([delta_x(t = t), delta_y(t = t)]); //function vecteur(t = 0) = [largeur*cos(t)/2, largeur*sin(t)/2]; //création des points extérieur de la spirale du point de départ vers le point d'arrivé A = [for(i=[0:1:angle]) (coeff_dir * i + d1) * [cos(i + theta1), sin(i + theta1)] + vecteur(t = i + theta1) ]; //création des points interieur de la spirale du point d'arrivé vers le point de départ B = [for(i=[angle:-1:0]) (coeff_dir * i + d1) * [cos(i + theta1), sin(i + theta1)] - vecteur(t = i + theta1) ]; //combinaison des 2 séries de points C = concat(A,B); //tracé de la courbe finale polygon(C); } module spirale_log_coord(x1 = 1, y1 = 0, x2 = 20, y2 = 0, tours = 2, largeur = 1) { //calcule des distances par rapport à l'origine d1 = calcule_distance_2d(x1, y1); d2 = calcule_distance_2d(x2, y2); //calcule des angles entre les vecteur OA et Ox theta1 = calcule_angle_2d(x1, y1); theta2 = calcule_angle_2d(x2, y2); echo("math.scad, module : spirale_log_coord"); echo("theta1 = ", theta1, ""); echo("theta2 = ", theta2, ""); //calcule de l'angle à balayer pour effectuer le nombre de tour voulu //pour lier le point de départ et le point d'arrivé delta_theta = theta2 - theta1 >= 0 ? theta2 - theta1 : 360 - (theta1 - theta2); angle = tours * 360 + delta_theta; theta2_ = angle + theta1; echo("angle = ", angle, ""); /*une spirale logarithmique est décrite par : r = a*b^theta Si on possède 2 points : r1 = a*b^theta1 r2 = a*b^theta2 on peut extraire le coefficient a : ln(r1) = ln(a*b^theta1) = ln(a) + ln(b^theta1) = ln(a) + theta1*ln(b) ln(r2) = ln(a*b^theta2) = ln(a) + ln(b^theta2) = ln(a) + theta2*ln(b) ln(r2) - ln(r1) = ln(a) - ln(a) + theta2*ln(b) - theta1*ln(b) ln(r2/r1) = ln(b) * (theta2 - theta1) ln(r2/r1)/(theta2-theta1) = ln(b) <=> b = exp( ln(r2/r1)/(theta2-theta1) ) */ b = exp( ln(d2/d1)/(theta2_-theta1) ); a = d1/(pow(b,theta1)); //création des points extérieur de la spirale du point de départ vers le point d'arrivé A = [for(i=[0:1:angle]) [(a*pow(b,(i + theta1)) + largeur/2) * cos(i + theta1), (a*pow(b,(i + theta1)) + largeur/2) * sin(i + theta1)]]; //création des points interieur de la spirale du point d'arrivé vers le point de départ B = [for(i=[angle:-1:0]) [(a*pow(b,(i + theta1)) - largeur/2) * cos(i + theta1), (a*pow(b,(i + theta1)) - largeur/2) * sin(i + theta1)]]; //combinaison des 2 séries de points C = concat(A,B); //tracé de la courbe finale polygon(C); } //spirale_coord2(x1 = 2.5, y1 = 0, x2 = 20, y2 = 0, tours = 2, largeur = 1); module spirale_point(A = [0, 0], B = [10, 10], tours = 1, largeur = 1) { spirale(A[0], A[1], B[0], B[1], tours, largeur); } module polygone_regulier(cotes = 5, rayon = 10) { polygon([for(i=[0: 360/cotes : 360])[rayon * cos(i), rayon * sin(i)]]); } module portion_disque(rayon = 10, angle = 180) { A = [for(i=[0 : 1 : angle])[rayon * cos(i), rayon * sin(i)]]; B = concat([[0, 0]], A); polygon(B); } module gaussienne(sigma = 0.5, mu = 0, interval = 20) { polygon([ for(i=[-interval/2:0.1:interval/2])[i, exp(-pow( (i - mu),2))/(2*pow(sigma,2))/(sigma * sqrt(2*pi)) ] ]); } module trompette(epaisseur = 2, hauteur = 10, r_min = 20, r_max = 40, precision = 100, facteur = 1) { x1 = ln(hauteur/(exp( facteur * (r_max - r_min)) - 1))/facteur; x2 = r_max - r_min + x1; function calcule_xb(xa, l) = -sqrt(pow(l, 2)/(1 + facteur * facteur * exp(-2*xa * facteur))) + xa; function calcule_yb(xa, l) = sqrt(pow(l, 2)/(1 + facteur * facteur * exp(2*xa * facteur))) + exp(facteur * xa); A = [for(i=[x1:(x2-x1)/precision:x2]) [i ,exp(facteur *i)]]; B = [for(i=[x2:-(x2-x1)/precision:x1]) [calcule_xb(i, epaisseur), calcule_yb(i, epaisseur)]]; C = concat(A,B); rotate_extrude() { translate([ -x2 - r_min, -exp(facteur * x1), 0]) {polygon(C);} } }