import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.* import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.* class LEDGroundSpike4 : Model { @Custom( about="Length of the spike" ) var length = 100 @Custom( about="Less than the internal diameter of the LED's pole") var diameter = 20.5 @Custom( about="Height of the tube above ground" ) var height = 20 @Custom( about="Thickness of the blades of the spike. Doesn't need to be as thick as topT" ) var spikeT = 2.0 @Custom var headT = 2.0 @Custom var shoulderSize = Vector2(3.0, 2.0) override fun build() : Shape3d { val foo = diameter val blade = PolygonBuilder().apply { moveTo( 0,0 ) lineBy( 0, diameter/2 ) lineBy( length - foo, 0 ) lineTo( length, 3 ) lineTo( length, 0 ) }.build().roundCorner(6,10) .extrude( spikeT ) .centerZ() // Note, the vanes are not equally spaced, giving an easier overhang. val spike = blade.rotateX(-90) + blade.rotateX(45).mirrorY().also() val cylinder = ( Circle( diameter/2 ) - Circle( diameter/2 - headT ) ).extrude(height).rotateY(-90) val r = diameter/2 - headT + spikeT/2 val gap2d = PolygonBuilder().apply { moveTo(0,0) lineTo( -r,0 ) circularArcTo( Vector2(r,0).rotate(45/180 * Math.PI), r, false, true ) }.build().offset(-spikeT/2) val gap = gap2d.extrude( 30 ).rotateY(-90).leftTo(-1) .color("Red") val shoulder = ( Circle( diameter/2 + shoulderSize.y ) ).extrude(shoulderSize.x) .bottomTo(-shoulderSize.x) .rotateY(-90) val head = cylinder + shoulder val coneLength = diameter*1.5 val cone = PolygonBuilder().apply { moveTo(0,0) lineTo( diameter/2, 0) lineTo( 0, coneLength ) }.build() .revolve(220) .rotateY(90) .leftTo(shoulder.right) val coneHole = Circle( diameter/2 - headT ).extrudeToPoint( coneLength ) .rotateY(90) .leftTo(-0.1) .color("Orange") val all = (spike + head + cone - gap - coneHole).bottomTo( -shoulderSize.y-headT/2) val result = all / Cube( length*3 ).centerXY() return result.rotateZ(90) } }