// Sash Window // A traditional wooden sash window with two vertically sliding panels and a central locking mechanism // Set units in millimeters (mm) @settings(defaultLengthUnit = mm, kclVersion = 1.0) // Window state: 0 for closed, 1 for open windowState = 0 // Basic window dimensions windowWidth = 500 windowHeight = 1000 // Frame thickness and depth frameWidth = 30 frameDepth = 50 // Number of divisions per sash (horizontal and vertical) sashOpeningCountHorizontal = 2 sashOpeningCountVertical = 1 // Derived dimensions sashWidth = windowWidth - (frameWidth * 2) sashHeight = (windowHeight - (frameWidth * 2)) / 2 + frameWidth / 2 sashDepth = frameDepth / 2 - 2 sashTravelDistance = sashHeight * windowState * 0.8 // Function to create panel with frame and openings fn panelFn(plane, offset, width, height, depth, perimeter, divisionThickness, openingCountHorizontal, openingCountVertical) { // Create panel base shape panelPlane = startSketchOn(offsetPlane(XZ, offset = offset)) panelShape = startProfile(panelPlane, at = [-width / 2, -height / 2]) |> yLine(length = height) |> xLine(length = width) |> yLine(length = -height) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close() panelBody = extrude(panelShape, length = depth) // Create opening grid within the panel voidAreaWidth = width - (perimeter * 2) voidAreaHeight = height - (perimeter * 2) divisionTotalThicknessHorizontal = divisionThickness * openingCountHorizontal - divisionThickness divisionTotalThicknessVertical = divisionThickness * openingCountVertical - divisionThickness voidWidth = (voidAreaWidth - divisionTotalThicknessHorizontal) / openingCountHorizontal voidHeight = (voidAreaHeight - divisionTotalThicknessVertical) / openingCountVertical voidStepHorizontal = voidWidth + divisionThickness voidStepVertical = voidHeight + divisionThickness voidPlane = startSketchOn(panelBody, face = END) voidShape = startProfile( voidPlane, at = [ -voidAreaWidth / 2, -voidAreaHeight / 2 ], ) |> yLine(length = voidHeight) |> xLine(length = voidWidth) |> yLine(length = -voidHeight) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close() |> patternLinear2d( %, instances = openingCountHorizontal, distance = voidStepHorizontal, axis = [1, 0], ) |> patternLinear2d( %, instances = openingCountVertical, distance = voidStepVertical, axis = [0, 1], ) voidBody = extrude(voidShape, length = -depth) |> appearance(color = "#a55e2c") return panelBody } // Create main window frame frame = panelFn( plane = XZ, offset = -frameDepth / 2, width = windowWidth, height = windowHeight, depth = frameDepth, perimeter = frameWidth, divisionThickness = 10, openingCountHorizontal = 1, openingCountVertical = 1, ) // Create bottom sliding sash bottomSash = panelFn( plane = XZ, offset = (frameDepth / 2 - sashDepth) / 2, width = sashWidth, height = sashHeight, depth = sashDepth, perimeter = frameWidth, divisionThickness = 10, openingCountHorizontal = sashOpeningCountHorizontal, openingCountVertical = sashOpeningCountVertical, ) |> translate( %, x = 0, y = 0, z = frameWidth / 2 - (sashHeight / 2), ) |> translate( %, x = 0, y = 0, z = sashTravelDistance, ) // open / close // Latch mechanism on bottom sash // Create latch plate latchPlateWidth = 13 latchPlateLength = 30 latchPlateThickness = 1 latchPlatePlane = startSketchOn(offsetPlane(XY, offset = frameWidth / 2)) latchPlateShape = startProfile( latchPlatePlane, at = [ -latchPlateLength / 2, -latchPlateWidth / 2 ], ) |> yLine(length = latchPlateWidth) |> xLine(length = latchPlateLength) |> yLine(length = -latchPlateWidth) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close() latchPlateBody = extrude(latchPlateShape, length = latchPlateThickness) |> translate( %, x = 0, y = -frameDepth / 4, z = 0, ) |> translate( %, x = 0, y = 0, z = sashTravelDistance, ) // open / close // Create latch cylinder latchCylinderHeight = 5 latchCylinderPlane = startSketchOn(offsetPlane(latchPlatePlane, offset = latchPlateThickness)) latchCylinderShape = startProfile(latchCylinderPlane, at = [40, -1]) |> xLine(length = -35) |> arc(interiorAbsolute = [-5, 0], endAbsolute = [5, 1]) |> xLine(length = 35) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close() latchCylinderBody = extrude(latchCylinderShape, length = latchCylinderHeight) |> translate( %, x = 0, y = -frameDepth / 4, z = 0, ) |> translate( %, x = 0, y = 0, z = sashTravelDistance, ) // open / close |> rotate( %, roll = 0, pitch = 0, yaw = -90 * windowState, ) // Create top fixed sash topSash = panelFn( plane = XZ, offset = -(frameDepth / 2 - sashDepth) / 2 - sashDepth, width = sashWidth, height = sashHeight, depth = sashDepth, perimeter = frameWidth, divisionThickness = 10, openingCountHorizontal = sashOpeningCountHorizontal, openingCountVertical = sashOpeningCountVertical, ) |> translate( %, x = 0, y = 0, z = sashHeight / 2 - (frameWidth / 2), ) // Create latch nut on the top sash latchNutPlane = startSketchOn(XZ) latchNutShape = startProfile( latchNutPlane, at = [ -latchPlateLength / 2, -latchPlateWidth / 2 ], ) |> yLine(length = latchPlateWidth) |> xLine(length = latchPlateLength) |> yLine(length = -latchPlateWidth) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close() latchNutPlateBody = extrude(latchNutShape, length = latchPlateThickness)