From 935c8cb52632a373cda3b55d2a10e0940aca633a Mon Sep 17 00:00:00 2001 From: babayaga Date: Fri, 4 Jul 2025 12:37:24 +0200 Subject: [PATCH] Open Box :) --- cad/drawers/500/10/Sheet-8.SLDPRT | 4 +- cad/drawers/500/10/~$500-10-Single.SLDASM | 3 + cad/drawers/500/10/~$Sheet-8.SLDPRT | 3 + .../__pycache__/converter.cpython-311.pyc | Bin 0 -> 3497 bytes cad/drawers/tools/box_folding_tool.png | 3 + cad/drawers/tools/box_folding_tool.scad | 268 +++++ cad/drawers/tools/box_folding_tool.step | 3 + cad/drawers/tools/box_folding_tool_true.stl | 982 ++++++++++++++++++ cad/drawers/tools/converter.py | 82 ++ cad/drawers/tools/export_step.sh | 66 ++ cad/drawers/tools/export_stl.sh | 59 ++ cad/drawers/tools/folded_view.png | 3 + cad/drawers/tools/reference/500-10.png | 3 + cad/drawers/tools/reference/variables.png | 3 + cad/drawers/tools/render.sh | 64 ++ 15 files changed, 1544 insertions(+), 2 deletions(-) create mode 100644 cad/drawers/500/10/~$500-10-Single.SLDASM create mode 100644 cad/drawers/500/10/~$Sheet-8.SLDPRT create mode 100644 cad/drawers/tools/__pycache__/converter.cpython-311.pyc create mode 100644 cad/drawers/tools/box_folding_tool.png create mode 100644 cad/drawers/tools/box_folding_tool.scad create mode 100644 cad/drawers/tools/box_folding_tool.step create mode 100644 cad/drawers/tools/box_folding_tool_true.stl create mode 100644 cad/drawers/tools/converter.py create mode 100644 cad/drawers/tools/export_step.sh create mode 100644 cad/drawers/tools/export_stl.sh create mode 100644 cad/drawers/tools/folded_view.png create mode 100644 cad/drawers/tools/reference/500-10.png create mode 100644 cad/drawers/tools/reference/variables.png create mode 100644 cad/drawers/tools/render.sh diff --git a/cad/drawers/500/10/Sheet-8.SLDPRT b/cad/drawers/500/10/Sheet-8.SLDPRT index f8b8037..3e671ea 100644 --- a/cad/drawers/500/10/Sheet-8.SLDPRT +++ b/cad/drawers/500/10/Sheet-8.SLDPRT @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f166cc53cf1b9cab1c92d8d8561a22d8a18dbd0005712516ee488e1446a3548 -size 193760 +oid sha256:dc2f32b23faed1939fb0e32644c8f0f7e93beb136766e74ee4c88929ee32c16a +size 155299 diff --git a/cad/drawers/500/10/~$500-10-Single.SLDASM b/cad/drawers/500/10/~$500-10-Single.SLDASM new file mode 100644 index 0000000..eb02c09 --- /dev/null +++ b/cad/drawers/500/10/~$500-10-Single.SLDASM @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4a275b60be72b83a988df4ef671a53ede5e064c77ec593ccb45ba7039cdd21c +size 3 diff --git a/cad/drawers/500/10/~$Sheet-8.SLDPRT b/cad/drawers/500/10/~$Sheet-8.SLDPRT new file mode 100644 index 0000000..eb02c09 --- /dev/null +++ b/cad/drawers/500/10/~$Sheet-8.SLDPRT @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4a275b60be72b83a988df4ef671a53ede5e064c77ec593ccb45ba7039cdd21c +size 3 diff --git a/cad/drawers/tools/__pycache__/converter.cpython-311.pyc b/cad/drawers/tools/__pycache__/converter.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0231c68623affd81e63c4599deada46917d9a79b GIT binary patch literal 3497 zcmb_cT}&I<6~1H77~?-|Y<_})9kAKJ5(r_Vly&$Ku zfKHqB0lf}k5~DT1mc}yzq37_H2BTZo7|sni1Ea6j5(uPdt>y?#p43-bW~g&zAPN|( zG=>UIt>&o)8^1tb=}y|ybVgizmabNfM!%+2MsTUQ_1n4_7><*T=O=1&m>2IS=0^9h~AE3UvI{*C-0NzP#tKP+shrQwet!}NO zeCj80fzFr_+Zc4znkdkTJ9C~gzH-L3)jqVy42<&(Y2_aaozydgA05`NC*aj;=fd8z z{x_hjv~+eoy?4B-MW`om$Mx)KI8cMXaiE89a&Ur;-N&4OIhqf1k+?u7_|OXW(Zi8g zJRvMCN1}L?9%d85(dt0`MIZe8&6_s|@V-e}-dB;diuBP*>n}8Dd1;tt6ETKPcF;VI zhq#b{=`gzyXJa@f@N^_b3#*vk!2D|e%ICjT$G2li=VFM9MPe&HdZG-alY_7?5oPEY zE6^XQMoM8bw7}9KnrEXCh7K*Od2o0+qHga`wgNI7+Q4)y5sjYGdVbpCYABBTlfI)^ z#$z;HjH^5oE~RKCv{McD^ncDaz6S7OWzNvF=~5Z$$*9 z?zjz>;vr#Gu~)Q0NkT#fj6$l1s5Go#!GCzrM~BBNrsFeL45bPvwK$g8z-mV*L`1P2 zA(k{llwYmCLh;(<*a)p-O)?E-(gHSq$i~?yyRxkqBK!@gheAz@rypl1}T)-;$|D*3CODxb8X!&{0`O9lE^v2d7A zM1@0`sdPSm0ml^re~o@nFV>HDCVatp9;zNpZUrYXzb>%xAj@+>=n^Io7WlImHoD!n zfy1l8aEJ*qTxe6>FR*Ns50+b<>yK~$XdK=EBXB3Vi{MMWiTo?L$VELt5JeLr%qf%l z>u3^=^uPxb+myMATC>yhqpzW>@<1qxUjPlDSJZccmta22|g;@95og^h%CC+0mDp zISgqk^DaEe$79(s(F7r?B$3lHIW3aYu+3&qP3PO*-npGiN^OI3+h7s7sk_8KwXbA6 zmnPDqMO{nnU83M>&rD`#9)FPiAU&10IQA``J&PxIL-t;M>6a|yvSnPfj2Df_b?(XV zXTy(2v!g|1w=NPn{B*s<<(oTq$S+MfU+(f#-!A@UUGn&3k56j8DmP!vP<*Q8(_aqncI>%(MR#w$ zwexp#pU>@fNv#8N>wu_Hp{;XgUi8FYI$mD-)(K3Bq_%r<+dWaELUY>=CAQDM7=ID^ z;{-4zlA0If<^@rsf}=6hAU4hK-rBwQwI7%gNsa~Cu^>7Y{`I<0*IYydRJ!t;x7MfU zMduyy<}LA;e(9!P<$)G&ml(+!l&wLrnn3s(2J|&pQyBxY)EAMCa^;QIG$q=mCF3>O zcuh23%Ny-!{Uc+>@u~TdIc)}{(VXJbR~~%)@Z-#_-+Yq#B;VxC2-#of7Nn*Na?^#h zC2c7*we5tm+i45HDaStP-Xq;&>jjDIlgU1j>?@S6!$pZ4kjVj&95`_uQg9_+7i#Pf z5>fFvY}t{Q9inLjNFqmNa#SQo&)BY-(9EdmQD6pUehO~%pMN%9H{(WsshPZdZAACo vRUIt88=#fwQMgvG*wQ7=%@gZ1z@1|yJ_21L&v!wp7q{{yXet(sf literal 0 HcmV?d00001 diff --git a/cad/drawers/tools/box_folding_tool.png b/cad/drawers/tools/box_folding_tool.png new file mode 100644 index 0000000..5497464 --- /dev/null +++ b/cad/drawers/tools/box_folding_tool.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0c8dfe22039ef5b04072e69d730e4381daffecce799b615b32fd7075ae405f10 +size 22761 diff --git a/cad/drawers/tools/box_folding_tool.scad b/cad/drawers/tools/box_folding_tool.scad new file mode 100644 index 0000000..1f87ca0 --- /dev/null +++ b/cad/drawers/tools/box_folding_tool.scad @@ -0,0 +1,268 @@ +// Customizable parameters for the box folding tool +// These values are based on the provided screenshot. + +// Overall dimensions +TotalWidth = 500; // [100:1000] +TotalLength = 500; // [100:1000] +Height = 80; // [20:200] + +// Material and slot properties +TotalThickness = 5; // [1:20] +BaseThickness = 3; // [0.5:19] +Slot_Width_Walls = 8; // [1:20] + +// Internal grid configuration +Nb_Boxes_U = 2; // [1:10] +Nb_Boxes_V = 2; // [1:10] + +// View control +Folded_View = false; // [true, false] +// Use "export" to render all parts separately for STEP conversion +view_mode = "preview"; // ["preview", "export"] + +// Note: InnerBox_Width from the screenshot (100) is not used directly. +// Instead, the compartment widths are calculated based on TotalWidth, Height, and Nb_Boxes_U/V. +// This ensures the design remains consistent with the overall dimensions. + +// --------------------------------------------------------------------- +// Main module to generate the box folding pattern +// --------------------------------------------------------------------- +module unfolded_pattern() { + GrooveDepth = TotalThickness - BaseThickness; + + difference() { + // 1. Create the base plate + cube([TotalWidth, TotalLength, TotalThickness], center = true); + + // 2. Create the cutting grooves + translate([0, 0, TotalThickness/2 - GrooveDepth/2]) { + // Grooves for the main box walls + wall_grooves(); + + // Grooves for internal compartments + if (Nb_Boxes_U > 1 || Nb_Boxes_V > 1) { + internal_grooves(); + } + } + } +} + +// --------------------------------------------------------------------- +// Helper modules +// --------------------------------------------------------------------- + +// Module for creating the grooves for the outer walls +module wall_grooves() { + InnerWidth = TotalWidth - 2 * Height; + InnerLength = TotalLength - 2 * Height; + GrooveDepth = TotalThickness - BaseThickness; + + // Grooves parallel to Y-axis (vertical) + translate([-InnerWidth/2, 0, 0]) + cube([Slot_Width_Walls, TotalLength, GrooveDepth], center=true); + translate([InnerWidth/2, 0, 0]) + cube([Slot_Width_Walls, TotalLength, GrooveDepth], center=true); + + // Grooves parallel to X-axis (horizontal) + translate([0, -InnerLength/2, 0]) + cube([TotalWidth, Slot_Width_Walls, GrooveDepth], center=true); + translate([0, InnerLength/2, 0]) + cube([TotalWidth, Slot_Width_Walls, GrooveDepth], center=true); +} + +// Module for creating the grooves for the internal compartments +module internal_grooves() { + InnerWidth = TotalWidth - 2 * Height; + InnerLength = TotalLength - 2 * Height; + GrooveDepth = TotalThickness - BaseThickness; + + CompartmentWidth = (InnerWidth - (Nb_Boxes_U - 1) * Slot_Width_Walls) / Nb_Boxes_U; + CompartmentLength = (InnerLength - (Nb_Boxes_V - 1) * Slot_Width_Walls) / Nb_Boxes_V; + + // Internal vertical grooves + if (Nb_Boxes_U > 1) { + for (i = [1 : Nb_Boxes_U - 1]) { + x_pos = -InnerWidth/2 + i * CompartmentWidth + (i - 1/2) * Slot_Width_Walls; + translate([x_pos, 0, 0]) + cube([Slot_Width_Walls, InnerLength, GrooveDepth], center = true); + } + } + + // Internal horizontal grooves + if (Nb_Boxes_V > 1) { + for (i = [1 : Nb_Boxes_V - 1]) { + y_pos = -InnerLength/2 + i * CompartmentLength + (i - 1/2) * Slot_Width_Walls; + translate([0, y_pos, 0]) + cube([InnerWidth, Slot_Width_Walls, GrooveDepth], center = true); + } + } +} + +// --------------------------------------------------------------------- +// Modules for Folded View +// --------------------------------------------------------------------- + +// Generates the fully assembled 3D box +module folded_box() { + // Inner dimensions of the box + InnerWidth = TotalWidth - 2 * Height; + InnerLength = TotalLength - 2 * Height; + + // Material thickness for all parts + wall_thickness = TotalThickness; + + // 1. Base Plate + translate([0, 0, wall_thickness / 2]) + cube([InnerWidth, InnerLength, wall_thickness], center = true); + + // 2. Outer Walls + // South Wall (bottom) - Full Width + translate([0, -InnerLength/2, Height/2 + wall_thickness]) + rotate([90, 0, 0]) + cube([InnerWidth, Height, wall_thickness], center=true); + + // North Wall (top) - Full Width + translate([0, InnerLength/2, Height/2 + wall_thickness]) + rotate([-90, 0, 0]) + cube([InnerWidth, Height, wall_thickness], center=true); + + // West Wall (left) - Shortened to fit between North/South walls + translate([-InnerWidth/2, 0, Height/2 + wall_thickness]) + rotate([0, 90, 0]) + cube([Height, InnerLength - 2 * wall_thickness, wall_thickness], center=true); + + // East Wall (right) - Shortened to fit between North/South walls + translate([InnerWidth/2, 0, Height/2 + wall_thickness]) + rotate([0, -90, 0]) + cube([Height, InnerLength - 2 * wall_thickness, wall_thickness], center=true); + + // 3. Internal Dividers + internal_dividers_folded(); +} + +// Generates the interlocking internal dividers for the folded view +module internal_dividers_folded() { + InnerWidth = TotalWidth - 2 * Height; + InnerLength = TotalLength - 2 * Height; + divider_thickness = Slot_Width_Walls; // Use slot width as the divider material thickness + + // Calculate compartment sizes + Compartment_U = (InnerWidth + divider_thickness) / Nb_Boxes_U; + Compartment_V = (InnerLength + divider_thickness) / Nb_Boxes_V; + + // Vertical dividers (U-direction) + for (i = [1 : Nb_Boxes_U - 1]) { + x_pos = -InnerWidth/2 + i * Compartment_U - divider_thickness/2; + difference() { + // Main divider piece + translate([x_pos, 0, Height/2 + TotalThickness]) + cube([divider_thickness, InnerLength, Height], center=true); + // Slots for horizontal dividers (top-down) + for (j = [1 : Nb_Boxes_V - 1]) { + y_pos = -InnerLength/2 + j * Compartment_V - divider_thickness/2; + translate([x_pos, y_pos, Height * 0.75 + TotalThickness]) + cube([divider_thickness + 0.1, divider_thickness, Height/2], center=true); + } + } + } + + // Horizontal dividers (V-direction) + for (j = [1 : Nb_Boxes_V - 1]) { + y_pos = -InnerLength/2 + j * Compartment_V - divider_thickness/2; + difference() { + // Main divider piece + translate([0, y_pos, Height/2 + TotalThickness]) + cube([InnerWidth, divider_thickness, Height], center=true); + // Slots for vertical dividers (bottom-up) + for (i = [1 : Nb_Boxes_U - 1]) { + x_pos = -InnerWidth/2 + i * Compartment_U - divider_thickness/2; + translate([x_pos, y_pos, Height * 0.25 + TotalThickness]) + cube([divider_thickness, divider_thickness + 0.1, Height/2], center=true); + } + } + } +} + +// --------------------------------------------------------------------- +// Module for exporting all parts separately +// --------------------------------------------------------------------- +module export_layout() { + wall_thickness = TotalThickness; + InnerWidth = TotalWidth - 2 * Height; + InnerLength = TotalLength - 2 * Height; + + // 1. Base Plate + translate([0, 0, -TotalThickness/2]) + cube([InnerWidth, InnerLength, wall_thickness], center = true); + + // Spacing for laying out parts + spacing = TotalWidth; + + // 2. Outer Walls + translate([spacing, 0, 0]) + cube([InnerWidth, Height, wall_thickness], center=true); // South + translate([spacing, Height + 10, 0]) + cube([InnerWidth, Height, wall_thickness], center=true); // North + + translate([spacing + InnerWidth + 10, 0, 0]) + cube([InnerLength - 2 * wall_thickness, Height, wall_thickness], center=true); // West + translate([spacing + InnerWidth + 10, Height + 10, 0]) + cube([InnerLength - 2 * wall_thickness, Height, wall_thickness], center=true); // East + + // 3. Internal Dividers + divider_thickness = Slot_Width_Walls; + Compartment_U = (InnerWidth + divider_thickness) / Nb_Boxes_U; + Compartment_V = (InnerLength + divider_thickness) / Nb_Boxes_V; + + // Place all vertical dividers in a row + for (i = [1 : Nb_Boxes_U - 1]) { + translate([2 * spacing + (i-1)*(divider_thickness+10), 0, 0]) + internal_divider_vertical_export(InnerLength, Compartment_V); + } + + // Place all horizontal dividers in a row + for (j = [1 : Nb_Boxes_V - 1]) { + translate([2 * spacing, (j-1)*(Height+10) + Height + 10, 0]) + internal_divider_horizontal_export(InnerWidth, Compartment_U); + } +} + +// Helper modules for export layout (without difference operations) +module internal_divider_vertical_export(length, compartment_v_size) { + divider_thickness = Slot_Width_Walls; + difference() { + cube([divider_thickness, length, Height], center=true); + // Notches for horizontal dividers (bottom-up) + for (i = [1 : Nb_Boxes_V - 1]) { + y_pos = -length/2 + i * compartment_v_size - divider_thickness/2; + translate([0, y_pos, -Height/4]) + cube([divider_thickness + 0.1, divider_thickness, Height/2], center=true); + } + } +} + +module internal_divider_horizontal_export(length, compartment_u_size) { + divider_thickness = Slot_Width_Walls; + difference() { + cube([length, divider_thickness, Height], center=true); + // Notches for vertical dividers (top-down) + for (j = [1 : Nb_Boxes_U - 1]) { + x_pos = -length/2 + j * compartment_u_size - divider_thickness/2; + translate([x_pos, 0, Height/4]) + cube([divider_thickness, divider_thickness + 0.1, Height/2], center=true); + } + } +} + +// --------------------------------------------------------------------- +// Render the final object +// --------------------------------------------------------------------- +if (view_mode == "export") { + export_layout(); +} else { + if (Folded_View) { + folded_box(); + } else { + unfolded_pattern(); + } +} \ No newline at end of file diff --git a/cad/drawers/tools/box_folding_tool.step b/cad/drawers/tools/box_folding_tool.step new file mode 100644 index 0000000..c95023d --- /dev/null +++ b/cad/drawers/tools/box_folding_tool.step @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d67319eb0d9bd9ba0b4e6a3f47293b3c0a10c0012887a2783fb2c247c854b1c2 +size 153814 diff --git a/cad/drawers/tools/box_folding_tool_true.stl b/cad/drawers/tools/box_folding_tool_true.stl new file mode 100644 index 0000000..414d45f --- /dev/null +++ b/cad/drawers/tools/box_folding_tool_true.stl @@ -0,0 +1,982 @@ +solid OpenSCAD_Model + facet normal -1 0 0 + outer loop + vertex -4 -167.5 5 + vertex -4 -4 45 + vertex -4 -4 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -4 -167.5 85 + vertex -4 -4 45 + vertex -4 -167.5 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -4 -4 45 + vertex -4 -167.5 85 + vertex -4 -4 85 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -4 4 45 + vertex -4 167.5 5 + vertex -4 4 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -4 167.5 5 + vertex -4 4 45 + vertex -4 167.5 85 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex -4 167.5 85 + vertex -4 4 45 + vertex -4 4 85 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex -172.5 165 85 + vertex -167.5 4 85 + vertex -167.5 165 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -167.5 4 85 + vertex -172.5 165 85 + vertex -167.5 -4 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -172.5 -165 85 + vertex -167.5 -4 85 + vertex -172.5 165 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -167.5 -4 85 + vertex -172.5 -165 85 + vertex -167.5 -165 85 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex -167.5 4 85 + vertex -4 -4 85 + vertex -4 4 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -4 -4 85 + vertex -167.5 4 85 + vertex -167.5 -4 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 170 172.5 85 + vertex 4 167.5 85 + vertex 170 167.5 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -4 4 85 + vertex 4 4 85 + vertex 4 167.5 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 4 4 85 + vertex -4 4 85 + vertex 4 -4 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -4 4 85 + vertex 4 167.5 85 + vertex -4 167.5 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 170 172.5 85 + vertex -4 167.5 85 + vertex 4 167.5 85 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex -170 172.5 85 + vertex -4 167.5 85 + vertex 170 172.5 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -4 167.5 85 + vertex -170 172.5 85 + vertex -170 167.5 85 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex 4 4 85 + vertex 167.5 -4 85 + vertex 167.5 4 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 167.5 -4 85 + vertex 4 4 85 + vertex 4 -4 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 167.5 4 85 + vertex 172.5 165 85 + vertex 167.5 165 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 172.5 165 85 + vertex 167.5 4 85 + vertex 172.5 -165 85 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex 167.5 -4 85 + vertex 172.5 -165 85 + vertex 167.5 4 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 172.5 -165 85 + vertex 167.5 -4 85 + vertex 167.5 -165 85 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex 4 -167.5 85 + vertex 170 -172.5 85 + vertex 170 -167.5 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -4 -4 85 + vertex 4 -4 85 + vertex -4 4 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 4 -4 85 + vertex -4 -4 85 + vertex 4 -167.5 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -4 -167.5 85 + vertex 4 -167.5 85 + vertex -4 -4 85 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex -4 -167.5 85 + vertex 170 -172.5 85 + vertex 4 -167.5 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -170 -172.5 85 + vertex -4 -167.5 85 + vertex -170 -167.5 85 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -4 -167.5 85 + vertex -170 -172.5 85 + vertex 170 -172.5 85 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 4 -167.5 85 + vertex 4 -4 45 + vertex 4 -4 85 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 4 -167.5 5 + vertex 4 -4 45 + vertex 4 -167.5 85 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 4 -4 45 + vertex 4 -167.5 5 + vertex 4 -4 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 4 4 45 + vertex 4 167.5 85 + vertex 4 4 85 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 4 167.5 85 + vertex 4 4 45 + vertex 4 167.5 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 4 167.5 5 + vertex 4 4 45 + vertex 4 4 5 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 170 -165 5 + vertex 172.5 165 5 + vertex 172.5 -165 5 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 172.5 165 5 + vertex 170 -165 5 + vertex 170 165 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 167.5 -4 5 + vertex 4 -4 5 + vertex 167.5 -165 5 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex 167.5 -165 5 + vertex 170 -167.5 5 + vertex 170 -165 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 4 -167.5 5 + vertex 167.5 -165 5 + vertex 4 -4 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 167.5 -165 5 + vertex 4 -167.5 5 + vertex 170 -167.5 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 170 167.5 5 + vertex 167.5 165 5 + vertex 170 165 5 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex 4 167.5 5 + vertex 167.5 165 5 + vertex 170 167.5 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 4 4 5 + vertex 167.5 165 5 + vertex 4 167.5 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 167.5 165 5 + vertex 4 4 5 + vertex 167.5 4 5 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -170 -172.5 5 + vertex 170 -170 5 + vertex 170 -172.5 5 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 170 -170 5 + vertex -170 -172.5 5 + vertex -170 -170 5 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -170 170 5 + vertex 170 172.5 5 + vertex 170 170 5 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 170 172.5 5 + vertex -170 170 5 + vertex -170 172.5 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -4 167.5 5 + vertex -167.5 165 5 + vertex -4 4 5 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex -170 167.5 5 + vertex -167.5 165 5 + vertex -4 167.5 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -167.5 165 5 + vertex -170 167.5 5 + vertex -170 165 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -4 4 5 + vertex -167.5 165 5 + vertex -167.5 4 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -167.5 -165 5 + vertex -4 -4 5 + vertex -167.5 -4 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -4 -4 5 + vertex -167.5 -165 5 + vertex -4 -167.5 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -170 -167.5 5 + vertex -167.5 -165 5 + vertex -170 -165 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -167.5 -165 5 + vertex -170 -167.5 5 + vertex -4 -167.5 5 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -172.5 -165 5 + vertex -170 165 5 + vertex -170 -165 5 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex -170 165 5 + vertex -172.5 -165 5 + vertex -172.5 165 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -167.5 -4 85 + vertex -4 -4 45 + vertex -4 -4 85 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -167.5 -4 5 + vertex -4 -4 45 + vertex -167.5 -4 85 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex -4 -4 45 + vertex -167.5 -4 5 + vertex -4 -4 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 4 -4 45 + vertex 167.5 -4 85 + vertex 4 -4 85 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 167.5 -4 5 + vertex 4 -4 45 + vertex 4 -4 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 4 -4 45 + vertex 167.5 -4 5 + vertex 167.5 -4 85 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex -4 4 45 + vertex -167.5 4 85 + vertex -4 4 85 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -167.5 4 5 + vertex -4 4 45 + vertex -4 4 5 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -4 4 45 + vertex -167.5 4 5 + vertex -167.5 4 85 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 167.5 4 85 + vertex 4 4 45 + vertex 4 4 85 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 167.5 4 5 + vertex 4 4 45 + vertex 167.5 4 85 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 4 4 45 + vertex 167.5 4 5 + vertex 4 4 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 170 0 + vertex -170 167.5 5 + vertex -170 170 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 170 0 + vertex -170 165 5 + vertex -170 167.5 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 170 0 + vertex -170 -165 5 + vertex -170 165 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 -170 0 + vertex -170 -165 5 + vertex -170 170 0 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex -170 -165 5 + vertex -170 -170 0 + vertex -170 -167.5 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 -170 5 + vertex -170 -167.5 5 + vertex -170 -170 0 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 -167.5 5 + vertex -170 -170 5 + vertex -170 -167.5 85 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 -172.5 85 + vertex -170 -170 5 + vertex -170 -172.5 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 -170 5 + vertex -170 -172.5 85 + vertex -170 -167.5 85 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 170 5 + vertex -170 172.5 85 + vertex -170 172.5 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 167.5 85 + vertex -170 170 5 + vertex -170 167.5 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -170 170 5 + vertex -170 167.5 85 + vertex -170 172.5 85 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 170 -167.5 85 + vertex 170 -170 5 + vertex 170 -167.5 5 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 170 -172.5 85 + vertex 170 -170 5 + vertex 170 -167.5 85 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 170 -170 5 + vertex 170 -172.5 85 + vertex 170 -172.5 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 170 172.5 85 + vertex 170 170 5 + vertex 170 172.5 5 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 170 167.5 85 + vertex 170 170 5 + vertex 170 172.5 85 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 170 167.5 5 + vertex 170 170 5 + vertex 170 167.5 85 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 170 170 5 + vertex 170 167.5 5 + vertex 170 170 0 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 170 165 5 + vertex 170 170 0 + vertex 170 167.5 5 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 170 -165 5 + vertex 170 170 0 + vertex 170 165 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 170 -170 0 + vertex 170 -165 5 + vertex 170 -167.5 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 170 -170 0 + vertex 170 -167.5 5 + vertex 170 -170 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 170 -165 5 + vertex 170 -170 0 + vertex 170 170 0 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 170 170 0 + vertex -170 170 5 + vertex 170 170 5 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -170 170 5 + vertex 170 170 0 + vertex -170 170 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -170 -170 0 + vertex 170 170 0 + vertex 170 -170 0 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 170 170 0 + vertex -170 -170 0 + vertex -170 170 0 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -170 -170 0 + vertex 170 -170 5 + vertex -170 -170 5 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 170 -170 5 + vertex -170 -170 0 + vertex 170 -170 0 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -170 -172.5 5 + vertex 170 -172.5 85 + vertex -170 -172.5 85 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 170 -172.5 85 + vertex -170 -172.5 5 + vertex 170 -172.5 5 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex -4 -167.5 5 + vertex -170 -167.5 85 + vertex -4 -167.5 85 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -170 -167.5 85 + vertex -4 -167.5 5 + vertex -170 -167.5 5 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 170 -167.5 5 + vertex 4 -167.5 85 + vertex 170 -167.5 85 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 4 -167.5 85 + vertex 170 -167.5 5 + vertex 4 -167.5 5 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 170 172.5 5 + vertex -170 172.5 85 + vertex 170 172.5 85 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -170 172.5 85 + vertex 170 172.5 5 + vertex -170 172.5 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -170 167.5 5 + vertex -4 167.5 85 + vertex -170 167.5 85 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex -4 167.5 85 + vertex -170 167.5 5 + vertex -4 167.5 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 4 167.5 5 + vertex 170 167.5 85 + vertex 4 167.5 85 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 170 167.5 85 + vertex 4 167.5 5 + vertex 170 167.5 5 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex -167.5 -165 85 + vertex -167.5 -4 5 + vertex -167.5 -4 85 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex -167.5 -4 5 + vertex -167.5 -165 85 + vertex -167.5 -165 5 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex -167.5 4 85 + vertex -167.5 165 5 + vertex -167.5 165 85 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex -167.5 165 5 + vertex -167.5 4 85 + vertex -167.5 4 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -170 -165 5 + vertex -172.5 -165 85 + vertex -172.5 -165 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -172.5 -165 85 + vertex -170 -165 5 + vertex -167.5 -165 85 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex -167.5 -165 85 + vertex -170 -165 5 + vertex -167.5 -165 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -172.5 -165 5 + vertex -172.5 165 85 + vertex -172.5 165 5 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex -172.5 165 85 + vertex -172.5 -165 5 + vertex -172.5 -165 85 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -170 165 5 + vertex -167.5 165 85 + vertex -167.5 165 5 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -167.5 165 85 + vertex -170 165 5 + vertex -172.5 165 85 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -172.5 165 85 + vertex -170 165 5 + vertex -172.5 165 5 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 167.5 -165 5 + vertex 167.5 -4 85 + vertex 167.5 -4 5 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 167.5 -4 85 + vertex 167.5 -165 5 + vertex 167.5 -165 85 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 167.5 4 5 + vertex 167.5 165 85 + vertex 167.5 165 5 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 167.5 165 85 + vertex 167.5 4 5 + vertex 167.5 4 85 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 170 165 5 + vertex 172.5 165 85 + vertex 172.5 165 5 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 172.5 165 85 + vertex 170 165 5 + vertex 167.5 165 85 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 167.5 165 85 + vertex 170 165 5 + vertex 167.5 165 5 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 172.5 -165 85 + vertex 172.5 165 5 + vertex 172.5 165 85 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 172.5 165 5 + vertex 172.5 -165 85 + vertex 172.5 -165 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 170 -165 5 + vertex 167.5 -165 85 + vertex 167.5 -165 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 167.5 -165 85 + vertex 170 -165 5 + vertex 172.5 -165 85 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 172.5 -165 85 + vertex 170 -165 5 + vertex 172.5 -165 5 + endloop + endfacet +endsolid OpenSCAD_Model diff --git a/cad/drawers/tools/converter.py b/cad/drawers/tools/converter.py new file mode 100644 index 0000000..a8c2e46 --- /dev/null +++ b/cad/drawers/tools/converter.py @@ -0,0 +1,82 @@ +# converter.py +# A Python script for use with FreeCAD's command-line interface. +# Converts a mesh file (like STL) into a solid model and exports it to STEP. + +import sys +import FreeCAD +import Part +import Mesh + +# --- Argument Validation --- +# The script name is sys.argv[0], followed by FreeCAD's internal args. +# The actual script arguments start after that. We expect two: input and output files. +# FreeCAD adds its own arguments, so we find our files at the end of the list. +if len(sys.argv) < 3: + print("Converter script usage: ") + sys.exit(1) + +input_file_path = sys.argv[-2] +output_file_path = sys.argv[-1] + +print(f"Input file: {input_file_path}") +print(f"Output file: {output_file_path}") + +# --- Conversion Logic --- +try: + # 1. Load the mesh from the input STL file + mesh = Mesh.read(input_file_path) + + # 2. Split the mesh into its separate, unconnected components (shells) + components = mesh.getSeparateComponents() + print(f"Found {len(components)} separate components in the mesh.") + + # 3. Convert each component mesh into a solid shape + solids = [] + for i, component_mesh in enumerate(components): + try: + # Create a shape from the mesh component + shape = Part.Shape() + shape.makeShapeFromMesh(component_mesh.Topology, 0.1) + + # Use a more robust method to ensure the shape is a solid + # This can fix minor issues and is more reliable than direct conversion. + if not shape.isNull() and shape.Faces: + solid = Part.Solid(Part.Shell(shape.Faces)) + if solid.Volume > 0: + solids.append(solid) + else: + # If creating a solid fails, try refining it first. + refined_shape = shape.removeSplitter() + if not refined_shape.isNull() and refined_shape.Faces: + solid = Part.Solid(Part.Shell(refined_shape.Faces)) + if solid.Volume > 0: + solids.append(solid) + else: + print(f"Warning: Component {i+1} could not be converted to a solid after refining.") + else: + print(f"Warning: Component {i+1} became null after refining.") + else: + print(f"Warning: Component {i+1} could not be converted to a shape.") + + except Exception as ex: + print(f"Warning: An exception occurred while processing component {i+1}: {ex}") + + if not solids: + print("Error: No valid solids could be created from the mesh.") + sys.exit(1) + + # 4. Combine all solids into a single compound part for export + if len(solids) > 1: + result_shape = Part.Compound(solids) + else: + result_shape = solids[0] + + # 5. Export the final shape to a STEP file + result_shape.exportStep(output_file_path) + + print("STEP export completed successfully.") + sys.exit(0) + +except Exception as e: + print(f"An error occurred during FreeCAD conversion: {e}") + sys.exit(1) \ No newline at end of file diff --git a/cad/drawers/tools/export_step.sh b/cad/drawers/tools/export_step.sh new file mode 100644 index 0000000..62bb413 --- /dev/null +++ b/cad/drawers/tools/export_step.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# --- export_step.sh --- +# Converts an OpenSCAD file to a STEP file using FreeCAD. +# +# !! REQUIRES FREECAD !! +# This script depends on FreeCAD being installed and 'FreeCADCmd.exe' +# being available in your system's PATH. +# +# Usage: ./export_step.sh [output.step] +# +# Arguments: +# $1: source_file - Input .scad file (Required) +# $2: output_file - Output .step file (Optional) + +# --- Input Validation --- +if [ -z "$1" ]; then + echo "Usage: $0 [output.step]" + echo "Error: Source file not specified." + exit 1 +fi + +# --- Argument Parsing --- +SOURCE_FILE="$1" +OUTPUT_FILE="$2" + +# --- Set Default Output Filename --- +if [ -z "$OUTPUT_FILE" ]; then + OUTPUT_FILE="${SOURCE_FILE%.scad}.step" +fi + +# --- Define Temporary STL file --- +TEMP_STL_FILE="temp_conversion.stl" + +# --- Step 1: Export from OpenSCAD to STL --- +echo "Step 1/3: Exporting '$SOURCE_FILE' to STL using dedicated export layout..." +openscad \ + -o "$TEMP_STL_FILE" \ + -D "view_mode=\"export\"" \ + "$SOURCE_FILE" + +if [ $? -ne 0 ]; then + echo "Error: OpenSCAD export failed." + exit 1 +fi +echo "STL export successful." + +# --- Step 2: Convert STL to STEP using FreeCAD --- +echo "Step 2/3: Converting '$TEMP_STL_FILE' to '$OUTPUT_FILE' using FreeCAD..." +# Note: Assuming FreeCADCmd.exe for Windows. Use 'freecadcmd' on Linux. +FreeCADCmd.exe -c converter.py "$TEMP_STL_FILE" "$OUTPUT_FILE" + +if [ $? -ne 0 ]; then + echo "Error: FreeCAD conversion failed. Is FreeCAD installed and in your PATH?" + rm -f "$TEMP_STL_FILE" # Clean up temp file + exit 1 +fi +echo "STEP conversion successful." + +# --- Step 3: Clean up temporary files --- +echo "Step 3/3: Cleaning up temporary files..." +rm -f "$TEMP_STL_FILE" +echo "Done." + +# --- Completion Message --- +echo "Export complete: '$OUTPUT_FILE' created successfully." \ No newline at end of file diff --git a/cad/drawers/tools/export_stl.sh b/cad/drawers/tools/export_stl.sh new file mode 100644 index 0000000..d9d362f --- /dev/null +++ b/cad/drawers/tools/export_stl.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# --- export_stl.sh --- +# Exports an OpenSCAD file to an STL file. +# +# Usage: ./export_stl.sh [output.stl] [folded_state] +# +# Arguments: +# $1: source_file - Input .scad file (Required) +# $2: output_file - Output .stl file (Optional) +# $3: folded_state - 'true' or 'false'. (Optional, defaults to 'true' for a solid model) + +# --- Input Validation --- +if [ -z "$1" ]; then + echo "Usage: $0 [output.stl] [folded_state]" + echo "Error: Source file not specified." + exit 1 +fi + +# --- Argument Parsing --- +SOURCE_FILE="$1" +OUTPUT_FILE="" +# Default to 'true' as we usually want to export the assembled solid model +FOLDED_STATE="true" + +# Case 1: All three arguments are provided +if [ -n "$3" ]; then + OUTPUT_FILE="$2" + FOLDED_STATE="$3" +# Case 2: Only two arguments are provided +elif [ -n "$2" ]; then + # Check if the second argument is the folded state or a filename + if [[ "$2" == "true" || "$2" == "false" ]]; then + FOLDED_STATE="$2" + else + OUTPUT_FILE="$2" + fi +fi + +# --- Set Default Output Filename --- +if [ -z "$OUTPUT_FILE" ]; then + OUTPUT_FILE="${SOURCE_FILE%.scad}_${FOLDED_STATE}.stl" +fi + +# --- OpenSCAD Export Command --- +# -D: Overrides a variable in the OpenSCAD script. +echo "Exporting '$SOURCE_FILE' to '$OUTPUT_FILE' with Folded_View=$FOLDED_STATE..." +openscad \ + -o "$OUTPUT_FILE" \ + -D "Folded_View=$FOLDED_STATE" \ + "$SOURCE_FILE" + +# --- Completion Message --- +if [ $? -eq 0 ]; then + echo "Export complete: '$OUTPUT_FILE' created successfully." +else + echo "Error: OpenSCAD export failed." + exit 1 +fi \ No newline at end of file diff --git a/cad/drawers/tools/folded_view.png b/cad/drawers/tools/folded_view.png new file mode 100644 index 0000000..debff5a --- /dev/null +++ b/cad/drawers/tools/folded_view.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bdb881283628ad41815602d576f85455cabaecb11e4d460fc89b91e1c19dab39 +size 20271 diff --git a/cad/drawers/tools/reference/500-10.png b/cad/drawers/tools/reference/500-10.png new file mode 100644 index 0000000..6cebc16 --- /dev/null +++ b/cad/drawers/tools/reference/500-10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a5fb3bfcadfe45ec0e70df11156eb801cb85715b33eaeb2818d0b8037174eebc +size 62770 diff --git a/cad/drawers/tools/reference/variables.png b/cad/drawers/tools/reference/variables.png new file mode 100644 index 0000000..24b2eab --- /dev/null +++ b/cad/drawers/tools/reference/variables.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb478861536f608b6865b0f63d0c76926567ae59567794c077badca5acfcf7fd +size 12217 diff --git a/cad/drawers/tools/render.sh b/cad/drawers/tools/render.sh new file mode 100644 index 0000000..56804c0 --- /dev/null +++ b/cad/drawers/tools/render.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# --- render.sh --- +# Renders an OpenSCAD file to a PNG image. +# +# Usage: ./render.sh [output_file.png] [folded_state] +# +# Arguments: +# $1: source_file - The path to the input OpenSCAD file. (Required) +# $2: output_file - The path for the output PNG image. (Optional) +# $3: folded_state - 'true' or 'false' to control the Folded_View parameter. +# (Optional, defaults to false) + +# --- Input Validation --- +if [ -z "$1" ]; then + echo "Usage: $0 [output_file.png] [folded_state]" + echo "Error: Source file not specified." + exit 1 +fi + +# --- Argument Parsing --- +SOURCE_FILE="$1" +OUTPUT_FILE="" +FOLDED_STATE="false" # Default value + +# Case 1: All three arguments are provided +if [ -n "$3" ]; then + OUTPUT_FILE="$2" + FOLDED_STATE="$3" +# Case 2: Only two arguments are provided +elif [ -n "$2" ]; then + # Check if the second argument is the folded state or a filename + if [[ "$2" == "true" || "$2" == "false" ]]; then + FOLDED_STATE="$2" + else + OUTPUT_FILE="$2" + fi +fi + +# --- Set Default Output Filename --- +if [ -z "$OUTPUT_FILE" ]; then + # Removes the .scad extension and appends .png + OUTPUT_FILE="${SOURCE_FILE%.scad}_${FOLDED_STATE}.png" +fi + +# --- OpenSCAD Render Command --- +# --view=iso: Sets the camera to a standard isometric view. +# --imgsize: Sets the output image resolution. +# -D: Overrides a variable in the OpenSCAD script. +echo "Rendering '$SOURCE_FILE' to '$OUTPUT_FILE' with Folded_View=$FOLDED_STATE..." +openscad \ + -o "$OUTPUT_FILE" \ + --view=iso \ + --imgsize=1024,768 \ + -D "Folded_View=$FOLDED_STATE" \ + "$SOURCE_FILE" + +# --- Completion Message --- +if [ $? -eq 0 ]; then + echo "Render complete: '$OUTPUT_FILE' created successfully." +else + echo "Error: OpenSCAD rendering failed." + exit 1 +fi \ No newline at end of file