commit
2315709ad6
10 changed files with 2901 additions and 0 deletions
@ -0,0 +1,200 @@ |
|||||||
|
""" |
||||||
|
punch-guide — build123d |
||||||
|
4 pièces : superieure, inferieure, couvercle, (bac) |
||||||
|
Exporte chaque pièce en STEP et STL dans ./exports/ |
||||||
|
""" |
||||||
|
|
||||||
|
from build123d import * |
||||||
|
|
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
# PARAMÈTRES — modifier ici uniquement |
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
|
||||||
|
# Fente (guide tract) — face droite, centrée en Y |
||||||
|
fente_largeur = 152.0 # mm — largeur de la fente |
||||||
|
fente_profondeur = 60.0 # mm — profondeur (longueur de la rainure) |
||||||
|
fente_section = 2.0 # mm — hauteur de la section (épaisseur papier + jeu) |
||||||
|
fente_z = 15.0 # mm — hauteur depuis le fond intérieur du chapeau |
||||||
|
|
||||||
|
# Cavité perforatrice |
||||||
|
cav_largeur = 100.0 # mm — X |
||||||
|
cav_profondeur = 85.0 # mm — Y |
||||||
|
cav_hauteur = 55.0 # mm — profondeur de creusement depuis le dessus |
||||||
|
cav_offset_y = 30.0 # mm — décalage en Y depuis la paroi arrière |
||||||
|
|
||||||
|
# Trou d'évacuation (confettis) |
||||||
|
evac_taille = 48.0 # mm — côté du carré (45 + jeu) |
||||||
|
evac_offset_x = 40.0 # mm — depuis paroi gauche intérieure |
||||||
|
evac_offset_y = 50.0 # mm — depuis paroi arrière intérieure |
||||||
|
|
||||||
|
# Parois |
||||||
|
epaisseur_paroi = 5.0 # mm |
||||||
|
epaisseur_fond = 10.0 # mm |
||||||
|
|
||||||
|
# Emboîtement |
||||||
|
emboitement_profondeur = 10.0 # mm |
||||||
|
emboitement_jeu = 0.3 # mm |
||||||
|
|
||||||
|
# Couvercle |
||||||
|
couvercle_epaisseur = 3.0 # mm |
||||||
|
couvercle_ouv_largeur = 70.0 # mm — ouverture X |
||||||
|
couvercle_ouv_profondeur = 50.0 # mm — ouverture Y |
||||||
|
|
||||||
|
# Bac |
||||||
|
bac_hauteur = 50.0 # mm |
||||||
|
|
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
# DIMENSIONS DÉRIVÉES |
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
|
||||||
|
chapeau_int_x = max(cav_largeur, fente_profondeur) |
||||||
|
chapeau_int_y = max(cav_profondeur + cav_offset_y, fente_largeur) |
||||||
|
|
||||||
|
chapeau_ext_x = chapeau_int_x + 2 * epaisseur_paroi |
||||||
|
chapeau_ext_y = chapeau_int_y + 2 * epaisseur_paroi |
||||||
|
chapeau_ext_z = epaisseur_fond + cav_hauteur |
||||||
|
|
||||||
|
# Position de la cavité dans le chapeau |
||||||
|
cav_x = (chapeau_ext_x - cav_largeur) / 2 # centrée en X |
||||||
|
cav_y = epaisseur_paroi + cav_offset_y # paroi arrière + offset |
||||||
|
|
||||||
|
# Fente |
||||||
|
fente_y = (chapeau_ext_y - fente_largeur) / 2 # centrée en Y sur la face |
||||||
|
fente_z_abs = epaisseur_fond + fente_z # hauteur absolue depuis le bas |
||||||
|
|
||||||
|
# Bac |
||||||
|
bac_ext_x = chapeau_ext_x - 2 * emboitement_jeu |
||||||
|
bac_ext_y = chapeau_ext_y - 2 * emboitement_jeu |
||||||
|
|
||||||
|
# Couvercle |
||||||
|
couv_ext_x = chapeau_ext_x + 2 * (epaisseur_paroi + emboitement_jeu) |
||||||
|
couv_ext_y = chapeau_ext_y + 2 * (epaisseur_paroi + emboitement_jeu) |
||||||
|
couv_ext_z = couvercle_epaisseur + emboitement_profondeur |
||||||
|
|
||||||
|
offset_couv = epaisseur_paroi + emboitement_jeu |
||||||
|
cav_centre_x = offset_couv + epaisseur_paroi + chapeau_int_x / 2 |
||||||
|
cav_centre_y = offset_couv + epaisseur_paroi + cav_offset_y + cav_profondeur / 2 |
||||||
|
|
||||||
|
|
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
# HELPER — boîte à l'origine, coin bas-gauche en (0,0,0) |
||||||
|
# build123d centre les Box sur l'origine par défaut, |
||||||
|
# on les translate pour les aligner comme en OpenSCAD. |
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
|
||||||
|
def box(x, y, z): |
||||||
|
"""Boîte pleine, coin bas-gauche-avant en (0,0,0).""" |
||||||
|
return Box(x, y, z).translate((x/2, y/2, z/2)) |
||||||
|
|
||||||
|
|
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
# PARTIE SUPÉRIEURE (chapeau) |
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
|
||||||
|
def make_superieure(): |
||||||
|
|
||||||
|
# 1. Corps principal |
||||||
|
corps = box(chapeau_ext_x, chapeau_ext_y, chapeau_ext_z) |
||||||
|
|
||||||
|
# 2. Lèvre d'emboîtement (cadre périphérique en bas) |
||||||
|
levre_bloc = box(chapeau_ext_x, chapeau_ext_y, emboitement_profondeur) |
||||||
|
levre_vide = box( |
||||||
|
chapeau_ext_x - 2 * epaisseur_paroi, |
||||||
|
chapeau_ext_y - 2 * epaisseur_paroi, |
||||||
|
emboitement_profondeur + 1 |
||||||
|
).translate((epaisseur_paroi, epaisseur_paroi, 0)) |
||||||
|
levre = levre_bloc - levre_vide |
||||||
|
levre = levre.translate((0, 0, -emboitement_profondeur)) |
||||||
|
|
||||||
|
base = corps + levre |
||||||
|
|
||||||
|
# 3. Cavité perforatrice (ouverte vers le haut) |
||||||
|
cavite = box(cav_largeur, cav_profondeur, cav_hauteur + 1) |
||||||
|
cavite = cavite.translate((cav_x, cav_y, epaisseur_fond)) |
||||||
|
|
||||||
|
# 4. Fente latérale (débouche sur la face droite, X max) |
||||||
|
fente = box(fente_profondeur + 1, fente_largeur, fente_section) |
||||||
|
fente = fente.translate(( |
||||||
|
chapeau_ext_x - fente_profondeur, |
||||||
|
fente_y, |
||||||
|
fente_z_abs |
||||||
|
)) |
||||||
|
|
||||||
|
# 5. Trou d'évacuation (perce le fond depuis en dessous) |
||||||
|
evac = box(evac_taille, evac_taille, epaisseur_fond + 2) |
||||||
|
evac = evac.translate(( |
||||||
|
epaisseur_paroi + evac_offset_x, |
||||||
|
epaisseur_paroi + evac_offset_y, |
||||||
|
-1 |
||||||
|
)) |
||||||
|
|
||||||
|
return base - cavite - fente - evac |
||||||
|
|
||||||
|
|
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
# PARTIE INFÉRIEURE (bac) |
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
|
||||||
|
def make_inferieure(): |
||||||
|
|
||||||
|
# 1. Bloc de base |
||||||
|
bac = box(bac_ext_x, bac_ext_y, bac_hauteur) |
||||||
|
|
||||||
|
# 2. Vidage intérieur (ouvert par le haut) |
||||||
|
vide = box( |
||||||
|
bac_ext_x - 2 * epaisseur_paroi, |
||||||
|
bac_ext_y - 2 * epaisseur_paroi, |
||||||
|
bac_hauteur |
||||||
|
).translate((epaisseur_paroi, epaisseur_paroi, epaisseur_fond)) |
||||||
|
|
||||||
|
return bac - vide |
||||||
|
|
||||||
|
|
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
# COUVERCLE |
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
|
||||||
|
def make_couvercle(): |
||||||
|
|
||||||
|
# 1. Bloc de base |
||||||
|
bloc = box(couv_ext_x, couv_ext_y, couv_ext_z) |
||||||
|
|
||||||
|
# 2. Évidement intérieur (lèvre qui coiffe le chapeau) |
||||||
|
vide_levre = box( |
||||||
|
couv_ext_x - 2 * epaisseur_paroi, |
||||||
|
couv_ext_y - 2 * epaisseur_paroi, |
||||||
|
emboitement_profondeur + 1 |
||||||
|
).translate((epaisseur_paroi, epaisseur_paroi, -1)) |
||||||
|
|
||||||
|
# 3. Ouverture rectangulaire centrée sur la cavité |
||||||
|
ouverture = box(couvercle_ouv_largeur, couvercle_ouv_profondeur, couvercle_epaisseur + 2) |
||||||
|
ouverture = ouverture.translate(( |
||||||
|
cav_centre_x - couvercle_ouv_largeur / 2, |
||||||
|
cav_centre_y - couvercle_ouv_profondeur / 2, |
||||||
|
emboitement_profondeur - 1 |
||||||
|
)) |
||||||
|
|
||||||
|
return bloc - vide_levre - ouverture |
||||||
|
|
||||||
|
|
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
# EXPORT |
||||||
|
# ───────────────────────────────────────────────────────────────────────────── |
||||||
|
|
||||||
|
import os |
||||||
|
os.makedirs("exports", exist_ok=True) |
||||||
|
|
||||||
|
pieces = { |
||||||
|
"superieure": make_superieure, |
||||||
|
"inferieure": make_inferieure, |
||||||
|
"couvercle": make_couvercle, |
||||||
|
} |
||||||
|
|
||||||
|
for nom, fn in pieces.items(): |
||||||
|
print(f"Construction : {nom}...") |
||||||
|
piece = fn() |
||||||
|
export_step(piece, f"exports/{nom}.step") |
||||||
|
export_stl(piece, f"exports/{nom}.stl") |
||||||
|
print(f" → exports/{nom}.step / .stl") |
||||||
|
|
||||||
|
print("Terminé.") |
||||||
@ -0,0 +1,61 @@ |
|||||||
|
// ============================================= |
||||||
|
// COUVERCLE.scad |
||||||
|
// Coiffe la partie supérieure par l'extérieur, |
||||||
|
// même principe d'emboîtement que chapeau/bac. |
||||||
|
// Ouverture rectangulaire centrée sur la cavité. |
||||||
|
// ============================================= |
||||||
|
|
||||||
|
include <parametres.scad> |
||||||
|
|
||||||
|
couvercle(); |
||||||
|
|
||||||
|
module couvercle() { |
||||||
|
|
||||||
|
// Dimensions extérieures du couvercle. |
||||||
|
// La lèvre intérieure doit glisser autour du chapeau : |
||||||
|
// on ajoute le jeu + l'épaisseur de paroi de chaque côté. |
||||||
|
couv_ext_x = chapeau_ext_x + 2 * (epaisseur_paroi + emboitement_jeu); |
||||||
|
couv_ext_y = chapeau_ext_y + 2 * (epaisseur_paroi + emboitement_jeu); |
||||||
|
couv_ext_z = couvercle_epaisseur + emboitement_profondeur; |
||||||
|
|
||||||
|
// Centre de la cavité en X/Y dans le repère du couvercle. |
||||||
|
// La cavité est centrée en X dans le chapeau, et positionnée en Y par cav_offset_y. |
||||||
|
// Dans le repère du couvercle, on décale de epaisseur_paroi + emboitement_jeu |
||||||
|
// pour compenser le débord de la lèvre. |
||||||
|
offset_couv = epaisseur_paroi + emboitement_jeu; // décalage repère chapeau → couvercle |
||||||
|
|
||||||
|
cav_centre_x = offset_couv + epaisseur_paroi + chapeau_int_x / 2; |
||||||
|
cav_centre_y = offset_couv + epaisseur_paroi + cav_offset_y + cav_profondeur / 2; |
||||||
|
|
||||||
|
difference() { |
||||||
|
|
||||||
|
// ── 1. BLOC DE BASE ─────────────────────────────────────────── |
||||||
|
cube([couv_ext_x, couv_ext_y, couv_ext_z]); |
||||||
|
|
||||||
|
|
||||||
|
// ── 2. ÉVIDEMENT INTÉRIEUR — lèvre d'emboîtement ───────────── |
||||||
|
// On creuse le dessous du couvercle pour qu'il vienne coiffer |
||||||
|
// le chapeau. La lèvre a l'épaisseur epaisseur_paroi. |
||||||
|
translate([epaisseur_paroi, epaisseur_paroi, -1]) |
||||||
|
cube([ |
||||||
|
couv_ext_x - 2 * epaisseur_paroi, |
||||||
|
couv_ext_y - 2 * epaisseur_paroi, |
||||||
|
emboitement_profondeur + 1 // s'arrête au plateau |
||||||
|
]); |
||||||
|
|
||||||
|
|
||||||
|
// ── 3. OUVERTURE RECTANGULAIRE ──────────────────────────────── |
||||||
|
// Trou traversant le plateau, centré sur la cavité perforatrice. |
||||||
|
translate([ |
||||||
|
cav_centre_x - couvercle_ouv_largeur / 2, |
||||||
|
cav_centre_y - couvercle_ouv_profondeur / 2, |
||||||
|
emboitement_profondeur - 1 // perce depuis le plateau vers le haut |
||||||
|
]) |
||||||
|
cube([ |
||||||
|
couvercle_ouv_largeur, |
||||||
|
couvercle_ouv_profondeur, |
||||||
|
couvercle_epaisseur + 2 |
||||||
|
]); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
// ============================================= |
||||||
|
// INFERIEURE.scad — Le bac de récupération |
||||||
|
// Boîte ouverte sur le dessus. |
||||||
|
// Dimensions dérivées du chapeau. |
||||||
|
// ============================================= |
||||||
|
|
||||||
|
include <parametres.scad> |
||||||
|
|
||||||
|
inferieure(); |
||||||
|
|
||||||
|
module inferieure() { |
||||||
|
|
||||||
|
// Dimensions extérieures du bac. |
||||||
|
// Le bac doit s'insérer dans la lèvre du chapeau : |
||||||
|
// on retire le jeu d'emboîtement sur chaque face. |
||||||
|
bac_ext_x = chapeau_ext_x - 2 * emboitement_jeu; |
||||||
|
bac_ext_y = chapeau_ext_y - 2 * emboitement_jeu; |
||||||
|
|
||||||
|
difference() { |
||||||
|
|
||||||
|
// ── 1. BLOC DE BASE ─────────────────────────────────────────── |
||||||
|
cube([bac_ext_x, bac_ext_y, bac_hauteur]); |
||||||
|
|
||||||
|
// ── 2. VIDAGE INTÉRIEUR (ouvert par le haut) ────────────────── |
||||||
|
translate([epaisseur_paroi, epaisseur_paroi, epaisseur_fond]) |
||||||
|
cube([ |
||||||
|
bac_ext_x - 2 * epaisseur_paroi, |
||||||
|
bac_ext_y - 2 * epaisseur_paroi, |
||||||
|
bac_hauteur // traversant vers le haut |
||||||
|
]); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,76 @@ |
|||||||
|
// ============================================= |
||||||
|
// PARAMETRES GLOBAUX — punch-guide |
||||||
|
// Modifier uniquement ce fichier. |
||||||
|
// ============================================= |
||||||
|
|
||||||
|
|
||||||
|
// ─── FENTE (guide tract) ───────────────────────────────────────────────────── |
||||||
|
// La fente est centrée sur la face droite du chapeau. |
||||||
|
|
||||||
|
fente_largeur = 152; // mm — largeur de la fente (tract 105mm + jeu latéral) |
||||||
|
fente_profondeur = 60; // mm — profondeur d'enfoncement du tract jusqu'à la butée |
||||||
|
fente_section = 2.0; // mm — hauteur de la section (épaisseur papier + jeu vertical) |
||||||
|
fente_z = 15; // mm — hauteur de la fente depuis le fond intérieur du chapeau |
||||||
|
|
||||||
|
|
||||||
|
// ─── CAVITÉ PERFORATRICE ───────────────────────────────────────────────────── |
||||||
|
// Pavé ouvert vers le haut, dans lequel la perforatrice s'encastre. |
||||||
|
|
||||||
|
cav_largeur = 100; // mm — dimension X de la cavité <<<< À MESURER |
||||||
|
cav_profondeur = 85; // mm — dimension Y de la cavité <<<< À MESURER |
||||||
|
cav_hauteur = 55; // mm — profondeur du creusement depuis le dessus <<<< À MESURER |
||||||
|
|
||||||
|
// Décalage de la cavité sur l'axe Y (perpendiculaire à la face de la fente). |
||||||
|
// Permet d'aligner la lame avec l'axe de la fente. |
||||||
|
// 0 = cavité calée contre la paroi arrière (opposée à la fente). |
||||||
|
cav_offset_y = 30; // mm <<<< À AJUSTER |
||||||
|
|
||||||
|
|
||||||
|
// ─── TROU D'ÉVACUATION ─────────────────────────────────────────────────────── |
||||||
|
// Trou carré dans le fond du chapeau, centré sous la lame. |
||||||
|
// Les confettis tombent dans le bac. |
||||||
|
|
||||||
|
evac_taille = 48; // mm — côté du trou (carré 45mm + jeu) |
||||||
|
evac_offset_x = 40; // mm — position X depuis la paroi gauche intérieure <<<< À AJUSTER |
||||||
|
evac_offset_y = 50; // mm — position Y depuis la paroi arrière intérieure <<<< À AJUSTER |
||||||
|
|
||||||
|
|
||||||
|
// ─── PAROIS ────────────────────────────────────────────────────────────────── |
||||||
|
|
||||||
|
epaisseur_paroi = 5; // mm |
||||||
|
epaisseur_fond = 10; // mm |
||||||
|
|
||||||
|
|
||||||
|
// ─── EMBOÎTEMENT chapeau / bac ─────────────────────────────────────────────── |
||||||
|
|
||||||
|
emboitement_profondeur = 10; // mm — hauteur du chevauchement |
||||||
|
emboitement_jeu = 0.3; // mm — jeu radial entre lèvre et bac (ajuster selon imprimante) |
||||||
|
|
||||||
|
|
||||||
|
// ─── COUVERCLE ─────────────────────────────────────────────────────────────── |
||||||
|
// Le couvercle coiffe le chapeau par l'extérieur (même système que chapeau/bac). |
||||||
|
// Il a une ouverture rectangulaire centrée sur la cavité de la perforatrice. |
||||||
|
|
||||||
|
couvercle_epaisseur = 3; // mm — épaisseur du plateau du couvercle |
||||||
|
couvercle_ouv_largeur = 70; // mm — largeur de l'ouverture / X |
||||||
|
couvercle_ouv_profondeur = 50; // mm — profondeur de l'ouverture / Y |
||||||
|
|
||||||
|
|
||||||
|
// ─── BAC DE RÉCUPÉRATION ───────────────────────────────────────────────────── |
||||||
|
|
||||||
|
bac_hauteur = 50; // mm — hauteur utile du bac |
||||||
|
|
||||||
|
|
||||||
|
// ─── DIMENSIONS DÉRIVÉES (ne pas modifier) ─────────────────────────────────── |
||||||
|
// |
||||||
|
// Le chapeau englobe tout : |
||||||
|
// X : le plus grand entre la cavité et la fente, + 2 × paroi |
||||||
|
// Y : le plus grand entre (cavité + son offset) et la profondeur de fente, + 2 × paroi |
||||||
|
// Z : fond + hauteur de cavité (la cavité ouvre le dessus, donc elle fixe la hauteur) |
||||||
|
|
||||||
|
chapeau_int_x = max(cav_largeur, fente_profondeur); |
||||||
|
chapeau_int_y = max(cav_profondeur + cav_offset_y, fente_largeur); |
||||||
|
|
||||||
|
chapeau_ext_x = chapeau_int_x + 2 * epaisseur_paroi; |
||||||
|
chapeau_ext_y = chapeau_int_y + 2 * epaisseur_paroi; |
||||||
|
chapeau_ext_z = epaisseur_fond + cav_hauteur; |
||||||
@ -0,0 +1,80 @@ |
|||||||
|
// ============================================= |
||||||
|
// SUPERIEURE.scad — Le chapeau |
||||||
|
// ============================================= |
||||||
|
|
||||||
|
include <parametres.scad> |
||||||
|
|
||||||
|
superieure(); |
||||||
|
|
||||||
|
module superieure() { |
||||||
|
difference() { |
||||||
|
|
||||||
|
// ── 1. BLOC DE BASE + LÈVRE D'EMBOÎTEMENT ──────────────────── |
||||||
|
union() { |
||||||
|
|
||||||
|
// Corps principal du chapeau |
||||||
|
cube([chapeau_ext_x, chapeau_ext_y, chapeau_ext_z]); |
||||||
|
|
||||||
|
// Lèvre d'emboîtement — cadre périphérique en bas du chapeau, |
||||||
|
// qui vient coiffer le bac par glissement vers le bas. |
||||||
|
translate([0, 0, -emboitement_profondeur]) |
||||||
|
difference() { |
||||||
|
// Bloc extérieur de la lèvre (même empreinte que le chapeau) |
||||||
|
cube([chapeau_ext_x, chapeau_ext_y, emboitement_profondeur]); |
||||||
|
// On vide l'intérieur : ne reste que le cadre |
||||||
|
translate([epaisseur_paroi, epaisseur_paroi, -1]) |
||||||
|
cube([ |
||||||
|
chapeau_ext_x - 2 * epaisseur_paroi, |
||||||
|
chapeau_ext_y - 2 * epaisseur_paroi, |
||||||
|
emboitement_profondeur + 2 |
||||||
|
]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// ── 2. CAVITÉ PERFORATRICE ──────────────────────────────────── |
||||||
|
// Pavé creusé depuis le dessus, ouvert vers le haut. |
||||||
|
// Centré en X, décalé en Y selon cav_offset_y. |
||||||
|
// |
||||||
|
// Centrage en X dans le chapeau : |
||||||
|
cav_x = (chapeau_ext_x - cav_largeur) / 2; |
||||||
|
// Position en Y : paroi arrière + offset |
||||||
|
cav_y = epaisseur_paroi + cav_offset_y; |
||||||
|
// La cavité part du dessus et descend de cav_hauteur |
||||||
|
cav_z = epaisseur_fond; // démarre au-dessus du fond |
||||||
|
|
||||||
|
translate([cav_x, cav_y, cav_z]) |
||||||
|
cube([cav_largeur, cav_profondeur, cav_hauteur + 1]); // +1 pour sortir du dessus |
||||||
|
|
||||||
|
|
||||||
|
// ── 3. FENTE LATÉRALE — guide tract (face DROITE, centrée) ─── |
||||||
|
// Rainure horizontale débouchant sur la face droite (X max). |
||||||
|
// Centrée en Y sur la face. |
||||||
|
// La butée est le fond de la rainure (paroi non percée). |
||||||
|
// |
||||||
|
// Centre de la fente en Y = centre du chapeau |
||||||
|
fente_y = (chapeau_ext_y - fente_largeur) / 2; |
||||||
|
// Hauteur absolue de la fente (depuis le bas du chapeau) |
||||||
|
fente_z_abs = epaisseur_fond + fente_z; |
||||||
|
|
||||||
|
translate([ |
||||||
|
chapeau_ext_x - fente_profondeur, // la fente entre par la droite |
||||||
|
fente_y, |
||||||
|
fente_z_abs |
||||||
|
]) |
||||||
|
cube([fente_profondeur + 1, fente_largeur, fente_section]); // +1 pour déboucher |
||||||
|
|
||||||
|
|
||||||
|
// ── 4. TROU D'ÉVACUATION DES CONFETTIS ─────────────────────── |
||||||
|
// Trou carré dans le fond, positionné par evac_offset_x/y |
||||||
|
// depuis le coin intérieur bas-gauche / arrière. |
||||||
|
|
||||||
|
translate([ |
||||||
|
epaisseur_paroi + evac_offset_x, |
||||||
|
epaisseur_paroi + evac_offset_y, |
||||||
|
-1 // perce depuis en dessous |
||||||
|
]) |
||||||
|
cube([evac_taille, evac_taille, epaisseur_fond + 2]); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,9 @@ |
|||||||
|
[project] |
||||||
|
name = "tractrudeuse" |
||||||
|
version = "0.1.0" |
||||||
|
requires-python = ">=3.11" |
||||||
|
dependencies = [ |
||||||
|
"build123d", |
||||||
|
"ipykernel>=7.2.0", |
||||||
|
"ocp-vscode", |
||||||
|
] |
||||||
@ -0,0 +1,297 @@ |
|||||||
|
{ |
||||||
|
"cells": [ |
||||||
|
{ |
||||||
|
"cell_type": "code", |
||||||
|
"id": "initial_id", |
||||||
|
"metadata": { |
||||||
|
"collapsed": true, |
||||||
|
"ExecuteTime": { |
||||||
|
"end_time": "2026-05-08T19:21:25.951438147Z", |
||||||
|
"start_time": "2026-05-08T19:21:24.452607608Z" |
||||||
|
} |
||||||
|
}, |
||||||
|
"source": [ |
||||||
|
"\"\"\"\n", |
||||||
|
"punch-guide — build123d\n", |
||||||
|
"4 pièces : superieure, inferieure, couvercle, (bac)\n", |
||||||
|
"Exporte chaque pièce en STEP et STL dans ./exports/\n", |
||||||
|
"\"\"\"\n", |
||||||
|
"\n", |
||||||
|
"from build123d import *\n", |
||||||
|
"\n", |
||||||
|
"# ─────────────────────────────────────────────────────────────────────────────\n", |
||||||
|
"# PARAMÈTRES — modifier ici uniquement\n", |
||||||
|
"# ─────────────────────────────────────────────────────────────────────────────\n", |
||||||
|
"\n", |
||||||
|
"# Fente (guide tract) — face droite, centrée en Y\n", |
||||||
|
"fente_largeur = 152.0 # mm — largeur de la fente\n", |
||||||
|
"fente_profondeur = 60.0 # mm — profondeur (longueur de la rainure)\n", |
||||||
|
"fente_section = 2.0 # mm — hauteur de la section (épaisseur papier + jeu)\n", |
||||||
|
"fente_z = 15.0 # mm — hauteur depuis le fond intérieur du chapeau\n", |
||||||
|
"\n", |
||||||
|
"# Cavité perforatrice\n", |
||||||
|
"cav_largeur = 100.0 # mm — X\n", |
||||||
|
"cav_profondeur = 85.0 # mm — Y\n", |
||||||
|
"cav_hauteur = 55.0 # mm — profondeur de creusement depuis le dessus\n", |
||||||
|
"cav_offset_y = 30.0 # mm — décalage en Y depuis la paroi arrière\n", |
||||||
|
"\n", |
||||||
|
"# Trou d'évacuation (confettis)\n", |
||||||
|
"evac_taille = 48.0 # mm — côté du carré (45 + jeu)\n", |
||||||
|
"evac_offset_x = 40.0 # mm — depuis paroi gauche intérieure\n", |
||||||
|
"evac_offset_y = 50.0 # mm — depuis paroi arrière intérieure\n", |
||||||
|
"\n", |
||||||
|
"# Parois\n", |
||||||
|
"epaisseur_paroi = 5.0 # mm\n", |
||||||
|
"epaisseur_fond = 10.0 # mm\n", |
||||||
|
"\n", |
||||||
|
"# Emboîtement\n", |
||||||
|
"emboitement_profondeur = 10.0 # mm\n", |
||||||
|
"emboitement_jeu = 0.3 # mm\n", |
||||||
|
"\n", |
||||||
|
"# Couvercle\n", |
||||||
|
"couvercle_epaisseur = 3.0 # mm\n", |
||||||
|
"couvercle_ouv_largeur = 70.0 # mm — ouverture X\n", |
||||||
|
"couvercle_ouv_profondeur = 50.0 # mm — ouverture Y\n", |
||||||
|
"\n", |
||||||
|
"# Bac\n", |
||||||
|
"bac_hauteur = 50.0 # mm\n", |
||||||
|
"\n", |
||||||
|
"# ─────────────────────────────────────────────────────────────────────────────\n", |
||||||
|
"# DIMENSIONS DÉRIVÉES\n", |
||||||
|
"# ─────────────────────────────────────────────────────────────────────────────\n", |
||||||
|
"\n", |
||||||
|
"chapeau_int_x = max(cav_largeur, fente_profondeur)\n", |
||||||
|
"chapeau_int_y = max(cav_profondeur + cav_offset_y, fente_largeur)\n", |
||||||
|
"\n", |
||||||
|
"chapeau_ext_x = chapeau_int_x + 2 * epaisseur_paroi\n", |
||||||
|
"chapeau_ext_y = chapeau_int_y + 2 * epaisseur_paroi\n", |
||||||
|
"chapeau_ext_z = epaisseur_fond + cav_hauteur\n", |
||||||
|
"\n", |
||||||
|
"# Position de la cavité dans le chapeau\n", |
||||||
|
"cav_x = (chapeau_ext_x - cav_largeur) / 2 # centrée en X\n", |
||||||
|
"cav_y = epaisseur_paroi + cav_offset_y # paroi arrière + offset\n", |
||||||
|
"\n", |
||||||
|
"# Fente\n", |
||||||
|
"fente_y = (chapeau_ext_y - fente_largeur) / 2 # centrée en Y sur la face\n", |
||||||
|
"fente_z_abs = epaisseur_fond + fente_z # hauteur absolue depuis le bas\n", |
||||||
|
"\n", |
||||||
|
"# Bac\n", |
||||||
|
"bac_ext_x = chapeau_ext_x + 2 * (epaisseur_paroi + emboitement_jeu)\n", |
||||||
|
"bac_ext_y = chapeau_ext_y + 2 * (epaisseur_paroi + emboitement_jeu)\n", |
||||||
|
"\n", |
||||||
|
"# Couvercle\n", |
||||||
|
"couv_ext_x = chapeau_ext_x + 2 * (epaisseur_paroi + emboitement_jeu)\n", |
||||||
|
"couv_ext_y = chapeau_ext_y + 2 * (epaisseur_paroi + emboitement_jeu)\n", |
||||||
|
"couv_ext_z = couvercle_epaisseur + emboitement_profondeur\n", |
||||||
|
"\n", |
||||||
|
"offset_couv = epaisseur_paroi + emboitement_jeu\n", |
||||||
|
"cav_centre_x = offset_couv + epaisseur_paroi + chapeau_int_x / 2\n", |
||||||
|
"cav_centre_y = offset_couv + epaisseur_paroi + cav_offset_y + cav_profondeur / 2\n", |
||||||
|
"\n", |
||||||
|
"\n", |
||||||
|
"# ─────────────────────────────────────────────────────────────────────────────\n", |
||||||
|
"# PARTIE SUPÉRIEURE (chapeau)\n", |
||||||
|
"# ─────────────────────────────────────────────────────────────────────────────\n", |
||||||
|
"\n", |
||||||
|
"def make_superieure():\n", |
||||||
|
" with BuildPart() as p:\n", |
||||||
|
" # 1. Corps principal\n", |
||||||
|
" with Locations(Location((chapeau_ext_x / 2, chapeau_ext_y / 2, chapeau_ext_z / 2))):\n", |
||||||
|
" Box(chapeau_ext_x, chapeau_ext_y, chapeau_ext_z)\n", |
||||||
|
"\n", |
||||||
|
" chamfer(edges().filter_by(Axis.Z), length=2)\n", |
||||||
|
"\n", |
||||||
|
" # 2. Cavité perforatrice (ouverte vers le haut)\n", |
||||||
|
" with Locations(Location((\n", |
||||||
|
" cav_x + cav_largeur / 2,\n", |
||||||
|
" cav_y + cav_profondeur / 2,\n", |
||||||
|
" epaisseur_fond + (cav_hauteur + 1) / 2,\n", |
||||||
|
" ))):\n", |
||||||
|
" Box(cav_largeur, cav_profondeur, cav_hauteur + 1, mode=Mode.SUBTRACT)\n", |
||||||
|
"\n", |
||||||
|
" # 3. Fente latérale (débouche sur la face droite, X max)\n", |
||||||
|
" with Locations(Location((\n", |
||||||
|
" chapeau_ext_x - fente_profondeur + (fente_profondeur + 1) / 2,\n", |
||||||
|
" fente_y + fente_largeur / 2,\n", |
||||||
|
" fente_z_abs + fente_section / 2,\n", |
||||||
|
" ))):\n", |
||||||
|
" Box(fente_profondeur + 1, fente_largeur, fente_section, mode=Mode.SUBTRACT)\n", |
||||||
|
"\n", |
||||||
|
" # 4. Trou d'évacuation (perce le fond depuis en dessous)\n", |
||||||
|
" with Locations(Location((\n", |
||||||
|
" epaisseur_paroi + evac_offset_x + evac_taille / 2,\n", |
||||||
|
" epaisseur_paroi + evac_offset_y + evac_taille / 2,\n", |
||||||
|
" -1 + (epaisseur_fond + 2) / 2,\n", |
||||||
|
" ))):\n", |
||||||
|
" Box(evac_taille, evac_taille, epaisseur_fond + 2, mode=Mode.SUBTRACT)\n", |
||||||
|
"\n", |
||||||
|
" # Chanfrein sur le pourtour supérieur du trou\n", |
||||||
|
" evac_top = edges().filter_by_position(Axis.Z, epaisseur_fond - 0.01, epaisseur_fond + 0.01)\n", |
||||||
|
" chamfer(evac_top, length=2)\n", |
||||||
|
"\n", |
||||||
|
" # chamfrein sur le pourtour de la fente\n", |
||||||
|
" fente_opening = (\n", |
||||||
|
" faces().sort_by(Axis.X)[-1]\n", |
||||||
|
" .edges()\n", |
||||||
|
" .filter_by_position(Axis.Z, fente_z_abs - 0.01, fente_z_abs + fente_section + 0.01)\n", |
||||||
|
" )\n", |
||||||
|
" chamfer(fente_opening, length=0.5)\n", |
||||||
|
"\n", |
||||||
|
" # Trous de boulons pour fixer la trouyoteuse\n", |
||||||
|
" cav_bottom = faces().filter_by_position(\n", |
||||||
|
" Axis.Z, epaisseur_fond - 0.01, epaisseur_fond + 0.01\n", |
||||||
|
" )[0]\n", |
||||||
|
"\n", |
||||||
|
" with Locations(cav_bottom):\n", |
||||||
|
" with GridLocations(50, 60, 2, 2):\n", |
||||||
|
" Hole(radius=3)\n", |
||||||
|
"\n", |
||||||
|
" # Plan centré sur la face droite, au-dessus de la fente\n", |
||||||
|
" z_logo = fente_z_abs + fente_section + 5\n", |
||||||
|
" plan_logo = Plane(\n", |
||||||
|
" origin=Vector(chapeau_ext_x, chapeau_ext_y / 2, z_logo),\n", |
||||||
|
" x_dir=Vector(0, 1, 0), # Y global → X local\n", |
||||||
|
" z_dir=Vector(1, 0, 0), # normale sortante (X+)\n", |
||||||
|
" )\n", |
||||||
|
"\n", |
||||||
|
" logo_shapes = import_svg(\"logo.svg\")\n", |
||||||
|
" min_x = min(s.bounding_box().min.X for s in logo_shapes)\n", |
||||||
|
" max_x = max(s.bounding_box().max.X for s in logo_shapes)\n", |
||||||
|
" cx = (min_x + max_x) / 2\n", |
||||||
|
"\n", |
||||||
|
" with BuildSketch(plan_logo) as sk:\n", |
||||||
|
" add([s.translate((-cx, 0, 0)) for s in logo_shapes])\n", |
||||||
|
" scale(by=0.7)\n", |
||||||
|
"\n", |
||||||
|
" extrude(amount=-1.5, mode=Mode.SUBTRACT) # 1.5 mm de profondeur\n", |
||||||
|
"\n", |
||||||
|
"\n", |
||||||
|
" return p.part\n", |
||||||
|
"\n", |
||||||
|
"\n", |
||||||
|
"# ─────────────────────────────────────────────────────────────────────────────\n", |
||||||
|
"# PARTIE INFÉRIEURE (bac)\n", |
||||||
|
"# ─────────────────────────────────────────────────────────────────────────────\n", |
||||||
|
"\n", |
||||||
|
"def make_inferieure():\n", |
||||||
|
" with BuildPart() as p:\n", |
||||||
|
" # Corps extérieur\n", |
||||||
|
" with Locations(Location((bac_ext_x / 2, bac_ext_y / 2, bac_hauteur / 2))):\n", |
||||||
|
" Box(bac_ext_x, bac_ext_y, bac_hauteur)\n", |
||||||
|
"\n", |
||||||
|
" top_edges = faces().sort_by(Axis.Z)[-1].edges()\n", |
||||||
|
" lateral_edges = edges().filter_by(Axis.Z)\n", |
||||||
|
" chamfer(top_edges + lateral_edges, length=2)\n", |
||||||
|
"\n", |
||||||
|
" # Lèvre intérieure d'emboitement\n", |
||||||
|
" with Locations(Location((bac_ext_x / 2, bac_ext_y / 2, bac_hauteur))):\n", |
||||||
|
" Box(\n", |
||||||
|
" bac_ext_x - 2 * epaisseur_paroi,\n", |
||||||
|
" bac_ext_y - 2 * epaisseur_paroi,\n", |
||||||
|
" emboitement_profondeur,\n", |
||||||
|
" mode=Mode.SUBTRACT,\n", |
||||||
|
" )\n", |
||||||
|
" # Vidage intérieur — ouvert par le haut\n", |
||||||
|
" with Locations(Location((bac_ext_x / 2, bac_ext_y / 2, epaisseur_fond + bac_hauteur / 2))):\n", |
||||||
|
" Box(\n", |
||||||
|
" bac_ext_x - 3 * epaisseur_paroi,\n", |
||||||
|
" bac_ext_y - 3 * epaisseur_paroi,\n", |
||||||
|
" bac_hauteur,\n", |
||||||
|
" mode=Mode.SUBTRACT,\n", |
||||||
|
" )\n", |
||||||
|
"\n", |
||||||
|
" return p.part\n", |
||||||
|
"\n", |
||||||
|
"\n", |
||||||
|
"# ─────────────────────────────────────────────────────────────────────────────\n", |
||||||
|
"# COUVERCLE\n", |
||||||
|
"# ─────────────────────────────────────────────────────────────────────────────\n", |
||||||
|
"\n", |
||||||
|
"def make_couvercle():\n", |
||||||
|
" with BuildPart() as p:\n", |
||||||
|
" # 1. Bloc de base\n", |
||||||
|
" with Locations(Location((couv_ext_x / 2, couv_ext_y / 2, couv_ext_z / 2))):\n", |
||||||
|
" Box(couv_ext_x, couv_ext_y, couv_ext_z)\n", |
||||||
|
"\n", |
||||||
|
" # 2. Évidement intérieur (lèvre qui coiffe le chapeau)\n", |
||||||
|
" with Locations(Location((couv_ext_x / 2, couv_ext_y / 2, (emboitement_profondeur - 1) / 2))):\n", |
||||||
|
" Box(\n", |
||||||
|
" couv_ext_x - 2 * epaisseur_paroi,\n", |
||||||
|
" couv_ext_y - 2 * epaisseur_paroi,\n", |
||||||
|
" emboitement_profondeur + 1,\n", |
||||||
|
" mode=Mode.SUBTRACT,\n", |
||||||
|
" )\n", |
||||||
|
"\n", |
||||||
|
" # 3. Ouverture rectangulaire centrée sur la cavité\n", |
||||||
|
" ouv_z = emboitement_profondeur - 1 + (couvercle_epaisseur + 2) / 2\n", |
||||||
|
" with Locations(Location((cav_centre_x, cav_centre_y, ouv_z))):\n", |
||||||
|
" Box(\n", |
||||||
|
" couvercle_ouv_largeur,\n", |
||||||
|
" couvercle_ouv_profondeur,\n", |
||||||
|
" couvercle_epaisseur + 2,\n", |
||||||
|
" mode=Mode.SUBTRACT,\n", |
||||||
|
" )\n", |
||||||
|
"\n", |
||||||
|
" # 4. Chanfrein — arêtes du dessus + arêtes latérales (verticales)\n", |
||||||
|
" top_edges = faces().sort_by(Axis.Z)[-1].edges()\n", |
||||||
|
" lateral_edges = edges().filter_by(Axis.Z)\n", |
||||||
|
" chamfer(top_edges + lateral_edges, length=2)\n", |
||||||
|
"\n", |
||||||
|
" return p.part\n", |
||||||
|
"\n", |
||||||
|
"\n", |
||||||
|
"def center_xy(part):\n", |
||||||
|
" bb = part.bounding_box()\n", |
||||||
|
" return part.translate((-bb.center().X, -bb.center().Y, 0))\n", |
||||||
|
"\n", |
||||||
|
"\n", |
||||||
|
"show(\n", |
||||||
|
" center_xy(make_superieure()),\n", |
||||||
|
" center_xy(make_inferieure()).translate((0, 0, -(bac_hauteur + gap))),\n", |
||||||
|
" center_xy(make_couvercle()).translate((0, 0, chapeau_ext_z + gap)),\n", |
||||||
|
" names=[\"superieure\", \"inferieure\", \"couvercle\"],\n", |
||||||
|
" colors=[\"#ff7800\", \"#000000\", \"#000000\"],\n", |
||||||
|
")" |
||||||
|
], |
||||||
|
"outputs": [ |
||||||
|
{ |
||||||
|
"name": "stdout", |
||||||
|
"output_type": "stream", |
||||||
|
"text": [ |
||||||
|
"+cc\n" |
||||||
|
] |
||||||
|
} |
||||||
|
], |
||||||
|
"execution_count": 75 |
||||||
|
}, |
||||||
|
{ |
||||||
|
"metadata": {}, |
||||||
|
"cell_type": "code", |
||||||
|
"outputs": [], |
||||||
|
"execution_count": null, |
||||||
|
"source": "", |
||||||
|
"id": "810fb3a101c2fccd" |
||||||
|
} |
||||||
|
], |
||||||
|
"metadata": { |
||||||
|
"kernelspec": { |
||||||
|
"display_name": "Python 3", |
||||||
|
"language": "python", |
||||||
|
"name": "python3" |
||||||
|
}, |
||||||
|
"language_info": { |
||||||
|
"codemirror_mode": { |
||||||
|
"name": "ipython", |
||||||
|
"version": 2 |
||||||
|
}, |
||||||
|
"file_extension": ".py", |
||||||
|
"mimetype": "text/x-python", |
||||||
|
"name": "python", |
||||||
|
"nbconvert_exporter": "python", |
||||||
|
"pygments_lexer": "ipython2", |
||||||
|
"version": "2.7.6" |
||||||
|
} |
||||||
|
}, |
||||||
|
"nbformat": 4, |
||||||
|
"nbformat_minor": 5 |
||||||
|
} |
||||||
Loading…
Reference in new issue