class Egbert : AbstractModel() { 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)) } @Piece( printable = false ) override fun build() : Shape3d { return pose1().rotateY(180).bottomTo(0) + sitting1().scale(.66).translateX(80) + sitting2().scale(.8).translateX(-80) } }