- in Excellon Editor -> remade the Tool edit made by editing the diameter values in the Tools Table to work for slots too
This commit is contained in:
parent
aa97a3722b
commit
66a205a6fd
|
@ -20,7 +20,8 @@ CAD program, and create G-Code for Isolation routing.
|
||||||
- each CNCJob object has now it's own text_collection for the annotations which allow for the individual enabling and disabling of the annotations
|
- each CNCJob object has now it's own text_collection for the annotations which allow for the individual enabling and disabling of the annotations
|
||||||
- added new menu category in File -> Backup with two menu entries that duplicate the functions of the export/import preferences buttons from the bottom of the Preferences window
|
- added new menu category in File -> Backup with two menu entries that duplicate the functions of the export/import preferences buttons from the bottom of the Preferences window
|
||||||
- in Excellon Editor fixed the display of the number of slots in the Tool Table after the resize done with the Resize tool
|
- in Excellon Editor fixed the display of the number of slots in the Tool Table after the resize done with the Resize tool
|
||||||
- in Excellon editor -> Resize tool, made sure that when the slot is resized, it's length remain the same, because the tool should influence only the 'thickness' of the slot. Since I don't know anything but the geometry and tool diameter, this is only an approximation and computationally intensive
|
- in Excellon Editor -> Resize tool, made sure that when the slot is resized, it's length remain the same, because the tool should influence only the 'thickness' of the slot. Since I don't know anything but the geometry and tool diameters (old and new), this is only an approximation and computationally intensive
|
||||||
|
- in Excellon Editor -> remade the Tool edit made by editing the diameter values in the Tools Table to work for slots too
|
||||||
|
|
||||||
15.08.2019
|
15.08.2019
|
||||||
|
|
||||||
|
|
|
@ -907,11 +907,11 @@ class FCDrillResize(FCShapeTool):
|
||||||
origin='center')))
|
origin='center')))
|
||||||
elif isinstance(select_shape.geo, Polygon):
|
elif isinstance(select_shape.geo, Polygon):
|
||||||
# I don't have any info regarding the angle of the slot geometry, nor how thick it is or
|
# I don't have any info regarding the angle of the slot geometry, nor how thick it is or
|
||||||
# how long it is given the angle. SO I will have to make an approximation because
|
# how long it is given the angle. So I will have to make an approximation because
|
||||||
# we need to conserve the slot length, we only resize the diameter for the tool
|
# we need to conserve the slot length, we only resize the diameter for the tool
|
||||||
# Therefore scaling won't work and buffering will not work either.
|
# Therefore scaling won't work and buffering will not work either.
|
||||||
|
|
||||||
# First we get the Linestring that is one that the original slot is built around with the4
|
# First we get the Linestring that is one that the original slot is built around with the
|
||||||
# tool having the diameter sel_dia
|
# tool having the diameter sel_dia
|
||||||
poly = select_shape.geo
|
poly = select_shape.geo
|
||||||
xmin, ymin, xmax, ymax = poly.bounds
|
xmin, ymin, xmax, ymax = poly.bounds
|
||||||
|
@ -940,16 +940,17 @@ class FCDrillResize(FCShapeTool):
|
||||||
# around them
|
# around them
|
||||||
start_pt = Point(cut_line_with_max_length_coords[0])
|
start_pt = Point(cut_line_with_max_length_coords[0])
|
||||||
stop_pt = Point(cut_line_with_max_length_coords[1])
|
stop_pt = Point(cut_line_with_max_length_coords[1])
|
||||||
start_cut_geo = start_pt.buffer(new_dia)
|
start_cut_geo = start_pt.buffer(new_dia / 2)
|
||||||
stop_cut_geo = stop_pt.buffer(new_dia)
|
stop_cut_geo = stop_pt.buffer(new_dia / 2)
|
||||||
|
|
||||||
# and we cut the above circle polygons from our line and get in this way a line around
|
# and we cut the above circle polygons from our line and get in this way a line around
|
||||||
# which we can build the new slot by buffering with the new tool diameter
|
# which we can build the new slot by buffering with the new tool diameter
|
||||||
new_line = cut_line_with_max_length.difference(start_cut_geo)
|
new_line = cut_line_with_max_length.difference(start_cut_geo)
|
||||||
new_line = new_line.difference(stop_cut_geo)
|
new_line = new_line.difference(stop_cut_geo)
|
||||||
|
|
||||||
# create the geometry for the resized slot by buffering with the new diameter value, new_dia
|
# create the geometry for the resized slot by buffering with half of the
|
||||||
new_poly = new_line.buffer(new_dia)
|
# new diameter value, new_dia
|
||||||
|
new_poly = new_line.buffer(new_dia / 2)
|
||||||
|
|
||||||
self.geometry.append(DrawToolShape(new_poly))
|
self.geometry.append(DrawToolShape(new_poly))
|
||||||
else:
|
else:
|
||||||
|
@ -985,7 +986,6 @@ class FCDrillResize(FCShapeTool):
|
||||||
|
|
||||||
sel_shapes_to_be_deleted.append(select_shape)
|
sel_shapes_to_be_deleted.append(select_shape)
|
||||||
|
|
||||||
self.draw_app.on_exc_shape_complete(self.destination_storage)
|
|
||||||
|
|
||||||
# a hack to make the tool_table display more drills/slots per diameter when shape(drill/slot)
|
# a hack to make the tool_table display more drills/slots per diameter when shape(drill/slot)
|
||||||
# is added.
|
# is added.
|
||||||
|
@ -1009,8 +1009,6 @@ class FCDrillResize(FCShapeTool):
|
||||||
else:
|
else:
|
||||||
self.draw_app.slot_points_edit[new_dia].append((0, 0))
|
self.draw_app.slot_points_edit[new_dia].append((0, 0))
|
||||||
|
|
||||||
self.geometry = []
|
|
||||||
|
|
||||||
for dia_key in list(self.draw_app.storage_dict.keys()):
|
for dia_key in list(self.draw_app.storage_dict.keys()):
|
||||||
# if following the resize of the drills there will be no more drills for some of the tools then
|
# if following the resize of the drills there will be no more drills for some of the tools then
|
||||||
# delete those tools
|
# delete those tools
|
||||||
|
@ -1034,9 +1032,15 @@ class FCDrillResize(FCShapeTool):
|
||||||
for shp in sel_shapes_to_be_deleted:
|
for shp in sel_shapes_to_be_deleted:
|
||||||
self.draw_app.selected.remove(shp)
|
self.draw_app.selected.remove(shp)
|
||||||
|
|
||||||
|
# add the new geometry to storage
|
||||||
|
self.draw_app.on_exc_shape_complete(self.destination_storage)
|
||||||
|
|
||||||
self.draw_app.build_ui()
|
self.draw_app.build_ui()
|
||||||
self.draw_app.replot()
|
self.draw_app.replot()
|
||||||
|
|
||||||
|
# empty the self.geometry
|
||||||
|
self.geometry = []
|
||||||
|
|
||||||
# we reactivate the signals after the after the tool editing
|
# we reactivate the signals after the after the tool editing
|
||||||
self.draw_app.tools_table_exc.itemChanged.connect(self.draw_app.on_tool_edit)
|
self.draw_app.tools_table_exc.itemChanged.connect(self.draw_app.on_tool_edit)
|
||||||
|
|
||||||
|
@ -2467,93 +2471,149 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
|
|
||||||
def on_tool_edit(self, item_changed):
|
def on_tool_edit(self, item_changed):
|
||||||
|
|
||||||
# if connected, disconnect the signal from the slot on item_changed as it creates issues
|
# if connected, disconnect the signal from the slot on item_changed as it creates issues
|
||||||
|
try:
|
||||||
self.tools_table_exc.itemChanged.disconnect()
|
self.tools_table_exc.itemChanged.disconnect()
|
||||||
self.tools_table_exc.cellPressed.disconnect()
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.tools_table_exc.cellPressed.disconnect()
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
# self.tools_table_exc.selectionModel().currentChanged.disconnect()
|
# self.tools_table_exc.selectionModel().currentChanged.disconnect()
|
||||||
|
|
||||||
self.is_modified = True
|
self.is_modified = True
|
||||||
current_table_dia_edited = None
|
new_dia = None
|
||||||
|
|
||||||
if self.tools_table_exc.currentItem() is not None:
|
if self.tools_table_exc.currentItem() is not None:
|
||||||
try:
|
try:
|
||||||
current_table_dia_edited = float(self.tools_table_exc.currentItem().text())
|
new_dia = float(self.tools_table_exc.currentItem().text())
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
log.debug("FlatCAMExcEditor.on_tool_edit() --> %s" % str(e))
|
log.debug("FlatCAMExcEditor.on_tool_edit() --> %s" % str(e))
|
||||||
self.tools_table_exc.setCurrentItem(None)
|
self.tools_table_exc.setCurrentItem(None)
|
||||||
return
|
return
|
||||||
|
|
||||||
row_of_item_changed = self.tools_table_exc.currentRow()
|
row_of_item_changed = self.tools_table_exc.currentRow()
|
||||||
|
|
||||||
# rows start with 0, tools start with 1 so we adjust the value by 1
|
# rows start with 0, tools start with 1 so we adjust the value by 1
|
||||||
key_in_tool2tooldia = row_of_item_changed + 1
|
key_in_tool2tooldia = row_of_item_changed + 1
|
||||||
|
old_dia = self.tool2tooldia[key_in_tool2tooldia]
|
||||||
|
|
||||||
dia_changed = self.tool2tooldia[key_in_tool2tooldia]
|
# SOURCE storage
|
||||||
|
source_storage = self.storage_dict[old_dia]
|
||||||
|
|
||||||
|
# DESTINATION storage
|
||||||
# tool diameter is not used so we create a new tool with the desired diameter
|
# tool diameter is not used so we create a new tool with the desired diameter
|
||||||
if current_table_dia_edited not in self.olddia_newdia.values():
|
if new_dia not in self.olddia_newdia:
|
||||||
# update the dict that holds as keys our initial diameters and as values the edited diameters
|
destination_storage = FlatCAMGeoEditor.make_storage()
|
||||||
self.olddia_newdia[dia_changed] = current_table_dia_edited
|
self.storage_dict[new_dia] = destination_storage
|
||||||
# update the dict that holds tool_no as key and tool_dia as value
|
|
||||||
self.tool2tooldia[key_in_tool2tooldia] = current_table_dia_edited
|
|
||||||
|
|
||||||
# update the tool offset
|
# self.olddia_newdia dict keeps the evidence on current tools diameters as keys and gets updated on values
|
||||||
modified_offset = self.exc_obj.tool_offset.pop(dia_changed, None)
|
# each time a tool diameter is edited or added
|
||||||
if modified_offset is not None:
|
self.olddia_newdia[new_dia] = new_dia
|
||||||
self.exc_obj.tool_offset[current_table_dia_edited] = modified_offset
|
|
||||||
|
|
||||||
self.replot()
|
|
||||||
else:
|
else:
|
||||||
# tool diameter is already in use so we move the drills from the prior tool to the new tool
|
# tool diameter is already in use so we move the drills from the prior tool to the new tool
|
||||||
factor = current_table_dia_edited / dia_changed
|
destination_storage = self.storage_dict[new_dia]
|
||||||
geometry = []
|
|
||||||
|
|
||||||
scaled_geo = []
|
# since we add a new tool, we update also the intial state of the tool_table through it's dictionary
|
||||||
for shape_exc in self.storage_dict[dia_changed].get_objects():
|
# we add a new entry in the tool2tooldia dict
|
||||||
|
self.tool2tooldia[len(self.olddia_newdia)] = new_dia
|
||||||
|
|
||||||
|
# CHANGE the elements geometry according to the new diameter
|
||||||
|
factor = new_dia / old_dia
|
||||||
|
new_geo = Polygon()
|
||||||
|
for shape_exc in source_storage.get_objects():
|
||||||
geo_list = []
|
geo_list = []
|
||||||
if isinstance(shape_exc.geo, MultiLineString) or isinstance(shape_exc.geo, MultiPolygon):
|
if isinstance(shape_exc.geo, MultiLineString):
|
||||||
for subgeo in shape_exc.geo:
|
for subgeo in shape_exc.geo:
|
||||||
geo_list.append(affinity.scale(subgeo, xfact=factor, yfact=factor, origin='center'))
|
geo_list.append(affinity.scale(subgeo, xfact=factor, yfact=factor, origin='center'))
|
||||||
scaled_geo = MultiLineString(geo_list)
|
new_geo = MultiLineString(geo_list)
|
||||||
elif isinstance(shape_exc.geo, Polygon):
|
elif isinstance(shape_exc.geo, Polygon):
|
||||||
scaled_geo = geo_list.append(affinity.scale(shape_exc.geo,
|
# I don't have any info regarding the angle of the slot geometry, nor how thick it is or
|
||||||
xfact=factor, yfact=factor, origin='center'))
|
# how long it is given the angle. So I will have to make an approximation because
|
||||||
|
# we need to conserve the slot length, we only resize the diameter for the tool
|
||||||
|
# Therefore scaling won't work and buffering will not work either.
|
||||||
|
|
||||||
|
# First we get the Linestring that is one that the original slot is built around with the
|
||||||
|
# tool having the diameter sel_dia
|
||||||
|
poly = shape_exc.geo
|
||||||
|
xmin, ymin, xmax, ymax = poly.bounds
|
||||||
|
# a line that is certain to be bigger than our slot because it's the diagonal
|
||||||
|
# of it's bounding box
|
||||||
|
poly_diagonal = LineString([(xmin, ymin), (xmax, ymax)])
|
||||||
|
poly_centroid = poly.centroid
|
||||||
|
# center of the slot geometry
|
||||||
|
poly_center = (poly_centroid.x, poly_centroid.y)
|
||||||
|
|
||||||
|
# make a list of intersections with the rotated line
|
||||||
|
list_of_cuttings = []
|
||||||
|
for angle in range(0, 359, 1):
|
||||||
|
rot_poly_diagonal = affinity.rotate(poly_diagonal, angle=angle, origin=poly_center)
|
||||||
|
cut_line = rot_poly_diagonal.intersection(poly)
|
||||||
|
cut_line_len = cut_line.length
|
||||||
|
list_of_cuttings.append(
|
||||||
|
(cut_line_len, cut_line)
|
||||||
|
)
|
||||||
|
# find the cut_line with the maximum length which is the LineString for which the start
|
||||||
|
# and stop point are the start and stop point of the slot as in the Gerber file
|
||||||
|
cut_line_with_max_length = max(list_of_cuttings, key=lambda i: i[0])[1]
|
||||||
|
# find the coordinates of this line
|
||||||
|
cut_line_with_max_length_coords = list(cut_line_with_max_length.coords)
|
||||||
|
# extract the first and last point of the line and build some buffered polygon circles
|
||||||
|
# around them
|
||||||
|
start_pt = Point(cut_line_with_max_length_coords[0])
|
||||||
|
stop_pt = Point(cut_line_with_max_length_coords[1])
|
||||||
|
start_cut_geo = start_pt.buffer(new_dia / 2)
|
||||||
|
stop_cut_geo = stop_pt.buffer(new_dia / 2)
|
||||||
|
|
||||||
|
# and we cut the above circle polygons from our line and get in this way a line around
|
||||||
|
# which we can build the new slot by buffering with the new tool diameter
|
||||||
|
new_line = cut_line_with_max_length.difference(start_cut_geo)
|
||||||
|
new_line = new_line.difference(stop_cut_geo)
|
||||||
|
|
||||||
|
# create the geometry for the resized slot by buffering with half of the
|
||||||
|
# new diameter value: new_dia
|
||||||
|
new_geo = new_line.buffer(new_dia / 2)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.points_edit.pop(old_dia, None)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
self.slot_points_edit.pop(old_dia, None)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# add bogus drill/slots points (for total count of drills/slots)
|
||||||
|
# for drills
|
||||||
if isinstance(shape_exc.geo, MultiLineString):
|
if isinstance(shape_exc.geo, MultiLineString):
|
||||||
# add bogus drill points (for total count of drills) but only if the shape is a MultiLineString
|
if new_dia not in self.points_edit:
|
||||||
# because the drills are MultiLineString
|
self.points_edit[new_dia] = [(0, 0)]
|
||||||
for k, v in self.olddia_newdia.items():
|
|
||||||
if v == current_table_dia_edited:
|
|
||||||
self.points_edit[k].append((0, 0))
|
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
# the shape is a Polygon or MultiPolygon therefore we have to increase the slot numbers
|
self.points_edit[new_dia].append((0, 0))
|
||||||
for k, v in self.olddia_newdia.items():
|
|
||||||
if v == current_table_dia_edited:
|
|
||||||
self.slot_points_edit[k].append((0, 0))
|
|
||||||
break
|
|
||||||
|
|
||||||
geometry.append(DrawToolShape(scaled_geo))
|
# for slots
|
||||||
|
if isinstance(shape_exc.geo, Polygon):
|
||||||
|
if new_dia not in self.slot_points_edit:
|
||||||
|
self.slot_points_edit[new_dia] = [(0, 0)]
|
||||||
|
else:
|
||||||
|
self.slot_points_edit[new_dia].append((0, 0))
|
||||||
|
|
||||||
# search for the old dia that correspond to the new dia and add the drills/slots in it's storage
|
self.add_exc_shape(shape=DrawToolShape(new_geo), storage=destination_storage)
|
||||||
# everything will be sorted out later, when the edited Excellon is updated
|
|
||||||
for k, v in self.olddia_newdia.items():
|
|
||||||
if v == current_table_dia_edited:
|
|
||||||
self.add_exc_shape(geometry, self.storage_dict[k])
|
|
||||||
break
|
|
||||||
|
|
||||||
# delete the old tool from which we moved the drills
|
# update the UI and the CANVAS
|
||||||
self.on_tool_delete(dia=dia_changed)
|
self.build_ui()
|
||||||
|
self.replot()
|
||||||
|
|
||||||
# delete the tool offset
|
# delete the old tool
|
||||||
self.exc_obj.tool_offset.pop(dia_changed, None)
|
self.on_tool_delete(dia=old_dia)
|
||||||
|
|
||||||
# we reactivate the signals after the after the tool editing
|
# we reactivate the signals after the after the tool editing
|
||||||
self.tools_table_exc.itemChanged.connect(self.on_tool_edit)
|
self.tools_table_exc.itemChanged.connect(self.on_tool_edit)
|
||||||
self.tools_table_exc.cellPressed.connect(self.on_row_selected)
|
self.tools_table_exc.cellPressed.connect(self.on_row_selected)
|
||||||
|
|
||||||
|
self.app.inform.emit(_("[success] Done. Tool edit completed."))
|
||||||
|
|
||||||
# self.tools_table_exc.selectionModel().currentChanged.connect(self.on_row_selected)
|
# self.tools_table_exc.selectionModel().currentChanged.connect(self.on_row_selected)
|
||||||
|
|
||||||
def on_name_activate(self):
|
def on_name_activate(self):
|
||||||
|
|
Loading…
Reference in New Issue