Exit Full View
Up

/Furniture/LightShadeCylindrical.foocad

LightShadeCylindrical
FooCAD Source Code
import static uk.co.nickthecoder.foocad.layout.v1.Layout2d.*
import static uk.co.nickthecoder.foocad.layout.v1.Layout3d.*

class LightShadeCylindrical : Model {

    func curved(x : double, y : double) = PolygonBuilder().apply {
        moveTo( -1, 0)
        lineTo( x, 0 )
        bezierBy( Vector2( 0, y/2 ), Vector2( 0, y/2 ), Vector2(-x, y) )
        lineTo( -1, y )
    }.build().mirrorY().also()

    static val ribbed = Circle( 10 )
    static val jagged = Square( 10 ).rotate(45).center()
    static val curved = curved( 3, 5 )
    static val flat = Square(5).center()

    @Custom( about="The diameter of the hole for the fixture" )
    var fixtureDiameter = 29

    var ripple : Shape2d = flat

    @Custom
    var piece1Size = Vector2( 100, 160 )

    @Custom
    var piece2Size = Vector2( 170, 110 )

    @Custom
    var piece3Size : Vector2 = Vector2( 200, 100 )

    @Custom
    var piece2Offset = 35

    @Custom
    var piece3Offset = -20

    val stepSize = 5

    
    @Piece
    meth piece1() = solid( piece1Size, 1 )

    @Piece
    meth piece2() = solid( piece2Size, 2 )

    @Piece
    meth piece3() = solid( piece3Size, 3 )

    
    override fun build() : Shape3d {
        val a = piece1().mirrorZ().color("Red")
        val b = piece2().mirrorZ().translateZ(-piece2Offset).color("Orange")
        val c = if (piece3Size == null) {
            Cube(0)
        } else {
            piece3().mirrorZ().translateZ(-piece2Offset - piece3Offset)
        }

        return a + b + c
    }


    meth solid( size : Vector2, pieceNumber : int ) : Shape3d {
        val main = if ( ripple == null ) {
            Circle( size.x/2 ).extrude( size.y )
        } else {
            rippleExtrude( size.x/2, size.y, ripple, pieceNumber )
        }

        val holeRadius = if (pieceNumber == 1 ) {
            fixtureDiameter/2
        } else if (pieceNumber == 3) {
            if (piece3Offset > 0) {
                piece2Size.x/2 + 1 - stepSize
            } else {
                piece1Size.x/2 + 1 - (pieceNumber-1) * stepSize
            }
        } else {
            piece1Size.x/2 +1 - (pieceNumber-1) * stepSize
        }
        val hole = Circle( holeRadius ).extrude( 300 ).translateZ(-1)
        println( "Piece $pieceNumber Hole radius = $holeRadius" )
        return main - hole
    }

    fun rippleExtrude( radius : double, height : double, ripple : Shape2d, pieceNumber : int ) : Shape3d {

        val count = height ~/ ripple.size.y
        val actualRippleHeight = height / count
        val actualRipple = ripple.scaleY( height / (ripple.size.y * count) ).frontTo(0)
        val profile = Square( radius - ripple.right, actualRipple.size.y ) +
            actualRipple.rightTo( radius )

        val completeProfile = profile.tileY( count ).toPolygon()

        val steppedProfile = if (pieceNumber == 1) {
            val first = completeProfile.transform( StepTransform2d( piece2Offset, stepSize ) )
            if (piece3Offset < 0 && piece3Size != null) {
                first.transform( StepTransform2d( piece2Offset + piece3Offset, stepSize ) )
            } else {
                first
            }
        } else if (pieceNumber == 2 && (piece3Size != null && piece3Offset > 0) ) {
            completeProfile.transform( StepTransform2d( piece3Offset, stepSize ) )
        } else {
            completeProfile
        }

        val stack = steppedProfile.revolve()
        return stack
    }

}

class StepTransform2d( val y : double, val delta : double ) : Transform2d {
    override meth transform(from: Vector2): Vector2 {

        val fromStep = y + delta - from.y

        if ( fromStep < 0 || from.x < delta ) return from

        val d = Math.min( delta, fromStep )
        return Vector2( from.x - d, from.y )
        
    }
}