def finger_pair(name, dx=0, dy=0): simple.make_active(name) xpos = (dx / 2) * 1.006 ypos = 1.006 * dy / 2 bpy.ops.object.duplicate_move( OBJECT_OT_duplicate={ "linked": False, "mode": 'TRANSLATION' }, TRANSFORM_OT_translate={"value": (xpos, ypos, 0.0)}) simple.active_name("_finger_pair") simple.make_active(name) bpy.ops.object.duplicate_move( OBJECT_OT_duplicate={ "linked": False, "mode": 'TRANSLATION' }, TRANSFORM_OT_translate={"value": (-xpos, -ypos, 0.0)}) simple.active_name("_finger_pair") simple.join_multiple("_finger_pair") bpy.ops.object.select_all(action='DESELECT') return bpy.context.active_object
def bar(width, thick, diameter, tolerance, amount=0, stem=1, twist=False, tneck=0.5, tthick=0.01, twist_keep=False, twist_line=False, twist_line_amount=2, which='MF'): # width = length of the bar # thick = thickness of the bar # diameter = diameter of the tool for joint creation # tolerance = Tolerance in the joint # amount = amount of fingers in the joint 0 means auto generate # stem = amount of radius the stem or neck of the joint will have # twist = twist lock addition # tneck = percentage the twist neck will have compared to thick # tthick = thicknest of the twist material # Which M,F, MF, MM, FF global DT if amount == 0: amount = round(thick / ((4 + 2 * (stem - 1)) * diameter * DT)) - 1 bpy.ops.curve.simple(align='WORLD', location=(0, 0, 0), rotation=(0, 0, 0), Simple_Type='Rectangle', Simple_width=width, Simple_length=thick, use_cyclic_u=True, edit_mode=False) simple.active_name('tmprect') fingers(diameter, tolerance, amount, stem=stem) if which == 'MM' or which == 'M' or which == 'MF': simple.rename('fingers', '_tmpfingers') simple.rotate(-math.pi / 2) simple.move(x=width / 2) simple.rename('tmprect', '_tmprect') simple.union('_tmp') simple.active_name("tmprect") twistm('tmprect', thick, diameter, tolerance, twist, tneck, tthick, -math.pi / 2, x=width / 2, twist_keep=twist_keep) twistf('receptacle', thick, diameter, tolerance, twist, tneck, tthick, twist_keep=twist_keep) simple.rename('receptacle', '_tmpreceptacle') if which == 'FF' or which == 'F' or which == 'MF': simple.rotate(-math.pi / 2) simple.move(x=-width / 2) simple.rename('tmprect', '_tmprect') simple.difference('_tmp', '_tmprect') simple.active_name("tmprect") if twist_keep: simple.make_active('twist_keep_f') simple.rotate(-math.pi / 2) simple.move(x=-width / 2) simple.remove_multiple("_") # Remove temporary base and holes simple.remove_multiple("fingers") # Remove temporary base and holes if twist_line: joinery.twist_line(thick, tthick, tolerance, tneck, twist_line_amount, width) if twist_keep: simple.duplicate() simple.active_name('tmptwist') simple.difference('tmp', 'tmprect') simple.rename('tmprect', 'Puzzle_bar') simple.remove_multiple("tmp") # Remove temporary base and holes simple.make_active('Puzzle_bar')
def arcbar(length, radius, thick, angle, diameter, tolerance, amount=0, stem=1, twist=False, tneck=0.5, tthick=0.01, twist_keep=False, which='MF', twist_line=False, twist_line_amount=2): # length is the total width of the segments including 2 * radius and thick # radius = radius of the curve # thick = thickness of the bar # angle = angle of the female part # diameter = diameter of the tool for joint creation # tolerance = Tolerance in the joint # amount = amount of fingers in the joint 0 means auto generate # stem = amount of radius the stem or neck of the joint will have # twist = twist lock addition # tneck = percentage the twist neck will have compared to thick # tthick = thicknest of the twist material # which = which joint to generate, Male Female MaleFemale M, F, MF if which == 'M': which = 'MM' elif which == 'F': which = 'FF' length -= (radius * 2 + thick) # adjust length to include 2x radius + thick # generate base rectangle # Generate male section and join to the base if which == 'MM' or which == 'MF': bar(length, thick, diameter, tolerance, amount=amount, stem=stem, twist=twist, tneck=tneck, tthick=tthick, which='M', twist_keep=twist_keep, twist_line=twist_line, twist_line_amount=twist_line_amount) simple.active_name('tmprect') if which == 'FF' or which == 'FM': bar(length, thick, diameter, tolerance, amount=amount, stem=stem, twist=twist, tneck=tneck, tthick=tthick, which='F', twist_keep=twist_keep, twist_line=twist_line, twist_line_amount=twist_line_amount) simple.rotate(math.pi) simple.active_name('tmprect') # Generate female section and join to base if which == 'FF' or which == 'MF': arc(radius, thick, angle, diameter, tolerance, amount=amount, stem=stem, twist=twist, tneck=tneck, tthick=tthick, which='F') simple.move(x=-length / 2 * 0.998) simple.active_name('tmp_receptacle') simple.union('tmp') simple.active_name('arcBar') simple.remove_multiple('tmp') if which == 'MM': arc(radius, thick, angle, diameter, tolerance, amount=amount, stem=stem, twist=twist, tneck=tneck, tthick=tthick, which='M') bpy.ops.transform.mirror(orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(True, False, False)) simple.move(x=-length / 2 * 0.998) simple.active_name('tmp_receptacle') simple.union('tmp') simple.active_name('arcBar') simple.remove_multiple('tmp') simple.make_active('arcBar')
def arcbararc(length, radius, thick, angle, angleb, diameter, tolerance, amount=0, stem=1, twist=False, tneck=0.5, tthick=0.01, which='MF', twist_keep=False, twist_line=False, twist_line_amount=2): # length is the total width of the segments including 2 * radius and thick # radius = radius of the curve # thick = thickness of the bar # angle = angle of the female part # angleb = angle of the male part # diameter = diameter of the tool for joint creation # tolerance = Tolerance in the joint # amount = amount of fingers in the joint 0 means auto generate # stem = amount of radius the stem or neck of the joint will have # twist = twist lock addition # tneck = percentage the twist neck will have compared to thick # tthick = thicknest of the twist material # which = which joint to generate, Male Female MaleFemale M, F, MF length -= (radius * 2 + thick) # adjust length to include 2x radius + thick # generate base rectangle bpy.ops.curve.simple(align='WORLD', location=(0, 0, 0), rotation=(0, 0, 0), Simple_Type='Rectangle', Simple_width=length * 1.005, Simple_length=thick, use_cyclic_u=True, edit_mode=False) simple.active_name("tmprect") # Generate male section and join to the base if which == 'M' or which == 'MF': arc(radius, thick, angleb, diameter, tolerance, amount=amount, stem=stem, twist=twist, tneck=tneck, tthick=tthick, which='M') simple.move(x=length / 2) simple.active_name('tmp_male') simple.select_multiple('tmp') bpy.ops.object.curve_boolean(boolean_type='UNION') simple.active_name('male') simple.remove_multiple('tmp') simple.rename('male', 'tmprect') # Generate female section and join to base if which == 'F' or which == 'MF': arc(radius, thick, angle, diameter, tolerance, amount=amount, stem=stem, twist=twist, tneck=tneck, tthick=tthick, which='F') simple.move(x=-length / 2) simple.active_name('tmp_receptacle') simple.union('tmp') simple.active_name('tmprect') if twist_line: joinery.twist_line(thick, tthick, tolerance, tneck, twist_line_amount, length) if twist_keep: simple.duplicate() simple.active_name('tmptwist') simple.difference('tmp', 'tmprect') simple.active_name('arcBarArc') simple.make_active('arcBarArc')
def twistf(name, length, diameter, tolerance, twist, tneck, tthick, twist_keep=False): # add twist lock to receptacle if twist: joinery.interlock_twist(length, tthick, tolerance, cx=0, cy=0, rotation=0, percentage=tneck) simple.rotate(math.pi / 2) simple.move(y=-tthick / 2 + 2 * diameter + 2 * tolerance) simple.active_name('xtemptwist') if twist_keep: simple.duplicate() simple.active_name('twist_keep_f') simple.make_active(name) simple.active_name('xtemp') simple.union('xtemp') simple.active_name(name)
def t(length, thick, diameter, tolerance, amount=0, stem=1, twist=False, tneck=0.5, tthick=0.01, combination='MF', base_gender='M', corner=False): if corner: if combination == 'MF': base_gender = 'M' combination = 'f' elif combination == 'F': base_gender = 'F' combination = 'f' elif combination == 'M': base_gender = 'M' combination = 'm' bar(length, thick, diameter, tolerance, amount=amount, stem=stem, twist=twist, tneck=tneck, tthick=tthick, which=base_gender) simple.active_name('tmp') fingers(diameter, tolerance, amount=amount, stem=stem) if combination == 'MF' or combination == 'M' or combination == 'm': simple.make_active('fingers') simple.move(y=thick / 2) simple.duplicate() simple.active_name('tmp') simple.union('tmp') if combination == 'M': simple.make_active('fingers') simple.mirrory() simple.active_name('tmp') simple.union('tmp') if combination == 'MF' or combination == 'F' or combination == 'f': simple.make_active('receptacle') simple.move(y=-thick / 2) simple.duplicate() simple.active_name('tmp') simple.difference('tmp', 'tmp') if combination == 'F': simple.make_active('receptacle') simple.mirrory() simple.active_name('tmp') simple.difference('tmp', 'tmp') simple.remove_multiple('receptacle') simple.remove_multiple('fingers') simple.rename('tmp', 't') simple.make_active('t')
def twistm(name, length, diameter, tolerance, twist, tneck, tthick, angle, twist_keep=False, x=0, y=0): # add twist lock to male connector global DT if twist: joinery.interlock_twist(length, tthick, tolerance, cx=0, cy=0, rotation=0, percentage=tneck) simple.rotate(math.pi / 2) simple.move(y=-tthick / 2 + 2 * diameter * DT) simple.rotate(angle) simple.move(x=x, y=y) simple.active_name('_twist') if twist_keep: simple.duplicate() simple.active_name('twist_keep_m') simple.make_active(name) simple.active_name('_tmp') simple.difference('_', '_tmp') simple.active_name(name)
def tile(diameter, tolerance, tile_x_amount, tile_y_amount, stem=1): global DT diameter = diameter * DT # diameter * DT * (2 + stem - 1) (4 + 2 * (stem - 1)) * diameter width = (tile_x_amount) * (4 + 2 * (stem - 1)) * diameter + diameter height = (tile_y_amount) * (4 + 2 * (stem - 1)) * diameter + diameter print('size:', width, height) fingers(diameter, tolerance, amount=tile_x_amount+2, stem=stem) simple.add_rectangle(width, height) simple.active_name('_base') simple.make_active('fingers') simple.active_name('_fingers') simple.intersect('_') simple.remove_multiple('_fingers') simple.rename('intersection', '_fingers') simple.move(y=height/2) simple.union('_') simple.active_name('_base') simple.remove_doubles() simple.rename('receptacle', '_receptacle') simple.move(y=-height/2) simple.difference('_', '_base') simple.active_name('base') fingers(diameter, tolerance, amount=tile_y_amount, stem=stem) simple.rename('base', '_base') simple.remove_doubles() simple.rename('fingers', '_fingers') simple.rotate(math.pi/2) simple.move(x=-width/2) simple.union('_') simple.active_name('_base') simple.rename('receptacle', '_receptacle') simple.rotate(math.pi/2) simple.move(x=width/2) simple.difference('_', '_base') simple.active_name('tile_ ' + str(tile_x_amount) + '_' + str(tile_y_amount))
def create_flex_side(length, height, finger_thick, top_bottom=False): # assumes the base fingers were created and exist # crates a flex side for mortise on curve # length = length of curve # height = height of side # finger_length = lenght of finger or mortise # finger_thick = finger thickness or thickness of material # finger_tol = Play for finger 0 is very tight # top_bottom = fingers on top and bottom if true, just on bottom if false # flex_pocket = width of pocket on the flex side. This is for kerf bending. if top_bottom: fingers = finger_pair("base", 0, height - finger_thick) else: simple.make_active("base") fingers = bpy.context.active_object bpy.ops.transform.translate(value=(0.0, height / 2 - finger_thick / 2 + 0.0003, 0.0)) bpy.ops.curve.simple(align='WORLD', location=(length / 2 + 0.00025, 0, 0), rotation=(0, 0, 0), Simple_Type='Rectangle', Simple_width=length, Simple_length=height, shape='3D', outputType='POLY', use_cyclic_u=True, handleType='AUTO', edit_mode=False) simple.active_name("_side") simple.make_active('_side') fingers.select_set(True) bpy.ops.object.curve_boolean(boolean_type='DIFFERENCE') simple.active_name("side") simple.remove_multiple('_') simple.remove_multiple('base')
def open_curve(line, thick, diameter, tolerance, amount=0, stem=1, twist=False, t_neck=0.5, t_thick=0.01, twist_amount=1, which='MF', twist_keep=False): # puts puzzle connectors at the end of an open curve # optionally puts twist lock connectors at the puzzle connection # optionally puts twist lock connectors along the open curve # line = shapely linestring # thick = thickness of the bar # diameter = diameter of the tool for joint creation # tolerance = Tolerance in the joint # amount = amount of fingers in the joint 0 means auto generate # stem = amount of radius the stem or neck of the joint will have # twist = twist lock addition # twist_amount = twist amount distributed on the curve not counting the joint twist locks # tneck = percentage the twist neck will have compared to thick # tthick = thicknest of the twist material # Which M,F, MF, MM, FF coords = list(line.coords) start_angle = joinery.angle(coords[0], coords[1]) + math.pi/2 end_angle = joinery.angle(coords[-1], coords[-2]) + math.pi/2 p_start = coords[0] p_end = coords[-1] print('start angle', start_angle) print('end angle', end_angle) bpy.ops.curve.simple(align='WORLD', location=(0, 0, 0), rotation=(0, 0, 0), Simple_Type='Rectangle', Simple_width=thick*2, Simple_length=thick * 2, use_cyclic_u=True, edit_mode=False, shape='3D') simple.active_name('tmprect') simple.move(y=thick) simple.duplicate() simple.rotate(start_angle) simple.move(x=p_start[0], y=p_start[1]) simple.make_active('tmprect') simple.rotate(end_angle) simple.move(x=p_end[0], y=p_end[1]) simple.union('tmprect') dilated = line.buffer(thick/2) # expand shapely object to thickness utils.shapelyToCurve('tmp_curve', dilated, 0.0) simple.difference('tmp', 'tmp_curve') # truncate curve at both ends with the rectangles fingers(diameter, tolerance, amount, stem=stem) simple.make_active('fingers') simple.rotate(end_angle) simple.move(x=p_end[0], y=p_end[1]) simple.active_name('tmp_fingers') simple.union('tmp_') simple.active_name('tmp_curve') twistm('tmp_curve', thick, diameter, tolerance, twist, t_neck, t_thick, end_angle, x=p_end[0], y=p_end[1], twist_keep=twist_keep) twistf('receptacle', thick, diameter, tolerance, twist, t_neck, t_thick, twist_keep=twist_keep) simple.rename('receptacle', 'tmp') simple.rotate(start_angle+math.pi) simple.move(x=p_start[0], y=p_start[1]) simple.difference('tmp', 'tmp_curve') if twist_keep: simple.make_active('twist_keep_f') simple.rotate(start_angle + math.pi) simple.move(x=p_start[0], y=p_start[1]) if twist_amount > 0 and twist: twist_start = line.length / (twist_amount+1) joinery.distributed_interlock(line, line.length, thick, t_thick, tolerance, twist_amount, tangent=math.pi/2, fixed_angle=0, start=twist_start, end=twist_start, closed=False, type='TWIST', twist_percentage=t_neck) if twist_keep: simple.duplicate() simple.active_name('twist_keep') simple.join_multiple('twist_keep') simple.make_active('interlock') simple.active_name('tmp_twist') simple.difference('tmp', 'tmp_curve') simple.active_name('puzzle_curve')
def mitre(length, thick, angle, angleb, diameter, tolerance, amount=0, stem=1, twist=False, tneck=0.5, tthick=0.01, which='MF'): # length is the total width of the segments including 2 * radius and thick # radius = radius of the curve # thick = thickness of the bar # angle = angle of the female part # angleb = angle of the male part # diameter = diameter of the tool for joint creation # tolerance = Tolerance in the joint # amount = amount of fingers in the joint 0 means auto generate # stem = amount of radius the stem or neck of the joint will have # twist = twist lock addition # tneck = percentage the twist neck will have compared to thick # tthick = thicknest of the twist material # which = which joint to generate, Male Female MaleFemale M, F, MF # generate base rectangle bpy.ops.curve.simple(align='WORLD', location=(0, -thick / 2, 0), rotation=(0, 0, 0), Simple_Type='Rectangle', Simple_width=length * 1.005 + 4 * thick, Simple_length=thick, use_cyclic_u=True, edit_mode=False, shape='3D') simple.active_name("tmprect") # generate cutout shapes bpy.ops.curve.simple(align='WORLD', location=(0, 0, 0), rotation=(0, 0, 0), Simple_Type='Rectangle', Simple_width=4 * thick, Simple_length=6 * thick, use_cyclic_u=True, edit_mode=False, shape='3D') simple.move(x=2 * thick) simple.rotate(angle) simple.move(x=length / 2) simple.active_name('tmpmitreright') bpy.ops.curve.simple(align='WORLD', location=(0, 0, 0), rotation=(0, 0, 0), Simple_Type='Rectangle', Simple_width=4 * thick, Simple_length=6 * thick, use_cyclic_u=True, edit_mode=False, shape='3D') simple.move(x=2 * thick) simple.rotate(angleb) simple.move(x=length / 2) simple.mirrorx() simple.active_name('tmpmitreleft') simple.difference('tmp', 'tmprect') simple.make_active('tmprect') fingers(diameter, tolerance, amount, stem=stem) # Generate male section and join to the base if which == 'M' or which == 'MF': simple.make_active('fingers') simple.duplicate() simple.active_name('tmpfingers') simple.rotate(angle - math.pi / 2) h = thick / math.cos(angle) h /= 2 simple.move(x=length / 2 + h * math.sin(angle), y=-thick / 2) if which == 'M': simple.rename('fingers', 'tmpfingers') simple.rotate(angleb - math.pi / 2) h = thick / math.cos(angleb) h /= 2 simple.move(x=length / 2 + h * math.sin(angleb), y=-thick / 2) simple.mirrorx() simple.union('tmp') simple.active_name('tmprect') # Generate female section and join to base if which == 'MF' or which == 'F': simple.make_active('receptacle') simple.mirrory() simple.duplicate() simple.active_name('tmpreceptacle') simple.rotate(angleb - math.pi / 2) h = thick / math.cos(angleb) h /= 2 simple.move(x=length / 2 + h * math.sin(angleb), y=-thick / 2) simple.mirrorx() if which == 'F': simple.rename('receptacle', 'tmpreceptacle2') simple.rotate(angle - math.pi / 2) h = thick / math.cos(angle) h /= 2 simple.move(x=length / 2 + h * math.sin(angle), y=-thick / 2) simple.difference('tmp', 'tmprect') simple.remove_multiple('receptacle') simple.remove_multiple('fingers') simple.rename('tmprect', 'mitre')
def arc(radius, thick, angle, diameter, tolerance, amount=0, stem=1, twist=False, tneck=0.5, tthick=0.01, twist_keep=False, which='MF'): # radius = radius of the curve # thick = thickness of the bar # angle = angle of the arc # diameter = diameter of the tool for joint creation # tolerance = Tolerance in the joint # amount = amount of fingers in the joint 0 means auto generate # stem = amount of radius the stem or neck of the joint will have # twist = twist lock addition # tneck = percentage the twist neck will have compared to thick # tthick = thicknest of the twist material # which = which joint to generate, Male Female MaleFemale M, F, MF global DT # diameter tolerance for diameter of finger creation if angle == 0: # angle cannot be 0 angle = 0.01 negative = False if angle < 0: # if angle < 0 then negative is true angle = -angle negative = True if amount == 0: amount = round(thick / ((4 + 2 * (stem - 1)) * diameter * DT)) - 1 fingers(diameter, tolerance, amount, stem=stem) twistf('receptacle', thick, diameter, tolerance, twist, tneck, tthick, twist_keep=twist_keep) # generate arc bpy.ops.curve.simple(align='WORLD', location=(0, 0, 0), rotation=(0, 0, 0), Simple_Type='Segment', Simple_a=radius - thick / 2, Simple_b=radius + thick / 2, Simple_startangle=-0.0001, Simple_endangle=math.degrees(angle), Simple_radius=radius, use_cyclic_u=False, edit_mode=False) bpy.context.active_object.name = "tmparc" simple.rename('fingers', '_tmpfingers') simple.rotate(math.pi) simple.move(x=radius) bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN') simple.rename('tmparc', '_tmparc') if which == 'MF' or which == 'M': simple.union('_tmp') simple.active_name("base") twistm('base', thick, diameter, tolerance, twist, tneck, tthick, math.pi, x=radius) simple.rename('base', '_tmparc') simple.rename('receptacle', '_tmpreceptacle') simple.mirrory() simple.move(x=radius) bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN') simple.rotate(angle) simple.make_active('_tmparc') if which == 'MF' or which == 'F': simple.difference('_tmp', '_tmparc') bpy.context.active_object.name = "PUZZLE_arc" bpy.ops.object.curve_remove_doubles() simple.remove_multiple("_") # Remove temporary base and holes simple.make_active('PUZZLE_arc') if which == 'M': simple.rotate(-angle) simple.mirrory() bpy.ops.object.transform_apply(location=True, rotation=True, scale=False) simple.rotate(-math.pi / 2) simple.move(y=radius) simple.rename('PUZZLE_arc', 'PUZZLE_arc_male') elif which == 'F': simple.mirrorx() simple.move(x=radius) simple.rotate(math.pi / 2) simple.rename('PUZZLE_arc', 'PUZZLE_arc_receptacle') else: simple.move(x=-radius) # bpy.ops.object.transform_apply(location=True, rotation=False, scale=False, properties=False) # if negative: # mirror if angle is negative simple.mirrory()