├── .gitignore ├── README.md ├── bevel.scad ├── box-pcb.scad ├── box-shell.scad ├── bsf-screw.scad ├── bsf-thread.scad ├── bspp-screw.scad ├── bspp-thread.scad ├── bsw-screw.scad ├── bsw-thread.scad ├── cable-gland.scad ├── canvas.scad ├── design ├── octree.svg └── thread-extrapolation.ods ├── electronic.scad ├── extensions.scad ├── extrude.scad ├── geometry.scad ├── glue.scad ├── hardware.scad ├── hirth-joint.scad ├── lib-screw.scad ├── lib-spiral.scad ├── mesh.scad ├── morph.scad ├── mx-knob.scad ├── mx-screw.scad ├── mx-thread.scad ├── mxf-screw.scad ├── mxf-thread.scad ├── polyhedron └── rhombicosidodecahedron.scad ├── printing.scad ├── screw-stand.scad ├── sew.scad ├── snap-joint.scad ├── test ├── images │ ├── clipart-library-penguin.jpg │ ├── clipart-library-penguin.scad │ ├── pixabay-morris-minor.png │ └── pixabay-morris-minor.scad ├── screws │ ├── test-bsf-screw-anim.scad │ ├── test-bsf-screw-tutorial.scad │ ├── test-bsf-screw-wall.scad │ ├── test-bspp-screw-wall.scad │ ├── test-bsw-screw-anim.scad │ ├── test-bsw-screw-tutorial.scad │ ├── test-bsw-screw-wall.scad │ ├── test-lib-screw-profiles.scad │ ├── test-lib-screw.scad │ ├── test-mx-screw-anim.scad │ ├── test-mx-screw-tutorial.scad │ ├── test-mx-screw-wall.scad │ ├── test-mxf-screw-anim.scad │ ├── test-mxf-screw-tutorial.scad │ ├── test-mxf-screw-wall.scad │ ├── test-unc-screw-anim.scad │ ├── test-unc-screw-tutorial.scad │ ├── test-unc-screw-wall.scad │ ├── test-unf-screw-anim.scad │ ├── test-unf-screw-tutorial.scad │ └── test-unf-screw-wall.scad ├── test-canvas-tutorial.scad ├── test-canvas.scad ├── test-extensions.scad ├── test-extrude.scad ├── test-geometry.scad ├── test-glue.scad ├── test-hardware.scad ├── test-hirth-joint.scad ├── test-mx-knob.scad ├── test-pixeled.scad ├── test-sew.scad ├── test-snap-joint-tutorial.scad ├── test-snap-joint.scad └── threads │ ├── test-bsf-thread.scad │ ├── test-bspp-thread.scad │ ├── test-bsw-thread.scad │ ├── test-mx-thread.scad │ ├── test-mxf-thread.scad │ ├── test-thread-comparison.scad │ ├── test-unc-thread.scad │ └── test-unf-thread.scad ├── things ├── 2.5-3.5-to-525-drive-adapter.scad ├── AaaD-puzzle.scad ├── box-pcb_HW-411_LM2596.scad ├── box-pcb_SM-GPN30E.scad ├── box-pcb_ZC255800+MP1584EN.scad ├── confusing-pyramid.scad ├── minecraft │ ├── creeper-lamp │ │ ├── cable_path_svg.scad │ │ ├── cable_path_svg.svg │ │ ├── creeper-body.scad │ │ ├── creeper-cable.scad │ │ ├── creeper-const.scad │ │ ├── creeper-foot.scad │ │ ├── creeper-ground.scad │ │ ├── creeper-head.scad │ │ ├── creeper-lib.scad │ │ ├── creeper-polygons.scad │ │ ├── creeper.scad │ │ ├── creeper_svg.scad │ │ └── creeper_svg.svg │ └── pickaxe │ │ ├── pickaxe.scad │ │ └── pickaxe_design.svg ├── office-tree-branch-beds.scad ├── office-tree.scad ├── pixeled │ ├── cap.scad │ ├── const.scad │ ├── layout.scad │ ├── nail.scad │ └── pixel.scad ├── snap-star.scad ├── tas-wrench-stand.scad └── tools │ └── ER-collet │ ├── ER-collet-handle.scad │ ├── ER-collet-handle.svg │ └── ER-collet-handle.svg.scad ├── unc-screw.scad ├── unc-thread.scad ├── unf-screw.scad ├── unf-thread.scad └── wrench.scad /.gitignore: -------------------------------------------------------------------------------- 1 | stl/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # agentscad 2 | My utilities for OpenSCAD 3 | 4 | # Prerequisites 5 | 6 | [Follow these instructions to use the library](https://github.com/GillesBouissac/agentscad/wiki/Prerequisites) 7 | 8 | # Canvas and Lithophanes 9 | 10 | ![Canvas panel](https://raw.githubusercontent.com/wiki/GillesBouissac/agentscad/img/panel-canvas.png) 11 | 12 |

13 | Tutorial for canvas here 14 |

15 | 16 | # Snap Joint 17 | 18 | ![Snap Joint panel](https://raw.githubusercontent.com/wiki/GillesBouissac/agentscad/img/panel-snap-joint.png) 19 | 20 |

21 | Tutorial for Snap Joint here 22 |

23 | 24 | # Screws, Bolts and Nuts shapes and passages 25 | 26 | ![MX bolt panel](https://raw.githubusercontent.com/wiki/GillesBouissac/agentscad/img/panel-screw.png) 27 | 28 |

29 | Tutorial for screws here 30 |

31 | 32 | # Threaded Screws, Bolts and Nuts (3D Printable) 33 | 34 | ![MX threaded panel](https://raw.githubusercontent.com/wiki/GillesBouissac/agentscad/img/panel-thread.png) 35 | 36 |

37 | Tutorial for threaded bolts 38 |

39 | 40 | # Hirth Joint 41 | 42 | ![Hirth Joint panel](https://raw.githubusercontent.com/wiki/GillesBouissac/agentscad/img/panel-hirth-joint.png) 43 | 44 |

45 | Tutorial for Hirth Joint here 46 |

47 | 48 | # Metric screw knobs 49 | 50 | ![Screw Knobs panel](https://raw.githubusercontent.com/wiki/GillesBouissac/agentscad/img/panel-mx-knob.png) 51 | 52 |

53 | Tutorial for screw knobs here 54 |

55 | 56 | # Beveling library 57 | 58 | ![Beveling panel](https://raw.githubusercontent.com/wiki/GillesBouissac/agentscad/img/panel-bevel.png) 59 | 60 |

61 | Tutorial for beveling here 62 |

63 | 64 | # Glue shapes library 65 | 66 | ![Glue panel](https://raw.githubusercontent.com/wiki/GillesBouissac/agentscad/img/panel-glue.png) 67 | 68 |

69 | Tutorial for glue shapes here 70 |

71 | -------------------------------------------------------------------------------- /bsf-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSF thread modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // API 18 | // 19 | // ---------------------------------------- 20 | 21 | // Renders an external thread (for bolts) 22 | module bsfThreadExternal ( screw, l=undef, f=true ) { libThreadExternal(screw,l,f); } 23 | 24 | // Renders an internal thread (for nuts) 25 | module bsfThreadInternal ( screw, l=undef, f=true, t=undef ) { libThreadInternal(screw,l,f,t); } 26 | 27 | // Nut with Hexagonal head 28 | module bsfNutHexagonalThreaded( screw, bt=true, bb=true ) { libNutHexagonalThreaded(screw,bt,bb); } 29 | 30 | // Nut with Square head 31 | module bsfNutSquareThreaded( screw, bt=true, bb=true ) { libNutSquareThreaded(screw,bt,bb); } 32 | 33 | // Bolt with Hexagonal head 34 | module bsfBoltHexagonalThreaded( screw, bt=true, bb=true ) { libBoltHexagonalThreaded(screw,bt,bb); } 35 | 36 | // Bolt with Allen head 37 | module bsfBoltAllenThreaded( screw, bt=true ) { libBoltAllenThreaded(screw,bt); } 38 | -------------------------------------------------------------------------------- /bspp-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSPPP thread modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // API 18 | // 19 | // ---------------------------------------- 20 | 21 | // Renders an external thread (for bolts) 22 | module bsppThreadExternal ( screw, l=undef, f=true ) { libThreadExternal(screw,l,f); } 23 | 24 | // Renders an internal thread (for nuts) 25 | module bsppThreadInternal ( screw, l=undef, f=true, t=undef ) { libThreadInternal(screw,l,f,t); } 26 | 27 | // Nut with Hexagonal head 28 | module bsppNutHexagonalThreaded( screw, bt=true, bb=true ) { libNutHexagonalThreaded(screw,bt,bb); } 29 | 30 | // Nut with Square head 31 | module bsppNutSquareThreaded( screw, bt=true, bb=true ) { libNutSquareThreaded(screw,bt,bb); } 32 | 33 | // Bolt with Hexagonal head 34 | module bsppBoltHexagonalThreaded( screw, bt=true, bb=true ) { libBoltHexagonalThreaded(screw,bt,bb); } 35 | 36 | // Bolt with Allen head 37 | module bsppBoltAllenThreaded( screw, bt=true ) { libBoltAllenThreaded(screw,bt); } 38 | -------------------------------------------------------------------------------- /bsw-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSW thread modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // API 18 | // 19 | // ---------------------------------------- 20 | 21 | // Renders an external thread (for bolts) 22 | module bswThreadExternal ( screw, l=undef, f=true ) { libThreadExternal(screw,l,f); } 23 | 24 | // Renders an internal thread (for nuts) 25 | module bswThreadInternal ( screw, l=undef, f=true, t=undef ) { libThreadInternal(screw,l,f,t); } 26 | 27 | // Nut with Hexagonal head 28 | module bswNutHexagonalThreaded( screw, bt=true, bb=true ) { libNutHexagonalThreaded(screw,bt,bb); } 29 | 30 | // Nut with Square head 31 | module bswNutSquareThreaded( screw, bt=true, bb=true ) { libNutSquareThreaded(screw,bt,bb); } 32 | 33 | // Bolt with Hexagonal head 34 | module bswBoltHexagonalThreaded( screw, bt=true, bb=true ) { libBoltHexagonalThreaded(screw,bt,bb); } 35 | 36 | // Bolt with Allen head 37 | module bswBoltAllenThreaded( screw, bt=true ) { libBoltAllenThreaded(screw,bt); } 38 | -------------------------------------------------------------------------------- /design/thread-extrapolation.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GillesBouissac/agentscad/d146a7e2b9cdc87eaee0589c107d81b24fb9ce29/design/thread-extrapolation.ods -------------------------------------------------------------------------------- /extrude.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Vigibot 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Mesh manipulations 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | use 15 | use 16 | use 17 | use 18 | use 19 | 20 | // 21 | // Generates a extrusion of given profile: 22 | // 23 | // @param profile the profile to extrude 24 | // @param height the z height of the generated end profile 25 | // @param caps true to generate start and end caps 26 | // @param vanishLineX vanishing line parallel to x axis 27 | // @param vanishLineY vanishing line parallel to y axis 28 | // @returns a mesh made of the initial profile and the extruded profile 29 | // 30 | module extrude(profile, height, caps=true, vanishLineX=undef, vanishLineY=undef, convexity=undef) { 31 | meshPolyhedron(extrudeProfile(profile, height, caps=caps, vanishLineX=vanishLineX, vanishLineY=vanishLineY), convexity=convexity); 32 | } 33 | 34 | // 35 | // Generates an extrusion of given profile 36 | // 37 | // @param profile the profile to extrude 38 | // @param height the z height of the generated end profile 39 | // @param caps true to generate start and end caps 40 | // @param vanishLineX vanishing line parallel to x axis 41 | // @param vanishLineY vanishing line parallel to y axis 42 | // @returns a mesh made of the initial profile and the extruded profile 43 | // 44 | function extrudeProfile(profile, height, caps=true, vanishLineX=undef, vanishLineY=undef) = 45 | sewMesh( [ profile, projectProfile(profile, height, vanishLineX=vanishLineX, vanishLineY=vanishLineY) ], caps=caps ); 46 | 47 | 48 | // 49 | // make a prism mesh from a polygon 50 | // 51 | // @param poly polygon to extrude 52 | // @param height prism height 53 | // @returns a mesh made of the initial profile and the extruded profile 54 | // 55 | module prism(poly, height=1, caps=true) { 56 | meshPolyhedron( prismMesh(poly=poly, height=height, caps=caps )); 57 | } 58 | 59 | function prismMesh(poly, height=1, caps=true) = 60 | extrudeProfile ( transform(translation([0,0,-height/2]), getMeshVertices(poly)), height=height, caps=caps ); 61 | 62 | // 63 | // make a frustum mesh from a polygon 64 | // 65 | // @param poly polygon to extrude 66 | // @param height frustum height 67 | // @param a frustum angle (0 = vertical) 68 | // @returns a mesh made of the initial profile and the extruded profile 69 | // 70 | module frustum(poly, height=1, angle=-45, caps=true) { 71 | meshPolyhedron(frustumMesh(poly=poly,height=height,angle=angle,caps=caps)); 72 | } 73 | 74 | function frustumMesh(poly, height=1, angle=-45, caps=true) = 75 | let( vertices=getMeshVertices(poly) ) 76 | let( faces=getMeshFaces(poly) ) 77 | let( n=len(vertices) ) 78 | newMesh (flatten([ 79 | for ( i=[0:n-1] ) 80 | let( v=vertices[i] ) 81 | let( i=atan2(v.y,v.x) ) 82 | let( dr=(height/2)*tan(angle) ) 83 | let( dx=dr*cos(i) ) 84 | let( dy=dr*sin(i) ) 85 | [ [v.x-dx,v.y-dy,-height/2], [v.x+dx,v.y+dy,+height/2] ] 86 | ]), 87 | [ 88 | if (caps) [ for ( i=[0:n-1] ) 2*faces[0][i] ], 89 | for( i=[0:2:2*(n-2)] ) [i,i+1,i+3,i+2], 90 | [2*n-2,2*n-1,1,0], 91 | if (caps) [ for ( i=[n-1:-1:0] ) 2*faces[0][i]+1 ] 92 | ] 93 | ); 94 | 95 | // 96 | // Scales a profile (list of points) along vectors directed to vanishing lines 97 | // 98 | // input profile is assumed to be in z=0 plane 99 | // 2 vanishing lines can be used: 100 | // - vanishLineX: [undef,y,z] position of the vanishing line parallel to x axis 101 | // Result is a scaling of the projected profile on y 102 | // - vanishLineY: [x,undef,z] position of the vanishing line parallel to y axis 103 | // Result is a scaling of the projected profile on x 104 | // 105 | // for a vanishing point: 106 | // - vanishLineX.z == vanishLineY.z 107 | // - the vanishing point coordinates are [vanishLineY.x, vanishLineX.y, vanishLineX.z] 108 | // 109 | // for a vertical scaling: 110 | // - only on x: vanishLineX == undef 111 | // - only on y: vanishLineY == undef 112 | // - no scaling: vanishLineX == vanishLineY == undef 113 | // 114 | // @param profile: list of 2D (x,y) points 115 | // @param height the projection stops at specified height 116 | // @returns the projected profile 117 | // 118 | function projectProfile(profile, height, vanishLineX=undef, vanishLineY=undef) = 119 | let ( 120 | vy = is_undef(vanishLineY) ? [0,0,0] : [ vanishLineY.x, 0, vanishLineY.z ], 121 | vx = is_undef(vanishLineX) ? [0,0,0] : [ 0, vanishLineX.y, vanishLineX.z ], 122 | 123 | try = is_undef(vanishLineX) ? identity4() : 124 | translation(+vx) * scaling([1, (vx.z - height)/vx.z, 1]) * translation(-vx), 125 | trx = is_undef(vanishLineY) ? identity4() : 126 | translation(+vy) * scaling([(vy.z - height)/vy.z, 1, 1]) * translation(-vy) 127 | ) transform(translation([0,0,height]) * try * trx, profile); 128 | -------------------------------------------------------------------------------- /geometry.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Some geometrical functions 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | use 14 | use 15 | use 16 | 17 | 18 | // ---------------------------------------- 19 | // 3D Geometry 20 | // ---------------------------------------- 21 | 22 | // Normalise a plane defined this way 23 | // [ 24 | // [px, py, pz], // mandatory: any point on the plane 25 | // [nx, ny, nz], // mandatory: vector normal to the plane 26 | // [ox, oy, oz] // optional: vector origin (default [0,0,0]) 27 | // ] 28 | function plane3(plane) = 29 | let( _p = vec3(plane[0]) ) 30 | let( _o = len(plane)>2 ? vec3(plane[2]) : [0,0,0] ) 31 | let( _n = vec3(plane[1])-_o) 32 | [ _p, _n, [0,0,0] ]; 33 | 34 | // Normalise a line defined this way 35 | // [ 36 | // [px, py, pz], // mandatory: any point on the line 37 | // [vx, vy, vz], // mandatory: vector parallel to the line 38 | // [ox, oy, oz] // optional: vector origin (default [0,0,0]) 39 | // ] 40 | function line3(line) = 41 | let( _p = vec3(line[0]) ) 42 | let( _o = len(line)>2 ? vec3(line[2]) : [0,0,0] ) 43 | let( _v = vec3(line[1])-_o) 44 | [ _p, _v, [0,0,0] ]; 45 | 46 | // ---------------------------------------- 47 | // 3D Operations 48 | // ---------------------------------------- 49 | 50 | // Intersection of three planes (Graphics Gems 1 - V.4) 51 | // - PInt={(P1.N1)(V2xV3)+(P2.V2)(V3xV1)+(P3.V3)(V1xV2)}/Det(V1,V2,V3). 52 | // Params: 53 | // - p1,p2,p3: 3 plane3 54 | // Returns: 55 | // - undef if 2 of the 3 planes are parallels 56 | // - otherwise: a 3D point 57 | function intersec_planes_3(p1,p2,p3) = 58 | let( _pl1=plane3(p1) ) 59 | let( _pl2=plane3(p2) ) 60 | let( _pl3=plane3(p3) ) 61 | let( _p1=_pl1[0], _p2=_pl2[0], _p3=_pl3[0] ) 62 | let( _n1=_pl1[1], _n2=_pl2[1], _n3=_pl3[1] ) 63 | let( d=det([_n1,_n2,_n3]) ) 64 | d==0 ? undef : ( 65 | (_p1*_n1)*cross(_n2,_n3)+ 66 | (_p2*_n2)*cross(_n3,_n1)+ 67 | (_p3*_n3)*cross(_n1,_n2) 68 | )/d; 69 | 70 | // Intersection of two planes 71 | // - computation derived from intersec_planes_3 72 | // we create the 3rd plane with: 73 | // - point [0,0,0] 74 | // - normal computed as the normal to input planes normal 75 | // this give the common points to the 3 planes 76 | // Params: 77 | // - p1,p2: 2 plane3 78 | // Returns: 79 | // - undef if 2 planes are parallels 80 | // - otherwise: a 3D line defined this way: 81 | // [ 82 | // [px, py, pz], // one point on the line 83 | // [vx, vy, vz] // direction vector of the line 84 | // ] 85 | function intersec_planes_2(p1,p2) = 86 | let( _pl1=plane3(p1) ) 87 | let( _pl2=plane3(p2) ) 88 | let( _p1=_pl1[0], _p2=_pl2[0] ) 89 | let( _n1=_pl1[1], _n2=_pl2[1] ) 90 | let( _n3=cross(_n1,_n2) ) 91 | let( _p3=intersec_planes_3(p1,p2,[[0,0,0],_n3]) ) 92 | is_undef(_p3) ? undef : [_p3,_n3,[0,0,0]]; 93 | 94 | 95 | // ---------------------------------------- 96 | // Useful tools to show basic 3D objects 97 | // ---------------------------------------- 98 | 99 | module renderPoint(point) { 100 | let( pt=vec3(point) ) 101 | translate(pt) 102 | sphere( 0.1 ); 103 | } 104 | module renderPoints(points) { 105 | for ( p=points ) renderPoint(p); 106 | } 107 | module renderPlane(plane, size=10) { 108 | let( _pl=plane3(plane) ) 109 | let( pt=_pl[0], vn=_pl[1] ) 110 | let( a=angle_vector(vn,[0,0,1]) ) 111 | let( c=cross(vn,[0,0,1]) ) 112 | { 113 | renderPoints([pt]); 114 | translate(pt) 115 | rotate(-a,c) 116 | cube( [size,size,0.01], center=true ); 117 | } 118 | } 119 | module renderPlanes(planes, size=10) { 120 | for ( p=planes ) renderPlane(p,size); 121 | } 122 | module renderLine(line, length=undef) { 123 | let( pt=vec3(line[0]), vc=vec3(line[1]) ) 124 | let( _l=is_undef(length) ? norm(vc) : length ) 125 | let( a=angle_vector(vc,[0,0,1]) ) 126 | let( c=cross(vc,[0,0,1]) ) 127 | { 128 | renderPoints([pt]); 129 | translate(pt) 130 | rotate(-a,c) 131 | cylinder( r=0.05, h=_l, center=true ); 132 | } 133 | } 134 | module renderLines(lines) { 135 | for ( l=lines ) renderLine(l); 136 | } 137 | 138 | 139 | -------------------------------------------------------------------------------- /glue.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Vigibot 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Shapes designed to glue parts avoiding supports 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // API 18 | // ---------------------------------------- 19 | module glue_circle ( d=CIRCLE_D, h=GLUE_H, g=GLUE_GRID, t=THICKNESS ) { 20 | ncircle = floor( d/(2*g) ); 21 | diff_d = d/ncircle; 22 | for ( i=[0:ncircle-1] ) 23 | difference() { 24 | cylinder( r=diff_d/2+(i*diff_d)/2+t/2, h=h, center=true ); 25 | cylinder( r=diff_d/2+(i*diff_d)/2-t/2, h=h+mfg(), center=true ); 26 | } 27 | 28 | nradius = floor( PI*d/(2*g) ); 29 | diff_a = 360/nradius; 30 | step = d / (is_undef($fn) ? 10: $fn) ; 31 | radius_profile = [ 32 | for ( x=[0:step:d/2-diff_d/2] ) 33 | [ diff_d/2+x, g/6*sin(x*180/(diff_d/2))+t/2 ], 34 | for ( x=[d/2-diff_d/2:-step:0] ) 35 | [ diff_d/2+x, g/6*sin(x*180/(diff_d/2))-t/2 ] 36 | ]; 37 | for ( i=[0:nradius] ) 38 | rotate( [0,0,i*diff_a] ) 39 | translate( [0,0,-h/2] ) 40 | linear_extrude( height=h ) 41 | polygon(radius_profile); 42 | } 43 | 44 | module glue_circle_receiver ( d=CIRCLE_D, h=GLUE_H, g=GLUE_GRID, t=THICKNESS ) { 45 | glue_circle( d, h+2*gap(), g, t+2*gap() ); 46 | } 47 | 48 | // ---------------------------------------- 49 | // Implementation 50 | // ---------------------------------------- 51 | CIRCLE_D = 50; 52 | GLUE_GRID = CIRCLE_D/6; 53 | GLUE_H = 4; 54 | THICKNESS = 3*nozzle()+0.05; 55 | 56 | // ---------------------------------------- 57 | // Showcase 58 | // ---------------------------------------- 59 | GLUE_D = 50; 60 | GLUE_T = 1.6 ; 61 | 62 | color( "gold" ) 63 | glue_circle ( GLUE_D, GLUE_T, $fn=200 ); 64 | 65 | translate( [0,0,20] ) 66 | rotate( [-30,0,0] ) 67 | difference() { 68 | translate( [0,0,5/2] ) 69 | cube( [ 70, 70, 5 ], center=true ); 70 | # glue_circle_receiver ( GLUE_D, GLUE_T, $fn=200 ); 71 | } 72 | 73 | translate( [0,0,-20] ) 74 | rotate( [+30,0,0] ) 75 | difference() { 76 | translate( [0,0,-5/2] ) 77 | cube( [ 70, 70, 5 ], center=true ); 78 | glue_circle_receiver ( GLUE_D, GLUE_T, $fn=200 ); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /mesh.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Vigibot 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Mesh manipulations 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | use 15 | use 16 | use 17 | use 18 | 19 | // ---------------------------------------- 20 | // Base API 21 | // ---------------------------------------- 22 | 23 | function classMesh() = "mesh"; 24 | 25 | // 26 | // Converts a mesh to a polyhedron module 27 | // 28 | module meshPolyhedron ( mesh, convexity=undef ) { 29 | class = assertClass(mesh,classMesh()); 30 | convexity = is_undef(convexity) ? 2 : convexity; 31 | polyhedron ( points=getMeshVertices(mesh), faces=getMeshFaces(mesh), convexity=convexity ); 32 | } 33 | 34 | // 35 | // Creates a new mesh from a list of vertices and faces 36 | // 37 | function newMesh( vertices, faces ) = [ classMesh(), vertices, faces ]; 38 | 39 | // Accessor to the list of vertices in a mesh 40 | // @return the list of 3D points 41 | function getMeshVertices( mesh ) = let(class = assertClass(mesh,classMesh())) mesh[1]; 42 | 43 | // Accessor to the list of faces in a mesh 44 | // @return the list of vertex indices in the mesh 45 | function getMeshFaces( mesh ) = let(class = assertClass(mesh,classMesh())) mesh[2]; 46 | 47 | 48 | // ---------------------------------------- 49 | // Simple Polygons 50 | // ---------------------------------------- 51 | 52 | // make a regular polygon mesh 53 | // - n: number of edges in the polygon 54 | // - r: radius of the circumscribed circle 55 | function meshRegularPolygon(n,r=1) = let() 56 | newMesh ( 57 | regularPolygon(n,r), 58 | [ [ for( i=[0:n-1] ) i ] ] 59 | ); 60 | 61 | // make a regular polygon profile 62 | // - n: number of edges in the polygon 63 | // - r: radius of the circumscribed circle 64 | function regularPolygon(n,r=1) = flatten([ 65 | for ( i=[0:n-1] ) transform(rotation([0,0,i*360/n]),[[r,0,0]]) 66 | ]); 67 | -------------------------------------------------------------------------------- /morph.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Vigibot 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Adaptation of morph function from openscad/list-comprehension-demos 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | use 14 | use 15 | use 16 | use 17 | 18 | // ---------------------------------------- 19 | // API 20 | // ---------------------------------------- 21 | 22 | // Morph two profile: Generates a succession of 'slices' profiles (=list of 3D points): 23 | // - The first one in the list is 'profile1' 24 | // - The last one in the list is 'profile2' 25 | // speed: power factor of the x^speed curve: >1 we reach profile2 faster, <1 we reach profile2 slowlier 26 | function morph ( profile1, profile2, slices=1, speed=1 ) = 27 | let ( 28 | profilelen = max(len(profile1),len(profile2)), 29 | profile1 = augment_profile(to_3d(profile1),profilelen), 30 | profile2 = augment_profile(to_3d(profile2),profilelen) 31 | )[ 32 | for(index = [0:slices-1]) 33 | interpolateProfile( profile1, profile2, index/(slices-1), speed ) 34 | ]; 35 | 36 | // Morph two profile: Generates a succession of 'slices' profiles (=list of 3D points): 37 | // The number of slices is the length of path_transforms 38 | // Each slice is transformed using the current path_transforms[] 39 | // This is a mix between morph and sweep 40 | // - The first one in the list is 'profile1' 41 | // - The last one in the list is 'profile2' 42 | function morphpath(profile1, profile2, path_transforms, speed=1) = let( 43 | slices = len(path_transforms), 44 | profilelen = max(len(profile1),len(profile2)), 45 | profile1 = augment_profile(to_3d(profile1),profilelen), 46 | profile2 = augment_profile(to_3d(profile2),profilelen) 47 | )[ 48 | for (index = [0:slices-1]) 49 | transform(path_transforms[index], interpolateProfile(profile1, profile2, index/(slices-1),speed)) 50 | ]; 51 | 52 | -------------------------------------------------------------------------------- /mx-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Metric screw thread modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // API 18 | // 19 | // ---------------------------------------- 20 | 21 | // Renders an external thread (for bolts) 22 | module mxThreadExternal ( screw, l=undef, f=true ) { libThreadExternal(screw,l,f); } 23 | 24 | // Renders an internal thread (for nuts) 25 | module mxThreadInternal ( screw, l=undef, f=true, t=undef ) { libThreadInternal(screw,l,f,t); } 26 | 27 | // Nut with Hexagonal head 28 | module mxNutHexagonalThreaded( screw, bt=true, bb=true ) { libNutHexagonalThreaded(screw,bt,bb); } 29 | 30 | // Nut with Square head 31 | module mxNutSquareThreaded( screw, bt=true, bb=true ) { libNutSquareThreaded(screw,bt,bb); } 32 | 33 | // Bolt with Hexagonal head 34 | module mxBoltHexagonalThreaded( screw, bt=true, bb=true ) { libBoltHexagonalThreaded(screw,bt,bb); } 35 | 36 | // Bolt with Allen head 37 | module mxBoltAllenThreaded( screw, bt=true ) { libBoltAllenThreaded(screw,bt); } 38 | -------------------------------------------------------------------------------- /mxf-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Metric fine screw thread modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // API 18 | // 19 | // ---------------------------------------- 20 | 21 | // Renders an external thread (for bolts) 22 | module mxfThreadExternal ( screw, l=undef, f=true ) { libThreadExternal(screw,l,f); } 23 | 24 | // Renders an internal thread (for nuts) 25 | module mxfThreadInternal ( screw, l=undef, f=true, t=undef ) { libThreadInternal(screw,l,f,t); } 26 | 27 | // Nut with Hexagonal head 28 | module mxfNutHexagonalThreaded( screw, bt=true, bb=true ) { libNutHexagonalThreaded(screw,bt,bb); } 29 | 30 | // Nut with Square head 31 | module mxfNutSquareThreaded( screw, bt=true, bb=true ) { libNutSquareThreaded(screw,bt,bb); } 32 | 33 | // Bolt with Hexagonal head 34 | module mxfBoltHexagonalThreaded( screw, bt=true, bb=true ) { libBoltHexagonalThreaded(screw,bt,bb); } 35 | 36 | // Bolt with Allen head 37 | module mxfBoltAllenThreaded( screw, bt=true ) { libBoltAllenThreaded(screw,bt); } 38 | -------------------------------------------------------------------------------- /printing.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Tools and constants for 3D printing 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | // ---------------------------------------- 14 | // 15 | // API 16 | // 17 | // ---------------------------------------- 18 | 19 | // Default values 20 | GAP = 0.2; 21 | NOZZLE = 0.4; 22 | LAYER = 0.2; 23 | OVERHANG = 70; 24 | 25 | VOLUME_MK3S = [250,210,210]; 26 | 27 | // Distance between 2 parts that must touch be not be stuck 28 | function gap(mult=1) = is_undef($gap) ? mult*GAP : mult*$gap; 29 | 30 | // The printer nozzle diameter 31 | function nozzle(mult=1) = is_undef($nozzle) ? mult*NOZZLE : mult*$nozzle; 32 | 33 | // The layer height 34 | function layer(mult=1) = is_undef($layer) ? mult*LAYER : mult*$layer; 35 | 36 | // The maximum overhang angle the printer can print from vertical 37 | function overhang() = is_undef($overhang) ? OVERHANG : $overhang; 38 | 39 | // The print volume available 40 | function printVolume() = is_undef($bed) ? getPrintVolumePrusaMk3s() : $bed; 41 | 42 | // Known volume sizes 43 | function getPrintVolumePrusaMk3s() = VOLUME_MK3S; 44 | 45 | -------------------------------------------------------------------------------- /sew.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: OpenSCAD extensions to scad language 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | use 14 | use 15 | use 16 | 17 | // 18 | // Joint n profiles (list of 2D or 3D points) with triangles 19 | // 20 | // @param profiles the list of profiles to joint 21 | // @param caps true to generate start and end caps 22 | // @param convexity convexity for visualisation before rendering 23 | // @return a polyhedron 24 | // 25 | module sew(profiles,caps=true,convexity=undef) { 26 | mesh = sewMesh(profiles,caps); 27 | meshPolyhedron(mesh,convexity=convexity); 28 | } 29 | 30 | // 31 | // Joint n profiles (list of 2D or 3D points) with triangles 32 | // 33 | // @param profiles the list of profiles to joint 34 | // @param caps true to generate start and end caps 35 | // @return a list of faces 36 | // 37 | function sewMesh(profiles,caps=true) = let( 38 | n = len(profiles), 39 | lengths = concat([ for (p=profiles) len(p)],[0]), 40 | o = [ for (i=[0:len(lengths)-1]) [columnSum(lengths,start=0,end=i-1), lengths[i]] ], 41 | vertexes = flatten(profiles), 42 | faces = flatten([ 43 | for (i=[0:n-2]) 44 | sewSelf (vertexes,o[i][0],o[i+1][0],o[i][1],o[i+1][1]) 45 | ]), 46 | scap = caps ? [range([ 0 : +1 : o[ 1][0]-1])] : [], 47 | ecap = caps ? [range([o[n][0]-1 : -1 : o[n-1][0]])] : [] 48 | ) newMesh(vertexes, caps ? concat(scap,faces,ecap) : faces) ; 49 | 50 | // 51 | // Joint 2 list of point from the same input profile (list of 2D or 3D points) with triangles 52 | // 53 | // @param points list of points to sew in a continuous list 54 | // @param s1 index of the first point of the first list 55 | // @param s2 index of the first point of the second list 56 | // @param l1 number of points in the first list 57 | // @param l2 number of points in the second list 58 | // @return a list of faces made with 3 indexes of points from input list of points 59 | // 60 | function sewSelf (points,s1,s2,l1=2,l2=2) = (l1<2 || l2<2) ? [] : _sewSelfFrom (points,s1,s2,l1,l2,0,0); 61 | function _sewSelfFrom (points,s1,s2,l1,l2,i1,i2) = let( 62 | // Candidates for next move 63 | c1 = i1 13 | use 14 | 15 | // ---------------------------------------- 16 | // Animation params: 17 | // fps: 10 18 | // steps: 100 19 | // ---------------------------------------- 20 | 21 | ALL_SCREW = [for ( idx=[0:bsfGetDataLength()-1] ) bsfData( idx ) ]; 22 | 23 | // Modulo 24 | function mod(a,m) = a - m*floor(a/m); 25 | module showcaseAnimated() { 26 | 27 | translate( [0,0,0] ) { 28 | 29 | idx=floor($t*len(ALL_SCREW)); 30 | screw = ALL_SCREW[idx]; 31 | 32 | translate( [1.5*screwGetHeadDP(screw),0,4*screwGetHeadLP(screw)] ) 33 | color( "gold" ) 34 | rotate( $vpr ) 35 | linear_extrude(1) 36 | text( screwGetName(screw), halign="center", valign="center", size=screwGetThreadD(screw) ); 37 | rotate( [180,0,0] ) 38 | translate( [0,screwGetHeadDP(screw)/1.5,0] ) { 39 | translate( [3*screwGetHeadDP(screw),0,0] ) { 40 | color( "red", 0.5 ) 41 | bsfBoltPassage( bsfClone(screw,tlp=3) ); 42 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 43 | color( "silver", 0.5 ) 44 | bsfNutPassage( screw ); 45 | } 46 | translate( [1.5*screwGetHeadDP(screw),0,0] ) { 47 | color( "red", 0.5 ) 48 | bsfBoltAllenPassage( bsfClone(screw,tlp=3) ); 49 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 50 | color( "silver", 0.5 ) 51 | bsfNutPassage( screw ); 52 | } 53 | bsfBoltAllen( screw ); 54 | translate( [0,0,+screwGetThreadL(screw)-screwGetSquareHeadL(screw)/2] ) 55 | color( "cyan", 0.5 ) 56 | bsfNutSquare( screw ); 57 | } 58 | rotate( [180,0,0] ) 59 | translate( [0,-screwGetHeadDP(screw)/1.5,0] ) { 60 | translate( [3*screwGetHeadDP(screw),0,0] ) { 61 | color( "red", 0.5 ) 62 | bsfBoltPassage( bsfClone(screw,tlp=3) ); 63 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 64 | color( "silver", 0.5 ) 65 | bsfNutPassage( screw ); 66 | } 67 | translate( [1.5*screwGetHeadDP(screw),0,0] ) { 68 | color( "red", 0.5 ) 69 | bsfBoltHexagonalPassage( bsfClone(screw,tlp=3) ); 70 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 71 | color( "silver", 0.5 ) 72 | bsfNutPassage( screw ); 73 | } 74 | bsfBoltHexagonal( screw ); 75 | translate( [0,0,+screwGetThreadL(screw)-screwGetSquareHeadL(screw)/2] ) 76 | color( "cyan", 0.5 ) 77 | bsfNutHexagonal( screw ); 78 | } 79 | } 80 | } 81 | 82 | showcaseAnimated ($fn=100); 83 | 84 | -------------------------------------------------------------------------------- /test/screws/test-bsf-screw-tutorial.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSF screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // Showcase 18 | // 19 | // ---------------------------------------- 20 | 21 | module showcaseWalls( wh1, wh2, ww=200, wp=20 ) { 22 | translate ( [0,wp/2,0] ) { 23 | color( "LightSkyBlue" ) 24 | translate ( [0,0,+(wh2+wh1)/2] ) 25 | cube( [ww,wp,wh2], center=true ); 26 | color( "DodgerBlue" ) 27 | translate ( [0,0,0] ) 28 | cube( [ww,wp,wh1], center=true ); 29 | } 30 | } 31 | 32 | module showCase() { 33 | translate ( [+100,0,0] ) { 34 | // 1: Some walls 35 | showcaseWalls (3,10,15); 36 | } 37 | 38 | translate ( [+80,0,0] ) { 39 | // 2: Bolt passage 40 | screw = BSF3_16(10,3); 41 | difference() { 42 | showcaseWalls (3,10,15); 43 | bsfBoltPassage (screw); 44 | } 45 | } 46 | 47 | translate ( [+60,0,0] ) { 48 | // 3: Allen bolt 49 | screw = BSF3_16(10,3); 50 | difference() { 51 | showcaseWalls (3,10,15); 52 | bsfBoltPassage (screw); 53 | } 54 | %bsfBoltAllen (screw); 55 | } 56 | 57 | translate ( [40,0,0] ) { 58 | // 4: Hexagonal bolt 59 | screw = BSF3_16(10,3); 60 | difference() { 61 | showcaseWalls (3,10,15); 62 | bsfBoltPassage (screw); 63 | } 64 | %bsfBoltHexagonal (screw); 65 | } 66 | 67 | translate ( [+20,0,0] ) { 68 | // 5: Tight passage allen 69 | screw = BSF3_16(10,3); 70 | difference() { 71 | showcaseWalls (3,10,15); 72 | bsfBoltAllenPassage (screw); 73 | } 74 | %bsfBoltAllen (screw); 75 | } 76 | 77 | translate ( [-0,0,0] ) { 78 | // 6: Tight passage hexagonal 79 | screw = BSF3_16(10,3); 80 | difference() { 81 | showcaseWalls (3,10,15); 82 | bsfBoltHexagonalPassage (screw); 83 | } 84 | %bsfBoltHexagonal (screw); 85 | } 86 | 87 | translate ( [-20,0,0] ) { 88 | // 7: Nut passage 89 | screw = BSF3_16(10,3); 90 | difference() { 91 | showcaseWalls (3,10,15); 92 | bsfBoltHexagonalPassage (screw); 93 | translate( [0,0,screwGetThreadL(screw)] ) 94 | bsfNutPassage (screw); 95 | } 96 | %bsfBoltHexagonal (bsfClone(screw,12)); 97 | } 98 | 99 | translate ( [-40,0,0] ) { 100 | // 8: Hexagonal nut 101 | screw = BSF3_16(10,3); 102 | difference() { 103 | showcaseWalls (3,10,15); 104 | bsfBoltHexagonalPassage (screw); 105 | translate( [0,0,screwGetThreadL(screw)] ) 106 | bsfNutPassage (screw); 107 | } 108 | %bsfBoltHexagonal (bsfClone(screw,12)); 109 | translate( [0,0,screwGetThreadL(screw)] ) 110 | %bsfNutHexagonal (screw); 111 | } 112 | 113 | translate ( [-60,0,0] ) { 114 | // 9: Square nut 115 | screw = BSF3_16(10,3); 116 | difference() { 117 | showcaseWalls (3,10,15); 118 | bsfBoltHexagonalPassage (screw); 119 | translate( [0,0,screwGetThreadL(screw)] ) 120 | bsfNutPassage (screw); 121 | } 122 | %bsfBoltHexagonal (bsfClone(screw,12)); 123 | translate( [0,0,screwGetThreadL(screw)] ) 124 | %bsfNutSquare (screw); 125 | } 126 | 127 | translate ( [-80,0,0] ) { 128 | // 10: Hexagonal nut passage 129 | screw = BSF3_16(10,3); 130 | difference() { 131 | showcaseWalls (3,10,15); 132 | bsfBoltHexagonalPassage (screw); 133 | translate( [0,0,screwGetThreadL(screw)] ) 134 | bsfNutHexagonalPassage (screw); 135 | } 136 | %bsfBoltHexagonal (bsfClone(screw,12)); 137 | translate( [0,0,screwGetThreadL(screw)] ) 138 | %bsfNutHexagonal (screw); 139 | } 140 | 141 | translate ( [-100,0,0] ) { 142 | // 11: Square nut passage 143 | screw = BSF3_16(10,3); 144 | difference() { 145 | translate ( [0,-screwGetSquareToolSize(screw)/2,0] ) 146 | showcaseWalls (3,10,15); 147 | bsfBoltPassage (screw); 148 | translate( [0,0,screwGetThreadL(screw)-4] ) 149 | bsfNutSquarePassage (screw); 150 | } 151 | %bsfBoltHexagonal (bsfClone(screw,12)); 152 | translate( [0,0,screwGetThreadL(screw)-3.8] ) 153 | %bsfNutSquare (screw); 154 | } 155 | } 156 | rotate( [0,180,0] ) 157 | showCase( $fn=100 ); 158 | -------------------------------------------------------------------------------- /test/screws/test-bsf-screw-wall.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSF screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | SCREWS_HDP = [ for ( idx=[0:bsfGetDataLength()-1] ) screwGetHeadDP ( bsfData( idx ) ) ]; 23 | ALL_SCREW = [for ( idx=[0:bsfGetDataLength()-1] ) bsfData( idx ) ]; 24 | SCREW_DISTANCE=7; 25 | 26 | WALL1_H=4; 27 | WALL2_H=160; 28 | WALL_W=100+columnSum( SCREWS_HDP, end=bsfGetDataLength()-1 )+(bsfGetDataLength()-1)*SCREW_DISTANCE; 29 | WALL_P=100; 30 | 31 | module showcaseScrewPassage ( t, tlp ) { 32 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 33 | bsfBoltPassage ( bsfClone(t, tlp=tlp) ); 34 | } 35 | } 36 | module showcaseScrew ( t ) { 37 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 38 | color( "silver", 0.7 ) { 39 | if ( screwGetIdx(t)%2 ) { 40 | bsfBoltAllen ( t ); 41 | } 42 | else { 43 | bsfBoltHexagonal ( t ); 44 | } 45 | } 46 | color( "gold" ) 47 | translate( [0,-t[8]/2-1.5,-t[9]/2] ) 48 | rotate ( [90,0,0] ) 49 | linear_extrude(1) 50 | text( t[1], halign="center", valign="center", size=2, $fn=100 ); 51 | } 52 | } 53 | 54 | module showcaseWalls( wh1, wh2, ww=WALL_W, wp=WALL_P ) { 55 | translate ( [0,wp/2,0] ) { 56 | color( "LightSkyBlue" ) 57 | translate ( [0,0,+(wh2+wh1)/2] ) 58 | cube( [ww,wp,wh2], center=true ); 59 | color( "DodgerBlue" ) 60 | translate ( [0,0,0] ) 61 | cube( [ww,wp,wh1], center=true ); 62 | } 63 | } 64 | 65 | module showcaseBigWall() { 66 | HLP = WALL1_H+10; 67 | difference() { 68 | showcaseWalls (WALL1_H,WALL2_H,WALL_W); 69 | for ( screw=ALL_SCREW ) { 70 | showcaseScrewPassage( screw, 2+screwGetThreadL(screw)*0.3 ); 71 | } 72 | } 73 | for ( screw=ALL_SCREW ) { 74 | showcaseScrew( screw ); 75 | } 76 | } 77 | 78 | dumpScrewsData(ALL_SCREW); 79 | showcaseBigWall ($fn=50); 80 | -------------------------------------------------------------------------------- /test/screws/test-bspp-screw-wall.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSPP (British Standard Pipe) screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | SCREWS_HDP = [ for ( idx=[0:bsppGetDataLength()-1] ) screwGetHeadDP ( bsppData( idx ) ) ]; 23 | ALL_SCREW = [for ( idx=[0:bsppGetDataLength()-1] ) bsppData( idx ) ]; 24 | SCREW_DISTANCE=7; 25 | 26 | WALL1_H=4; 27 | WALL2_H=160; 28 | WALL_W=100+columnSum( SCREWS_HDP, end=bsppGetDataLength()-1 )+(bsppGetDataLength()-1)*SCREW_DISTANCE; 29 | WALL_P=100; 30 | 31 | module showcaseScrewPassage ( t, tlp ) { 32 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 33 | bsppBoltPassage ( bsppClone(t, tlp=tlp) ); 34 | } 35 | } 36 | module showcaseScrew ( t ) { 37 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 38 | color( "silver", 0.7 ) { 39 | difference() { 40 | bsppBoltHexagonal ( t ); 41 | cylinder(r=bsppGetPipeD(t)/2, h=1000, center=true); 42 | } 43 | } 44 | color( "gold" ) 45 | translate( [0,-t[8]/2-1.5,-t[9]/2] ) 46 | rotate ( [90,0,0] ) 47 | linear_extrude(1) 48 | text( t[1], halign="center", valign="center", size=2, $fn=100 ); 49 | } 50 | } 51 | 52 | module showcaseWalls( wh1, wh2, ww=WALL_W, wp=WALL_P ) { 53 | translate ( [0,wp/2,0] ) { 54 | color( "LightSkyBlue" ) 55 | translate ( [0,0,+(wh2+wh1)/2] ) 56 | cube( [ww,wp,wh2], center=true ); 57 | color( "DodgerBlue" ) 58 | translate ( [0,0,0] ) 59 | cube( [ww,wp,wh1], center=true ); 60 | } 61 | } 62 | 63 | module showcaseBigWall() { 64 | HLP = WALL1_H+10; 65 | difference() { 66 | showcaseWalls (WALL1_H,WALL2_H,WALL_W); 67 | for ( screw=ALL_SCREW ) { 68 | showcaseScrewPassage( screw, 2+screwGetThreadL(screw)*0.3 ); 69 | } 70 | } 71 | for ( screw=ALL_SCREW ) { 72 | showcaseScrew( screw ); 73 | } 74 | } 75 | 76 | dumpScrewsData(ALL_SCREW); 77 | showcaseBigWall ($fn=50); 78 | -------------------------------------------------------------------------------- /test/screws/test-bsw-screw-anim.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSW screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // Animation params: 17 | // fps: 10 18 | // steps: 100 19 | // ---------------------------------------- 20 | 21 | ALL_SCREW = [for ( idx=[0:bswGetDataLength()-1] ) bswData( idx ) ]; 22 | 23 | // Modulo 24 | function mod(a,m) = a - m*floor(a/m); 25 | module showcaseAnimated() { 26 | 27 | translate( [0,0,0] ) { 28 | 29 | idx=floor($t*len(ALL_SCREW)); 30 | screw = ALL_SCREW[idx]; 31 | 32 | translate( [1.5*screwGetHeadDP(screw),0,4*screwGetHeadLP(screw)] ) 33 | color( "gold" ) 34 | rotate( $vpr ) 35 | linear_extrude(1) 36 | text( screwGetName(screw), halign="center", valign="center", size=screwGetThreadD(screw) ); 37 | rotate( [180,0,0] ) 38 | translate( [0,screwGetHeadDP(screw)/1.5,0] ) { 39 | translate( [3*screwGetHeadDP(screw),0,0] ) { 40 | color( "red", 0.5 ) 41 | bswBoltPassage( bswClone(screw,tlp=3) ); 42 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 43 | color( "silver", 0.5 ) 44 | bswNutPassage( screw ); 45 | } 46 | translate( [1.5*screwGetHeadDP(screw),0,0] ) { 47 | color( "red", 0.5 ) 48 | bswBoltAllenPassage( bswClone(screw,tlp=3) ); 49 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 50 | color( "silver", 0.5 ) 51 | bswNutPassage( screw ); 52 | } 53 | bswBoltAllen( screw ); 54 | translate( [0,0,+screwGetThreadL(screw)-screwGetSquareHeadL(screw)/2] ) 55 | color( "cyan", 0.5 ) 56 | bswNutSquare( screw ); 57 | } 58 | rotate( [180,0,0] ) 59 | translate( [0,-screwGetHeadDP(screw)/1.5,0] ) { 60 | translate( [3*screwGetHeadDP(screw),0,0] ) { 61 | color( "red", 0.5 ) 62 | bswBoltPassage( bswClone(screw,tlp=3) ); 63 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 64 | color( "silver", 0.5 ) 65 | bswNutPassage( screw ); 66 | } 67 | translate( [1.5*screwGetHeadDP(screw),0,0] ) { 68 | color( "red", 0.5 ) 69 | bswBoltHexagonalPassage( bswClone(screw,tlp=3) ); 70 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 71 | color( "silver", 0.5 ) 72 | bswNutPassage( screw ); 73 | } 74 | bswBoltHexagonal( screw ); 75 | translate( [0,0,+screwGetThreadL(screw)-screwGetSquareHeadL(screw)/2] ) 76 | color( "cyan", 0.5 ) 77 | bswNutHexagonal( screw ); 78 | } 79 | } 80 | } 81 | 82 | showcaseAnimated ($fn=100); 83 | 84 | -------------------------------------------------------------------------------- /test/screws/test-bsw-screw-tutorial.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSW screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // Showcase 18 | // 19 | // ---------------------------------------- 20 | 21 | module showcaseWalls( wh1, wh2, ww=200, wp=20 ) { 22 | translate ( [0,wp/2,0] ) { 23 | color( "LightSkyBlue" ) 24 | translate ( [0,0,+(wh2+wh1)/2] ) 25 | cube( [ww,wp,wh2], center=true ); 26 | color( "DodgerBlue" ) 27 | translate ( [0,0,0] ) 28 | cube( [ww,wp,wh1], center=true ); 29 | } 30 | } 31 | 32 | module showCase() { 33 | translate ( [+100,0,0] ) { 34 | // 1: Some walls 35 | showcaseWalls (3,10,15); 36 | } 37 | 38 | translate ( [+80,0,0] ) { 39 | // 2: Bolt passage 40 | screw = BSW5_32(10,3); 41 | difference() { 42 | showcaseWalls (3,10,15); 43 | bswBoltPassage (screw); 44 | } 45 | } 46 | 47 | translate ( [+60,0,0] ) { 48 | // 3: Allen bolt 49 | screw = BSW5_32(10,3); 50 | difference() { 51 | showcaseWalls (3,10,15); 52 | bswBoltPassage (screw); 53 | } 54 | %bswBoltAllen (screw); 55 | } 56 | 57 | translate ( [40,0,0] ) { 58 | // 4: Hexagonal bolt 59 | screw = BSW5_32(10,3); 60 | difference() { 61 | showcaseWalls (3,10,15); 62 | bswBoltPassage (screw); 63 | } 64 | %bswBoltHexagonal (screw); 65 | } 66 | 67 | translate ( [+20,0,0] ) { 68 | // 5: Tight passage allen 69 | screw = BSW5_32(10,3); 70 | difference() { 71 | showcaseWalls (3,10,15); 72 | bswBoltAllenPassage (screw); 73 | } 74 | %bswBoltAllen (screw); 75 | } 76 | 77 | translate ( [-0,0,0] ) { 78 | // 6: Tight passage hexagonal 79 | screw = BSW5_32(10,3); 80 | difference() { 81 | showcaseWalls (3,10,15); 82 | bswBoltHexagonalPassage (screw); 83 | } 84 | %bswBoltHexagonal (screw); 85 | } 86 | 87 | translate ( [-20,0,0] ) { 88 | // 7: Nut passage 89 | screw = BSW5_32(10,3); 90 | difference() { 91 | showcaseWalls (3,10,15); 92 | bswBoltHexagonalPassage (screw); 93 | translate( [0,0,screwGetThreadL(screw)] ) 94 | bswNutPassage (screw); 95 | } 96 | %bswBoltHexagonal (bswClone(screw,12)); 97 | } 98 | 99 | translate ( [-40,0,0] ) { 100 | // 8: Hexagonal nut 101 | screw = BSW5_32(10,3); 102 | difference() { 103 | showcaseWalls (3,10,15); 104 | bswBoltHexagonalPassage (screw); 105 | translate( [0,0,screwGetThreadL(screw)] ) 106 | bswNutPassage (screw); 107 | } 108 | %bswBoltHexagonal (bswClone(screw,12)); 109 | translate( [0,0,screwGetThreadL(screw)] ) 110 | %bswNutHexagonal (screw); 111 | } 112 | 113 | translate ( [-60,0,0] ) { 114 | // 9: Square nut 115 | screw = BSW5_32(10,3); 116 | difference() { 117 | showcaseWalls (3,10,15); 118 | bswBoltHexagonalPassage (screw); 119 | translate( [0,0,screwGetThreadL(screw)] ) 120 | bswNutPassage (screw); 121 | } 122 | %bswBoltHexagonal (bswClone(screw,12)); 123 | translate( [0,0,screwGetThreadL(screw)] ) 124 | %bswNutSquare (screw); 125 | } 126 | 127 | translate ( [-80,0,0] ) { 128 | // 10: Hexagonal nut passage 129 | screw = BSW5_32(10,3); 130 | difference() { 131 | showcaseWalls (3,10,15); 132 | bswBoltHexagonalPassage (screw); 133 | translate( [0,0,screwGetThreadL(screw)] ) 134 | bswNutHexagonalPassage (screw); 135 | } 136 | %bswBoltHexagonal (bswClone(screw,12)); 137 | translate( [0,0,screwGetThreadL(screw)] ) 138 | %bswNutHexagonal (screw); 139 | } 140 | 141 | translate ( [-100,0,0] ) { 142 | // 11: Square nut passage 143 | screw = BSW5_32(10,3); 144 | difference() { 145 | translate ( [0,-screwGetSquareToolSize(screw)/2,0] ) 146 | showcaseWalls (3,10,15); 147 | bswBoltPassage (screw); 148 | translate( [0,0,screwGetThreadL(screw)-4] ) 149 | bswNutSquarePassage (screw); 150 | } 151 | %bswBoltHexagonal (bswClone(screw,12)); 152 | translate( [0,0,screwGetThreadL(screw)-3.8] ) 153 | %bswNutSquare (screw); 154 | } 155 | } 156 | rotate( [0,180,0] ) 157 | showCase( $fn=100 ); 158 | -------------------------------------------------------------------------------- /test/screws/test-bsw-screw-wall.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSW screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | SCREWS_HDP = [ for ( idx=[0:bswGetDataLength()-1] ) screwGetHeadDP ( bswData( idx ) ) ]; 23 | ALL_SCREW = [for ( idx=[0:bswGetDataLength()-1] ) bswData( idx ) ]; 24 | SCREW_DISTANCE=7; 25 | 26 | WALL1_H=4; 27 | WALL2_H=160; 28 | WALL_W=100+columnSum( SCREWS_HDP, end=bswGetDataLength()-1 )+(bswGetDataLength()-1)*SCREW_DISTANCE; 29 | WALL_P=100; 30 | 31 | module showcaseScrewPassage ( t, tlp ) { 32 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 33 | bswBoltPassage ( bswClone(t, tlp=tlp) ); 34 | } 35 | } 36 | module showcaseScrew ( t ) { 37 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 38 | color( "silver", 0.7 ) { 39 | if ( screwGetIdx(t)%2 ) { 40 | bswBoltAllen ( t ); 41 | } 42 | else { 43 | bswBoltHexagonal ( t ); 44 | } 45 | } 46 | color( "gold" ) 47 | translate( [0,-t[8]/2-1.5,-t[9]/2] ) 48 | rotate ( [90,0,0] ) 49 | linear_extrude(1) 50 | text( t[1], halign="center", valign="center", size=2, $fn=100 ); 51 | } 52 | } 53 | 54 | module showcaseWalls( wh1, wh2, ww=WALL_W, wp=WALL_P ) { 55 | translate ( [0,wp/2,0] ) { 56 | color( "LightSkyBlue" ) 57 | translate ( [0,0,+(wh2+wh1)/2] ) 58 | cube( [ww,wp,wh2], center=true ); 59 | color( "DodgerBlue" ) 60 | translate ( [0,0,0] ) 61 | cube( [ww,wp,wh1], center=true ); 62 | } 63 | } 64 | 65 | module showcaseBigWall() { 66 | HLP = WALL1_H+10; 67 | difference() { 68 | showcaseWalls (WALL1_H,WALL2_H,WALL_W); 69 | for ( screw=ALL_SCREW ) { 70 | showcaseScrewPassage( screw, 2+screwGetThreadL(screw)*0.3 ); 71 | } 72 | } 73 | for ( screw=ALL_SCREW ) { 74 | showcaseScrew( screw ); 75 | } 76 | } 77 | 78 | dumpScrewsData(ALL_SCREW); 79 | showcaseBigWall ($fn=50); 80 | -------------------------------------------------------------------------------- /test/screws/test-lib-screw-profiles.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: lib-screw testing 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | PRECISION = 50; 16 | PART_TO_SHOW = 0; // [0:Profile,1:Complex structure] 17 | SHOW_HOLLOW = true; 18 | 19 | // ---------------------------------------- 20 | // 21 | // Showcase 22 | // 23 | // ---------------------------------------- 24 | function profile_m() = "M"; // Metric or UTS profile 25 | function profile_w() = "W"; // Whitworth profile 26 | 27 | module showName( d, dy=0 ) { 28 | translate( [screwGetPitch(d),dy,0.1] ) 29 | linear_extrude(1) 30 | text( screwGetName(d), halign="center", valign="center", size=1 ); 31 | } 32 | 33 | // Thread profiles visualisation 34 | module showParts( part=0 ) { 35 | if ( part==0 ) { 36 | screw_w = libScrewDataCompletion([["Profile BSW / BSF", 6,12,1]],0,prf=profile_w()); 37 | screw_m = libScrewDataCompletion([["Profile M / UNC / UNF", 6,12,1]],0,prf=profile_m()); 38 | !union() { 39 | color("white") 40 | union() { 41 | intersection() { 42 | rotate( [90,0,90] ) 43 | union() { 44 | libThreadExternal(screw_m,l=2*screwGetPitch(screw_m),f=true); 45 | libThreadInternal(screw_m,l=2*screwGetPitch(screw_m),f=true,t=1); 46 | } 47 | cube( [100,100,0.01], center=true ); 48 | } 49 | showName(screw_m,-0.6); 50 | } 51 | translate( [0,0,-2] ) 52 | color("lightblue") 53 | union() { 54 | intersection() { 55 | rotate( [90,0,90] ) 56 | union() { 57 | libThreadExternal(screw_w,l=2*screwGetPitch(screw_m),f=true); 58 | libThreadInternal(screw_w,l=2*screwGetPitch(screw_m),f=true,t=1); 59 | } 60 | cube( [100,100,0.01], center=true ); 61 | } 62 | showName(screw_w,-0.6); 63 | } 64 | } 65 | } 66 | 67 | // Complex structure 68 | if ( part==1 ) { 69 | screw_w = libScrewDataCompletion([["Profile BSW / BSF",inch2mm(1/16),inch2mm(3/8),1]],0,prf=profile_w()); 70 | screw_hole = libScrewDataCompletion([["B",2,6,1]],0,prf=profile_w()); 71 | 72 | difference() { 73 | render(convexity=20) 74 | union() { 75 | libThreadExternal( screw_w, 10, f=false ); 76 | libThreadInternal( screw_w, 10, f=false, t=1 ); 77 | } 78 | if (SHOW_HOLLOW) { 79 | #negative_parts(screw_hole); 80 | } 81 | else { 82 | negative_parts(screw_hole); 83 | } 84 | } 85 | } 86 | } 87 | 88 | module negative_parts(screw_hole) { 89 | render(convexity=20) 90 | union() { 91 | translate( [-1,0,9] ) 92 | rotate( [ 60, 20, -60 ] ) 93 | translate( [0,0,-10] ) 94 | libThreadExternal( screw_hole, 16 ); 95 | rotate( [ 0, 0, -90 ] ) 96 | translate( [5,5,3] ) 97 | cylinder( r=4.5,10 ); 98 | } 99 | } 100 | 101 | showParts(PART_TO_SHOW, $fn=PRECISION); 102 | 103 | -------------------------------------------------------------------------------- /test/screws/test-mx-screw-anim.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Metric screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | 14 | // ---------------------------------------- 15 | // Animation params: 16 | // fps: 10 17 | // steps: 100 18 | // ---------------------------------------- 19 | 20 | ALL_SCREW = [for ( idx=[0:mxGetDataLength()-1] ) mxData( idx ) ]; 21 | 22 | // Modulo 23 | function mod(a,m) = a - m*floor(a/m); 24 | module showcaseAnimated() { 25 | 26 | translate( [0,0,0] ) { 27 | 28 | idx=floor($t*len(ALL_SCREW)); 29 | screw = ALL_SCREW[idx]; 30 | 31 | translate( [1.5*mxGetHeadDP(screw),0,4*mxGetHeadLP(screw)] ) 32 | color( "gold" ) 33 | rotate( $vpr ) 34 | linear_extrude(1) 35 | text( mxGetName(screw), halign="center", valign="center", size=mxGetThreadD(screw) ); 36 | rotate( [180,0,0] ) 37 | translate( [0,mxGetHeadDP(screw)/1.5,0] ) { 38 | translate( [3*mxGetHeadDP(screw),0,0] ) { 39 | color( "red", 0.5 ) 40 | mxBoltPassage( mxClone(screw,tlp=3) ); 41 | translate( [0,0,+mxGetThreadL(screw)-mxGetHeadLP(screw)/2] ) 42 | color( "silver", 0.5 ) 43 | mxNutPassage( screw ); 44 | } 45 | translate( [1.5*mxGetHeadDP(screw),0,0] ) { 46 | color( "red", 0.5 ) 47 | mxBoltAllenPassage( mxClone(screw,tlp=3) ); 48 | translate( [0,0,+mxGetThreadL(screw)-mxGetHeadLP(screw)/2] ) 49 | color( "silver", 0.5 ) 50 | mxNutPassage( screw ); 51 | } 52 | mxBoltAllen( screw ); 53 | translate( [0,0,+mxGetThreadL(screw)-mxGetSquareHeadL(screw)/2] ) 54 | color( "cyan", 0.5 ) 55 | mxNutSquare( screw ); 56 | } 57 | rotate( [180,0,0] ) 58 | translate( [0,-mxGetHeadDP(screw)/1.5,0] ) { 59 | translate( [3*mxGetHeadDP(screw),0,0] ) { 60 | color( "red", 0.5 ) 61 | mxBoltPassage( mxClone(screw,tlp=3) ); 62 | translate( [0,0,+mxGetThreadL(screw)-mxGetHeadLP(screw)/2] ) 63 | color( "silver", 0.5 ) 64 | mxNutPassage( screw ); 65 | } 66 | translate( [1.5*mxGetHeadDP(screw),0,0] ) { 67 | color( "red", 0.5 ) 68 | mxBoltHexagonalPassage( mxClone(screw,tlp=3) ); 69 | translate( [0,0,+mxGetThreadL(screw)-mxGetHeadLP(screw)/2] ) 70 | color( "silver", 0.5 ) 71 | mxNutPassage( screw ); 72 | } 73 | mxBoltHexagonal( screw ); 74 | translate( [0,0,+mxGetThreadL(screw)-mxGetSquareHeadL(screw)/2] ) 75 | color( "cyan", 0.5 ) 76 | mxNutHexagonal( screw ); 77 | } 78 | } 79 | } 80 | 81 | showcaseAnimated ($fn=100); 82 | 83 | -------------------------------------------------------------------------------- /test/screws/test-mx-screw-tutorial.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Metric screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // Showcase 18 | // 19 | // ---------------------------------------- 20 | 21 | module showcaseWalls( wh1, wh2, ww=200, wp=20 ) { 22 | translate ( [0,wp/2,0] ) { 23 | color( "LightSkyBlue" ) 24 | translate ( [0,0,+(wh2+wh1)/2] ) 25 | cube( [ww,wp,wh2], center=true ); 26 | color( "DodgerBlue" ) 27 | translate ( [0,0,0] ) 28 | cube( [ww,wp,wh1], center=true ); 29 | } 30 | } 31 | 32 | module showCase() { 33 | translate ( [+100,0,0] ) { 34 | // 1: Some walls 35 | showcaseWalls (3,10,15); 36 | } 37 | 38 | translate ( [+80,0,0] ) { 39 | // 2: Bolt passage 40 | screw = M3(10,3); 41 | difference() { 42 | showcaseWalls (3,10,15); 43 | mxBoltPassage (screw); 44 | } 45 | } 46 | 47 | translate ( [+60,0,0] ) { 48 | // 3: Allen bolt 49 | screw = M3(10,3); 50 | difference() { 51 | showcaseWalls (3,10,15); 52 | mxBoltPassage (screw); 53 | } 54 | %mxBoltAllen (screw); 55 | } 56 | 57 | translate ( [40,0,0] ) { 58 | // 4: Hexagonal bolt 59 | screw = M3(10,3); 60 | difference() { 61 | showcaseWalls (3,10,15); 62 | mxBoltPassage (screw); 63 | } 64 | %mxBoltHexagonal (screw); 65 | } 66 | 67 | translate ( [+20,0,0] ) { 68 | // 5: Tight passage allen 69 | screw = M3(10,3); 70 | difference() { 71 | showcaseWalls (3,10,15); 72 | mxBoltAllenPassage (screw); 73 | } 74 | %mxBoltAllen (screw); 75 | } 76 | 77 | translate ( [-0,0,0] ) { 78 | // 6: Tight passage hexagonal 79 | screw = M3(10,3); 80 | difference() { 81 | showcaseWalls (3,10,15); 82 | mxBoltHexagonalPassage (screw); 83 | } 84 | %mxBoltHexagonal (screw); 85 | } 86 | 87 | translate ( [-20,0,0] ) { 88 | // 7: Nut passage 89 | screw = M3(10,3); 90 | difference() { 91 | showcaseWalls (3,10,15); 92 | mxBoltHexagonalPassage (screw); 93 | translate( [0,0,screwGetThreadL(screw)] ) 94 | mxNutPassage (screw); 95 | } 96 | %mxBoltHexagonal (mxClone(screw,12)); 97 | } 98 | 99 | translate ( [-40,0,0] ) { 100 | // 8: Hexagonal nut 101 | screw = M3(10,3); 102 | difference() { 103 | showcaseWalls (3,10,15); 104 | mxBoltHexagonalPassage (screw); 105 | translate( [0,0,screwGetThreadL(screw)] ) 106 | mxNutPassage (screw); 107 | } 108 | %mxBoltHexagonal (mxClone(screw,12)); 109 | translate( [0,0,screwGetThreadL(screw)] ) 110 | %mxNutHexagonal (screw); 111 | } 112 | 113 | translate ( [-60,0,0] ) { 114 | // 9: Square nut 115 | screw = M3(10,3); 116 | difference() { 117 | showcaseWalls (3,10,15); 118 | mxBoltHexagonalPassage (screw); 119 | translate( [0,0,screwGetThreadL(screw)] ) 120 | mxNutPassage (screw); 121 | } 122 | %mxBoltHexagonal (mxClone(screw,12)); 123 | translate( [0,0,screwGetThreadL(screw)] ) 124 | %mxNutSquare (screw); 125 | } 126 | 127 | translate ( [-80,0,0] ) { 128 | // 10: Hexagonal nut passage 129 | screw = M3(10,3); 130 | difference() { 131 | showcaseWalls (3,10,15); 132 | mxBoltHexagonalPassage (screw); 133 | translate( [0,0,screwGetThreadL(screw)] ) 134 | mxNutHexagonalPassage (screw); 135 | } 136 | %mxBoltHexagonal (mxClone(screw,12)); 137 | translate( [0,0,screwGetThreadL(screw)] ) 138 | %mxNutHexagonal (screw); 139 | } 140 | 141 | translate ( [-100,0,0] ) { 142 | // 11: Square nut passage 143 | screw = M3(10,3); 144 | difference() { 145 | translate ( [0,-screwGetSquareToolSize(screw)/2,0] ) 146 | showcaseWalls (3,10,15); 147 | mxBoltPassage (screw); 148 | translate( [0,0,screwGetThreadL(screw)-4] ) 149 | mxNutSquarePassage (screw); 150 | } 151 | %mxBoltHexagonal (mxClone(screw,12)); 152 | translate( [0,0,screwGetThreadL(screw)-3.8] ) 153 | %mxNutSquare (screw); 154 | } 155 | } 156 | rotate( [0,180,0] ) 157 | showCase( $fn=100 ); 158 | -------------------------------------------------------------------------------- /test/screws/test-mx-screw-wall.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Metric screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | SCREWS_HDP = [ for ( idx=[0:mxGetDataLength()-1] ) mxGetHeadDP ( mxData( idx ) ) ]; 23 | ALL_SCREW = [for ( idx=[0:mxGetDataLength()-1] ) mxData( idx ) ]; 24 | SCREW_DISTANCE=3; 25 | 26 | WALL1_H=4; 27 | WALL2_H=136; 28 | WALL_W=100+columnSum( SCREWS_HDP, end=mxGetDataLength()-1 )+(mxGetDataLength()-1)*SCREW_DISTANCE; 29 | WALL_P=100; 30 | 31 | module showcaseScrewPassage ( t, tlp ) { 32 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 33 | mxBoltPassage ( mxClone(t, tlp=tlp) ); 34 | } 35 | } 36 | module showcaseScrew ( t ) { 37 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 38 | color( "silver", 0.7 ) { 39 | if ( mxGetIdx(t)%2 ) { 40 | mxBoltAllen ( t ); 41 | } 42 | else { 43 | mxBoltHexagonal ( t ); 44 | } 45 | } 46 | color( "gold" ) 47 | translate( [0,-t[8]/2-1.5,-t[9]/2] ) 48 | rotate ( [90,0,0] ) 49 | linear_extrude(1) 50 | text( t[1], halign="center", valign="center", size=2, $fn=100 ); 51 | } 52 | } 53 | 54 | module showcaseWalls( wh1, wh2, ww=WALL_W, wp=WALL_P ) { 55 | translate ( [0,wp/2,0] ) { 56 | color( "LightSkyBlue" ) 57 | translate ( [0,0,+(wh2+wh1)/2] ) 58 | cube( [ww,wp,wh2], center=true ); 59 | color( "DodgerBlue" ) 60 | translate ( [0,0,0] ) 61 | cube( [ww,wp,wh1], center=true ); 62 | } 63 | } 64 | 65 | module showcaseBigWall() { 66 | HLP = WALL1_H+10; 67 | difference() { 68 | showcaseWalls (WALL1_H,WALL2_H,WALL_W); 69 | for ( screw=ALL_SCREW ) { 70 | showcaseScrewPassage( screw, 2+mxGetThreadL(screw)*0.3 ); 71 | } 72 | } 73 | for ( screw=ALL_SCREW ) { 74 | showcaseScrew( screw ); 75 | } 76 | } 77 | 78 | dumpScrewsData(ALL_SCREW); 79 | showcaseBigWall ($fn=50); 80 | -------------------------------------------------------------------------------- /test/screws/test-mxf-screw-anim.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: MXF screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // Animation params: 17 | // fps: 10 18 | // steps: 100 19 | // ---------------------------------------- 20 | 21 | ALL_SCREW = [for ( idx=[0:mxfGetDataLength()-1] ) mxfData( idx ) ]; 22 | 23 | // Modulo 24 | function mod(a,m) = a - m*floor(a/m); 25 | module showcaseAnimated() { 26 | 27 | translate( [0,0,0] ) { 28 | 29 | idx=floor($t*len(ALL_SCREW)); 30 | screw = ALL_SCREW[idx]; 31 | 32 | translate( [1.5*screwGetHeadDP(screw),0,4*screwGetHeadLP(screw)] ) 33 | color( "gold" ) 34 | rotate( $vpr ) 35 | linear_extrude(1) 36 | text( screwGetName(screw), halign="center", valign="center", size=screwGetThreadD(screw) ); 37 | rotate( [180,0,0] ) 38 | translate( [0,screwGetHeadDP(screw)/1.5,0] ) { 39 | translate( [3*screwGetHeadDP(screw),0,0] ) { 40 | color( "red", 0.5 ) 41 | mxfBoltPassage( mxfClone(screw,tlp=3) ); 42 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 43 | color( "silver", 0.5 ) 44 | mxfNutPassage( screw ); 45 | } 46 | translate( [1.5*screwGetHeadDP(screw),0,0] ) { 47 | color( "red", 0.5 ) 48 | mxfBoltAllenPassage( mxfClone(screw,tlp=3) ); 49 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 50 | color( "silver", 0.5 ) 51 | mxfNutPassage( screw ); 52 | } 53 | mxfBoltAllen( screw ); 54 | translate( [0,0,+screwGetThreadL(screw)-screwGetSquareHeadL(screw)/2] ) 55 | color( "cyan", 0.5 ) 56 | mxfNutSquare( screw ); 57 | } 58 | rotate( [180,0,0] ) 59 | translate( [0,-screwGetHeadDP(screw)/1.5,0] ) { 60 | translate( [3*screwGetHeadDP(screw),0,0] ) { 61 | color( "red", 0.5 ) 62 | mxfBoltPassage( mxfClone(screw,tlp=3) ); 63 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 64 | color( "silver", 0.5 ) 65 | mxfNutPassage( screw ); 66 | } 67 | translate( [1.5*screwGetHeadDP(screw),0,0] ) { 68 | color( "red", 0.5 ) 69 | mxfBoltHexagonalPassage( mxfClone(screw,tlp=3) ); 70 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 71 | color( "silver", 0.5 ) 72 | mxfNutPassage( screw ); 73 | } 74 | mxfBoltHexagonal( screw ); 75 | translate( [0,0,+screwGetThreadL(screw)-screwGetSquareHeadL(screw)/2] ) 76 | color( "cyan", 0.5 ) 77 | mxfNutHexagonal( screw ); 78 | } 79 | } 80 | } 81 | 82 | showcaseAnimated ($fn=100); 83 | 84 | -------------------------------------------------------------------------------- /test/screws/test-mxf-screw-tutorial.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: MXF screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // Showcase 18 | // 19 | // ---------------------------------------- 20 | 21 | module showcaseWalls( wh1, wh2, ww=200, wp=20 ) { 22 | translate ( [0,wp/2,0] ) { 23 | color( "LightSkyBlue" ) 24 | translate ( [0,0,+(wh2+wh1)/2] ) 25 | cube( [ww,wp,wh2], center=true ); 26 | color( "DodgerBlue" ) 27 | translate ( [0,0,0] ) 28 | cube( [ww,wp,wh1], center=true ); 29 | } 30 | } 31 | 32 | module showCase() { 33 | translate ( [+100,0,0] ) { 34 | // 1: Some walls 35 | showcaseWalls (3,10,15); 36 | } 37 | 38 | translate ( [+80,0,0] ) { 39 | // 2: Bolt passage 40 | screw = MF3(10,3); 41 | difference() { 42 | showcaseWalls (3,10,15); 43 | mxfBoltPassage (screw); 44 | } 45 | } 46 | 47 | translate ( [+60,0,0] ) { 48 | // 3: Allen bolt 49 | screw = MF3(10,3); 50 | difference() { 51 | showcaseWalls (3,10,15); 52 | mxfBoltPassage (screw); 53 | } 54 | %mxfBoltAllen (screw); 55 | } 56 | 57 | translate ( [40,0,0] ) { 58 | // 4: Hexagonal bolt 59 | screw = MF3(10,3); 60 | difference() { 61 | showcaseWalls (3,10,15); 62 | mxfBoltPassage (screw); 63 | } 64 | %mxfBoltHexagonal (screw); 65 | } 66 | 67 | translate ( [+20,0,0] ) { 68 | // 5: Tight passage allen 69 | screw = MF3(10,3); 70 | difference() { 71 | showcaseWalls (3,10,15); 72 | mxfBoltAllenPassage (screw); 73 | } 74 | %mxfBoltAllen (screw); 75 | } 76 | 77 | translate ( [-0,0,0] ) { 78 | // 6: Tight passage hexagonal 79 | screw = MF3(10,3); 80 | difference() { 81 | showcaseWalls (3,10,15); 82 | mxfBoltHexagonalPassage (screw); 83 | } 84 | %mxfBoltHexagonal (screw); 85 | } 86 | 87 | translate ( [-20,0,0] ) { 88 | // 7: Nut passage 89 | screw = MF3(10,3); 90 | difference() { 91 | showcaseWalls (3,10,15); 92 | mxfBoltHexagonalPassage (screw); 93 | translate( [0,0,screwGetThreadL(screw)] ) 94 | mxfNutPassage (screw); 95 | } 96 | %mxfBoltHexagonal (mxfClone(screw,12)); 97 | } 98 | 99 | translate ( [-40,0,0] ) { 100 | // 8: Hexagonal nut 101 | screw = MF3(10,3); 102 | difference() { 103 | showcaseWalls (3,10,15); 104 | mxfBoltHexagonalPassage (screw); 105 | translate( [0,0,screwGetThreadL(screw)] ) 106 | mxfNutPassage (screw); 107 | } 108 | %mxfBoltHexagonal (mxfClone(screw,12)); 109 | translate( [0,0,screwGetThreadL(screw)] ) 110 | %mxfNutHexagonal (screw); 111 | } 112 | 113 | translate ( [-60,0,0] ) { 114 | // 9: Square nut 115 | screw = MF3(10,3); 116 | difference() { 117 | showcaseWalls (3,10,15); 118 | mxfBoltHexagonalPassage (screw); 119 | translate( [0,0,screwGetThreadL(screw)] ) 120 | mxfNutPassage (screw); 121 | } 122 | %mxfBoltHexagonal (mxfClone(screw,12)); 123 | translate( [0,0,screwGetThreadL(screw)] ) 124 | %mxfNutSquare (screw); 125 | } 126 | 127 | translate ( [-80,0,0] ) { 128 | // 10: Hexagonal nut passage 129 | screw = MF3(10,3); 130 | difference() { 131 | showcaseWalls (3,10,15); 132 | mxfBoltHexagonalPassage (screw); 133 | translate( [0,0,screwGetThreadL(screw)] ) 134 | mxfNutHexagonalPassage (screw); 135 | } 136 | %mxfBoltHexagonal (mxfClone(screw,12)); 137 | translate( [0,0,screwGetThreadL(screw)] ) 138 | %mxfNutHexagonal (screw); 139 | } 140 | 141 | translate ( [-100,0,0] ) { 142 | // 11: Square nut passage 143 | screw = MF3(10,3); 144 | difference() { 145 | translate ( [0,-screwGetSquareToolSize(screw)/2,0] ) 146 | showcaseWalls (3,10,15); 147 | mxfBoltPassage (screw); 148 | translate( [0,0,screwGetThreadL(screw)-4] ) 149 | mxfNutSquarePassage (screw); 150 | } 151 | %mxfBoltHexagonal (mxfClone(screw,12)); 152 | translate( [0,0,screwGetThreadL(screw)-3.8] ) 153 | %mxfNutSquare (screw); 154 | } 155 | } 156 | rotate( [0,180,0] ) 157 | showCase( $fn=100 ); 158 | -------------------------------------------------------------------------------- /test/screws/test-mxf-screw-wall.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: MXF screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | SCREWS_HDP = [ for ( idx=[0:mxfGetDataLength()-1] ) screwGetHeadDP ( mxfData( idx ) ) ]; 23 | ALL_SCREW = [for ( idx=[0:mxfGetDataLength()-1] ) mxfData( idx ) ]; 24 | SCREW_DISTANCE=7; 25 | 26 | WALL1_H=4; 27 | WALL2_H=150; 28 | WALL_W=100+columnSum( SCREWS_HDP, end=mxfGetDataLength()-1 )+(mxfGetDataLength()-1)*SCREW_DISTANCE; 29 | WALL_P=100; 30 | 31 | module showcaseScrewPassage ( t, tlp ) { 32 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 33 | mxfBoltPassage ( mxfClone(t, tlp=tlp) ); 34 | } 35 | } 36 | module showcaseScrew ( t ) { 37 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 38 | color( "silver", 0.7 ) { 39 | if ( screwGetIdx(t)%2 ) { 40 | mxfBoltAllen ( t ); 41 | } 42 | else { 43 | mxfBoltHexagonal ( t ); 44 | } 45 | } 46 | color( "gold" ) 47 | translate( [0,-t[8]/2-1.5,-t[9]/2] ) 48 | rotate ( [90,0,0] ) 49 | linear_extrude(1) 50 | text( t[1], halign="center", valign="center", size=2, $fn=100 ); 51 | } 52 | } 53 | 54 | module showcaseWalls( wh1, wh2, ww=WALL_W, wp=WALL_P ) { 55 | translate ( [0,wp/2,0] ) { 56 | color( "LightSkyBlue" ) 57 | translate ( [0,0,+(wh2+wh1)/2] ) 58 | cube( [ww,wp,wh2], center=true ); 59 | color( "DodgerBlue" ) 60 | translate ( [0,0,0] ) 61 | cube( [ww,wp,wh1], center=true ); 62 | } 63 | } 64 | 65 | module showcaseBigWall() { 66 | HLP = WALL1_H+10; 67 | difference() { 68 | showcaseWalls (WALL1_H,WALL2_H,WALL_W); 69 | for ( screw=ALL_SCREW ) { 70 | showcaseScrewPassage( screw, 2+screwGetThreadL(screw)*0.3 ); 71 | } 72 | } 73 | for ( screw=ALL_SCREW ) { 74 | showcaseScrew( screw ); 75 | } 76 | } 77 | 78 | dumpScrewsData(ALL_SCREW); 79 | showcaseBigWall ($fn=50); 80 | -------------------------------------------------------------------------------- /test/screws/test-unc-screw-anim.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: UNC screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // Animation params: 17 | // fps: 10 18 | // steps: 100 19 | // ---------------------------------------- 20 | 21 | ALL_SCREW = [for ( idx=[0:uncGetDataLength()-1] ) uncData( idx ) ]; 22 | 23 | // Modulo 24 | function mod(a,m) = a - m*floor(a/m); 25 | module showcaseAnimated() { 26 | 27 | translate( [0,0,0] ) { 28 | 29 | idx=floor($t*len(ALL_SCREW)); 30 | screw = ALL_SCREW[idx]; 31 | 32 | translate( [1.5*screwGetHeadDP(screw),0,4*screwGetHeadLP(screw)] ) 33 | color( "gold" ) 34 | rotate( $vpr ) 35 | linear_extrude(1) 36 | text( screwGetName(screw), halign="center", valign="center", size=screwGetThreadD(screw) ); 37 | rotate( [180,0,0] ) 38 | translate( [0,screwGetHeadDP(screw)/1.5,0] ) { 39 | translate( [3*screwGetHeadDP(screw),0,0] ) { 40 | color( "red", 0.5 ) 41 | uncBoltPassage( uncClone(screw,tlp=3) ); 42 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 43 | color( "silver", 0.5 ) 44 | uncNutPassage( screw ); 45 | } 46 | translate( [1.5*screwGetHeadDP(screw),0,0] ) { 47 | color( "red", 0.5 ) 48 | uncBoltAllenPassage( uncClone(screw,tlp=3) ); 49 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 50 | color( "silver", 0.5 ) 51 | uncNutPassage( screw ); 52 | } 53 | uncBoltAllen( screw ); 54 | translate( [0,0,+screwGetThreadL(screw)-screwGetSquareHeadL(screw)/2] ) 55 | color( "cyan", 0.5 ) 56 | uncNutSquare( screw ); 57 | } 58 | rotate( [180,0,0] ) 59 | translate( [0,-screwGetHeadDP(screw)/1.5,0] ) { 60 | translate( [3*screwGetHeadDP(screw),0,0] ) { 61 | color( "red", 0.5 ) 62 | uncBoltPassage( uncClone(screw,tlp=3) ); 63 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 64 | color( "silver", 0.5 ) 65 | uncNutPassage( screw ); 66 | } 67 | translate( [1.5*screwGetHeadDP(screw),0,0] ) { 68 | color( "red", 0.5 ) 69 | uncBoltHexagonalPassage( uncClone(screw,tlp=3) ); 70 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 71 | color( "silver", 0.5 ) 72 | uncNutPassage( screw ); 73 | } 74 | uncBoltHexagonal( screw ); 75 | translate( [0,0,+screwGetThreadL(screw)-screwGetSquareHeadL(screw)/2] ) 76 | color( "cyan", 0.5 ) 77 | uncNutHexagonal( screw ); 78 | } 79 | } 80 | } 81 | 82 | showcaseAnimated ($fn=100); 83 | 84 | -------------------------------------------------------------------------------- /test/screws/test-unc-screw-tutorial.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: UNC screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // Showcase 18 | // 19 | // ---------------------------------------- 20 | 21 | module showcaseWalls( wh1, wh2, ww=200, wp=20 ) { 22 | translate ( [0,wp/2,0] ) { 23 | color( "LightSkyBlue" ) 24 | translate ( [0,0,+(wh2+wh1)/2] ) 25 | cube( [ww,wp,wh2], center=true ); 26 | color( "DodgerBlue" ) 27 | translate ( [0,0,0] ) 28 | cube( [ww,wp,wh1], center=true ); 29 | } 30 | } 31 | 32 | module showCase() { 33 | translate ( [+100,0,0] ) { 34 | // 1: Some walls 35 | showcaseWalls (3,10,15); 36 | } 37 | 38 | translate ( [+80,0,0] ) { 39 | // 2: Bolt passage 40 | screw = UNC_N5(10,3); 41 | difference() { 42 | showcaseWalls (3,10,15); 43 | uncBoltPassage (screw); 44 | } 45 | } 46 | 47 | translate ( [+60,0,0] ) { 48 | // 3: Allen bolt 49 | screw = UNC_N5(10,3); 50 | difference() { 51 | showcaseWalls (3,10,15); 52 | uncBoltPassage (screw); 53 | } 54 | %uncBoltAllen (screw); 55 | } 56 | 57 | translate ( [40,0,0] ) { 58 | // 4: Hexagonal bolt 59 | screw = UNC_N5(10,3); 60 | difference() { 61 | showcaseWalls (3,10,15); 62 | uncBoltPassage (screw); 63 | } 64 | %uncBoltHexagonal (screw); 65 | } 66 | 67 | translate ( [+20,0,0] ) { 68 | // 5: Tight passage allen 69 | screw = UNC_N5(10,3); 70 | difference() { 71 | showcaseWalls (3,10,15); 72 | uncBoltAllenPassage (screw); 73 | } 74 | %uncBoltAllen (screw); 75 | } 76 | 77 | translate ( [-0,0,0] ) { 78 | // 6: Tight passage hexagonal 79 | screw = UNC_N5(10,3); 80 | difference() { 81 | showcaseWalls (3,10,15); 82 | uncBoltHexagonalPassage (screw); 83 | } 84 | %uncBoltHexagonal (screw); 85 | } 86 | 87 | translate ( [-20,0,0] ) { 88 | // 7: Nut passage 89 | screw = UNC_N5(10,3); 90 | difference() { 91 | showcaseWalls (3,10,15); 92 | uncBoltHexagonalPassage (screw); 93 | translate( [0,0,screwGetThreadL(screw)] ) 94 | uncNutPassage (screw); 95 | } 96 | %uncBoltHexagonal (uncClone(screw,12)); 97 | } 98 | 99 | translate ( [-40,0,0] ) { 100 | // 8: Hexagonal nut 101 | screw = UNC_N5(10,3); 102 | difference() { 103 | showcaseWalls (3,10,15); 104 | uncBoltHexagonalPassage (screw); 105 | translate( [0,0,screwGetThreadL(screw)] ) 106 | uncNutPassage (screw); 107 | } 108 | %uncBoltHexagonal (uncClone(screw,12)); 109 | translate( [0,0,screwGetThreadL(screw)] ) 110 | %uncNutHexagonal (screw); 111 | } 112 | 113 | translate ( [-60,0,0] ) { 114 | // 9: Square nut 115 | screw = UNC_N5(10,3); 116 | difference() { 117 | showcaseWalls (3,10,15); 118 | uncBoltHexagonalPassage (screw); 119 | translate( [0,0,screwGetThreadL(screw)] ) 120 | uncNutPassage (screw); 121 | } 122 | %uncBoltHexagonal (uncClone(screw,12)); 123 | translate( [0,0,screwGetThreadL(screw)] ) 124 | %uncNutSquare (screw); 125 | } 126 | 127 | translate ( [-80,0,0] ) { 128 | // 10: Hexagonal nut passage 129 | screw = UNC_N5(10,3); 130 | difference() { 131 | showcaseWalls (3,10,15); 132 | uncBoltHexagonalPassage (screw); 133 | translate( [0,0,screwGetThreadL(screw)] ) 134 | uncNutHexagonalPassage (screw); 135 | } 136 | %uncBoltHexagonal (uncClone(screw,12)); 137 | translate( [0,0,screwGetThreadL(screw)] ) 138 | %uncNutHexagonal (screw); 139 | } 140 | 141 | translate ( [-100,0,0] ) { 142 | // 11: Square nut passage 143 | screw = UNC_N5(10,3); 144 | difference() { 145 | translate ( [0,-screwGetSquareToolSize(screw)/2,0] ) 146 | showcaseWalls (3,10,15); 147 | uncBoltPassage (screw); 148 | translate( [0,0,screwGetThreadL(screw)-4] ) 149 | uncNutSquarePassage (screw); 150 | } 151 | %uncBoltHexagonal (uncClone(screw,12)); 152 | translate( [0,0,screwGetThreadL(screw)-3.8] ) 153 | %uncNutSquare (screw); 154 | } 155 | } 156 | rotate( [0,180,0] ) 157 | showCase( $fn=100 ); 158 | -------------------------------------------------------------------------------- /test/screws/test-unc-screw-wall.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: UNC screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | SCREWS_HDP = [ for ( idx=[0:uncGetDataLength()-1] ) screwGetHeadDP ( uncData( idx ) ) ]; 23 | ALL_SCREW = [for ( idx=[0:uncGetDataLength()-1] ) uncData( idx ) ]; 24 | SCREW_DISTANCE=7; 25 | 26 | WALL1_H=4; 27 | WALL2_H=160; 28 | WALL_W=100+columnSum( SCREWS_HDP, end=uncGetDataLength()-1 )+(uncGetDataLength()-1)*SCREW_DISTANCE; 29 | WALL_P=100; 30 | 31 | module showcaseScrewPassage ( t, tlp ) { 32 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 33 | uncBoltPassage ( uncClone(t, tlp=tlp) ); 34 | } 35 | } 36 | module showcaseScrew ( t ) { 37 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 38 | color( "silver", 0.7 ) { 39 | if ( screwGetIdx(t)%2 ) { 40 | uncBoltAllen ( t ); 41 | } 42 | else { 43 | uncBoltHexagonal ( t ); 44 | } 45 | } 46 | color( "gold" ) 47 | translate( [0,-t[8]/2-1.5,-t[9]/2] ) 48 | rotate ( [90,0,0] ) 49 | linear_extrude(1) 50 | text( t[1], halign="center", valign="center", size=2, $fn=100 ); 51 | } 52 | } 53 | 54 | module showcaseWalls( wh1, wh2, ww=WALL_W, wp=WALL_P ) { 55 | translate ( [0,wp/2,0] ) { 56 | color( "LightSkyBlue" ) 57 | translate ( [0,0,+(wh2+wh1)/2] ) 58 | cube( [ww,wp,wh2], center=true ); 59 | color( "DodgerBlue" ) 60 | translate ( [0,0,0] ) 61 | cube( [ww,wp,wh1], center=true ); 62 | } 63 | } 64 | 65 | module showcaseBigWall() { 66 | HLP = WALL1_H+10; 67 | difference() { 68 | showcaseWalls (WALL1_H,WALL2_H,WALL_W); 69 | for ( screw=ALL_SCREW ) { 70 | showcaseScrewPassage( screw, 2+screwGetThreadL(screw)*0.3 ); 71 | } 72 | } 73 | for ( screw=ALL_SCREW ) { 74 | showcaseScrew( screw ); 75 | } 76 | } 77 | 78 | dumpScrewsData(ALL_SCREW); 79 | showcaseBigWall ($fn=50); 80 | -------------------------------------------------------------------------------- /test/screws/test-unf-screw-anim.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: UNF screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // Animation params: 17 | // fps: 10 18 | // steps: 100 19 | // ---------------------------------------- 20 | 21 | ALL_SCREW = [for ( idx=[0:unfGetDataLength()-1] ) unfData( idx ) ]; 22 | 23 | // Modulo 24 | function mod(a,m) = a - m*floor(a/m); 25 | module showcaseAnimated() { 26 | 27 | translate( [0,0,0] ) { 28 | 29 | idx=floor($t*len(ALL_SCREW)); 30 | screw = ALL_SCREW[idx]; 31 | 32 | translate( [1.5*screwGetHeadDP(screw),0,4*screwGetHeadLP(screw)] ) 33 | color( "gold" ) 34 | rotate( $vpr ) 35 | linear_extrude(1) 36 | text( screwGetName(screw), halign="center", valign="center", size=screwGetThreadD(screw) ); 37 | rotate( [180,0,0] ) 38 | translate( [0,screwGetHeadDP(screw)/1.5,0] ) { 39 | translate( [3*screwGetHeadDP(screw),0,0] ) { 40 | color( "red", 0.5 ) 41 | unfBoltPassage( unfClone(screw,tlp=3) ); 42 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 43 | color( "silver", 0.5 ) 44 | unfNutPassage( screw ); 45 | } 46 | translate( [1.5*screwGetHeadDP(screw),0,0] ) { 47 | color( "red", 0.5 ) 48 | unfBoltAllenPassage( unfClone(screw,tlp=3) ); 49 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 50 | color( "silver", 0.5 ) 51 | unfNutPassage( screw ); 52 | } 53 | unfBoltAllen( screw ); 54 | translate( [0,0,+screwGetThreadL(screw)-screwGetSquareHeadL(screw)/2] ) 55 | color( "cyan", 0.5 ) 56 | unfNutSquare( screw ); 57 | } 58 | rotate( [180,0,0] ) 59 | translate( [0,-screwGetHeadDP(screw)/1.5,0] ) { 60 | translate( [3*screwGetHeadDP(screw),0,0] ) { 61 | color( "red", 0.5 ) 62 | unfBoltPassage( unfClone(screw,tlp=3) ); 63 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 64 | color( "silver", 0.5 ) 65 | unfNutPassage( screw ); 66 | } 67 | translate( [1.5*screwGetHeadDP(screw),0,0] ) { 68 | color( "red", 0.5 ) 69 | unfBoltHexagonalPassage( unfClone(screw,tlp=3) ); 70 | translate( [0,0,+screwGetThreadL(screw)-screwGetHeadLP(screw)/2] ) 71 | color( "silver", 0.5 ) 72 | unfNutPassage( screw ); 73 | } 74 | unfBoltHexagonal( screw ); 75 | translate( [0,0,+screwGetThreadL(screw)-screwGetSquareHeadL(screw)/2] ) 76 | color( "cyan", 0.5 ) 77 | unfNutHexagonal( screw ); 78 | } 79 | } 80 | } 81 | 82 | showcaseAnimated ($fn=100); 83 | 84 | -------------------------------------------------------------------------------- /test/screws/test-unf-screw-tutorial.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: UNF screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // Showcase 18 | // 19 | // ---------------------------------------- 20 | 21 | module showcaseWalls( wh1, wh2, ww=200, wp=20 ) { 22 | translate ( [0,wp/2,0] ) { 23 | color( "LightSkyBlue" ) 24 | translate ( [0,0,+(wh2+wh1)/2] ) 25 | cube( [ww,wp,wh2], center=true ); 26 | color( "DodgerBlue" ) 27 | translate ( [0,0,0] ) 28 | cube( [ww,wp,wh1], center=true ); 29 | } 30 | } 31 | 32 | module showCase() { 33 | translate ( [+100,0,0] ) { 34 | // 1: Some walls 35 | showcaseWalls (3,10,15); 36 | } 37 | 38 | translate ( [+80,0,0] ) { 39 | // 2: Bolt passage 40 | screw = UNF_N5(10,3); 41 | difference() { 42 | showcaseWalls (3,10,15); 43 | unfBoltPassage (screw); 44 | } 45 | } 46 | 47 | translate ( [+60,0,0] ) { 48 | // 3: Allen bolt 49 | screw = UNF_N5(10,3); 50 | difference() { 51 | showcaseWalls (3,10,15); 52 | unfBoltPassage (screw); 53 | } 54 | %unfBoltAllen (screw); 55 | } 56 | 57 | translate ( [40,0,0] ) { 58 | // 4: Hexagonal bolt 59 | screw = UNF_N5(10,3); 60 | difference() { 61 | showcaseWalls (3,10,15); 62 | unfBoltPassage (screw); 63 | } 64 | %unfBoltHexagonal (screw); 65 | } 66 | 67 | translate ( [+20,0,0] ) { 68 | // 5: Tight passage allen 69 | screw = UNF_N5(10,3); 70 | difference() { 71 | showcaseWalls (3,10,15); 72 | unfBoltAllenPassage (screw); 73 | } 74 | %unfBoltAllen (screw); 75 | } 76 | 77 | translate ( [-0,0,0] ) { 78 | // 6: Tight passage hexagonal 79 | screw = UNF_N5(10,3); 80 | difference() { 81 | showcaseWalls (3,10,15); 82 | unfBoltHexagonalPassage (screw); 83 | } 84 | %unfBoltHexagonal (screw); 85 | } 86 | 87 | translate ( [-20,0,0] ) { 88 | // 7: Nut passage 89 | screw = UNF_N5(10,3); 90 | difference() { 91 | showcaseWalls (3,10,15); 92 | unfBoltHexagonalPassage (screw); 93 | translate( [0,0,screwGetThreadL(screw)] ) 94 | unfNutPassage (screw); 95 | } 96 | %unfBoltHexagonal (unfClone(screw,12)); 97 | } 98 | 99 | translate ( [-40,0,0] ) { 100 | // 8: Hexagonal nut 101 | screw = UNF_N5(10,3); 102 | difference() { 103 | showcaseWalls (3,10,15); 104 | unfBoltHexagonalPassage (screw); 105 | translate( [0,0,screwGetThreadL(screw)] ) 106 | unfNutPassage (screw); 107 | } 108 | %unfBoltHexagonal (unfClone(screw,12)); 109 | translate( [0,0,screwGetThreadL(screw)] ) 110 | %unfNutHexagonal (screw); 111 | } 112 | 113 | translate ( [-60,0,0] ) { 114 | // 9: Square nut 115 | screw = UNF_N5(10,3); 116 | difference() { 117 | showcaseWalls (3,10,15); 118 | unfBoltHexagonalPassage (screw); 119 | translate( [0,0,screwGetThreadL(screw)] ) 120 | unfNutPassage (screw); 121 | } 122 | %unfBoltHexagonal (unfClone(screw,12)); 123 | translate( [0,0,screwGetThreadL(screw)] ) 124 | %unfNutSquare (screw); 125 | } 126 | 127 | translate ( [-80,0,0] ) { 128 | // 10: Hexagonal nut passage 129 | screw = UNF_N5(10,3); 130 | difference() { 131 | showcaseWalls (3,10,15); 132 | unfBoltHexagonalPassage (screw); 133 | translate( [0,0,screwGetThreadL(screw)] ) 134 | unfNutHexagonalPassage (screw); 135 | } 136 | %unfBoltHexagonal (unfClone(screw,12)); 137 | translate( [0,0,screwGetThreadL(screw)] ) 138 | %unfNutHexagonal (screw); 139 | } 140 | 141 | translate ( [-100,0,0] ) { 142 | // 11: Square nut passage 143 | screw = UNF_N5(10,3); 144 | difference() { 145 | translate ( [0,-screwGetSquareToolSize(screw)/2,0] ) 146 | showcaseWalls (3,10,15); 147 | unfBoltPassage (screw); 148 | translate( [0,0,screwGetThreadL(screw)-4] ) 149 | unfNutSquarePassage (screw); 150 | } 151 | %unfBoltHexagonal (unfClone(screw,12)); 152 | translate( [0,0,screwGetThreadL(screw)-3.8] ) 153 | %unfNutSquare (screw); 154 | } 155 | } 156 | rotate( [0,180,0] ) 157 | showCase( $fn=100 ); 158 | -------------------------------------------------------------------------------- /test/screws/test-unf-screw-wall.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: UNF screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | SCREWS_HDP = [ for ( idx=[0:unfGetDataLength()-1] ) screwGetHeadDP ( unfData( idx ) ) ]; 23 | ALL_SCREW = [for ( idx=[0:unfGetDataLength()-1] ) unfData( idx ) ]; 24 | SCREW_DISTANCE=7; 25 | 26 | WALL1_H=4; 27 | WALL2_H=70; 28 | WALL_W=100+columnSum( SCREWS_HDP, end=unfGetDataLength()-1 )+(unfGetDataLength()-1)*SCREW_DISTANCE; 29 | WALL_P=100; 30 | 31 | module showcaseScrewPassage ( t, tlp ) { 32 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 33 | unfBoltPassage ( unfClone(t, tlp=tlp) ); 34 | } 35 | } 36 | module showcaseScrew ( t ) { 37 | translate( [ t[0]*SCREW_DISTANCE + columnSum( SCREWS_HDP, end=t[0] )-WALL_W/2,0,0] ) { 38 | color( "silver", 0.7 ) { 39 | if ( screwGetIdx(t)%2 ) { 40 | unfBoltAllen ( t ); 41 | } 42 | else { 43 | unfBoltHexagonal ( t ); 44 | } 45 | } 46 | color( "gold" ) 47 | translate( [0,-t[8]/2-1.5,-t[9]/2] ) 48 | rotate ( [90,0,0] ) 49 | linear_extrude(1) 50 | text( t[1], halign="center", valign="center", size=2, $fn=100 ); 51 | } 52 | } 53 | 54 | module showcaseWalls( wh1, wh2, ww=WALL_W, wp=WALL_P ) { 55 | translate ( [0,wp/2,0] ) { 56 | color( "LightSkyBlue" ) 57 | translate ( [0,0,+(wh2+wh1)/2] ) 58 | cube( [ww,wp,wh2], center=true ); 59 | color( "DodgerBlue" ) 60 | translate ( [0,0,0] ) 61 | cube( [ww,wp,wh1], center=true ); 62 | } 63 | } 64 | 65 | module showcaseBigWall() { 66 | HLP = WALL1_H+10; 67 | difference() { 68 | showcaseWalls (WALL1_H,WALL2_H,WALL_W); 69 | for ( screw=ALL_SCREW ) { 70 | showcaseScrewPassage( screw, 2+screwGetThreadL(screw)*0.3 ); 71 | } 72 | } 73 | for ( screw=ALL_SCREW ) { 74 | showcaseScrew( screw ); 75 | } 76 | } 77 | 78 | dumpScrewsData(ALL_SCREW); 79 | showcaseBigWall ($fn=50); 80 | -------------------------------------------------------------------------------- /test/test-canvas.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Vigibot 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Test canvas manipulations and rendering 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | use 15 | use 16 | use 17 | 18 | // rendering precision tuning 19 | $fn=80; 20 | 21 | // 22 | // Images sources: 23 | // Penguin: http://clipart-library.com/clipart/709738.htm 24 | // Morris Minor: https://pixabay.com/fr/photos/morris-minor-limousine-oldtimer-4754082/ 25 | // 26 | use 27 | use 28 | 29 | penguin = levels_clipartlibrarypenguin(); 30 | module showPlane(preserve=true, moved=false, resized=false) { 31 | canvas = newCanvas( [200,100], [2*$fn,$fn] ); 32 | image = drawImage ( penguin, canvas, 33 | size=resized?[100,50]:undef, start=moved?[90,40]:undef, preserve=preserve ); 34 | mesh = canvas2mesh( image, skin=false, minlayer=2, thickness=5 ); 35 | projected = getMeshVertices(mesh); 36 | lithophane = newMesh(projected,getMeshFaces(mesh)); 37 | render() 38 | meshPolyhedron ( lithophane ); 39 | } 40 | module showSphereFull( skin=true, positive=true, resized=false ) { 41 | // If image size is reduced we need more pixels in the canvas 42 | canvas = newCanvas( [2,1], resized?[4*$fn,2*$fn]:[2*$fn,$fn] ); 43 | image = drawImage ( penguin, canvas, size=resized?[undef,0.5]:undef ); 44 | mesh = canvas2mesh( image, skin=skin, positive=positive, thickness=10 ); 45 | projected = projectSphereCylindrical( getMeshVertices(mesh), 100 ); 46 | lithophane = newMesh(projected,getMeshFaces(mesh)); 47 | render() 48 | meshPolyhedron ( lithophane ); 49 | } 50 | module showSphereCrop(preserve=true) { 51 | levels = imageCrop(penguin, [40,40], [43,66]); 52 | canvas = newCanvas( [2,1], [2*$fn,$fn] ); 53 | image = drawImage ( levels, canvas, size=[1,0.5], preserve=preserve ); 54 | mesh = canvas2mesh( image, skin=true, thickness=10 ); 55 | projected = projectSphereCylindrical( getMeshVertices(mesh), 100 ); 56 | lithophane = newMesh(projected,getMeshFaces(mesh)); 57 | render() 58 | meshPolyhedron ( lithophane ); 59 | } 60 | module showCylinder() { 61 | canvas = newCanvas( [2,1], [2*$fn,$fn] ); 62 | image = drawImage ( penguin, canvas ); 63 | mesh = canvas2mesh( image, skin=false, thickness=10 ); 64 | projected = projectCylinder( getMeshVertices(mesh), 100, 314 ); 65 | lithophane = newMesh(projected,getMeshFaces(mesh)); 66 | render() 67 | meshPolyhedron ( lithophane ); 68 | } 69 | module showBigShere() { 70 | levels = levels_pixabaymorrisminor(); 71 | canvas = newCanvas( [2,1], [6*$fn,3*$fn] ); 72 | image = drawImage ( levels, canvas, size=[undef,0.4] ); 73 | mesh = canvas2mesh( image, skin=true, thickness=5 ); 74 | projected = projectSphereCylindrical( getMeshVertices(mesh), 100 ); 75 | lithophane = newMesh(projected,getMeshFaces(mesh)); 76 | render() 77 | meshPolyhedron ( lithophane ); 78 | } 79 | module showText( t ) { 80 | % 81 | for ( i=[0:len(t)-1] ) 82 | translate( [0,0,-150-i*40] ) 83 | rotate( [90,0,0] ) 84 | color( "gold" ) 85 | linear_extrude ( height=1 ) 86 | text( t[i], halign="center", size=30-i*3 ); 87 | } 88 | /* 89 | */ 90 | translate ( [000,0,0] ) { 91 | rotate( [90,0,0] ) 92 | translate ( [-100,-50,0] ) 93 | showPlane(); 94 | showText( [ "Plane", "thick", "positive", "preserve on" ] ); 95 | } 96 | translate ( [300,0,0] ) { 97 | rotate( [90,0,0] ) 98 | translate ( [-100,-50,0] ) 99 | showPlane(resized=true,moved=true,preserve=false); 100 | showText( [ "Plane", "resize", "move", "preserve off", "thick", "positive" ] ); 101 | } 102 | translate ( [600,0,0] ) { 103 | rotate( [0,0,90] ) 104 | scale( 0.7 ) 105 | showCylinder(); 106 | showText( [ "Cylinder", "thick", "positive", "preserve on" ] ); 107 | } 108 | translate ( [900,0,0] ) { 109 | rotate( [0,0,90] ) 110 | showSphereFull(skin=true); 111 | showText( [ "Sphere", "positive", "preserve on", "skin" ] ); 112 | } 113 | translate ( [1200,0,0] ) { 114 | rotate( [0,0,90] ) 115 | showSphereFull(skin=true,positive=false); 116 | showText( [ "Sphere", "negative", "preserve on", "skin" ] ); 117 | } 118 | translate ( [1500,0,0] ) { 119 | rotate( [0,0,90] ) 120 | showSphereFull(skin=true,resized=true); 121 | showText( [ "Sphere", "resize", "preserve on", "skin", "positive" ] ); 122 | } 123 | translate ( [1800,0,0] ) { 124 | rotate( [0,0,90] ) 125 | showSphereCrop(); 126 | showText( [ "Sphere", "crop", "resize", "preserve on", "skin", "positive" ] ); 127 | } 128 | translate ( [2100,0,0] ) { 129 | rotate( [0,0,90] ) 130 | showSphereCrop(preserve=false); 131 | showText( [ "Sphere", "preserve off", "crop", "resize", "skin", "positive" ] ); 132 | } 133 | translate ( [1000,1500,800] ) { 134 | scale( [10,10,10] ) 135 | rotate( [0,0,90] ) 136 | showBigShere(); 137 | } 138 | /* 139 | */ 140 | 141 | -------------------------------------------------------------------------------- /test/test-extrude.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: OpenSCAD extensions to scad language 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | use 15 | use 16 | 17 | translate([+4.5,0,0]) 18 | extrude(regularPolygon(100), 1, false, [undef,2,2], [0,undef,4] ); 19 | 20 | translate([+4.5,3,0]) 21 | extrude(regularPolygon(100), 1, true, [undef,0,4], [2,undef,2] ); 22 | 23 | translate([+1.5,0,0]) 24 | extrude(regularPolygon(12), 1, true, [undef,1,1] ); 25 | 26 | translate([+1.5,3,0]) 27 | extrude(regularPolygon(12), 1, true, undef, [1,undef,1] ); 28 | 29 | translate([-1.5,0,0]) 30 | extrude(regularPolygon(8), 1, true, [undef,1,1], [0,undef,1.3] ); 31 | 32 | translate([-1.5,3,0]) 33 | extrude(regularPolygon(8), 1, true, [undef,0,1.3], [1,undef,1] ); 34 | 35 | translate([-4.5,3,0]) 36 | extrude(regularPolygon(3), 1 ); 37 | 38 | translate([-4.5,0,0]) 39 | extrude(regularPolygon(3), 1, true, [undef,0,1], [0,undef,1] ); 40 | 41 | translate([-1.5,6,0]) 42 | prism(meshRegularPolygon(6)); 43 | 44 | translate([-4.5,6,0]) 45 | prism(meshRegularPolygon(12), caps=false); 46 | 47 | translate([1.5,6,0]) 48 | frustum(meshRegularPolygon(7), 1, 30); 49 | 50 | translate([4.5,6,0]) 51 | frustum(meshRegularPolygon(7), 1, 30, caps=false); 52 | -------------------------------------------------------------------------------- /test/test-geometry.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Some geometrical functions 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | use 14 | use 15 | use 16 | 17 | 18 | // ---------------------------------------- 19 | // TEST intersec_planes_3 20 | // ---------------------------------------- 21 | 22 | test_ip3_0_planes = [ 23 | [ [-3,4,0], [0,0,2] ], 24 | [ [-4,0,4], [0,3,0] ], 25 | [ [0,1,-2], [4,0,0] ] ]; 26 | test_ip3_0 = intersec_planes_3( 27 | test_ip3_0_planes[0], 28 | test_ip3_0_planes[1], 29 | test_ip3_0_planes[2] 30 | ); 31 | color("yellow") renderPlanes(test_ip3_0_planes); 32 | color("red") renderPoints([test_ip3_0]); 33 | echo("test_ip3_0=",roundDownList(test_ip3_0)); 34 | assert(roundDownList(test_ip3_0)==[0,0,0], 35 | "ERROR intersec_planes_3 test 0"); 36 | 37 | test_ip3_1_planes = [ 38 | [ [25,-2,0], [0,2,2] ], 39 | [ [25,-1,4], [0,3,-10] ], 40 | [ [23,-3,2], [4,8,0] ] ]; 41 | test_ip3_1 = intersec_planes_3( 42 | test_ip3_1_planes[0], 43 | test_ip3_1_planes[1], 44 | test_ip3_1_planes[2] 45 | ); 46 | color("blue") renderPlanes(test_ip3_1_planes); 47 | color("red") renderPoints([test_ip3_1]); 48 | echo("test_ip3_1=",roundDownList(test_ip3_1)); 49 | assert(roundDownList(test_ip3_1)==[26.69,-4.85,2.84], 50 | "ERROR intersec_planes_3 test 1"); 51 | 52 | test_ip3_2 = intersec_planes_3( 53 | [ [1,2,0], [0,0,2] ], 54 | [ [4,2,0], [0,0,2] ], 55 | [ [0,5,6], [4,0,0] ] 56 | ); 57 | echo("test_ip3_2=",test_ip3_2); 58 | assert(is_undef(test_ip3_2), 59 | "ERROR intersec_planes_3 test 2"); 60 | 61 | 62 | // ---------------------------------------- 63 | // TEST intersec_planes_2 64 | // ---------------------------------------- 65 | 66 | test_ip2_0_planes = [ 67 | [ [9,2,0], [4,1,-1] ], 68 | [ [9,5,4], [-2,3,1] ] ]; 69 | test_ip2_0 = intersec_planes_2( 70 | test_ip2_0_planes[0], 71 | test_ip2_0_planes[1] 72 | ); 73 | color("green") renderPlanes(test_ip2_0_planes); 74 | color("red") renderLines([test_ip2_0]); 75 | test_ip2_0_check=roundDownList(test_ip2_0); 76 | echo("test_ip2_0=",test_ip2_0_check); 77 | assert(test_ip2_0_check== [[7.68,5.9,-1.36],[4,-2,14],[0,0,0]], 78 | "ERROR intersec_planes_2 test 0"); 79 | 80 | test_ip2_1 = intersec_planes_2( 81 | [ [1,2,0], [2,2,1] ], 82 | [ [3,5,4], [60,60,30] ] 83 | ); 84 | echo("test_ip2_1=",test_ip2_1); 85 | assert(is_undef(test_ip2_1), 86 | "ERROR intersec_planes_2 test 1"); 87 | 88 | 89 | 90 | // ---------------------------------------- 91 | // Utilities 92 | // ---------------------------------------- 93 | $fn=10; 94 | 95 | function roundDownList(val) = [ for (v=val) 96 | if ( is_list(v) ) 97 | [ for (c=v) roundDown(c,0.01) ] 98 | else 99 | roundDown(v,0.01) 100 | ]; 101 | -------------------------------------------------------------------------------- /test/test-glue.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Glue shapes library test 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | 14 | color( "gold" ) 15 | glue_circle ( $fn=200 ); 16 | 17 | translate( [0,0,20] ) 18 | rotate( [-30,0,0] ) 19 | difference() { 20 | translate( [0,0,5/2] ) 21 | cube( [ 70, 70, 5 ], center=true ); 22 | # glue_circle_receiver ( $fn=200 ); 23 | } 24 | 25 | translate( [0,0,-20] ) 26 | rotate( [+30,0,0] ) 27 | difference() { 28 | translate( [0,0,-5/2] ) 29 | cube( [ 70, 70, 5 ], center=true ); 30 | glue_circle_receiver ( $fn=200 ); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /test/test-hardware.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Test hardware modules 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | use 14 | use 15 | 16 | 17 | PRECISION = 200; 18 | SEPARATION = 0; 19 | 20 | module show_er() { 21 | collets_min = [ // Minimum printable dimensions with default prinable settings 22 | newER8(1), newER11(1), newER16(1), newER20(1), 23 | newER25(1), newER32(2), newER40(3), newER50(6) 24 | ]; 25 | collets_max = [ // Maximum printable dimensions with default prinable settings 26 | newER8(4), newER11(6.5), newER16(10), newER20(13), 27 | newER25(16), newER32(20), newER40(26), newER50(34) 28 | ]; 29 | 30 | YER = -50; 31 | YERMAX = -110; 32 | YPASS = 10; 33 | offsetx = columnSum(collets_min,3)/2; 34 | for ( i=[0:len(collets_min)-1] ) let( 35 | x = columnSum(collets_min,3,0,i), 36 | col = collets_min[i], 37 | colmax = collets_max[i] 38 | ) { 39 | translate([x-offsetx,YER,0]) 40 | ERCollet(col); 41 | translate([x-offsetx,YERMAX,0]) 42 | ERCollet(colmax); 43 | color( "gold" ) 44 | translate([x-offsetx,YER,ERColletGetL(col)+5]) 45 | rotate ( [90,0,0] ) 46 | linear_extrude(1) 47 | text(ERColletGetName(col), halign="center", valign="center", size=3, $fn=100 ); 48 | color("lime") 49 | translate([x-offsetx,YPASS,0]) ERColletPassage(col); 50 | color("blue") 51 | translate([x-offsetx,YER,0]) ERColletExtractorRing(col); 52 | } 53 | } 54 | 55 | module show_parts( part=0, cut=undef, cut_rotation=undef ) { 56 | zip = newZipTie2_5(); 57 | zipu1 = makeZipU( zip, 20 ); 58 | zipu2 = makeZipU( zip, 10, 5 ); 59 | zipo1 = makeZipOblong( zip, 1.5, 3 ); 60 | 61 | if ( part==0 ) { 62 | intersection () { 63 | union() { 64 | zipShape ( zipu1 ); 65 | rotate( [0,90,0] ) 66 | zipShape ( zipo1 ); 67 | translate( [0, 0, 2]) 68 | difference() { 69 | zipConduitShape ( zipu2 ); 70 | zipConduitHollow( zipu2 ); 71 | } 72 | } 73 | color ( "#fff",0.1 ) 74 | rotate( [0,0,is_undef(cut_rotation)?0:cut_rotation] ) 75 | translate( [-500,is_undef(cut)?-500:cut,-500] ) 76 | cube( [1000,1000,1000] ); 77 | } 78 | color( "#fff" ) 79 | translate( [0, 0, 2]) 80 | zipShape ( zipu2 ); 81 | show_er(); 82 | } 83 | 84 | if ( part==1 ) { 85 | #zipShapePassage ( zipu2, $gap=1 ); 86 | zipShape ( zipu2 ); 87 | } 88 | if ( part==2 ) { 89 | #zipShapePassage ( zipo1 ); 90 | zipShape ( zipo1 ); 91 | } 92 | if ( part==3 ) { 93 | difference() { 94 | zipConduitShape( zipu2 ); 95 | zipConduitHollow( zipu2 ); 96 | } 97 | zipShape ( zipu2 ); 98 | } 99 | if ( part==4 ) { 100 | show_er(); 101 | } 102 | } 103 | 104 | // 0: all 105 | // 1: zip U shape 106 | // 2: zip Obblong shape 107 | // 3: zip U shape conduit 108 | // 4: ER Collets 109 | show_parts ( 4, 0, -90, $fn=PRECISION ); 110 | 111 | 112 | -------------------------------------------------------------------------------- /test/test-hirth-joint.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Metric screw modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | use <../hirth-joint.scad> 14 | 15 | MARGIN = 0.2; 16 | 17 | // ---------------------------------------- 18 | // 19 | // Showcase 20 | // 21 | // ---------------------------------------- 22 | module hirthJointShow( part=0 ) { 23 | INTER = 10; 24 | 25 | RADIUS = 10; 26 | TOOTH = 21; 27 | HEIGHT = 1.2; 28 | SHOULDER = 0; 29 | INLAY = 2; 30 | 31 | if ( part==0 || part==1 ) { 32 | color( "YellowGreen" ) 33 | translate( [0,0,+SHOULDER+HEIGHT/2+INTER/2] ) 34 | rotate( [180,0,0] ) 35 | rotate( [0,0,180] ) 36 | hirthJointSinus( RADIUS, TOOTH, HEIGHT, SHOULDER, INLAY ); 37 | } 38 | 39 | if ( part==0 || part==2 ) { 40 | color( "Lime" ) 41 | translate( [0,0,-SHOULDER-HEIGHT/2-INTER/2] ) 42 | hirthJointSinus( RADIUS, TOOTH, HEIGHT, SHOULDER, INLAY ); 43 | } 44 | 45 | if ( part==0 || part==3 ) { 46 | color( "SkyBlue" ) 47 | translate( [0,3*RADIUS,-SHOULDER-HEIGHT/2-INTER/2] ) 48 | hirthJointTriangle( RADIUS, TOOTH, HEIGHT, SHOULDER, INLAY ); 49 | } 50 | 51 | if ( part==0 || part==4 ) { 52 | color( "Khaki" ) 53 | translate( [2.5*RADIUS,1.5*RADIUS,-SHOULDER-HEIGHT/2-INTER/2] ) 54 | hirthJointRectangle( RADIUS, TOOTH, HEIGHT, SHOULDER, INLAY ); 55 | } 56 | 57 | if ( part==0 || part==5 ) { 58 | translate( [0,0,-1.5*INTER-SHOULDER-HEIGHT] ) { 59 | difference() { 60 | color( "DarkGreen" ) 61 | translate( [0,0,-2] ) 62 | cylinder( r=(RADIUS+2)/cos(30), h=4, center=true ); 63 | hirthJointPassage( RADIUS, HEIGHT, SHOULDER, INLAY ); 64 | } 65 | } 66 | } 67 | 68 | if ( part==0 || part==6 ) 69 | translate( [0,50,0] ) { 70 | translate( [0,0,0] ) { 71 | hirthJointSinus( 5, 11, 2, 1, 1, shift=0.5, rmin=0 ); 72 | %hirthJointPassage( 5, 2, 1, 1 ); 73 | } 74 | 75 | translate( [15,0,0] ) { 76 | hirthJointRectangle( 5, 11, 1, 1, 1, shift=0, rmin=2.5 ); 77 | %hirthJointPassage( 5, 1, 1, 1 ); 78 | } 79 | translate( [30,0,0] ) { 80 | hirthJointTriangle( 5, 11, 1, 1, 1, shift=0, rmin=4 ); 81 | %hirthJointPassage( 5, 1, 1, 1 ); 82 | } 83 | 84 | translate( [0,15,0] ) { 85 | difference() { 86 | union() { 87 | // Automatic rmin 88 | hirthJointSinus( 5, 11, 1, 1, 1, shift=0.5 ); 89 | translate( [0,0,3+0.01] ) 90 | rotate([0,180,0]) 91 | hirthJointSinus( 5, 11, 1, 1, 1, shift=0.5 ); 92 | } 93 | translate( [0,-500,0] ) 94 | cube( 1000, center=true ); 95 | } 96 | } 97 | translate( [15,15,0] ) { 98 | difference() { 99 | union() { 100 | hirthJointRectangle( 5, 11, 1, 1, 1, shift=0.5 ); 101 | translate( [0,0,3+0.01] ) 102 | rotate([0,180,0]) 103 | hirthJointRectangle( 5, 11, 1, 1, 1, shift=0.5 ); 104 | } 105 | cylinder(r=2.5,h=10, center=true); 106 | } 107 | } 108 | translate( [30,15,0] ) { 109 | difference() { 110 | union() { 111 | hirthJointTriangle( 5, 11, 1, 1, 1, shift=0.5 ); 112 | translate( [0,0,3+0.01] ) 113 | rotate([0,180,0]) 114 | hirthJointTriangle( 5, 11, 1, 1, 1, shift=0.5 ); 115 | } 116 | cylinder(r=2.5,h=10, center=true); 117 | } 118 | } 119 | 120 | echo ("test=", hirthJointProfileSinus(1) ); 121 | } 122 | 123 | } 124 | 125 | $fn=50; 126 | 127 | difference() { 128 | hirthJointShow( 0 ); 129 | cylinder( r=1.5+MARGIN/2, h=100, center=true ); 130 | } 131 | -------------------------------------------------------------------------------- /test/test-mx-knob.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Knob modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | use <../mx-knob.scad> 14 | use <../mx-screw.scad> 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | module mxKnobTest() { 23 | translate([+60,+30,0]) { 24 | mxKnob ( M12(), 50, 100, cap_height=30 ); 25 | rotate( [180,0,0] ) 26 | %mxBoltHexagonal ( M12() ); 27 | } 28 | translate([+15,+50,0]) 29 | rotate( [90,0,0] ) { 30 | mxKnob ( M6(), 25, 20, part=0 ); 31 | rotate( [180,0,0] ) 32 | #mxBoltHexagonal ( M6() ); 33 | } 34 | translate([-15,+30,0]) { 35 | mxKnob ( M1_6(tlp=3), 15, 15, part=0 ); 36 | rotate( [180,0,0] ) 37 | %mxBoltHexagonal ( M1_6() ); 38 | } 39 | 40 | translate([+60,-30,0]) { 41 | mxKnob ( M12() ); 42 | rotate( [180,0,0] ) 43 | %mxBoltHexagonal ( M12() ); 44 | } 45 | translate([+15,-30,0]) { 46 | mxKnob ( M6(), part=1 ); 47 | mxKnob ( M6(), part=3 ); 48 | rotate( [180,0,0] ) 49 | %mxBoltHexagonal ( M6() ); 50 | } 51 | translate([-15,-30,0]) { 52 | mxKnob ( M1_6(tlp=3) ); 53 | rotate( [180,0,0] ) 54 | %mxBoltHexagonal ( M1_6() ); 55 | } 56 | } 57 | mxKnobTest($fn=50); 58 | -------------------------------------------------------------------------------- /test/test-pixeled.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2_21, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Minecraft Pickaxe - test layout 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | use 15 | use 16 | 17 | /** 18 | * $part: 19 | * ALL() 20 | * 0: Cells only 21 | * 1: Caps only 22 | * 2: Nails only 23 | * 24 | * 3: Cells for printing 25 | * 4: Caps for printing 26 | * 5: Nails for printing 27 | * 28 | * $subpart: 29 | * ALL() 30 | * 0: part 0 31 | * 1: part 1 32 | * etc... 33 | * 34 | * $cut: 35 | * true: cut the figure to see internal structure (debug purpose) 36 | * false: normal display (default) 37 | * 38 | */ 39 | 40 | // Custom sizes 41 | $pixel_w = 30; 42 | $pixel_h = 20; 43 | 44 | // Selection of what to display 45 | $part = ALL(); 46 | $subpart = ALL(); 47 | 48 | // Beveling is essentially to counter first layer overextrusion 49 | // set this value to 0 to disable beveling 50 | $bevel = 0.3; 51 | 52 | layoutPixeledObject(TEST_CELLS(), TEST_NAILS(), TEST_COLORS()); 53 | 54 | 55 | 56 | VAL_PART1 = VAL_UNICOLOR_CELL(1); 57 | VAL_PART1_SHINE = VAL_BICOLOR_CELL(2); 58 | VAL_PART2 = VAL_UNICOLOR_CELL(3); 59 | VAL_PART2_SHINE = VAL_BICOLOR_CELL(4); 60 | 61 | COLOR_DARK_BROWN = "#513c1a"; 62 | COLOR_LIGHT_BROWN = "#a3752d"; 63 | COLOR_DARK_TURQUOISE = "#20594b"; 64 | COLOR_LIGHT_TURQUOISE = "#32e8bf"; 65 | 66 | /** 67 | * Mapping from layout values to colors 68 | */ 69 | function TEST_COLORS() = [ 70 | [ // Cell color mapping: IDX_COLOR_CELL() array 71 | [ VAL_PART1, COLOR_DARK_BROWN ], 72 | [ VAL_PART1_SHINE, COLOR_DARK_BROWN ], 73 | [ VAL_PART2, COLOR_DARK_TURQUOISE ], 74 | [ VAL_PART2_SHINE, COLOR_DARK_TURQUOISE ] 75 | ],[ // Cap color mapping: IDX_COLOR_CAP() array 76 | [ VAL_PART1_SHINE, COLOR_LIGHT_BROWN ], 77 | [ VAL_PART2_SHINE, COLOR_LIGHT_TURQUOISE ] 78 | ]]; 79 | 80 | function TEST_CELLS() = 81 | let ( 82 | _ = VAL_EMPTY(), 83 | z = VAL_PART1, 84 | x = VAL_PART1_SHINE, 85 | m = VAL_PART2, 86 | o = VAL_PART2_SHINE 87 | ) 88 | [[ 89 | [ o,_ ], 90 | [ o,o ], 91 | ],[ 92 | [ _,x ], 93 | [ _,_ ], 94 | ]]; 95 | 96 | function TEST_NAILS() = 97 | let ( 98 | _ = VAL_EMPTY(), 99 | r = VAL_NAIL_RGT(), 100 | x = VAL_NAIL_LFT() + VAL_NAIL_BOT(), 101 | I = VAL_NAIL_TOP() + VAL_NAIL_BOT() 102 | ) 103 | [[ 104 | [ r,_ ], 105 | [ _,I ], 106 | ],[ 107 | [ _,x ], 108 | [ _,_ ], 109 | ]]; 110 | -------------------------------------------------------------------------------- /test/test-sew.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: OpenSCAD extensions to scad language 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | use 14 | use 15 | use 16 | 17 | 18 | 19 | unevenSurface = [ 20 | [ [0,1,0], [3,0,0], [6,1,0] ], 21 | [ [0,1,1], [2,0,1], [4,0,1], [6,1,1] ], 22 | [ [0,1,2], [1,0,2], [2,0,2], [3,-0.5,2], [4,0,2], [5,0,2], [6,1,2] ], 23 | [ [0,1,3], [2,0,3], [4,0,3], [6,1,3] ], 24 | [ [0,1,4], [3,0,4], [6,1,4] ], 25 | ]; 26 | color("lime") 27 | translate( [10,0,0] ) 28 | sew(unevenSurface); 29 | 30 | 31 | radius = 5; 32 | height = 14; 33 | layers = 10; 34 | candleSurface = [ 35 | for (i=[0:layers-1]) 36 | transform( 37 | translation([0,0,i*height/layers]) * rotation([0,0,-30*i]), 38 | circle($fn=6,r=radius)) 39 | ]; 40 | color("lightblue") 41 | difference() { 42 | sew(candleSurface,convexity=10); 43 | cylinder(r=1, h=1000, $fn=50); 44 | } 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /test/test-snap-joint-tutorial.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Snap Joint tutorial 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | use <../snap-joint.scad> 14 | 15 | // ---------------------------------------- 16 | // API 17 | // ---------------------------------------- 18 | $fn=50; 19 | showCase() { 20 | step_01(); 21 | step_02(); 22 | step_03(); 23 | step_04(); 24 | step_05(); 25 | step_06(); 26 | step_07(); 27 | step_08(); 28 | step_09(); 29 | step_10(); 30 | step_11(); 31 | step_12(); 32 | }; 33 | 34 | // ---------------------------------------- 35 | // Showcase 36 | // ---------------------------------------- 37 | SHOW_ITV_H = 30; 38 | 39 | // 1: Simple Joint internal part 40 | module step_01() { 41 | joint = newSnapCircleInt (); 42 | snapJoint(joint); 43 | } 44 | 45 | // 2: Same with external part 46 | module step_02() { 47 | joint = newSnapCircleInt(); 48 | snapJoint(joint); 49 | joint_e = newSnapCircleExt(source=joint); 50 | snapJoint(joint_e); 51 | } 52 | 53 | // 3: Gap 54 | module step_03() { 55 | $gap = 1; 56 | 57 | joint = newSnapCircleInt(); 58 | snapJoint(joint); 59 | joint_e = newSnapCircleExt(source=joint); 60 | snapJoint(joint_e); 61 | } 62 | 63 | // 4: Springs/Cutter 64 | module step_04() { 65 | joint = newSnapCircleInt(springs=true); 66 | snapJoint(joint); 67 | joint_e = newSnapCircleExt(source=joint); 68 | snapJoint(joint_e); 69 | } 70 | 71 | // 5: Polygon 5 72 | module step_05() { 73 | joint = newSnapPolygonInt(springs=true); 74 | snapJoint(joint); 75 | joint_e = newSnapPolygonExt(source=joint); 76 | snapJoint(joint_e); 77 | } 78 | 79 | // 6: Polygon 4 80 | module step_06() { 81 | joint = newSnapPolygonInt ( 82 | leaves=4, 83 | springs=true ); 84 | snapJoint(joint); 85 | joint_e = newSnapPolygonExt(source=joint); 86 | snapJoint(joint_e); 87 | } 88 | 89 | // 7: Cut external: one time joint 90 | module step_07() { 91 | joint = newSnapCircleInt (); 92 | snapJoint(joint); 93 | joint_e = newSnapCircleExt ( 94 | source=joint, 95 | springs=true ); 96 | snapJoint(joint_e); 97 | } 98 | 99 | // 8: Height/Thickness 100 | module step_08() { 101 | joint = newSnapCircleInt ( 102 | height = 10, 103 | thickness = 3, 104 | springs = true ); 105 | snapJoint(joint); 106 | } 107 | 108 | // 9: Hook 109 | module step_09() { 110 | joint = newSnapCircleInt ( 111 | height = 10, 112 | springs = true, 113 | hook_h = 5, 114 | hook_w = 1.6 ); 115 | snapJoint(joint); 116 | } 117 | 118 | // 10: Spring width 119 | module step_10() { 120 | joint = newSnapCircleInt ( 121 | height = 10, 122 | springs = true, 123 | hook_h = 5, 124 | hook_w = 1.6, 125 | spring_w = 5 ); 126 | snapJoint(joint); 127 | } 128 | 129 | // 11: Spring angle 130 | module step_11() { 131 | joint = newSnapCircleInt ( 132 | height = 10, 133 | springs = true, 134 | hook_h = 5, 135 | hook_w = 1.6, 136 | spring_w = 5, 137 | spring_a = 33 ); 138 | snapJoint(joint); 139 | } 140 | 141 | // 12: Cut 142 | module step_12() { 143 | joint = newSnapCircleInt ( 144 | springs = true, 145 | cutwidth = 2, 146 | cutdistance = 7 147 | ); 148 | snapJoint(joint); 149 | } 150 | 151 | // ---------------------------------------- 152 | // Implementation 153 | // ---------------------------------------- 154 | 155 | module showOneStep ( x=0 ) { 156 | translate([x,SHOW_ITV_H,0]) 157 | children(); 158 | translate([x,0,0]) 159 | children(); 160 | } 161 | 162 | module showCase( only_one=undef ) { 163 | range = SHOW_ITV_H*($children-1); 164 | intersection () { 165 | union() { 166 | if ( is_undef(only_one) ) 167 | for ( i=[0:$children-1] ) 168 | showOneStep(-range/2+i*SHOW_ITV_H) 169 | children(i); 170 | else 171 | showOneStep() 172 | children(only_one-1); 173 | } 174 | color ( "#fff",0.1 ) 175 | translate( [-500,0,-500] ) 176 | cube( [1000,1000,1000] ); 177 | } 178 | } 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /test/threads/test-bsf-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSF thread test 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // Showcase 18 | // ---------------------------------------- 19 | 20 | module showName( d, z ) { 21 | %color( "gold" ) 22 | translate( [0,-7,z] ) 23 | rotate( [90,0,0] ) 24 | linear_extrude(0.1) 25 | text( screwGetName(d), halign="center", valign="center", size=2, $fn=100 ); 26 | } 27 | 28 | module showParts( part=0 ) { 29 | IX=20; 30 | color( "silver" ) 31 | translate( [50,7,-20] ) 32 | rotate( [90,0,0] ) 33 | linear_extrude(0.1) 34 | text( "BSW BSF",halign="center",valign="center",size=10,$fn=100 ); 35 | 36 | if ( part==0 ) { 37 | s1 = BSF3_16(); 38 | s2 = BSF7_32(); 39 | s3 = BSF1_4(tl=20); 40 | s4 = BSF3_8(tl=30); 41 | s5 = BSF1_2(); 42 | s6 = BSF7_8(); 43 | translate([0,0,0]) { 44 | bsfNutHexagonalThreaded(s1, $fn=50); 45 | showName(s1, -2); 46 | } 47 | translate([15,0,0]) { 48 | bsfNutSquareThreaded(s2, $fn=50); 49 | showName(s2, -2); 50 | } 51 | translate([30,0,0]) { 52 | bsfBoltHexagonalThreaded(s3, $fn=50); 53 | showName(s3, -7); 54 | } 55 | translate([50,0,0]) { 56 | bsfBoltAllenThreaded(s4, $fn=50); 57 | showName(s4, -11); 58 | } 59 | translate([70,0,0]) { 60 | bsfThreadInternal(s5, $fn=50); 61 | showName(s5, -2); 62 | } 63 | translate([90,0,0]) { 64 | bsfThreadExternal(bsfClone(s6,16),$fn=50); 65 | showName(s6, -4); 66 | } 67 | } 68 | if ( part==1 ) { 69 | s1 = BSF1_4(tl=20); 70 | translate([0*IX,0,0]) { 71 | bsfNutHexagonalThreaded(s1, $fn=50); 72 | showName(s1, -2); 73 | } 74 | translate([1*IX,0,0]) { 75 | bsfNutSquareThreaded(s1, $fn=50); 76 | showName(s1, -2); 77 | } 78 | translate([2*IX,0,0]) { 79 | bsfBoltHexagonalThreaded(s1, $fn=50); 80 | showName(s1, -7); 81 | } 82 | translate([3*IX,0,0]) { 83 | bsfBoltAllenThreaded(s1, $fn=50); 84 | showName(s1, -9); 85 | } 86 | } 87 | if ( part==2 ) { 88 | s1 = BSF3_8(tl=20); 89 | translate([0*IX,0,0]) { 90 | bsfNutHexagonalThreaded(s1, $fn=50); 91 | showName(s1, -2); 92 | } 93 | translate([1*IX,0,0]) { 94 | bsfNutSquareThreaded(s1, $fn=50); 95 | showName(s1, -2); 96 | } 97 | translate([2*IX,0,0]) { 98 | bsfBoltHexagonalThreaded(s1, $fn=50); 99 | showName(s1, -9); 100 | } 101 | translate([3*IX,0,0]) { 102 | bsfBoltAllenThreaded(s1, $fn=50); 103 | showName(s1, -11); 104 | } 105 | } 106 | } 107 | 108 | showParts(0); 109 | -------------------------------------------------------------------------------- /test/threads/test-bspp-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSPP thread test 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | use 16 | use 17 | 18 | // ---------------------------------------- 19 | // 20 | // Showcase 21 | // 22 | // ---------------------------------------- 23 | $fn=50; 24 | 25 | module showVerticalText(t, z) { 26 | %color( "gold" ) 27 | translate( [0,-7,z] ) 28 | rotate( [90,0,0] ) 29 | linear_extrude(0.1) 30 | text( t, halign="center", valign="center", size=2 ); 31 | } 32 | 33 | module showName( d, z ) { 34 | showVerticalText(screwGetName(d), z); 35 | } 36 | 37 | module showParts( part=0 ) { 38 | IX=20; 39 | color( "silver" ) 40 | translate( [40,7,-20] ) 41 | rotate( [90,0,0] ) 42 | linear_extrude(0.1) 43 | text( "BSPP",halign="center",valign="center",size=10 ); 44 | 45 | if ( part==0 ) { 46 | translate([00,0,0]) { 47 | screw = BSPP1_4(); 48 | difference() { 49 | bsppBoltHexagonalThreaded(screw); 50 | cylinder(r=bsppGetPipeD(screw)/2, h=1000, center=true); 51 | } 52 | showName(screw, -12); 53 | } 54 | translate([40,0,0]) { 55 | screw = BSPP1_2(); 56 | difference() { 57 | bsppThreadExternal(screw); 58 | cylinder(r=bsppGetPipeD(screw)/2, h=1000, center=true); 59 | } 60 | showName(screw, -2); 61 | } 62 | translate([80,0,0]) { 63 | screw1 = BSPP1_8(tl=7.26); 64 | screw2 = BSW3_8(tl=5.15); 65 | difference() { 66 | union() { 67 | bsppThreadExternal(screw1); 68 | translate([0,0,-screwGetHexagonalHeadL(screw2)]) 69 | rotate([180,0,0]) 70 | bswBoltHexagonalThreaded(screw2); 71 | } 72 | cylinder(r=bsppGetPipeD(screw1)/2, h=1000, center=true); 73 | } 74 | showVerticalText("BSPP 1/8 to BSW 3/8 adapter", -22); 75 | } 76 | } 77 | } 78 | 79 | showParts(0); 80 | 81 | -------------------------------------------------------------------------------- /test/threads/test-bsw-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: BSW thread test 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | module showName( d, z ) { 23 | %color( "gold" ) 24 | translate( [0,-7,z] ) 25 | rotate( [90,0,0] ) 26 | linear_extrude(0.1) 27 | text( screwGetName(d), halign="center", valign="center", size=2, $fn=100 ); 28 | } 29 | 30 | module showParts( part=0 ) { 31 | IX=20; 32 | color( "silver" ) 33 | translate( [50,7,-20] ) 34 | rotate( [90,0,0] ) 35 | linear_extrude(0.1) 36 | text( "BSW BSF",halign="center",valign="center",size=10,$fn=100 ); 37 | 38 | if ( part==0 ) { 39 | s1 = BSW1_16(); 40 | s2 = BSW5_32(); 41 | s3 = BSW1_4(tl=20); 42 | s4 = BSW3_8(tl=30); // AKA: Congrès thread 43 | s5 = BSW1_2(); 44 | s6 = BSW7_8(); 45 | translate([0,0,0]) { 46 | bswNutHexagonalThreaded(s1, $fn=50); 47 | showName(s1, -2); 48 | } 49 | translate([15,0,0]) { 50 | bswNutSquareThreaded(s2, $fn=50); 51 | showName(s2, -2); 52 | } 53 | translate([30,0,0]) { 54 | bswBoltHexagonalThreaded(s3, $fn=50); 55 | showName(s3, -7); 56 | } 57 | translate([50,0,0]) { 58 | bswBoltAllenThreaded(s4, $fn=50); 59 | showName(s4, -11); 60 | } 61 | translate([70,0,0]) { 62 | bswThreadInternal(screw=s5,$fn=50); 63 | showName(s5, -2); 64 | } 65 | translate([90,0,0]) { 66 | bswThreadExternal(bswClone(s6,16),$fn=50); 67 | showName(s6, -4); 68 | } 69 | } 70 | if ( part==1 ) { 71 | s1 = BSW1_4(tl=20); 72 | translate([0*IX,0,0]) { 73 | bswNutHexagonalThreaded(s1, $fn=100); 74 | showName(s1, -2); 75 | } 76 | translate([1*IX,0,0]) { 77 | bswNutSquareThreaded(s1, $fn=100); 78 | showName(s1, -2); 79 | } 80 | translate([2*IX,0,0]) { 81 | bswBoltHexagonalThreaded(s1, $fn=100); 82 | showName(s1, -7); 83 | } 84 | translate([3*IX,0,0]) { 85 | bswBoltAllenThreaded(s1, $fn=100); 86 | showName(s1, -9); 87 | } 88 | } 89 | if ( part==2 ) { 90 | s1 = BSW3_8(tl=20); 91 | translate([0*IX,0,0]) { 92 | bswNutHexagonalThreaded(s1, $fn=100); 93 | showName(s1, -2); 94 | } 95 | translate([1*IX,0,0]) { 96 | bswNutSquareThreaded(s1, $fn=100); 97 | showName(s1, -2); 98 | } 99 | translate([2*IX,0,0]) { 100 | bswBoltHexagonalThreaded(s1, $fn=100); 101 | showName(s1, -9); 102 | } 103 | translate([3*IX,0,0]) { 104 | bswBoltAllenThreaded(s1, $fn=100); 105 | showName(s1, -11); 106 | } 107 | } 108 | } 109 | 110 | showParts(0); 111 | 112 | -------------------------------------------------------------------------------- /test/threads/test-mx-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Metric screw thread test 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | module showName( d, z ) { 23 | %color( "gold" ) 24 | translate( [0,-7,z] ) 25 | rotate( [90,0,0] ) 26 | linear_extrude(0.1) 27 | text( screwGetName(d), halign="center", valign="center", size=2, $fn=100 ); 28 | } 29 | 30 | module showParts( part=0 ) { 31 | IX=20; 32 | color( "DodgerBlue" ) 33 | translate( [50,7,-20] ) 34 | rotate( [90,0,0] ) 35 | linear_extrude(0.1) 36 | text( "MC MF",halign="center",valign="center",size=10,$fn=100 ); 37 | 38 | if ( part==0 ) { 39 | s1 = M1_6(); 40 | s2 = M5(); 41 | s3 = M6(tl=20); 42 | s4 = M10(tl=30); 43 | s5 = M12(); 44 | s6 = M22(); 45 | translate([0,0,0]) { 46 | mxNutHexagonalThreaded(s1, $fn=50); 47 | showName(s1, -2); 48 | } 49 | translate([15,0,0]) { 50 | mxNutSquareThreaded(s2, $fn=50); 51 | showName(s2, -2); 52 | } 53 | translate([30,0,0]) { 54 | mxBoltHexagonalThreaded(s3, $fn=50); 55 | showName(s3, -7); 56 | } 57 | translate([50,0,0]) { 58 | mxBoltAllenThreaded(s4, $fn=50); 59 | showName(s4, -11); 60 | } 61 | translate([70,0,0]) { 62 | mxThreadInternal(s5, $fn=50); 63 | showName(s5, -2); 64 | } 65 | translate([90,0,0]) { 66 | mxThreadExternal(mxClone(s6,16),$fn=50); 67 | showName(s6, -4); 68 | } 69 | } 70 | if ( part==1 ) { 71 | s1 = M5(tl=20); 72 | translate([0*IX,0,0]) { 73 | mxNutHexagonalThreaded(s1, $fn=100); 74 | showName(s1, -2); 75 | } 76 | translate([1*IX,0,0]) { 77 | mxNutSquareThreaded(s1, $fn=100); 78 | showName(s1, -2); 79 | } 80 | translate([2*IX,0,0]) { 81 | mxBoltHexagonalThreaded(s1, $fn=100); 82 | showName(s1, -7); 83 | } 84 | translate([3*IX,0,0]) { 85 | mxBoltAllenThreaded(s1, $fn=100); 86 | showName(s1, -9); 87 | } 88 | } 89 | if ( part==2 ) { 90 | s1 = M6(tl=20); 91 | translate([0*IX,0,0]) { 92 | mxNutHexagonalThreaded(s1, $fn=100); 93 | showName(s1, -2); 94 | } 95 | translate([1*IX,0,0]) { 96 | mxNutSquareThreaded(s1, $fn=100); 97 | showName(s1, -2); 98 | } 99 | translate([2*IX,0,0]) { 100 | mxBoltHexagonalThreaded(s1, $fn=100); 101 | showName(s1, -9); 102 | } 103 | translate([3*IX,0,0]) { 104 | mxBoltAllenThreaded(s1, $fn=100); 105 | showName(s1, -11); 106 | } 107 | } 108 | } 109 | 110 | showParts(0); 111 | -------------------------------------------------------------------------------- /test/threads/test-mxf-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Metric fine screw thread test 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | module showName( d, z ) { 23 | %color( "gold" ) 24 | translate( [0,-7,z] ) 25 | rotate( [90,0,0] ) 26 | linear_extrude(0.1) 27 | text( screwGetName(d), halign="center", valign="center", size=2, $fn=100 ); 28 | } 29 | 30 | module showParts( part=0 ) { 31 | IX=20; 32 | color( "DodgerBlue" ) 33 | translate( [50,7,-20] ) 34 | rotate( [90,0,0] ) 35 | linear_extrude(0.1) 36 | text( "MC MF",halign="center",valign="center",size=10,$fn=100 ); 37 | 38 | if ( part==0 ) { 39 | s1 = MF1_6(); 40 | s2 = MF5(); 41 | s3 = MF6(tl=20); 42 | s4 = MF10(tl=30); 43 | s5 = MF12(); 44 | s6 = MF22(); 45 | translate([0,0,0]) { 46 | mxfNutHexagonalThreaded(s1, $fn=50); 47 | showName(s1, -2); 48 | } 49 | translate([15,0,0]) { 50 | mxfNutSquareThreaded(s2, $fn=50); 51 | showName(s2, -2); 52 | } 53 | translate([30,0,0]) { 54 | mxfBoltHexagonalThreaded(s3, $fn=50); 55 | showName(s3, -7); 56 | } 57 | translate([50,0,0]) { 58 | mxfBoltAllenThreaded(s4, $fn=50); 59 | showName(s4, -11); 60 | } 61 | translate([70,0,0]) { 62 | mxfThreadInternal(s5, $fn=50); 63 | showName(s5, -2); 64 | } 65 | translate([90,0,0]) { 66 | mxfThreadExternal(mxfClone(s6,16),$fn=50); 67 | showName(s6, -4); 68 | } 69 | } 70 | if ( part==1 ) { 71 | s1 = MF5(tl=20); 72 | translate([0*IX,0,0]) { 73 | mxfNutHexagonalThreaded(s1, $fn=100); 74 | showName(s1, -2); 75 | } 76 | translate([1*IX,0,0]) { 77 | mxfNutSquareThreaded(s1, $fn=100); 78 | showName(s1, -2); 79 | } 80 | translate([2*IX,0,0]) { 81 | mxfBoltHexagonalThreaded(s1, $fn=100); 82 | showName(s1, -7); 83 | } 84 | translate([3*IX,0,0]) { 85 | mxfBoltAllenThreaded(s1, $fn=100); 86 | showName(s1, -9); 87 | } 88 | } 89 | if ( part==2 ) { 90 | s1 = MF6(tl=20); 91 | translate([0*IX,0,0]) { 92 | mxfNutHexagonalThreaded(s1, $fn=100); 93 | showName(s1, -2); 94 | } 95 | translate([1*IX,0,0]) { 96 | mxfNutSquareThreaded(s1, $fn=100); 97 | showName(s1, -2); 98 | } 99 | translate([2*IX,0,0]) { 100 | mxfBoltHexagonalThreaded(s1, $fn=100); 101 | showName(s1, -9); 102 | } 103 | translate([3*IX,0,0]) { 104 | mxfBoltAllenThreaded(s1, $fn=100); 105 | showName(s1, -11); 106 | } 107 | } 108 | } 109 | 110 | showParts(0); 111 | -------------------------------------------------------------------------------- /test/threads/test-thread-comparison.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Thread standards comparison 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | use 16 | use 17 | use 18 | use 19 | 20 | // ---------------------------------------- 21 | // 22 | // Showcase 23 | // 24 | // ---------------------------------------- 25 | XI=15; 26 | ZI=-25; 27 | module renderThread ( d, x, z ) { 28 | translate( [x*XI,0,z*ZI] ) { 29 | libBoltHexagonalThreaded (d); 30 | color( "gold" ) 31 | translate( [0,0,-6] ) 32 | rotate( [90,0,0] ) 33 | linear_extrude(1) 34 | text( screwGetName(d), halign="center", valign="center", size=2, $fn=100 ); 35 | } 36 | } 37 | 38 | module showcase() { 39 | renderThread ( M6 ( tl=15 ), 0, 0); 40 | renderThread ( MF6 ( tl=15 ), 0, 1); 41 | renderThread ( UNC1_4 ( tl=15 ), 1, 0); 42 | renderThread ( UNF1_4 ( tl=15 ), 1, 1); 43 | renderThread ( BSW1_4 ( tl=15 ), 2, 0); 44 | renderThread ( BSF1_4 ( tl=15 ), 2, 1); 45 | } 46 | 47 | showcase ($fn=50); 48 | 49 | echo("========== Metric thread data =========="); 50 | mxdata = [ for ( i=[0:mxGetDataLength()-1] ) 51 | mxData(i) 52 | ]; 53 | dumpScrewsData(mxdata); 54 | 55 | echo("========== Metric fine thread data =========="); 56 | mxfdata = [ for ( i=[0:mxfGetDataLength()-1] ) 57 | mxfData(i) 58 | ]; 59 | dumpScrewsData(mxfdata); 60 | 61 | echo("========== UNC thread data =========="); 62 | uncdata = [ for ( i=[0:uncGetDataLength()-1] ) 63 | uncData(i) 64 | ]; 65 | dumpScrewsData(uncdata); 66 | 67 | echo("========== UNC fine thread data =========="); 68 | unfdata = [ for ( i=[0:unfGetDataLength()-1] ) 69 | unfData(i) 70 | ]; 71 | dumpScrewsData(unfdata); 72 | 73 | echo("========== BSW thread data =========="); 74 | bswdata = [ for ( i=[0:bswGetDataLength()-1] ) 75 | bswData(i) 76 | ]; 77 | dumpScrewsData(bswdata); 78 | 79 | echo("========== BSW fine thread data =========="); 80 | bsfdata = [ for ( i=[0:bsfGetDataLength()-1] ) 81 | bsfData(i) 82 | ]; 83 | dumpScrewsData(bsfdata); 84 | -------------------------------------------------------------------------------- /test/threads/test-unc-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: UNC thread test 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | module showName( d, z ) { 23 | %color( "gold" ) 24 | translate( [0,-7,z] ) 25 | rotate( [90,0,0] ) 26 | linear_extrude(0.1) 27 | text( screwGetName(d), halign="center", valign="center", size=2, $fn=100 ); 28 | } 29 | 30 | module showParts( part=0 ) { 31 | IX=20; 32 | color( "gold" ) 33 | translate( [50,7,-20] ) 34 | rotate( [90,0,0] ) 35 | linear_extrude(0.1) 36 | text( "UNC UNF",halign="center",valign="center",size=10,$fn=100 ); 37 | 38 | if ( part==0 ) { 39 | s1 = UNC_N1(); 40 | s2 = UNC_N5(); 41 | s3 = UNC1_4(tl=20); 42 | s4 = UNC3_8(tl=30); 43 | s5 = UNC1_2(); 44 | s6 = UNC7_8(); 45 | translate([2,0,0]) { 46 | uncNutHexagonalThreaded(s1, $fn=50); 47 | showName(s1, -2); 48 | } 49 | translate([15,0,0]) { 50 | uncNutSquareThreaded(s2, $fn=50); 51 | showName(s2, -2); 52 | } 53 | translate([30,0,0]) { 54 | uncBoltHexagonalThreaded(s3, $fn=50); 55 | showName(s3, -7); 56 | } 57 | translate([50,0,0]) { 58 | uncBoltAllenThreaded(s4, $fn=50); 59 | showName(s4, -11); 60 | } 61 | translate([70,0,0]) { 62 | uncThreadInternal(s5, $fn=50); 63 | showName(s5, -2); 64 | } 65 | translate([90,0,0]) { 66 | uncThreadExternal(uncClone(s6,16),$fn=50); 67 | showName(s6, -4); 68 | } 69 | } 70 | if ( part==1 ) { 71 | s1 = UNC1_4(tl=20); 72 | translate([0*IX,0,0]) { 73 | uncNutHexagonalThreaded(s1, $fn=100); 74 | showName(s1, -2); 75 | } 76 | translate([1*IX,0,0]) { 77 | uncNutSquareThreaded(s1, $fn=100); 78 | showName(s1, -2); 79 | } 80 | translate([2*IX,0,0]) { 81 | uncBoltHexagonalThreaded(s1, $fn=100); 82 | showName(s1, -7); 83 | } 84 | translate([3*IX,0,0]) { 85 | uncBoltAllenThreaded(s1, $fn=100); 86 | showName(s1, -9); 87 | } 88 | } 89 | if ( part==2 ) { 90 | s1 = UNC3_8(tl=20); 91 | translate([0*IX,0,0]) { 92 | uncNutHexagonalThreaded(s1, $fn=100); 93 | showName(s1, -2); 94 | } 95 | translate([1*IX,0,0]) { 96 | uncNutSquareThreaded(s1, $fn=100); 97 | showName(s1, -2); 98 | } 99 | translate([2*IX,0,0]) { 100 | uncBoltHexagonalThreaded(s1, $fn=100); 101 | showName(s1, -9); 102 | } 103 | ! translate([3*IX,0,0]) { 104 | uncBoltAllenThreaded(s1, $fn=100); 105 | showName(s1, -11); 106 | } 107 | } 108 | } 109 | 110 | showParts(0); 111 | -------------------------------------------------------------------------------- /test/threads/test-unf-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: UNF thread test 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | use 15 | 16 | // ---------------------------------------- 17 | // 18 | // Showcase 19 | // 20 | // ---------------------------------------- 21 | 22 | module showName( d, z ) { 23 | %color( "gold" ) 24 | translate( [0,-7,z] ) 25 | rotate( [90,0,0] ) 26 | linear_extrude(0.1) 27 | text( screwGetName(d), halign="center", valign="center", size=2, $fn=100 ); 28 | } 29 | 30 | module showParts( part=0 ) { 31 | IX=20; 32 | color( "gold" ) 33 | translate( [50,7,-20] ) 34 | rotate( [90,0,0] ) 35 | linear_extrude(0.1) 36 | text( "UNC UNF",halign="center",valign="center",size=10,$fn=100 ); 37 | 38 | if ( part==0 ) { 39 | s1 = UNF_N0(); 40 | s2 = UNF_N5(); 41 | s3 = UNF1_4(tl=20); 42 | s4 = UNF3_8(tl=30); 43 | s5 = UNF1_2(); 44 | s6 = UNF7_8(); 45 | translate([2,0,0]) { 46 | unfNutHexagonalThreaded(s1, $fn=50); 47 | showName(s1, -2); 48 | } 49 | translate([15,0,0]) { 50 | unfNutSquareThreaded(s2, $fn=50); 51 | showName(s2, -2); 52 | } 53 | translate([30,0,0]) { 54 | unfBoltHexagonalThreaded(s3, $fn=50); 55 | showName(s3, -7); 56 | } 57 | translate([50,0,0]) { 58 | unfBoltAllenThreaded(s4, $fn=50); 59 | showName(s4, -11); 60 | } 61 | translate([70,0,0]) { 62 | unfThreadInternal(s5, $fn=50); 63 | showName(s5, -2); 64 | } 65 | translate([90,0,0]) { 66 | unfThreadExternal(unfClone(s6,16),$fn=50); 67 | showName(s6, -4); 68 | } 69 | } 70 | if ( part==1 ) { 71 | s1 = UNF1_4(tl=20); 72 | translate([0*IX,0,0]) { 73 | unfNutHexagonalThreaded(s1, $fn=50); 74 | showName(s1, -2); 75 | } 76 | translate([1*IX,0,0]) { 77 | unfNutSquareThreaded(s1, $fn=50); 78 | showName(s1, -2); 79 | } 80 | translate([2*IX,0,0]) { 81 | unfBoltHexagonalThreaded(s1, $fn=50); 82 | showName(s1, -7); 83 | } 84 | translate([3*IX,0,0]) { 85 | unfBoltAllenThreaded(s1, $fn=50); 86 | showName(s1, -9); 87 | } 88 | } 89 | if ( part==2 ) { 90 | s1 = UNF3_8(tl=20); 91 | translate([0*IX,0,0]) { 92 | unfNutHexagonalThreaded(s1, $fn=50); 93 | showName(s1, -2); 94 | } 95 | translate([1*IX,0,0]) { 96 | unfNutSquareThreaded(s1, $fn=50); 97 | showName(s1, -2); 98 | } 99 | translate([2*IX,0,0]) { 100 | unfBoltHexagonalThreaded(s1, $fn=50); 101 | showName(s1, -9); 102 | } 103 | translate([3*IX,0,0]) { 104 | unfBoltAllenThreaded(s1, $fn=50); 105 | showName(s1, -11); 106 | } 107 | } 108 | } 109 | 110 | showParts(0); 111 | -------------------------------------------------------------------------------- /things/box-pcb_HW-411_LM2596.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Box for HW411 pcb module (LM2596 DC-DC step down) 10 | * http://tpelectronic.ir/datasheets/20150123144301750.pdf 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | use 15 | use 16 | use 17 | use 18 | use 19 | use 20 | 21 | // ---------------------------------------- 22 | // Implementation 23 | // ---------------------------------------- 24 | PRECISION = 100; 25 | SEPARATION = 0; 26 | CABLE_D = 3; 27 | 28 | SCREW = M2_5(tl=16, ahd=5) ; 29 | HW411 = newPcb ( 30 | sx=44, sy=22, 31 | holes=[ 32 | [-15, +7.5, SCREW ], 33 | [+15, -7.5, SCREW ] 34 | ] 35 | ); 36 | ZIP_TIE_CABLE = newZipTie2_5(); 37 | ZIP_TIE_BOX = makeZipU(newZipTie2_5(),7.4,4); 38 | 39 | module show_parts( part=0, cut=undef, cut_rotation=undef ) { 40 | draftbox = newBoxShell ( bsz=8 ); 41 | cables = [ 42 | newCable ( CABLE_D/2, CABLE_D, c=[0,0,0], v=[+1,0,0] ) 43 | ,newCable ( CABLE_D/2, CABLE_D, c=[0,0,0], v=[-1,0,0] ) 44 | ]; 45 | box = newPcbBox ( 46 | pcb = HW411, 47 | shell = draftbox, 48 | cables = cables, 49 | cablezip = ZIP_TIE_CABLE, 50 | boxzip = ZIP_TIE_BOX, 51 | margin = nozzle(), 52 | incrustation = 3 53 | ); 54 | 55 | if ( part==0 ) { 56 | intersection () { 57 | union() { 58 | translate( [0,0,+SEPARATION] ) 59 | pcbBoxTop( box ); 60 | translate( [0,0,-SEPARATION] ) 61 | pcbBoxBottom( box ); 62 | % 63 | translate ( getPcbBoxPcbTranslation(box) ) 64 | pcbShape ( getPcbBoxPcb(box) ); 65 | } 66 | color ( "#fff",0.1 ) 67 | rotate( [0,0,is_undef(cut_rotation)?0:cut_rotation] ) 68 | translate( [-500,is_undef(cut)?-500:cut,-500] ) 69 | cube( [1000,1000,1000] ); 70 | } 71 | } 72 | 73 | if ( part==1 ) { 74 | pcbBoxBottom( box ); 75 | } 76 | if ( part==2 ) { 77 | rotate( [180,0,0] ) { 78 | pcbBoxTop( box ); 79 | } 80 | } 81 | if ( part==3 ) { 82 | translate( [0,30,0]) 83 | pcbBoxBottom( box ); 84 | translate( [0,-30,0]) 85 | rotate( [180,0,0] ) { 86 | pcbBoxTop( box ); 87 | } 88 | } 89 | } 90 | 91 | // 0: all cut to see inside 92 | // 1: bottom 93 | // 2: top 94 | // 3: top+bottom printables 95 | show_parts ( 3, 0, 0, $fn=PRECISION ); 96 | 97 | -------------------------------------------------------------------------------- /things/box-pcb_SM-GPN30E.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Box for SM-GPN30E pcb module (AC-DC power supply 30W / 5-36V) 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | use 14 | use 15 | use 16 | use 17 | use 18 | use 19 | 20 | // ---------------------------------------- 21 | // Implementation 22 | // ---------------------------------------- 23 | PRECISION = 50; 24 | SEPARATION = 0; 25 | CABLE_D = 3.5; 26 | 27 | SCREW = M3(tl=20, ahd=5) ; 28 | PCB = newPcb ( 29 | sx=100, sy=50, below=4, above=26, 30 | holes=[ 31 | [-81/2, +20, SCREW ], 32 | [-81/2, -20, SCREW ], 33 | [+81/2, -20, SCREW ], 34 | [+81/2, +20, SCREW ] 35 | ] 36 | ); 37 | ZIP_TIE_CABLE = newZipTie2_5(); 38 | 39 | module vents ( sx, sy, wt=0.8, sp=1.2 ) { 40 | int = wt+sp; 41 | nb = floor((sy-wt)/int); 42 | aw = nb*int + wt; 43 | off = (sy-aw+wt)/2; 44 | 45 | for ( i=[0:nb] ) 46 | translate( [0,-sy/2+off+i*int,500] ) { 47 | efsx = i==0 ? sx-2*int : i==nb ? sx-2*int : sx; 48 | cube( [efsx-wt,wt,1000], center=true ); 49 | translate( [-efsx/2+wt/2,0,0] ) 50 | cylinder ( r=wt/2, h=1000, center=true ); 51 | translate( [+efsx/2-wt/2,0,0] ) 52 | cylinder ( r=wt/2, h=1000, center=true ); 53 | } 54 | } 55 | 56 | module top_with_vents ( box ) { 57 | difference() { 58 | pcbBoxTop( box ); 59 | 60 | // Vent for 7N65C Mosfet heatsink 61 | translate ( [50-40,0,0] ) { 62 | translate ( [0,0,5.5] ) 63 | rotate( [90,90,0] ) 64 | vents( 16, 18 ); 65 | translate ( [0,-25+11,0] ) 66 | vents( 18, 18 ); 67 | } 68 | 69 | // Vent for MBR20100F Schottky Barrier heatsink 70 | translate ( [-50+28,0,0] ) { 71 | translate ( [0,0,5.5] ) 72 | rotate( [90,90,0] ) 73 | vents( 16, 22 ); 74 | translate ( [0,-25+12,0] ) 75 | vents( 22, 20 ); 76 | } 77 | } 78 | } 79 | 80 | module show_box() { 81 | // The draft controls the base parameters of the enclosing box shell 82 | // bsz forced to have the box joint at 10mm height, ie not in components 83 | // t forced because this is a relative big box, one more layer bot and top is better 84 | draftbox = newBoxShell ( bsz=10, t=1.2 ); 85 | cables = [ 86 | newCable ( CABLE_D/2, CABLE_D, c=[0,0,-5], v=[+1,0,0] ) 87 | ,newCable ( CABLE_D/2, CABLE_D, c=[0,0,+5], v=[-1,0,0] ) 88 | ]; 89 | box = newPcbBox ( 90 | pcb = PCB, 91 | shell = draftbox, 92 | cables = cables, 93 | cablezip = ZIP_TIE_CABLE, 94 | boxzip = undef, 95 | margin = nozzle(), 96 | incrustation = 3 97 | ); 98 | translate( [0,30,0]) 99 | pcbBoxBottom( box ); 100 | translate( [0,-30,0]) 101 | rotate( [180,0,0] ) { 102 | top_with_vents( box ); 103 | } 104 | } 105 | 106 | show_box ( $fn=PRECISION ); 107 | 108 | -------------------------------------------------------------------------------- /things/confusing-pyramid.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Not so easy pyramid puzzle 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | // ---------------------------------------- 14 | // API 15 | // ---------------------------------------- 16 | 17 | /* [Global] */ 18 | 19 | // Height of the pyramid 20 | PYRAMID_HEIGHT = 60; // [0:250] 21 | 22 | // Beveling around shapes 23 | BEVEL = 0.5; // [0:5] 24 | 25 | 26 | // ---------------------------------------- 27 | // Implementation 28 | // ---------------------------------------- 29 | 30 | /* [Hidden] */ 31 | 32 | PYRAMID_H = PYRAMID_HEIGHT-2*BEVEL; 33 | 34 | ALPHA = 2*asin( 1/(2*sin(60)) ); 35 | 36 | FACE_H = PYRAMID_H/sin(ALPHA); 37 | 38 | SIDE_L = FACE_H/sin(60); 39 | SIDE_l = SIDE_L/2; 40 | 41 | FACE_HS = SIDE_l*tan(30); 42 | FACE_HL = FACE_H-FACE_HS; 43 | 44 | PYRAMID_HS = FACE_HS*tan(ALPHA/2); 45 | PYRAMID_HL = PYRAMID_H-PYRAMID_HS; 46 | 47 | module cutter() { 48 | cut_w = PYRAMID_H*10; 49 | rotate( [-(180-ALPHA)/2,0,0] ) 50 | translate( [0,0,cut_w/2] ) 51 | cube( [cut_w,cut_w,cut_w], center=true ); 52 | } 53 | 54 | module pyramid() { 55 | // [0,0,0] is the center of the pyramid 56 | translate( [0,0,-PYRAMID_HS] ) 57 | linear_extrude ( height=PYRAMID_H, scale=0 ) 58 | polygon( [ 59 | [ 0, FACE_HL], 60 | [+SIDE_l, -FACE_HS], 61 | [-SIDE_l, -FACE_HS] 62 | ]); 63 | } 64 | 65 | module pyramidPart() { 66 | translate( [0,-PYRAMID_HS-BEVEL,PYRAMID_HS+BEVEL] ) 67 | minkowski() { 68 | difference() { 69 | pyramid(); 70 | // Beveling with minkowski adds a thickness we must remove 71 | translate( [0,-BEVEL*cos(45),-BEVEL*cos(45)] ) 72 | cutter(); 73 | } 74 | sphere(BEVEL); 75 | } 76 | } 77 | 78 | // ---------------------------------------- 79 | // Final rendering 80 | // ---------------------------------------- 81 | pyramidPart( $fn=100 ); 82 | translate( [0,PYRAMID_HL+2*BEVEL,0] ) 83 | pyramidPart( $fn=100 ); 84 | -------------------------------------------------------------------------------- /things/minecraft/creeper-lamp/cable_path_svg.scad: -------------------------------------------------------------------------------- 1 | // Generated by inkscape 1.0.2 (394de47547, 2021-03-26) + inkscape-paths2openscad 0.27 2 | // Sat May 15 21:48:06 2021 from "cable_path_svg.svg" 3 | 4 | // Module names are of the form poly_(). As a result, 5 | // you can associate a polygon in this OpenSCAD program with the corresponding 6 | // SVG element in the Inkscape document by looking for the XML element with 7 | // the attribute id="inkscape-path-id". 8 | 9 | // fudge value is used to ensure that subtracted solids are a tad taller 10 | // in the z dimension than the polygon being subtracted from. This helps 11 | // keep the resulting .stl file manifold. 12 | fudge = 0.1; 13 | user_unit_scale_x = 1.0; 14 | user_unit_scale_y = 1.0; 15 | custom_scale_x = 1; 16 | custom_scale_y = 1; 17 | zsize = 5; 18 | line_fn = 8; 19 | min_line_width = 0.20000000298023224; 20 | line_width_scale = 1.0; 21 | function min_line_mm(w) = max(min_line_width, w * line_width_scale) * 1; 22 | 23 | 24 | rect5579_0_center = [0.000000,0.000000]; 25 | rect5579_0_points = [[-145.000000,-150.000000],[145.000000,-150.000000],[145.000000,150.000000],[-145.000000,150.000000],[-145.000000,-150.000000]]; 26 | module poly_rect5579(h, w, s, res=line_fn) 27 | { 28 | scale([custom_scale_x, -custom_scale_y, 1]) union() 29 | { 30 | translate (rect5579_0_center) linear_extrude(height=h, convexity=10, scale=0.01*s) 31 | translate (-rect5579_0_center) polygon(rect5579_0_points); 32 | } 33 | } 34 | 35 | cablePathFront_0_center = [-59.500527,68.995320]; 36 | cablePathFront_0_points = [[-56.305871,123.193530],[-56.392101,110.096780],[-56.388525,108.084985],[-56.434420,105.922474],[-56.614721,103.642701],[-57.014362,101.279115],[-57.322976,100.076346],[-57.718276,98.865169],[-58.210878,97.649764],[-58.811398,96.434313],[-59.530455,95.222998],[-60.378663,94.020000],[-61.366641,92.829500],[-62.505005,91.655680],[-64.395804,89.741023],[-66.296353,87.599563],[-68.155037,85.273097],[-69.920242,82.803419],[-71.540355,80.232323],[-72.963762,77.601605],[-74.138849,74.953059],[-74.617143,73.635161],[-75.014002,72.328480],[-75.658086,69.492806],[-76.144376,66.366558],[-76.495038,62.978396],[-76.732237,59.356979],[-76.878141,55.530967],[-76.954914,51.529020],[-76.989733,43.111960],[-77.001053,27.909810],[-76.964570,26.459907],[-76.854381,25.076883],[-76.669377,23.764418],[-76.408451,22.526189],[-76.070493,21.365877],[-75.654395,20.287160],[-75.159047,19.293717],[-74.583342,18.389228],[-73.926171,17.577370],[-73.186425,16.861824],[-72.362996,16.246269],[-71.454774,15.734382],[-70.460652,15.329844],[-69.379520,15.036333],[-68.210270,14.857529],[-66.951793,14.797110],[-42.000000,14.823710]]; 37 | module poly_cablePathFront(h, w, s, res=line_fn) 38 | { 39 | scale([custom_scale_x, -custom_scale_y, 1]) union() 40 | { 41 | for (t = [0: len(cablePathFront_0_points)-2]) { 42 | hull() { 43 | translate(cablePathFront_0_points[t]) 44 | cylinder(h=h, r=w/2, $fn=res); 45 | translate(cablePathFront_0_points[t + 1]) 46 | cylinder(h=h, r=w/2, $fn=res); 47 | } 48 | } 49 | } 50 | } 51 | 52 | cableProfile_0_center = [-56.000001,131.500000]; 53 | cableProfile_0_points = [[-58.000001,134.000000],[-58.000001,129.000000],[-57.959509,128.595945],[-57.843313,128.220063],[-57.415501,127.584500],[-56.779939,127.156687],[-56.404056,127.040492],[-56.000001,127.000000],[-55.595946,127.040492],[-55.220063,127.156687],[-54.584501,127.584500],[-54.156689,128.220063],[-54.040493,128.595945],[-54.000001,129.000000],[-54.000001,134.000000],[-54.040493,134.404055],[-54.156689,134.779937],[-54.584501,135.415500],[-55.220063,135.843313],[-55.595946,135.959508],[-56.000001,136.000000],[-56.404056,135.959508],[-56.779939,135.843313],[-57.415501,135.415500],[-57.843313,134.779937],[-57.959509,134.404055],[-58.000001,134.000000],[-58.000001,134.000000]]; 54 | module poly_cableProfile(h, w, s, res=line_fn) 55 | { 56 | scale([custom_scale_x, -custom_scale_y, 1]) union() 57 | { 58 | translate (cableProfile_0_center) linear_extrude(height=h, convexity=10, scale=0.01*s) 59 | translate (-cableProfile_0_center) polygon(cableProfile_0_points); 60 | } 61 | } 62 | 63 | cablePathSide_0_center = [63.750010,31.000000]; 64 | cablePathSide_0_points = [[60.000000,140.000000],[60.138360,86.921770],[60.199281,83.467833],[60.372676,80.545805],[60.644490,78.075894],[61.000671,75.978306],[61.427165,74.173249],[61.909919,72.580930],[62.987990,69.715330],[64.323138,66.636213],[65.069395,64.844765],[65.797955,62.839241],[66.456202,60.585027],[66.991522,58.047509],[67.351299,55.192075],[67.482920,51.984110],[67.500020,-78.000001]]; 65 | module poly_cablePathSide(h, w, s, res=line_fn) 66 | { 67 | scale([custom_scale_x, -custom_scale_y, 1]) union() 68 | { 69 | for (t = [0: len(cablePathSide_0_points)-2]) { 70 | hull() { 71 | translate(cablePathSide_0_points[t]) 72 | cylinder(h=h, r=w/2, $fn=res); 73 | translate(cablePathSide_0_points[t + 1]) 74 | cylinder(h=h, r=w/2, $fn=res); 75 | } 76 | } 77 | } 78 | } 79 | 80 | module cable_path_svg(h) 81 | { 82 | difference() 83 | { 84 | union() 85 | { 86 | translate ([0,0,0]) poly_rect5579(h, min_line_mm(0.1), 100.0); 87 | translate ([0,0,0]) poly_cablePathFront(h, min_line_mm(4.0), 100.0); 88 | translate ([0,0,0]) poly_cableProfile(h, min_line_mm(4.0), 100.0); 89 | translate ([0,0,0]) poly_cablePathSide(h, min_line_mm(9.0), 100.0); 90 | } 91 | union() 92 | { 93 | } 94 | } 95 | } 96 | 97 | //cable_path_svg(zsize); 98 | -------------------------------------------------------------------------------- /things/minecraft/creeper-lamp/creeper-cable.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Minecraft Creeper Lamp - cable passage 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | use 15 | use 16 | include 17 | include 18 | 19 | 20 | /** 21 | * Cable passage 22 | */ 23 | module cablePassage() { 24 | rotate( [0,0,90] ) 25 | sweep(normalizedCableProfile, path_transforms); 26 | } 27 | 28 | /** 29 | * Cable cut to show the inside 30 | */ 31 | module cableCut() { 32 | rotate( [0,0,90] ) 33 | sweep(cutProfile, path_transforms); 34 | } 35 | 36 | cutProfile = [ 37 | [0, 0], 38 | [0, -HEAD_W], 39 | [-HEAD_W, -HEAD_W], 40 | [-HEAD_W, 0], 41 | ]; 42 | 43 | normalizedCablePathSide = [ 44 | for(pt = cablePathSide_0_points) 45 | [pt.x - 67.5, 0, 142 - pt.y] 46 | ]; 47 | normalizedCablePathFront = [ 48 | for(pt = cablePathFront_0_points) 49 | [77 + pt.x, 0, 142 - pt.y] 50 | ]; 51 | normalizedCableProfile = [ 52 | for(pt = cableProfile_0_points) 53 | [ pt.x - cableProfile_0_center.x, cableProfile_0_center.y - pt.y] 54 | ]; 55 | 56 | /** 57 | * assume line is such that: 58 | * len(list) >= 2 59 | * list[i].z <= list[i+1].z 60 | */ 61 | function indexForZ ( line, z, _i=-1 ) = 62 | _i>=len(line)-1 ? _i : 63 | line[_i+1].z >= z ? _i : 64 | indexForZ( line, z, _i+1 ) 65 | ; 66 | 67 | function interpolatey(pt0, pt1, z) = 68 | let( 69 | n = (pt1.z-pt0.z)/(z-pt0.z) 70 | ) (pt1.x-pt0.x)/n + pt0.x 71 | ; 72 | 73 | function interpolatexFromPathSide(z) = 74 | let( 75 | i = indexForZ(normalizedCablePathSide, z) 76 | ) interpolatey( normalizedCablePathSide[i], normalizedCablePathSide[i+1], z ) 77 | ; 78 | 79 | function cablePath() = [ 80 | for(pt = normalizedCablePathFront) 81 | [pt.x,interpolatexFromPathSide(pt.z),pt.z] 82 | ]; 83 | 84 | path_transforms = construct_transform_path ( cablePath() ); 85 | -------------------------------------------------------------------------------- /things/minecraft/creeper-lamp/creeper-const.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Minecraft Creeper Lamp - constants 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | SHADER_T = 1.2; 15 | 16 | CGREEN1 = "#005500"; 17 | CGREEN2 = "#00d400"; 18 | CGREEN3 = "#66ff00"; 19 | CBROWN1 = "#784212"; 20 | CBROWN2 = "#b7950b"; 21 | CBROWN3 = "#fad7a0"; 22 | CGREY = "#b3b3b3"; 23 | CBLACK = "#202020"; 24 | 25 | HEAD_W = 120; 26 | HEAD_L = HEAD_W; 27 | HEAD_H = HEAD_W; 28 | 29 | WALL_THIN = 2; 30 | WALL_THICK = 4; 31 | 32 | LED_RING_D = 50; 33 | 34 | PLUG_D = 10.5; 35 | 36 | SPRING_DEXT = 20; 37 | SPRING_DINT = SPRING_DEXT-2*1.2; 38 | SPRING_PD = LED_RING_D-2*WALL_THICK; 39 | SPRING_L = 50; 40 | SPRING_GAP = 10; 41 | SPRING_GRIP_H = (SPRING_L-SPRING_GAP)/2; 42 | 43 | BODY_H = 56; 44 | BODY_L = 64; 45 | BODY_W = 32; 46 | BODY_BDH = 16; 47 | BODY_HDH = 10; 48 | 49 | FOOT_H = 24; 50 | FOOT_L = 32; 51 | FOOT_W = 24; 52 | 53 | GROUND_H = 32; 54 | GROUND_L = 136; 55 | GROUND_W = 136; 56 | 57 | FOOT_BH = GROUND_H; 58 | BODY_BH = FOOT_BH+BODY_BDH; 59 | HEAD_BH = BODY_BH+BODY_H-BODY_HDH; 60 | 61 | LED_RING_H = HEAD_W/2; 62 | 63 | BEVEL = 0.6; 64 | 65 | // Head face selector 66 | FACE_ALL = 0; 67 | FACE_FRONT = 1; 68 | FACE_RIGHT = 2; 69 | FACE_BACK = 3; 70 | FACE_LEFT = 4; 71 | FACE_TOP = 5; 72 | -------------------------------------------------------------------------------- /things/minecraft/creeper-lamp/creeper-lib.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Minecraft Creeper Lamp - tools 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | use 15 | use 16 | use 17 | use 18 | 19 | module bevelCube( length, width=undef, height=undef, nobot=false ) { 20 | w = is_undef(width) ? length : width; 21 | th = is_undef(height) ? length : height; 22 | h = nobot ? th*2 : th; 23 | dh = nobot ? -th/2 : 0; 24 | translate( [length/2,-w/2,dh] ) 25 | bevelCutLinear(w, h, -1); 26 | translate( [-length/2,+w/2,dh] ) 27 | rotate( [0,0,180] ) 28 | bevelCutLinear(w, h, -1); 29 | translate( [+length/2,w/2,dh] ) 30 | rotate( [0,0,90] ) 31 | bevelCutLinear(length, h, -1); 32 | translate( [-length/2,-w/2,dh] ) 33 | rotate( [0,0,-90] ) 34 | bevelCutLinear(length, h, -1); 35 | translate( [0,0,0] ) 36 | rotate( [90,0,0] ) 37 | translate( [length/2,-h/2,0] ) 38 | bevelCutLinear(h, w, -1); 39 | translate( [0,0,0] ) 40 | rotate( [90,0,180] ) 41 | translate( [length/2,-h/2,0] ) 42 | bevelCutLinear(h, w, -1); 43 | } 44 | 45 | // 46 | // Extrudes polygons following vectors from points to vaninsing lines 47 | // 48 | // polygons in a plane paralel to [x,y] plane: 49 | // - polys: list of polygons of 2D (x,y) points 50 | // - polysz: z distance of polygons plane 51 | // 52 | // polygons will be extruded along vectors to vanishing lines 53 | // - width: width of the required slice between polygons plane and image plane 54 | // 55 | // vanishing lines imply scaling of polygons on image plane: 56 | // - vanishLineX: [-,y,z] position of the vanishing line parallel to x axis 57 | // - vanishLineY: [x,-,z] position of the vanishing line parallel to y axis 58 | // 59 | // for a vanishing point: 60 | // - vanishLineX: [x,y,z] position of the vanishing point 61 | // - vanishLineY: undef 62 | // 63 | module extrudePolygons ( polys, polysz, width, vanishLineX, vanishLineY=undef ) { 64 | vx = [ 0, vanishLineX.y, vanishLineX.z ]; 65 | vy = is_undef(vanishLineY) ? [ vanishLineX.x, 0, vanishLineX.z ] : [ vanishLineY.x, 0, vanishLineY.z ]; 66 | 67 | // p: polygon plane 68 | // lyp: distance from vy to polygon plane 69 | // lxp: distance from vx to polygon plane 70 | // dxp: x distance from vy to polygon point 71 | // dyp: y distance from vx to polygon point 72 | lyp = polysz - vy.z; 73 | lxp = polysz - vx.z; 74 | 75 | // i: image plane closer to [0,0,0] by slice width 76 | // lyi: distance from vy to image plane 77 | // lxi: distance from vx to image plane 78 | // dxi: x distance from vy to image point 79 | // dyi: y distance from vx to image point 80 | lyi = lyp - width; 81 | lxi = lxp - width; 82 | 83 | // rx: dxi/dxp 84 | // ry: dyi/dyp 85 | rx = lyi/lyp; 86 | ry = lxi/lxp; 87 | 88 | for ( p=polys ) 89 | let( 90 | p1 = transform(translation([0,0,polysz]),p), 91 | p2 = transform( 92 | translation([0,0,-width]) 93 | * 94 | translation(+vx) * scaling([1,ry,1]) * translation(-vx) 95 | * 96 | translation(+vy) * scaling([rx,1,1]) * translation(-vy) 97 | ,p1) 98 | ) 99 | skin( [ p2, p1 ] ); 100 | } 101 | 102 | -------------------------------------------------------------------------------- /things/office-tree-branch-beds.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Render beds for printing branches 10 | * Author: Gilles Bouissac 11 | */ 12 | 13 | use 14 | use 15 | use 16 | 17 | // ---------------------------------------- 18 | // API 19 | // ---------------------------------------- 20 | 21 | // part: bed number [0-9] 22 | // $layer: will be printed with 0.3mm layers 23 | showCase ( part=3, $fn=PRECISION, $layer=0.3 ); 24 | 25 | 26 | // ---------------------------------------- 27 | // Showcase 28 | // ---------------------------------------- 29 | PRECISION = 100; 30 | 31 | BEDS = [ 32 | [ // BED 0 33 | [ 00, [ -65, -20], 0 ], 34 | [ 44, [ 102, -42], -60 ], 35 | [ 43, [ 60, -42], -60 ], 36 | [ 42, [ 10, -42], -60 ], 37 | [ 41, [ 30, -92], 165 ], 38 | [ 40, [ 74, 27], 60 ], 39 | [ 39, [ -33, -88], 90 ], 40 | [ 38, [ -68, -51], -90 ], 41 | [ 37, [-100, -76], 90 ], 42 | [ 36, [ 98, 80], 182 ], 43 | [ 35, [ 18, 8], 75 ], 44 | [ 34, [ 15, 80], 184 ], 45 | [ 33, [ -10, 30],-170 ], 46 | [ 32, [-100, 20], 70 ], 47 | ], 48 | [ // BED 1 49 | [ 01, [ -60, -01], 0 ], 50 | [ 31, [ 19, -25], -80 ], 51 | [ 30, [ -35, -23], -80 ], 52 | [ 29, [ -95, -15], -80 ], 53 | [ 28, [ 52, 80],-170 ], 54 | [ 27, [-110, 90], -52 ], 55 | ], 56 | [ // BED 2 57 | [ 02, [ -50, -85], 30 ], 58 | [ 03, [ 50, 85],-150 ], 59 | ], 60 | [ // BED 3 61 | [ 04, [ -50, -85], 30 ], 62 | [ 05, [ 50, 85],-150 ], 63 | ], 64 | [ // BED 4 65 | [ 06, [ -40, -85], 30 ], 66 | [ 07, [ 45, 75],-150 ], 67 | ], 68 | [ // BED 5 69 | [ 08, [ -30, -90], 30 ], 70 | [ 09, [ 25, 50],-150 ], 71 | [ 26, [ 25, 85], -25 ], 72 | ], 73 | [ // BED 6 74 | [ 10, [ -22, -90], 30 ], 75 | [ 11, [ 20, 20],-150 ], 76 | [ 25, [ 22, 85], -20 ], 77 | [ 24, [ 7, 60],-177 ], 78 | ], 79 | [ // BED 7 80 | [ 12, [ -22, -85], 26 ], 81 | [ 13, [ 18, 18],-150 ], 82 | [ 23, [ 15, 70], -10 ], 83 | [ 22, [ -10, 90],-145 ], 84 | ], 85 | [ // BED 8 86 | [ 14, [ -18, -90], 26 ], 87 | [ 15, [ 10, -23],-174 ], 88 | [ 21, [ 12, 68], -10 ], 89 | [ 20, [ 27, 00], 145 ], 90 | ], 91 | [ // BED 9 92 | [ 16, [ -10, -90], 26 ], 93 | [ 17, [ 3, -30],-174 ], 94 | [ 19, [ 3, 75], -17 ], 95 | [ 18, [ 30, -8], 145 ], 96 | ], 97 | ]; 98 | 99 | BRANCH_NB = getBranchNb(); 100 | 101 | module showCase ( part ) { 102 | // Checks that: 103 | // we missed no branch 104 | // we didn't ask to print a branch twice 105 | // we didn't ask to print an unexisting branch 106 | branches = [ for ( i=[0:BRANCH_NB-1] ) i ]; 107 | declared = sortNum([ 108 | for ( bed=BEDS ) 109 | for ( b=bed ) 110 | b[0] 111 | ]); 112 | missing = [ 113 | for ( b=branches ) 114 | let( 115 | found = search ( b, declared ) 116 | ) if ( len(found)==0) b 117 | ]; 118 | if ( len(missing)>0 ) { 119 | error = str("WARNING - branches not declared in any bed: ", missing); 120 | translate( [-printVolume().x/2,printVolume().y/2+5,0] ) text( error ); 121 | } 122 | unknown = [ 123 | for ( d=declared ) 124 | let( 125 | found = search ( d, branches ) 126 | ) if ( len(found)==0) d 127 | ]; 128 | if ( len(unknown)>0 ) { 129 | error = str("WARNING - unknown branches declared: ", unknown); 130 | translate( [-printVolume().x/2,printVolume().y/2+25,0] ) text( error ); 131 | } 132 | duplicates = [ 133 | for ( b=branches ) 134 | let( 135 | found = search ( b, declared, 0 ) 136 | ) if ( len(found)>1) b 137 | ]; 138 | if ( len(duplicates)>0 ) { 139 | error = str("WARNING - duplicates branches declared: ", duplicates); 140 | translate( [-printVolume().x/2,printVolume().y/2+45,0] ) text( error ); 141 | } 142 | 143 | // Print beds for branches, sub_parts are bed numbers 144 | % translate([0,0,-1]) 145 | cube( [ printVolume().x, printVolume().y, 1 ], center=true ); 146 | 147 | // Print required bed 148 | for ( b=BEDS[part] ) 149 | translate( b[1] ) { 150 | %translate( [0,0,40] ) 151 | color( "yellow" ) 152 | text( str(b[0]), halign="center" ); 153 | rotate( [0,0,is_undef(b[2])?0:b[2]] ) 154 | branch( b[0] ); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /things/pixeled/cap.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Minecraft Pickaxe - cell caps for minecraft tool 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | use 15 | use 16 | use 17 | use 18 | use 19 | use 20 | 21 | function getMinWidth() = (nozzle()+0.1); 22 | function getCapW() = getPixelW()-2*getMinWidth()-2*getRadiusBevel(); 23 | function getCapInsert() = 2*layer(); 24 | function getCapT() = 1; 25 | 26 | function getSnapR() = getCapW()/(2*sin(45)); 27 | function getSnapH() = getPixelH()/2 - getCapInsert(); 28 | function getSnapA() = 50; 29 | 30 | function getJointQuadI() = newSnapPolygonInt ( height=getSnapH(), radius=getSnapR(), spring_w=getPixelW()/5, cutdistance=getPixelW()/3, spring_a=getSnapA(), leaves=4, springs=true ); 31 | function getJointQuadE() = newSnapPolygonExt ( source=getJointQuadI() ); 32 | function getJointElevation() = getSnapJointVGap(getJointQuadE())+mfg(); 33 | 34 | function drad() = getSnapJointSpringW(getJointQuadE())-getSnapJointHGap(getJointQuadI()); 35 | function getCapGripWidth() = getCapW() - 2*drad(); 36 | 37 | module cap() { 38 | elevation = getJointElevation(); 39 | jointI = getJointQuadI(); 40 | gap = 2*gap(); 41 | translate( [0,0,elevation] ) { 42 | intersection() { 43 | snapJoint( jointI ); 44 | translate( [0,0,-500+getSnapH()] ) 45 | cube ( [getCapW()-gap,getCapW()-gap,1000], center=true ); 46 | } 47 | } 48 | intersection() { 49 | translate( [0,0,elevation] ) 50 | snapJointShape ( jointI ); 51 | translate( [0,0,getPixelH()/2-getCapT()/2+elevation/2] ) 52 | cube ( [ getCapW()-gap, getCapW()-gap, getCapT()-elevation], center=true ); 53 | } 54 | } 55 | 56 | module capPassage() { 57 | elevation = getJointElevation(); 58 | jointE = getJointQuadE(); 59 | translate( [0,0,+elevation] ) 60 | snapJointHollow( jointE ); 61 | translate( [0,0,getPixelH()/2-getCapInsert()/2] ) 62 | cube ( [ getCapW(), getCapW(), getCapInsert()+mfg()], center=true ); 63 | } 64 | 65 | module partCaps( part_layout, colors=[[],[]] ) { 66 | hy = floor(len(part_layout)/2); 67 | hx = floor(len(part_layout[0])/2); 68 | for ( i = [0:len(part_layout)-1] ) { 69 | for ( j = [0:len(part_layout[i])-1] ) { 70 | let ( val = part_layout[i][j] ) 71 | if ( val>=0 ) { 72 | translate( [ (j-hx)*getPixelW(), (hy-i)*getPixelW(), 0 ] ) 73 | color( getCapColor(colors, val) ) 74 | if ( isCellBicolor(val) ) { 75 | cap(); 76 | rotate( [180,0,0] ) 77 | cap(); 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /things/pixeled/const.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2_21, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Minecraft Pickaxe - constants for minecraft tool 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | 15 | function getPixelW() = is_undef($pixel_w) ? 25 : $pixel_w; 16 | function getPixelH() = is_undef($pixel_h) ? 20 : $pixel_h; 17 | function getNailH() = getPixelW()/2; 18 | 19 | // Used to render all parts or subparts 20 | function ALL() = -1; 21 | 22 | // Empty value in any layout 23 | function VAL_EMPTY() = -1; 24 | 25 | // Offset in layouts to specify one color cell (ie no cap) 26 | VAL_UNICOLOR_CELL_FIRST = 000; 27 | VAL_UNICOLOR_CELL_LAST = 099; 28 | function VAL_UNICOLOR_CELL(v) = VAL_UNICOLOR_CELL_FIRST+v; 29 | function isCellUnicolor(v) = VAL_UNICOLOR_CELL_FIRST<=v && v<=VAL_UNICOLOR_CELL_LAST; 30 | 31 | // Offset in layouts to specify bi color cell (ie with colored cap) 32 | VAL_BICOLOR_CELL_FIRST = 100; 33 | VAL_BICOLOR_CELL_LAST = 199; 34 | function VAL_BICOLOR_CELL(v) = VAL_BICOLOR_CELL_FIRST+v; 35 | function isCellBicolor(v) = VAL_BICOLOR_CELL_FIRST<=v && v<=VAL_BICOLOR_CELL_LAST; 36 | 37 | // Value in nails layout to tell there is a nail 38 | function VAL_NAIL_TOP() = 8; 39 | function VAL_NAIL_LFT() = 4; 40 | function VAL_NAIL_BOT() = 2; 41 | function VAL_NAIL_RGT() = 1; 42 | 43 | // Values ordered from higher to lower 44 | function NAIL_VALS() = [ 45 | VAL_NAIL_TOP(), 46 | VAL_NAIL_LFT(), 47 | VAL_NAIL_BOT(), 48 | VAL_NAIL_RGT() 49 | ]; 50 | 51 | // Index in color mapping arrays 52 | function IDX_COLOR_CELL() = 0; 53 | function IDX_COLOR_CAP() = 1; 54 | 55 | function getLayoutColor( mapping, v, _i=0 ) = 56 | mapping[_i][0]==v ? mapping[_i][1] : 57 | _i 15 | use 16 | use 17 | use 18 | use 19 | 20 | function getNailGap() = 0.15; 21 | function getNailW() = getPixelH()/8-2*getNailGap(); 22 | function getNailProfile() = meshRegularPolygon(8, getNailW()/(2*cos(45/2))); 23 | function getNailPassageProfile() = newMesh(wrinkle(getMeshVertices(getNailProfile()), -getNailGap(), true), getMeshFaces(getNailProfile())); 24 | 25 | // Horizontal and Vertical nail never cross each other 26 | function getNailMarginH() = 0.1; 27 | function getNailMaxH() = getPixelH()/4-getNailMarginH(); 28 | function getNailVH() = [+(getNailMaxH()-getNailW()-2*layer()), -getNailMaxH()]; 29 | function getNailHH() = [-(getNailMaxH()-getNailW()-2*layer()), +getNailMaxH()]; 30 | 31 | // Index in nails layouts arrays 32 | IDX_TOP_NAILS = 0; 33 | IDX_LFT_NAILS = 1; 34 | IDX_BOT_NAILS = 2; 35 | IDX_RGT_NAILS = 3; 36 | 37 | module nail( l=getNailH() ) { 38 | rotate( [-90,0,0] ) 39 | rotate( [0,0,45/2] ) 40 | extrude( getMeshVertices(getNailProfile()), l ); 41 | } 42 | module nailPassage( l=getNailH() ) { 43 | rotate( [-90,0,0] ) 44 | rotate( [0,0,45/2] ) 45 | extrude( getMeshVertices(getNailPassageProfile()), l+2*gap() ); 46 | } 47 | module locateNailInLayer() { 48 | x = getPixelW()/2 - getNailW()/2 - 2*(nozzle()+0.1); 49 | translate ( [+x, 0, 0 ] ) 50 | children(); 51 | translate ( [-x, 0, 0 ] ) 52 | children(); 53 | } 54 | module nailPassagesLayer( l=getNailH() ) { 55 | locateNailInLayer() 56 | nailPassage(l); 57 | } 58 | module nailsLayer( l=getNailH() ) { 59 | locateNailInLayer() 60 | nail(l); 61 | } 62 | 63 | function decomposeValues ( val, values, _i=0 ) = let ( 64 | i = floor ( val / values[_i] ), 65 | r = val % values[_i], 66 | cr = concat ( [ i>0 ], _i<(len(values)-1) ? decomposeValues(r, values, _i+1) : []) 67 | ) cr; 68 | 69 | module locateNailInCell( val ) { 70 | values = decomposeValues ( val, NAIL_VALS() ); 71 | if ( values[IDX_TOP_NAILS] ) { 72 | translate ( [0, 0, getNailVH()[0] ] ) 73 | children(); 74 | translate ( [0, 0, getNailVH()[1] ] ) 75 | children(); 76 | } 77 | if ( values[IDX_LFT_NAILS] ) { 78 | translate ( [0, 0, getNailHH()[0] ] ) 79 | rotate ( [0, 0, +90] ) children(); 80 | translate ( [0, 0, getNailHH()[1] ] ) 81 | rotate ( [0, 0, +90] ) children(); 82 | } 83 | if ( values[IDX_BOT_NAILS] ) { 84 | translate ( [0, 0, getNailVH()[0] ] ) 85 | rotate ( [0, 0, 180] ) children(); 86 | translate ( [0, 0, getNailVH()[1] ] ) 87 | rotate ( [0, 0, 180] ) children(); 88 | } 89 | if ( values[IDX_RGT_NAILS] ) { 90 | translate ( [0, 0, getNailHH()[0] ] ) 91 | rotate ( [0, 0, -90] ) children(); 92 | translate ( [0, 0, getNailHH()[1] ] ) 93 | rotate ( [0, 0, -90] ) children(); 94 | } 95 | } 96 | 97 | module partNails( part_layout, nails_layout, colors=[[],[]] ) { 98 | hy = floor(len(part_layout)/2); 99 | hx = floor(len(part_layout[0])/2); 100 | for ( i = [0:len(part_layout)-1] ) { 101 | for ( j = [0:len(part_layout[i])-1] ) { 102 | let ( val = part_layout[i][j] ) 103 | if ( val>=0 ) { 104 | translate( [ (j-hx)*getPixelW(), (hy-i)*getPixelW(), 0 ] ) { 105 | color( getPixelColor(colors, val) ) 106 | locateNailInCell(nails_layout[i][j]) 107 | nailsLayer(); 108 | } 109 | } 110 | } 111 | } 112 | } 113 | 114 | module partNailPassages( part_layout, nails_layout ) { 115 | hy = floor(len(part_layout)/2); 116 | hx = floor(len(part_layout[0])/2); 117 | for ( i = [0:len(part_layout)-1] ) { 118 | for ( j = [0:len(part_layout[i])-1] ) { 119 | let ( val = part_layout[i][j] ) 120 | if ( val>=0 ) { 121 | translate( [ (j-hx)*getPixelW(), (hy-i)*getPixelW(), 0 ] ) { 122 | locateNailInCell(nails_layout[i][j]) 123 | nailPassagesLayer(); 124 | } 125 | } 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /things/pixeled/pixel.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: Minecraft Pickaxe - cells for minecraft tool 10 | * Design: Gilles Bouissac 11 | * Author: Gilles Bouissac 12 | */ 13 | 14 | use 15 | use 16 | use 17 | use 18 | 19 | use 20 | use 21 | use 22 | 23 | module unicolorCell() { 24 | cube ( [ getPixelW(), getPixelW(), getPixelH() ], center=true ); 25 | } 26 | 27 | module bicolorCell() { 28 | difference() { 29 | cube ( [ getPixelW(), getPixelW(), getPixelH() ], center=true ); 30 | 31 | rotate ( [0,0,0] ) 32 | capPassage(); 33 | rotate ( [180,0,0] ) 34 | capPassage(); 35 | 36 | cube ( [ getCapGripWidth(), getCapGripWidth(), getPixelW()], center=true ); 37 | } 38 | } 39 | 40 | module partCells( part_layout, nails_layout, colors=[[],[]] ) { 41 | hy = floor(len(part_layout)/2); 42 | hx = floor(len(part_layout[0])/2); 43 | for ( i = [0:len(part_layout)-1] ) { 44 | for ( j = [0:len(part_layout[i])-1] ) { 45 | let ( val = part_layout[i][j] ) 46 | if ( val>=0 ) { 47 | translate( [ (j-hx)*getPixelW(), (hy-i)*getPixelW(), 0 ] ) { 48 | difference() { 49 | color( getPixelColor(colors, val) ) 50 | if ( isCellUnicolor(val) ) 51 | unicolorCell(); 52 | else 53 | bicolorCell(); 54 | locateNailInCell(nails_layout[i][j]) 55 | nailPassagesLayer(); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | 63 | module bevelEdge() { 64 | BEVEL_PROFILE = [ 65 | [ +getPixelW()/2, 0 ], 66 | [ +getPixelW()/2, +getRadiusBevel() ], 67 | [ -getPixelW()/2, +getRadiusBevel() ], 68 | [ -getPixelW()/2, 0 ] 69 | ]; 70 | 71 | rotate( [-90,0,0] ) 72 | extrude(BEVEL_PROFILE, getRadiusBevel(), true, [undef, 0, getRadiusBevel()], [0, undef, -getPixelW()/2]); 73 | } 74 | 75 | module bevelCellSide() { 76 | translate( [0,-getPixelW()/2,+getPixelH()/2] ) 77 | bevelEdge(); 78 | translate( [0,-getPixelW()/2,-getPixelH()/2] ) 79 | rotate( [0,180,0] ) 80 | bevelEdge(); 81 | } 82 | 83 | module bevelCell(data, i, j) { 84 | 85 | // top cell bevel 86 | if ( i==0 || data[i-1][j]==VAL_EMPTY() ) { 87 | rotate( [0,0,180] ) 88 | bevelCellSide(); 89 | } 90 | 91 | // bottom cell bevel 92 | if ( i==len(data)-1 || data[i+1][j]==VAL_EMPTY() ) { 93 | bevelCellSide(); 94 | } 95 | 96 | // right cell bevel 97 | if ( j==len(data[i])-1 || data[i][j+1]==VAL_EMPTY() ) { 98 | rotate( [0,0,+90] ) 99 | bevelCellSide(); 100 | } 101 | 102 | // left cell bevel 103 | if ( j==0 || data[i][j-1]==VAL_EMPTY() ) { 104 | rotate( [0,0,-90] ) 105 | bevelCellSide(); 106 | } 107 | } 108 | 109 | module partBevel( part_layout, i, j) { 110 | if ( bevelActive() ) { 111 | hy = floor(len(part_layout)/2); 112 | hx = floor(len(part_layout[0])/2); 113 | for ( i = [0:len(part_layout)-1] ) 114 | for ( j = [0:len(part_layout[i])-1] ) 115 | if (part_layout[i][j]!=VAL_EMPTY()) 116 | translate( [ (j-hx)*getPixelW(), (hy-i)*getPixelW(), 0 ] ) 117 | bevelCell(part_layout, i, j); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /unc-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: UNC thread modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // API 18 | // 19 | // ---------------------------------------- 20 | 21 | // Renders an external thread (for bolts) 22 | module uncThreadExternal ( screw, l=undef, f=true ) { libThreadExternal(screw,l,f); } 23 | 24 | // Renders an internal thread (for nuts) 25 | module uncThreadInternal ( screw, l=undef, f=true, t=undef ) { libThreadInternal(screw,l,f,t); } 26 | 27 | // Nut with Hexagonal head 28 | module uncNutHexagonalThreaded( screw, bt=true, bb=true ) { libNutHexagonalThreaded(screw,bt,bb); } 29 | 30 | // Nut with Square head 31 | module uncNutSquareThreaded( screw, bt=true, bb=true ) { libNutSquareThreaded(screw,bt,bb); } 32 | 33 | // Bolt with Hexagonal head 34 | module uncBoltHexagonalThreaded( screw, bt=true, bb=true ) { libBoltHexagonalThreaded(screw,bt,bb); } 35 | 36 | // Bolt with Allen head 37 | module uncBoltAllenThreaded( screw, bt=true ) { libBoltAllenThreaded(screw,bt); } 38 | -------------------------------------------------------------------------------- /unf-thread.scad: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Gilles Bouissac 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * 9 | * Description: UNF thread modelisation 10 | * Author: Gilles Bouissac 11 | */ 12 | use 13 | use 14 | 15 | // ---------------------------------------- 16 | // 17 | // API 18 | // 19 | // ---------------------------------------- 20 | 21 | // Renders an external thread (for bolts) 22 | module unfThreadExternal ( screw, l=undef, f=true ) { libThreadExternal(screw,l,f); } 23 | 24 | // Renders an internal thread (for nuts) 25 | module unfThreadInternal ( screw, l=undef, f=true, t=undef ) { libThreadInternal(screw,l,f,t); } 26 | 27 | // Nut with Hexagonal head 28 | module unfNutHexagonalThreaded( screw, bt=true, bb=true ) { libNutHexagonalThreaded(screw,bt,bb); } 29 | 30 | // Nut with Square head 31 | module unfNutSquareThreaded( screw, bt=true, bb=true ) { libNutSquareThreaded(screw,bt,bb); } 32 | 33 | // Bolt with Hexagonal head 34 | module unfBoltHexagonalThreaded( screw, bt=true, bb=true ) { libBoltHexagonalThreaded(screw,bt,bb); } 35 | 36 | // Bolt with Allen head 37 | module unfBoltAllenThreaded( screw, bt=true ) { libBoltAllenThreaded(screw,bt); } 38 | --------------------------------------------------------------------------------