/Furniture/TileCurtain.foocad

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.
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
}
}
