- Gerber Editor: added support for Gerber polarity change commands (LPD, LPC)

This commit is contained in:
Marius Stanciu 2019-04-12 19:29:12 +03:00
parent e478d6e043
commit 80c5cf86b7
3 changed files with 189 additions and 70 deletions

View File

@ -21,6 +21,7 @@ CAD program, and create G-Code for Isolation routing.
- updated the shortcut list with the Gerber Editor shortcut keys - updated the shortcut list with the Gerber Editor shortcut keys
- Gerber Editor: fixed error when adding an aperture with code value lower than the ones that already exists - Gerber Editor: fixed error when adding an aperture with code value lower than the ones that already exists
- when adding an aperture with code '0' (zero) it will automatically be set with size zero and type: 'REG' (from region); here we store all the regions from a Gerber file, the ones without a declared aperture - when adding an aperture with code '0' (zero) it will automatically be set with size zero and type: 'REG' (from region); here we store all the regions from a Gerber file, the ones without a declared aperture
- Gerber Editor: added support for Gerber polarity change commands (LPD, LPC)
11.04.2019 11.04.2019

244
camlib.py
View File

@ -2169,6 +2169,10 @@ class Gerber (Geometry):
# applying a union for every new polygon. # applying a union for every new polygon.
poly_buffer = [] poly_buffer = []
# made True when the LPC command is encountered in Gerber parsing
# it allows adding data into the clear_geometry key of the self.apertures[aperture] dict
self.is_lpc = False
# store here the follow geometry # store here the follow geometry
follow_buffer = [] follow_buffer = []
@ -2243,19 +2247,26 @@ class Gerber (Geometry):
if not geo.is_empty: if not geo.is_empty:
follow_buffer.append(geo) follow_buffer.append(geo)
try: try:
self.apertures[current_aperture]['follow_geometry'].append(geo) self.apertures[last_path_aperture]['follow_geometry'].append(geo)
except KeyError: except KeyError:
self.apertures[current_aperture]['follow_geometry'] = [] self.apertures[last_path_aperture]['follow_geometry'] = []
self.apertures[current_aperture]['follow_geometry'].append(geo) self.apertures[last_path_aperture]['follow_geometry'].append(geo)
geo = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4)) geo = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
if not geo.is_empty: if not geo.is_empty:
poly_buffer.append(geo) poly_buffer.append(geo)
try: if self.is_lpc is True:
self.apertures[current_aperture]['solid_geometry'].append(geo) try:
except KeyError: self.apertures[last_path_aperture]['clear_geometry'].append(geo)
self.apertures[current_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[current_aperture]['solid_geometry'].append(geo) self.apertures[last_path_aperture]['clear_geometry'] = []
self.apertures[last_path_aperture]['clear_geometry'].append(geo)
else:
try:
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except KeyError:
self.apertures[last_path_aperture]['solid_geometry'] = []
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
path = [path[-1]] path = [path[-1]]
@ -2264,10 +2275,12 @@ class Gerber (Geometry):
# TODO: Remove when bug fixed # TODO: Remove when bug fixed
if len(poly_buffer) > 0: if len(poly_buffer) > 0:
if current_polarity == 'D': if current_polarity == 'D':
self.is_lpc = True
# self.follow_geometry = self.follow_geometry.union(cascaded_union(follow_buffer)) # self.follow_geometry = self.follow_geometry.union(cascaded_union(follow_buffer))
self.solid_geometry = self.solid_geometry.union(cascaded_union(poly_buffer)) self.solid_geometry = self.solid_geometry.union(cascaded_union(poly_buffer))
else: else:
self.is_lpc = False
# self.follow_geometry = self.follow_geometry.difference(cascaded_union(follow_buffer)) # self.follow_geometry = self.follow_geometry.difference(cascaded_union(follow_buffer))
self.solid_geometry = self.solid_geometry.difference(cascaded_union(poly_buffer)) self.solid_geometry = self.solid_geometry.difference(cascaded_union(poly_buffer))
@ -2420,11 +2433,18 @@ class Gerber (Geometry):
int(self.steps_per_circle)) int(self.steps_per_circle))
if not flash.is_empty: if not flash.is_empty:
poly_buffer.append(flash) poly_buffer.append(flash)
try: if self.is_lpc is True:
self.apertures[current_aperture]['solid_geometry'].append(flash) try:
except KeyError: self.apertures[current_aperture]['clear_geometry'].append(flash)
self.apertures[current_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[current_aperture]['solid_geometry'].append(flash) self.apertures[current_aperture]['clear_geometry'] = []
self.apertures[current_aperture]['clear_geometry'].append(flash)
else:
try:
self.apertures[current_aperture]['solid_geometry'].append(flash)
except KeyError:
self.apertures[current_aperture]['solid_geometry'] = []
self.apertures[current_aperture]['solid_geometry'].append(flash)
except IndexError: except IndexError:
log.warning("Line %d: %s -> Nothing there to flash!" % (line_num, gline)) log.warning("Line %d: %s -> Nothing there to flash!" % (line_num, gline))
@ -2467,11 +2487,18 @@ class Gerber (Geometry):
geo = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4)) geo = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
if not geo.is_empty: if not geo.is_empty:
poly_buffer.append(geo) poly_buffer.append(geo)
try: if self.is_lpc is True:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) try:
except KeyError: self.apertures[last_path_aperture]['clear_geometry'].append(geo)
self.apertures[last_path_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) self.apertures[last_path_aperture]['clear_geometry'] = []
self.apertures[last_path_aperture]['clear_geometry'].append(geo)
else:
try:
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except KeyError:
self.apertures[last_path_aperture]['solid_geometry'] = []
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
path = [path[-1]] path = [path[-1]]
@ -2497,11 +2524,18 @@ class Gerber (Geometry):
geo = LineString(path).buffer(width/1.999, int(self.steps_per_circle / 4)) geo = LineString(path).buffer(width/1.999, int(self.steps_per_circle / 4))
if not geo.is_empty: if not geo.is_empty:
poly_buffer.append(geo) poly_buffer.append(geo)
try: if self.is_lpc is True:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) try:
except KeyError: self.apertures[last_path_aperture]['clear_geometry'].append(geo)
self.apertures[last_path_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) self.apertures[last_path_aperture]['clear_geometry'] = []
self.apertures[last_path_aperture]['clear_geometry'].append(geo)
else:
try:
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except KeyError:
self.apertures[last_path_aperture]['solid_geometry'] = []
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
path = [path[-1]] path = [path[-1]]
@ -2525,11 +2559,18 @@ class Gerber (Geometry):
self.apertures[current_aperture]['follow_geometry'].append(geo) self.apertures[current_aperture]['follow_geometry'].append(geo)
poly_buffer.append(geo) poly_buffer.append(geo)
try: if self.is_lpc is True:
self.apertures[current_aperture]['solid_geometry'].append(geo) try:
except KeyError: self.apertures[current_aperture]['clear_geometry'].append(geo)
self.apertures[current_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[current_aperture]['solid_geometry'].append(geo) self.apertures[current_aperture]['clear_geometry'] = []
self.apertures[current_aperture]['clear_geometry'].append(geo)
else:
try:
self.apertures[current_aperture]['solid_geometry'].append(geo)
except KeyError:
self.apertures[current_aperture]['solid_geometry'] = []
self.apertures[current_aperture]['solid_geometry'].append(geo)
continue continue
# Only one path defines region? # Only one path defines region?
@ -2578,11 +2619,18 @@ class Gerber (Geometry):
self.apertures['0']['solid_geometry'] = [] self.apertures['0']['solid_geometry'] = []
used_aperture = '0' used_aperture = '0'
try: if self.is_lpc is True:
self.apertures[used_aperture]['solid_geometry'].append(region) try:
except KeyError: self.apertures[used_aperture]['clear_geometry'].append(region)
self.apertures[used_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[used_aperture]['solid_geometry'].append(region) self.apertures[used_aperture]['clear_geometry'] = []
self.apertures[used_aperture]['clear_geometry'].append(region)
else:
try:
self.apertures[used_aperture]['solid_geometry'].append(region)
except KeyError:
self.apertures[used_aperture]['solid_geometry'] = []
self.apertures[used_aperture]['solid_geometry'].append(region)
path = [[current_x, current_y]] # Start new path path = [[current_x, current_y]] # Start new path
continue continue
@ -2653,11 +2701,18 @@ class Gerber (Geometry):
geo = shply_box(minx, miny, maxx, maxy) geo = shply_box(minx, miny, maxx, maxy)
poly_buffer.append(geo) poly_buffer.append(geo)
try: if self.is_lpc is True:
self.apertures[current_aperture]['solid_geometry'].append(geo) try:
except KeyError: self.apertures[current_aperture]['clear_geometry'].append(geo)
self.apertures[current_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[current_aperture]['solid_geometry'].append(geo) self.apertures[current_aperture]['clear_geometry'] = []
self.apertures[current_aperture]['clear_geometry'].append(geo)
else:
try:
self.apertures[current_aperture]['solid_geometry'].append(geo)
except KeyError:
self.apertures[current_aperture]['solid_geometry'] = []
self.apertures[current_aperture]['solid_geometry'].append(geo)
except: except:
pass pass
last_path_aperture = current_aperture last_path_aperture = current_aperture
@ -2742,19 +2797,33 @@ class Gerber (Geometry):
if self.apertures[last_path_aperture]["type"] != 'R': if self.apertures[last_path_aperture]["type"] != 'R':
if not geo.is_empty: if not geo.is_empty:
poly_buffer.append(geo) poly_buffer.append(geo)
try: if self.is_lpc is True:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) try:
except KeyError: self.apertures[last_path_aperture]['clear_geometry'].append(geo)
self.apertures[last_path_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) self.apertures[last_path_aperture]['clear_geometry'] = []
self.apertures[last_path_aperture]['clear_geometry'].append(geo)
else:
try:
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except KeyError:
self.apertures[last_path_aperture]['solid_geometry'] = []
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except Exception as e: except Exception as e:
log.debug("camlib.Gerber.parse_lines() --> %s" % str(e)) log.debug("camlib.Gerber.parse_lines() --> %s" % str(e))
poly_buffer.append(geo) poly_buffer.append(geo)
try: if self.is_lpc is True:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) try:
except KeyError: self.apertures[last_path_aperture]['clear_geometry'].append(geo)
self.apertures[last_path_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) self.apertures[last_path_aperture]['clear_geometry'] = []
self.apertures[last_path_aperture]['clear_geometry'].append(geo)
else:
try:
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except KeyError:
self.apertures[last_path_aperture]['solid_geometry'] = []
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
# if linear_x or linear_y are None, ignore those # if linear_x or linear_y are None, ignore those
if linear_x is not None and linear_y is not None: if linear_x is not None and linear_y is not None:
@ -2797,18 +2866,32 @@ class Gerber (Geometry):
try: try:
if self.apertures[last_path_aperture]["type"] != 'R': if self.apertures[last_path_aperture]["type"] != 'R':
poly_buffer.append(geo) poly_buffer.append(geo)
if self.is_lpc is True:
try:
self.apertures[last_path_aperture]['clear_geometry'].append(geo)
except KeyError:
self.apertures[last_path_aperture]['clear_geometry'] = []
self.apertures[last_path_aperture]['clear_geometry'].append(geo)
else:
try:
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except KeyError:
self.apertures[last_path_aperture]['solid_geometry'] = []
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except:
poly_buffer.append(geo)
if self.is_lpc is True:
try:
self.apertures[last_path_aperture]['clear_geometry'].append(geo)
except KeyError:
self.apertures[last_path_aperture]['clear_geometry'] = []
self.apertures[last_path_aperture]['clear_geometry'].append(geo)
else:
try: try:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except KeyError: except KeyError:
self.apertures[last_path_aperture]['solid_geometry'] = [] self.apertures[last_path_aperture]['solid_geometry'] = []
self.apertures[last_path_aperture]['solid_geometry'].append(geo) self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except:
poly_buffer.append(geo)
try:
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except KeyError:
self.apertures[last_path_aperture]['solid_geometry'] = []
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
# Reset path starting point # Reset path starting point
path = [[linear_x, linear_y]] path = [[linear_x, linear_y]]
@ -2832,11 +2915,18 @@ class Gerber (Geometry):
) )
if not flash.is_empty: if not flash.is_empty:
poly_buffer.append(flash) poly_buffer.append(flash)
try: if self.is_lpc is True:
self.apertures[current_aperture]['solid_geometry'].append(flash) try:
except KeyError: self.apertures[current_aperture]['clear_geometry'].append(flash)
self.apertures[current_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[current_aperture]['solid_geometry'].append(flash) self.apertures[current_aperture]['clear_geometry'] = []
self.apertures[current_aperture]['clear_geometry'].append(flash)
else:
try:
self.apertures[current_aperture]['solid_geometry'].append(flash)
except KeyError:
self.apertures[current_aperture]['solid_geometry'] = []
self.apertures[current_aperture]['solid_geometry'].append(flash)
# maybe those lines are not exactly needed but it is easier to read the program as those coordinates # maybe those lines are not exactly needed but it is easier to read the program as those coordinates
# are used in case that circular interpolation is encountered within the Gerber file # are used in case that circular interpolation is encountered within the Gerber file
@ -2931,11 +3021,18 @@ class Gerber (Geometry):
buffered = LineString(path).buffer(width / 1.999, int(self.steps_per_circle)) buffered = LineString(path).buffer(width / 1.999, int(self.steps_per_circle))
if not buffered.is_empty: if not buffered.is_empty:
poly_buffer.append(buffered) poly_buffer.append(buffered)
try: if self.is_lpc is True:
self.apertures[last_path_aperture]['solid_geometry'].append(buffered) try:
except KeyError: self.apertures[last_path_aperture]['clear_geometry'].append(buffered)
self.apertures[last_path_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[last_path_aperture]['solid_geometry'].append(buffered) self.apertures[last_path_aperture]['clear_geometry'] = []
self.apertures[last_path_aperture]['clear_geometry'].append(buffered)
else:
try:
self.apertures[last_path_aperture]['solid_geometry'].append(buffered)
except KeyError:
self.apertures[last_path_aperture]['solid_geometry'] = []
self.apertures[last_path_aperture]['solid_geometry'].append(buffered)
current_x = circular_x current_x = circular_x
current_y = circular_y current_y = circular_y
@ -3068,11 +3165,18 @@ class Gerber (Geometry):
geo = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4)) geo = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
if not geo.is_empty: if not geo.is_empty:
poly_buffer.append(geo) poly_buffer.append(geo)
try: if self.is_lpc is True:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) try:
except KeyError: self.apertures[last_path_aperture]['clear_geometry'].append(geo)
self.apertures[last_path_aperture]['solid_geometry'] = [] except KeyError:
self.apertures[last_path_aperture]['solid_geometry'].append(geo) self.apertures[last_path_aperture]['clear_geometry'] = []
self.apertures[last_path_aperture]['clear_geometry'].append(geo)
else:
try:
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
except KeyError:
self.apertures[last_path_aperture]['solid_geometry'] = []
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
# --- Apply buffer --- # --- Apply buffer ---

View File

@ -1896,6 +1896,20 @@ class FlatCAMGrbEditor(QtCore.QObject):
follow_storage_elem = [] follow_storage_elem = []
self.storage_dict[apid] = {} self.storage_dict[apid] = {}
# first check if we have any clear_geometry (LPC) and if yes then we need to substract it
# from the solid_geometry
temp_geo = []
if 'clear_geometry' in self.gerber_obj.apertures[apid]:
for clear_geo in self.gerber_obj.apertures[apid]['clear_geometry']:
for solid_geo in self.gerber_obj.apertures[apid]['solid_geometry']:
if solid_geo.intersects(clear_geo):
res_geo = clear_geo.symmetric_difference(solid_geo)
temp_geo.append(res_geo)
else:
temp_geo.append(solid_geo)
self.gerber_obj.apertures[apid]['solid_geometry'] = deepcopy(temp_geo)
# add the Gerber geometry to editor storage
for k, v in self.gerber_obj.apertures[apid].items(): for k, v in self.gerber_obj.apertures[apid].items():
try: try:
if k == 'solid_geometry': if k == 'solid_geometry':