- editing a multi geometry will no longer pop-up a Tcl window

- solved issue #292 where a new geometry renamed with many underscores failed to store the name in a saved project
- the name for the saved projects are updated to the current time and not to the time of the app startup
- some PEP8 changes related to comments starting with only one '#' symbol
This commit is contained in:
Marius Stanciu
2019-05-30 21:05:12 +03:00
parent ad7222a768
commit 8ee516ec14
55 changed files with 695 additions and 684 deletions

311
camlib.py
View File

@@ -1,12 +1,11 @@
############################################################
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
############################################################
# ########################################################## ##
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
# ########################################################## ##
#import traceback
from io import StringIO
@@ -58,6 +57,12 @@ if platform.architecture()[0] == '64bit':
from ortools.constraint_solver import pywrapcp
from ortools.constraint_solver import routing_enums_pb2
import gettext
import FlatCAMTranslation as fcTranslate
fcTranslate.apply_language('strings')
import builtins
log = logging.getLogger('base2')
log.setLevel(logging.DEBUG)
@@ -66,11 +71,6 @@ handler = logging.StreamHandler()
handler.setFormatter(formatter)
log.addHandler(handler)
import gettext
import FlatCAMTranslation as fcTranslate
fcTranslate.apply_language('strings')
import builtins
if '_' not in builtins.__dict__:
_ = gettext.gettext
@@ -132,21 +132,20 @@ class Geometry(object):
:param radius: Radius of the circle.
:return: None
"""
# TODO: Decide what solid_geometry is supposed to be and how we append to it.
if self.solid_geometry is None:
self.solid_geometry = []
if type(self.solid_geometry) is list:
self.solid_geometry.append(Point(origin).buffer(radius, int(int(self.geo_steps_per_circle) / 4)))
self.solid_geometry.append(Point(origin).buffer(
radius, int(int(self.geo_steps_per_circle) / 4)))
return
try:
self.solid_geometry = self.solid_geometry.union(Point(origin).buffer(radius,
int(int(self.geo_steps_per_circle) / 4)))
except:
#print "Failed to run union on polygons."
log.error("Failed to run union on polygons.")
self.solid_geometry = self.solid_geometry.union(Point(origin).buffer(
radius, int(int(self.geo_steps_per_circle) / 4)))
except Exception as e:
log.error("Failed to run union on polygons. %s" % str(e))
return
def add_polygon(self, points):
@@ -165,9 +164,8 @@ class Geometry(object):
try:
self.solid_geometry = self.solid_geometry.union(Polygon(points))
except:
#print "Failed to run union on polygons."
log.error("Failed to run union on polygons.")
except Exception as e:
log.error("Failed to run union on polygons. %s" % str(e))
return
def add_polyline(self, points):
@@ -186,13 +184,11 @@ class Geometry(object):
try:
self.solid_geometry = self.solid_geometry.union(LineString(points))
except:
#print "Failed to run union on polygons."
log.error("Failed to run union on polylines.")
except Exception as e:
log.error("Failed to run union on polylines. %s" % str(e))
return
def is_empty(self):
if isinstance(self.solid_geometry, BaseGeometry):
return self.solid_geometry.is_empty
@@ -213,18 +209,18 @@ class Geometry(object):
if self.solid_geometry is None:
self.solid_geometry = []
#pathonly should be allways True, otherwise polygons are not subtracted
# pathonly should be allways True, otherwise polygons are not subtracted
flat_geometry = self.flatten(pathonly=True)
log.debug("%d paths" % len(flat_geometry))
polygon=Polygon(points)
toolgeo=cascaded_union(polygon)
diffs=[]
polygon = Polygon(points)
toolgeo = cascaded_union(polygon)
diffs = []
for target in flat_geometry:
if type(target) == LineString or type(target) == LinearRing:
diffs.append(target.difference(toolgeo))
else:
log.warning("Not implemented.")
self.solid_geometry=cascaded_union(diffs)
self.solid_geometry = cascaded_union(diffs)
def bounds(self):
"""
@@ -336,7 +332,8 @@ class Geometry(object):
poly, which can can be iterable, contain iterable of, or
be itself an implementer of .contains().
:param poly: See description
:param point: See description
:param geoset: a polygon or list of polygons where to find if the param point is contained
:return: Polygon containing point or None.
"""
@@ -366,12 +363,12 @@ class Geometry(object):
if geometry is None:
geometry = self.solid_geometry
## If iterable, expand recursively.
# ## If iterable, expand recursively.
try:
for geo in geometry:
interiors.extend(self.get_interiors(geometry=geo))
## Not iterable, get the interiors if polygon.
# ## Not iterable, get the interiors if polygon.
except TypeError:
if type(geometry) == Polygon:
interiors.extend(geometry.interiors)
@@ -393,12 +390,12 @@ class Geometry(object):
if geometry is None:
geometry = self.solid_geometry
## If iterable, expand recursively.
# ## If iterable, expand recursively.
try:
for geo in geometry:
exteriors.extend(self.get_exteriors(geometry=geo))
## Not iterable, get the exterior if polygon.
# ## Not iterable, get the exterior if polygon.
except TypeError:
if type(geometry) == Polygon:
exteriors.append(geometry.exterior)
@@ -423,7 +420,7 @@ class Geometry(object):
if reset:
self.flat_geometry = []
## If iterable, expand recursively.
# ## If iterable, expand recursively.
try:
for geo in geometry:
if geo is not None:
@@ -431,7 +428,7 @@ class Geometry(object):
reset=False,
pathonly=pathonly)
## Not iterable, do the actual indexing and add.
# ## Not iterable, do the actual indexing and add.
except TypeError:
if pathonly and type(geometry) == Polygon:
self.flat_geometry.append(geometry.exterior)
@@ -480,18 +477,18 @@ class Geometry(object):
# if reset:
# self.flat_geometry = []
#
# ## If iterable, expand recursively.
# # ## If iterable, expand recursively.
# try:
# for geo in geometry:
# self.flatten_to_paths(geometry=geo, reset=False)
#
# ## Not iterable, do the actual indexing and add.
# # ## Not iterable, do the actual indexing and add.
# except TypeError:
# if type(geometry) == Polygon:
# g = geometry.exterior
# self.flat_geometry.append(g)
#
# ## Add first and last points of the path to the index.
# # ## Add first and last points of the path to the index.
# self.flat_geometry_rtree.insert(len(self.flat_geometry) - 1, g.coords[0])
# self.flat_geometry_rtree.insert(len(self.flat_geometry) - 1, g.coords[-1])
#
@@ -694,7 +691,6 @@ class Geometry(object):
else:
scale_factor = 1 / dpi
geos = []
unscaled_geos = []
@@ -715,7 +711,7 @@ class Geometry(object):
pass
try:
blue= src.read(3)
blue = src.read(3)
except:
pass
@@ -807,7 +803,7 @@ class Geometry(object):
assert type(polygon) == Polygon or type(polygon) == MultiPolygon, \
"Expected a Polygon or MultiPolygon, got %s" % type(polygon)
## The toolpaths
# ## The toolpaths
# Index first and last points in paths
def get_pts(o):
return [o.coords[0], o.coords[-1]]
@@ -893,7 +889,7 @@ class Geometry(object):
# Current buffer radius
radius = tooldia / 2 * (1 - overlap)
## The toolpaths
# ## The toolpaths
# Index first and last points in paths
def get_pts(o):
return [o.coords[0], o.coords[-1]]
@@ -973,7 +969,7 @@ class Geometry(object):
# log.debug("camlib.clear_polygon3()")
## The toolpaths
# ## The toolpaths
# Index first and last points in paths
def get_pts(o):
return [o.coords[0], o.coords[-1]]
@@ -1071,7 +1067,7 @@ class Geometry(object):
# Assuming geolist is a flat list of flat elements
## Index first and last points in paths
# ## Index first and last points in paths
def get_pts(o):
return [o.coords[0], o.coords[-1]]
@@ -1085,7 +1081,7 @@ class Geometry(object):
# storage.insert(LineString(shape))
# #storage.insert(shape)
## Iterate over geometry paths getting the nearest each time.
# ## Iterate over geometry paths getting the nearest each time.
#optimized_paths = []
optimized_paths = FlatCAMRTreeStorage()
optimized_paths.get_points = get_pts
@@ -1129,15 +1125,15 @@ class Geometry(object):
else:
# Have to lift tool. End path.
#log.debug("Path #%d not within boundary. Next." % path_count)
#optimized_paths.append(geo)
# log.debug("Path #%d not within boundary. Next." % path_count)
# optimized_paths.append(geo)
optimized_paths.insert(geo)
geo = candidate
current_pt = geo.coords[-1]
# Next
#pt, geo = storage.nearest(current_pt)
# pt, geo = storage.nearest(current_pt)
except StopIteration: # Nothing left in storage.
#pass
@@ -1159,7 +1155,7 @@ class Geometry(object):
log.debug("path_connect()")
## Index first and last points in paths
# ## Index first and last points in paths
def get_pts(o):
return [o.coords[0], o.coords[-1]]
#
@@ -1173,18 +1169,14 @@ class Geometry(object):
path_count = 0
pt, geo = storage.nearest(origin)
storage.remove(geo)
#optimized_geometry = [geo]
# optimized_geometry = [geo]
optimized_geometry = FlatCAMRTreeStorage()
optimized_geometry.get_points = get_pts
#optimized_geometry.insert(geo)
# optimized_geometry.insert(geo)
try:
while True:
path_count += 1
#print "geo is", geo
_, left = storage.nearest(geo.coords[0])
#print "left is", left
# If left touches geo, remove left from original
# storage and append to geo.
@@ -1210,7 +1202,6 @@ class Geometry(object):
continue
_, right = storage.nearest(geo.coords[-1])
#print "right is", right
# If right touches geo, remove left from original
# storage and append to geo.
@@ -1243,7 +1234,7 @@ class Geometry(object):
if type(right) == LinearRing:
optimized_geometry.insert(right)
else:
# Cannot exteng geo any further. Put it away.
# Cannot extend geo any further. Put it away.
optimized_geometry.insert(geo)
# Continue with right.
@@ -1252,7 +1243,7 @@ class Geometry(object):
except StopIteration: # Nothing found in storage.
optimized_geometry.insert(geo)
#print path_count
# print path_count
log.debug("path_count = %d" % path_count)
return optimized_geometry
@@ -1288,7 +1279,7 @@ class Geometry(object):
def to_dict(self):
"""
Returns a respresentation of the object as a dictionary.
Returns a representation of the object as a dictionary.
Attributes to include are listed in ``self.ser_attrs``.
:return: A dictionary-encoded copy of the object.
@@ -1485,7 +1476,7 @@ class ApertureMacro:
<Comment>: 0 <Text>
"""
## Regular expressions
# ## Regular expressions
am1_re = re.compile(r'^%AM([^\*]+)\*(.+)?(%)?$')
am2_re = re.compile(r'(.*)%$')
amcomm_re = re.compile(r'^0(.*)')
@@ -1496,8 +1487,8 @@ class ApertureMacro:
self.name = name
self.raw = ""
## These below are recomputed for every aperture
## definition, in other words, are temporary variables.
# ## These below are recomputed for every aperture
# ## definition, in other words, are temporary variables.
self.primitives = []
self.locvars = {}
self.geometry = None
@@ -1543,14 +1534,14 @@ class ApertureMacro:
# Separate parts
parts = self.raw.split('*')
#### Every part in the macro ####
#### Every part in the macro ## ##
for part in parts:
### Comments. Ignored.
# ## Comments. Ignored.
match = ApertureMacro.amcomm_re.search(part)
if match:
continue
### Variables
# ## Variables
# These are variables defined locally inside the macro. They can be
# numerical constant or defind in terms of previously define
# variables, which can be defined locally or in an aperture
@@ -1575,14 +1566,14 @@ class ApertureMacro:
self.locvars[var] = eval(val)
continue
### Primitives
# ## Primitives
# Each is an array. The first identifies the primitive, while the
# rest depend on the primitive. All are strings representing a
# number and may contain variable definition. The values of these
# variables are defined in an aperture definition.
match = ApertureMacro.amprim_re.search(part)
if match:
## Replace all variables
# ## Replace all variables
for v in self.locvars:
# replaced the following line with the next to fix Mentor custom apertures not parsed OK
# part = re.sub(r'\$' + str(v) + r'(?![0-9a-zA-Z])', str(self.locvars[v]), part)
@@ -1594,7 +1585,7 @@ class ApertureMacro:
# Change x with *
part = re.sub(r'[xX]', "*", part)
## Store
# ## Store
elements = part.split(",")
self.primitives.append([eval(x) for x in elements])
continue
@@ -1754,8 +1745,8 @@ class ApertureMacro:
i = 1 # Number of rings created so far
## If the ring does not have an interior it means that it is
## a disk. Then stop.
# ## If the ring does not have an interior it means that it is
# ## a disk. Then stop.
while len(ring.interiors) > 0 and i < nrings:
r -= thickness + gap
if r <= 0:
@@ -1764,7 +1755,7 @@ class ApertureMacro:
result = cascaded_union([result, ring])
i += 1
## Crosshair
# ## Crosshair
hor = LineString([(x - cross_len, y), (x + cross_len, y)]).buffer(cross_th/2.0, cap_style=2)
ver = LineString([(x, y-cross_len), (x, y + cross_len)]).buffer(cross_th/2.0, cap_style=2)
result = cascaded_union([result, hor, ver])
@@ -1802,7 +1793,7 @@ class ApertureMacro:
:rtype: shapely.geometry.polygon
"""
## Primitive makers
# ## Primitive makers
makers = {
"1": ApertureMacro.make_circle,
"2": ApertureMacro.make_vectorline,
@@ -1815,19 +1806,19 @@ class ApertureMacro:
"7": ApertureMacro.make_thermal
}
## Store modifiers as local variables
# ## Store modifiers as local variables
modifiers = modifiers or []
modifiers = [float(m) for m in modifiers]
self.locvars = {}
for i in range(0, len(modifiers)):
self.locvars[str(i + 1)] = modifiers[i]
## Parse
# ## Parse
self.primitives = [] # Cleanup
self.geometry = Polygon()
self.parse_content()
## Make the geometry
# ## Make the geometry
for primitive in self.primitives:
# Make the primitive
prim_geo = makers[str(int(primitive[0]))](primitive[1:])
@@ -1898,9 +1889,7 @@ class Gerber (Geometry):
:rtype: Gerber
"""
# How to discretize a circle.
# if steps_per_circle is None:
# steps_per_circle = int(Gerber.defaults['steps_per_circle'])
# How to approximate a circle with lines.
self.steps_per_circle = int(self.app.defaults["gerber_circle_steps"])
# Initialize parent
@@ -1917,7 +1906,7 @@ class Gerber (Geometry):
"""Zeros in Gerber numbers. If 'L' then remove leading zeros, if 'T' remove trailing zeros. Used during parsing.
"""
## Gerber elements ##
# ## Gerber elements # ##
'''
apertures = {
'id':{
@@ -1963,7 +1952,7 @@ class Gerber (Geometry):
self.ser_attrs += ['int_digits', 'frac_digits', 'apertures',
'aperture_macros', 'solid_geometry', 'source_file']
#### Parser patterns ####
# ### Parser patterns ## ##
# FS - Format Specification
# The format of X and Y must be the same!
# L-omit leading zeros, T-omit trailing zeros, D-no zero supression
@@ -1985,7 +1974,7 @@ class Gerber (Geometry):
# AM - Aperture Macro
# Beginning of macro (Ends with *%):
#self.am_re = re.compile(r'^%AM([a-zA-Z0-9]*)\*')
# self.am_re = re.compile(r'^%AM([a-zA-Z0-9]*)\*')
# Tool change
# May begin with G54 but that is deprecated
@@ -2159,7 +2148,7 @@ class Gerber (Geometry):
self.parse_lines(line_generator())
#@profile
# @profile
def parse_lines(self, glines):
"""
Main Gerber parser. Reads Gerber and populates ``self.paths``, ``self.apertures``,
@@ -2228,7 +2217,7 @@ class Gerber (Geometry):
# If a region is being defined
making_region = False
#### Parsing starts here ####
# ### Parsing starts here ## ##
line_num = 0
gline = ""
try:
@@ -2240,15 +2229,15 @@ class Gerber (Geometry):
gline = gline.strip(' \r\n')
# log.debug("Line=%3s %s" % (line_num, gline))
# ###############################################################
# ############################################################# ##
# Ignored lines #
# Comments ######
# ###############################################################
# Comments #### ##
# ############################################################# ##
match = self.comm_re.search(gline)
if match:
continue
# Polarity change ########
# Polarity change ###### ##
# Example: %LPD*% or %LPC*%
# If polarity changes, creates geometry from current
# buffer, then adds or subtracts accordingly.
@@ -2303,10 +2292,10 @@ class Gerber (Geometry):
current_polarity = new_polarity
continue
# ###############################################################
# Number format ##################
# ############################################################# ##
# Number format ############################################### ##
# Example: %FSLAX24Y24*%
# ###############################################################
# ############################################################# ##
# TODO: This is ignoring most of the format. Implement the rest.
match = self.fmt_re.search(gline)
if match:
@@ -2322,7 +2311,7 @@ class Gerber (Geometry):
log.debug("Gerber format found. Coordinates type = %s (Absolute or Relative)" % absolute)
continue
### Mode (IN/MM)
# ## Mode (IN/MM)
# Example: %MOIN*%
match = self.mode_re.search(gline)
if match:
@@ -2332,9 +2321,9 @@ class Gerber (Geometry):
self.convert_units(match.group(1))
continue
# ###############################################################
# Combined Number format and Mode --- Allegro does this #########
# ###############################################################
# ############################################################# ##
# Combined Number format and Mode --- Allegro does this ####### ##
# ############################################################# ##
match = self.fmt_re_alt.search(gline)
if match:
absolute = {'A': 'Absolute', 'I': 'Relative'}[match.group(2)]
@@ -2353,9 +2342,9 @@ class Gerber (Geometry):
self.convert_units(match.group(5))
continue
# ###############################################################
# ############################################################# ##
# Search for OrCAD way for having Number format
# ###############################################################
# ############################################################# ##
match = self.fmt_re_orcad.search(gline)
if match:
if match.group(1) is not None:
@@ -2379,9 +2368,9 @@ class Gerber (Geometry):
self.convert_units(match.group(5))
continue
# ###############################################################
# ############################################################# ##
# Units (G70/1) OBSOLETE
# ###############################################################
# ############################################################# ##
match = self.units_re.search(gline)
if match:
obs_gerber_units = {'0': 'IN', '1': 'MM'}[match.group(1)]
@@ -2390,21 +2379,21 @@ class Gerber (Geometry):
self.convert_units({'0': 'IN', '1': 'MM'}[match.group(1)])
continue
# ###############################################################
# Absolute/relative coordinates G90/1 OBSOLETE ##########
# #######################################################
# ############################################################# ##
# Absolute/relative coordinates G90/1 OBSOLETE ######## ##
# ##################################################### ##
match = self.absrel_re.search(gline)
if match:
absolute = {'0': "Absolute", '1': "Relative"}[match.group(1)]
log.warning("Gerber obsolete coordinates type found = %s (Absolute or Relative) " % absolute)
continue
# ###############################################################
# Aperture Macros #######################################
# ############################################################# ##
# Aperture Macros ##################################### ##
# Having this at the beginning will slow things down
# but macros can have complicated statements than could
# be caught by other patterns.
# ###############################################################
# ############################################################# ##
if current_macro is None: # No macro started yet
match = self.am1_re.search(gline)
# Start macro if match, else not an AM, carry on.
@@ -2431,18 +2420,18 @@ class Gerber (Geometry):
self.aperture_macros[current_macro].append(gline)
continue
### Aperture definitions %ADD...
# ## Aperture definitions %ADD...
match = self.ad_re.search(gline)
if match:
# log.info("Found aperture definition. Line %d: %s" % (line_num, gline))
self.aperture_parse(match.group(1), match.group(2), match.group(3))
continue
# ###############################################################
# Operation code alone ########################
# ############################################################# ##
# Operation code alone ###################### ##
# Operation code alone, usually just D03 (Flash)
# self.opcode_re = re.compile(r'^D0?([123])\*$')
# ###############################################################
# ############################################################# ##
match = self.opcode_re.search(gline)
if match:
current_operation_code = int(match.group(1))
@@ -2479,10 +2468,10 @@ class Gerber (Geometry):
continue
# ###############################################################
# ############################################################# ##
# Tool/aperture change
# Example: D12*
# ###############################################################
# ############################################################# ##
match = self.tool_re.search(gline)
if match:
current_aperture = match.group(1)
@@ -2529,9 +2518,9 @@ class Gerber (Geometry):
continue
# ###############################################################
# ############################################################# ##
# G36* - Begin region
# ###############################################################
# ############################################################# ##
if self.regionon_re.search(gline):
if len(path) > 1:
# Take care of what is left in the path
@@ -2563,9 +2552,9 @@ class Gerber (Geometry):
making_region = True
continue
# ###############################################################
# ############################################################# ##
# G37* - End region
# ###############################################################
# ############################################################# ##
if self.regionoff_re.search(gline):
making_region = False
@@ -2632,7 +2621,7 @@ class Gerber (Geometry):
path = [[current_x, current_y]] # Start new path
continue
### G01/2/3* - Interpolation mode change
# ## G01/2/3* - Interpolation mode change
# Can occur along with coordinates and operation code but
# sometimes by itself (handled here).
# Example: G01*
@@ -2641,7 +2630,7 @@ class Gerber (Geometry):
current_interpolation_mode = int(match.group(1))
continue
### G01 - Linear interpolation plus flashes
# ## G01 - Linear interpolation plus flashes
# Operation code (D0x) missing is deprecated... oh well I will support it.
# REGEX: r'^(?:G0?(1))?(?:X(-?\d+))?(?:Y(-?\d+))?(?:D0([123]))?\*$'
match = self.lin_re.search(gline)
@@ -2896,7 +2885,7 @@ class Gerber (Geometry):
# log.debug("Line_number=%3s X=%s Y=%s (%s)" % (line_num, linear_x, linear_y, gline))
continue
### G74/75* - Single or multiple quadrant arcs
# ## G74/75* - Single or multiple quadrant arcs
match = self.quad_re.search(gline)
if match:
if match.group(1) == '4':
@@ -2905,7 +2894,7 @@ class Gerber (Geometry):
quadrant_mode = 'MULTI'
continue
### G02/3 - Circular interpolation
# ## G02/3 - Circular interpolation
# 2-clockwise, 3-counterclockwise
# Ex. format: G03 X0 Y50 I-50 J0 where the X, Y coords are the coords of the End Point
match = self.circ_re.search(gline)
@@ -3084,12 +3073,12 @@ class Gerber (Geometry):
else:
log.warning("Invalid arc in line %d." % line_num)
## EOF
# ## EOF
match = self.eof_re.search(gline)
if match:
continue
### Line did not match any pattern. Warn user.
# ## Line did not match any pattern. Warn user.
log.warning("Line ignored (%d): %s" % (line_num, gline))
if len(path) > 1:
@@ -3100,7 +3089,7 @@ class Gerber (Geometry):
pass
else:
# EOF, create shapely LineString if something still in path
## --- Buffered ---
# ## --- Buffered ---
geo_dict = dict()
# this treats the case when we are storing geometry as paths
@@ -3392,7 +3381,7 @@ class Gerber (Geometry):
self.app.inform.emit(_("[success] Gerber Scale done."))
## solid_geometry ???
# ## solid_geometry ???
# It's a cascaded union of objects.
# self.solid_geometry = affinity.scale(self.solid_geometry, factor,
# factor, origin=(0, 0))
@@ -3435,7 +3424,7 @@ class Gerber (Geometry):
else:
return affinity.translate(obj, xoff=dx, yoff=dy)
## Solid geometry
# ## Solid geometry
self.solid_geometry = offset_geom(self.solid_geometry)
self.follow_geometry = offset_geom(self.follow_geometry)
@@ -3677,7 +3666,7 @@ class Excellon(Geometry):
self.num_tools = [] # List for keeping the tools sorted
self.index_per_tool = {} # Dictionary to store the indexed points for each tool
## IN|MM -> Units are inherited from Geometry
# ## IN|MM -> Units are inherited from Geometry
#self.units = units
# Trailing "T" or leading "L" (default)
@@ -3708,7 +3697,7 @@ class Excellon(Geometry):
'excellon_format_upper_in', 'excellon_format_lower_in', 'excellon_units', 'slots',
'source_file']
#### Patterns ####
#### Patterns ## ##
# Regex basics:
# ^ - beginning
# $ - end
@@ -3855,7 +3844,7 @@ class Excellon(Geometry):
line_units = ''
#### Parsing starts here ####
#### Parsing starts here ## ##
line_num = 0 # Line number
eline = ""
try:
@@ -3946,7 +3935,7 @@ class Excellon(Geometry):
log.warning("Found end of the header: %s" % eline)
continue
## Alternative units format M71/M72
# ## Alternative units format M71/M72
# Supposed to be just in the body (yes, the body)
# but some put it in the header (PADS for example).
# Will detect anywhere. Occurrence will change the
@@ -3966,10 +3955,10 @@ class Excellon(Geometry):
':' + str(self.excellon_format_lower_in))
continue
#### Body ####
#### Body ## ##
if not in_header:
## Tool change ##
# ## Tool change # ##
match = self.toolsel_re.search(eline)
if match:
current_tool = str(int(match.group(1)))
@@ -4009,7 +3998,7 @@ class Excellon(Geometry):
continue
## Allegro Type Tool change ##
# ## Allegro Type Tool change # ##
if allegro_warning is True:
match = self.absinc_re.search(eline)
match1 = self.stop_re.search(eline)
@@ -4019,7 +4008,7 @@ class Excellon(Geometry):
log.debug(" Tool change for Allegro type of Excellon: %s" % current_tool)
continue
## Slots parsing for drilled slots (contain G85)
# ## Slots parsing for drilled slots (contain G85)
# a Excellon drilled slot line may look like this:
# X01125Y0022244G85Y0027756
match = self.slots_re.search(eline)
@@ -4032,7 +4021,7 @@ class Excellon(Geometry):
start_coords_match = match.group(1)
stop_coords_match = match.group(2)
# Slot coordinates without period ##
# Slot coordinates without period # ##
# get the coordinates for slot start and for slot stop into variables
start_coords_noperiod = self.coordsnoperiod_re.search(start_coords_match)
stop_coords_noperiod = self.coordsnoperiod_re.search(stop_coords_match)
@@ -4101,7 +4090,7 @@ class Excellon(Geometry):
)
continue
# Slot coordinates with period: Use literally. ##
# Slot coordinates with period: Use literally. # ##
# get the coordinates for slot start and for slot stop into variables
start_coords_period = self.coordsperiod_re.search(start_coords_match)
stop_coords_period = self.coordsperiod_re.search(stop_coords_match)
@@ -4170,7 +4159,7 @@ class Excellon(Geometry):
)
continue
## Coordinates without period ##
# ## Coordinates without period # ##
match = self.coordsnoperiod_re.search(eline)
if match:
matchr = self.repeat_re.search(eline)
@@ -4201,7 +4190,7 @@ class Excellon(Geometry):
log.error("Missing coordinates")
continue
## Excellon Routing parse
# ## Excellon Routing parse
if len(re.findall("G00", eline)) > 0:
self.match_routing_start = 'G00'
@@ -4251,7 +4240,7 @@ class Excellon(Geometry):
# log.debug("{:15} {:8} {:8}".format(eline, x, y))
continue
## Coordinates with period: Use literally. ##
# ## Coordinates with period: Use literally. # ##
match = self.coordsperiod_re.search(eline)
if match:
matchr = self.repeat_re.search(eline)
@@ -4282,7 +4271,7 @@ class Excellon(Geometry):
log.error("Missing coordinates")
continue
## Excellon Routing parse
# ## Excellon Routing parse
if len(re.findall("G00", eline)) > 0:
self.match_routing_start = 'G00'
@@ -4333,10 +4322,10 @@ class Excellon(Geometry):
# log.debug("{:15} {:8} {:8}".format(eline, x, y))
continue
#### Header ####
#### Header ## ##
if in_header:
## Tool definitions ##
# ## Tool definitions # ##
match = self.toolset_re.search(eline)
if match:
@@ -4354,7 +4343,7 @@ class Excellon(Geometry):
log.debug(" Tool definition: %s %s" % (name, spec))
continue
## Units and number format ##
# ## Units and number format # ##
match = self.units_re.match(eline)
if match:
self.units_found = match.group(1)
@@ -4412,7 +4401,7 @@ class Excellon(Geometry):
log.warning("Type of zeros found: %s" % self.zeros)
continue
## Units and number format outside header##
# ## Units and number format outside header# ##
match = self.units_re.match(eline)
if match:
self.units_found = match.group(1)
@@ -4489,7 +4478,7 @@ class Excellon(Geometry):
# You must show all zeros to the right of the number and can omit
# all zeros to the left of the number. The CNC-7 will count the number
# of digits you typed and automatically fill in the missing zeros.
## flatCAM expects 6digits
# ## flatCAM expects 6digits
# flatCAM expects the number of digits entered into the defaults
if self.units.lower() == "in": # Inches is 00.0000
@@ -5284,7 +5273,7 @@ class CNCjob(Geometry):
self.postdata['toolC'] = exobj.tools[tool]["C"]
self.tooldia = exobj.tools[tool]["C"]
################################################
############################################## ##
# Create the data.
node_list = []
locations = create_data_array()
@@ -5334,7 +5323,7 @@ class CNCjob(Geometry):
log.warning('No solution found.')
else:
log.warning('Specify an instance greater than 0.')
################################################
############################################## ##
# Only if tool has points.
if tool in points:
@@ -5390,7 +5379,7 @@ class CNCjob(Geometry):
self.postdata['toolC']=exobj.tools[tool]["C"]
self.tooldia = exobj.tools[tool]["C"]
################################################
############################################## ##
node_list = []
locations = create_data_array()
tsp_size = len(locations)
@@ -5432,7 +5421,7 @@ class CNCjob(Geometry):
log.warning('No solution found.')
else:
log.warning('Specify an instance greater than 0.')
################################################
############################################## ##
# Only if tool has points.
if tool in points:
@@ -5588,7 +5577,7 @@ class CNCjob(Geometry):
else:
temp_solid_geometry = geometry
## Flatten the geometry. Only linear elements (no polygons) remain.
# ## Flatten the geometry. Only linear elements (no polygons) remain.
flat_geometry = self.flatten(temp_solid_geometry, pathonly=True)
log.debug("%d paths" % len(flat_geometry))
@@ -5665,7 +5654,7 @@ class CNCjob(Geometry):
"This is dangerous, skipping %s file") % self.options['name'])
return 'fail'
## Index first and last points in paths
# ## Index first and last points in paths
# What points to index.
def get_pts(o):
return [o.coords[0], o.coords[-1]]
@@ -5719,7 +5708,7 @@ class CNCjob(Geometry):
if self.dwell is True:
self.gcode += self.doformat(p.dwell_code) # Dwell time
## Iterate over geometry paths getting the nearest each time.
# ## Iterate over geometry paths getting the nearest each time.
log.debug("Starting G-Code...")
path_count = 0
current_pt = (0, 0)
@@ -5855,7 +5844,7 @@ class CNCjob(Geometry):
else:
temp_solid_geometry = geometry.solid_geometry
## Flatten the geometry. Only linear elements (no polygons) remain.
# ## Flatten the geometry. Only linear elements (no polygons) remain.
flat_geometry = self.flatten(temp_solid_geometry, pathonly=True)
log.debug("%d paths" % len(flat_geometry))
@@ -5928,7 +5917,7 @@ class CNCjob(Geometry):
"This is dangerous, skipping %s file") % self.options['name'])
return 'fail'
## Index first and last points in paths
# ## Index first and last points in paths
# What points to index.
def get_pts(o):
return [o.coords[0], o.coords[-1]]
@@ -6041,7 +6030,7 @@ class CNCjob(Geometry):
log.debug("Generate_from_solderpaste_geometry()")
## Index first and last points in paths
# ## Index first and last points in paths
# What points to index.
def get_pts(o):
return [o.coords[0], o.coords[-1]]
@@ -6077,7 +6066,7 @@ class CNCjob(Geometry):
else self.app.defaults['tools_solderpaste_pp']
p = self.app.postprocessors[self.pp_solderpaste_name]
## Flatten the geometry. Only linear elements (no polygons) remain.
# ## Flatten the geometry. Only linear elements (no polygons) remain.
flat_geometry = self.flatten(kwargs['solid_geometry'], pathonly=True)
log.debug("%d paths" % len(flat_geometry))
@@ -6096,7 +6085,7 @@ class CNCjob(Geometry):
self.gcode += self.doformat(p.spindle_off_code)
self.gcode += self.doformat(p.toolchange_code)
## Iterate over geometry paths getting the nearest each time.
# ## Iterate over geometry paths getting the nearest each time.
log.debug("Starting SolderPaste G-Code...")
path_count = 0
current_pt = (0, 0)
@@ -6355,12 +6344,12 @@ class CNCjob(Geometry):
gobj = self.codes_split(line)
## Units
# ## Units
if 'G' in gobj and (gobj['G'] == 20.0 or gobj['G'] == 21.0):
self.units = {20.0: "IN", 21.0: "MM"}[gobj['G']]
continue
## Changing height
# ## Changing height
if 'Z' in gobj:
if 'Roland' in self.pp_excellon_name or 'Roland' in self.pp_geometry_name:
pass
@@ -7699,7 +7688,7 @@ class FlatCAMRTree(object):
# Python RTree Index
self.rti = rtindex.Index()
## Track object-point relationship
# ## Track object-point relationship
# Each is list of points in object.
self.obj2points = []