- fixed bug in Panelization Tool for which in case of Excellon objects, the panel kept a reference to the source object which created issues when moving or disabling/enabling the plots

- cleaned up the module imports throughout the app (the TclCommands are not yet verified)
This commit is contained in:
Marius Stanciu 2019-10-16 02:28:18 +03:00 committed by Marius
parent 4be989fa5c
commit dfc0b98181
38 changed files with 567 additions and 407 deletions

View File

@ -9,6 +9,8 @@
import urllib.request
import urllib.parse
import urllib.error
import webbrowser
import getopt
import random
import simplejson as json
@ -40,10 +42,12 @@ import vispy.scene as scene
# #######################################
from ObjectCollection import *
from FlatCAMObj import *
from camlib import to_dict, dict2obj, ET, ParseError
from flatcamGUI.PlotCanvas import *
from flatcamGUI.PlotCanvasLegacy import *
from flatcamGUI.FlatCAMGUI import *
from FlatCAMCommon import LoudDict
from FlatCAMPostProc import load_postprocessors

View File

@ -10,24 +10,33 @@
# File modified by: Marius Stanciu #
# ##########################################################
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextDocument
from shapely.geometry import Point, Polygon, MultiPolygon, MultiLineString, LineString, LinearRing
from shapely.ops import cascaded_union
import shapely.affinity as affinity
import copy
from copy import deepcopy
from io import StringIO
import traceback
import inspect # TODO: For debugging only.
from datetime import datetime
from flatcamEditors.FlatCAMTextEditor import TextEditor
from flatcamGUI.ObjectUI import *
from FlatCAMCommon import LoudDict
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
from camlib import *
from flatcamParsers.ParseExcellon import Excellon
from flatcamParsers.ParseGerber import Gerber
from camlib import Geometry, CNCjob
import FlatCAMApp
import itertools
import tkinter as tk
import sys
import os, sys, itertools
import ezdxf
import math
import numpy as np
import gettext
import FlatCAMTranslation as fcTranslate
@ -66,7 +75,7 @@ class FlatCAMObj(QtCore.QObject):
app = None
# signal to plot a single object
plot_single_object = pyqtSignal()
plot_single_object = QtCore.pyqtSignal()
def __init__(self, name):
"""

View File

@ -9,8 +9,6 @@
from importlib.machinery import SourceFileLoader
import os
from abc import ABCMeta, abstractmethod
from datetime import datetime
import math
# module-root dictionary of postprocessors
import FlatCAMApp

View File

@ -11,13 +11,20 @@
# File modified by: Marius Stanciu #
# ##########################################################
# from PyQt5.QtCore import QModelIndex
from FlatCAMObj import *
import inspect # TODO: Remove
import FlatCAMApp
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, QSettings
# import webbrowser
from PyQt5.QtGui import QColor
# from PyQt5.QtCore import QModelIndex
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry, FlatCAMExcellon, FlatCAMCNCjob, FlatCAMDocument, FlatCAMScript
import inspect # TODO: Remove
import FlatCAMApp
import re
import logging
import collections
from copy import deepcopy
from numpy import Inf
import gettext
import FlatCAMTranslation as fcTranslate
@ -27,6 +34,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class KeySensitiveListView(QtWidgets.QTreeView):
"""

View File

@ -12,6 +12,8 @@ CAD program, and create G-Code for Isolation routing.
15.10.2019
- adjusted the layout in NCC Tool
- fixed bug in Panelization Tool for which in case of Excellon objects, the panel kept a reference to the source object which created issues when moving or disabling/enabling the plots
- cleaned up the module imports throughout the app (the TclCommands are not yet verified)
14.10.2019

View File

@ -11,12 +11,9 @@ from PyQt5 import QtWidgets
from io import StringIO
import numpy as np
from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos, dot, float32, \
transpose
from numpy.linalg import solve, norm
import re, sys, os, platform
import math
import platform
from copy import deepcopy
import traceback
@ -26,8 +23,8 @@ from rtree import index as rtindex
from lxml import etree as ET
# See: http://toblerity.org/shapely/manual.html
from shapely.geometry import Polygon, LineString, Point, LinearRing, MultiLineString
from shapely.geometry import MultiPoint, MultiPolygon
from shapely.geometry import Polygon, LineString, Point, LinearRing, MultiLineString, MultiPoint, MultiPolygon
from shapely.geometry import box as shply_box
from shapely.ops import cascaded_union, unary_union, polygonize
import shapely.affinity as affinity
@ -64,7 +61,6 @@ import gettext
import FlatCAMTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
log = logging.getLogger('base2')
@ -336,8 +332,8 @@ class ApertureMacro:
points = [(0, 0)]*nverts
for i in range(nverts):
points[i] = (x + 0.5 * dia * cos(2*pi * i/nverts),
y + 0.5 * dia * sin(2*pi * i/nverts))
points[i] = (x + 0.5 * dia * np.cos(2*np.pi * i/nverts),
y + 0.5 * dia * np.sin(2*np.pi * i/nverts))
poly = Polygon(points)
poly_rotated = affinity.rotate(poly, angle, origin=(0, 0))
@ -637,10 +633,10 @@ class Geometry(object):
def bounds_rec(obj):
if type(obj) is list:
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
minx = np.Inf
miny = np.Inf
maxx = -np.Inf
maxy = -np.Inf
for k in obj:
if type(k) is dict:
@ -1155,7 +1151,7 @@ class Geometry(object):
log.debug("Image import as monochrome.")
else:
mask_setting = (red <= mask[1]) + (green <= mask[2]) + (blue <= mask[3])
total = np.zeros(red.shape, dtype=float32)
total = np.zeros(red.shape, dtype=np.float32)
for band in red, green, blue:
total += band
total /= 3
@ -3298,10 +3294,10 @@ class CNCjob(Geometry):
def bounds_rec(obj):
if type(obj) is list:
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
minx = np.Inf
miny = np.Inf
maxx = -np.Inf
maxy = -np.Inf
for k in obj:
if type(k) is dict:
@ -4049,9 +4045,9 @@ class CNCjob(Geometry):
arcdir = [None, None, "cw", "ccw"]
if current['G'] in [2, 3]: # arc
center = [gobj['I'] + current['X'], gobj['J'] + current['Y']]
radius = sqrt(gobj['I']**2 + gobj['J']**2)
start = arctan2(-gobj['J'], -gobj['I'])
stop = arctan2(-center[1] + y, -center[0] + x)
radius = np.sqrt(gobj['I']**2 + gobj['J']**2)
start = np.arctan2(-gobj['J'], -gobj['I'])
stop = np.arctan2(-center[1] + y, -center[0] + x)
path += arc(center, radius, start, stop, arcdir[current['G']], int(self.steps_per_circle / 4))
# Update current instruction
@ -4710,10 +4706,10 @@ class CNCjob(Geometry):
def bounds_rec(obj):
if type(obj) is list:
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
minx = np.Inf
miny = np.Inf
maxx = -np.Inf
maxy = -np.Inf
for k in obj:
if type(k) is dict:
@ -4742,15 +4738,15 @@ class CNCjob(Geometry):
bounds_coords = bounds_rec(self.solid_geometry)
else:
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
minx = np.Inf
miny = np.Inf
maxx = -np.Inf
maxy = -np.Inf
for k, v in self.cnc_tools.items():
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
minx = np.Inf
miny = np.Inf
maxx = -np.Inf
maxy = -np.Inf
try:
for k in v['solid_geometry']:
minx_, miny_, maxx_, maxy_ = bounds_rec(k)
@ -5186,10 +5182,10 @@ class CNCjob(Geometry):
def get_bounds(geometry_list):
xmin = Inf
ymin = Inf
xmax = -Inf
ymax = -Inf
xmin = np.Inf
ymin = np.Inf
xmax = -np.Inf
ymax = -np.Inf
for gs in geometry_list:
try:
@ -5229,33 +5225,33 @@ def arc(center, radius, start, stop, direction, steps_per_circ):
da_sign = {"cw": -1.0, "ccw": 1.0}
points = []
if direction == "ccw" and stop <= start:
stop += 2 * pi
stop += 2 * np.pi
if direction == "cw" and stop >= start:
stop -= 2 * pi
stop -= 2 * np.pi
angle = abs(stop - start)
# angle = stop-start
steps = max([int(ceil(angle / (2 * pi) * steps_per_circ)), 2])
steps = max([int(np.ceil(angle / (2 * np.pi) * steps_per_circ)), 2])
delta_angle = da_sign[direction] * angle * 1.0 / steps
for i in range(steps + 1):
theta = start + delta_angle * i
points.append((center[0] + radius * cos(theta), center[1] + radius * sin(theta)))
points.append((center[0] + radius * np.cos(theta), center[1] + radius * np.sin(theta)))
return points
def arc2(p1, p2, center, direction, steps_per_circ):
r = sqrt((center[0] - p1[0]) ** 2 + (center[1] - p1[1]) ** 2)
start = arctan2(p1[1] - center[1], p1[0] - center[0])
stop = arctan2(p2[1] - center[1], p2[0] - center[0])
r = np.sqrt((center[0] - p1[0]) ** 2 + (center[1] - p1[1]) ** 2)
start = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stop = np.arctan2(p2[1] - center[1], p2[0] - center[0])
return arc(center, r, start, stop, direction, steps_per_circ)
def arc_angle(start, stop, direction):
if direction == "ccw" and stop <= start:
stop += 2 * pi
stop += 2 * np.pi
if direction == "cw" and stop >= start:
stop -= 2 * pi
stop -= 2 * np.pi
angle = abs(stop - start)
return angle
@ -5665,12 +5661,12 @@ def three_point_circle(p1, p2, p3):
a2 = (p2 + p3) / 2.0
# Normals
b1 = dot((p2 - p1), array([[0, -1], [1, 0]], dtype=float32))
b2 = dot((p3 - p2), array([[0, 1], [-1, 0]], dtype=float32))
b1 = np.dot((p2 - p1), np.array([[0, -1], [1, 0]], dtype=np.float32))
b2 = np.dot((p3 - p2), np.array([[0, 1], [-1, 0]], dtype=np.float32))
# Params
try:
T = solve(transpose(array([-b1, b2])), a1 - a2)
T = solve(np.transpose(np.array([-b1, b2])), a1 - a2)
except Exception as e:
log.debug("camlib.three_point_circle() --> %s" % str(e))
return
@ -5685,11 +5681,11 @@ def three_point_circle(p1, p2, p3):
def distance(pt1, pt2):
return sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2)
return np.sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2)
def distance_euclidian(x1, y1, x2, y2):
return sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
return np.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
class FlatCAMRTree(object):

View File

@ -8,19 +8,23 @@
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, QSettings
from shapely.geometry import LineString, LinearRing, MultiLineString
from shapely.ops import cascaded_union
import shapely.affinity as affinity
from numpy import arctan2, Inf, array, sqrt, sign, dot
from rtree import index as rtindex
from camlib import *
from camlib import distance, arc, FlatCAMRTreeStorage
from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, LengthEntry, RadioSet, SpinBoxDelegate
from flatcamEditors.FlatCAMGeoEditor import FCShapeTool, DrawTool, DrawToolShape, DrawToolUtilityShape, FlatCAMGeoEditor
from flatcamParsers.ParseExcellon import Excellon
import FlatCAMApp
from copy import copy, deepcopy
from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon, Point
import shapely.affinity as affinity
import numpy as np
from rtree import index as rtindex
import traceback
import math
import logging
from copy import deepcopy
import gettext
import FlatCAMTranslation as fcTranslate
@ -30,6 +34,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class FCDrillAdd(FCShapeTool):
"""
@ -3214,8 +3220,7 @@ class FlatCAMExcEditor(QtCore.QObject):
_("An internal error has ocurred. See Shell.\n")
msg += traceback.format_exc()
app_obj.inform.emit(msg)
raise
# raise
return
with self.app.proc_container.new(_("Creating Excellon.")):
@ -3998,10 +4003,10 @@ class FlatCAMExcEditor(QtCore.QObject):
def get_shapely_list_bounds(geometry_list):
xmin = Inf
ymin = Inf
xmax = -Inf
ymax = -Inf
xmin = np.Inf
ymin = np.Inf
xmax = -np.Inf
ymax = -np.Inf
for gs in geometry_list:
try:

View File

@ -13,24 +13,26 @@
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, QSettings
from camlib import *
from camlib import distance, arc, three_point_circle, Geometry, FlatCAMRTreeStorage
from FlatCAMTool import FlatCAMTool
from flatcamGUI.ObjectUI import LengthEntry, RadioSet
from flatcamGUI.ObjectUI import RadioSet
from flatcamGUI.GUIElements import OptionalInputSection, FCCheckBox, FCEntry, FCComboBox, FCTextAreaRich, \
FCTable, FCDoubleSpinner, FCButton, EvalEntry2, FCInputDialog
from flatcamParsers.ParseFont import *
import FlatCAMApp
from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon
# from shapely.geometry import mapping
from shapely.ops import cascaded_union, unary_union
import shapely.affinity as affinity
from shapely.geometry.polygon import orient
from numpy import arctan2, Inf, array, sqrt, sign, dot
import numpy as np
from numpy.linalg import norm as numpy_norm
from rtree import index as rtindex
from flatcamGUI.GUIElements import OptionalInputSection, FCCheckBox, FCEntry, FCComboBox, FCTextAreaRich, \
FCTable, FCDoubleSpinner, FCButton, EvalEntry2, FCInputDialog
from flatcamParsers.ParseFont import *
from copy import deepcopy
# from vispy.io import read_png
import gettext
import FlatCAMTranslation as fcTranslate
@ -684,8 +686,8 @@ class TransformEditorTool(FlatCAMTool):
self.rotate_button.set_value(_("Rotate"))
self.rotate_button.setToolTip(
_("Rotate the selected shape(s).\n"
"The point of reference is the middle of\n"
"the bounding box for all selected shapes.")
"The point of reference is the middle of\n"
"the bounding box for all selected shapes.")
)
self.rotate_button.setFixedWidth(60)
@ -802,7 +804,7 @@ class TransformEditorTool(FlatCAMTool):
self.scale_link_cb.setText(_("Link"))
self.scale_link_cb.setToolTip(
_("Scale the selected shape(s)\n"
"using the Scale Factor X for both axis."))
"using the Scale Factor X for both axis."))
self.scale_link_cb.setFixedWidth(50)
self.scale_zero_ref_cb = FCCheckBox()
@ -1060,7 +1062,6 @@ class TransformEditorTool(FlatCAMTool):
_("Transformation cancelled. No shape selected."))
return
self.draw_app.select_tool("select")
self.app.ui.notebook.setTabText(2, "Tools")
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
@ -1081,10 +1082,7 @@ class TransformEditorTool(FlatCAMTool):
self.app.inform.emit('[ERROR_NOTCL] %s' %
_("Wrong value format entered, use a number."))
return
self.app.worker_task.emit({'fcn': self.on_rotate_action,
'params': [value]})
# self.on_rotate_action(value)
return
self.app.worker_task.emit({'fcn': self.on_rotate_action, 'params': [value]})
def on_flipx(self):
# self.on_flip("Y")
@ -1205,13 +1203,9 @@ class TransformEditorTool(FlatCAMTool):
axis = 'Y'
point = (0, 0)
if self.scale_zero_ref_cb.get_value():
self.app.worker_task.emit({'fcn': self.on_scale,
'params': [axis, xvalue, yvalue, point]})
# self.on_scale("Y", xvalue, yvalue, point=(0,0))
self.app.worker_task.emit({'fcn': self.on_scale, 'params': [axis, xvalue, yvalue, point]})
else:
# self.on_scale("Y", xvalue, yvalue)
self.app.worker_task.emit({'fcn': self.on_scale,
'params': [axis, xvalue, yvalue]})
self.app.worker_task.emit({'fcn': self.on_scale, 'params': [axis, xvalue, yvalue]})
return
@ -1304,7 +1298,7 @@ class TransformEditorTool(FlatCAMTool):
except Exception as e:
self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
(_("Rotation action was not executed"),str(e)))
(_("Rotation action was not executed"), str(e)))
return
def on_flip(self, axis):
@ -1664,10 +1658,10 @@ class DrawToolShape(object):
# now it can get bounds for nested lists of objects
def bounds_rec(shape_el):
if type(shape_el) is list:
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
minx = np.Inf
miny = np.Inf
maxx = -np.Inf
maxy = -np.Inf
for k in shape_el:
minx_, miny_, maxx_, maxy_ = bounds_rec(k)
@ -1904,10 +1898,10 @@ class DrawTool(object):
def bounds(self, obj):
def bounds_rec(o):
if type(o) is list:
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
minx = np.Inf
miny = np.Inf
maxx = -np.Inf
maxy = -np.Inf
for k in o:
try:
@ -1977,7 +1971,7 @@ class FCCircle(FCShapeTool):
if len(self.points) == 1:
p1 = self.points[0]
p2 = data
radius = sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
radius = np.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
return DrawToolUtilityShape(Point(p1).buffer(radius, int(self.steps_per_circ / 4)))
return None
@ -2086,36 +2080,36 @@ class FCArc(FCShapeTool):
p1 = self.points[1]
p2 = data
radius = sqrt((center[0] - p1[0]) ** 2 + (center[1] - p1[1]) ** 2)
startangle = arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = arctan2(p2[1] - center[1], p2[0] - center[0])
radius = np.sqrt((center[0] - p1[0]) ** 2 + (center[1] - p1[1]) ** 2)
startangle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = np.arctan2(p2[1] - center[1], p2[0] - center[0])
return DrawToolUtilityShape([LineString(arc(center, radius, startangle, stopangle,
self.direction, self.steps_per_circ)),
Point(center)])
elif self.mode == '132':
p1 = array(self.points[0])
p3 = array(self.points[1])
p2 = array(data)
p1 = np.array(self.points[0])
p3 = np.array(self.points[1])
p2 = np.array(data)
try:
center, radius, t = three_point_circle(p1, p2, p3)
except TypeError:
return
direction = 'cw' if sign(t) > 0 else 'ccw'
direction = 'cw' if np.sign(t) > 0 else 'ccw'
startangle = arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = arctan2(p3[1] - center[1], p3[0] - center[0])
startangle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = np.arctan2(p3[1] - center[1], p3[0] - center[0])
return DrawToolUtilityShape([LineString(arc(center, radius, startangle, stopangle,
direction, self.steps_per_circ)),
Point(center), Point(p1), Point(p3)])
else: # '12c'
p1 = array(self.points[0])
p2 = array(self.points[1])
p1 = np.array(self.points[0])
p2 = np.array(self.points[1])
# Midpoint
a = (p1 + p2) / 2.0
@ -2124,7 +2118,7 @@ class FCArc(FCShapeTool):
c = p2 - p1
# Perpendicular vector
b = dot(c, array([[0, -1], [1, 0]], dtype=float32))
b = np.dot(c, np.array([[0, -1], [1, 0]], dtype=np.float32))
b /= numpy_norm(b)
# Distance
@ -2133,14 +2127,14 @@ class FCArc(FCShapeTool):
# Which side? Cross product with c.
# cross(M-A, B-A), where line is AB and M is test point.
side = (data[0] - p1[0]) * c[1] - (data[1] - p1[1]) * c[0]
t *= sign(side)
t *= np.sign(side)
# Center = a + bt
center = a + b * t
radius = numpy_norm(center - p1)
startangle = arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = arctan2(p2[1] - center[1], p2[0] - center[0])
startangle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = np.arctan2(p2[1] - center[1], p2[0] - center[0])
return DrawToolUtilityShape([LineString(arc(center, radius, startangle, stopangle,
self.direction, self.steps_per_circ)),
@ -2156,29 +2150,29 @@ class FCArc(FCShapeTool):
p2 = self.points[2]
radius = distance(center, p1)
startangle = arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = arctan2(p2[1] - center[1], p2[0] - center[0])
startangle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = np.arctan2(p2[1] - center[1], p2[0] - center[0])
self.geometry = DrawToolShape(LineString(arc(center, radius, startangle, stopangle,
self.direction, self.steps_per_circ)))
elif self.mode == '132':
p1 = array(self.points[0])
p3 = array(self.points[1])
p2 = array(self.points[2])
p1 = np.array(self.points[0])
p3 = np.array(self.points[1])
p2 = np.array(self.points[2])
center, radius, t = three_point_circle(p1, p2, p3)
direction = 'cw' if sign(t) > 0 else 'ccw'
direction = 'cw' if np.sign(t) > 0 else 'ccw'
startangle = arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = arctan2(p3[1] - center[1], p3[0] - center[0])
startangle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = np.arctan2(p3[1] - center[1], p3[0] - center[0])
self.geometry = DrawToolShape(LineString(arc(center, radius, startangle, stopangle,
direction, self.steps_per_circ)))
else: # self.mode == '12c'
p1 = array(self.points[0])
p2 = array(self.points[1])
pc = array(self.points[2])
p1 = np.array(self.points[0])
p2 = np.array(self.points[1])
pc = np.array(self.points[2])
# Midpoint
a = (p1 + p2) / 2.0
@ -2187,7 +2181,7 @@ class FCArc(FCShapeTool):
c = p2 - p1
# Perpendicular vector
b = dot(c, array([[0, -1], [1, 0]], dtype=float32))
b = np.dot(c, np.array([[0, -1], [1, 0]], dtype=np.float32))
b /= numpy_norm(b)
# Distance
@ -2196,14 +2190,14 @@ class FCArc(FCShapeTool):
# Which side? Cross product with c.
# cross(M-A, B-A), where line is AB and M is test point.
side = (pc[0] - p1[0]) * c[1] - (pc[1] - p1[1]) * c[0]
t *= sign(side)
t *= np.sign(side)
# Center = a + bt
center = a + b * t
radius = numpy_norm(center - p1)
startangle = arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = arctan2(p2[1] - center[1], p2[0] - center[0])
startangle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = np.arctan2(p2[1] - center[1], p2[0] - center[0])
self.geometry = DrawToolShape(LineString(arc(center, radius, startangle, stopangle,
self.direction, self.steps_per_circ)))
@ -4237,7 +4231,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
"""
snap_x, snap_y = (x, y)
snap_distance = Inf
snap_distance = np.Inf
# # ## Object (corner?) snap
# # ## No need for the objects, just the coordinates
@ -4814,11 +4808,11 @@ class FlatCAMGeoEditor(QtCore.QObject):
def distance(pt1, pt2):
return sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2)
return np.sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2)
def mag(vec):
return sqrt(vec[0] ** 2 + vec[1] ** 2)
return np.sqrt(vec[0] ** 2 + vec[1] ** 2)
def poly2rings(poly):
@ -4826,10 +4820,10 @@ def poly2rings(poly):
def get_shapely_list_bounds(geometry_list):
xmin = Inf
ymin = Inf
xmax = -Inf
ymax = -Inf
xmin = np.Inf
ymin = np.Inf
xmax = -np.Inf
ymax = -np.Inf
for gs in geometry_list:
try:

View File

@ -8,29 +8,28 @@
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, QSettings
from shapely.geometry import LineString, LinearRing, MultiLineString
# from shapely.geometry import mapping
from shapely.ops import cascaded_union, unary_union
from shapely.geometry import LineString, LinearRing, MultiLineString, Point, Polygon, MultiPolygon
from shapely.ops import cascaded_union
import shapely.affinity as affinity
from numpy import arctan2, Inf, array, sqrt, sign, dot
from rtree import index as rtindex
import threading
import time
from copy import copy, deepcopy
import logging
from camlib import *
from camlib import distance, arc, three_point_circle
from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, LengthEntry, RadioSet, \
SpinBoxDelegate, EvalEntry, EvalEntry2, FCInputDialog, FCButton, OptionalInputSection, FCCheckBox
from FlatCAMObj import FlatCAMGerber
from flatcamParsers.ParseGerber import Gerber
EvalEntry2, FCInputDialog, FCButton, OptionalInputSection, FCCheckBox
from FlatCAMTool import FlatCAMTool
import FlatCAMApp
import numpy as np
from numpy.linalg import norm as numpy_norm
import math
# from vispy.io import read_png
# import pngcanvas
import traceback
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -39,6 +38,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class DrawToolShape(object):
"""
@ -147,10 +148,10 @@ class DrawTool(object):
def bounds(obj):
def bounds_rec(o):
if type(o) is list:
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
minx = np.Inf
miny = np.Inf
maxx = -np.Inf
maxy = -np.Inf
for k in o:
try:
@ -311,13 +312,13 @@ class FCPad(FCShapeTool):
p4 = (point_x - self.half_width, point_y + self.half_height - self.half_width)
down_center = [point_x, point_y - self.half_height + self.half_width]
d_start_angle = math.pi
d_start_angle = np.pi
d_stop_angle = 0.0
down_arc = arc(down_center, self.half_width, d_start_angle, d_stop_angle, 'ccw', self.steps_per_circ)
up_center = [point_x, point_y + self.half_height - self.half_width]
u_start_angle = 0.0
u_stop_angle = math.pi
u_stop_angle = np.pi
up_arc = arc(up_center, self.half_width, u_start_angle, u_stop_angle, 'ccw', self.steps_per_circ)
geo.append(p1)
@ -340,13 +341,13 @@ class FCPad(FCShapeTool):
p4 = (point_x - self.half_width + self.half_height, point_y + self.half_height)
left_center = [point_x - self.half_width + self.half_height, point_y]
d_start_angle = math.pi / 2
d_stop_angle = 1.5 * math.pi
d_start_angle = np.pi / 2
d_stop_angle = 1.5 * np.pi
left_arc = arc(left_center, self.half_height, d_start_angle, d_stop_angle, 'ccw', self.steps_per_circ)
right_center = [point_x + self.half_width - self.half_height, point_y]
u_start_angle = 1.5 * math.pi
u_stop_angle = math.pi / 2
u_start_angle = 1.5 * np.pi
u_stop_angle = np.pi / 2
right_arc = arc(right_center, self.half_height, u_start_angle, u_stop_angle, 'ccw', self.steps_per_circ)
geo.append(p1)
@ -618,13 +619,13 @@ class FCPadArray(FCShapeTool):
p4 = (point_x - self.half_width, point_y + self.half_height - self.half_width)
down_center = [point_x, point_y - self.half_height + self.half_width]
d_start_angle = math.pi
d_start_angle = np.pi
d_stop_angle = 0.0
down_arc = arc(down_center, self.half_width, d_start_angle, d_stop_angle, 'ccw', self.steps_per_circ)
up_center = [point_x, point_y + self.half_height - self.half_width]
u_start_angle = 0.0
u_stop_angle = math.pi
u_stop_angle = np.pi
up_arc = arc(up_center, self.half_width, u_start_angle, u_stop_angle, 'ccw', self.steps_per_circ)
geo.append(p1)
@ -647,13 +648,13 @@ class FCPadArray(FCShapeTool):
p4 = (point_x - self.half_width + self.half_height, point_y + self.half_height)
left_center = [point_x - self.half_width + self.half_height, point_y]
d_start_angle = math.pi / 2
d_stop_angle = 1.5 * math.pi
d_start_angle = np.pi / 2
d_stop_angle = 1.5 * np.pi
left_arc = arc(left_center, self.half_height, d_start_angle, d_stop_angle, 'ccw', self.steps_per_circ)
right_center = [point_x + self.half_width - self.half_height, point_y]
u_start_angle = 1.5 * math.pi
u_stop_angle = math.pi / 2
u_start_angle = 1.5 * np.pi
u_stop_angle = np.pi / 2
right_arc = arc(right_center, self.half_height, u_start_angle, u_stop_angle, 'ccw', self.steps_per_circ)
geo.append(p1)
@ -1296,7 +1297,7 @@ class FCTrack(FCRegion):
self.draw_app.bend_mode = 2
self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_path2.png'))
QtGui.QGuiApplication.setOverrideCursor(self.cursor)
msg = _('Track Mode 2: Reverse 45 degrees ...')
msg = _('Track Mode 2: Reverse 45 degrees ...')
elif self.draw_app.bend_mode == 2:
self.draw_app.bend_mode = 3
self.cursor = QtGui.QCursor(QtGui.QPixmap('share/aero_path3.png'))
@ -1415,7 +1416,7 @@ class FCDisc(FCShapeTool):
if len(self.points) == 1:
p1 = self.points[0]
p2 = data
radius = sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
radius = math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
new_geo_el['solid'] = Point(p1).buffer((radius + self.buf_val / 2), int(self.steps_per_circ / 4))
return DrawToolUtilityShape(new_geo_el)
@ -1557,9 +1558,9 @@ class FCSemiDisc(FCShapeTool):
p1 = self.points[1]
p2 = data
radius = sqrt((center[0] - p1[0]) ** 2 + (center[1] - p1[1]) ** 2) + (self.buf_val / 2)
startangle = arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = arctan2(p2[1] - center[1], p2[0] - center[0])
radius = np.sqrt((center[0] - p1[0]) ** 2 + (center[1] - p1[1]) ** 2) + (self.buf_val / 2)
startangle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = np.arctan2(p2[1] - center[1], p2[0] - center[0])
new_geo_el['solid'] = LineString(
arc(center, radius, startangle, stopangle, self.direction, self.steps_per_circ))
@ -1567,20 +1568,20 @@ class FCSemiDisc(FCShapeTool):
return DrawToolUtilityShape([new_geo_el, new_geo_el_pt1])
elif self.mode == '132':
p1 = array(self.points[0])
p3 = array(self.points[1])
p2 = array(data)
p1 = np.array(self.points[0])
p3 = np.array(self.points[1])
p2 = np.array(data)
try:
center, radius, t = three_point_circle(p1, p2, p3)
except TypeError:
return
direction = 'cw' if sign(t) > 0 else 'ccw'
direction = 'cw' if np.sign(t) > 0 else 'ccw'
radius += (self.buf_val / 2)
startangle = arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = arctan2(p3[1] - center[1], p3[0] - center[0])
startangle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = np.arctan2(p3[1] - center[1], p3[0] - center[0])
new_geo_el['solid'] = LineString(
arc(center, radius, startangle, stopangle, direction, self.steps_per_circ))
@ -1591,8 +1592,8 @@ class FCSemiDisc(FCShapeTool):
return DrawToolUtilityShape([new_geo_el, new_geo_el_pt2, new_geo_el_pt1, new_geo_el_pt3])
else: # '12c'
p1 = array(self.points[0])
p2 = array(self.points[1])
p1 = np.array(self.points[0])
p2 = np.array(self.points[1])
# Midpoint
a = (p1 + p2) / 2.0
@ -1600,7 +1601,7 @@ class FCSemiDisc(FCShapeTool):
c = p2 - p1
# Perpendicular vector
b = dot(c, array([[0, -1], [1, 0]], dtype=float32))
b = np.dot(c, np.array([[0, -1], [1, 0]], dtype=np.float32))
b /= numpy_norm(b)
# Distance
@ -1609,14 +1610,14 @@ class FCSemiDisc(FCShapeTool):
# Which side? Cross product with c.
# cross(M-A, B-A), where line is AB and M is test point.
side = (data[0] - p1[0]) * c[1] - (data[1] - p1[1]) * c[0]
t *= sign(side)
t *= np.sign(side)
# Center = a + bt
center = a + b * t
radius = numpy_norm(center - p1) + (self.buf_val / 2)
startangle = arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = arctan2(p2[1] - center[1], p2[0] - center[0])
startangle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stopangle = np.arctan2(p2[1] - center[1], p2[0] - center[0])
new_geo_el['solid'] = LineString(
arc(center, radius, startangle, stopangle, self.direction, self.steps_per_circ))
@ -1636,8 +1637,8 @@ class FCSemiDisc(FCShapeTool):
p2 = self.points[2]
radius = distance(center, p1) + (self.buf_val / 2)
start_angle = arctan2(p1[1] - center[1], p1[0] - center[0])
stop_angle = arctan2(p2[1] - center[1], p2[0] - center[0])
start_angle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stop_angle = np.arctan2(p2[1] - center[1], p2[0] - center[0])
new_geo_el['solid'] = Polygon(
arc(center, radius, start_angle, stop_angle, self.direction, self.steps_per_circ))
new_geo_el['follow'] = Polygon(
@ -1645,16 +1646,16 @@ class FCSemiDisc(FCShapeTool):
self.geometry = DrawToolShape(new_geo_el)
elif self.mode == '132':
p1 = array(self.points[0])
p3 = array(self.points[1])
p2 = array(self.points[2])
p1 = np.array(self.points[0])
p3 = np.array(self.points[1])
p2 = np.array(self.points[2])
center, radius, t = three_point_circle(p1, p2, p3)
direction = 'cw' if sign(t) > 0 else 'ccw'
direction = 'cw' if np.sign(t) > 0 else 'ccw'
radius += (self.buf_val / 2)
start_angle = arctan2(p1[1] - center[1], p1[0] - center[0])
stop_angle = arctan2(p3[1] - center[1], p3[0] - center[0])
start_angle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stop_angle = np.arctan2(p3[1] - center[1], p3[0] - center[0])
new_geo_el['solid'] = Polygon(arc(center, radius, start_angle, stop_angle, direction, self.steps_per_circ))
new_geo_el['follow'] = Polygon(
@ -1662,9 +1663,9 @@ class FCSemiDisc(FCShapeTool):
self.geometry = DrawToolShape(new_geo_el)
else: # self.mode == '12c'
p1 = array(self.points[0])
p2 = array(self.points[1])
pc = array(self.points[2])
p1 = np.array(self.points[0])
p2 = np.array(self.points[1])
pc = np.array(self.points[2])
# Midpoint
a = (p1 + p2) / 2.0
@ -1673,7 +1674,7 @@ class FCSemiDisc(FCShapeTool):
c = p2 - p1
# Perpendicular vector
b = dot(c, array([[0, -1], [1, 0]], dtype=float32))
b = np.dot(c, np.array([[0, -1], [1, 0]], dtype=np.float32))
b /= numpy_norm(b)
# Distance
@ -1682,14 +1683,14 @@ class FCSemiDisc(FCShapeTool):
# Which side? Cross product with c.
# cross(M-A, B-A), where line is AB and M is test point.
side = (pc[0] - p1[0]) * c[1] - (pc[1] - p1[1]) * c[0]
t *= sign(side)
t *= np.sign(side)
# Center = a + bt
center = a + b * t
radius = numpy_norm(center - p1) + (self.buf_val / 2)
start_angle = arctan2(p1[1] - center[1], p1[0] - center[0])
stop_angle = arctan2(p2[1] - center[1], p2[0] - center[0])
start_angle = np.arctan2(p1[1] - center[1], p1[0] - center[0])
stop_angle = np.arctan2(p2[1] - center[1], p2[0] - center[0])
new_geo_el['solid'] = Polygon(
arc(center, radius, start_angle, stop_angle, self.direction, self.steps_per_circ))
@ -2437,9 +2438,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.apertures_box.addLayout(grid1)
apcode_lbl = QtWidgets.QLabel('%s:' % _('Aperture Code'))
apcode_lbl.setToolTip(
_("Code for the new aperture")
)
apcode_lbl.setToolTip(_("Code for the new aperture"))
grid1.addWidget(apcode_lbl, 1, 0)
self.apcode_entry = FCEntry()
@ -2448,11 +2447,11 @@ class FlatCAMGrbEditor(QtCore.QObject):
apsize_lbl = QtWidgets.QLabel('%s:' % _('Aperture Size'))
apsize_lbl.setToolTip(
_("Size for the new aperture.\n"
"If aperture type is 'R' or 'O' then\n"
"this value is automatically\n"
"calculated as:\n"
"sqrt(width**2 + height**2)")
_("Size for the new aperture.\n"
"If aperture type is 'R' or 'O' then\n"
"this value is automatically\n"
"calculated as:\n"
"sqrt(width**2 + height**2)")
)
grid1.addWidget(apsize_lbl, 2, 0)
@ -2462,10 +2461,10 @@ class FlatCAMGrbEditor(QtCore.QObject):
aptype_lbl = QtWidgets.QLabel('%s:' % _('Aperture Type'))
aptype_lbl.setToolTip(
_("Select the type of new aperture. Can be:\n"
"C = circular\n"
"R = rectangular\n"
"O = oblong")
_("Select the type of new aperture. Can be:\n"
"C = circular\n"
"R = rectangular\n"
"O = oblong")
)
grid1.addWidget(aptype_lbl, 3, 0)
@ -2475,9 +2474,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.apdim_lbl = QtWidgets.QLabel('%s:' % _('Aperture Dim'))
self.apdim_lbl.setToolTip(
_("Dimensions for the new aperture.\n"
"Active only for rectangular apertures (type R).\n"
"The format is (width, height)")
_("Dimensions for the new aperture.\n"
"Active only for rectangular apertures (type R).\n"
"The format is (width, height)")
)
grid1.addWidget(self.apdim_lbl, 4, 0)
@ -2495,12 +2494,12 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.addaperture_btn = QtWidgets.QPushButton(_('Add'))
self.addaperture_btn.setToolTip(
_( "Add a new aperture to the aperture list.")
_("Add a new aperture to the aperture list.")
)
self.delaperture_btn = QtWidgets.QPushButton(_('Delete'))
self.delaperture_btn.setToolTip(
_( "Delete a aperture in the aperture list")
_("Delete a aperture in the aperture list")
)
hlay_ad.addWidget(self.addaperture_btn)
hlay_ad.addWidget(self.delaperture_btn)
@ -2677,8 +2676,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.array_type_combo = FCComboBox()
self.array_type_combo.setToolTip(
_( "Select the type of pads array to create.\n"
"It can be Linear X(Y) or Circular")
_("Select the type of pads array to create.\n"
"It can be Linear X(Y) or Circular")
)
self.array_type_combo.addItem(_("Linear"))
self.array_type_combo.addItem(_("Circular"))
@ -2733,10 +2732,10 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.linear_angle_label = QtWidgets.QLabel('%s:' % _('Angle'))
self.linear_angle_label.setToolTip(
_( "Angle at which the linear array is placed.\n"
"The precision is of max 2 decimals.\n"
"Min value is: -359.99 degrees.\n"
"Max value is: 360.00 degrees.")
_("Angle at which the linear array is placed.\n"
"The precision is of max 2 decimals.\n"
"Min value is: -359.99 degrees.\n"
"Max value is: 360.00 degrees.")
)
self.linear_angle_label.setMinimumWidth(100)
@ -2808,9 +2807,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
"scale": {"button": self.app.ui.aperture_scale_btn,
"constructor": FCScale},
"markarea": {"button": self.app.ui.aperture_markarea_btn,
"constructor": FCMarkArea},
"constructor": FCMarkArea},
"eraser": {"button": self.app.ui.aperture_eraser_btn,
"constructor": FCEraser},
"constructor": FCEraser},
"copy": {"button": self.app.ui.aperture_copy_btn,
"constructor": FCApertureCopy},
"transform": {"button": self.app.ui.grb_transform_btn,
@ -3245,7 +3244,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.storage_dict[ap_id]['width'] = dims[0]
self.storage_dict[ap_id]['height'] = dims[1]
size_val = math.sqrt((dims[0] ** 2) + (dims[1] ** 2))
size_val = np.sqrt((dims[0] ** 2) + (dims[1] ** 2))
self.apsize_entry.set_value(size_val)
except Exception as e:
@ -3613,7 +3612,6 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.ui.grb_draw_eraser.triggered.connect(self.on_eraser)
self.app.ui.grb_draw_transformations.triggered.connect(self.on_transform)
def disconnect_canvas_event_handlers(self):
# we restore the key and mouse control to FlatCAMApp method
@ -3803,7 +3801,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
# we subtract the big "negative" (clear) geometry from each solid polygon but only the part of clear geometry
# that fits inside the solid. otherwise we may loose the solid
for apid in self.gerber_obj.apertures:
temp_solid_geometry= []
temp_solid_geometry = []
if 'geometry' in self.gerber_obj.apertures[apid]:
# for elem in self.gerber_obj.apertures[apid]['geometry']:
# if 'solid' in elem:
@ -6032,10 +6030,10 @@ class TransformEditorTool(FlatCAMTool):
def get_shapely_list_bounds(geometry_list):
xmin = Inf
ymin = Inf
xmax = -Inf
ymax = -Inf
xmin = np.Inf
ymin = np.Inf
xmax = -np.Inf
ymax = -np.Inf
for gs in geometry_list:
try:

View File

@ -14,6 +14,8 @@
from flatcamGUI.PreferencesUI import *
from matplotlib.backend_bases import KeyEvent as mpl_key_event
from copy import deepcopy
from datetime import datetime
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -3696,7 +3698,7 @@ class FlatCAMSystemTray(QtWidgets.QSystemTrayIcon):
class BookmarkManager(QtWidgets.QWidget):
mark_rows = pyqtSignal()
mark_rows = QtCore.pyqtSignal()
def __init__(self, app, storage, parent=None):
super(BookmarkManager, self).__init__(parent)

View File

@ -12,18 +12,14 @@
# ##########################################################
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtCore import Qt, pyqtSlot
from PyQt5.QtWidgets import QTextEdit, QCompleter, QAction
from PyQt5.QtGui import QColor, QKeySequence, QPalette, QTextCursor
from PyQt5.QtGui import QKeySequence, QTextCursor
from copy import copy
import re
import logging
import html
import webbrowser
from copy import deepcopy
import sys
from datetime import datetime
log = logging.getLogger('base')
@ -513,7 +509,7 @@ class EvalEntry2(QtWidgets.QLineEdit):
class FCSpinner(QtWidgets.QSpinBox):
returnPressed = pyqtSignal()
returnPressed = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(FCSpinner, self).__init__(parent)
@ -580,7 +576,7 @@ class FCSpinner(QtWidgets.QSpinBox):
class FCDoubleSpinner(QtWidgets.QDoubleSpinBox):
returnPressed = pyqtSignal()
returnPressed = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(FCDoubleSpinner, self).__init__(parent)
@ -869,16 +865,16 @@ class FCTextAreaExtended(QtWidgets.QTextEdit):
if self.textCursor().block().text().startswith(" "):
# skip the white space
self.moveCursor(QtGui.QTextCursor.NextWord)
self.moveCursor(QtGui.QTextCursor.NextCharacter,QtGui.QTextCursor.KeepAnchor)
self.moveCursor(QtGui.QTextCursor.NextCharacter, QtGui.QTextCursor.KeepAnchor)
character = self.textCursor().selectedText()
if character == "#":
# delete #
self.textCursor().deletePreviousChar()
# delete white space
self.moveCursor(QtGui.QTextCursor.NextWord,QtGui.QTextCursor.KeepAnchor)
self.moveCursor(QtGui.QTextCursor.NextWord, QtGui.QTextCursor.KeepAnchor)
self.textCursor().removeSelectedText()
else:
self.moveCursor(QtGui.QTextCursor.PreviousCharacter,QtGui.QTextCursor.KeepAnchor)
self.moveCursor(QtGui.QTextCursor.PreviousCharacter, QtGui.QTextCursor.KeepAnchor)
self.textCursor().insertText("# ")
cursor = QtGui.QTextCursor(self.textCursor())
cursor.setPosition(pos)
@ -1261,7 +1257,6 @@ class FCDetachableTab(QtWidgets.QTabWidget):
attached = True
break
# If the tab is not attached, close it's window and
# remove the reference to it
if not attached:
@ -1342,8 +1337,8 @@ class FCDetachableTab(QtWidgets.QTabWidget):
can be re-attached by closing the dialog or by dragging the window into the tab bar
"""
onCloseSignal = pyqtSignal(QtWidgets.QWidget, str, QtGui.QIcon)
onDropSignal = pyqtSignal(str, QtCore.QPoint)
onCloseSignal = QtCore.pyqtSignal(QtWidgets.QWidget, str, QtGui.QIcon)
onDropSignal = QtCore.pyqtSignal(str, QtCore.QPoint)
def __init__(self, name, contentWidget):
QtWidgets.QMainWindow.__init__(self, None)
@ -1384,7 +1379,7 @@ class FCDetachableTab(QtWidgets.QTabWidget):
An event filter class to detect a QMainWindow drop event
"""
onDropSignal = pyqtSignal(QtCore.QPoint)
onDropSignal = QtCore.pyqtSignal(QtCore.QPoint)
def __init__(self):
QtCore.QObject.__init__(self)
@ -1416,11 +1411,11 @@ class FCDetachableTab(QtWidgets.QTabWidget):
return False
class FCTabBar(QtWidgets.QTabBar):
onDetachTabSignal = pyqtSignal(int, QtCore.QPoint)
onMoveTabSignal = pyqtSignal(int, int)
detachedTabDropSignal = pyqtSignal(str, int, QtCore.QPoint)
onDetachTabSignal = QtCore.pyqtSignal(int, QtCore.QPoint)
onMoveTabSignal = QtCore.pyqtSignal(int, int)
detachedTabDropSignal = QtCore.pyqtSignal(str, int, QtCore.QPoint)
right_click = pyqtSignal(int)
right_click = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
QtWidgets.QTabBar.__init__(self, parent)
@ -1498,7 +1493,7 @@ class FCDetachableTab(QtWidgets.QTabWidget):
self.dragInitiated = True
# If the current movement is a drag initiated by the left button
if (((event.buttons() & QtCore.Qt.LeftButton)) and self.dragInitiated and self.can_be_dragged):
if ((event.buttons() & QtCore.Qt.LeftButton)) and self.dragInitiated and self.can_be_dragged:
# Stop the move event
finishMoveEvent = QtGui.QMouseEvent(
@ -1591,7 +1586,7 @@ class FCDetachableTab(QtWidgets.QTabWidget):
class FCDetachableTab2(FCDetachableTab):
tab_closed_signal = pyqtSignal(object)
tab_closed_signal = QtCore.pyqtSignal(object)
def __init__(self, protect=None, protect_by_name=None, parent=None):
super(FCDetachableTab2, self).__init__(protect=protect, protect_by_name=protect_by_name, parent=parent)
@ -1729,7 +1724,7 @@ class OptionalHideInputSection:
class FCTable(QtWidgets.QTableWidget):
drag_drop_sig = pyqtSignal()
drag_drop_sig = QtCore.pyqtSignal()
def __init__(self, drag_drop=False, protected_rows=None, parent=None):
super(FCTable, self).__init__(parent)
@ -2024,8 +2019,8 @@ class _ExpandableTextEdit(QTextEdit):
Class implements edit line, which expands themselves automatically
"""
historyNext = pyqtSignal()
historyPrev = pyqtSignal()
historyNext = QtCore.pyqtSignal()
historyPrev = QtCore.pyqtSignal()
def __init__(self, termwidget, *args):
QTextEdit.__init__(self, *args)
@ -2148,7 +2143,7 @@ class _ExpandableTextEdit(QTextEdit):
class MyCompleter(QCompleter):
insertText = pyqtSignal(str)
insertText = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
QCompleter.__init__(self)
@ -2166,4 +2161,3 @@ class MyCompleter(QCompleter):
def getSelected(self):
return self.lastSelected

View File

@ -11,8 +11,6 @@
# Date: 3/10/2019 #
# ##########################################################
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt
from flatcamGUI.GUIElements import *
import sys

View File

@ -7,7 +7,7 @@
# Modified by Marius Stanciu 09/21/2019 #
############################################################
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5 import QtCore
from PyQt5.QtCore import pyqtSignal
# needed for legacy mode

View File

@ -8,11 +8,8 @@
from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import *
import platform
import webbrowser
import sys
from flatcamEditors.FlatCAMGeoEditor import FCShapeTool
import gettext
import FlatCAMTranslation as fcTranslate
import builtins

View File

@ -6,12 +6,15 @@
# MIT Licence #
# ##########################################################
import numpy as np
from PyQt5.QtGui import QPalette
from PyQt5.QtCore import QSettings
import numpy as np
import vispy.scene as scene
from vispy.scene.cameras.base_camera import BaseCamera
from vispy.color import Color
import time
white = Color("#ffffff")

View File

@ -9,7 +9,6 @@
# ##########################################################
import math
import sys
def norm(v):

View File

@ -1,4 +1,14 @@
from camlib import *
from camlib import Geometry
import FlatCAMApp
import shapely.affinity as affinity
from shapely.geometry import Point, LineString
import numpy as np
import re
import logging
import traceback
import FlatCAMTranslation as fcTranslate
@ -8,6 +18,8 @@ import builtins
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class Excellon(Geometry):
"""
@ -1017,10 +1029,10 @@ class Excellon(Geometry):
def bounds_rec(obj):
if type(obj) is list:
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
minx = np.Inf
miny = np.Inf
maxx = -np.Inf
maxy = -np.Inf
for k in obj:
if type(k) is dict:

View File

@ -11,12 +11,11 @@
# ######################################################################
import re, os, sys, glob
import itertools
from shapely.geometry import Point, Polygon
from shapely.affinity import translate, scale, rotate
from shapely.affinity import translate, scale
from shapely.geometry import MultiPolygon
from shapely.geometry.base import BaseGeometry
import freetype as ft
from fontTools import ttLib

View File

@ -1,4 +1,19 @@
from camlib import *
from camlib import Geometry, arc, arc_angle, ApertureMacro
import FlatCAMApp
import numpy as np
import re
import logging
import traceback
from copy import deepcopy
import sys
from shapely.ops import cascaded_union
from shapely.geometry import Polygon, MultiPolygon, LineString, Point
import shapely.affinity as affinity
from shapely.geometry import box as shply_box
import FlatCAMTranslation as fcTranslate
import gettext
@ -7,6 +22,8 @@ import builtins
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class Gerber(Geometry):
"""
@ -253,14 +270,14 @@ class Gerber(Geometry):
self.apertures[apid] = {"type": "R",
"width": float(paramList[0]),
"height": float(paramList[1]),
"size": sqrt(float(paramList[0]) ** 2 + float(paramList[1]) ** 2)} # Hack
"size": np.sqrt(float(paramList[0]) ** 2 + float(paramList[1]) ** 2)} # Hack
return apid
if apertureType == "O": # Obround
self.apertures[apid] = {"type": "O",
"width": float(paramList[0]),
"height": float(paramList[1]),
"size": sqrt(float(paramList[0]) ** 2 + float(paramList[1]) ** 2)} # Hack
"size": np.sqrt(float(paramList[0]) ** 2 + float(paramList[1]) ** 2)} # Hack
return apid
if apertureType == "P": # Polygon (regular)
@ -1231,15 +1248,15 @@ class Gerber(Geometry):
if quadrant_mode == 'MULTI':
center = [i + current_x, j + current_y]
radius = sqrt(i ** 2 + j ** 2)
start = arctan2(-j, -i) # Start angle
radius = np.sqrt(i ** 2 + j ** 2)
start = np.arctan2(-j, -i) # Start angle
# Numerical errors might prevent start == stop therefore
# we check ahead of time. This should result in a
# 360 degree arc.
if current_x == circular_x and current_y == circular_y:
stop = start
else:
stop = arctan2(-center[1] + circular_y, -center[0] + circular_x) # Stop angle
stop = np.arctan2(-center[1] + circular_y, -center[0] + circular_x) # Stop angle
this_arc = arc(center, radius, start, stop,
arcdir[current_interpolation_mode],
@ -1273,10 +1290,10 @@ class Gerber(Geometry):
valid = False
log.debug("I: %f J: %f" % (i, j))
for center in center_candidates:
radius = sqrt(i ** 2 + j ** 2)
radius = np.sqrt(i ** 2 + j ** 2)
# Make sure radius to start is the same as radius to end.
radius2 = sqrt((center[0] - circular_x) ** 2 + (center[1] - circular_y) ** 2)
radius2 = np.sqrt((center[0] - circular_x) ** 2 + (center[1] - circular_y) ** 2)
if radius2 < radius * 0.95 or radius2 > radius * 1.05:
continue # Not a valid center.
@ -1284,16 +1301,16 @@ class Gerber(Geometry):
i = center[0] - current_x
j = center[1] - current_y
start = arctan2(-j, -i) # Start angle
stop = arctan2(-center[1] + circular_y, -center[0] + circular_x) # Stop angle
start = np.arctan2(-j, -i) # Start angle
stop = np.arctan2(-center[1] + circular_y, -center[0] + circular_x) # Stop angle
angle = abs(arc_angle(start, stop, arcdir[current_interpolation_mode]))
log.debug("ARC START: %f, %f CENTER: %f, %f STOP: %f, %f" %
(current_x, current_y, center[0], center[1], circular_x, circular_y))
log.debug("START Ang: %f, STOP Ang: %f, DIR: %s, ABS: %.12f <= %.12f: %s" %
(start * 180 / pi, stop * 180 / pi, arcdir[current_interpolation_mode],
angle * 180 / pi, pi / 2 * 180 / pi, angle <= (pi + 1e-6) / 2))
(start * 180 / np.pi, stop * 180 / np.pi, arcdir[current_interpolation_mode],
angle * 180 / np.pi, np.pi / 2 * 180 / np.pi, angle <= (np.pi + 1e-6) / 2))
if angle <= (pi + 1e-6) / 2:
if angle <= (np.pi + 1e-6) / 2:
log.debug("########## ACCEPTING ARC ############")
this_arc = arc(center, radius, start, stop,
arcdir[current_interpolation_mode],
@ -1478,8 +1495,8 @@ class Gerber(Geometry):
n_vertices = aperture['nVertices']
points = []
for i in range(0, n_vertices):
x = loc[0] + 0.5 * diam * (cos(2 * pi * i / n_vertices))
y = loc[1] + 0.5 * diam * (sin(2 * pi * i / n_vertices))
x = loc[0] + 0.5 * diam * (np.cos(2 * np.pi * i / n_vertices))
y = loc[1] + 0.5 * diam * (np.sin(2 * np.pi * i / n_vertices))
points.append((x, y))
ply = Polygon(points)
if 'rotation' in aperture:
@ -1553,10 +1570,10 @@ class Gerber(Geometry):
def bounds_rec(obj):
if type(obj) is list and type(obj) is not MultiPolygon:
minx = Inf
miny = Inf
maxx = -Inf
maxy = -Inf
minx = np.Inf
miny = np.Inf
maxx = -np.Inf
maxy = -np.Inf
for k in obj:
if type(k) is dict:

View File

@ -5,8 +5,9 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, FCEntry
import math
import gettext
@ -321,11 +322,11 @@ class ToolCalculator(FlatCAMTool):
def on_calculate_inch_units(self):
mm_val = float(self.mm_entry.get_value())
self.inch_entry.set_value('%.*f' % (self.decimals,(mm_val / 25.4)))
self.inch_entry.set_value('%.*f' % (self.decimals, (mm_val / 25.4)))
def on_calculate_mm_units(self):
inch_val = float(self.inch_entry.get_value())
self.mm_entry.set_value('%.*f' % (self.decimals,(inch_val * 25.4)))
self.mm_entry.set_value('%.*f' % (self.decimals, (inch_val * 25.4)))
def on_calculate_eplate(self):
length = float(self.pcblength_entry.get_value())

View File

@ -5,12 +5,21 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets, QtGui, QtCore
from FlatCAMTool import FlatCAMTool
from ObjectCollection import *
from FlatCAMApp import *
from shapely.geometry import box
from shapely.ops import cascaded_union, unary_union
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, RadioSet, FCComboBox
from FlatCAMObj import FlatCAMGerber
from shapely.geometry import box, MultiPolygon, Polygon, LineString, LinearRing
from shapely.ops import cascaded_union, unary_union
import shapely.affinity as affinity
from matplotlib.backend_bases import KeyEvent as mpl_key_event
from numpy import Inf
from copy import deepcopy
import math
import logging
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -19,6 +28,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class CutOut(FlatCAMTool):

View File

@ -1,9 +1,14 @@
from PyQt5 import QtWidgets, QtCore
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, EvalEntry
from FlatCAMObj import FlatCAMGerber, FlatCAMExcellon, FlatCAMGeometry
from shapely.geometry import Point
from shapely import affinity
from PyQt5 import QtCore
import logging
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -12,6 +17,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class DblSidedTool(FlatCAMTool):

View File

@ -5,12 +5,15 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets, QtCore
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
from flatcamGUI.VisPyVisuals import *
from flatcamGUI.GUIElements import FCEntry
from math import sqrt
import copy
import math
import logging
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -19,6 +22,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class Distance(FlatCAMTool):
@ -335,7 +340,7 @@ class Distance(FlatCAMTool):
elif len(self.points) == 2:
dx = self.points[1][0] - self.points[0][0]
dy = self.points[1][1] - self.points[0][1]
d = sqrt(dx ** 2 + dy ** 2)
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(_("MEASURING: Result D(x) = {d_x} | D(y) = {d_y} | Distance = {d_z}").format(

View File

@ -5,14 +5,16 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets, QtCore
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
from flatcamGUI.VisPyVisuals import *
from flatcamGUI.GUIElements import FCEntry
from shapely.ops import nearest_points
from shapely.geometry import Point
from math import sqrt
import math
import logging
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -21,6 +23,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class DistanceMin(FlatCAMTool):
@ -260,7 +264,7 @@ class DistanceMin(FlatCAMTool):
except Exception as e:
pass
d = sqrt(dx ** 2 + dy ** 2)
d = math.sqrt(dx ** 2 + dy ** 2)
self.total_distance_entry.set_value('%.*f' % (self.decimals, abs(d)))
self.h_point = (min(first_pos.x, last_pos.x) + (abs(dx) / 2), min(first_pos.y, last_pos.y) + (abs(dy) / 2))

View File

@ -5,14 +5,15 @@
# MIT Licence #
# ##########################################################
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, \
OptionalHideInputSection, OptionalInputSection
from PyQt5 import QtGui, QtCore, QtWidgets
from FlatCAMTool import FlatCAMTool
from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, \
OptionalHideInputSection, OptionalInputSection
from copy import deepcopy
import logging
from shapely.geometry import Polygon, MultiPolygon, Point
import gettext
import FlatCAMTranslation as fcTranslate
@ -22,6 +23,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class Film(FlatCAMTool):
@ -166,7 +169,7 @@ class Film(FlatCAMTool):
self.ois_scale = OptionalInputSection(self.film_scale_cb, [self.film_scalex_label, self.film_scalex_entry,
self.film_scaley_label, self.film_scaley_entry])
# Skew Geometry
self.film_skew_cb =FCCheckBox('%s' % _("Skew Film geometry"))
self.film_skew_cb = FCCheckBox('%s' % _("Skew Film geometry"))
self.film_skew_cb.setToolTip(
_("Positive values will skew to the right\n"
"while negative values will skew to the left.")
@ -202,9 +205,9 @@ class Film(FlatCAMTool):
"It can be one of the four points of the geometry bounding box.")
)
self.film_skew_reference = RadioSet([{'label': _('Bottom Left'), 'value': 'bottomleft'},
{'label': _('Top Left'), 'value': 'topleft'},
{'label': _('Bottom Right'), 'value': 'bottomright'},
{'label': _('Top right'), 'value': 'topright'}],
{'label': _('Top Left'), 'value': 'topleft'},
{'label': _('Bottom Right'), 'value': 'bottomright'},
{'label': _('Top right'), 'value': 'topright'}],
orientation='vertical',
stretch=False)

View File

@ -5,11 +5,11 @@
# MIT Licence #
# ##########################################################
from FlatCAMTool import FlatCAMTool
from flatcamGUI.GUIElements import RadioSet, FCComboBox, FCSpinner
from PyQt5 import QtGui, QtWidgets
from FlatCAMTool import FlatCAMTool
from flatcamGUI.GUIElements import RadioSet, FCComboBox, FCSpinner
import gettext
import FlatCAMTranslation as fcTranslate
import builtins

View File

@ -5,12 +5,13 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets, QtCore
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
from flatcamGUI.VisPyVisuals import *
from FlatCAMObj import FlatCAMGerber
from copy import copy
import logging
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -19,11 +20,13 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class ToolMove(FlatCAMTool):
toolName = _("Move")
replot_signal = pyqtSignal(list)
replot_signal = QtCore.pyqtSignal(list)
def __init__(self, app):
FlatCAMTool.__init__(self, app)

View File

@ -5,12 +5,23 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets, QtCore, QtGui
from FlatCAMTool import FlatCAMTool
from copy import copy, deepcopy
from ObjectCollection import *
import time
from shapely.geometry import base
from flatcamGUI.GUIElements import FCCheckBox, FCDoubleSpinner, RadioSet, FCTable, FCInputDialog
from flatcamParsers.ParseGerber import Gerber
from FlatCAMObj import FlatCAMGeometry, FlatCAMGerber
import FlatCAMApp
from copy import deepcopy
import numpy as np
import math
from shapely.geometry import base
from shapely.ops import cascaded_union
from shapely.geometry import MultiPolygon, Polygon, MultiLineString, LineString, LinearRing
import logging
import traceback
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -19,6 +30,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class NonCopperClear(FlatCAMTool, Gerber):
@ -473,7 +486,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
"Add", self.on_add_tool_by_key, icon=QtGui.QIcon("share/plus16.png"))
self.tools_table.addContextMenu(
"Delete", lambda:
self.on_tool_delete(rows_to_delete=None, all=None), icon=QtGui.QIcon("share/delete32.png"))
self.on_tool_delete(rows_to_delete=None, all_tools=None), icon=QtGui.QIcon("share/delete32.png"))
# #############################################################################
# ########################## VARIABLES ########################################
@ -1040,12 +1053,19 @@ class NonCopperClear(FlatCAMTool, Gerber):
"New diameter value is already in the Tool Table."))
self.build_ui()
def on_tool_delete(self, rows_to_delete=None, all=None):
def on_tool_delete(self, rows_to_delete=None, all_tools=None):
"""
Will delete a tool in the tool table
:param rows_to_delete: which rows to delete; can be a list
:param all_tools: delete all tools in the tool table
:return:
"""
self.ui_disconnect()
deleted_tools_list = []
if all:
if all_tools:
self.paint_tools.clear()
self.build_ui()
return

View File

@ -5,13 +5,19 @@
# MIT Licence #
# ##########################################################
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
from shapely.geometry import Point
from shapely import affinity
from shapely.ops import nearest_points
from PyQt5 import QtCore
from PyQt5 import QtWidgets, QtCore, QtGui
from FlatCAMTool import FlatCAMTool
from flatcamGUI.GUIElements import OptionalHideInputSection, FCTextArea, FCEntry, FCSpinner, FCCheckBox
from FlatCAMObj import FlatCAMGerber
import FlatCAMApp
from shapely.geometry import MultiPolygon
from shapely.ops import nearest_points
import numpy as np
import logging
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -20,13 +26,15 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class ToolOptimal(FlatCAMTool):
toolName = _("Optimal Tool")
update_text = pyqtSignal(list)
update_sec_distances = pyqtSignal(dict)
update_text = QtCore.pyqtSignal(list)
update_sec_distances = QtCore.pyqtSignal(dict)
def __init__(self, app):
FlatCAMTool.__init__(self, app)

View File

@ -5,19 +5,22 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets, QtCore
from FlatCAMTool import FlatCAMTool
from shapely.geometry import Point, Polygon, LineString
from shapely.ops import cascaded_union, unary_union
import FlatCAMApp
from FlatCAMObj import *
from shapely.geometry import Point, Polygon, LineString, MultiPolygon
from shapely.ops import unary_union
import math
from copy import copy, deepcopy
import numpy as np
import zlib
import re
import time
import logging
import traceback
import gettext
import FlatCAMTranslation as fcTranslate
@ -27,6 +30,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class ToolPDF(FlatCAMTool):
"""

View File

@ -5,10 +5,25 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import Qt
from FlatCAMTool import FlatCAMTool
from copy import copy, deepcopy
from ObjectCollection import *
from shapely.geometry import base
from copy import deepcopy
# from ObjectCollection import *
from flatcamParsers.ParseGerber import Gerber
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry
from camlib import Geometry
from flatcamGUI.GUIElements import FCTable, FCDoubleSpinner, FCCheckBox, FCInputDialog, RadioSet
import FlatCAMApp
from shapely.geometry import base, Polygon, MultiPolygon, LinearRing
from shapely.ops import cascaded_union
import numpy as np
from numpy import Inf
import traceback
import logging
import gettext
import FlatCAMTranslation as fcTranslate
@ -18,6 +33,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class ToolPaint(FlatCAMTool, Gerber):
@ -374,6 +391,7 @@ class ToolPaint(FlatCAMTool, Gerber):
self.mm = None
self.mp = None
self.mr = None
self.sel_rect = []
@ -641,10 +659,10 @@ class ToolPaint(FlatCAMTool, Gerber):
for tooluid_key, tooluid_value in self.paint_tools.items():
if float('%.*f' % (self.decimals, tooluid_value['tooldia'])) == tool_sorted:
tool_id += 1
id = QtWidgets.QTableWidgetItem('%d' % int(tool_id))
id.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
id_item = QtWidgets.QTableWidgetItem('%d' % int(tool_id))
id_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
row_no = tool_id - 1
self.tools_table.setItem(row_no, 0, id) # Tool name/id
self.tools_table.setItem(row_no, 0, id_item) # Tool name/id
# Make sure that the drill diameter when in MM is with no more than 2 decimals
# There are no drill bits in MM with more than 2 decimals diameter
@ -2213,7 +2231,7 @@ class ToolPaint(FlatCAMTool, Gerber):
log.debug("Could not Paint the polygons. %s" % str(e))
self.app.inform.emit('[ERROR] %s\n%s' %
(_("Could not do Paint All. Try a different combination of parameters. "
"Or a different Method of paint"), str(e)))
"Or a different Method of paint"), str(e)))
return
pol_nr += 1
@ -2373,7 +2391,7 @@ class ToolPaint(FlatCAMTool, Gerber):
log.debug("Could not Paint the polygons. %s" % str(e))
self.app.inform.emit('[ERROR] %s\n%s' %
(_("Could not do Paint All. Try a different combination of parameters. "
"Or a different Method of paint"), str(e)))
"Or a different Method of paint"), str(e)))
return
pol_nr += 1

View File

@ -5,19 +5,29 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets, QtGui, QtCore
from FlatCAMTool import FlatCAMTool
from copy import copy, deepcopy
from ObjectCollection import *
import time
from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet, FCCheckBox, OptionalInputSection
from FlatCAMObj import FlatCAMGeometry, FlatCAMGerber, FlatCAMExcellon
import FlatCAMApp
from copy import deepcopy
# from ObjectCollection import *
import numpy as np
import shapely.affinity as affinity
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
import logging
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class Panelize(FlatCAMTool):
@ -367,15 +377,13 @@ class Panelize(FlatCAMTool):
# Get source object.
try:
obj = self.app.collection.get_by_name(str(name))
panel_obj = self.app.collection.get_by_name(str(name))
except Exception as e:
log.debug("Panelize.on_panelize() --> %s" % str(e))
self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
(_("Could not retrieve object"), name))
return "Could not retrieve object: %s" % name
panel_obj = obj
if panel_obj is None:
self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
(_("Object not found"), panel_obj))
@ -443,6 +451,18 @@ class Panelize(FlatCAMTool):
rows -= 1
panel_lengthy = ((ymax - ymin) * rows) + (spacing_rows * (rows - 1))
if isinstance(panel_obj, FlatCAMExcellon) or isinstance(panel_obj, FlatCAMGeometry):
# make a copy of the panelized Excellon or Geometry tools
copied_tools = dict()
for tt, tt_val in list(panel_obj.tools.items()):
copied_tools[tt] = deepcopy(tt_val)
if isinstance(panel_obj, FlatCAMGerber):
# make a copy of the panelized Gerber apertures
copied_apertures = dict()
for tt, tt_val in list(panel_obj.apertures.items()):
copied_apertures[tt] = deepcopy(tt_val)
def panelize_2():
if panel_obj is not None:
self.app.inform.emit(_("Generating panel ... "))
@ -452,7 +472,7 @@ class Panelize(FlatCAMTool):
def job_init_excellon(obj_fin, app_obj):
currenty = 0.0
self.app.progress.emit(10)
obj_fin.tools = panel_obj.tools.copy()
obj_fin.tools = copied_tools
obj_fin.drills = []
obj_fin.slots = []
obj_fin.solid_geometry = []
@ -472,7 +492,6 @@ class Panelize(FlatCAMTool):
currentx = 0.0
for col in range(columns):
element += 1
disp_number = 0
old_disp_number = 0
if panel_obj.drills:
@ -493,7 +512,7 @@ class Panelize(FlatCAMTool):
drill_nr += 1
disp_number = int(np.interp(drill_nr, [0, geo_len_drills], [0, 100]))
if disp_number > old_disp_number and disp_number <= 100:
if old_disp_number < disp_number <= 100:
self.app.proc_container.update_view_text(' %s: %d D:%d%%' %
(_("Copy"),
int(element),
@ -520,7 +539,7 @@ class Panelize(FlatCAMTool):
slot_nr += 1
disp_number = int(np.interp(slot_nr, [0, geo_len_slots], [0, 100]))
if disp_number > old_disp_number and disp_number <= 100:
if old_disp_number < disp_number <= 100:
self.app.proc_container.update_view_text(' %s: %d S:%d%%' %
(_("Copy"),
int(element),
@ -557,12 +576,12 @@ class Panelize(FlatCAMTool):
# create the initial structure on which to create the panel
if isinstance(panel_obj, FlatCAMGeometry):
obj_fin.multigeo = panel_obj.multigeo
obj_fin.tools = deepcopy(panel_obj.tools)
obj_fin.tools = copied_tools
if panel_obj.multigeo is True:
for tool in panel_obj.tools:
obj_fin.tools[tool]['solid_geometry'][:] = []
elif isinstance(panel_obj, FlatCAMGerber):
obj_fin.apertures = deepcopy(panel_obj.apertures)
obj_fin.apertures = copied_apertures
for ap in obj_fin.apertures:
obj_fin.apertures[ap]['geometry'] = list()
@ -594,7 +613,6 @@ class Panelize(FlatCAMTool):
for col in range(columns):
element += 1
disp_number = 0
old_disp_number = 0
if isinstance(panel_obj, FlatCAMGeometry):

View File

@ -5,11 +5,11 @@
# MIT Licence #
# ##########################################################
from FlatCAMTool import FlatCAMTool
from PyQt5 import QtWidgets, QtCore
from FlatCAMTool import FlatCAMTool
from flatcamGUI.GUIElements import RadioSet, FCSpinner, FCButton, FCTable
from flatcamGUI.GUIElements import RadioSet, FCComboBox, FCSpinner, FCButton, FCTable
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtCore import pyqtSignal
import re
import os
from datetime import datetime
@ -26,7 +26,7 @@ if '_' not in builtins.__dict__:
class PcbWizard(FlatCAMTool):
file_loaded = pyqtSignal(str, str)
file_loaded = QtCore.pyqtSignal(str, str)
toolName = _("PcbWizard Import Tool")

View File

@ -6,10 +6,14 @@
# ##########################################################
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
from FlatCAMObj import FlatCAMCNCjob
from shapely.geometry import MultiPolygon, Polygon
from shapely.ops import cascaded_union
from copy import deepcopy
import logging
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -18,11 +22,13 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class Properties(FlatCAMTool):
toolName = _("Properties")
calculations_finished = pyqtSignal(float, float, float, float, object)
calculations_finished = QtCore.pyqtSignal(float, float, float, float, object)
def __init__(self, app):
FlatCAMTool.__init__(self, app)
@ -150,18 +156,18 @@ class Properties(FlatCAMTool):
self.addChild(obj_name, [obj.options['name']])
def job_thread(obj):
def job_thread(obj_prop):
proc = self.app.proc_container.new(_("Calculating dimensions ... Please wait."))
length = 0.0
width = 0.0
area = 0.0
geo = obj.solid_geometry
geo = obj_prop.solid_geometry
if geo:
# calculate physical dimensions
try:
xmin, ymin, xmax, ymax = obj.bounds()
xmin, ymin, xmax, ymax = obj_prop.bounds()
length = abs(xmax - xmin)
width = abs(ymax - ymin)
@ -179,9 +185,9 @@ class Properties(FlatCAMTool):
xmax = []
ymax = []
for tool in obj.tools:
for tool_k in obj_prop.tools:
try:
x0, y0, x1, y1 = cascaded_union(obj.tools[tool]['solid_geometry']).bounds
x0, y0, x1, y1 = cascaded_union(obj_prop.tools[tool_k]['solid_geometry']).bounds
xmin.append(x0)
ymin.append(y0)
xmax.append(x1)
@ -207,25 +213,25 @@ class Properties(FlatCAMTool):
log.debug("Properties.addItems() --> %s" % str(e))
area_chull = 0.0
if not isinstance(obj, FlatCAMCNCjob):
if not isinstance(obj_prop, FlatCAMCNCjob):
# calculate and add convex hull area
if geo:
if isinstance(geo, MultiPolygon):
env_obj = geo.convex_hull
elif (isinstance(geo, MultiPolygon) and len(geo) == 1) or \
(isinstance(geo, list) and len(geo) == 1) and isinstance(geo[0], Polygon):
env_obj = cascaded_union(obj.solid_geometry)
env_obj = cascaded_union(obj_prop.solid_geometry)
env_obj = env_obj.convex_hull
else:
env_obj = cascaded_union(obj.solid_geometry)
env_obj = cascaded_union(obj_prop.solid_geometry)
env_obj = env_obj.convex_hull
area_chull = env_obj.area
else:
try:
area_chull = []
for tool in obj.tools:
area_el = cascaded_union(obj.tools[tool]['solid_geometry']).convex_hull
for tool_k in obj_prop.tools:
area_el = cascaded_union(obj_prop.tools[tool_k]['solid_geometry']).convex_hull
area_chull.append(area_el.area)
area_chull = max(area_chull)
except Exception as e:

View File

@ -5,15 +5,18 @@
# MIT Licence #
# ##########################################################
from FlatCAMTool import FlatCAMTool
from copy import copy, deepcopy
from ObjectCollection import *
import time
from FlatCAMPool import *
from os import getpid
from shapely.ops import nearest_points
from shapely.geometry.base import BaseGeometry
from PyQt5 import QtWidgets
from FlatCAMTool import FlatCAMTool
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, OptionalInputSection
from copy import deepcopy
from FlatCAMPool import *
# from os import getpid
from shapely.ops import nearest_points
from shapely.geometry import MultiPolygon, Polygon
import logging
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -22,12 +25,14 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class RulesCheck(FlatCAMTool):
toolName = _("Check Rules")
tool_finished = pyqtSignal(list)
tool_finished = QtCore.pyqtSignal(list)
def __init__(self, app):
super(RulesCheck, self).__init__(self)

View File

@ -6,7 +6,7 @@
# MIT Licence #
# ##########################################################
# from PyQt5.QtCore import pyqtSignal
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor
from PyQt5.QtWidgets import QVBoxLayout, QWidget

View File

@ -5,12 +5,18 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets, QtCore
from FlatCAMTool import FlatCAMTool
# from copy import copy, deepcopy
from ObjectCollection import *
import time
from flatcamGUI.GUIElements import FCCheckBox, FCButton
from shapely.geometry import Polygon, MultiPolygon, MultiLineString, LineString
from shapely.ops import cascaded_union
import traceback
from copy import deepcopy
import time
import logging
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
@ -19,6 +25,8 @@ fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class ToolSub(FlatCAMTool):

View File

@ -5,8 +5,10 @@
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets
from FlatCAMTool import FlatCAMTool
from FlatCAMObj import *
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCButton, OptionalInputSection, EvalEntry2
from FlatCAMObj import FlatCAMCNCjob
import gettext
import FlatCAMTranslation as fcTranslate
@ -271,7 +273,7 @@ class ToolTransform(FlatCAMTool):
_("Flip the selected object(s) over the X axis.")
)
hlay0= QtWidgets.QHBoxLayout()
hlay0 = QtWidgets.QHBoxLayout()
self.transform_lay.addLayout(hlay0)
hlay0.addWidget(self.flipx_button)
@ -312,7 +314,7 @@ class ToolTransform(FlatCAMTool):
self.ois_flip = OptionalInputSection(self.flip_ref_cb, [self.flip_ref_entry, self.flip_ref_button], logic=True)
hlay1= QtWidgets.QHBoxLayout()
hlay1 = QtWidgets.QHBoxLayout()
self.transform_lay.addLayout(hlay1)
hlay1.addWidget(self.flip_ref_label)