class WateringJug : Model { @Custom var thickness = 1.4 // The height of the jug portion. To spout is higher than this! @Custom var height = 150 // Squashes the jug. Note this will affect the wall thickness too. // If squashed < 1, then the x values are scaled (making the jug narrower) // If squashed = 1, then the jug is circular // If squahsed > 1, then the y values are scaled @Custom var squashed = 1.0 override fun build() : Shape3d { val shapes = SVGParser().parseFile( "WateringJug.svg" ).shapes // So that we can print at any scale, but still respecting the @Custom thickness // We build the jug at the "normal" size, and then scale the whole thing at the end. val scale = height / shapes["jug"].size.y val scaledThickness = thickness / scale val jugP = shapes["jug"].toOrigin().translateX(0.001) val insideP = jugP.offset( -scaledThickness ) val jug = jugP.translateX(0.1).revolve() val jugInside = insideP.revolve() + Cylinder( scaledThickness * 3, insideP.size.x ).translateZ( insideP.size.y ) + Cylinder( insideP.size.y, scaledThickness*2 ).translateZ( scaledThickness ) val spoutP = shapes["spout"].toOrigin().translateX(0.001) val spoutInsideP = spoutP.offset( -scaledThickness ) val sliceEnd = Cube( 100 ).centerXY().rotateX(-45).translateZ(spoutP.size.y-16) val sliceBase = Cube( 140 ).centerXY().translateZ(-80).rotateX(30) val spout = spoutP.revolve() - sliceEnd - sliceBase val spoutInside = spoutInsideP.revolve() - sliceBase + Cylinder( spoutInsideP.size.y, scaledThickness+1 ).translateZ( scaledThickness ) val placedSpoutInside = spoutInside.rotateX(34).translate(0,6,90) val placedSpout = spout.rotateX(34).translate(0,6,90) val radius = shapes["opening"].size.x + scaledThickness + 0.5 val rim = ( Circle(scaledThickness*1.1).translate(-scaledThickness*2,scaledThickness*3) .hull( Circle(scaledThickness/2) ) ) .translate( radius, insideP.size.y ) .revolve().color("Red") var result : Shape3d = (jug + placedSpout - jugInside - placedSpoutInside + rim) if ( squashed < 1 ) { result = result.scale(scale * squashed, scale, scale) } else { result = result.scale(scale, scale * squashed, scale) } return result // Cube(1, jugP.size.y, jugP.size.y*1.2 ).scale(scale).centerXY() } }