Exit Full View
ZipUp

/Furniture/TileCurtain.foocad

TileCurtain

A curtain made up of tiles on strong thread.

NOTE. The shape of the holes was tweaked to work well with a 0.6mm hotend. YMMV.

FooCAD Source Code
import uk.co.nickthecoder.foocad.extras.v1.*
import static uk.co.nickthecoder.foocad.extras.v1.Extras.*
import uk.co.nickthecoder.foocad.screws.v3.*
import uk.co.nickthecoder.foocad.threaded.v2.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
import uk.co.nickthecoder.foocad.smartextrusion.v1.*
import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.*

class TileCurtain : Model {

    @Custom
    var size = Vector3( 20, 20, 0.8 )

    @Custom
    var holeDiameter = 1.0

    @Custom
    var holeThickness = 1.2

    @Custom
    var xGap = 6.0
    
    @Custom
    var round = 2.5

    @Custom( about="For pieces `mount` and `mountCurved`" )
    var mountColumns = 2//8

    @Custom( about="Only used for piece `mountCurved`" )
    var mountRadius = 200

    @Custom
    var holeAngle = 15

    @Custom
    var angleStart = 0.4

    meth hole() : Shape3d {
        val plain = (Square( holeDiameter + holeThickness*2, holeDiameter + holeThickness )
                .roundCorner(3,1)
                .roundCorner(2,1)
                .centerX() -
            Square( holeDiameter, holeDiameter+0.2 ).centerX().roundCorners(listOf<int>(2,3),holeDiameter/2-0.1,1)
        ).extrude( size.y )
            .rotateX(90)
            .centerXTo( size.x/4 + xGap/4 )
            .centerY()

        val chamfer = Cube(10).centerXTo( plain.middle.x )
            .rotateX( holeAngle )
            .translateY( plain.back )
            .translateZ( angleStart )
            .mirrorY().also()

        return plain - chamfer
    }

    @Piece
    meth tile() : Shape3d {
        val tile = Square( size.x, size.y )
            .center()
            .roundAllCorners( round )
            .smartExtrude(size.z)
            .bottom( Chamfer( size.z/2 ) )

        val holes = hole()            
            .bottomTo( tile.top )
            .mirrorX().also()

        return tile + holes
    }

    @Piece
    meth endTile() : Shape3d {
        val tile = Square( size.x *1.5 + xGap*0.5, size.y )
            .center()
            .roundAllCorners( round )
            .smartExtrude(size.z)
            .bottom( Chamfer( size.z/2 ) )

        val hole = hole()
            .bottomTo( tile.top )
        val threeHoles = hole
            .repeatX(3, size.x /2 + xGap/2 ).centerX()
        val extraHole = hole.rightTo( threeHoles.right - hole.size.x + holeThickness )

        return tile + threeHoles + extraHole
    }


    @Piece
    meth tileWithHole() : Shape3d {
        val plain = tile()
        return plain - Cylinder(plain.size.z + 0.2, 4).bottomTo(-0.1)
    }


    @Piece
    meth endTileWithHole() : Shape3d {
        val plain = endTile()
        return plain - 
            Cylinder(plain.size.z + 0.2, 4).bottomTo(-0.1)
                .centerXTo( -size.x/2 + xGap/2 )
    }

    meth lockThread() = Thread(6).rodChamfer(0.7)

    var mountSize = Vector2( 12, 10 )

    @Piece
    meth mount() : Shape3d {

        val block = Square( (size.x + xGap) * mountColumns - xGap, mountSize.x ).center()
            .smartExtrude( mountSize.y )
            .top( Chamfer(1) )

        val holes = Square( holeDiameter*2 ).center()
            .extrude( block.size.z*1.6 )
            .rotateX(45)
            .frontTo(block.middle.y - 3)
            .repeatX( mountColumns * 2, (size.x + xGap)/2 )
            .centerX()
            .color("Red")

        val lockHoles = lockThread()
            .threadedHole( block.size.z -0.2 )
                .chamferStart(false)
            .bottomTo(0.4)
            .repeatX( mountColumns, size.x + xGap )
            .centerX()
            .color("Red")

        val screwHoles = Countersink()
            .topTo( block.top )
            .repeatX( mountColumns -1, (size.x + xGap) ).centerX()

        return block - holes - lockHoles - screwHoles
    }


    @Piece
    meth mountCurved() : Shape3d {
        val outer = Circle( mountRadius )
        val inner = outer.offset( - mountSize.x )
        val mid = -mountRadius + mountSize.x/2

        val anglePer = 306 / ((Math.PI * mountRadius)/(size.x + xGap))

        val fromAngle =  -90 - anglePer * mountColumns/2
        val toAngle = -90 + anglePer * mountColumns/2
        val block = CircularArc( mountRadius, mountRadius-mountSize.x, fromAngle, toAngle)
            .smartExtrude( mountSize.y )
            .top( Chamfer(1) )

        val holes = Square( holeDiameter*2 ).center()
            .extrude( block.size.z*1.6 )
            .rotateX(-45)
            .backTo(mid + 3)
            .repeatAroundZ( mountColumns * 2, anglePer/2 ).rotateZ( -(mountColumns-0.5) * anglePer/2 )
            .color("Red")

        val lockHoles = lockThread()
            .threadedHole( block.size.z -0.2 )
                .chamferStart(false)
            .bottomTo(0.2)
            .translateY( mid )
            .repeatAroundZ( mountColumns, anglePer ).rotateZ( -(mountColumns/2-0.5) * anglePer )
            
        val screwHoles = Countersink()
            .topTo( block.top )
            .translateY( mid )
            .repeatAroundZ( mountColumns-1, anglePer ).rotateZ( -(mountColumns/2-1) * anglePer )
            .color("Green")

        return block - holes - lockHoles - screwHoles
    }

    @Piece
    meth lockBolt() = lockThread().bolt(mountSize.y-0.8) - Cube( 10, 1, 1 ).centerXY().rotateZ(30)

    @Piece( print="tile" )
    override fun build() : Shape3d {
        val across = 15
        val down = 4
        val yGap = 1.2

        val a = tile().rotateX(-90).color("Orange")
        val b = tile().rotateX(-90).bottomTo(a.top).leftTo( a.middle.x + xGap/2 ).color("Yellow")

        val aRow = a.repeatX(across,size.x + xGap)
        val bRow = b.repeatX(across,size.x + xGap).bottomTo(aRow.top+yGap)

        val endA = endTile().rotateX(-90).color("Orange").rightTo( bRow.right )
        val endB = endTile().rotateX(-90).color("Yellow").bottomTo(bRow.bottom).leftTo( aRow.left )

        val twoRows = aRow + bRow + endA + endB

        return twoRows.tileZ(down, yGap)
    }

    @Piece
    meth vertical() : Shape3d {
        val yGap = 1
        val zCount = 4
        val xCount = 4

        val tile = tile().rotateX(-90)
        val endTile = endTile().mirrorX().rotateX(-90).leftTo(tile.left)

        val leftColumn = (endTile + tile.bottomTo( endTile.top + yGap ))
            .tileZ(zCount,yGap)
            .bottomTo(0)

        val midColumn = (
                tile.bottomTo( size.y + yGap ).centerXTo( size.x + xGap ) +
                tile.leftTo( endTile.right + xGap ).bottomTo(0)
            ).tileZ(zCount,yGap)


        val middleColumns = (midColumn.color("Green") + midColumn.translateX(size.x+xGap))
            .repeatX( xCount, (size.x + xGap)*2 )

        val rightColumn = (endTile.rightTo(tile.right).bottomTo( endTile.top + yGap ) + tile)
            .tileZ(zCount,yGap)
            .bottomTo(0)
            .leftTo( middleColumns.right - size.x/2 + xGap /2 )
            .color("Green")

        return leftColumn + middleColumns + rightColumn
    }


    @Piece
    meth vertical2() : Shape3d {
        val yGap = 1
        val zCount = 4
        val xCount = 4

        val tile = tile().rotateX(-90)
        val endTile = endTile().mirrorX().rotateX(-90).leftTo(tile.left)

        val leftColumn = (endTile + tile.bottomTo( endTile.top + yGap ))
            .tileZ(zCount,yGap)
            .bottomTo(0)

        val midColumn = (
                tile.bottomTo( size.y + yGap ).centerXTo( size.x + xGap ).tileX(2, xGap) +
                tile.leftTo( endTile.right + xGap ).bottomTo(0)
            ).tileZ(zCount,yGap)


        val middleColumns = (
                midColumn.color("Green") +
                midColumn.mirrorZ().bottomTo(0).leftTo( leftColumn.right + size.x + xGap*2 )
            )
            .repeatX( xCount, (size.x + xGap)*3 )

        val rightColumn = (endTile.rightTo(tile.right).bottomTo( endTile.top + yGap ) + tile)
            .tileZ(zCount,yGap)
            .bottomTo(0)
            .leftTo( middleColumns.right - size.x/2 + xGap /2 )
            .color("Green")

        return leftColumn + middleColumns + rightColumn
    }

}