import FreeCAD as App
import FreeCADGui as Gui
import Part
import math

#
# ========= USER PARAMETERS =========
#
shaft_diameter_in   = 3.0      # overall shaft diameter
shaft_length_in     = 12.0     # shaft length
num_notches         = 15       # number of half-circle notches
notch_radius_in     = 0.15     # radius of each notch (inches)
#
# ===================================
#

INCH_TO_MM = 25.4

shaft_radius_mm = (shaft_diameter_in / 2.0) * INCH_TO_MM
shaft_length_mm = shaft_length_in * INCH_TO_MM
notch_radius_mm = notch_radius_in * INCH_TO_MM

doc = App.ActiveDocument
if doc is None:
    doc = App.newDocument("SplineLikeShaft")
else:
    doc = App.ActiveDocument

# ---------------- Shaft (cylinder) ----------------
shaft = doc.addObject("Part::Cylinder", "Shaft")
shaft.Radius = shaft_radius_mm
shaft.Height = shaft_length_mm
shaft.Placement = App.Placement(
    App.Vector(0, 0, 0),
    App.Rotation(App.Vector(0, 0, 1), 0)
)

doc.recompute()

# ---------------- Notch cylinders ----------------
notch_objs = []

# Place the notch centers on a circle slightly *inside* the outer radius
# so that the cut is clearly into the shaft surface.
notch_center_radius = shaft_radius_mm - notch_radius_mm * 0.5

for i in range(num_notches):
    angle = 2.0 * math.pi * i / float(num_notches)
    x = notch_center_radius * math.cos(angle)
    y = notch_center_radius * math.sin(angle)

    notch = doc.addObject("Part::Cylinder", f"Notch_{i+1}")
    notch.Radius = notch_radius_mm
    notch.Height = shaft_length_mm + 2.0   # extend through whole shaft
    notch.Placement = App.Placement(
        App.Vector(x, y, -1.0),           # a bit below 0 so it fully passes through
        App.Rotation(App.Vector(0, 0, 1), 0)
    )
    notch_objs.append(notch)

doc.recompute()

# ---------------- Combine notches & cut ----------------
# Make a compound of all notch cylinders
compound = doc.addObject("Part::Compound", "NotchCompound")
compound.Links = notch_objs
doc.recompute()

# Cut notches out of shaft
cut = doc.addObject("Part::Cut", "NotchedShaft")
cut.Base = shaft
cut.Tool = compound
doc.recompute()

# Hide construction solids, show result only
shaft.ViewObject.Visibility = False
compound.ViewObject.Visibility = False
for n in notch_objs:
    n.ViewObject.Visibility = False

cut.ViewObject.Visibility = True

if Gui.ActiveDocument:
    Gui.ActiveDocument.ActiveView.fitAll()

App.Console.PrintMessage(
    "Done: circular shaft with %d half-round notches.\n"
    "  Shaft: %.3f in diameter, %.3f in long\n"
    "  Notch radius: %.3f in\n" %
    (num_notches, shaft_diameter_in, shaft_length_in, notch_radius_in)
)
