diff --git a/FlatCAMApp.py b/FlatCAMApp.py
index b6a695ae..3f0d9086 100644
--- a/FlatCAMApp.py
+++ b/FlatCAMApp.py
@@ -890,6 +890,9 @@ class App(QtCore.QObject):
# Subtract Tool
"tools_sub_close_paths": True,
+ # Distance Tool
+ "tools_dist_snap_center": False,
+
# ###################################################################################
# ################################ TOOLS 2 ##########################################
# ###################################################################################
diff --git a/README.md b/README.md
index e50d47be..2728cc8b 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,14 @@ CAD program, and create G-Code for Isolation routing.
=================================================
+5.02.2020
+
+- Modified the Distance Tool such that the Measure button can't be clicked while measuring is in progress
+- optimized selection of drills in the Excellon Editor
+- fixed bugs in multiple selection in Excellon Editor
+- fixed selection problems in Gerber Editor
+- in Distance Tool, when run in the Excellon or Gerber Editor, added a new option to snap to center of the geometry (drill for Excellon, pad for Gerber)
+
3.02.2020
- modified Spinbox and DoubleSpinbox Custom UI elements such that they issue a warning status message when the typed value is out of range
diff --git a/flatcamEditors/FlatCAMExcEditor.py b/flatcamEditors/FlatCAMExcEditor.py
index e2dc8bdb..a4136d3c 100644
--- a/flatcamEditors/FlatCAMExcEditor.py
+++ b/flatcamEditors/FlatCAMExcEditor.py
@@ -1334,8 +1334,8 @@ class FCDrillCopy(FCDrillMove):
class FCDrillSelect(DrawTool):
- def __init__(self, exc_editor_app):
- DrawTool.__init__(self, exc_editor_app)
+ def __init__(self, draw_app):
+ DrawTool.__init__(self, draw_app)
self.name = 'drill_select'
try:
@@ -1343,7 +1343,7 @@ class FCDrillSelect(DrawTool):
except Exception as e:
pass
- self.exc_editor_app = exc_editor_app
+ self.exc_editor_app = draw_app
self.storage = self.exc_editor_app.storage_dict
# self.selected = self.exc_editor_app.selected
@@ -1368,10 +1368,10 @@ class FCDrillSelect(DrawTool):
else:
mod_key = None
- if mod_key == self.draw_app.app.defaults["global_mselect_key"]:
+ if mod_key == self.exc_editor_app.app.defaults["global_mselect_key"]:
pass
else:
- self.exc_editor_app.selected = []
+ self.exc_editor_app.selected = list()
def click_release(self, pos):
self.exc_editor_app.tools_table_exc.clearSelection()
@@ -1379,8 +1379,10 @@ class FCDrillSelect(DrawTool):
try:
for storage in self.exc_editor_app.storage_dict:
- for sh in self.exc_editor_app.storage_dict[storage].get_objects():
- self.sel_storage.insert(sh)
+ # for sh in self.exc_editor_app.storage_dict[storage].get_objects():
+ # self.sel_storage.insert(sh)
+ _, st_closest_shape = self.exc_editor_app.storage_dict[storage].nearest(pos)
+ self.sel_storage.insert(st_closest_shape)
_, closest_shape = self.sel_storage.nearest(pos)
@@ -1417,37 +1419,41 @@ class FCDrillSelect(DrawTool):
else:
mod_key = None
- if mod_key == self.draw_app.app.defaults["global_mselect_key"]:
+ if mod_key == self.exc_editor_app.app.defaults["global_mselect_key"]:
if closest_shape in self.exc_editor_app.selected:
self.exc_editor_app.selected.remove(closest_shape)
else:
self.exc_editor_app.selected.append(closest_shape)
else:
- self.draw_app.selected = []
- self.draw_app.selected.append(closest_shape)
+ self.exc_editor_app.selected = list()
+ self.exc_editor_app.selected.append(closest_shape)
# select the diameter of the selected shape in the tool table
try:
- self.draw_app.tools_table_exc.cellPressed.disconnect()
+ self.exc_editor_app.tools_table_exc.cellPressed.disconnect()
except (TypeError, AttributeError):
pass
- self.exc_editor_app.tools_table_exc.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
+ # if mod_key == self.exc_editor_app.app.defaults["global_mselect_key"]:
+ # self.exc_editor_app.tools_table_exc.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
+ self.sel_tools.clear()
+
for shape_s in self.exc_editor_app.selected:
for storage in self.exc_editor_app.storage_dict:
if shape_s in self.exc_editor_app.storage_dict[storage].get_objects():
self.sel_tools.add(storage)
+ self.exc_editor_app.tools_table_exc.clearSelection()
for storage in self.sel_tools:
- for k, v in self.draw_app.tool2tooldia.items():
+ for k, v in self.exc_editor_app.tool2tooldia.items():
if v == storage:
self.exc_editor_app.tools_table_exc.selectRow(int(k) - 1)
- self.draw_app.last_tool_selected = int(k)
+ self.exc_editor_app.last_tool_selected = int(k)
break
- self.exc_editor_app.tools_table_exc.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
+ # self.exc_editor_app.tools_table_exc.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
- self.draw_app.tools_table_exc.cellPressed.connect(self.draw_app.on_row_selected)
+ self.exc_editor_app.tools_table_exc.cellPressed.connect(self.exc_editor_app.on_row_selected)
# delete whatever is in selection storage, there is no longer need for those shapes
self.sel_storage = FlatCAMExcEditor.make_storage()
@@ -2054,32 +2060,32 @@ class FlatCAMExcEditor(QtCore.QObject):
self.in_action = False
- self.storage_dict = {}
+ self.storage_dict = dict()
- self.current_storage = []
+ self.current_storage = list()
# build the data from the Excellon point into a dictionary
# {tool_dia: [geometry_in_points]}
- self.points_edit = {}
- self.slot_points_edit = {}
+ self.points_edit = dict()
+ self.slot_points_edit = dict()
- self.sorted_diameters = []
+ self.sorted_diameters = list()
- self.new_drills = []
- self.new_tools = {}
- self.new_slots = []
- self.new_tool_offset = {}
+ self.new_drills = list()
+ self.new_tools = dict()
+ self.new_slots = list()
+ self.new_tool_offset = dict()
# dictionary to store the tool_row and diameters in Tool_table
# it will be updated everytime self.build_ui() is called
- self.olddia_newdia = {}
+ self.olddia_newdia = dict()
- self.tool2tooldia = {}
+ self.tool2tooldia = dict()
# this will store the value for the last selected tool, for use after clicking on canvas when the selection
# is cleared but as a side effect also the selected tool is cleared
self.last_tool_selected = None
- self.utility = []
+ self.utility = list()
# this will flag if the Editor "tools" are launched from key shortcuts (True) or from menu toolbar (False)
self.launched_from_shortcuts = False
diff --git a/flatcamEditors/FlatCAMGrbEditor.py b/flatcamEditors/FlatCAMGrbEditor.py
index 2bd6a8bb..e1006725 100644
--- a/flatcamEditors/FlatCAMGrbEditor.py
+++ b/flatcamEditors/FlatCAMGrbEditor.py
@@ -2300,10 +2300,10 @@ class FCApertureSelect(DrawTool):
# since FCApertureSelect tool is activated whenever a tool is exited I place here the reinitialization of the
# bending modes using in FCRegion and FCTrack
- self.draw_app.bend_mode = 1
+ self.grb_editor_app.bend_mode = 1
# here store the selected apertures
- self.sel_aperture = set()
+ self.sel_aperture = list()
try:
self.grb_editor_app.apertures_table.clearSelection()
@@ -2332,7 +2332,7 @@ class FCApertureSelect(DrawTool):
else:
mod_key = None
- if mod_key == self.draw_app.app.defaults["global_mselect_key"]:
+ if mod_key == self.grb_editor_app.app.defaults["global_mselect_key"]:
pass
else:
self.grb_editor_app.selected = []
@@ -2348,46 +2348,53 @@ class FCApertureSelect(DrawTool):
else:
mod_key = None
+ if mod_key != self.grb_editor_app.app.defaults["global_mselect_key"]:
+ self.grb_editor_app.selected.clear()
+ self.sel_aperture.clear()
+
for storage in self.grb_editor_app.storage_dict:
try:
- for geo_el in self.grb_editor_app.storage_dict[storage]['geometry']:
- if 'solid' in geo_el.geo:
- geometric_data = geo_el.geo['solid']
+ for shape_stored in self.grb_editor_app.storage_dict[storage]['geometry']:
+ if 'solid' in shape_stored.geo:
+ geometric_data = shape_stored.geo['solid']
if Point(point).within(geometric_data):
- if mod_key == self.grb_editor_app.app.defaults["global_mselect_key"]:
- if geo_el in self.draw_app.selected:
- self.draw_app.selected.remove(geo_el)
- self.sel_aperture.remove(storage)
- else:
- # add the object to the selected shapes
- self.draw_app.selected.append(geo_el)
- self.sel_aperture.add(storage)
+ if shape_stored in self.grb_editor_app.selected:
+ self.grb_editor_app.selected.remove(shape_stored)
else:
- self.draw_app.selected.append(geo_el)
- self.sel_aperture.add(storage)
+ # add the object to the selected shapes
+ self.grb_editor_app.selected.append(shape_stored)
except KeyError:
pass
# select the aperture in the Apertures Table that is associated with the selected shape
+ self.sel_aperture.clear()
+
+ self.grb_editor_app.apertures_table.clearSelection()
try:
- self.draw_app.apertures_table.cellPressed.disconnect()
+ self.grb_editor_app.apertures_table.cellPressed.disconnect()
except Exception as e:
log.debug("FlatCAMGrbEditor.FCApertureSelect.click_release() --> %s" % str(e))
- self.grb_editor_app.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
+ for shape_s in self.grb_editor_app.selected:
+ for storage in self.grb_editor_app.storage_dict:
+ if shape_s in self.grb_editor_app.storage_dict[storage]['geometry']:
+ self.sel_aperture.append(storage)
+
+ # self.grb_editor_app.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
for aper in self.sel_aperture:
for row in range(self.grb_editor_app.apertures_table.rowCount()):
if str(aper) == self.grb_editor_app.apertures_table.item(row, 1).text():
- self.grb_editor_app.apertures_table.selectRow(row)
- self.draw_app.last_aperture_selected = aper
- self.grb_editor_app.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
+ if not self.grb_editor_app.apertures_table.item(row, 0).isSelected():
+ self.grb_editor_app.apertures_table.selectRow(row)
+ self.grb_editor_app.last_aperture_selected = aper
+ # self.grb_editor_app.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
- self.draw_app.apertures_table.cellPressed.connect(self.draw_app.on_row_selected)
+ self.grb_editor_app.apertures_table.cellPressed.connect(self.grb_editor_app.on_row_selected)
return ""
def clean_up(self):
- self.draw_app.plot_all()
+ self.grb_editor_app.plot_all()
class FCTransform(FCShapeTool):
diff --git a/flatcamTools/ToolDistance.py b/flatcamTools/ToolDistance.py
index 1a5bc568..84a6c547 100644
--- a/flatcamTools/ToolDistance.py
+++ b/flatcamTools/ToolDistance.py
@@ -9,13 +9,18 @@ from PyQt5 import QtWidgets, QtCore
from FlatCAMTool import FlatCAMTool
from flatcamGUI.VisPyVisuals import *
-from flatcamGUI.GUIElements import FCEntry
+from flatcamGUI.GUIElements import FCEntry, FCButton, FCCheckBox
+
+from shapely.geometry import Point, MultiLineString, Polygon
+
+import FlatCAMTranslation as fcTranslate
+from camlib import FlatCAMRTreeStorage
+from flatcamEditors.FlatCAMGeoEditor import DrawToolShape
from copy import copy
import math
import logging
import gettext
-import FlatCAMTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
@@ -43,82 +48,101 @@ class Distance(FlatCAMTool):
self.layout.addWidget(title_label)
# ## Form Layout
- form_layout = QtWidgets.QFormLayout()
- self.layout.addLayout(form_layout)
+ grid0 = QtWidgets.QGridLayout()
+ grid0.setColumnStretch(0, 0)
+ grid0.setColumnStretch(1, 1)
+ self.layout.addLayout(grid0)
self.units_label = QtWidgets.QLabel('%s:' % _("Units"))
self.units_label.setToolTip(_("Those are the units in which the distance is measured."))
self.units_value = QtWidgets.QLabel("%s" % str({'mm': _("METRIC (mm)"), 'in': _("INCH (in)")}[self.units]))
self.units_value.setDisabled(True)
+ grid0.addWidget(self.units_label, 0, 0)
+ grid0.addWidget(self.units_value, 0, 1)
+
+ self.snap_center_cb = FCCheckBox(_("Snap to center"))
+ self.snap_center_cb.setToolTip(
+ _("Mouse cursor will snap to the center of the pad/drill\n"
+ "when it is hovering over the geometry of the pad/drill.")
+ )
+ grid0.addWidget(self.snap_center_cb, 1, 0, 1, 2)
+
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid0.addWidget(separator_line, 2, 0, 1, 2)
+
self.start_label = QtWidgets.QLabel("%s:" % _('Start Coords'))
self.start_label.setToolTip(_("This is measuring Start point coordinates."))
- self.stop_label = QtWidgets.QLabel("%s:" % _('Stop Coords'))
- self.stop_label.setToolTip(_("This is the measuring Stop point coordinates."))
-
- self.distance_x_label = QtWidgets.QLabel('%s:' % _("Dx"))
- self.distance_x_label.setToolTip(_("This is the distance measured over the X axis."))
-
- self.distance_y_label = QtWidgets.QLabel('%s:' % _("Dy"))
- self.distance_y_label.setToolTip(_("This is the distance measured over the Y axis."))
-
- self.angle_label = QtWidgets.QLabel('%s:' % _("Angle"))
- self.angle_label.setToolTip(_("This is orientation angle of the measuring line."))
-
- self.total_distance_label = QtWidgets.QLabel("%s:" % _('DISTANCE'))
- self.total_distance_label.setToolTip(_("This is the point to point Euclidian distance."))
-
self.start_entry = FCEntry()
self.start_entry.setReadOnly(True)
self.start_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.start_entry.setToolTip(_("This is measuring Start point coordinates."))
+ grid0.addWidget(self.start_label, 3, 0)
+ grid0.addWidget(self.start_entry, 3, 1)
+
+ self.stop_label = QtWidgets.QLabel("%s:" % _('Stop Coords'))
+ self.stop_label.setToolTip(_("This is the measuring Stop point coordinates."))
+
self.stop_entry = FCEntry()
self.stop_entry.setReadOnly(True)
self.stop_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.stop_entry.setToolTip(_("This is the measuring Stop point coordinates."))
+ grid0.addWidget(self.stop_label, 4, 0)
+ grid0.addWidget(self.stop_entry, 4, 1)
+
+ self.distance_x_label = QtWidgets.QLabel('%s:' % _("Dx"))
+ self.distance_x_label.setToolTip(_("This is the distance measured over the X axis."))
+
self.distance_x_entry = FCEntry()
self.distance_x_entry.setReadOnly(True)
self.distance_x_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.distance_x_entry.setToolTip(_("This is the distance measured over the X axis."))
+ grid0.addWidget(self.distance_x_label, 5, 0)
+ grid0.addWidget(self.distance_x_entry, 5, 1)
+
+ self.distance_y_label = QtWidgets.QLabel('%s:' % _("Dy"))
+ self.distance_y_label.setToolTip(_("This is the distance measured over the Y axis."))
+
self.distance_y_entry = FCEntry()
self.distance_y_entry.setReadOnly(True)
self.distance_y_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.distance_y_entry.setToolTip(_("This is the distance measured over the Y axis."))
+ grid0.addWidget(self.distance_y_label, 6, 0)
+ grid0.addWidget(self.distance_y_entry, 6, 1)
+
+ self.angle_label = QtWidgets.QLabel('%s:' % _("Angle"))
+ self.angle_label.setToolTip(_("This is orientation angle of the measuring line."))
+
self.angle_entry = FCEntry()
self.angle_entry.setReadOnly(True)
self.angle_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.angle_entry.setToolTip(_("This is orientation angle of the measuring line."))
+ grid0.addWidget(self.angle_label, 7, 0)
+ grid0.addWidget(self.angle_entry, 7, 1)
+
+ self.total_distance_label = QtWidgets.QLabel("%s:" % _('DISTANCE'))
+ self.total_distance_label.setToolTip(_("This is the point to point Euclidian distance."))
+
self.total_distance_entry = FCEntry()
self.total_distance_entry.setReadOnly(True)
self.total_distance_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.total_distance_entry.setToolTip(_("This is the point to point Euclidian distance."))
- self.measure_btn = QtWidgets.QPushButton(_("Measure"))
+ grid0.addWidget(self.total_distance_label, 8, 0)
+ grid0.addWidget(self.total_distance_entry, 8, 1)
+
+ self.measure_btn = FCButton(_("Measure"))
# self.measure_btn.setFixedWidth(70)
self.layout.addWidget(self.measure_btn)
- form_layout.addRow(self.units_label, self.units_value)
- form_layout.addRow(self.start_label, self.start_entry)
- form_layout.addRow(self.stop_label, self.stop_entry)
- form_layout.addRow(self.distance_x_label, self.distance_x_entry)
- form_layout.addRow(self.distance_y_label, self.distance_y_entry)
- form_layout.addRow(self.angle_label, self.angle_entry)
- form_layout.addRow(self.total_distance_label, self.total_distance_entry)
-
- # initial view of the layout
- self.start_entry.set_value('(0, 0)')
- self.stop_entry.set_value('(0, 0)')
- self.distance_x_entry.set_value('0.0')
- self.distance_y_entry.set_value('0.0')
- self.angle_entry.set_value('0.0')
- self.total_distance_entry.set_value('0.0')
-
self.layout.addStretch()
# store here the first click and second click of the measurement process
@@ -137,6 +161,15 @@ class Distance(FlatCAMTool):
self.mm = None
self.mr = None
+ # monitor if the tool was used
+ self.tool_done = False
+
+ # store the grid status here
+ self.grid_status_memory = False
+
+ # store here if the snap button was clicked
+ self.snap_toggled = None
+
# VisPy visuals
if self.app.is_legacy is False:
self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1)
@@ -145,6 +178,7 @@ class Distance(FlatCAMTool):
self.sel_shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='measurement')
self.measure_btn.clicked.connect(self.activate_measure_tool)
+ self.snap_center_cb.toggled.connect(self.on_snap_toggled)
def run(self, toggle=False):
self.app.report_usage("ToolDistance()")
@@ -154,6 +188,8 @@ class Distance(FlatCAMTool):
self.rel_point1 = None
self.rel_point2 = None
+ self.tool_done = False
+
if self.app.tool_tab_locked is True:
return
@@ -177,7 +213,7 @@ class Distance(FlatCAMTool):
# Remove anything else in the GUI
self.app.ui.tool_scroll_area.takeWidget()
- # Put ourself in the GUI
+ # Put ourselves in the GUI
self.app.ui.tool_scroll_area.setWidget(self)
# Switch notebook to tool page
@@ -195,20 +231,45 @@ class Distance(FlatCAMTool):
self.angle_entry.set_value('0.0')
self.total_distance_entry.set_value('0.0')
+ self.snap_center_cb.set_value(self.app.defaults['tools_dist_snap_center'])
+
+ # snap center works only for Gerber and Execellon Editor's
+ if self.original_call_source == 'exc_editor' or self.original_call_source == 'grb_editor':
+ self.snap_center_cb.show()
+ else:
+ self.snap_center_cb.hide()
+
# this is a hack; seems that triggering the grid will make the visuals better
# trigger it twice to return to the original state
self.app.ui.grid_snap_btn.trigger()
self.app.ui.grid_snap_btn.trigger()
+ if self.app.ui.grid_snap_btn.isChecked():
+ self.grid_status_memory = True
+
log.debug("Distance Tool --> tool initialized")
+ def on_snap_toggled(self, state):
+ self.app.defaults['tools_dist_snap_center'] = state
+ if state:
+ # disengage the grid snapping since it will be hard to find the drills or pads on grid
+ if self.app.ui.grid_snap_btn.isChecked():
+ self.app.ui.grid_snap_btn.trigger()
+
def activate_measure_tool(self):
# ENABLE the Measuring TOOL
self.active = True
+ # disable the measuring button
+ self.measure_btn.setDisabled(True)
+ self.measure_btn.setText('%s...' % _("Working"))
+
self.clicked_meas = 0
self.original_call_source = copy(self.app.call_source)
+ snap_center = self.app.defaults['tools_dist_snap_center']
+ self.on_snap_toggled(snap_center)
+
self.app.inform.emit(_("MEASURING: Click on the Start point ..."))
self.units = self.app.defaults['units'].lower()
@@ -267,6 +328,10 @@ class Distance(FlatCAMTool):
self.active = False
self.points = []
+ # disable the measuring button
+ self.measure_btn.setDisabled(False)
+ self.measure_btn.setText(_("Measure"))
+
self.app.call_source = copy(self.original_call_source)
if self.original_call_source == 'app':
self.app.mm = self.canvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot)
@@ -307,8 +372,16 @@ class Distance(FlatCAMTool):
# delete the measuring line
self.delete_shape()
+ # restore the grid status
+ if (self.app.ui.grid_snap_btn.isChecked() and self.grid_status_memory is False) or \
+ (not self.app.ui.grid_snap_btn.isChecked() and self.grid_status_memory is True):
+ self.app.ui.grid_snap_btn.trigger()
+
log.debug("Distance Tool --> exit tool")
+ if self.tool_done is False:
+ self.app.inform.emit('%s' % _("Distance Tool finished."))
+
def on_mouse_click_release(self, event):
# mouse click releases will be accepted only if the left button is clicked
# this is necessary because right mouse click or middle mouse click
@@ -323,11 +396,71 @@ class Distance(FlatCAMTool):
pos_canvas = self.canvas.translate_coords(event_pos)
- # if GRID is active we need to get the snapped positions
- if self.app.grid_status() == True:
- pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
+ if self.snap_center_cb.get_value() is False:
+ # if GRID is active we need to get the snapped positions
+ if self.app.grid_status():
+ pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
+ else:
+ pos = pos_canvas[0], pos_canvas[1]
else:
- pos = pos_canvas[0], pos_canvas[1]
+ pos = (pos_canvas[0], pos_canvas[1])
+ current_pt = Point(pos)
+ shapes_storage = self.make_storage()
+
+ if self.original_call_source == 'exc_editor':
+ for storage in self.app.exc_editor.storage_dict:
+ __, st_closest_shape = self.app.exc_editor.storage_dict[storage].nearest(pos)
+ shapes_storage.insert(st_closest_shape)
+
+ __, closest_shape = shapes_storage.nearest(pos)
+
+ # if it's a drill
+ if isinstance(closest_shape.geo, MultiLineString):
+ radius = closest_shape.geo[0].length / 2.0
+ center_pt = closest_shape.geo.centroid
+
+ geo_buffered = center_pt.buffer(radius)
+
+ if current_pt.within(geo_buffered):
+ pos = (center_pt.x, center_pt.y)
+
+ # if it's a slot
+ elif isinstance(closest_shape.geo, Polygon):
+ geo_buffered = closest_shape.geo.buffer(0)
+ center_pt = geo_buffered.centroid
+
+ if current_pt.within(geo_buffered):
+ pos = (center_pt.x, center_pt.y)
+
+ elif self.original_call_source == 'grb_editor':
+ clicked_pads = list()
+ for storage in self.app.grb_editor.storage_dict:
+ try:
+ for shape_stored in self.app.grb_editor.storage_dict[storage]['geometry']:
+ if 'solid' in shape_stored.geo:
+ geometric_data = shape_stored.geo['solid']
+ if Point(current_pt).within(geometric_data):
+ if isinstance(shape_stored.geo['follow'], Point):
+ clicked_pads.append(shape_stored.geo['follow'])
+ except KeyError:
+ pass
+
+ if len(clicked_pads) > 1:
+ self.tool_done = True
+ self.deactivate_measure_tool()
+ self.app.inform.emit('[WARNING_NOTCL] %s' % _("Pads overlapped. Aborting."))
+ return
+
+ pos = (clicked_pads[0].x, clicked_pads[0].y)
+
+ self.app.on_jump_to(custom_location=pos, fit_center=False)
+ # Update cursor
+ self.app.app_cursor.enabled = True
+ self.app.app_cursor.set_data(np.asarray([(pos[0], pos[1])]),
+ symbol='++', edge_color='#000000',
+ edge_width=self.app.defaults["global_cursor_width"],
+ size=self.app.defaults["global_cursor_size"])
+
self.points.append(pos)
# Reset here the relative coordinates so there is a new reference on the click position
@@ -340,41 +473,46 @@ class Distance(FlatCAMTool):
self.rel_point2 = copy(self.rel_point1)
self.rel_point1 = pos
- if len(self.points) == 1:
- self.start_entry.set_value("(%.*f, %.*f)" % (self.decimals, pos[0], self.decimals, pos[1]))
- self.app.inform.emit(_("MEASURING: Click on the Destination point ..."))
- elif len(self.points) == 2:
- dx = self.points[1][0] - self.points[0][0]
- dy = self.points[1][1] - self.points[0][1]
- d = math.sqrt(dx ** 2 + dy ** 2)
- self.stop_entry.set_value("(%.*f, %.*f)" % (self.decimals, pos[0], self.decimals, pos[1]))
+ self.calculate_distance(pos=pos)
- self.app.inform.emit("{tx1}: {tx2} D(x) = {d_x} | D(y) = {d_y} | {tx3} = {d_z}".format(
- tx1=_("MEASURING"),
- tx2=_("Result"),
- tx3=_("Distance"),
- d_x='%*f' % (self.decimals, abs(dx)),
- d_y='%*f' % (self.decimals, abs(dy)),
- d_z='%*f' % (self.decimals, abs(d)))
+ def calculate_distance(self, pos):
+ if len(self.points) == 1:
+ self.start_entry.set_value("(%.*f, %.*f)" % (self.decimals, pos[0], self.decimals, pos[1]))
+ self.app.inform.emit(_("MEASURING: Click on the Destination point ..."))
+ elif len(self.points) == 2:
+ self.app.app_cursor.enabled = False
+ dx = self.points[1][0] - self.points[0][0]
+ dy = self.points[1][1] - self.points[0][1]
+ d = math.sqrt(dx ** 2 + dy ** 2)
+ self.stop_entry.set_value("(%.*f, %.*f)" % (self.decimals, pos[0], self.decimals, pos[1]))
+
+ self.app.inform.emit("{tx1}: {tx2} D(x) = {d_x} | D(y) = {d_y} | {tx3} = {d_z}".format(
+ tx1=_("MEASURING"),
+ tx2=_("Result"),
+ tx3=_("Distance"),
+ d_x='%*f' % (self.decimals, abs(dx)),
+ d_y='%*f' % (self.decimals, abs(dy)),
+ d_z='%*f' % (self.decimals, abs(d)))
+ )
+
+ self.distance_x_entry.set_value('%.*f' % (self.decimals, abs(dx)))
+ self.distance_y_entry.set_value('%.*f' % (self.decimals, abs(dy)))
+
+ if dx != 0.0:
+ try:
+ angle = math.degrees(math.atan(dy / dx))
+ self.angle_entry.set_value('%.*f' % (self.decimals, angle))
+ except Exception:
+ pass
+
+ self.total_distance_entry.set_value('%.*f' % (self.decimals, abs(d)))
+ self.app.ui.rel_position_label.setText(
+ "Dx: {} Dy: {} ".format(
+ '%.*f' % (self.decimals, pos[0]), '%.*f' % (self.decimals, pos[1])
)
-
- self.distance_x_entry.set_value('%.*f' % (self.decimals, abs(dx)))
- self.distance_y_entry.set_value('%.*f' % (self.decimals, abs(dy)))
-
- if dx != 0.0:
- try:
- angle = math.degrees(math.atan(dy / dx))
- self.angle_entry.set_value('%.*f' % (self.decimals, angle))
- except Exception as e:
- pass
-
- self.total_distance_entry.set_value('%.*f' % (self.decimals, abs(d)))
- self.app.ui.rel_position_label.setText(
- "Dx: {} Dy: {} ".format(
- '%.*f' % (self.decimals, pos[0]), '%.*f' % (self.decimals, pos[1])
- )
- )
- self.deactivate_measure_tool()
+ )
+ self.tool_done = True
+ self.deactivate_measure_tool()
def on_mouse_move_meas(self, event):
try: # May fail in case mouse not within axes
@@ -391,7 +529,7 @@ class Distance(FlatCAMTool):
pos_canvas = self.app.plotcanvas.translate_coords((x, y))
- if self.app.grid_status() == True:
+ if self.app.grid_status():
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
# Update cursor
@@ -465,7 +603,15 @@ class Distance(FlatCAMTool):
self.sel_shapes.clear()
self.sel_shapes.redraw()
- def set_meas_units(self, units):
- self.meas.units_label.setText("[" + self.app.options["units"].lower() + "]")
+ @staticmethod
+ def make_storage():
+ # ## Shape storage.
+ storage = FlatCAMRTreeStorage()
+ storage.get_points = DrawToolShape.get_pts
+
+ return storage
+
+ # def set_meas_units(self, units):
+ # self.meas.units_label.setText("[" + self.app.options["units"].lower() + "]")
# end of file