Exit Full View
Up

/Games/Sphericon.foocad

Sphericon

Inspired by Maker's Muse

Solid which roll in weird ways! The simplest if a bi-cone, (two cones with attached at their bases). This bi-cone is then sliced down the middle, and the two pieces rotated by 90 degrees.

Note, this is NOT how the shapes are constructed, but is simple explaination of their shape. They are constructed by building the 2D cross section of the sliced bi-cone, and the revolving that cross section through 180 degrees to form half of the solid.

The basic cross section shape (square for sides=4, hexagon for sides=6 etc) can be extended by adding extra bits to each vertex. See @Custom extend.

Unlike Maker's Muse, I have made the connecting pieces circluar (his were polygonal). This allows me to twist the two halves into place, and must be carefully aligned. You may find the pieces rotate too easily, in which case, damage the surface of the ring. I used a pair of wire cutters to make lots of diagonal marks. If you prefer the polygonal approach look for the comments in the groove and ring parts.

Note, you can glue the ring into one of the halves if you want.

Notes

The ring is optional. You could permanently glue the two halves together.

The distribution of mass isn't the same as a perfectly solid object. The "join" will have more mass, as there are solid layers there. The ring and grooves will also affect the mass distribution further. I'm not sure how these impact on the rolling, but I think it may cause it to speed up and slow down, because in some directions of travel there will be a larger angular momentum than in other directions when the object is travelling at the same linear speed.

To understand this, just consider the ring, and imagine it is MUCH denser than the main parts (whereas in reality, it is only slightly denser). The angular momentum will be different when the ring is spinning about its axis, compared to when it is spinning at 90 degrees to its axis (I think). Maths hard! To test this, make the ring out of metal, preferably lead.

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

class Sphericon : Model {
    
    // The "radius" of the solid. The distan
    @Custom
    var size = 30

    @Custom
    var extend = 4

    // Must be an even number >= 4
    @Custom
    var sides = 6

    @Custom
    var round = 5.0

    @Custom
    var ringHeight = 20

    // We need an "interferance" fit between the ring and the main part.
    // Adjust this, and re-print the ring until it is just right.
    // The better your printer, the smaller the slack ;-)
    // If it is too loose, damage the surfaces e.g. stab it with a knife, 
    // without stabbing yourself!
    @Custom
    var slack = 0.2

    // DO you want a circular ring, or a polygon?
    @Custom
    var circularRing = true

    @Piece
    fun main() : Shape3d {

        val rotation = if ((sides % 4) == 0) 0 else 180/sides

        var plain : Shape2d = Circle( size ).sides(sides).rotate(rotation)
        if ( extend <= 0 ) {
            plain = plain.roundAllCorners(round)
        }

        var profile = plain

        if ( extend > 0 && round > 0) {
            val extension = Circle( round ).translateX(size + extend) +
                Square( size + extend, round*2 ).centerY()
            profile = profile + extension.rotate(rotation).repeatAround( sides )
        }

        val halfP = profile / Square( (size + extend)*3 ).centerY()

        val half = halfP.revolve(180).rotateX(90)

        val scale = if (sides == 4) 0.4 else 0.5
        val groove = if (circularRing) {
            Circle( size*scale ).internalChamferedExtrude( ringHeight/2, 1, 0 )
        } else {
            Circle( size*(scale-0.1) ).sides( sides ).internalChamferedExtrude( ringHeight/2, 1, 0 )
        }

        return half - groove
    }

    // This used to be a ring, but I changed it to a solid.
    // Use a low infill (or even zero!)
    @Piece
    fun ring() : Shape3d {
        val scale = if (sides == 4) 0.4 else 0.5
        val ring = if (circularRing) {
            Circle( size*scale - slack ).chamferedExtrude( ringHeight - 1, 0.5 ) //-
        } else {
            Circle( size*(scale-0.1) - slack ).sides(sides).chamferedExtrude( ringHeight - 2*slack, 0.5 ) // -
        }

        return ring.color("Green")
    }

    @Piece
    fun inspect() = (main() + ring().center() ) / (
       Cube( 1, 100, 100 ).center() +
       Cube( 100, 1, 100 ).center()
   )

    override fun build() : Shape3d {
        val main : Shape3d = main()
        val ring : Shape3d = ring()
        return main.tileY(2,2) +
            ring.translateY(-ring.size.y/2 - main.size.y/2- 2)
    }

}