trait CraneComponent:
    # Default length of the crane body
    length is Real: 4
    # Local Z positions along the body for axles
    drive_along is Real: -length * 0.35 * 0.5
    ground_along is Real: length * 0.2 * 0.5
    guide_along is Real: length * 0.65 * 0.5
    drive_out is Real: 0.26
    ground_out is Real: 0.25
    guide_out is Real: 0.14

    # Default values for bearing and link separation
    drive_separation is Real: 0.2
    guide_separation is Real: 0.30
    ground_separation is Real: 0.2
    input_separation is Real: 0.2
    output_separation is Real: 0.2

    local_along_normal is Math.Vec3: Definitions.AlongBodyNormal
    local_model_plane_normal is Math.Vec3: Definitions.ModelPlaneNormal
    local_zero_angle_normal is Math.Vec3: local_model_plane_normal.cross(local_along_normal)

    # Central connectors for snap
    snap_drive is Interfaces.RedirectedCraneAxleConnector:
        position: drive_out * local_zero_angle_normal + drive_along * local_along_normal
    snap_ground is Interfaces.RedirectedCraneAxleConnector:
        position: ground_out * local_zero_angle_normal + ground_along * local_along_normal
    snap_guide is Interfaces.RedirectedCraneAxleConnector:
        position: guide_out * local_zero_angle_normal + guide_along * local_along_normal
    snap_input is Interfaces.RedirectedCraneAxleConnector:
        position: -0.5 * length * local_along_normal
    snap_output is Interfaces.RedirectedCraneAxleConnector:
        position: 0.5 * length * local_along_normal

    # Bearing connectors
    input_bearing_left is Interfaces.RedirectedCraneAxleConnector:
        position: snap_input.position - input_separation*0.5 * local_model_plane_normal
        main_axis: snap_input.main_axis
        normal: snap_input.normal
    input_bearing_right is Interfaces.RedirectedCraneAxleConnector:
        position: snap_input.position + input_separation*0.5 * local_model_plane_normal
        main_axis: snap_input.main_axis
        normal: snap_input.normal
    output_bearing_left is Interfaces.RedirectedCraneAxleConnector:
        position: snap_output.position - output_separation*0.5 * local_model_plane_normal
        main_axis: snap_output.main_axis
        normal: snap_output.normal
    output_bearing_right is Interfaces.RedirectedCraneAxleConnector:
        position: snap_output.position + output_separation*0.5 * local_model_plane_normal
        main_axis: snap_output.main_axis
        normal: snap_output.normal
    ground_bearing_left is Interfaces.RedirectedCraneAxleConnector:
        position: snap_ground.position - ground_separation*0.5 * local_model_plane_normal
        main_axis: snap_ground.main_axis
        normal: snap_ground.normal
    ground_bearing_right is Interfaces.RedirectedCraneAxleConnector:
        position: snap_ground.position + ground_separation*0.5 * local_model_plane_normal
        main_axis: snap_ground.main_axis
        normal: snap_ground.normal
    guide_bearing_left is Interfaces.RedirectedCraneAxleConnector:
        position: snap_guide.position - guide_separation*0.5 * local_model_plane_normal
        main_axis: snap_guide.main_axis
        normal: snap_guide.normal
    guide_bearing_right is Interfaces.RedirectedCraneAxleConnector:
        position: snap_guide.position + guide_separation*0.5 * local_model_plane_normal
        main_axis: snap_guide.main_axis
        normal: snap_guide.normal
    drive_bearing_left is Interfaces.RedirectedCraneAxleConnector:
        position: snap_drive.position - drive_separation*0.5 * local_model_plane_normal
        main_axis: snap_drive.main_axis
        normal: snap_drive.normal
    drive_bearing_right is Interfaces.RedirectedCraneAxleConnector:
        position: snap_drive.position + drive_separation*0.5 * local_model_plane_normal
        main_axis: snap_drive.main_axis
        normal: snap_drive.normal

    # Group connectors into axle connector triplets
    drive is Interfaces.AxleBearingInterface:
        snap_center: snap_drive
        left_bearing: drive_bearing_left
        right_bearing: drive_bearing_right
    guide is Interfaces.AxleBearingInterface:
        snap_center: snap_guide
        left_bearing: guide_bearing_left
        right_bearing: guide_bearing_right
    ground is Interfaces.AxleBearingInterface:
        snap_center: snap_ground
        left_bearing: ground_bearing_left
        right_bearing: ground_bearing_right
    input is Interfaces.AxleBearingInterface:
        snap_center: snap_input
        left_bearing: input_bearing_left
        right_bearing: input_bearing_right
    output is Interfaces.AxleBearingInterface:
        snap_center: snap_output
        left_bearing: output_bearing_left
        right_bearing: output_bearing_right
