Exit Full View
Up

/Tools/RazorBladeKnife.foocad

RazorBladeKnife
FooCAD Source Code
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()
     }
}