- fixed the Tcl Command AlignDrill

- fixed the Tcl Command AlignDrillGrid
- fixed the Tcl COmmand Panelize, Excellon panelization section
- Fixed an issue in Tool Calibration export_excellon method call
- PEP8 corrections all over the app
This commit is contained in:
Marius Stanciu
2020-11-02 03:32:00 +02:00
committed by Marius
parent fac4caf961
commit 374c29b4b0
63 changed files with 492 additions and 537 deletions

View File

@@ -9,13 +9,12 @@ from shapely.geometry import LineString
from shapely.affinity import rotate
from ezdxf.math.vector import Vector as ezdxf_vector
from appParsers.ParseFont import *
from appParsers.ParseDXF_Spline import *
import logging
log = logging.getLogger('base2')
from appParsers.ParseFont import *
from appParsers.ParseDXF_Spline import *
def distance(pt1, pt2):
return math.sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2)
@@ -107,12 +106,12 @@ def dxfarc2shapely(arc, n_points=100):
arc_center = ocs.to_wcs(arc.dxf.center)
start_angle = arc.dxf.start_angle + 180
end_angle = arc.dxf.end_angle + 180
dir = 'CW'
direction = 'CW'
else:
arc_center = arc.dxf.center
start_angle = arc.dxf.start_angle
end_angle = arc.dxf.end_angle
dir = 'CCW'
direction = 'CCW'
center_x = arc_center[0]
center_y = arc_center[1]
@@ -127,7 +126,7 @@ def dxfarc2shapely(arc, n_points=100):
step_angle = float(abs(end_angle - start_angle) / n_points)
while angle <= end_angle:
if dir == 'CCW':
if direction == 'CCW':
x = center_x + radius * math.cos(math.radians(angle))
y = center_y + radius * math.sin(math.radians(angle))
else:
@@ -138,7 +137,7 @@ def dxfarc2shapely(arc, n_points=100):
# in case the number of segments do not cover everything until the end of the arc
if angle != end_angle:
if dir == 'CCW':
if direction == 'CCW':
x = center_x + radius * math.cos(math.radians(end_angle))
y = center_y + radius * math.sin(math.radians(end_angle))
else:
@@ -164,12 +163,12 @@ def dxfellipse2shapely(ellipse, ellipse_segments=100):
center = ocs.to_wcs(ellipse.dxf.center)
start_angle = ocs.to_wcs(ellipse.dxf.start_param)
end_angle = ocs.to_wcs(ellipse.dxf.end_param)
dir = 'CW'
direction = 'CW'
else:
center = ellipse.dxf.center
start_angle = ellipse.dxf.start_param
end_angle = ellipse.dxf.end_param
dir = 'CCW'
direction = 'CCW'
# print("Dir = %s" % dir)
major_axis = ellipse.dxf.major_axis
@@ -189,7 +188,7 @@ def dxfellipse2shapely(ellipse, ellipse_segments=100):
angle = start_angle
for step in range(line_seg + 1):
if dir == 'CW':
if direction == 'CW':
major_dim = normalize_2(major_axis)
minor_dim = normalize_2(Vector([ratio * k for k in major_axis]))
vx = (major_dim[0] + major_dim[1]) * math.cos(angle)
@@ -381,6 +380,7 @@ def get_geo(dxf_object, container):
return geo
def getdxftext(exf_object, object_type, units=None):
pass

View File

@@ -400,7 +400,7 @@ class Vector(list):
# ----------------------------------------------------------------------
def __str__(self):
return "[%s]" % ", ".join([("%15g" % (x)).strip() for x in self])
return "[%s]" % ", ".join([("%15g" % x).strip() for x in self])
# ----------------------------------------------------------------------
def eq(self, v, acc=_accuracy):
@@ -805,7 +805,6 @@ class Vector(list):
#
# #-----------------------------------------------------------------------
# def __call__(self, i, x):
# # FIXME should interpolate to find the interval
# C = self.coefficients(i)
# return ((C[0]*x + C[1])*x + C[2])*x + C[3]
#

View File

@@ -10,13 +10,15 @@
# ## and made it work with Python 3 #
# ######################################################################
import re, os, sys, glob
import re
import os
import sys
import glob
from shapely.geometry import Point, Polygon
from shapely.geometry import Polygon
from shapely.affinity import translate, scale
from shapely.geometry import MultiPolygon
import freetype as ft
from fontTools import ttLib
@@ -32,7 +34,7 @@ if '_' not in builtins.__dict__:
log = logging.getLogger('base2')
class ParseFont():
class ParseFont:
FONT_SPECIFIER_NAME_ID = 4
FONT_SPECIFIER_FAMILY_ID = 1
@@ -69,12 +71,12 @@ class ParseFont():
if os.path.isfile(executable):
data = os.popen(executable).readlines()
match = re.compile('\d+: (.+)')
set = []
set_lst = []
for line in data:
result = match.match(line)
if result:
set.append(result.group(1))
return set
set_lst.append(result.group(1))
return set_lst
else:
directories = [
# what seems to be the standard installation point
@@ -91,7 +93,7 @@ class ParseFont():
dir_set = []
for directory in directories:
directory = directory = os.path.expanduser(os.path.expandvars(directory))
directory = os.path.expanduser(os.path.expandvars(directory))
try:
if os.path.isdir(directory):
for path, children, files in os.walk(directory):
@@ -116,7 +118,7 @@ class ParseFont():
dir_set = []
for directory in directories:
directory = directory = os.path.expanduser(os.path.expandvars(directory))
directory = os.path.expanduser(os.path.expandvars(directory))
try:
if os.path.isdir(directory):
for path, children, files in os.walk(directory):
@@ -144,7 +146,7 @@ class ParseFont():
winreg.HKEY_LOCAL_MACHINE,
keyName
)
except OSError as err:
except OSError:
pass
if not k:
@@ -195,7 +197,7 @@ class ParseFont():
break
return name, family
def __init__(self, app, parent=None):
def __init__(self, app):
super(ParseFont, self).__init__()
self.app = app
@@ -217,7 +219,7 @@ class ParseFont():
if paths is None:
if sys.platform == 'win32':
font_directory = ParseFont.get_win32_font_path()
paths = [font_directory,]
paths = [font_directory, ]
# now get all installed fonts directly...
for f in self.get_win32_fonts(font_directory):
@@ -275,7 +277,7 @@ class ParseFont():
else:
try:
name = name.replace(" Regular", '')
except Exception as e:
except Exception:
pass
self.regular_f.update({name: font})
log.debug("Font parsing is finished.")
@@ -318,7 +320,7 @@ class ParseFont():
if previous > 0 and glyph_index > 0:
delta = face.get_kerning(previous, glyph_index)
pen_x += delta.x
except Exception as e:
except Exception:
pass
face.load_glyph(glyph_index)

View File

@@ -2,16 +2,13 @@ from PyQt5 import QtWidgets
from camlib import Geometry, arc, arc_angle, ApertureMacro, grace
import numpy as np
# import re
# import logging
import traceback
from copy import deepcopy
# import sys
from shapely.ops import unary_union, linemerge
# from shapely.affinity import scale, translate
import shapely.affinity as affinity
from shapely.geometry import box as shply_box
from shapely.geometry import Point
from lxml import etree as ET
import ezdxf
@@ -315,12 +312,12 @@ class Gerber(Geometry):
First is ``G54D11*`` and seconds is ``G36*``.
:param filename: Gerber file to parse.
:type filename: str
:param follow: If true, will not create polygons, just lines
following the gerber path.
:type follow: bool
:return: None
:param filename: Gerber file to parse.
:type filename: str
:param follow: If true, will not create polygons, just lines
following the gerber path.
:type follow: bool
:return: None
"""
with open(filename, 'r') as gfile:
@@ -1837,12 +1834,10 @@ class Gerber(Geometry):
geos_length = 1
if geos_length == 1:
geo_qrcode = []
geo_qrcode.append(Polygon(geos[0].exterior))
geo_qrcode = [Polygon(geos[0].exterior)]
for i_el in geos[0].interiors:
geo_qrcode.append(Polygon(i_el).buffer(0, resolution=res))
for poly in geo_qrcode:
geos.append(poly)
geos = [poly for poly in geo_qrcode]
if type(self.solid_geometry) == list:
self.solid_geometry += geos
@@ -1864,15 +1859,14 @@ class Gerber(Geometry):
self.solid_geometry = [self.solid_geometry]
if '0' not in self.apertures:
self.apertures['0'] = {}
self.apertures['0']['type'] = 'REG'
self.apertures['0']['size'] = 0.0
self.apertures['0']['geometry'] = []
self.apertures['0'] = {
'type': 'REG',
'size': 0.0,
'geometry': []
}
for pol in self.solid_geometry:
new_el = {}
new_el['solid'] = pol
new_el['follow'] = pol.exterior
new_el = {'solid': pol, 'follow': pol.exterior}
self.apertures['0']['geometry'].append(new_el)
def import_dxf_as_gerber(self, filename, units='MM'):
@@ -1914,15 +1908,14 @@ class Gerber(Geometry):
# create the self.apertures data structure
if '0' not in self.apertures:
self.apertures['0'] = {}
self.apertures['0']['type'] = 'REG'
self.apertures['0']['size'] = 0.0
self.apertures['0']['geometry'] = []
self.apertures['0'] = {
'type': 'REG',
'size': 0.0,
'geometry': []
}
for pol in flat_geo:
new_el = {}
new_el['solid'] = pol
new_el['follow'] = pol
new_el = {'solid': pol, 'follow': pol}
self.apertures['0']['geometry'].append(deepcopy(new_el))
def scale(self, xfactor, yfactor=None, point=None):

View File

@@ -82,12 +82,10 @@ class PdfParser(QtCore.QObject):
self.restore_gs_re = re.compile(r'^.*Q.*$')
# graphic stack where we save parameters like transformation, line_width
self.gs = {}
# each element is a list composed of sublist elements
# (each sublist has 2 lists each having 2 elements: first is offset like:
# offset_geo = [off_x, off_y], second element is scale list with 2 elements, like: scale_geo = [sc_x, sc_yy])
self.gs['transform'] = []
self.gs['line_width'] = [] # each element is a float
self.gs = {'transform': [], 'line_width': []}
# conversion factor to INCH
self.point_to_unit_factor = 0.01388888888
@@ -102,15 +100,17 @@ class PdfParser(QtCore.QObject):
# 1 inch = 72 points => 1 point = 1 / 72 = 0.01388888888 inch
self.point_to_unit_factor = 1 / 72
path = {}
path['lines'] = [] # it's a list of lines subpaths
path['bezier'] = [] # it's a list of bezier arcs subpaths
path['rectangle'] = [] # it's a list of rectangle subpaths
path = {
'lines': [], # it's a list of lines subpaths
'bezier': [], # it's a list of bezier arcs subpaths
'rectangle': [] # it's a list of rectangle subpaths
}
subpath = {}
subpath['lines'] = [] # it's a list of points
subpath['bezier'] = [] # it's a list of sublists each like this [start, c1, c2, stop]
subpath['rectangle'] = [] # it's a list of sublists of points
subpath = {
'lines': [], # it's a list of points
'bezier': [], # it's a list of sublists each like this [start, c1, c2, stop]
'rectangle': [] # it's a list of sublists of points
}
# store the start point (when 'm' command is encountered)
current_subpath = None
@@ -141,12 +141,14 @@ class PdfParser(QtCore.QObject):
# store the apertures with clear geometry here
# we are interested only in the circular geometry (drill holes) therefore we target only Bezier subpaths
clear_apertures_dict = {}
# everything will be stored in the '0' aperture since we are dealing with clear polygons not strokes
clear_apertures_dict['0'] = {}
clear_apertures_dict['0']['size'] = 0.0
clear_apertures_dict['0']['type'] = 'C'
clear_apertures_dict['0']['geometry'] = []
clear_apertures_dict = {
'0': {
'size': 0.0,
'type': 'C',
'geometry': []
}
}
# on stroke color change we create a new apertures dictionary and store the old one in a storage from where
# it will be transformed into Gerber object
@@ -527,14 +529,10 @@ class PdfParser(QtCore.QObject):
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['solid'] = poly
new_el['follow'] = poly.exterior
new_el = {'solid': poly, 'follow': poly.exterior}
apertures_dict[copy(found_aperture)]['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['solid'] = pdf_geo
new_el['follow'] = pdf_geo.exterior
new_el = {'solid': pdf_geo, 'follow': pdf_geo.exterior}
apertures_dict[copy(found_aperture)]['geometry'].append(deepcopy(new_el))
else:
if str(aperture) in apertures_dict.keys():
@@ -546,14 +544,10 @@ class PdfParser(QtCore.QObject):
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['solid'] = poly
new_el['follow'] = poly.exterior
new_el = {'solid': poly, 'follow': poly.exterior}
apertures_dict[str(aperture)]['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['solid'] = pdf_geo
new_el['follow'] = pdf_geo.exterior
new_el = {'solid': pdf_geo, 'follow': pdf_geo.exterior}
apertures_dict[str(aperture)]['geometry'].append(deepcopy(new_el))
else:
apertures_dict[str(aperture)] = {}
@@ -563,14 +557,10 @@ class PdfParser(QtCore.QObject):
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['solid'] = poly
new_el['follow'] = poly.exterior
new_el = {'solid': poly, 'follow': poly.exterior}
apertures_dict[str(aperture)]['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['solid'] = pdf_geo
new_el['follow'] = pdf_geo.exterior
new_el = {'solid': pdf_geo, 'follow': pdf_geo.exterior}
apertures_dict[str(aperture)]['geometry'].append(deepcopy(new_el))
continue
@@ -675,12 +665,10 @@ class PdfParser(QtCore.QObject):
if path_geo:
try:
for g in path_geo:
new_el = {}
new_el['clear'] = g
new_el = {'clear': g}
clear_apertures_dict['0']['geometry'].append(new_el)
except TypeError:
new_el = {}
new_el['clear'] = path_geo
new_el = {'clear': path_geo}
clear_apertures_dict['0']['geometry'].append(new_el)
# now that we finished searching for drill holes (this is not very precise because holes in the
@@ -690,12 +678,10 @@ class PdfParser(QtCore.QObject):
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['clear'] = poly
new_el = {'clear': poly}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['clear'] = pdf_geo
new_el = {'clear': pdf_geo}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
except KeyError:
# in case there is no stroke width yet therefore no aperture
@@ -706,12 +692,10 @@ class PdfParser(QtCore.QObject):
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['clear'] = poly
new_el = {'clear': poly}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['clear'] = pdf_geo
new_el = {'clear': pdf_geo}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
else:
# else, add the geometry as usual
@@ -719,14 +703,10 @@ class PdfParser(QtCore.QObject):
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['solid'] = poly
new_el['follow'] = poly.exterior
new_el = {'solid': poly, 'follow': poly.exterior}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['solid'] = pdf_geo
new_el['follow'] = pdf_geo.exterior
new_el = {'solid': pdf_geo, 'follow': pdf_geo.exterior}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
except KeyError:
# in case there is no stroke width yet therefore no aperture
@@ -737,14 +717,10 @@ class PdfParser(QtCore.QObject):
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['solid'] = poly
new_el['follow'] = poly.exterior
new_el = {'solid': poly, 'follow': poly.exterior}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['solid'] = pdf_geo
new_el['follow'] = pdf_geo.exterior
new_el = {'solid': pdf_geo, 'follow': pdf_geo.exterior}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
continue
@@ -890,50 +866,41 @@ class PdfParser(QtCore.QObject):
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['solid'] = poly
new_el['follow'] = poly.exterior
new_el = {'solid': poly, 'follow': poly.exterior}
apertures_dict[copy(found_aperture)]['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['solid'] = pdf_geo
new_el['follow'] = pdf_geo.exterior
new_el = {'solid': pdf_geo, 'follow': pdf_geo.exterior}
apertures_dict[copy(found_aperture)]['geometry'].append(deepcopy(new_el))
else:
if str(aperture) in apertures_dict.keys():
aperture += 1
apertures_dict[str(aperture)] = {}
apertures_dict[str(aperture)]['size'] = round(applied_size, 5)
apertures_dict[str(aperture)]['type'] = 'C'
apertures_dict[str(aperture)]['geometry'] = []
apertures_dict[str(aperture)] = {
'size': round(applied_size, 5),
'type': 'C',
'geometry': []
}
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['solid'] = poly
new_el['follow'] = poly.exterior
new_el = {'solid': poly, 'follow': poly.exterior}
apertures_dict[str(aperture)]['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['solid'] = pdf_geo
new_el['follow'] = pdf_geo.exterior
new_el = {'solid': pdf_geo, 'follow': pdf_geo.exterior}
apertures_dict[str(aperture)]['geometry'].append(deepcopy(new_el))
else:
apertures_dict[str(aperture)] = {}
apertures_dict[str(aperture)]['size'] = round(applied_size, 5)
apertures_dict[str(aperture)]['type'] = 'C'
apertures_dict[str(aperture)]['geometry'] = []
apertures_dict[str(aperture)] = {
'size': round(applied_size, 5),
'type': 'C',
'geometry': []
}
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['solid'] = poly
new_el['follow'] = poly.exterior
new_el = {'solid': poly, 'follow': poly.exterior}
apertures_dict[str(aperture)]['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['solid'] = pdf_geo
new_el['follow'] = pdf_geo.exterior
new_el = {'solid': pdf_geo, 'follow': pdf_geo.exterior}
apertures_dict[str(aperture)]['geometry'].append(deepcopy(new_el))
# ############################################# ##
@@ -946,60 +913,52 @@ class PdfParser(QtCore.QObject):
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in fill_geo:
new_el = {}
new_el['clear'] = poly
new_el = {'clear': poly}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['clear'] = pdf_geo
new_el = {'clear': pdf_geo}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
except KeyError:
# in case there is no stroke width yet therefore no aperture
apertures_dict['0'] = {}
apertures_dict['0']['size'] = round(applied_size, 5)
apertures_dict['0']['type'] = 'C'
apertures_dict['0']['geometry'] = []
apertures_dict['0'] = {
'size': round(applied_size, 5),
'type': 'C',
'geometry': []
}
for pdf_geo in fill_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['clear'] = poly
new_el = {'clear': poly}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['clear'] = pdf_geo
new_el = {'clear': pdf_geo}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
else:
try:
for pdf_geo in path_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in fill_geo:
new_el = {}
new_el['solid'] = poly
new_el['follow'] = poly.exterior
new_el = {'solid': poly, 'follow': poly.exterior}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['solid'] = pdf_geo
new_el['follow'] = pdf_geo.exterior
new_el = {'solid': pdf_geo, 'follow': pdf_geo.exterior}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
except KeyError:
# in case there is no stroke width yet therefore no aperture
apertures_dict['0'] = {}
apertures_dict['0']['size'] = round(applied_size, 5)
apertures_dict['0']['type'] = 'C'
apertures_dict['0']['geometry'] = []
apertures_dict['0'] = {
'size': round(applied_size, 5),
'type': 'C',
'geometry': []
}
for pdf_geo in fill_geo:
if isinstance(pdf_geo, MultiPolygon):
for poly in pdf_geo:
new_el = {}
new_el['solid'] = poly
new_el['follow'] = poly.exterior
new_el = {'solid': poly, 'follow': poly.exterior}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
else:
new_el = {}
new_el['solid'] = pdf_geo
new_el['follow'] = pdf_geo.exterior
new_el = {'solid': pdf_geo, 'follow': pdf_geo.exterior}
apertures_dict['0']['geometry'].append(deepcopy(new_el))
continue

View File

@@ -24,7 +24,7 @@ from svg.path import Line, Arc, CubicBezier, QuadraticBezier, parse_path
# from svg.path.path import Move
# from svg.path.path import Close
import svg.path
from shapely.geometry import LineString, MultiLineString
from shapely.geometry import LineString, MultiLineString, Point
from shapely.affinity import skew, affine_transform, rotate
import numpy as np
@@ -286,6 +286,8 @@ def svgcircle2shapely(circle, n_points=64, factor=1.0):
:type circle: xml.etree.ElementTree.Element
:param n_points: circle resolution; nr of points to b e used to approximate a circle
:type n_points: int
:param factor:
:type factor: float
:return: Shapely representation of the circle.
:rtype: shapely.geometry.polygon.LinearRing
"""
@@ -310,6 +312,8 @@ def svgellipse2shapely(ellipse, n_points=64, factor=1.0):
:type ellipse: xml.etree.ElementTree.Element
:param n_points: Number of discrete points in output.
:type n_points: int
:param factor:
:type factor: float
:return: Shapely representation of the ellipse.
:rtype: shapely.geometry.polygon.LinearRing
"""