kopia lustrzana https://github.com/vilemduha/blendercam
				
				
				
			
		
			
				
	
	
		
			1460 wiersze
		
	
	
		
			45 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			1460 wiersze
		
	
	
		
			45 KiB
		
	
	
	
		
			Python
		
	
	
| """Fabex 'puzzle_joinery.py' © 2021 Alain Pelletier
 | |
| 
 | |
| Functions to add various puzzle joints as curves.
 | |
| """
 | |
| 
 | |
| from math import (
 | |
|     cos,
 | |
|     degrees,
 | |
|     pi,
 | |
|     sin,
 | |
|     sqrt,
 | |
|     tan,
 | |
| )
 | |
| 
 | |
| import bpy
 | |
| 
 | |
| from .constants import DT
 | |
| from . import joinery
 | |
| 
 | |
| from .utilities.shapely_utils import shapely_to_curve
 | |
| from .utilities.simple_utils import (
 | |
|     duplicate,
 | |
|     mirror_x,
 | |
|     mirror_y,
 | |
|     union,
 | |
|     intersect,
 | |
|     rename,
 | |
|     difference,
 | |
|     active_name,
 | |
|     move,
 | |
|     rotate,
 | |
|     make_active,
 | |
|     remove_multiple,
 | |
|     select_multiple,
 | |
|     join_multiple,
 | |
|     remove_doubles,
 | |
|     add_rectangle,
 | |
| )
 | |
| 
 | |
| 
 | |
| def finger(diameter, stem=2):
 | |
|     """Create a joint shape based on the specified diameter and stem.
 | |
| 
 | |
|     This function generates a 3D joint shape using Blender's curve
 | |
|     operations. It calculates the dimensions of a rectangle and an ellipse
 | |
|     based on the provided diameter and stem parameters. The function then
 | |
|     creates these shapes, duplicates and mirrors them, and performs boolean
 | |
|     operations to form the final joint shape. The resulting object is named
 | |
|     and cleaned up to ensure no overlapping vertices remain.
 | |
| 
 | |
|     Args:
 | |
|         diameter (float): The diameter of the tool for joint creation.
 | |
|         stem (float?): The amount of radius the stem or neck of the joint will have. Defaults
 | |
|             to 2.
 | |
| 
 | |
|     Returns:
 | |
|         None: This function does not return any value.
 | |
|     """
 | |
| 
 | |
|     # DT = Bit diameter tolerance
 | |
|     global DT
 | |
|     RESOLUTION = 12  # Data resolution
 | |
|     cube_sx = diameter * DT * (2 + stem - 1)
 | |
|     cube_ty = diameter * DT
 | |
|     cube_sy = 2 * diameter * DT
 | |
|     circle_radius = diameter * DT / 2
 | |
|     c1x = cube_sx / 2
 | |
|     c2x = cube_sx / 2
 | |
|     c2y = 3 * circle_radius
 | |
|     c1y = circle_radius
 | |
| 
 | |
|     bpy.ops.curve.simple(
 | |
|         align="WORLD",
 | |
|         location=(0, cube_ty, 0),
 | |
|         rotation=(0, 0, 0),
 | |
|         Simple_Type="Rectangle",
 | |
|         Simple_width=cube_sx,
 | |
|         Simple_length=cube_sy,
 | |
|         use_cyclic_u=True,
 | |
|         edit_mode=False,
 | |
|     )
 | |
|     bpy.context.active_object.name = "ftmprect"
 | |
| 
 | |
|     bpy.ops.curve.simple(
 | |
|         align="WORLD",
 | |
|         location=(c2x, c2y, 0),
 | |
|         rotation=(0, 0, 0),
 | |
|         Simple_Type="Ellipse",
 | |
|         Simple_a=circle_radius,
 | |
|         Simple_b=circle_radius,
 | |
|         Simple_sides=4,
 | |
|         use_cyclic_u=True,
 | |
|         edit_mode=False,
 | |
|         shape="3D",
 | |
|     )
 | |
| 
 | |
|     bpy.context.active_object.name = "ftmpcirc_add"
 | |
|     bpy.context.object.data.resolution_u = RESOLUTION
 | |
| 
 | |
|     bpy.ops.object.origin_set(type="ORIGIN_CURSOR", center="MEDIAN")
 | |
| 
 | |
|     duplicate()
 | |
|     mirror_x()
 | |
| 
 | |
|     union("ftmp")
 | |
|     rename("ftmp", "_sum")
 | |
| 
 | |
|     rc1 = circle_radius
 | |
| 
 | |
|     bpy.ops.curve.simple(
 | |
|         align="WORLD",
 | |
|         location=(c1x, c1y, 0),
 | |
|         rotation=(0, 0, 0),
 | |
|         Simple_Type="Ellipse",
 | |
|         Simple_a=circle_radius,
 | |
|         Simple_b=rc1,
 | |
|         Simple_sides=4,
 | |
|         use_cyclic_u=True,
 | |
|         edit_mode=False,
 | |
|         shape="3D",
 | |
|     )
 | |
| 
 | |
|     bpy.context.active_object.name = "_circ_delete"
 | |
|     bpy.context.object.data.resolution_u = RESOLUTION
 | |
|     bpy.ops.object.origin_set(type="ORIGIN_CURSOR", center="MEDIAN")
 | |
| 
 | |
|     duplicate()
 | |
|     mirror_x()
 | |
|     union("_circ")
 | |
| 
 | |
|     difference("_", "_sum")
 | |
|     bpy.ops.object.curve_remove_doubles()
 | |
|     rename("_sum", "_puzzle")
 | |
| 
 | |
| 
 | |
| def fingers(diameter, inside, amount=1, stem=1):
 | |
|     """Create a specified number of fingers for a joint tool.
 | |
| 
 | |
|     This function generates a set of fingers based on the provided diameter
 | |
|     and tolerance values. It calculates the necessary translations for
 | |
|     positioning the fingers and duplicates them if more than one is
 | |
|     required. Additionally, it creates a receptacle using a silhouette
 | |
|     offset from the fingers, allowing for precise joint creation.
 | |
| 
 | |
|     Args:
 | |
|         diameter (float): The diameter of the tool used for joint creation.
 | |
|         inside (float): The tolerance in the joint receptacle.
 | |
|         amount (int?): The number of fingers to create. Defaults to 1.
 | |
|         stem (float?): The amount of radius the stem or neck of the joint will have. Defaults
 | |
|             to 1.
 | |
|     """
 | |
| 
 | |
|     global DT  # Bit diameter tolerance
 | |
| 
 | |
|     xtranslate = -(4 + 2 * (stem - 1)) * (amount - 1) * diameter * DT / 2
 | |
|     finger(diameter, stem=stem)  # generate male finger
 | |
|     active_name("puzzlem")
 | |
|     move(x=xtranslate, y=-0.00002)
 | |
| 
 | |
|     if amount > 1:
 | |
|         # duplicate translate the amount needed (faster than generating new)
 | |
|         for i in range(amount - 1):
 | |
|             bpy.ops.object.duplicate_move(
 | |
|                 OBJECT_OT_duplicate={"linked": False, "mode": "TRANSLATION"},
 | |
|                 TRANSFORM_OT_translate={"value": ((4 + 2 * (stem - 1)) * diameter * DT, 0, 0.0)},
 | |
|             )
 | |
|         union("puzzle")
 | |
| 
 | |
|     active_name("fingers")
 | |
|     bpy.ops.object.origin_set(type="ORIGIN_CURSOR", center="MEDIAN")
 | |
| 
 | |
|     # Receptacle is made using the silhouette offset from the fingers
 | |
|     if inside > 0:
 | |
|         bpy.ops.object.silhouette_offset(offset=inside, style="1")
 | |
|         active_name("receptacle")
 | |
|         move(y=-inside)
 | |
| 
 | |
| 
 | |
| def twist_female(name, length, diameter, tolerance, twist, tneck, tthick, twist_keep=False):
 | |
|     """Add a twist lock to a receptacle.
 | |
| 
 | |
|     This function modifies the receptacle by adding a twist lock feature if
 | |
|     the `twist` parameter is set to True. It performs several operations
 | |
|     including interlocking the twist, rotating the object, and moving it to
 | |
|     the correct position. If `twist_keep` is True, it duplicates the twist
 | |
|     lock for further modifications. The function utilizes parameters such as
 | |
|     length, diameter, tolerance, and thickness to accurately create the
 | |
|     twist lock.
 | |
| 
 | |
|     Args:
 | |
|         name (str): The name of the receptacle to be modified.
 | |
|         length (float): The length of the receptacle.
 | |
|         diameter (float): The diameter of the receptacle.
 | |
|         tolerance (float): The tolerance value for the twist lock.
 | |
|         twist (bool): A flag indicating whether to add a twist lock.
 | |
|         tneck (float): The neck thickness for the twist lock.
 | |
|         tthick (float): The thickness of the twist lock.
 | |
|         twist_keep (bool?): A flag indicating whether to keep the twist
 | |
|             lock after duplication. Defaults to False.
 | |
|     """
 | |
| 
 | |
|     # add twist lock to receptacle
 | |
|     if twist:
 | |
|         joinery.interlock_twist(length, tthick, tolerance, cx=0, cy=0, rotation=0, percentage=tneck)
 | |
|         rotate(pi / 2)
 | |
|         move(y=-tthick / 2 + 2 * diameter + 2 * tolerance)
 | |
|         active_name("xtemptwist")
 | |
|         if twist_keep:
 | |
|             duplicate()
 | |
|             active_name("twist_keep_f")
 | |
|         make_active(name)
 | |
|         active_name("xtemp")
 | |
|         union("xtemp")
 | |
|         active_name(name)
 | |
| 
 | |
| 
 | |
| def twist_male(
 | |
|     name, length, diameter, tolerance, twist, tneck, tthick, angle, twist_keep=False, x=0, y=0
 | |
| ):
 | |
|     """Add a twist lock to a male connector.
 | |
| 
 | |
|     This function modifies the geometry of a male connector by adding a
 | |
|     twist lock feature. It utilizes various parameters to determine the
 | |
|     dimensions and positioning of the twist lock. If the `twist_keep`
 | |
|     parameter is set to True, it duplicates the twist lock for further
 | |
|     modifications. The function also allows for adjustments in position
 | |
|     through the `x` and `y` parameters.
 | |
| 
 | |
|     Args:
 | |
|         name (str): The name of the connector to be modified.
 | |
|         length (float): The length of the connector.
 | |
|         diameter (float): The diameter of the connector.
 | |
|         tolerance (float): The tolerance level for the twist lock.
 | |
|         twist (bool): A flag indicating whether to add a twist lock.
 | |
|         tneck (float): The neck thickness for the twist lock.
 | |
|         tthick (float): The thickness of the twist lock.
 | |
|         angle (float): The angle at which to rotate the twist lock.
 | |
|         twist_keep (bool?): A flag indicating whether to keep the twist lock duplicate. Defaults to
 | |
|             False.
 | |
|         x (float?): The x-coordinate for positioning. Defaults to 0.
 | |
|         y (float?): The y-coordinate for positioning. Defaults to 0.
 | |
| 
 | |
|     Returns:
 | |
|         None: This function modifies the state of the connector but does not return a
 | |
|             value.
 | |
|     """
 | |
| 
 | |
|     # add twist lock to male connector
 | |
|     global DT
 | |
|     if twist:
 | |
|         joinery.interlock_twist(length, tthick, tolerance, cx=0, cy=0, rotation=0, percentage=tneck)
 | |
|         rotate(pi / 2)
 | |
|         move(y=-tthick / 2 + 2 * diameter * DT)
 | |
|         rotate(angle)
 | |
|         move(x=x, y=y)
 | |
|         active_name("_twist")
 | |
|         if twist_keep:
 | |
|             duplicate()
 | |
|             active_name("twist_keep_m")
 | |
|         make_active(name)
 | |
|         active_name("_tmp")
 | |
|         difference("_", "_tmp")
 | |
|         active_name(name)
 | |
| 
 | |
| 
 | |
| 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",
 | |
| ):
 | |
|     """Create a bar with specified dimensions and joint features.
 | |
| 
 | |
|     This function generates a bar with customizable parameters such as
 | |
|     width, thickness, and joint characteristics. It can automatically
 | |
|     determine the number of fingers in the joint if the amount is set to
 | |
|     zero. The function also supports various options for twisting and neck
 | |
|     dimensions, allowing for flexible design of the bar according to the
 | |
|     specified parameters. The resulting bar can be manipulated further based
 | |
|     on the provided options.
 | |
| 
 | |
|     Args:
 | |
|         width (float): The length of the bar.
 | |
|         thick (float): The thickness of the bar.
 | |
|         diameter (float): The diameter of the tool used for joint creation.
 | |
|         tolerance (float): The tolerance in the joint.
 | |
|         amount (int?): The number of fingers in the joint; 0 means auto-generate. Defaults to
 | |
|             0.
 | |
|         stem (float?): The radius of the stem or neck of the joint. Defaults to 1.
 | |
|         twist (bool?): Whether to add a twist lock. Defaults to False.
 | |
|         tneck (float?): The percentage the twist neck will have compared to thickness. Defaults
 | |
|             to 0.5.
 | |
|         tthick (float?): The thickness of the twist material. Defaults to 0.01.
 | |
|         twist_keep (bool?): Whether to keep the twist feature. Defaults to False.
 | |
|         twist_line (bool?): Whether to add a twist line. Defaults to False.
 | |
|         twist_line_amount (int?): The amount for the twist line. Defaults to 2.
 | |
|         which (str?): Specifies the type of joint; options are 'M', 'F', 'MF', 'MM', 'FF'.
 | |
|             Defaults to 'MF'.
 | |
| 
 | |
|     Returns:
 | |
|         None: This function does not return a value but modifies the state of the 3D
 | |
|             model in Blender.
 | |
|     """
 | |
| 
 | |
|     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,
 | |
|     )
 | |
|     active_name("tmprect")
 | |
| 
 | |
|     fingers(diameter, tolerance, amount, stem=stem)
 | |
| 
 | |
|     if which == "MM" or which == "M" or which == "MF":
 | |
|         rename("fingers", "_tmpfingers")
 | |
|         rotate(-pi / 2)
 | |
|         move(x=width / 2)
 | |
|         rename("tmprect", "_tmprect")
 | |
|         union("_tmp")
 | |
|         active_name("tmprect")
 | |
|         twist_male(
 | |
|             "tmprect",
 | |
|             thick,
 | |
|             diameter,
 | |
|             tolerance,
 | |
|             twist,
 | |
|             tneck,
 | |
|             tthick,
 | |
|             -pi / 2,
 | |
|             x=width / 2,
 | |
|             twist_keep=twist_keep,
 | |
|         )
 | |
| 
 | |
|     twist_female(
 | |
|         "receptacle", thick, diameter, tolerance, twist, tneck, tthick, twist_keep=twist_keep
 | |
|     )
 | |
|     rename("receptacle", "_tmpreceptacle")
 | |
|     if which == "FF" or which == "F" or which == "MF":
 | |
|         rotate(-pi / 2)
 | |
|         move(x=-width / 2)
 | |
|         rename("tmprect", "_tmprect")
 | |
|         difference("_tmp", "_tmprect")
 | |
|         active_name("tmprect")
 | |
|         if twist_keep:
 | |
|             make_active("twist_keep_f")
 | |
|             rotate(-pi / 2)
 | |
|             move(x=-width / 2)
 | |
| 
 | |
|     remove_multiple("_")  # Remove temporary base and holes
 | |
|     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:
 | |
|             duplicate()
 | |
|         active_name("tmptwist")
 | |
|         difference("tmp", "tmprect")
 | |
|     rename("tmprect", "Puzzle_bar")
 | |
|     remove_multiple("tmp")  # Remove temporary base and holes
 | |
|     make_active("Puzzle_bar")
 | |
| 
 | |
| 
 | |
| def arc(
 | |
|     radius,
 | |
|     thick,
 | |
|     angle,
 | |
|     diameter,
 | |
|     tolerance,
 | |
|     amount=0,
 | |
|     stem=1,
 | |
|     twist=False,
 | |
|     tneck=0.5,
 | |
|     tthick=0.01,
 | |
|     twist_keep=False,
 | |
|     which="MF",
 | |
| ):
 | |
|     """Generate an arc with specified parameters.
 | |
| 
 | |
|     This function creates a 3D arc based on the provided radius, thickness,
 | |
|     angle, and other parameters. It handles the generation of fingers for
 | |
|     the joint and applies twisting features if specified. The function also
 | |
|     manages the orientation and positioning of the generated arc in a 3D
 | |
|     space.
 | |
| 
 | |
|     Args:
 | |
|         radius (float): The radius of the curve.
 | |
|         thick (float): The thickness of the bar.
 | |
|         angle (float): The angle of the arc (must not be zero).
 | |
|         diameter (float): The diameter of the tool for joint creation.
 | |
|         tolerance (float): Tolerance in the joint.
 | |
|         amount (int?): The amount of fingers in the joint; 0 means auto-generate. Defaults to
 | |
|             0.
 | |
|         stem (float?): The amount of radius the stem or neck of the joint will have. Defaults
 | |
|             to 1.
 | |
|         twist (bool?): Whether to add a twist lock. Defaults to False.
 | |
|         tneck (float?): Percentage the twist neck will have compared to thickness. Defaults to
 | |
|             0.5.
 | |
|         tthick (float?): Thickness of the twist material. Defaults to 0.01.
 | |
|         twist_keep (bool?): Whether to keep the twist. Defaults to False.
 | |
|         which (str?): Specifies which joint to generate ('M', 'F', 'MF'). Defaults to 'MF'.
 | |
| 
 | |
|     Returns:
 | |
|         None: This function does not return a value but modifies the 3D scene
 | |
|             directly.
 | |
|     """
 | |
| 
 | |
|     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)
 | |
|     twist_female(
 | |
|         "receptacle", thick, diameter, tolerance, twist, tneck, tthick, twist_keep=twist_keep
 | |
|     )
 | |
|     twist_female("testing", thick, diameter, tolerance, twist, tneck, tthick, twist_keep=twist_keep)
 | |
|     print("Generating Arc")
 | |
|     # 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=degrees(angle),
 | |
|         Simple_radius=radius,
 | |
|         use_cyclic_u=False,
 | |
|         edit_mode=False,
 | |
|     )
 | |
|     bpy.context.active_object.name = "tmparc"
 | |
| 
 | |
|     rename("fingers", "_tmpfingers")
 | |
| 
 | |
|     rotate(pi)
 | |
|     move(x=radius)
 | |
|     bpy.ops.object.origin_set(type="ORIGIN_CURSOR", center="MEDIAN")
 | |
| 
 | |
|     rename("tmparc", "_tmparc")
 | |
|     if which == "MF" or which == "M":
 | |
|         union("_tmp")
 | |
|         active_name("base")
 | |
|         twist_male("base", thick, diameter, tolerance, twist, tneck, tthick, pi, x=radius)
 | |
|         rename("base", "_tmparc")
 | |
| 
 | |
|     rename("receptacle", "_tmpreceptacle")
 | |
|     mirror_y()
 | |
|     move(x=radius)
 | |
|     bpy.ops.object.origin_set(type="ORIGIN_CURSOR", center="MEDIAN")
 | |
|     rotate(angle)
 | |
|     make_active("_tmparc")
 | |
| 
 | |
|     if which == "MF" or which == "F":
 | |
|         difference("_tmp", "_tmparc")
 | |
|     bpy.context.active_object.name = "PUZZLE_arc"
 | |
|     bpy.ops.object.curve_remove_doubles()
 | |
|     remove_multiple("_")  # Remove temporary base and holes
 | |
|     make_active("PUZZLE_arc")
 | |
|     if which == "M":
 | |
|         rotate(-angle)
 | |
|         mirror_y()
 | |
|         bpy.ops.object.transform_apply(location=True, rotation=True, scale=False)
 | |
|         rotate(-pi / 2)
 | |
|         move(y=radius)
 | |
|         rename("PUZZLE_arc", "PUZZLE_arc_male")
 | |
|     elif which == "F":
 | |
|         mirror_x()
 | |
|         move(x=radius)
 | |
|         rotate(pi / 2)
 | |
|         rename("PUZZLE_arc", "PUZZLE_arc_receptacle")
 | |
|     else:
 | |
|         move(x=-radius)
 | |
|     # bpy.ops.object.transform_apply(location=True, rotation=False, scale=False, properties=False)
 | |
|     #
 | |
|     if negative:  # mirror if angle is negative
 | |
|         mirror_y()
 | |
|     #
 | |
|     # bpy.ops.object.curve_remove_doubles()
 | |
| 
 | |
| 
 | |
| def arc_bar_arc(
 | |
|     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,
 | |
| ):
 | |
|     """Generate an arc bar joint with specified parameters.
 | |
| 
 | |
|     This function creates a joint consisting of male and female sections
 | |
|     based on the provided parameters. It adjusts the length to account for
 | |
|     the radius and thickness, generates a base rectangle, and then
 | |
|     constructs the male and/or female sections as specified. Additionally,
 | |
|     it can create a twist lock feature if required. The function utilizes
 | |
|     Blender's bpy operations to manipulate 3D objects.
 | |
| 
 | |
|     Args:
 | |
|         length (float): The total width of the segments including 2 * radius and thickness.
 | |
|         radius (float): The radius of the curve.
 | |
|         thick (float): The thickness of the bar.
 | |
|         angle (float): The angle of the female part.
 | |
|         angleb (float): The angle of the male part.
 | |
|         diameter (float): The diameter of the tool for joint creation.
 | |
|         tolerance (float): Tolerance in the joint.
 | |
|         amount (int?): The number of fingers in the joint; 0 means auto-generate. Defaults to
 | |
|             0.
 | |
|         stem (float?): The amount of radius the stem or neck of the joint will have. Defaults
 | |
|             to 1.
 | |
|         twist (bool?): Whether to add a twist lock feature. Defaults to False.
 | |
|         tneck (float?): Percentage the twist neck will have compared to thickness. Defaults to
 | |
|             0.5.
 | |
|         tthick (float?): Thickness of the twist material. Defaults to 0.01.
 | |
|         which (str?): Specifies which joint to generate ('M', 'F', or 'MF'). Defaults to 'MF'.
 | |
|         twist_keep (bool?): Whether to keep the twist after creation. Defaults to False.
 | |
|         twist_line (bool?): Whether to create a twist line feature. Defaults to False.
 | |
|         twist_line_amount (int?): Amount for the twist line feature. Defaults to 2.
 | |
| 
 | |
|     Returns:
 | |
|         None: This function does not return a value but modifies the Blender scene
 | |
|             directly.
 | |
|     """
 | |
| 
 | |
|     # adjust length to include 2x radius + thick
 | |
|     length -= radius * 2 + 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,
 | |
|     )
 | |
|     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",
 | |
|         )
 | |
|         move(x=length / 2)
 | |
|         active_name("tmp_male")
 | |
|         select_multiple("tmp")
 | |
|         bpy.ops.object.curve_boolean(boolean_type="UNION")
 | |
|         active_name("male")
 | |
|         remove_multiple("tmp")
 | |
|         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",
 | |
|         )
 | |
|         move(x=-length / 2)
 | |
|         active_name("tmp_receptacle")
 | |
|         union("tmp")
 | |
|         active_name("tmprect")
 | |
| 
 | |
|     if twist_line:
 | |
|         joinery.twist_line(thick, tthick, tolerance, tneck, twist_line_amount, length)
 | |
|         if twist_keep:
 | |
|             duplicate()
 | |
|         active_name("tmptwist")
 | |
|         difference("tmp", "tmprect")
 | |
| 
 | |
|     active_name("arcBarArc")
 | |
|     make_active("arcBarArc")
 | |
| 
 | |
| 
 | |
| def arc_bar(
 | |
|     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,
 | |
| ):
 | |
|     """Generate an arc bar joint based on specified parameters.
 | |
| 
 | |
|     This function constructs an arc bar joint by generating male and female
 | |
|     sections according to the specified parameters such as length, radius,
 | |
|     thickness, and joint type. The function adjusts the length to account
 | |
|     for the radius and thickness of the bar and creates the appropriate
 | |
|     geometric shapes for the joint. It also includes options for twisting
 | |
|     and adjusting the neck thickness of the joint.
 | |
| 
 | |
|     Args:
 | |
|         length (float): The total width of the segments including 2 * radius and thickness.
 | |
|         radius (float): The radius of the curve.
 | |
|         thick (float): The thickness of the bar.
 | |
|         angle (float): The angle of the female part.
 | |
|         diameter (float): The diameter of the tool for joint creation.
 | |
|         tolerance (float): Tolerance in the joint.
 | |
|         amount (int?): The number of fingers in the joint; 0 means auto-generate. Defaults to
 | |
|             0.
 | |
|         stem (float?): The amount of radius the stem or neck of the joint will have. Defaults
 | |
|             to 1.
 | |
|         twist (bool?): Whether to add a twist lock. Defaults to False.
 | |
|         tneck (float?): Percentage the twist neck will have compared to thickness. Defaults to
 | |
|             0.5.
 | |
|         tthick (float?): Thickness of the twist material. Defaults to 0.01.
 | |
|         twist_keep (bool?): Whether to keep the twist. Defaults to False.
 | |
|         which (str?): Specifies which joint to generate ('M', 'F', 'MF'). Defaults to 'MF'.
 | |
|         twist_line (bool?): Whether to include a twist line. Defaults to False.
 | |
|         twist_line_amount (int?): Amount of twist line. Defaults to 2.
 | |
|     """
 | |
| 
 | |
|     if which == "M":
 | |
|         which = "MM"
 | |
|     elif which == "F":
 | |
|         which = "FF"
 | |
|     # adjust length to include 2x radius + thick
 | |
|     length -= radius * 2 + 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,
 | |
|         )
 | |
|         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,
 | |
|         )
 | |
|         rotate(pi)
 | |
|         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",
 | |
|         )
 | |
|         move(x=-length / 2 * 0.998)
 | |
|         active_name("tmp_receptacle")
 | |
|         union("tmp")
 | |
|         active_name("arcBar")
 | |
|         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),
 | |
|         )
 | |
|         move(x=-length / 2 * 0.998)
 | |
|         active_name("tmp_receptacle")
 | |
|         union("tmp")
 | |
|         active_name("arcBar")
 | |
|         remove_multiple("tmp")
 | |
| 
 | |
|     make_active("arcBar")
 | |
| 
 | |
| 
 | |
| def multiangle(
 | |
|     radius,
 | |
|     thick,
 | |
|     angle,
 | |
|     diameter,
 | |
|     tolerance,
 | |
|     amount=0,
 | |
|     stem=1,
 | |
|     twist=False,
 | |
|     tneck=0.5,
 | |
|     tthick=0.01,
 | |
|     combination="MFF",
 | |
| ):
 | |
|     """Generate a multi-angle joint based on specified parameters.
 | |
| 
 | |
|     This function creates a multi-angle joint by generating various
 | |
|     geometric shapes using the provided parameters such as radius,
 | |
|     thickness, angle, diameter, and tolerance. It utilizes Blender's
 | |
|     operations to create and manipulate curves, resulting in a joint that
 | |
|     can be customized with different combinations of male and female parts.
 | |
|     The function also allows for automatic generation of the number of
 | |
|     fingers in the joint and includes options for twisting and neck
 | |
|     dimensions.
 | |
| 
 | |
|     Args:
 | |
|         radius (float): The radius of the curve.
 | |
|         thick (float): The thickness of the bar.
 | |
|         angle (float): The angle of the female part.
 | |
|         diameter (float): The diameter of the tool for joint creation.
 | |
|         tolerance (float): Tolerance in the joint.
 | |
|         amount (int?): The amount of fingers in the joint; 0 means auto-generate. Defaults to
 | |
|             0.
 | |
|         stem (float?): The amount of radius the stem or neck of the joint will have. Defaults
 | |
|             to 1.
 | |
|         twist (bool?): Indicates if a twist lock addition is required. Defaults to False.
 | |
|         tneck (float?): Percentage the twist neck will have compared to thickness. Defaults to
 | |
|             0.5.
 | |
|         tthick (float?): Thickness of the twist material. Defaults to 0.01.
 | |
|         combination (str?): Specifies which joint to generate ('M', 'F', 'MF', 'MFF', 'MMF').
 | |
|             Defaults to 'MFF'.
 | |
| 
 | |
|     Returns:
 | |
|         None: This function does not return a value but performs operations in
 | |
|             Blender.
 | |
|     """
 | |
| 
 | |
|     r_exterior = radius + thick / 2
 | |
|     r_interior = radius - thick / 2
 | |
| 
 | |
|     height = sqrt(r_exterior * r_exterior - radius * radius) + r_interior / 4
 | |
| 
 | |
|     bpy.ops.curve.simple(
 | |
|         align="WORLD",
 | |
|         location=(0, height, 0),
 | |
|         rotation=(0, 0, 0),
 | |
|         Simple_Type="Rectangle",
 | |
|         Simple_width=r_interior,
 | |
|         Simple_length=r_interior / 2,
 | |
|         use_cyclic_u=True,
 | |
|         edit_mode=False,
 | |
|         shape="3D",
 | |
|     )
 | |
|     active_name("tmp_rect")
 | |
| 
 | |
|     bpy.ops.curve.simple(
 | |
|         align="WORLD",
 | |
|         location=(0, 0, 0),
 | |
|         rotation=(0, 0, 0),
 | |
|         Simple_Type="Circle",
 | |
|         Simple_sides=4,
 | |
|         Simple_radius=r_interior,
 | |
|         shape="3D",
 | |
|         use_cyclic_u=True,
 | |
|         edit_mode=False,
 | |
|     )
 | |
|     move(y=radius * tan(angle))
 | |
|     active_name("tmpCircle")
 | |
| 
 | |
|     arc(
 | |
|         radius,
 | |
|         thick,
 | |
|         angle,
 | |
|         diameter,
 | |
|         tolerance,
 | |
|         amount=amount,
 | |
|         stem=stem,
 | |
|         twist=twist,
 | |
|         tneck=tneck,
 | |
|         tthick=tthick,
 | |
|         which="MF",
 | |
|     )
 | |
|     active_name("tmp_arc")
 | |
|     if combination == "MFF":
 | |
|         duplicate()
 | |
|         mirror_x()
 | |
|     elif combination == "MMF":
 | |
|         arc(
 | |
|             radius,
 | |
|             thick,
 | |
|             angle,
 | |
|             diameter,
 | |
|             tolerance,
 | |
|             amount=amount,
 | |
|             stem=stem,
 | |
|             twist=twist,
 | |
|             tneck=tneck,
 | |
|             tthick=tthick,
 | |
|             which="M",
 | |
|         )
 | |
|         active_name("tmp_arc")
 | |
|         mirror_y()
 | |
|         rotate(pi / 2)
 | |
|     union("tmp_")
 | |
|     difference("tmp", "tmp_")
 | |
|     active_name("multiAngle60")
 | |
| 
 | |
| 
 | |
| 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,
 | |
| ):
 | |
|     """Generate a 3D model based on specified parameters.
 | |
| 
 | |
|     This function creates a 3D model by manipulating geometric shapes based
 | |
|     on the provided parameters. It handles different combinations of shapes
 | |
|     and orientations based on the specified gender and corner options. The
 | |
|     function utilizes several helper functions to perform operations such as
 | |
|     moving, duplicating, and uniting shapes to form the final model.
 | |
| 
 | |
|     Args:
 | |
|         length (float): The length of the model.
 | |
|         thick (float): The thickness of the model.
 | |
|         diameter (float): The diameter of the model.
 | |
|         tolerance (float): The tolerance level for the model dimensions.
 | |
|         amount (int?): The amount of material to use. Defaults to 0.
 | |
|         stem (int?): The stem value for the model. Defaults to 1.
 | |
|         twist (bool?): Whether to apply a twist to the model. Defaults to False.
 | |
|         tneck (float?): The neck thickness. Defaults to 0.5.
 | |
|         tthick (float?): The thickness for the neck. Defaults to 0.01.
 | |
|         combination (str?): The combination type ('MF', 'F', 'M'). Defaults to 'MF'.
 | |
|         base_gender (str?): The base gender for the model ('M' or 'F'). Defaults to 'M'.
 | |
|         corner (bool?): Whether to apply corner adjustments. Defaults to False.
 | |
| 
 | |
|     Returns:
 | |
|         None: This function does not return a value but modifies the 3D model
 | |
|             directly.
 | |
|     """
 | |
| 
 | |
|     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,
 | |
|     )
 | |
|     active_name("tmp")
 | |
|     fingers(diameter, tolerance, amount=amount, stem=stem)
 | |
|     if combination == "MF" or combination == "M" or combination == "m":
 | |
|         make_active("fingers")
 | |
|         move(y=thick / 2)
 | |
|         duplicate()
 | |
|         active_name("tmp")
 | |
|         union("tmp")
 | |
| 
 | |
|     if combination == "M":
 | |
|         make_active("fingers")
 | |
|         mirror_y()
 | |
|         active_name("tmp")
 | |
|         union("tmp")
 | |
| 
 | |
|     if combination == "MF" or combination == "F" or combination == "f":
 | |
|         make_active("receptacle")
 | |
|         move(y=-thick / 2)
 | |
|         duplicate()
 | |
|         active_name("tmp")
 | |
|         difference("tmp", "tmp")
 | |
| 
 | |
|     if combination == "F":
 | |
|         make_active("receptacle")
 | |
|         mirror_y()
 | |
|         active_name("tmp")
 | |
|         difference("tmp", "tmp")
 | |
| 
 | |
|     remove_multiple("receptacle")
 | |
|     remove_multiple("fingers")
 | |
| 
 | |
|     rename("tmp", "t")
 | |
|     make_active("t")
 | |
| 
 | |
| 
 | |
| def curved_t(
 | |
|     length,
 | |
|     thick,
 | |
|     radius,
 | |
|     diameter,
 | |
|     tolerance,
 | |
|     amount=0,
 | |
|     stem=1,
 | |
|     twist=False,
 | |
|     tneck=0.5,
 | |
|     tthick=0.01,
 | |
|     combination="MF",
 | |
|     base_gender="M",
 | |
| ):
 | |
|     """Create a curved shape based on specified parameters.
 | |
| 
 | |
|     This function generates a 3D curved shape using the provided dimensions
 | |
|     and characteristics. It utilizes the `bar` and `arc` functions to create
 | |
|     the desired geometry and applies transformations such as mirroring and
 | |
|     union operations to achieve the final shape. The function also allows
 | |
|     for customization based on the gender specification, which influences
 | |
|     the shape's design.
 | |
| 
 | |
|     Args:
 | |
|         length (float): The length of the bar.
 | |
|         thick (float): The thickness of the bar.
 | |
|         radius (float): The radius of the arc.
 | |
|         diameter (float): The diameter used in arc creation.
 | |
|         tolerance (float): The tolerance level for the shape.
 | |
|         amount (int?): The amount parameter for the shape generation. Defaults to 0.
 | |
|         stem (int?): The stem parameter for the shape generation. Defaults to 1.
 | |
|         twist (bool?): A flag indicating whether to apply a twist to the shape. Defaults to
 | |
|             False.
 | |
|         tneck (float?): The neck thickness parameter. Defaults to 0.5.
 | |
|         tthick (float?): The thickness parameter for the neck. Defaults to 0.01.
 | |
|         combination (str?): The combination type for the shape. Defaults to 'MF'.
 | |
|         base_gender (str?): The base gender for the shape design. Defaults to 'M'.
 | |
| 
 | |
|     Returns:
 | |
|         None: This function does not return a value but modifies the 3D model in the
 | |
|             environment.
 | |
|     """
 | |
| 
 | |
|     bar(
 | |
|         length,
 | |
|         thick,
 | |
|         diameter,
 | |
|         tolerance,
 | |
|         amount=amount,
 | |
|         stem=stem,
 | |
|         twist=twist,
 | |
|         tneck=tneck,
 | |
|         tthick=tthick,
 | |
|         which=combination,
 | |
|     )
 | |
|     active_name("tmpbar")
 | |
| 
 | |
|     bpy.ops.curve.simple(
 | |
|         align="WORLD",
 | |
|         location=(0, 0, 0),
 | |
|         rotation=(0, 0, 0),
 | |
|         Simple_Type="Rectangle",
 | |
|         Simple_width=3 * radius,
 | |
|         Simple_length=thick,
 | |
|         use_cyclic_u=True,
 | |
|         edit_mode=False,
 | |
|     )
 | |
|     active_name("tmp_rect")
 | |
| 
 | |
|     if base_gender == "MF":
 | |
|         arc(
 | |
|             radius,
 | |
|             thick,
 | |
|             pi / 2,
 | |
|             diameter,
 | |
|             tolerance,
 | |
|             amount=amount,
 | |
|             stem=stem,
 | |
|             twist=twist,
 | |
|             tneck=tneck,
 | |
|             tthick=tthick,
 | |
|             which="M",
 | |
|         )
 | |
|         move(-radius)
 | |
|         active_name("tmp_arc")
 | |
|         arc(
 | |
|             radius,
 | |
|             thick,
 | |
|             pi / 2,
 | |
|             diameter,
 | |
|             tolerance,
 | |
|             amount=amount,
 | |
|             stem=stem,
 | |
|             twist=twist,
 | |
|             tneck=tneck,
 | |
|             tthick=tthick,
 | |
|             which="F",
 | |
|         )
 | |
|         move(radius)
 | |
|         mirror_y()
 | |
|         active_name("tmp_arc")
 | |
|         union("tmp_arc")
 | |
|         duplicate()
 | |
|         mirror_x()
 | |
|         union("tmp_arc")
 | |
|         difference("tmp_", "tmp_arc")
 | |
|     else:
 | |
|         arc(
 | |
|             radius,
 | |
|             thick,
 | |
|             pi / 2,
 | |
|             diameter,
 | |
|             tolerance,
 | |
|             amount=amount,
 | |
|             stem=stem,
 | |
|             twist=twist,
 | |
|             tneck=tneck,
 | |
|             tthick=tthick,
 | |
|             which=base_gender,
 | |
|         )
 | |
|         active_name("tmp_arc")
 | |
|         difference("tmp_", "tmp_arc")
 | |
|         if base_gender == "M":
 | |
|             move(-radius)
 | |
|         else:
 | |
|             move(radius)
 | |
|         duplicate()
 | |
|         mirror_x()
 | |
| 
 | |
|     union("tmp")
 | |
|     active_name("curved_t")
 | |
| 
 | |
| 
 | |
| def mitre(
 | |
|     length,
 | |
|     thick,
 | |
|     angle,
 | |
|     angleb,
 | |
|     diameter,
 | |
|     tolerance,
 | |
|     amount=0,
 | |
|     stem=1,
 | |
|     twist=False,
 | |
|     tneck=0.5,
 | |
|     tthick=0.01,
 | |
|     which="MF",
 | |
| ):
 | |
|     """Generate a mitre joint based on specified parameters.
 | |
| 
 | |
|     This function creates a 3D representation of a mitre joint using
 | |
|     Blender's bpy.ops.curve.simple operations. It generates a base rectangle
 | |
|     and cutout shapes, then constructs male and female sections of the joint
 | |
|     based on the provided angles and dimensions. The function allows for
 | |
|     customization of various parameters such as thickness, diameter,
 | |
|     tolerance, and the number of fingers in the joint. The resulting joint
 | |
|     can be either male, female, or a combination of both.
 | |
| 
 | |
|     Args:
 | |
|         length (float): The total width of the segments including 2 * radius and thickness.
 | |
|         thick (float): The thickness of the bar.
 | |
|         angle (float): The angle of the female part.
 | |
|         angleb (float): The angle of the male part.
 | |
|         diameter (float): The diameter of the tool for joint creation.
 | |
|         tolerance (float): Tolerance in the joint.
 | |
|         amount (int?): Amount of fingers in the joint; 0 means auto-generate. Defaults to 0.
 | |
|         stem (float?): Amount of radius the stem or neck of the joint will have. Defaults to 1.
 | |
|         twist (bool?): Indicates if a twist lock addition is required. Defaults to False.
 | |
|         tneck (float?): Percentage the twist neck will have compared to thickness. Defaults to
 | |
|             0.5.
 | |
|         tthick (float?): Thickness of the twist material. Defaults to 0.01.
 | |
|         which (str?): Specifies which joint to generate ('M', 'F', 'MF'). Defaults to '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",
 | |
|     )
 | |
|     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",
 | |
|     )
 | |
|     move(x=2 * thick)
 | |
|     rotate(angle)
 | |
|     move(x=length / 2)
 | |
|     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",
 | |
|     )
 | |
|     move(x=2 * thick)
 | |
|     rotate(angleb)
 | |
|     move(x=length / 2)
 | |
|     mirror_x()
 | |
|     active_name("tmpmitreleft")
 | |
|     difference("tmp", "tmprect")
 | |
|     make_active("tmprect")
 | |
| 
 | |
|     fingers(diameter, tolerance, amount, stem=stem)
 | |
| 
 | |
|     #  Generate male section and join to the base
 | |
|     if which == "M" or which == "MF":
 | |
|         make_active("fingers")
 | |
|         duplicate()
 | |
|         active_name("tmpfingers")
 | |
|         rotate(angle - pi / 2)
 | |
|         h = thick / cos(angle)
 | |
|         h /= 2
 | |
|         move(x=length / 2 + h * sin(angle), y=-thick / 2)
 | |
|         if which == "M":
 | |
|             rename("fingers", "tmpfingers")
 | |
|             rotate(angleb - pi / 2)
 | |
|             h = thick / cos(angleb)
 | |
|             h /= 2
 | |
|             move(x=length / 2 + h * sin(angleb), y=-thick / 2)
 | |
|             mirror_x()
 | |
| 
 | |
|         union("tmp")
 | |
|         active_name("tmprect")
 | |
| 
 | |
|     # Generate female section and join to base
 | |
|     if which == "MF" or which == "F":
 | |
|         make_active("receptacle")
 | |
|         mirror_y()
 | |
|         duplicate()
 | |
|         active_name("tmpreceptacle")
 | |
|         rotate(angleb - pi / 2)
 | |
|         h = thick / cos(angleb)
 | |
|         h /= 2
 | |
|         move(x=length / 2 + h * sin(angleb), y=-thick / 2)
 | |
|         mirror_x()
 | |
|         if which == "F":
 | |
|             rename("receptacle", "tmpreceptacle2")
 | |
|             rotate(angle - pi / 2)
 | |
|             h = thick / cos(angle)
 | |
|             h /= 2
 | |
|             move(x=length / 2 + h * sin(angle), y=-thick / 2)
 | |
|         difference("tmp", "tmprect")
 | |
| 
 | |
|     remove_multiple("receptacle")
 | |
|     remove_multiple("fingers")
 | |
|     rename("tmprect", "mitre")
 | |
| 
 | |
| 
 | |
| 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,
 | |
| ):
 | |
|     """Open a curve and add puzzle connectors with optional twist lock
 | |
|     connectors.
 | |
| 
 | |
|     This function takes a shapely LineString and creates an open curve with
 | |
|     specified parameters such as thickness, diameter, tolerance, and twist
 | |
|     options. It generates puzzle connectors at the ends of the curve and can
 | |
|     optionally add twist lock connectors along the curve. The function also
 | |
|     handles the creation of the joint based on the provided parameters,
 | |
|     ensuring that the resulting geometry meets the specified design
 | |
|     requirements.
 | |
| 
 | |
|     Args:
 | |
|         line (LineString): A shapely LineString representing the path of the curve.
 | |
|         thick (float): The thickness of the bar used in the joint.
 | |
|         diameter (float): The diameter of the tool for joint creation.
 | |
|         tolerance (float): The tolerance in the joint.
 | |
|         amount (int?): The number of fingers in the joint; 0 means auto-generate. Defaults to
 | |
|             0.
 | |
|         stem (float?): The amount of radius the stem or neck of the joint will have. Defaults
 | |
|             to 1.
 | |
|         twist (bool?): Whether to add twist lock connectors. Defaults to False.
 | |
|         t_neck (float?): The percentage the twist neck will have compared to thickness. Defaults
 | |
|             to 0.5.
 | |
|         t_thick (float?): The thickness of the twist material. Defaults to 0.01.
 | |
|         twist_amount (int?): The amount of twist distributed on the curve, not counting joint twists.
 | |
|             Defaults to 1.
 | |
|         which (str?): Specifies the type of joint; options include 'M', 'F', 'MF', 'MM', 'FF'.
 | |
|             Defaults to 'MF'.
 | |
|         twist_keep (bool?): Whether to keep the twist lock connectors. Defaults to False.
 | |
| 
 | |
|     Returns:
 | |
|         None: This function does not return a value but modifies the geometry in the
 | |
|             Blender context.
 | |
|     """
 | |
| 
 | |
|     coords = list(line.coords)
 | |
| 
 | |
|     start_angle = joinery.angle(coords[0], coords[1]) + pi / 2
 | |
|     end_angle = joinery.angle(coords[-1], coords[-2]) + 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",
 | |
|     )
 | |
|     active_name("tmprect")
 | |
|     move(y=thick)
 | |
|     duplicate()
 | |
|     rotate(start_angle)
 | |
|     move(x=p_start[0], y=p_start[1])
 | |
|     make_active("tmprect")
 | |
|     rotate(end_angle)
 | |
|     move(x=p_end[0], y=p_end[1])
 | |
|     union("tmprect")
 | |
|     dilated = line.buffer(thick / 2)  # expand shapely object to thickness
 | |
|     shapely_to_curve("tmp_curve", dilated, 0.0)
 | |
|     # truncate curve at both ends with the rectangles
 | |
|     difference("tmp", "tmp_curve")
 | |
| 
 | |
|     fingers(diameter, tolerance, amount, stem=stem)
 | |
|     make_active("fingers")
 | |
|     rotate(end_angle)
 | |
|     move(x=p_end[0], y=p_end[1])
 | |
|     active_name("tmp_fingers")
 | |
|     union("tmp_")
 | |
|     active_name("tmp_curve")
 | |
|     twist_male(
 | |
|         "tmp_curve",
 | |
|         thick,
 | |
|         diameter,
 | |
|         tolerance,
 | |
|         twist,
 | |
|         t_neck,
 | |
|         t_thick,
 | |
|         end_angle,
 | |
|         x=p_end[0],
 | |
|         y=p_end[1],
 | |
|         twist_keep=twist_keep,
 | |
|     )
 | |
| 
 | |
|     twist_female(
 | |
|         "receptacle", thick, diameter, tolerance, twist, t_neck, t_thick, twist_keep=twist_keep
 | |
|     )
 | |
|     rename("receptacle", "tmp")
 | |
|     rotate(start_angle + pi)
 | |
|     move(x=p_start[0], y=p_start[1])
 | |
|     difference("tmp", "tmp_curve")
 | |
|     if twist_keep:
 | |
|         make_active("twist_keep_f")
 | |
|         rotate(start_angle + pi)
 | |
|         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=pi / 2,
 | |
|             fixed_angle=0,
 | |
|             start=twist_start,
 | |
|             end=twist_start,
 | |
|             closed=False,
 | |
|             type="TWIST",
 | |
|             twist_percentage=t_neck,
 | |
|         )
 | |
|         if twist_keep:
 | |
|             duplicate()
 | |
|             active_name("twist_keep")
 | |
|             join_multiple("twist_keep")
 | |
|             make_active("interlock")
 | |
| 
 | |
|         active_name("tmp_twist")
 | |
|         difference("tmp", "tmp_curve")
 | |
|         active_name("puzzle_curve")
 | |
| 
 | |
| 
 | |
| def tile(diameter, tolerance, tile_x_amount, tile_y_amount, stem=1):
 | |
|     """Create a tile shape based on specified dimensions and parameters.
 | |
| 
 | |
|     This function calculates the dimensions of a tile based on the provided
 | |
|     diameter and tolerance, as well as the number of tiles in the x and y
 | |
|     directions. It constructs the tile shape by creating a base and adding
 | |
|     features such as fingers for interlocking. The function also handles
 | |
|     transformations such as moving, rotating, and performing boolean
 | |
|     operations to achieve the desired tile geometry.
 | |
| 
 | |
|     Args:
 | |
|         diameter (float): The diameter of the tile.
 | |
|         tolerance (float): The tolerance to be applied to the tile dimensions.
 | |
|         tile_x_amount (int): The number of tiles along the x-axis.
 | |
|         tile_y_amount (int): The number of tiles along the y-axis.
 | |
|         stem (int?): A parameter affecting the tile's features. Defaults to 1.
 | |
| 
 | |
|     Returns:
 | |
|         None: This function does not return a value but modifies global state.
 | |
|     """
 | |
| 
 | |
|     global DT
 | |
|     diameter = diameter * DT
 | |
|     width = ((tile_x_amount) * (4 + 2 * (stem - 1)) + 1) * diameter
 | |
|     height = ((tile_y_amount) * (4 + 2 * (stem - 1)) + 1) * diameter
 | |
| 
 | |
|     print("Size:", width, height)
 | |
|     fingers(diameter, tolerance, amount=tile_x_amount, stem=stem)
 | |
|     add_rectangle(width, height)
 | |
|     active_name("_base")
 | |
| 
 | |
|     make_active("fingers")
 | |
|     active_name("_fingers")
 | |
|     intersect("_")
 | |
|     remove_multiple("_fingers")
 | |
|     rename("intersection", "_fingers")
 | |
|     move(y=height / 2)
 | |
|     union("_")
 | |
|     active_name("_base")
 | |
|     remove_doubles()
 | |
|     rename("receptacle", "_receptacle")
 | |
|     move(y=-height / 2)
 | |
|     difference("_", "_base")
 | |
|     active_name("base")
 | |
|     fingers(diameter, tolerance, amount=tile_y_amount, stem=stem)
 | |
|     rename("base", "_base")
 | |
|     remove_doubles()
 | |
|     rename("fingers", "_fingers")
 | |
|     rotate(pi / 2)
 | |
|     move(x=-width / 2)
 | |
|     union("_")
 | |
|     active_name("_base")
 | |
|     rename("receptacle", "_receptacle")
 | |
|     rotate(pi / 2)
 | |
|     move(x=width / 2)
 | |
|     difference("_", "_base")
 | |
|     active_name("tile_ " + str(tile_x_amount) + "_" + str(tile_y_amount))
 |