package uk.co.nickthecoder.foocad.woodworking.v1 class JointedPieceOfWood( val parent : PieceOfWood, val side : int, val shape : Shape2d, val depth : double, val bury : double, val along : double, val across : double ) : PieceOfWood() { override meth getSize() = parent.size meth otherEnd() = JointedPieceOfWood( parent, side, shape.mirrorX(), depth, bury, maxAlong()-along, across ) meth bothEnds() = JointedPieceOfWood( this, side, shape.mirrorX(), depth, bury, maxAlong()-along, across ) meth otherSide() = JointedPieceOfWood( parent, side, shape.mirrorY(), depth, bury, along, maxAcross()-across ) meth bothSides() = JointedPieceOfWood( this, side, shape.mirrorY(), depth, bury, along, maxAcross()-across ) /** * How deep is "shape" cut into the wood. * Note. "distance" and "depth" are synonyms. * When cutting joints, the word "depth" makes sense * But when routing grooves using the word "distance" is more appropriate. */ meth depth( depth : double ) = JointedPieceOfWood( parent, side, shape, depth, bury, along, across ) meth distance( depth : double) = JointedPieceOfWood( parent, side, shape, depth, bury, along, across ) meth depthRatio( ratio : double ) = depth( maxDepth() * ratio ) meth distanceRatio( ratio : double) = depth( maxDistance() * ratio ) /** * Moves the joint along the length of the wood. * Except when using side = END_GRAIN or START_GRAIN, in which case, * it moves the joint across (in the direction of the wood's width, rather than its length) */ meth along( along : double ) = JointedPieceOfWood( parent, side, shape, depth, bury, along, across ) meth alongRatio( ratio : double ) = JointedPieceOfWood( parent, side, shape.centerX(), depth, bury, maxAlong() * ratio, across ) /** */ meth across( across : double ) = JointedPieceOfWood( parent, side, shape, depth, bury, along, across ) meth acrossRatio( ratio : double ) = JointedPieceOfWood( parent, side, shape.centerY(), depth, bury, along, maxAcross() * ratio ) meth bury( bury : double ) = JointedPieceOfWood( parent, side, shape, depth, bury, along, across ) meth buryRatio( ratio : double ) = bury( maxDepth() * ratio ) /** * Offset is a synonym of "bury". * When cutting joints (such as a mortice), it makes sense to use the word "bury". * But when cutting grooves, the word "offset" is more appropriate. */ meth offset( bury : double ) = bury( bury ) meth offsetRatio( ratio : double ) = buryRatio( ratio ) /** * When cutting grooves, if you want to leave an equal amount uncut at both ends. * This sets the offset, and ALSO sets the distance to maxDistance() - offset * 2. */ meth equalOffsets( offset : double ) = JointedPieceOfWood( parent, side, shape, maxDistance()- offset*2, offset, along, across ) /** * Replace the shape of this joint with another. * You can (ab)use this is various ways! */ meth shape( shape : Shape2d ) = JointedPieceOfWood( parent, side, shape, depth, bury, along, across ) meth maxAlong() = maxAlong(side) meth maxAcross() = maxAcross(side) meth maxDepth() = maxDepth(side) meth maxDistance() = maxDepth(side) meth _flipShape() : Shape2d { val half = side % 3 val across = if (half == 0) { wood.width } else if (half == 1) { wood.thickness } else { wood.width } return if ( half == 1 ) { shape.mirrorY().translateY( across ) } else { shape.mirrorX().translateX( across ) } } // WithWood override meth getWood() : Wood = parent.getWood() // Lazy3d override meth build() : Shape3d { val direction = side % 3 var extruded : Shape3d = shape.offset(0.1) .extrude( depth + 0.2 ) .translateZ( -0.1 ) .margin( -0.1 ) .color( parent.color ) .translate(along, across, -bury) val toSide = if( side == Woodworking.FACE_SIDE ) { extruded.rotateX(90).rotateY(90).translate( 0, depth, parent.size.z) } else if ( side == Woodworking.OPPOSITE_SIDE ) { extruded.rotateX(-90).rotateY(90).translate( wood.width, wood.thickness - depth, parent.size.z ) } else if ( side == Woodworking.FACE_EDGE ) { extruded.rotateY(90).rotateZ(180).translate( depth, wood.thickness, parent.size.z ) } else if ( side == Woodworking.OPPOSITE_EDGE ) { extruded.rotateY(90).translate( wood.width - depth, 0, parent.size.z ) } else if ( side == Woodworking.END_GRAIN ) { extruded.translateZ( parent.size.z - depth ) } else if ( side == Woodworking.START_GRAIN ) { extruded.rotateX(180).translate( 0, wood.thickness, depth ) } else { Log.println( "Invalid side: $side. Expected 0..5 See Woodworking.FACE_SIDE etc." ) Text("").extrude(1) } return parent - toSide + Woodworking.debugCutout( toSide ) } }