diff --git a/lasercut/crosspart.py b/lasercut/crosspart.py index 722cb47..8379dcf 100644 --- a/lasercut/crosspart.py +++ b/lasercut/crosspart.py @@ -275,6 +275,7 @@ def remove_intersections(first_part, second_part, referential_faces, axis, inver first_box = make_nodes_xz(first_box, first_box_x, first_part.properties.thickness, height, first_part.properties.node_type, first_part.properties.node_thickness) dog_bone_radius = min(first_box_x, height) * 2. / 30. + FreeCAD.Console.PrintError("Radius remove_intersections: %f\n" % dog_bone_radius) if invert_y: if first_part.properties.dog_bone: @@ -293,6 +294,7 @@ def remove_intersections(first_part, second_part, referential_faces, axis, inver second_part.properties.node_type, second_part.properties.node_thickness) dog_bone_radius = min(second_box_y, height) * 2. / 30. + FreeCAD.Console.PrintError("Radius remove_intersections: %f\n" % dog_bone_radius) if not invert_y: if second_part.properties.dog_bone: diff --git a/lasercut/flextab.py b/lasercut/flextab.py index 2a697d7..8c786c4 100644 --- a/lasercut/flextab.py +++ b/lasercut/flextab.py @@ -46,7 +46,7 @@ def make_round_tab(tab, tab_part, other_parts): tab_part.toAdd.append(tab_to_add_transformed) #print "tab " + str(tab.dog_bone) hole = helper.tab_join_create_hole_on_plane(tab, tab.tabs_width, y, tab_part.properties, - part_interactor.properties, tab.dog_bone) + part_interactor.properties) part_interactor.toRemove.append(helper.transform_part(hole, tab)) break @@ -64,7 +64,7 @@ def make_round_tab(tab, tab_part, other_parts): tab.tabs_width, y) tab_part.toRemove.append(helper.transform_part(groove, tab)) hole = helper.tab_join_create_hole_on_plane(tab, tab.tabs_width, y, tab_part.properties, - part_interactor.properties, tab.dog_bone) + part_interactor.properties) part_interactor.toRemove.append(helper.transform_part(hole, tab)) break return diff --git a/lasercut/helper.py b/lasercut/helper.py index 2982c7c..5437a64 100644 --- a/lasercut/helper.py +++ b/lasercut/helper.py @@ -392,7 +392,7 @@ def check_limit_y_on_for_tab(tab_face, height, pos_y, width, thickness, material return y_plus_inside, y_minus_inside -def tab_join_create_hole_on_plane(tab_face, width, pos_y, material_face, material_plane, dog_bone=False): +def tab_join_create_hole_on_plane(tab_face, width, pos_y, material_face, material_plane): z_plus_inside, z_minus_inside = check_limit_z(tab_face, width, pos_y, material_face, material_plane) y_plus_inside, y_minus_inside = check_limit_y(tab_face, material_face.thickness, pos_y, width, material_plane) @@ -428,8 +428,8 @@ def tab_join_create_hole_on_plane(tab_face, width, pos_y, material_face, materia hole = Part.makeBox(corrected_length, corrected_width, corrected_height, origin) hole.translate(FreeCAD.Vector(0, pos_y, 0)) - if dog_bone: - hole = make_dog_bone_on_limits_on_yz(hole, corrected_length, + if tab_face.dog_bone: + hole = make_dog_bone_on_limits_on_yz(tab_face, hole, corrected_length, z_minus_inside and y_minus_inside, z_minus_inside and y_plus_inside, z_plus_inside and y_minus_inside, @@ -437,19 +437,34 @@ def tab_join_create_hole_on_plane(tab_face, width, pos_y, material_face, materia return hole -def make_dog_bone_on_limits_on_yz(shape, length, +def make_dog_bone_on_limits_on_yz(tab_face, shape, length, y_min_z_min=True, y_max_z_min=True, y_min_z_max=True, y_max_z_max=True): bound_box = shape.BoundBox - radius = min(bound_box.YMax - bound_box.YMin, bound_box.ZMax - bound_box.ZMin) * 2 / 30. - shift = radius / 2.0 + + if not hasattr(tab_face, 'dog_bone_diameter_auto') or tab_face.dog_bone_diameter_auto: + radius = min(bound_box.YMax - bound_box.YMin, bound_box.ZMax - bound_box.ZMin) * 2 / 30. + else: + radius = tab_face.dog_bone_diameter / 2.0 + + FreeCAD.Console.PrintError("Radius make_dog_bone_on_limits_on_yz: %f\n" % radius) + + base_shift = radius / 2.0 + + shift_x = base_shift + if hasattr(tab_face, 'dog_bone_shift_x'): + shift_x += tab_face.dog_bone_shift_x + shift_y = base_shift + if hasattr(tab_face, 'dog_bone_shift_y'): + shift_y += tab_face.dog_bone_shift_y + if y_min_z_min: - shape = shape.fuse(make_dog_bone_on_yz(bound_box.YMin + shift, bound_box.ZMin + shift, length, radius)) + shape = shape.fuse(make_dog_bone_on_yz(bound_box.YMin + shift_y, bound_box.ZMin + shift_x, length, radius)) if y_max_z_min: - shape = shape.fuse(make_dog_bone_on_yz(bound_box.YMax - shift, bound_box.ZMin + shift, length, radius)) + shape = shape.fuse(make_dog_bone_on_yz(bound_box.YMax - shift_y, bound_box.ZMin + shift_x, length, radius)) if y_min_z_max: - shape = shape.fuse(make_dog_bone_on_yz(bound_box.YMin + shift, bound_box.ZMax - shift, length, radius)) + shape = shape.fuse(make_dog_bone_on_yz(bound_box.YMin + shift_y, bound_box.ZMax - shift_x, length, radius)) if y_max_z_max: - shape = shape.fuse(make_dog_bone_on_yz(bound_box.YMax - shift, bound_box.ZMax - shift, length, radius)) + shape = shape.fuse(make_dog_bone_on_yz(bound_box.YMax - shift_y, bound_box.ZMax - shift_x, length, radius)) return shape @@ -466,6 +481,9 @@ def make_dog_bone_on_yz(pos_y, pos_z, height, radius): def make_dog_bone_on_limits_on_xy(shape, length, x_min_only=False): bound_box = shape.BoundBox radius = min(bound_box.XMax - bound_box.XMin, bound_box.YMax - bound_box.YMin) * 2 / 30. + + FreeCAD.Console.PrintError("Radius make_dog_bone_on_limits_on_xy: %f\n" % radius) + shift = radius / 2.0 shape = shape.fuse(make_dog_bone_on_xy(bound_box.XMin + shift, bound_box.YMin + shift, length, radius)) if x_min_only is False: diff --git a/lasercut/join.py b/lasercut/join.py index 3b9a12d..882115f 100644 --- a/lasercut/join.py +++ b/lasercut/join.py @@ -108,7 +108,7 @@ def screw_way_on_face(material_face, material_plane, screw_nut_spec, pos_y, dog_ # X est vers le haut # Y est aligné sur la face # Z est devant la camera -def tab_join_create_tab_on_face(material_face, material_plane, width, pos_y, tab_face, dog_bone=False): +def tab_join_create_tab_on_face(material_face, material_plane, width, pos_y, tab_face): y_plus_inside, y_minus_inside = helper.check_limit_y_on_for_tab(tab_face, material_face.thickness, pos_y, width, material_plane.thickness, material_face) @@ -140,16 +140,35 @@ def tab_join_create_tab_on_face(material_face, material_plane, width, pos_y, tab left_hole = None right_hole = None - if dog_bone: - radius = min(corrected_width, corrected_length) * 2 / 30. + if tab_face.dog_bone: + if not hasattr(tab_face, 'dog_bone_diameter_auto') or tab_face.dog_bone_diameter_auto: + radius = min(corrected_width, corrected_length) * 2 / 30. + else: + radius = tab_face.dog_bone_diameter / 2.0 + FreeCAD.Console.PrintError("Radius tab_join_create_tab_on_face: %f\n" % radius) + + base_shift = radius / 2.0 + + shift_x = base_shift + if hasattr(tab_face, 'dog_bone_shift_x'): + shift_x += tab_face.dog_bone_shift_x + shift_y = base_shift + if hasattr(tab_face, 'dog_bone_shift_y'): + shift_y += tab_face.dog_bone_shift_y + if y_minus_inside: left_hole = Part.makeCylinder(radius, corrected_height, - FreeCAD.Vector(0, -corrected_width_center + pos_y, -corrected_height / 2.0), + FreeCAD.Vector( + shift_x, + -corrected_width_center + pos_y - shift_y, + -corrected_height / 2.0), FreeCAD.Vector(0, 0, 1.)) if y_plus_inside: right_hole = Part.makeCylinder(radius, corrected_height, - FreeCAD.Vector(0, -corrected_width_center + corrected_width + pos_y, - -corrected_height / 2.0), + FreeCAD.Vector( + shift_x, + -corrected_width_center + pos_y + corrected_width + shift_y, + -corrected_height / 2.0), FreeCAD.Vector(0, 0, 1.)) hole = left_hole if hole and right_hole: @@ -165,7 +184,7 @@ def make_tab_join(tab, tab_part, other_parts): for i, y in enumerate(slots_pos): for part_interactor in other_parts: tab_to_add, tab_dog_bone = tab_join_create_tab_on_face(tab_part.properties, part_interactor.properties, - tab.tabs_width, y, tab, tab.tab_dog_bone) + tab.tabs_width, y, tab) intersect_test, tab_to_add_transformed = helper.check_intersect(tab_to_add, tab, part_interactor.properties) @@ -174,7 +193,7 @@ def make_tab_join(tab, tab_part, other_parts): if tab_dog_bone: tab_part.toRemove.append(helper.transform_part(tab_dog_bone, tab)) hole = helper.tab_join_create_hole_on_plane(tab, tab.tabs_width, y, tab_part.properties, - part_interactor.properties, tab.dog_bone) + part_interactor.properties) part_interactor.toRemove.append(helper.transform_part(hole, tab)) break return @@ -193,8 +212,7 @@ def make_continuous_tab_joins(tab, tab_part, other_parts): if tab_id % 2 == 0: for part_interactor in other_parts: tab_to_add, tab_dog_bone = tab_join_create_tab_on_face(tab_part.properties, part_interactor.properties, - virtual_tab_length, y_pos_center, tab, - tab.tab_dog_bone) + virtual_tab_length, y_pos_center, tab) intersect_test, tab_to_add_transformed = helper.check_intersect(tab_to_add, tab, part_interactor.properties) if intersect_test: @@ -202,8 +220,7 @@ def make_continuous_tab_joins(tab, tab_part, other_parts): if tab_dog_bone: tab_part.toRemove.append(helper.transform_part(tab_dog_bone, tab)) hole = helper.tab_join_create_hole_on_plane(tab, virtual_tab_length, y_pos_center, - tab_part.properties, part_interactor.properties, - tab.dog_bone) + tab_part.properties, part_interactor.properties) part_interactor.toRemove.append(helper.transform_part(hole, tab)) break y_pos += virtual_tab_length @@ -219,12 +236,10 @@ def make_tslot_tab_join(tab, tab_part, other_parts): for part_interactor in other_parts: left_tab_to_add, left_tab_dog_bone = tab_join_create_tab_on_face(tab_part.properties, part_interactor.properties, - tab.tabs_width, y - half_tab_distance, - tab, tab.tab_dog_bone) + tab.tabs_width, y - half_tab_distance, tab) right_tab_to_add, right_tab_dog_bone = tab_join_create_tab_on_face(tab_part.properties, part_interactor.properties, - tab.tabs_width, y + half_tab_distance, - tab, tab.tab_dog_bone) + tab.tabs_width, y + half_tab_distance, tab) right_intersect_test, right_tab_to_add_transformed = helper.check_intersect(right_tab_to_add, tab, part_interactor.properties) @@ -240,11 +255,9 @@ def make_tslot_tab_join(tab, tab_part, other_parts): tab_part.toRemove.append(helper.transform_part(right_tab_dog_bone, tab)) left_hole = helper.tab_join_create_hole_on_plane(tab, tab.tabs_width, y - half_tab_distance, - tab_part.properties, part_interactor.properties, - tab.dog_bone) + tab_part.properties, part_interactor.properties) right_hole = helper.tab_join_create_hole_on_plane(tab, tab.tabs_width, y + half_tab_distance, - tab_part.properties, part_interactor.properties, - tab.dog_bone) + tab_part.properties, part_interactor.properties) part_interactor.toRemove.append(helper.transform_part(left_hole, tab)) part_interactor.toRemove.append(helper.transform_part(right_hole, tab)) @@ -294,4 +307,4 @@ def make_tabs_joins(parts, tabs): flextab.make_flex_tab_join(tab, tab_part, other_parts) else: raise ValueError("Unknown tab type") - return parts_element \ No newline at end of file + return parts_element diff --git a/lasercut/tabproperties.py b/lasercut/tabproperties.py index 120ef19..cb1ea7e 100644 --- a/lasercut/tabproperties.py +++ b/lasercut/tabproperties.py @@ -36,7 +36,9 @@ class TabProperties(helper.ObjectProperties): TYPE_NOT_DEFINED = 'Not Defined' _allowed = ('face_name', 'y_length', 'thickness', 'tabs_width', 'tabs_number', 'tabs_shift', - 'dog_bone', 'tab_dog_bone', 'screw_diameter', 'screw_length', 'screw_length_tol', 'makeScrew', + 'dog_bone', 'tab_dog_bone', + 'dog_bone_diameter_auto', 'dog_bone_diameter', 'dog_bone_shift_x', 'dog_bone_shift_y', + 'screw_diameter', 'screw_length', 'screw_length_tol', 'makeScrew', 'y_invert', 'half_tab_ratio', 'interval_ratio', 'freecad_obj_name', 'tab_type', 'group_id', 'description', 'link_name', 'tab_name', 'transform_matrix') @@ -52,6 +54,7 @@ def __init__(self, **kwargs): self.freecad_object = None self.freecad_face = None self.transform_matrix = None + self.group_id = self._count() if not kwargs['freecad_face']: raise ValueError("Must init with freecad face") if not hasattr(self, 'freecad_obj_name') :#or not hasattr(self, 'freecad_face'): @@ -72,6 +75,9 @@ def __init__(self, **kwargs): self.y_length = y_length.Length except ValueError as e: FreeCAD.Console.PrintError(e) + self.__init_defaults__() + + def __init_defaults__(self): if not hasattr(self, 'tabs_number'): self.tabs_number = 1 if not hasattr(self, 'tabs_width'): @@ -92,9 +98,16 @@ def __init__(self, **kwargs): self.dog_bone = True if not hasattr(self, 'tab_dog_bone'): self.tab_dog_bone = False + if not hasattr(self, 'dog_bone_diameter_auto'): + self.dog_bone_diameter_auto = True + if not hasattr(self, 'dog_bone_diameter'): + self.dog_bone_diameter = 1. + if not hasattr(self, 'dog_bone_shift_x'): + self.dog_bone_shift_x = 0. + if not hasattr(self, 'dog_bone_shift_y'): + self.dog_bone_shift_y = 0. if not hasattr(self, 'y_invert'): self.y_invert = False - self.group_id = self._count() if not hasattr(self, 'link_name'): self.link_name = "" @@ -104,4 +117,4 @@ def recomputeInit(self, freecad_obj, freecad_face): x_local, y_length, thickness = helper.get_local_axis(freecad_face) self.thickness = thickness.Length self.y_length = y_length.Length - self.transform_matrix = helper.get_matrix_transform(freecad_face) \ No newline at end of file + self.transform_matrix = helper.get_matrix_transform(freecad_face) diff --git a/panel/tab.py b/panel/tab.py index 892efbd..bdac711 100644 --- a/panel/tab.py +++ b/panel/tab.py @@ -50,8 +50,19 @@ def __init__(self, tab_properties): WidgetValue(type=float, name="interval_ratio", show_name="Interval ratio", widget=None, interval_value=[0.1, 5.], step=0.1, decimals=2), WidgetValue(type=bool, name="dog_bone", show_name="Dog bone hole", widget=None), - WidgetValue(type=bool, name="tab_dog_bone", show_name="Tab dog bone hole", widget=None) - ]) + WidgetValue(type=bool, name="tab_dog_bone", show_name="Tab dog bone hole", widget=None), + WidgetValue(type=bool, name="dog_bone_diameter_auto", + show_name="Auto dog bone hole diameter", widget=None), + WidgetValue(type=float, name="dog_bone_diameter", + show_name="Dog bone diameter (ignored if auto is set)", widget=None, + interval_value=[0., 300.], step=1., decimals=2), + WidgetValue(type=float, name="dog_bone_shift_x", + show_name="Dog bone shift x", widget=None, + interval_value=[-300., 300.], step=1., decimals=2), + WidgetValue(type=float, name="dog_bone_shift_y", + show_name="Dog bone shift y", widget=None, + interval_value=[-300., 300.], step=1., decimals=2), + ]) def get_tab_type(self): return self.object_property.tab_type @@ -89,7 +100,19 @@ def __init__(self, tab_properties): widget=None, interval_value=[2., 300.], step=1., decimals=0), WidgetValue(type=bool, name="y_invert", show_name="Invert Y", widget=None), WidgetValue(type=bool, name="dog_bone", show_name="Dog bone hole", widget=None), - WidgetValue(type=bool, name="tab_dog_bone", show_name="Tab dog bone hole", widget=None)] + WidgetValue(type=bool, name="tab_dog_bone", show_name="Tab dog bone hole", widget=None), + WidgetValue(type=bool, name="dog_bone_diameter_auto", + show_name="Auto dog bone hole diameter", widget=None), + WidgetValue(type=float, name="dog_bone_diameter", + show_name="Dog bone diameter (ignored if auto is set)", widget=None, + interval_value=[0., 300.], step=1., decimals=2), + WidgetValue(type=float, name="dog_bone_shift_x", + show_name="Dog bone shift x", widget=None, + interval_value=[-300., 300.], step=1., decimals=2), + WidgetValue(type=float, name="dog_bone_shift_y", + show_name="Dog bone shift y", widget=None, + interval_value=[-300., 300.], step=1., decimals=2), + ] class TabFlexWidget(BaseTabWidget): @@ -100,7 +123,7 @@ def __init__(self, tab_properties): self.widget_list = [WidgetValue(type=float, name="tabs_width", show_name="Width of tabs", widget=None, interval_value=[1., 300.], step=1., decimals=2), WidgetValue(type=bool, name="y_invert", show_name="Invert Y", widget=None), - WidgetValue(type=bool, name="dog_bone", show_name="Dog bone hole", widget=None)] + aidgetValue(type=bool, name="dog_bone", show_name="Dog bone hole", widget=None)] class TabLink(ParamWidget): @@ -219,6 +242,7 @@ def get(self, name): if self.faces[index].tab_name == name: #FreeCAD.Console.PrintMessage("found " + name + "\n") face = self.faces[index] + face.__init_defaults__() if not face.link_name: widget = self.createWidgetFromTabProperties(face) else: