- 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)
This commit is contained in:
Marius Stanciu 2020-02-06 01:39:19 +02:00 committed by Marius
parent 23a1495c32
commit 7424bb917c
5 changed files with 298 additions and 128 deletions

View File

@ -890,6 +890,9 @@ class App(QtCore.QObject):
# Subtract Tool
"tools_sub_close_paths": True,
# Distance Tool
"tools_dist_snap_center": False,
# ###################################################################################
# ################################ TOOLS 2 ##########################################
# ###################################################################################

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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("<b>%s:</b>" % _('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("<b>%s:</b>" % _('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(
"<b>Dx</b>: {}&nbsp;&nbsp; <b>Dy</b>: {}&nbsp;&nbsp;&nbsp;&nbsp;".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(
"<b>Dx</b>: {}&nbsp;&nbsp; <b>Dy</b>: {}&nbsp;&nbsp;&nbsp;&nbsp;".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