/Garden/AntiBirdSpikes.foocad

Add nails (or pointed plastic spikes) to stop birds perching on the top of the bird table's roof.
Needs a brim/ears for good bed adhesion.
import uk.co.nickthecoder.foocad.smartextrusion.v1.*
import static uk.co.nickthecoder.foocad.smartextrusion.v1.SmartExtrusion.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*
class AntiBirdSpikes : Model {
@Custom
var roofRidgeSize = Vector3( 161, 20, 3.0 ) //Vector3(50,20,3.0)
@Custom
var chairBackSize = Vector3( 210, 10, 20 )
@Custom
var chairBackGap = 4
@Custom
var nailRidgeSize = Vector2( 5, 2 )
@Custom
var holeEvery = 7
@Custom
var angle = 90
@Custom
var headDiameter = 5.0
@Custom
var nailDiameter = 2.0
@Slice( brimWidth=5 )
@Piece
meth withNail() : Shape3d {
var halfAngleRadians = Math.PI/180 * angle/2
val triangle = PolygonBuilder().apply {
val x = roofRidgeSize.y * Math.sin( halfAngleRadians )
val y = roofRidgeSize.y * Math.cos( halfAngleRadians )
moveTo( -x, 0 )
lineTo( x, 0 )
lineTo( 0, y )
}.build()
val ridge = Square( nailRidgeSize.x, triangle.back + nailRidgeSize.y ).centerX()
.roundAllCorners(1,1)
val solid = (triangle + ridge)
.extrude(roofRidgeSize.x).rotateX(90)
.centerY()
val remove = triangle.translateY(-roofRidgeSize.z / Math.sin( halfAngleRadians ))
.extrude(roofRidgeSize.x+0.02).rotateX(90)
.centerY()
val hole = (
Cylinder( 10, headDiameter/2 ).topTo(remove.top) +
Cylinder( 20, nailDiameter/2 ).bottomTo(remove.top+0.2)
).color("Red")
val holes = hole.repeatY( roofRidgeSize.x / holeEvery, holeEvery).centerY()
val attachmentHoles = Cylinder( 50, nailDiameter/2 )
.rotateY( angle/2 )
.translateX( remove.right - roofRidgeSize.z *2 -2 )
.frontTo( solid.front + 10 )
.mirrorX().also().mirrorY().also()
return solid - remove - holes - attachmentHoles
}
var plasticRidgeSize = Vector2( 14, 5 )
var plasticRidgeSpacing = 6
meth plasticRidge( length : double, height : double ) : Shape3d {
val ridgePiece = Square( plasticRidgeSize.x, height )
.roundCorners( listOf<int>(3,2), plasticRidgeSize.x/2, 1 )
.scaleX(0.5)
.extrude(1.2)
.rotateX(90).centerXY()
.rotateZ(90).rotateZ(90).translateZ(-2).also(2)
return ridgePiece
.translate( 0, plasticRidgeSpacing, plasticRidgeSize.y/2 ).also()
.repeatY( length / plasticRidgeSpacing/2, plasticRidgeSpacing*2 )
.centerXY()
}
@Slice( brimWidth=5 )
@Piece
meth plastic() : Shape3d {
var halfAngleRadians = Math.PI/180 * angle/2
val triangle = PolygonBuilder().apply {
val x = roofRidgeSize.y * Math.sin( halfAngleRadians )
val y = roofRidgeSize.y * Math.cos( halfAngleRadians )
moveTo( -x, 0 )
lineTo( x, 0 )
lineTo( 0, y )
}.build()
val solid = triangle
.extrude(roofRidgeSize.x).rotateX(90)
.centerY()
val remove = triangle.translateY(-roofRidgeSize.z / Math.sin( halfAngleRadians ))
.extrude(roofRidgeSize.x+0.02).rotateX(90)
.centerY()
val ridge = plasticRidge( roofRidgeSize.x, solid.top + plasticRidgeSize.y )
val attachmentHoles = Cylinder( 50, nailDiameter/2 )
.rotateY( angle/2 )
.translateX( remove.right - roofRidgeSize.z *2 -2 )
.frontTo( solid.front + 10 )
.mirrorX().also().mirrorY().also()
return solid + ridge - remove - attachmentHoles
}
@Piece
meth chairBack() : Shape3d {
val solid = Square( chairBackSize.y, chairBackSize.z ).centerX()
.roundCorners(listOf<int>(3,2),chairBackSize.y/2 )
.extrude(chairBackSize.x).rotateX(90)
.centerY()
val remove = Square( chairBackGap, chairBackSize.z ).centerX()
.roundCorners(listOf<int>(3,2),1,1 )
.backTo( solid.top - 4 )
.extrude( chairBackSize.x + 0.02 ).rotateX(90)
.centerY()
val ridge = plasticRidge( chairBackSize.x-1, solid.top+2.5 )
return solid + ridge - remove
}
@Piece( print="withNail" )
override fun build() : Shape3d {
return withNail()
}
}
