math.scad 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /***********************************CONSTANTES***********************************/
  2. pi = 3.1415926535;
  3. /***********************************ARITHMÉTIQUE***********************************/
  4. function PGCD(a,b) = a > b ? PGCD(b , a-b) : a < b ? PGCD(a, b-a) : a;
  5. /**********************************************************************************/
  6. /***********************************GEOMETRIE***********************************/
  7. /**********************************************************************************/
  8. /***********************************FONCTIONS 2D***********************************/
  9. //CONVERSION
  10. function rad(angle = 0) = pi * angle / 180;
  11. function degre(angle = 0) = angle * 180 / pi;
  12. function calcule_distance_2d(x, y) = sqrt(pow(x, 2) + pow(y, 2));
  13. function milieu( A, B) = [ (A[0] + B[0])/2, (A[1] + B[1])/2 ];
  14. /***************************************************************************************
  15. calcul de l'angle formé par la droite OA avec A[x, y] et l'axe des abscisses
  16. pour connaitre le sens de l'angle il faut vérifier si y est positif ou négatif
  17. pour éviter les divisions par 0 il faut vérifier si y == 0
  18. ***************************************************************************************/
  19. //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));
  20. 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;
  21. /******************************DEVELOPPANTE DE CERCLE******************************/
  22. function developpante_x(r = 1, t = 0) = r*(cos(t)+rad(t)*sin(t));
  23. function developpante_y(r = 1, t = 0) = r*(sin(t)-rad(t)*cos(t));
  24. //INTERSECTION
  25. /*On cherche à calculer le point d'intersection
  26. d'une développante de cercle et d'un cercle.
  27. Pour se faire il faut chercher la valeur du paramètre a dans les équations :
  28. x(a) = r*(cos(a) + a*sin(a))
  29. y(a) = r*(sin(a) - a*cos(a))
  30. En utilisant pythagore on conclue que le paramètre doit satisfaire :
  31. tel que x(a)² + y(a)² = R²
  32. avec R le rayon du cercle que coupe la développante.
  33. [r*(cos(a) + a*sin(a))]² + [r*(sin(a) - a*cos(a))]² = R²
  34. r² * (cos(a) + a*sin(a))² + r² * (sin(a) - a*cos(a))² = R²
  35. On peut factoriser par r²
  36. r² * [ (cos(a) + a*sin(a))² + (sin(a) - a*cos(a))² ] = R²
  37. (cos(a) + a*sin(a))² + (sin(a) - a*cos(a))² = R²/r²
  38. On utilise les identitées remarquables :
  39. cos(a)² + 2a*cos(a)*sin(a) + a²*sin(a)² + sin(a)² - 2a*cos(a)*sin(a) + a²*cos(a)² = R²/r²
  40. cos(a)² + a²*sin(a)² + sin(a)² + a²*cos(a)² = R²/r²
  41. cos(a)² + sin(a)² + a²*sin(a)² + a²*cos(a)² = R²/r²
  42. cos(a)² + sin(a)² + a²*( sin(a)² + cos(a)² ) = R²/r²
  43. Sachant que cos² + sin² = 1 on obtient :
  44. 1 + a² = R²/r²
  45. a² = R²/r² - 1
  46. a = sqrt(R²/r² - 1)
  47. */
  48. function intersect_rad(r=1, R=2) = sqrt( (R*R)/(r*r) - 1);
  49. function intersect(r=1, R=2) = degre(intersect_rad(r, R));
  50. /***********************************FONCTIONS 3D***********************************/
  51. function projection_xy(vecteur) = [vecteur[0], vecteur[1], 0];
  52. function conversion_cartesien_spherique(vecteur) =
  53. [norm(vecteur),
  54. norm(projection_xy(vecteur)) == 0 ? 0 : vecteur[1] < 0 ? 360-acos(vecteur[0]/norm(projection_xy(vecteur))) : acos(vecteur[0]/norm(projection_xy(vecteur))),
  55. acos(vecteur[2]/norm(vecteur))];
  56. /***********************************MODULES***********************************/
  57. /***************************************************************************************
  58. Modules pour créer une spirale
  59. spirale_coord prend en arguments :
  60. x1 l'abscisse du point de départ
  61. y1 l'ordonnée du point de départ
  62. x2 l'abscisse du point d'arrivé
  63. y2 l'ordonnée du point d'arrivé
  64. tour désigne le nombre de tour qui devront être effectué pour passer du point de départ au point d'arrivé
  65. largeur désigne la largeur du bras de la spirale
  66. spirale_point prend en arguments:
  67. A un vecteur représentant le point de départ
  68. B un vecteur représentant le point d'arrivé
  69. tour désigne le nombre de tour qui devront être effectué pour passer du point de départ au point d'arrivé
  70. largeur désigne la largeur du bras de la spirale
  71. **********************************************************************************/
  72. module spirale_coord(x1 = 10, y1 = 0, x2 = 10, y2 = 10, tours = 2, largeur = 1)
  73. {
  74. //calcule des distances par rapport à l'origine
  75. d1 = calcule_distance_2d(x1, y1);
  76. d2 = calcule_distance_2d(x2, y2);
  77. //calcule des angles entre les vecteur OA et Ox
  78. theta1 = calcule_angle_2d(x1, y1);
  79. theta2 = calcule_angle_2d(x2, y2);
  80. //calcule de l'angle à balayer pour effectuer le nombre de tour voulu
  81. //pour lier le point de départ et le point d'arrivé
  82. angle = tours * 360 + (theta2 - theta1);
  83. //la spirale est de type linéaire, cela signifie que le rayon de la courbe va croitre de manière proportionnelle à l'angle
  84. coeff_dir = (d2 - d1)/angle;
  85. //création des points extérieur de la spirale du point de départ vers le point d'arrivé
  86. A = [for(i=[0:1:angle])
  87. [(coeff_dir * i + d1 + largeur/2) * cos(i + theta1),
  88. (coeff_dir * i + d1 + largeur/2) * sin(i + theta1)]];
  89. //création des points interieur de la spirale du point d'arrivé vers le point de départ
  90. B = [for(i=[angle:-1:0])
  91. [(coeff_dir * i + d1 - largeur/2) * cos(i + theta1),
  92. (coeff_dir * i + d1 - largeur/2) * sin(i + theta1)]];
  93. //combinaison des 2 séries de points
  94. C = concat(A,B);
  95. //tracé de la courbe finale
  96. polygon(C);
  97. }
  98. module spirale_coord2(x1 = 0, y1 = 0, x2 = 0, y2 = 10, tours = 2, largeur = 1)
  99. {
  100. /*pour une spirale linéaire, ou d'Archimède, la relation est la suivante :
  101. r = a + b*theta
  102. cela signifie que les coordonnées cartésiennes sont :
  103. x(theta) = r*cos(theta) = (a + b*theta)*cos(theta)
  104. y(theta) = r*sin(theta) = (a + b*theta)*sin(theta)
  105. */
  106. function delta_x(t = 0) = cos(t) - rad(t)*sin(t);
  107. function delta_y(t = 0) = sin(t) + rad(t)*cos(t);
  108. //calcule des distances par rapport à l'origine
  109. d1 = calcule_distance_2d(x1, y1);
  110. d2 = calcule_distance_2d(x2, y2);
  111. //calcule des angles entre les vecteur OA et Ox
  112. theta1 = calcule_angle_2d(x1, y1);
  113. theta2 = calcule_angle_2d(x2, y2);
  114. //calcule de l'angle à balayer pour effectuer le nombre de tour voulu
  115. //pour lier le point de départ et le point d'arrivé
  116. angle = tours * 360 + abs(theta2 - theta1);
  117. //la spirale est de type linéaire, cela signifie que le rayon de la courbe va croitre de manière proportionnelle à l'angle
  118. coeff_dir = (d2 - d1)/angle;
  119. 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)]);
  120. //function vecteur(t = 0) = [largeur*cos(t)/2, largeur*sin(t)/2];
  121. //création des points extérieur de la spirale du point de départ vers le point d'arrivé
  122. A = [for(i=[0:1:angle])
  123. (coeff_dir * i + d1) * [cos(i + theta1), sin(i + theta1)] + vecteur(t = i + theta1) ];
  124. //création des points interieur de la spirale du point d'arrivé vers le point de départ
  125. B = [for(i=[angle:-1:0])
  126. (coeff_dir * i + d1) * [cos(i + theta1), sin(i + theta1)] - vecteur(t = i + theta1) ];
  127. //combinaison des 2 séries de points
  128. C = concat(A,B);
  129. //tracé de la courbe finale
  130. polygon(C);
  131. }
  132. module spirale_log_coord(x1 = 1, y1 = 0, x2 = 20, y2 = 0, tours = 2, largeur = 1)
  133. {
  134. //calcule des distances par rapport à l'origine
  135. d1 = calcule_distance_2d(x1, y1);
  136. d2 = calcule_distance_2d(x2, y2);
  137. //calcule des angles entre les vecteur OA et Ox
  138. theta1 = calcule_angle_2d(x1, y1);
  139. theta2 = calcule_angle_2d(x2, y2);
  140. echo("<font color='#ffa400'>math.scad, module : spirale_log_coord</font>");
  141. echo("<font color='#ffa400'>theta1 = ", theta1, "</font>");
  142. echo("<font color='#ffa400'>theta2 = ", theta2, "</font>");
  143. //calcule de l'angle à balayer pour effectuer le nombre de tour voulu
  144. //pour lier le point de départ et le point d'arrivé
  145. delta_theta = theta2 - theta1 >= 0 ? theta2 - theta1 : 360 - (theta1 - theta2);
  146. angle = tours * 360 + delta_theta;
  147. theta2_ = angle + theta1;
  148. echo("<font color='#ffa400'>angle = ", angle, "</font>");
  149. /*une spirale logarithmique est décrite par : r = a*b^theta
  150. Si on possède 2 points :
  151. r1 = a*b^theta1
  152. r2 = a*b^theta2
  153. on peut extraire le coefficient a :
  154. ln(r1) = ln(a*b^theta1) = ln(a) + ln(b^theta1) = ln(a) + theta1*ln(b)
  155. ln(r2) = ln(a*b^theta2) = ln(a) + ln(b^theta2) = ln(a) + theta2*ln(b)
  156. ln(r2) - ln(r1) = ln(a) - ln(a) + theta2*ln(b) - theta1*ln(b)
  157. ln(r2/r1) = ln(b) * (theta2 - theta1)
  158. ln(r2/r1)/(theta2-theta1) = ln(b)
  159. <=> b = exp( ln(r2/r1)/(theta2-theta1) )
  160. */
  161. b = exp( ln(d2/d1)/(theta2_-theta1) );
  162. a = d1/(pow(b,theta1));
  163. //création des points extérieur de la spirale du point de départ vers le point d'arrivé
  164. A = [for(i=[0:1:angle])
  165. [(a*pow(b,(i + theta1)) + largeur/2) * cos(i + theta1),
  166. (a*pow(b,(i + theta1)) + largeur/2) * sin(i + theta1)]];
  167. //création des points interieur de la spirale du point d'arrivé vers le point de départ
  168. B = [for(i=[angle:-1:0])
  169. [(a*pow(b,(i + theta1)) - largeur/2) * cos(i + theta1),
  170. (a*pow(b,(i + theta1)) - largeur/2) * sin(i + theta1)]];
  171. //combinaison des 2 séries de points
  172. C = concat(A,B);
  173. //tracé de la courbe finale
  174. polygon(C);
  175. }
  176. //spirale_coord2(x1 = 2.5, y1 = 0, x2 = 20, y2 = 0, tours = 2, largeur = 1);
  177. module spirale_point(A = [0, 0], B = [10, 10], tours = 1, largeur = 1)
  178. {
  179. spirale(A[0], A[1], B[0], B[1], tours, largeur);
  180. }
  181. module polygone_regulier(cotes = 5, rayon = 10)
  182. {
  183. polygon([for(i=[0: 360/cotes : 360])[rayon * cos(i), rayon * sin(i)]]);
  184. }
  185. module portion_disque(rayon = 10, angle = 180)
  186. {
  187. A = [for(i=[0 : 1 : angle])[rayon * cos(i), rayon * sin(i)]];
  188. B = concat([[0, 0]], A);
  189. polygon(B);
  190. }
  191. module gaussienne(sigma = 0.5, mu = 0, interval = 20)
  192. {
  193. polygon([ for(i=[-interval/2:0.1:interval/2])[i, exp(-pow( (i - mu),2))/(2*pow(sigma,2))/(sigma * sqrt(2*pi)) ] ]);
  194. }
  195. module trompette(epaisseur = 2, hauteur = 10, r_min = 20, r_max = 40, precision = 100, facteur = 1)
  196. {
  197. x1 = ln(hauteur/(exp( facteur * (r_max - r_min)) - 1))/facteur;
  198. x2 = r_max - r_min + x1;
  199. function calcule_xb(xa, l) = -sqrt(pow(l, 2)/(1 + facteur * facteur * exp(-2*xa * facteur))) + xa;
  200. function calcule_yb(xa, l) = sqrt(pow(l, 2)/(1 + facteur * facteur * exp(2*xa * facteur))) + exp(facteur * xa);
  201. A = [for(i=[x1:(x2-x1)/precision:x2]) [i ,exp(facteur *i)]];
  202. B = [for(i=[x2:-(x2-x1)/precision:x1]) [calcule_xb(i, epaisseur), calcule_yb(i, epaisseur)]];
  203. C = concat(A,B);
  204. rotate_extrude()
  205. {
  206. translate([ -x2 - r_min, -exp(facteur * x1), 0])
  207. {polygon(C);}
  208. }
  209. }