{"$type":"in.atmob.paste.bundle","files":[{"path":"spiral_lamp_shade.py","$type":"in.atmob.paste.bundle#inlineFile","content":"import math\n\nimport FreeCAD\nimport Part\n\n# Initialize active document or create a new one\ndocument = FreeCAD.activeDocument()\nif not document:\n    document = FreeCAD.newDocument(\"SpiralLampShade\")\n\n# Shade dimensional parameters (in mm)\ntotal_sections = 60  # Number of horizontal cross-section slices along the Z-axis\ntotal_height = 240.0  # Total height of the lamp shade in mm\nmid_radius = 100.0  # Maximum radius achieved at the mid-height bulge\nouter_radius = 70.0  # Radius at the bottom and top ends\nstar_points = 64  # Number of sharp peaks/star points around the circumference\ntotal_twist_angle = math.radians(60)  # Maximum rotation angle (in radians)\n\n# Base mounting parameters for the light bulb socket (in mm)\nbase_height = 3.92  # Height of the solid base mounting ring\nhole_diameter = 41.0  # Standard diameter for E27 socket hardware\nhole_radius = hole_diameter / 2.0\n\n\ndef calculate_twist_factor(normalized_height, damping_factor=-2.5):\n    \"\"\"Calculate a non-linear rotation factor along the height profile (0.0 to 1.0).\n    \n    Uses a cubic ease curve combined with a polynomial perturbation wave\n    to create a smooth, organic spiral acceleration instead of a linear twist.\n    \"\"\"\n    x = float(normalized_height)\n    # Cubic smoothstep base progression from 0.0 to 1.0\n    base_twist = 3 * x * x - 2 * x * x * x\n    # Bell-shaped perturbation bump centered at mid-height (x = 0.5)\n    perturbation = (4 * x * (1 - x)) ** 3 * (x - 0.5)\n    return base_twist + damping_factor * perturbation\n\n\nprofile_wires = []\n\nfor section_index in range(total_sections):\n    # Normalized height ratio ranging from 0.0 at the base to 1.0 at the top\n    height_ratio = section_index / float(total_sections - 1)\n    z_position = height_ratio * total_height\n    \n    # Calculate the variable radial bulge profile along the height\n    # Curve profile: f(x) = sin(pi * x^(1/1.3)) creates an asymmetric vertical bulb shape\n    shape_factor = math.sin(math.pow(height_ratio, (1 / 1.3)) * math.pi)\n    current_base_radius = outer_radius + (mid_radius - outer_radius) * shape_factor\n    \n    # Calculate angular shift for the current Z height slice\n    current_twist = calculate_twist_factor(height_ratio) * total_twist_angle\n    \n    external_points = []\n    contour_resolution = star_points * 2  # 2 vertices per star point (peak and trough)\n    \n    # Generate the star/accordion wave geometry around the perimeter\n    for point_index in range(contour_resolution):\n        # Angular position including the accumulated twist shift\n        theta = current_twist + (point_index * 2 * math.pi / contour_resolution)\n        \n        # Cosine wave oscillates between -1.0 (trough) and +1.0 (peak)\n        star_wave = math.cos(\n            point_index * 2 * math.pi * star_points / contour_resolution,\n        )\n        # Depth of the zig-zag indentations scaled proportionally to current radius\n        zigzag_depth = 0.05 * current_base_radius\n        current_radius = current_base_radius + star_wave * zigzag_depth\n        \n        # Convert polar coordinates (radius, theta) to Cartesian (X, Y)\n        x = current_radius * math.cos(theta)\n        y = current_radius * math.sin(theta)\n        external_points.append(FreeCAD.Vector(x, y, z_position))\n    \n    # Close the polygon loop by re-adding the start point\n    external_points.append(external_points[0])\n    \n    outer_wire = Part.makePolygon(external_points)\n    profile_wires.append(outer_wire)\n\n# Generate a continuous 3D solid by skinning/lofting through all wire profiles\nloft_body = Part.makeLoft(profile_wires, True, False, False)\n\n# Subtract a hole at the base for E27 socket insertion (compatible with 3D printer vase mode)\nsocket_cutting_tool = Part.makeCylinder(\n    hole_radius,\n    base_height + 1.0,\n    FreeCAD.Vector(0, 0, -1),\n    FreeCAD.Vector(0, 0, 1),\n)\nfinal_lamp_shade = loft_body.cut(socket_cutting_tool)\n\n# Export the solid geometry to the active FreeCAD document tree\nvisual_object = document.addObject(\"Part::Feature\", \"LampShade\")\nvisual_object.Shape = final_lamp_shade\ndocument.recompute()\n","language":"python"}],"title":"Spiral lamp shade generator script","createdAt":"2026-07-26T21:29:38.479Z","visibility":"public","description":"Decorative lamp shade in the shape of an egg with wavy patterns."}