Ejemplo n.º 1
0
def cross_cube_top(ai_constraints):
  """ Generate the whole top figure
  """
  # alias
  cc_c = cross_cube_sub_top_check(ai_constraints)
  cccrbr = cc_c['cross_cube_cnc_router_bit_radius']
  ccect = cc_c['cross_cube_extra_cut_thickness']
  cw5 = cc_c['cube_width']/5.0
  fa1t = cc_c['face_A1_thickness']
  fa2t = cc_c['face_A2_thickness']
  fb1t = cc_c['face_B1_thickness']
  fb2t = cc_c['face_B2_thickness']
  #
  # top_sub_outline
  def top_sub_outline(ai_previous_face_thickness, ai_current_face_thickness, ai_post_face_thickness):
    """ Generate a sub-outline of the top_outline
    """
    #
    pre_ft = ai_previous_face_thickness
    cur_ft = ai_current_face_thickness
    post_ft = ai_post_face_thickness
    #
    r_top_sub_ol = []
    r_top_sub_ol.append((pre_ft+ccect, cur_ft+ccect, 0))
    r_top_sub_ol.append((1*cw5, cur_ft+ccect, -1*cccrbr))
    r_top_sub_ol.append((1*cw5, 0, 0))
    r_top_sub_ol.append((2*cw5, 0, 0))
    r_top_sub_ol.append((2*cw5, cur_ft+ccect, -1*cccrbr))
    r_top_sub_ol.append((3*cw5, cur_ft+ccect, -1*cccrbr))
    r_top_sub_ol.append((3*cw5, 0, 0))
    r_top_sub_ol.append((4*cw5, 0, 0))
    r_top_sub_ol.append((4*cw5, cur_ft+ccect, -1*cccrbr))
    r_top_sub_ol.append((5*cw5-post_ft-ccect, cur_ft+ccect, 0))
    #
    return(r_top_sub_ol)
  # top_outline
  top_ol = []
  top_ol.extend(cnc25d_api.outline_rotate(top_sub_outline(fb1t, fa1t, fb2t)[:-1], cc_c['cube_width']/2.0, cc_c['cube_width']/2.0, 0*math.pi/2))
  top_ol.extend(cnc25d_api.outline_rotate(top_sub_outline(fa1t, fb2t, fa2t)[:-1], cc_c['cube_width']/2.0, cc_c['cube_width']/2.0, 1*math.pi/2))
  top_ol.extend(cnc25d_api.outline_rotate(top_sub_outline(fb2t, fa2t, fb1t)[:-1], cc_c['cube_width']/2.0, cc_c['cube_width']/2.0, 2*math.pi/2))
  top_ol.extend(cnc25d_api.outline_rotate(top_sub_outline(fa2t, fb1t, fa1t)[:-1], cc_c['cube_width']/2.0, cc_c['cube_width']/2.0, 3*math.pi/2))
  top_ol = cnc25d_api.outline_close(top_ol)
  top_A = []
  top_A.append(top_ol)
  # holes
  if(cc_c['top_rod_hole_radius']>0):
    top_A.append((fb1t+cc_c['top_rod_hole_h_position'], fa1t+cc_c['top_rod_hole_h_position'], cc_c['top_rod_hole_radius']))
    top_A.append((cc_c['cube_width']-(fb2t+cc_c['top_rod_hole_h_position']), fa1t+cc_c['top_rod_hole_h_position'], cc_c['top_rod_hole_radius']))
    top_A.append((cc_c['cube_width']-(fb2t+cc_c['top_rod_hole_h_position']), cc_c['cube_width']-(fa2t+cc_c['top_rod_hole_h_position']), cc_c['top_rod_hole_radius']))
    top_A.append((fb1t+cc_c['top_rod_hole_h_position'], cc_c['cube_width']-(fa2t+cc_c['top_rod_hole_h_position']), cc_c['top_rod_hole_radius']))
  # top-hollow
  # [todo]
  # return
  return(top_A)
Ejemplo n.º 2
0
def marked_circle_crenel(ai_x, ai_y, ai_radius, ai_orientation, ai_router_bit_radius, ai_mark_type=2):
  """ generate the A-outline of a marked circle-crenel, centered on (ai_x, ai_y) and with the orientation ai_orientation
  """
  if(ai_mark_type==0):
    r_mcc = (ai_x, ai_y, ai_radius)
  elif(ai_mark_type==1):
    A_mcc = []
    A_mcc.append((ai_x+ai_radius*math.cos(ai_orientation-math.pi/4), ai_y+ai_radius*math.sin(ai_orientation-math.pi/4), 0))
    A_mcc.append((ai_x+math.sqrt(2)*ai_radius*math.cos(ai_orientation-0*math.pi/4), ai_y+math.sqrt(2)*ai_radius*math.sin(ai_orientation-0*math.pi/4), ai_router_bit_radius))
    A_mcc.append((ai_x+ai_radius*math.cos(ai_orientation+math.pi/4), ai_y+ai_radius*math.sin(ai_orientation+math.pi/4), 0))
    A_mcc.append((ai_x+ai_radius*math.cos(ai_orientation+math.pi), ai_y+ai_radius*math.sin(ai_orientation+math.pi), ai_x+ai_radius*math.cos(ai_orientation-math.pi/4), ai_y+ai_radius*math.sin(ai_orientation-math.pi/4), 0))
    #r_mcc = cnc25d_api.cnc_cut_outline(A_mcc, "marked_circle_crenel")
    r_mcc = A_mcc
  elif(ai_mark_type==2):
    A_mcc = []
    A_mcc.append((ai_x+ai_radius*math.cos(-math.pi/2), ai_y+ai_radius*math.sin(-math.pi/2), 0))
    A_mcc.append((ai_x+(1+math.sqrt(2))*ai_radius, ai_y-ai_radius, ai_router_bit_radius))
    A_mcc.append((ai_x+ai_radius*math.cos(math.pi/4), ai_y+ai_radius*math.sin(math.pi/4), 0))
    A_mcc.append((ai_x+ai_radius*math.cos(math.pi), ai_y+ai_radius*math.sin(math.pi), A_mcc[0][0], A_mcc[0][1], 0))
    #r_mcc = cnc25d_api.cnc_cut_outline(cnc25d_api.outline_rotate(A_mcc, ai_x, ai_y, ai_orientation), "marked_circle_crenel")
    r_mcc = cnc25d_api.outline_rotate(A_mcc, ai_x, ai_y, ai_orientation)
  else:
    print("ERR182: Error, ai_mark_type {:d} doesn't exist".format(ai_mark_type))
    sys.exit(2)
  return(r_mcc)
Ejemplo n.º 3
0
def bell_base_holes(ai_c):
  """ generate the hole-outlines (type-a) of the bell_base part
  """
  ### intermediate parameters
  wall_thickness = max(ai_c['face_thickness'], ai_c['side_thickness'])
  ect = ai_c['bell_extra_cut_thickness']
  ### figure construction
  r_f = []
  # z_axle_hole
  if(ai_c['z_hole_radius']>0):
    z_axle_hole_position = math.sqrt(2)*(ai_c['bell_face_width']/2.0-wall_thickness) - ai_c['z_hole_position_length']
    for i in range(4):
      a = i*math.pi/2+math.pi/4
      r_f.append((z_axle_hole_position*math.cos(a), z_axle_hole_position*math.sin(a), ai_c['z_hole_radius']))
  # base_fastening_holes
  for i in range(ai_c['base_hole_nb']):
    a = i*2*math.pi/ai_c['base_hole_nb']+ai_c['base_hole_angle']
    r_f.append((ai_c['base_hole_position_radius']*math.cos(a), ai_c['base_hole_position_radius']*math.sin(a), ai_c['base_hole_radius']))
  # external_buttress
  if(ai_c['ext_buttress_y_length']>0):
    py = -1*ai_c['bell_face_width']/2.0 - ai_c['ext_buttress_y_position']
    px1 = -1*ai_c['ext_buttress_x_distance']/2.0 - ai_c['ext_buttress_x_width']
    px2 = ai_c['ext_buttress_x_distance']/2.0
    for i in range(4):
      for px in (px1, px2):
        hol = []
        hol.append((px-ect, py+ect, -1*ai_c['bell_cnc_router_bit_radius']))
        hol.append((px-ect, py-ai_c['ext_buttress_y_length']-ect, -1*ai_c['bell_cnc_router_bit_radius']))
        hol.append((px+ai_c['ext_buttress_x_width']+ect, py-ai_c['ext_buttress_y_length']-ect, -1*ai_c['bell_cnc_router_bit_radius']))
        hol.append((px+ai_c['ext_buttress_x_width']+ect, py+ect, -1*ai_c['bell_cnc_router_bit_radius']))
        hol.append((px-ect, py+ect, 0))
        r_f.append(cnc25d_api.outline_rotate(hol, 0.0, 0.0, i*math.pi/2))
  ### return
  return(r_f)
Ejemplo n.º 4
0
def make_holder_crenel(ai_holder_maximal_height_plus, ai_holder_crenel_height, ai_holder_crenel_skin_width, ai_holder_crenel_half_width, 
                       ai_holder_crenel_router_bit_radius, ai_holder_side_outer_smoothing_radius, ai_holder_smoothing_radius, ai_holder_crenel_x_position, ai_angle, ai_ox, ai_oy):
  """ generate the A-outline of the holder-crenel
  """
  x0 = ai_holder_crenel_x_position
  x1 = x0 + ai_holder_maximal_height_plus
  x2 = x1 - ai_holder_crenel_height
  y22 = ai_holder_crenel_half_width+ai_holder_crenel_skin_width
  y21 = ai_holder_crenel_half_width
  y12 = -1*y22
  y11 = -1*y21
  dx3 = (1+math.sqrt(2))*ai_holder_crenel_router_bit_radius
  x3 = x2 - dx3
  y23 = y21 - dx3
  y13 = -1*y23
  holder_crenel = []
  holder_crenel.append([x0, y12, ai_holder_smoothing_radius]) # it will be removed at the end of the function
  holder_crenel.append([x1, y12, ai_holder_side_outer_smoothing_radius])
  holder_crenel.append([x1, y11, 0])
  if(y23>ai_holder_crenel_half_width*0.1):
    holder_crenel.append([x3, y11, ai_holder_crenel_router_bit_radius])
    holder_crenel.append([x2, y13, 0])
    holder_crenel.append([x2, y23, 0])
    holder_crenel.append([x3, y21, ai_holder_crenel_router_bit_radius])
  else:
    holder_crenel.append([x2, y11, ai_holder_crenel_router_bit_radius])
    holder_crenel.append([x2, y21, ai_holder_crenel_router_bit_radius])
  holder_crenel.append([x1, y21, 0])
  holder_crenel.append([x1, y22, ai_holder_side_outer_smoothing_radius])
  holder_crenel.append([x0, y22, ai_holder_smoothing_radius])
  #
  r_holder_crenel = cnc25d_api.outline_rotate(holder_crenel, ai_ox, ai_oy, ai_angle)
  #first_point = r_holder_crenel[1]
  return(r_holder_crenel[1:])
Ejemplo n.º 5
0
def bell_base_main_hole_outline(ai_c):
  """ generate the A-outline of the main hole of the bell_base part
  """
  ### constant
  radian_epsilon = math.pi/1000
  ### intermediate parameters
  bell_face_width_10 = ai_c['bell_face_width']/10.0
  wall_thickness = max(ai_c['face_thickness'], ai_c['side_thickness'])
  ect = ai_c['bell_extra_cut_thickness']
  ### sub-outline construction
  sol = []
  sol.append((-3*bell_face_width_10, -5*bell_face_width_10+1.5*wall_thickness, ai_c['bell_cnc_router_bit_radius']))
  sol.append((-3*bell_face_width_10, -5*bell_face_width_10-ect, -1*ai_c['bell_cnc_router_bit_radius']))
  sol.append((-1*bell_face_width_10, -5*bell_face_width_10-ect, -1*ai_c['bell_cnc_router_bit_radius']))
  sol.append((-1*bell_face_width_10, -5*bell_face_width_10+wall_thickness, 0))
  sol.append((1*bell_face_width_10, -5*bell_face_width_10+wall_thickness, 0))
  sol.append((1*bell_face_width_10, -5*bell_face_width_10-ect, -1*ai_c['bell_cnc_router_bit_radius']))
  sol.append((3*bell_face_width_10, -5*bell_face_width_10-ect, -1*ai_c['bell_cnc_router_bit_radius']))
  sol.append((3*bell_face_width_10, -5*bell_face_width_10+1.5*wall_thickness, ai_c['bell_cnc_router_bit_radius']))
  if(ai_c['z_hole_radius']>0):
    lAB = 2*bell_face_width_10 - wall_thickness
    lAC = ai_c['z_hole_position_length']
    lCD = ai_c['z_hole_external_radius']
    aBAC = math.pi/4
    lCB = math.sqrt(lAB**2+lAC**2-2*lAB*lAC*math.cos(aBAC)) # law of cosines in the triangle ABC
    cos_aACB = (lCB**2+lAC**2-lAB**2)/(2*lCB*lAC)
    if(abs(cos_aACB)>1):
      print("ERR359: Error, cos_aACB {:0.3f} is out of the range -1..1".format(cos_aACB))
      sys.exit(2)
    aACB = math.acos(cos_aACB)
    cos_aBCD = lCD/lCB
    if(abs(cos_aBCD)>1):
      print("ERR364: Error, cos_aBCD {:0.3f} is out of the range -1..1".format(cos_aBCD))
      sys.exit(2)
    aBCD = math.acos(cos_aBCD)
    aACD = aACB + aBCD
    #print("dbg370: aACB {:0.3f}  aBCD {:0.3f}  aACD {:0.3f}".format(aACB, aBCD, aACD))
    lEC = math.sqrt(2)*wall_thickness + lAC
    Cx = 5*bell_face_width_10 - lEC * math.cos(math.pi/4) # sqrt(2)/2
    Cy = -5*bell_face_width_10 + lEC * math.sin(math.pi/4)
    Fx = Cx - ai_c['z_hole_external_radius']*math.cos(math.pi/4)
    Fy = Cy + ai_c['z_hole_external_radius']*math.sin(math.pi/4)
    Dx = Cx + ai_c['z_hole_external_radius']*math.cos(-math.pi/4-aACD)
    Dy = Cy + ai_c['z_hole_external_radius']*math.sin(-math.pi/4-aACD)
    Gx = Cx + ai_c['z_hole_external_radius']*math.cos(-math.pi/4+aACD)
    Gy = Cy + ai_c['z_hole_external_radius']*math.sin(-math.pi/4+aACD)
    if(aACD>math.pi-radian_epsilon):
      sol.append((Fx, Fy, ai_c['bell_cnc_router_bit_radius']))
    else:
      sol.append((Dx, Dy, 0))
      sol.append((Fx, Fy, Gx, Gy, 0))
  #print("dbg351: sol:", sol)
  ### outline construction
  r_ol = []
  for i in range(4):
    r_ol.extend(cnc25d_api.outline_rotate(sol, 0.0, 0.0, i*math.pi/2))
  r_ol = cnc25d_api.outline_close(r_ol)
  ### return
  return(r_ol)
Ejemplo n.º 6
0
def gearbar_2d_construction(c):
    """
  construct the 2D-figures with outlines at the A-format for the gearbar design
  """
    ### gearbar outline
    if (c['gear_tooth_nb'] > 0):
        i_gear_profile = inherit_gear_profile()  # inherit from gear_profile
        i_gear_profile.apply_external_constraint(gear_profile_constraint(c))
        gear_profile_A = i_gear_profile.get_A_figure('first_gear')[
            0]  # Warning: gear_profile provide only B-format outline currently
        gear_profile_A = cnc25d_api.outline_rotate(
            gear_profile_A, c['g1_ix'], c['g1_iy'],
            -1 * c['g1_inclination'] + math.pi / 2)
        gear_profile_A = cnc25d_api.outline_shift_xy(
            gear_profile_A, -1 * gear_profile_A[0][0], 1,
            -1 * c['g1_iy'] + c['gearbar_height'], 1
        )  # gearbar_fig inclinatiion is always zero. Inclination only visible in simulation
    else:
        gear_profile_A = [(0, c['gearbar_height']),
                          (c['gearbar_length'], c['gearbar_height'])]
    gearbar_outline = gear_profile_A
    gearbar_outline.append((gearbar_outline[-1][0], 0))
    gearbar_outline.append((0, 0))
    gearbar_outline.append((0, gearbar_outline[0][1]))
    #print("dbg200: gearbar_outline:", gearbar_outline)
    ### gearbar-hole figure
    gearbar_hole_figure = []
    if ((c['gearbar_hole_radius'] > 0) and (c['pi_module'] > 0)):
        hole_x = c[
            'first_tooth_position'] + c['gearbar_hole_offset'] * c['pi_module']
        while (hole_x < (c['gearbar_length'] - c['gearbar_hole_radius'])):
            #print("dbg312: hole_x {:0.3f}".format(hole_x))
            gearbar_hole_figure.append([
                hole_x, c['gearbar_hole_height_position'],
                c['gearbar_hole_radius']
            ])
            hole_x += c['gearbar_hole_increment'] * c['pi_module']

    ### design output
    gb_figure = [gearbar_outline]
    gb_figure.extend(gearbar_hole_figure)
    ###
    r_figures = {}
    r_height = {}
    #
    r_figures['gearbar_fig'] = gb_figure
    r_height['gearbar_fig'] = c['gear_profile_height']
    ###
    return ((r_figures, r_height))
Ejemplo n.º 7
0
def make_holder_crenel(ai_holder_maximal_height_plus, ai_holder_crenel_height,
                       ai_holder_crenel_skin_width,
                       ai_holder_crenel_half_width,
                       ai_holder_crenel_router_bit_radius,
                       ai_holder_side_outer_smoothing_radius,
                       ai_holder_smoothing_radius, ai_holder_crenel_x_position,
                       ai_angle, ai_ox, ai_oy):
    """ generate the A-outline of the holder-crenel
  """
    x0 = ai_holder_crenel_x_position
    x1 = x0 + ai_holder_maximal_height_plus
    x2 = x1 - ai_holder_crenel_height
    y22 = ai_holder_crenel_half_width + ai_holder_crenel_skin_width
    y21 = ai_holder_crenel_half_width
    y12 = -1 * y22
    y11 = -1 * y21
    dx3 = (1 + math.sqrt(2)) * ai_holder_crenel_router_bit_radius
    x3 = x2 - dx3
    y23 = y21 - dx3
    y13 = -1 * y23
    holder_crenel = []
    holder_crenel.append([x0, y12, ai_holder_smoothing_radius
                          ])  # it will be removed at the end of the function
    holder_crenel.append([x1, y12, ai_holder_side_outer_smoothing_radius])
    holder_crenel.append([x1, y11, 0])
    if (y23 > ai_holder_crenel_half_width * 0.1):
        holder_crenel.append([x3, y11, ai_holder_crenel_router_bit_radius])
        holder_crenel.append([x2, y13, 0])
        holder_crenel.append([x2, y23, 0])
        holder_crenel.append([x3, y21, ai_holder_crenel_router_bit_radius])
    else:
        holder_crenel.append([x2, y11, ai_holder_crenel_router_bit_radius])
        holder_crenel.append([x2, y21, ai_holder_crenel_router_bit_radius])
    holder_crenel.append([x1, y21, 0])
    holder_crenel.append([x1, y22, ai_holder_side_outer_smoothing_radius])
    holder_crenel.append([x0, y22, ai_holder_smoothing_radius])
    #
    r_holder_crenel = cnc25d_api.outline_rotate(holder_crenel, ai_ox, ai_oy,
                                                ai_angle)
    #first_point = r_holder_crenel[1]
    return (r_holder_crenel[1:])
Ejemplo n.º 8
0
def gearbar_2d_construction(c):
  """
  construct the 2D-figures with outlines at the A-format for the gearbar design
  """
  ### gearbar outline
  if(c['gear_tooth_nb']>0):
    i_gear_profile = inherit_gear_profile() # inherit from gear_profile
    i_gear_profile.apply_external_constraint(gear_profile_constraint(c))
    gear_profile_A = i_gear_profile.get_A_figure('first_gear')[0] # Warning: gear_profile provide only B-format outline currently
    gear_profile_A = cnc25d_api.outline_rotate(gear_profile_A, c['g1_ix'], c['g1_iy'], -1*c['g1_inclination'] + math.pi/2)
    gear_profile_A = cnc25d_api.outline_shift_xy(gear_profile_A, -1*gear_profile_A[0][0], 1, -1*c['g1_iy'] + c['gearbar_height'], 1) # gearbar_fig inclinatiion is always zero. Inclination only visible in simulation
  else:
    gear_profile_A = [(0, c['gearbar_height']),(c['gearbar_length'], c['gearbar_height'])]
  gearbar_outline = gear_profile_A
  gearbar_outline.append((gearbar_outline[-1][0], 0))
  gearbar_outline.append((0, 0))
  gearbar_outline.append((0, gearbar_outline[0][1]))
  #print("dbg200: gearbar_outline:", gearbar_outline)
  ### gearbar-hole figure
  gearbar_hole_figure = []
  if((c['gearbar_hole_radius']>0)and(c['pi_module']>0)):
    hole_x = c['first_tooth_position'] + c['gearbar_hole_offset'] * c['pi_module']
    while(hole_x<(c['gearbar_length']-c['gearbar_hole_radius'])):
      #print("dbg312: hole_x {:0.3f}".format(hole_x))
      gearbar_hole_figure.append([hole_x, c['gearbar_hole_height_position'], c['gearbar_hole_radius']])
      hole_x += c['gearbar_hole_increment'] * c['pi_module']

  ### design output
  gb_figure = [gearbar_outline]
  gb_figure.extend(gearbar_hole_figure)
  ###
  r_figures = {}
  r_height = {}
  #
  r_figures['gearbar_fig'] = gb_figure
  r_height['gearbar_fig'] = c['gear_profile_height']
  ###
  return((r_figures, r_height))
Ejemplo n.º 9
0
def gearwheel_2d_construction(c):
  """
  construct the 2D-figures with outlines at the A-format for the gearwheel design
  """
  ### precision
  radian_epsilon = math.pi/1000
  ### axle
  axle_figure = []
  if(c['axle_type']=='circle'):
    if(not c['crenel_axle_merge']):
      axle_figure.append([c['g1_ix'], c['g1_iy'], c['axle_radius']])
    else:
      axle_A = [(c['g1_ix']+c['axle_radius']*math.cos(-1*c['crenel_half_width_angle']), c['g1_iy']+c['axle_radius']*math.sin(-1*c['crenel_half_width_angle']), 0)]
      if(c['crenel_rectangle_type']==1):
        crenel_A = [
          (c['g1_ix']+c['axle_radius']+c['crenel_height'], c['g1_iy']-c['crenel_width']/2.0, -1*c['crenel_rbr']),
          (c['g1_ix']+c['axle_radius']+c['crenel_height'], c['g1_iy']+c['crenel_width']/2.0, -1*c['crenel_rbr']),
          (c['g1_ix']+c['axle_radius']*math.cos(1*c['crenel_half_width_angle']), c['g1_iy']+c['axle_radius']*math.sin(1*c['crenel_half_width_angle']), 0)]
        crenel_A_marked = crenel_A[:]
        crenel_A_marked[-1] = (crenel_A[-1][0], crenel_A[-1][1], 0.6*c['crenel_height'])
      elif(c['crenel_rectangle_type']==2):
        tmp_l = c['crenel_rbr'] * (1+math.sqrt(2))
        crenel_A = [
          (c['g1_ix']+c['axle_radius']+c['crenel_height']+1*tmp_l, c['g1_iy']-c['crenel_width']/2.0+0*tmp_l, 1*c['crenel_rbr']),
          (c['g1_ix']+c['axle_radius']+c['crenel_height']+0*tmp_l, c['g1_iy']-c['crenel_width']/2.0+1*tmp_l, 0*c['crenel_rbr']),
          (c['g1_ix']+c['axle_radius']+c['crenel_height']+0*tmp_l, c['g1_iy']+c['crenel_width']/2.0-1*tmp_l, 0*c['crenel_rbr']),
          (c['g1_ix']+c['axle_radius']+c['crenel_height']+1*tmp_l, c['g1_iy']+c['crenel_width']/2.0-0*tmp_l, 1*c['crenel_rbr']),
          (c['g1_ix']+c['axle_radius']*math.cos(1*c['crenel_half_width_angle']), c['g1_iy']+c['axle_radius']*math.sin(1*c['crenel_half_width_angle']), 0)]
        crenel_A_marked = crenel_A[:]
        crenel_A_marked[-1] = (crenel_A[-1][0], crenel_A[-1][1], 0.6*c['crenel_height'])
      arc_half_angle = (c['crenel_portion_angle'] - 2*c['crenel_half_width_angle'])/2.0
      arc_middle_a = c['crenel_half_width_angle'] + arc_half_angle
      arc_end_a = arc_middle_a + arc_half_angle
      crenel_A.append((c['g1_ix']+c['axle_radius']*math.cos(arc_middle_a), c['g1_iy']+c['axle_radius']*math.sin(arc_middle_a), c['g1_ix']+c['axle_radius']*math.cos(arc_end_a), c['g1_iy']+c['axle_radius']*math.sin(arc_end_a), 0))
      crenel_A_marked.append(crenel_A[-1])
      for i in range(c['crenel_number']):
        if(i<c['crenel_mark_nb']):
          crenel_A_selected = crenel_A_marked
        else:
          crenel_A_selected = crenel_A
        axle_A.extend(cnc25d_api.outline_rotate(crenel_A_selected, c['g1_ix'], c['g1_iy'], i*c['crenel_portion_angle']))
      axle_A[-1] = (axle_A[-1][0], axle_A[-1][1], axle_A[0][0], axle_A[0][1], 0)
      axle_A_rotated = cnc25d_api.outline_rotate(axle_A, c['g1_ix'], c['g1_iy'], c['crenel_angle'])
      axle_figure.append(axle_A_rotated)
  elif(c['axle_type']=='rectangle'):
    axle_A = [
      [c['g1_ix']-c['axle_x_width']/2.0, c['g1_iy']-c['axle_y_width']/2.0, -1*c['axle_rbr']],
      [c['g1_ix']+c['axle_x_width']/2.0, c['g1_iy']-c['axle_y_width']/2.0, -1*c['axle_rbr']],
      [c['g1_ix']+c['axle_x_width']/2.0, c['g1_iy']+c['axle_y_width']/2.0, -1*c['axle_rbr']],
      [c['g1_ix']-c['axle_x_width']/2.0, c['g1_iy']+c['axle_y_width']/2.0, -1*c['axle_rbr']]]
    axle_A = cnc25d_api.outline_close(axle_A)
    axle_figure.append(axle_A)

  ### crenel
  #crenel_template
  if(c['crenel_number']>0):
    if((c['crenel_type']=='rectangle')and(not c['crenel_axle_merge'])):
      if(c['crenel_rectangle_type']==1):
        template_crenel = [
          (c['g1_ix']+c['crenel_radius']+0*c['crenel_height'], c['g1_iy']-1*c['crenel_width']/2.0, -1*c['crenel_rbr']),
          (c['g1_ix']+c['crenel_radius']+1*c['crenel_height'], c['g1_iy']-1*c['crenel_width']/2.0, -1*c['crenel_rbr']),
          (c['g1_ix']+c['crenel_radius']+1*c['crenel_height'], c['g1_iy']+1*c['crenel_width']/2.0, -1*c['crenel_rbr']),
          (c['g1_ix']+c['crenel_radius']+0*c['crenel_height'], c['g1_iy']+1*c['crenel_width']/2.0, -1*c['crenel_rbr'])]
      elif(c['crenel_rectangle_type']==2):
        tmp_l = c['crenel_rbr'] * (1+math.sqrt(2))
        template_crenel = [
          (c['g1_ix']+c['crenel_radius']+0*c['crenel_height']-1*tmp_l, c['g1_iy']-1*c['crenel_width']/2.0+0*tmp_l, 1*c['crenel_rbr']),
          (c['g1_ix']+c['crenel_radius']+1*c['crenel_height']+1*tmp_l, c['g1_iy']-1*c['crenel_width']/2.0+0*tmp_l, 1*c['crenel_rbr']),
          (c['g1_ix']+c['crenel_radius']+1*c['crenel_height']+0*tmp_l, c['g1_iy']-1*c['crenel_width']/2.0+1*tmp_l, 0*c['crenel_rbr']),
          (c['g1_ix']+c['crenel_radius']+1*c['crenel_height']+0*tmp_l, c['g1_iy']+1*c['crenel_width']/2.0-1*tmp_l, 0*c['crenel_rbr']),
          (c['g1_ix']+c['crenel_radius']+1*c['crenel_height']+1*tmp_l, c['g1_iy']+1*c['crenel_width']/2.0-0*tmp_l, 1*c['crenel_rbr']),
          (c['g1_ix']+c['crenel_radius']+0*c['crenel_height']-1*tmp_l, c['g1_iy']+1*c['crenel_width']/2.0-0*tmp_l, 1*c['crenel_rbr']),
          (c['g1_ix']+c['crenel_radius']+0*c['crenel_height']-0*tmp_l, c['g1_iy']+1*c['crenel_width']/2.0-1*tmp_l, 0*c['crenel_rbr']),
          (c['g1_ix']+c['crenel_radius']+0*c['crenel_height']-0*tmp_l, c['g1_iy']-1*c['crenel_width']/2.0+1*tmp_l, 0*c['crenel_rbr'])]
      template_crenel = cnc25d_api.outline_close(template_crenel)
      for i in range(c['crenel_number']):
        crenel_A = cnc25d_api.outline_rotate(template_crenel, c['g1_ix'], c['g1_iy'], c['crenel_angle']+i*c['crenel_portion_angle'])
        axle_figure.append(crenel_A)
    elif(c['crenel_type']=='circle'):
      for i in range(c['crenel_number']):
        ta = c['crenel_angle']+i*c['crenel_portion_angle']
        if(i<c['crenel_mark_nb']):
          axle_figure.append(marked_circle_crenel(c['g1_ix']+c['crenel_radius']*math.cos(ta), c['g1_iy']+c['crenel_radius']*math.sin(ta), c['crenel_width']/2.0, ta+math.pi/2, c['crenel_rbr']))
        else:
          axle_figure.append((c['g1_ix']+c['crenel_radius']*math.cos(ta), c['g1_iy']+c['crenel_radius']*math.sin(ta), c['crenel_width']/2.0))
  #print("dbg435: axle_figure:", axle_figure)

  ### wheel hollow (a.k.a legs)
  wheel_hollow_figure = []
  if(c['wheel_hollow_leg_number']>0):
    wh_angle = 2*math.pi/c['wheel_hollow_leg_number']
    wh_leg_top_angle1 = math.asin(float(c['wheel_hollow_leg_width']/2.0+c['wheel_hollow_rbr'])/(c['wheel_hollow_external_radius']-c['wheel_hollow_rbr']))
    if(wh_angle<2*wh_leg_top_angle1+radian_epsilon):
      print("ERR664: Error, wh_angle {:0.2f} too small compare to wh_leg_top_angle1 {:0.2f}!".format(wh_angle, wh_leg_top_angle1))
      sys.exit(2)
    wh_leg_bottom_angle1 = math.asin(float(c['wheel_hollow_leg_width']/2.0+c['wheel_hollow_rbr'])/(c['wheel_hollow_internal_radius']+c['wheel_hollow_rbr']))
    #wh_leg_top_angle2 = math.asin((c['wheel_hollow_leg_width']/2)/c['wheel_hollow_external_radius'])
    wh_leg_top_angle2 = math.asin(float(c['wheel_hollow_leg_width'])/(2*c['wheel_hollow_external_radius']))
    #wh_leg_bottom_angle2 = math.asin((c['wheel_hollow_leg_width']/2)/c['wheel_hollow_internal_radius'])
    wh_leg_bottom_angle2 = math.asin(float(c['wheel_hollow_leg_width'])/(2*c['wheel_hollow_internal_radius']))
    # angular coordinates of the points
    wh_top1_a = c['wheel_hollow_leg_angle']+wh_leg_top_angle2
    wh_top2_a = c['wheel_hollow_leg_angle']+wh_angle/2.0
    wh_top3_a = c['wheel_hollow_leg_angle']+wh_angle-wh_leg_top_angle2
    wh_bottom1_a = c['wheel_hollow_leg_angle']+wh_leg_bottom_angle2
    wh_bottom2_a = c['wheel_hollow_leg_angle']+wh_angle/2.0
    wh_bottom3_a = c['wheel_hollow_leg_angle']+wh_angle-wh_leg_bottom_angle2
    # Cartesian coordinates of the points
    wh_top1_x = c['g1_ix'] + c['wheel_hollow_external_radius']*math.cos(wh_top1_a)
    wh_top1_y = c['g1_iy'] + c['wheel_hollow_external_radius']*math.sin(wh_top1_a)
    wh_top2_x = c['g1_ix'] + c['wheel_hollow_external_radius']*math.cos(wh_top2_a)
    wh_top2_y = c['g1_iy'] + c['wheel_hollow_external_radius']*math.sin(wh_top2_a)
    wh_top3_x = c['g1_ix'] + c['wheel_hollow_external_radius']*math.cos(wh_top3_a)
    wh_top3_y = c['g1_iy'] + c['wheel_hollow_external_radius']*math.sin(wh_top3_a)
    wh_bottom1_x = c['g1_ix'] + c['wheel_hollow_internal_radius']*math.cos(wh_bottom1_a)
    wh_bottom1_y = c['g1_iy'] + c['wheel_hollow_internal_radius']*math.sin(wh_bottom1_a)
    wh_bottom2_x = c['g1_ix'] + c['wheel_hollow_internal_radius']*math.cos(wh_bottom2_a)
    wh_bottom2_y = c['g1_iy'] + c['wheel_hollow_internal_radius']*math.sin(wh_bottom2_a)
    wh_bottom3_x = c['g1_ix'] + c['wheel_hollow_internal_radius']*math.cos(wh_bottom3_a)
    wh_bottom3_y = c['g1_iy'] + c['wheel_hollow_internal_radius']*math.sin(wh_bottom3_a)
    # create one outline
    if(wh_angle<2*wh_leg_bottom_angle1+radian_epsilon):
      wh_outline_A = [
        [wh_top1_x, wh_top1_y, c['wheel_hollow_rbr']],
        [wh_top2_x, wh_top2_y, wh_top3_x, wh_top3_y, c['wheel_hollow_rbr']],
        [wh_bottom2_x, wh_bottom2_y, c['wheel_hollow_rbr']]]
    else:
      wh_outline_A = [
        [wh_top1_x, wh_top1_y, c['wheel_hollow_rbr']],
        [wh_top2_x, wh_top2_y, wh_top3_x, wh_top3_y, c['wheel_hollow_rbr']],
        [wh_bottom3_x, wh_bottom3_y, c['wheel_hollow_rbr']],
        [wh_bottom2_x, wh_bottom2_y, wh_bottom1_x, wh_bottom1_y, c['wheel_hollow_rbr']]]
    wh_outline_A = cnc25d_api.outline_close(wh_outline_A)
    for i in range(c['wheel_hollow_leg_number']):
      wheel_hollow_figure.append(cnc25d_api.outline_rotate(wh_outline_A, c['g1_ix'], c['g1_iy'], i*wh_angle))


  ### design output
  gw_figure = []
  if(c['gear_tooth_nb']>0):
    i_gear_profile = inherit_gear_profile(c) # inherit from gear_profile
    gw_figure.extend(i_gear_profile.get_A_figure('first_gear'))
  else:
    gw_figure.append((c['g1_ix'], c['g1_iy'], float(c['gear_primitive_diameter'])/2))
  gw_figure.extend(axle_figure)
  gw_figure.extend(wheel_hollow_figure)
  ###
  r_figures = {}
  r_height = {}
  #
  r_figures['gearwheel_fig'] = gw_figure
  r_height['gearwheel_fig'] = c['gear_profile_height']
  ###
  return((r_figures, r_height))
Ejemplo n.º 10
0
def gearbar_constraint_check(c):
  """ check the gearbar constraint c and set the dynamic default values
  """
  #print("dbg122: len(c)", len(c))
  ### precision
  radian_epsilon = math.pi/1000
  ### check parameter coherence (part 1)
  c['gearbar_hole_radius'] = float(c['gearbar_hole_diameter'])/2
  # c['gearbar_hole_height_position']
  if((c['gearbar_hole_height_position']+c['gearbar_hole_radius'])>c['gearbar_height']):
    print("ERR215: Error, gearbar_hole_height_position {:0.3} and gearbar_hole_radius {:0.3f} are too big compare to gearbar_height {:0.3f} !".format(c['gearbar_hole_height_position'], c['gearbar_hole_radius'], c['gearbar_height']))
    sys.exit(2)
  # c['gearbar_hole_increment']
  if(c['gearbar_hole_increment']==0):
    print("ERR183: Error gearbar_hole_increment must be bigger than zero!")
    sys.exit(2)
  # c['gear_tooth_nb']
  if(c['gear_tooth_nb']>0): # create a gear_profile
    i_gear_profile = inherit_gear_profile() # inherit from gear_profile
    i_gear_profile.apply_external_constraint(gear_profile_constraint(c))
    gear_profile_parameters = i_gear_profile.get_constraint()
    # extract some gear_profile high-level parameter
    #print('dbg556: gear_profile_parameters:', gear_profile_parameters)
    c['g1_ix'] = gear_profile_parameters['g1_param']['center_ox']
    c['g1_iy'] = gear_profile_parameters['g1_param']['center_oy']
    c['g1_inclination'] = gear_profile_parameters['g1_param']['gearbar_inclination']
    gear_profile_for_length = i_gear_profile.get_A_figure('first_gear')[0]
    gear_profile_for_length = cnc25d_api.outline_rotate(gear_profile_for_length, c['g1_ix'], c['g1_iy'], -1*c['g1_inclination'] + math.pi/2)
    gear_profile_for_length = cnc25d_api.outline_shift_xy(gear_profile_for_length, -1*gear_profile_for_length[0][0], 1, -1*c['g1_iy'] + c['gearbar_height'], 1)
    #print("dbg127: gear_profile_for_length:", gear_profile_for_length)
    c['gearbar_length'] = gear_profile_for_length[-1][0] - gear_profile_for_length[0][0]
    ## get some parameters
    c['minimal_gear_profile_height'] = c['gearbar_height'] - (gear_profile_parameters['g1_param']['hollow_height'] + gear_profile_parameters['g1_param']['dedendum_height'])
    c['pi_module'] = gear_profile_parameters['g1_param']['pi_module']
    pfe = gear_profile_parameters['g1_param']['portion_first_end']
    full_positive_slope = gear_profile_parameters['g1_param']['full_positive_slope']
    full_negative_slope = gear_profile_parameters['g1_param']['full_negative_slope']
    bottom_land = gear_profile_parameters['g1_param']['bottom_land']
    top_land = gear_profile_parameters['g1_param']['top_land']
    if((top_land + full_positive_slope + bottom_land + full_negative_slope)!=c['pi_module']):
      print("ERR269: Error with top_land {:0.3f}  full_positive_slope {:0.3f}  bottom_land {:0.3f}  full_negative_slope {:0.3f} and pi_module  {:0.3f}".format(top_land, full_positive_slope, bottom_land, full_negative_slope, c['pi_module']))
      sys.exit(2)
    if(pfe==0):
      c['first_tooth_position'] = full_positive_slope + bottom_land + full_negative_slope + float(top_land)/2
    elif(pfe==1):
      c['first_tooth_position'] = full_positive_slope + bottom_land + full_negative_slope + top_land
    elif(pfe==2):
      c['first_tooth_position'] = full_negative_slope + float(top_land)/2
    elif(pfe==3):
      c['first_tooth_position'] = float(bottom_land)/2 + full_negative_slope + float(top_land)/2
  else: # no gear_profile, just a circle
    if(c['gear_primitive_diameter']<radian_epsilon):
      print("ERR885: Error, the no-gear-profile line outline length gear_primitive_diameter {:0.2f} is too small!".format(c['gear_primitive_diameter']))
      sys.exit(2)
    #c['g1_ix'] = c['center_position_x
    #c['g1_iy'] = c['center_position_y
    c['gearbar_length'] = c['gear_primitive_diameter']
    c['minimal_gear_profile_height'] = c['gearbar_height']
    c['pi_module'] = c['gear_module'] * math.pi
    c['first_tooth_position'] = float(c['pi_module'])/2

  ### check parameter coherence (part 2)
  # minimal_gear_profile_height
  if(c['minimal_gear_profile_height']<radian_epsilon):
    print("ERR265: Error, minimal_gear_profile_height {:0.3f} is too small".format(c['minimal_gear_profile_height']))
    sys.exit(2)
  # gearbar_hole_diameter
  if((c['gearbar_hole_height_position']+c['gearbar_hole_radius'])>c['minimal_gear_profile_height']):
    print("ERR269: Error, gearbar_hole_height_position {:0.3f} and gearbar_hole_radius {:0.3f} are too big compare to minimal_gear_profile_height {:0.3f}".format(c['gearbar_hole_height_position'], c['gearbar_hole_radius'], c['minimal_gear_profile_height']))
    sys.exit(2)
  # pi_module
  if(c['gearbar_hole_radius']>0):
    if(c['pi_module']==0):
      print("ERR277: Error, pi_module is null. You might need to use --gear_module")
      sys.exit(2)
  ###
  return(c)
Ejemplo n.º 11
0
def gearbar_constraint_check(c):
    """ check the gearbar constraint c and set the dynamic default values
  """
    #print("dbg122: len(c)", len(c))
    ### precision
    radian_epsilon = math.pi / 1000
    ### check parameter coherence (part 1)
    c['gearbar_hole_radius'] = float(c['gearbar_hole_diameter']) / 2
    # c['gearbar_hole_height_position']
    if ((c['gearbar_hole_height_position'] + c['gearbar_hole_radius']) >
            c['gearbar_height']):
        print(
            "ERR215: Error, gearbar_hole_height_position {:0.3} and gearbar_hole_radius {:0.3f} are too big compare to gearbar_height {:0.3f} !"
            .format(c['gearbar_hole_height_position'],
                    c['gearbar_hole_radius'], c['gearbar_height']))
        sys.exit(2)
    # c['gearbar_hole_increment']
    if (c['gearbar_hole_increment'] == 0):
        print("ERR183: Error gearbar_hole_increment must be bigger than zero!")
        sys.exit(2)
    # c['gear_tooth_nb']
    if (c['gear_tooth_nb'] > 0):  # create a gear_profile
        i_gear_profile = inherit_gear_profile()  # inherit from gear_profile
        i_gear_profile.apply_external_constraint(gear_profile_constraint(c))
        gear_profile_parameters = i_gear_profile.get_constraint()
        # extract some gear_profile high-level parameter
        #print('dbg556: gear_profile_parameters:', gear_profile_parameters)
        c['g1_ix'] = gear_profile_parameters['g1_param']['center_ox']
        c['g1_iy'] = gear_profile_parameters['g1_param']['center_oy']
        c['g1_inclination'] = gear_profile_parameters['g1_param'][
            'gearbar_inclination']
        gear_profile_for_length = i_gear_profile.get_A_figure('first_gear')[0]
        gear_profile_for_length = cnc25d_api.outline_rotate(
            gear_profile_for_length, c['g1_ix'], c['g1_iy'],
            -1 * c['g1_inclination'] + math.pi / 2)
        gear_profile_for_length = cnc25d_api.outline_shift_xy(
            gear_profile_for_length, -1 * gear_profile_for_length[0][0], 1,
            -1 * c['g1_iy'] + c['gearbar_height'], 1)
        #print("dbg127: gear_profile_for_length:", gear_profile_for_length)
        c['gearbar_length'] = gear_profile_for_length[-1][
            0] - gear_profile_for_length[0][0]
        ## get some parameters
        c['minimal_gear_profile_height'] = c['gearbar_height'] - (
            gear_profile_parameters['g1_param']['hollow_height'] +
            gear_profile_parameters['g1_param']['dedendum_height'])
        c['pi_module'] = gear_profile_parameters['g1_param']['pi_module']
        pfe = gear_profile_parameters['g1_param']['portion_first_end']
        full_positive_slope = gear_profile_parameters['g1_param'][
            'full_positive_slope']
        full_negative_slope = gear_profile_parameters['g1_param'][
            'full_negative_slope']
        bottom_land = gear_profile_parameters['g1_param']['bottom_land']
        top_land = gear_profile_parameters['g1_param']['top_land']
        if ((top_land + full_positive_slope + bottom_land +
             full_negative_slope) != c['pi_module']):
            print(
                "ERR269: Error with top_land {:0.3f}  full_positive_slope {:0.3f}  bottom_land {:0.3f}  full_negative_slope {:0.3f} and pi_module  {:0.3f}"
                .format(top_land, full_positive_slope, bottom_land,
                        full_negative_slope, c['pi_module']))
            sys.exit(2)
        if (pfe == 0):
            c['first_tooth_position'] = full_positive_slope + bottom_land + full_negative_slope + float(
                top_land) / 2
        elif (pfe == 1):
            c['first_tooth_position'] = full_positive_slope + bottom_land + full_negative_slope + top_land
        elif (pfe == 2):
            c['first_tooth_position'] = full_negative_slope + float(
                top_land) / 2
        elif (pfe == 3):
            c['first_tooth_position'] = float(
                bottom_land) / 2 + full_negative_slope + float(top_land) / 2
    else:  # no gear_profile, just a circle
        if (c['gear_primitive_diameter'] < radian_epsilon):
            print(
                "ERR885: Error, the no-gear-profile line outline length gear_primitive_diameter {:0.2f} is too small!"
                .format(c['gear_primitive_diameter']))
            sys.exit(2)
        #c['g1_ix'] = c['center_position_x
        #c['g1_iy'] = c['center_position_y
        c['gearbar_length'] = c['gear_primitive_diameter']
        c['minimal_gear_profile_height'] = c['gearbar_height']
        c['pi_module'] = c['gear_module'] * math.pi
        c['first_tooth_position'] = float(c['pi_module']) / 2

    ### check parameter coherence (part 2)
    # minimal_gear_profile_height
    if (c['minimal_gear_profile_height'] < radian_epsilon):
        print(
            "ERR265: Error, minimal_gear_profile_height {:0.3f} is too small".
            format(c['minimal_gear_profile_height']))
        sys.exit(2)
    # gearbar_hole_diameter
    if ((c['gearbar_hole_height_position'] + c['gearbar_hole_radius']) >
            c['minimal_gear_profile_height']):
        print(
            "ERR269: Error, gearbar_hole_height_position {:0.3f} and gearbar_hole_radius {:0.3f} are too big compare to minimal_gear_profile_height {:0.3f}"
            .format(c['gearbar_hole_height_position'],
                    c['gearbar_hole_radius'],
                    c['minimal_gear_profile_height']))
        sys.exit(2)
    # pi_module
    if (c['gearbar_hole_radius'] > 0):
        if (c['pi_module'] == 0):
            print(
                "ERR277: Error, pi_module is null. You might need to use --gear_module"
            )
            sys.exit(2)
    ###
    return (c)
Ejemplo n.º 12
0
def cross_cube_top(ai_constraints):
    """ Generate the whole top figure
  """
    # alias
    cc_c = cross_cube_sub_top_check(ai_constraints)
    cccrbr = cc_c["cross_cube_cnc_router_bit_radius"]
    ccect = cc_c["cross_cube_extra_cut_thickness"]
    cw5 = cc_c["cube_width"] / 5.0
    fa1t = cc_c["face_A1_thickness"]
    fa2t = cc_c["face_A2_thickness"]
    fb1t = cc_c["face_B1_thickness"]
    fb2t = cc_c["face_B2_thickness"]
    #
    # top_sub_outline
    def top_sub_outline(ai_previous_face_thickness, ai_current_face_thickness, ai_post_face_thickness):
        """ Generate a sub-outline of the top_outline
    """
        #
        pre_ft = ai_previous_face_thickness
        cur_ft = ai_current_face_thickness
        post_ft = ai_post_face_thickness
        #
        r_top_sub_ol = []
        r_top_sub_ol.append((pre_ft + ccect, cur_ft + ccect, 0))
        r_top_sub_ol.append((1 * cw5, cur_ft + ccect, -1 * cccrbr))
        r_top_sub_ol.append((1 * cw5, 0, 0))
        r_top_sub_ol.append((2 * cw5, 0, 0))
        r_top_sub_ol.append((2 * cw5, cur_ft + ccect, -1 * cccrbr))
        r_top_sub_ol.append((3 * cw5, cur_ft + ccect, -1 * cccrbr))
        r_top_sub_ol.append((3 * cw5, 0, 0))
        r_top_sub_ol.append((4 * cw5, 0, 0))
        r_top_sub_ol.append((4 * cw5, cur_ft + ccect, -1 * cccrbr))
        r_top_sub_ol.append((5 * cw5 - post_ft - ccect, cur_ft + ccect, 0))
        #
        return r_top_sub_ol

    # top_outline
    top_ol = []
    top_ol.extend(
        cnc25d_api.outline_rotate(
            top_sub_outline(fb1t, fa1t, fb2t)[:-1], cc_c["cube_width"] / 2.0, cc_c["cube_width"] / 2.0, 0 * math.pi / 2
        )
    )
    top_ol.extend(
        cnc25d_api.outline_rotate(
            top_sub_outline(fa1t, fb2t, fa2t)[:-1], cc_c["cube_width"] / 2.0, cc_c["cube_width"] / 2.0, 1 * math.pi / 2
        )
    )
    top_ol.extend(
        cnc25d_api.outline_rotate(
            top_sub_outline(fb2t, fa2t, fb1t)[:-1], cc_c["cube_width"] / 2.0, cc_c["cube_width"] / 2.0, 2 * math.pi / 2
        )
    )
    top_ol.extend(
        cnc25d_api.outline_rotate(
            top_sub_outline(fa2t, fb1t, fa1t)[:-1], cc_c["cube_width"] / 2.0, cc_c["cube_width"] / 2.0, 3 * math.pi / 2
        )
    )
    top_ol = cnc25d_api.outline_close(top_ol)
    top_A = []
    top_A.append(top_ol)
    # holes
    if cc_c["top_rod_hole_radius"] > 0:
        top_A.append(
            (
                fb1t + cc_c["top_rod_hole_h_position"],
                fa1t + cc_c["top_rod_hole_h_position"],
                cc_c["top_rod_hole_radius"],
            )
        )
        top_A.append(
            (
                cc_c["cube_width"] - (fb2t + cc_c["top_rod_hole_h_position"]),
                fa1t + cc_c["top_rod_hole_h_position"],
                cc_c["top_rod_hole_radius"],
            )
        )
        top_A.append(
            (
                cc_c["cube_width"] - (fb2t + cc_c["top_rod_hole_h_position"]),
                cc_c["cube_width"] - (fa2t + cc_c["top_rod_hole_h_position"]),
                cc_c["top_rod_hole_radius"],
            )
        )
        top_A.append(
            (
                fb1t + cc_c["top_rod_hole_h_position"],
                cc_c["cube_width"] - (fa2t + cc_c["top_rod_hole_h_position"]),
                cc_c["top_rod_hole_radius"],
            )
        )
    # top-hollow
    # [todo]
    # return
    return top_A