import static uk.co.nickthecoder.foocad.along.v2.Along.* /** Uses standard, old fashioned razor blades to make a knife. The blade is held in place by a tapered rod which goes through the blade's hole. The taper keeps the rod in place, but can be quickly released if you push it (e.g. with the corner of the cover!). The length and thickness of the knife are customisable, but the other dimensions are decided by the size ofthe razor blade. In the UK, this style of knife is often called a "stanley" knife (a brand name), but this version does NOT have a retractable blade, and has a simple cover instead. Print Notes. Using coloured transparent filament gives a pleasing effect (the in-fill makes nice patterns). I needed a brim. Otherwise the back end of the blade lifts up. But I replaced this by adding "ears" at the ends instead. Set the custom value or "ears" to (0,0) if you don't want the ears. */ class RazorBladeKnife : Model { // The length of the blade (ish) // Anything less that 70, and the slot begins to appear. @Custom var length = 120 @Custom var thickness = 12 // This is the size of the slot at the end of the cover. The slot is tapered, // so that the cover is wedged in place. @Custom var bladeT = 0.2 var height = 23 var roundRadius = 2 // The diameter of the middle of the slug (should be smaller than the hole // in the razor blade. var slugD = 6 var taper = 0.5 var slack = 0.5 @Custom( about="Diameter of circles which help fix the knife to the print bed" ) var ear = Vector2(30, 0.2) fun bladeProfile() : Shape2d { return PolygonBuilder().apply { moveTo( 16, 0 ) lineTo( 30, 19 ) lineTo(-30, 19 ) lineTo(-16, 0 ) }.build() - Circle( 3.5 ).translateY( 9 ) } fun coverProfile() : Shape2d { val height = this.height - roundRadius * 2 return PolygonBuilder().apply { val foo = 10 moveTo( 0, 0 ) lineTo( foo, 0 ) lineTo( foo + height*0.6, height ) lineTo( 0, height ) }.build() } fun sideProfile() : Shape2d { val height = this.height - roundRadius * 2 return PolygonBuilder().apply { moveTo( length - height*1.4, 0 ) radius( height * 0.15 ) lineTo( length - height*0.5, height * 0.2 ) lineTo( length - height*0.5, height * 0.5 ) lineTo( 49, height ) lineTo( height*0.6, height ) radius(2) lineTo(0,0) }.build() } fun frontProfile() : Shape2d { return PolygonBuilder().apply { moveTo( 0.1, 0 ) lineTo( thickness/2-roundRadius, height - roundRadius*2 ) lineTo(-thickness/2+roundRadius, height - roundRadius*2 ) lineTo(-0.1, 0 ) }.build() } fun topProfile() : Shape2d { return PolygonBuilder().apply { //radius(1) moveTo( 0, -thickness/2 + roundRadius ) lineTo( length, -0.1 ) lineTo( length, 0.1 ) lineTo( 0, thickness/2 - roundRadius ) }.build() } @Piece fun knife() : Shape3d { val extrudeFront = frontProfile().extrude( length ) .alongX2().centerY() val extrudeSide = sideProfile().extrude( height - roundRadius * 2 ) .rotateX(90).centerY() val extrudeTop = topProfile().extrude( height ) val knife = extrudeSide / extrudeFront / extrudeTop val slot = Cube( 52, 1, 20 ).centerY() .translateZ(1.5) .translateX(-2) val hole = Cylinder( thickness + 0.1, slugD/2 + taper + slack, slugD/2 - taper + slack ) .sides(16) .rotateX(90) .centerY() .translate( 17, 0, 11 ) .color("Red") val ears = Cylinder( ear.y, ear.x/2 ).translateX( length-height*1.3 ).also() return knife.minkowski( Sphere( roundRadius ).sides(10) ).bottomTo(0) - slot - hole + ears } @Piece fun slug() : Shape3d { return Cylinder( thickness * 0.7, slugD/2 + taper, slugD/2 - taper*0.7 ) .sides(16) .translateX(-5) } @Piece fun cover() : Shape3d { val extrudeFront = frontProfile().extrude( length ) .alongX2().centerY() val extrudeSide = coverProfile().extrude( height - roundRadius * 2 ) .rotateX(90).centerY() val extrudeTop = topProfile().extrude( height ) val cover = extrudeSide / extrudeFront / extrudeTop val slot = Cube( 1, bladeT, 20 ).centerY().hull(Cube(1,1,20).centerY().translateX(24)) .translateZ(1.5) return cover.minkowski( Sphere( roundRadius ).sides(10) ).bottomTo(0) - slot } override fun build() : Shape3d { return knife() + cover().rightTo( 7 ) + slug().rightTo(-20) + bladeProfile().extrude(bladeT) .rotateX(90).centerY() .translateX(17) .translateZ(2) .previewOnly() } }