// Cycloidal Gear
// A cycloidal gear is a gear with a continuous, curved tooth profile. They are used in watchmaking and high precision robotics actuation

// Set units
@settings(defaultLengthUnit = in, kclVersion = 1.0)

// Create a function for the cycloidal gear
fn cycloidalGear(gearPitch, gearHeight, holeDiameter, helixAngle: number(deg)) {
  // Create a function to draw the gear profile as a sketch. Rotate each profile about the gear's axis by an helix angle proportional to the total gear height
  fn gearSketch(@gHeight) {
    helixAngleP = helixAngle * gHeight / gearHeight
    gearProfile = startSketchOn(offsetPlane(XY, offset = gHeight))
      |> startProfile(at = [
           gearPitch * 1.55 * cos(helixAngleP) + gearPitch * sin(-helixAngleP),
           gearPitch * 1.55 * sin(helixAngleP) + gearPitch * cos(-helixAngleP)
         ])
      |> arc(angleStart = 90 + helixAngleP, angleEnd = -90 + helixAngleP, radius = gearPitch)
      |> tangentialArc(radius = gearPitch * 1.67, angle = 60)
      |> tangentialArc(radius = gearPitch, angle = -180)
      |> tangentialArc(radius = gearPitch * 1.67, angle = 60)
      |> tangentialArc(radius = gearPitch, angle = -180)
      |> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
      |> close(%)
      |> subtract2d(tool = circle(center = [0, 0], radius = holeDiameter / 2))
    return gearProfile
  }

  // Draw sketches of the gear profile along the gear height and loft them together
  gearLoft = loft([
    gearSketch(0),
    gearSketch(gearHeight / 2),
    gearSketch(gearHeight)
  ])

  return gearLoft
}

// Call the cycloidal gear function
cycloidalGear(
  gearPitch = .3,
  gearHeight = 1.5,
  holeDiameter = 0.297,
  helixAngle = -80,
)
