/** Fill Egbert's head with compost, and grow some plants. Note, the current design leaves a hole between the body and the head due to the overhang being too big, but this doesn't affect the final result so I haven't fixed it. But if this bothers you, add a flat section, (a cylinder) so that it can use bridging before the overhang gets too big. Ahh, for the sitting poses, you'd need to hollow out the body too. Print Notes * Zero infill * Small layer height (because of overhangs). * My "Family of three" were scaled as follows : pose1 : 100% sitting1 : 66% sitting2 : 80% Post Print Fill the body and legs with sand to make it stable. I used thistle plaster instead of sand, as I had a nearly full sack spare. */ class Egbert : Model { var headRadius = 30 var headHeight = 45 var headThickness = 3 var arm1 = 8 var arm2 = 7 var arm3 = 6 var leg1 = 16 var leg2 = 14 var leg3 = 15 fun head() : Shape3d { val profile = PolygonBuilder().apply { moveTo(0,0) bezierTo( Vector2( headRadius*0.75, 0 ), Vector2( headRadius*0.9, headHeight*0.5 ), Vector2( headRadius, headHeight ) ) //circularArcTo( r-thickness, height, thickness/2, true, true ) lineTo( headRadius-headThickness, headHeight ) bezierTo( Vector2((headRadius-headThickness)*0.9, headHeight * 0.5), Vector2((headRadius-headThickness)*0.75, headThickness), Vector2(0, headThickness) ) }.build() return profile.revolve() } /** Goes *inside* Egbert's head. */ @Piece fun cup() : Shape3d { // The cup is smaller than the real head. val headRadius = this.headRadius - headThickness - 0.2 val headHeight = this.headHeight - headThickness - 0.2 val headThickness = 0.8 val extra = 10 val profile = PolygonBuilder().apply { moveTo(0,0) bezierTo( Vector2( headRadius*0.75, 0 ), Vector2( headRadius*0.9, headHeight*0.5 ), Vector2( headRadius, headHeight ) ) lineTo( headRadius + headThickness, headHeight ) lineTo( headRadius + headThickness, headHeight + extra ) lineTo( headRadius-headThickness, headHeight + extra ) lineTo( headRadius-headThickness, headHeight ) //circularArcTo( r-thickness, height, thickness/2, true, true ) lineTo( headRadius-headThickness, headHeight ) bezierTo( Vector2((headRadius-headThickness)*0.9, headHeight * 0.5), Vector2((headRadius-headThickness)*0.75, headThickness), Vector2(0, headThickness) ) }.build() return profile.revolve().mirrorZ().toOriginZ() } fun body() : Shape3d { val r1 = 30 val r2 = 13 val h1 = 20 val h2 = 60 val profile = PolygonBuilder().apply { moveTo(0,0) bezierTo( Vector2( r1*0.8, 0 ), Vector2( r1, h1*0.5 ), Vector2( r1, h1 ) ) bezierTo( Vector2( r1, h1 + h2*0.7 ), Vector2( r2, h1 + h2 ), Vector2( 0, h1 + h2 ) ) }.build() return profile.revolve() } fun arm( elbow : Vector3, hand : Vector3 ) = arm( Vector3( 17, 0, 60 ), elbow, hand ) fun arm( sholder : Vector3, elbow : Vector3, hand : Vector3 ) : Shape3d { val upper = Sphere( arm1 ).translate(sholder).hull( Sphere( arm2 ).translate( elbow ) ) val lower = Sphere( arm2 ).translate(elbow).hull( Sphere( arm3 ).translate( hand ) ) return upper + lower } fun leg( x : double, y : double, z : double ) = leg( Vector3( x, y, z ) ) fun leg( foot : Vector3 ) : Shape3d { val leg = Sphere( leg1 ).hull( Sphere( leg2 ).translate( foot ) ) val cutShoe = Sphere( leg3 ) .scaleY(1.5) / Cube( leg3 * 3 ).center().translateZ(leg3*1.3) val shoe = cutShoe.translateY( leg3 * -0.2 ) .translate( foot ).translateZ(-15) return leg + shoe } val hip = Vector3( 15, 0, 15 ) @Piece fun pose1() : Shape3d { val head = head() val body = body() val leftArm = arm( Vector3(40, -5, 44), Vector3( 26, -10, 22 ) ) val rightArm = arm( Vector3(40, 2, 80), Vector3( 27, 5, 100 ) ).mirrorX() val leftLeg = leg( 5, 4, -24).translate( hip ) val result = body + leftArm + rightArm + leftLeg.mirrorX().also() + head.translateZ(body.size.z - headThickness*2) return result .mirrorZ().toOriginZ() } @Piece fun sitting1() : Shape3d { val head = head() val body = body() val leftArm = arm( Vector3(25, -15, 44), Vector3( 10, -26, 32 ) ) val rightArm = leftArm.mirrorX() val leftLeg = leg( 5, 4, -24 ).rotateX(-90).translate( hip ) val result = body + leftArm + rightArm + leftLeg.mirrorX().also() + head.translateZ(body.size.z - headThickness*2) return (result / Cube( 200 ).centerXY().translateZ(3)) } @Piece fun sitting2() : Shape3d { val head = head() val body = body() val leftArm = arm( Vector3(30, -15, 44), Vector3( 35, -40, 30 ) ) val rightArm = arm( Vector3(35, -15, 80), Vector3( 30, -15, 110 ) ).mirrorX() val leftLeg = leg( 5, 4, -24 ).rotateX(-90).rotateZ(10).translate( hip ) val result = body + leftArm + rightArm + leftLeg.mirrorX().also() + head.translateZ(body.size.z - headThickness*2) return (result / Cube( 200 ).centerXY().translateZ(3)) } override fun build() : Shape3d { return pose1().rotateY(180).bottomTo(0) + sitting1().scale(.66).translateX(80) + sitting2().scale(.8).translateX(-80) } }