kcl-samples → car-wheel

car-wheel

car-wheel

KCL

// Car Wheel
// A sports car wheel with a circular lug pattern and spokes.


// Define constants
// Base units for this model are in inches
const lugCount = 5
const lugSpacing = 114.3 * mm()
const offset = -35 * mm()
const backSpacing = 6.38
const wheelWidth = 9.5
const wheelDiameter = 19

const spokeGap = 0.2
const spokeAngle = 0.02
const spokeThickness = 0.95

// Create the wheel center
const lugBase = startSketchOn('XZ')
  |> circle({
       center: [0, 0],
       radius: (lugSpacing + 1.5) / 2
     }, %)
  |> hole(circle({
       center: [0, 0],
       radius: (lugSpacing - 1.5) / 2
     }, %), %)
  |> extrude(wheelWidth / 20, %)

// Extend the wheel center and bore holes to accomidate the lug heads
const lugExtrusion = startSketchOn(lugBase, 'END')
  |> circle({
       center: [0, 0],
       radius: (lugSpacing + 1.5) / 2
     }, %)
  |> hole(circle({
       center: [0, 0],
       radius: (lugSpacing - 1.5) / 2
     }, %), %)
  |> extrude(wheelWidth / 10, %)

// Create the circular pattern for the lugs
const lugClearance = startSketchOn(lugExtrusion, 'END')
  |> circle({
       center: [lugSpacing / 2, 0],
       radius: 1.2 / 2
     }, %)
  |> patternCircular2d({
       arcDegrees: 360,
       center: [0, 0],
       repetitions: lugCount - 1,
       rotateDuplicates: true
     }, %)
  |> extrude(-wheelWidth / 10, %)

// Create the circular pattern for the lug holes
const lugHoles = startSketchOn(lugBase, 'END')
  |> circle({
       center: [lugSpacing / 2, 0],
       radius: 16 * mm() / 2
     }, %)
  |> patternCircular2d({
       arcDegrees: 360,
       center: [0, 0],
       repetitions: lugCount - 1,
       rotateDuplicates: true
     }, %)
  |> extrude(-wheelWidth / 20, %)

// Add detail to the wheel center by revolving curved edge profiles
const wheelCenterInner = startSketchOn('XY')
  |> startProfileAt([(lugSpacing - 1.5) / 2, 0], %)
  |> yLine(-wheelWidth / 10 - (wheelWidth / 20), %)
  |> bezierCurve({
       to: [-0.4, 0.3],
       control1: [-0.3, 0],
       control2: [0, 0.3]
     }, %)
  |> yLineTo(0, %)
  |> lineTo([profileStartX(%), profileStartY(%)], %)
  |> close(%)
  |> revolve({ axis: 'y' }, %)

const wheelCenterOuter = startSketchOn('XY')
  |> startProfileAt([(lugSpacing + 1.5) / 2, 0], %)
  |> yLine(-wheelWidth / 10 - (wheelWidth / 20), %)
  |> bezierCurve({
       to: [0.4, -0.1],
       control1: [0.3, 0],
       control2: [0.2, -0.3]
     }, %)
  |> yLineTo(-wheelWidth / 20, %)
  |> lineTo([profileStartX(%), profileStartY(%)], %)
  |> close(%)
  |> revolve({ axis: 'y' }, %)

// Write a function that defines the spoke geometry, patterns and extrudes it
fn spoke = (spokeGap, spokeAngle, spokeThickness) => {
  // Seperating the spoke base planes
  const plane001 = {
    plane: {
      origin: [0.0, 0.0, spokeGap / 2],
      xAxis: [1.0, 0.0, spokeAngle],
      yAxis: [0.0, 1.0, 0.0],
      zAxis: [0.0, 0.0, 1.0]
    }
  }

  // Spoke cross sections
  const spokeProfile = startSketchOn(plane001)
    |> startProfileAt([(lugSpacing + 2) / 2, -0.7], %)
    |> bezierCurve({
         to: [
           (wheelDiameter - lugSpacing - 2.9) / 2,
           offset
         ],
         control1: [
           (wheelDiameter - lugSpacing - 2.9) / 3.5,
           offset / 7
         ],
         control2: [
           (wheelDiameter - lugSpacing - 2.9) / 4,
           offset / 1.5
         ]
       }, %)
    |> yLine(-wheelWidth / 15, %)
    |> bezierCurve({
         to: [
           -(wheelDiameter - lugSpacing - 2.9) / 2,
           -offset
         ],
         control1: [
           -(wheelDiameter - lugSpacing - 2.9) / 5,
           -offset / 7
         ],
         control2: [
           -(wheelDiameter - lugSpacing - 2.9) / 5,
           -offset / 1.5
         ]
       }, %)
    |> lineTo([profileStartX(%), profileStartY(%)], %)
    |> close(%)

  // Circular pattern spokes
  const spokePattern = extrude(spokeThickness, spokeProfile)
    |> patternCircular3d({
         axis: [0, 1, 0],
         center: [0, -2000, 0],
         repetitions: 5,
         arcDegrees: 360,
         rotateDuplicates: true
       }, %)

  return spokePattern
}

spoke(spokeGap, spokeAngle, spokeThickness)
spoke(-spokeGap, -spokeAngle, -spokeThickness)

// Define and revolve wheel exterior
const wheelOuterRevolve = startSketchOn('XY')
  |> startProfileAt([
       wheelDiameter / 2,
       -wheelWidth + backSpacing + offset
     ], %)
  |> yLine(wheelWidth * 0.25, %)
  |> line([-wheelWidth * 0.02, wheelWidth * 0.02], %)
  |> yLine(wheelWidth * 0.25, %)
  |> line([wheelWidth * 0.02, wheelWidth * 0.02], %)
  |> yLineTo(backSpacing + offset, %)
  |> line([wheelWidth * 0.05, wheelWidth * .01], %)
  |> yLine(wheelWidth * 0.05, %)
  |> xLine(-wheelWidth * 0.03, %)
  |> yLine(-wheelWidth * 0.02, %)
  |> line([-wheelWidth * 0.05, -wheelWidth * 0.01], %)
  |> yLine(-backSpacing * 0.7, %)
  |> line([
       -wheelDiameter * 0.01,
       -wheelWidth * 0.02
     ], %)
  |> yLineTo(offset - 0.2, %)
  |> line([
       -wheelDiameter * 0.03,
       -wheelWidth * 0.02
     ], %)
  |> yLine(-wheelWidth * 0.02, %)
  |> line([
       wheelDiameter * 0.03,
       -wheelWidth * 0.1
     ], %)
  |> yLine(-wheelWidth * 0.05, %)
  |> line([wheelWidth * 0.02, -wheelWidth * 0.02], %)
  |> yLineTo(-wheelWidth + backSpacing + offset - 0.28, %)
  |> line([wheelWidth * 0.05, -wheelWidth * 0.01], %)
  |> yLine(-wheelWidth * 0.02, %)
  |> xLine(wheelWidth * 0.03, %)
  |> yLine(wheelWidth * 0.05, %)
  |> close(%)
  |> revolve({ axis: 'y' }, %)