import static uk.co.nickthecoder.foocad.arrange.v1.Arrange.* import static uk.co.nickthecoder.foocad.chamferedextrude.v1.ChamferedExtrude.* class WireTwistTidy : Model { var size = Vector2( 50, 10 ) var thickness = 2 var innerThickness = 1 var lipThickness = 1.5 var clearance = 0.3 var slack = 0.9 var recess = 6 val wireD = 3 var overhang = 3 fun yin(radius : double) : Shape2d { val part = PolygonBuilder().apply { moveTo( -radius, 0 ) lineTo( -radius, wireD / 2 ) circularArcTo( Vector2( -wireD/2, radius ), radius, false, false ) lineTo( -wireD/2, -radius * 0.3 ) bezierTo( Vector2( 0, -radius ), Vector2( -radius, -radius*0.9 ), Vector2( -radius, 0 ) ) }.build() val topSemi = Circle( radius ) intersection Square( radius *2, radius ).centerX() val foo = part + topSemi - part.rotate(180).offset( wireD ) return foo } @Piece fun inner() : Shape3d { val radius = size.x / 2 - recess val yin = yin(radius) val largeHollow = yin - yin.offset( -innerThickness ) val smallHollow = yin.offset(-innerThickness - clearance ) - yin.offset( -2*innerThickness - clearance ) val height = size.y - lipThickness * 2 val circle = Circle( size.x / 2 ) val flats = Square( overhang + slack, circle.size.y*3 ).center() .rightTo( circle.right ) .rotate(-45) .rotate(180).also() val holes = yin.offset( -2*innerThickness - clearance ) + yin.offset( -innerThickness ).rotate(180) val lip = (circle - flats - holes).extrude(lipThickness) val left = ( (yin-yin.offset(-innerThickness - clearance)).extrude( wireD ) + smallHollow.extrude( height + lipThickness ) ) .color("Green") val right = largeHollow.rotate(180) .extrude( height - wireD - clearance ) .color("Orange") return lip + (left + right).bottomTo(lip.top) } @Piece fun inner2() = inner().mirrorY() @Piece fun inner2Alternate() : Shape3d { val inner = inner() val radius = size.x / 2 - recess val yin = yin(radius).offset( wireD ) val valley = yin intersection yin.rotate(180).toPolygon() val straight = Square( 100, wireD ).backTo( -valley.front ) .rotate(-8) .leftTo( size.x *0.2 ) .rotate(180).also() val remove = ( valley + straight ).extrude( lipThickness + 0.2 ).bottomTo( -0.1) return (inner - remove).mirrorY() } @Piece fun outer() : Shape3d { val innerR = size.x / 2 + slack val largeCircle = Circle( innerR + thickness ) val base = largeCircle.chamferedExtrude(lipThickness, lipThickness/2, 0) val sides = (Circle( innerR + thickness ) - Circle( innerR )) .extrude( size.y + slack ) .bottomTo( base.top ) val slots = Square( wireD * 1.2, base.size.x*2 ) .leftTo( -innerR ) .backTo(0) .extrude( size.y/2+wireD/2 ) .topTo( sides.top +0.1 ) .rotateZ(180).also() val overhang = (largeCircle - Square( 100, size.x - overhang*2 ).center()) .chamferedExtrude( lipThickness, 0, lipThickness/2 ) .bottomTo( sides.top ) return base + sides - slots + overhang } @Piece fun all() : Shape3d { return arrangeX( 2, inner(), inner2Alternate(), outer() ) } override fun build() : Shape3d { val inner = inner().color("Yellow") val inner2 = inner2().rotateY(180).topTo( size.y ).color("Green") val outer = outer().bottomTo( - lipThickness ) return inner + inner2 + outer.previewOnly() } }