Exit Full View
Up

/Christmas/Baubles.foocad

Baubles

Inspired by 3D scroll saw designs, such as the onese here : [https://bijaju54.wordpress.com/tag/free-3d-christmas-ornament-scroll-saw-patterns/]

These take quite a while to render - over 3 minutes on my crusty old laptop.

Take two profiles (Shape2d) from an SVG document. The first profile determines the general shape of the bauble. We use "revolve" to create a "solid of revolution". But rather than have a solid object we create "slices" The number of slices is given by @Custom slices.

The widths of these these slices is determined by the other profile from the SVG document. The thickness of the slices is a constant ( @Custom thickness ).

Use inkscape to edit the profiles in the SVG document to create your own shapes. Also consider combining this model with something else inside the bauble. A tiny bird for example, as it it were in a bird cage. Or maybe an intial, so each person has their own personal bauble.

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

class Baubles : Model {
    
    @Custom
    var thickness = 1.0

    @Custom
    var slices = 5

    val doc = SVGParser().parseFile( "Baubles.svg" )

    fun make( profile : Shape2d, profile2 : Shape2d ) : Shape3d {
        val outside = profile.toOrigin().translateX(0.001)
        val inside = outside.offset( -thickness ) +
            Square( thickness+0.1, outside.size.y - thickness* 2 )
                .translateY( thickness )

        val rev = (outside - inside).revolve()
        val other = profile2.toOrigin().mirrorX().also().extrude( rev.size.x )
            .rotateX(90)
            //.centerY()
            
        val slice = rev / other

        val hanger : Shape3d = hanger().translateZ(slice.size.z - 0.5)

        return slice.repeatAroundZ(slices, 360/slices) + hanger
    }

    fun hanger() = (Circle( 3 ) - Circle( 2 )).extrude(2).rotateX(90).toOriginZ().centerY()

    fun make( doc : SVGDocument, name : String ) : Shape3d {
        
        val profile = doc.shapes[ "${name}a" ]
        val thickness = doc.shapes[ "${name}b" ]
        return make( profile, thickness )
    }

    @Piece
    fun one() = make( doc, "1" )

    @Piece
    fun two() = make( doc, "2" )

    @Piece
    fun three() = make( doc, "3" )

    @Piece
    fun four() = make( doc, "4" )

    override fun build() : Shape3d {

        return make( doc, "1" ) +
            make( doc, "2" ).translateX(30) +
            make( doc, "3" ).translateY(30) +
            make( doc, "4" ).translate(30, 30, 0)
    }
}