- rewrited the Gerber Parser in camlib - success
- moved the self.apertures[aperture]['geometry'] processing for clear_geometry (geometry made with Gerber LPC command) in Gerber Editor
This commit is contained in:
@@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
|
|||||||
|
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
|
15.05.2019
|
||||||
|
|
||||||
|
- rewrited the Gerber Parser in camlib - success
|
||||||
|
- moved the self.apertures[aperture]['geometry'] processing for clear_geometry (geometry made with Gerber LPC command) in Gerber Editor
|
||||||
|
|
||||||
12.05.2019
|
12.05.2019
|
||||||
|
|
||||||
- some modifications to ToolCutout
|
- some modifications to ToolCutout
|
||||||
|
|||||||
616
camlib.py
616
camlib.py
@@ -2175,8 +2175,11 @@ class Gerber (Geometry):
|
|||||||
# store the file units here:
|
# store the file units here:
|
||||||
gerber_units = 'IN'
|
gerber_units = 'IN'
|
||||||
|
|
||||||
# this is for temporary storage of geometry until it is added to poly_buffer
|
# this is for temporary storage of solid geometry until it is added to poly_buffer
|
||||||
geo = None
|
geo_s = None
|
||||||
|
|
||||||
|
# this is for temporary storage of follow geometry until it is added to follow_buffer
|
||||||
|
geo_f = None
|
||||||
|
|
||||||
# Polygons are stored here until there is a change in polarity.
|
# Polygons are stored here until there is a change in polarity.
|
||||||
# Only then they are combined via cascaded_union and added or
|
# Only then they are combined via cascaded_union and added or
|
||||||
@@ -2204,6 +2207,8 @@ class Gerber (Geometry):
|
|||||||
previous_x = None
|
previous_x = None
|
||||||
previous_y = None
|
previous_y = None
|
||||||
|
|
||||||
|
current_d = None
|
||||||
|
|
||||||
# Absolute or Relative/Incremental coordinates
|
# Absolute or Relative/Incremental coordinates
|
||||||
# Not implemented
|
# Not implemented
|
||||||
absolute = True
|
absolute = True
|
||||||
@@ -2226,20 +2231,21 @@ class Gerber (Geometry):
|
|||||||
try:
|
try:
|
||||||
for gline in glines:
|
for gline in glines:
|
||||||
line_num += 1
|
line_num += 1
|
||||||
|
|
||||||
self.source_file += gline + '\n'
|
self.source_file += gline + '\n'
|
||||||
|
|
||||||
### Cleanup
|
# Cleanup #
|
||||||
gline = gline.strip(' \r\n')
|
gline = gline.strip(' \r\n')
|
||||||
# log.debug("Line=%3s %s" % (line_num, gline))
|
# log.debug("Line=%3s %s" % (line_num, gline))
|
||||||
|
|
||||||
#### Ignored lines
|
# ###############################################################
|
||||||
## Comments
|
# Ignored lines #
|
||||||
|
# Comments ######
|
||||||
|
# ###############################################################
|
||||||
match = self.comm_re.search(gline)
|
match = self.comm_re.search(gline)
|
||||||
if match:
|
if match:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### Polarity change
|
# Polarity change ########
|
||||||
# Example: %LPD*% or %LPC*%
|
# Example: %LPD*% or %LPC*%
|
||||||
# If polarity changes, creates geometry from current
|
# If polarity changes, creates geometry from current
|
||||||
# buffer, then adds or subtracts accordingly.
|
# buffer, then adds or subtracts accordingly.
|
||||||
@@ -2248,30 +2254,31 @@ class Gerber (Geometry):
|
|||||||
new_polarity = match.group(1)
|
new_polarity = match.group(1)
|
||||||
# log.info("Polarity CHANGE, LPC = %s, poly_buff = %s" % (self.is_lpc, poly_buffer))
|
# log.info("Polarity CHANGE, LPC = %s, poly_buff = %s" % (self.is_lpc, poly_buffer))
|
||||||
self.is_lpc = True if new_polarity == 'C' else False
|
self.is_lpc = True if new_polarity == 'C' else False
|
||||||
|
|
||||||
if len(path) > 1 and current_polarity != new_polarity:
|
if len(path) > 1 and current_polarity != new_polarity:
|
||||||
|
|
||||||
# finish the current path and add it to the storage
|
# finish the current path and add it to the storage
|
||||||
# --- Buffered ----
|
# --- Buffered ----
|
||||||
width = self.apertures[last_path_aperture]["size"]
|
width = self.apertures[last_path_aperture]["size"]
|
||||||
|
|
||||||
|
|
||||||
geo_f = LineString(path)
|
|
||||||
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
|
||||||
follow_buffer.append(geo_f)
|
|
||||||
poly_buffer.append(geo_s)
|
|
||||||
|
|
||||||
geo_dict = dict()
|
geo_dict = dict()
|
||||||
geo_dict['follow'] = geo_f
|
geo_f = LineString(path)
|
||||||
if self.is_lpc:
|
if not geo_f.is_empty:
|
||||||
geo_dict['clear'] = geo_s
|
follow_buffer.append(geo_f)
|
||||||
else:
|
geo_dict['follow'] = geo_f
|
||||||
geo_dict['solid'] = geo_s
|
|
||||||
try:
|
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
if not geo_s.is_empty:
|
||||||
except KeyError:
|
poly_buffer.append(geo_s)
|
||||||
|
if self.is_lpc is True:
|
||||||
|
geo_dict['clear'] = geo_s
|
||||||
|
else:
|
||||||
|
geo_dict['solid'] = geo_s
|
||||||
|
|
||||||
|
if last_path_aperture not in self.apertures:
|
||||||
|
self.apertures[last_path_aperture] = dict()
|
||||||
|
if 'geometry' not in self.apertures[last_path_aperture]:
|
||||||
self.apertures[last_path_aperture]['geometry'] = []
|
self.apertures[last_path_aperture]['geometry'] = []
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
self.apertures[last_path_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||||
|
|
||||||
path = [path[-1]]
|
path = [path[-1]]
|
||||||
|
|
||||||
@@ -2293,8 +2300,10 @@ class Gerber (Geometry):
|
|||||||
current_polarity = new_polarity
|
current_polarity = new_polarity
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### Number format
|
# ###############################################################
|
||||||
|
# Number format ##################
|
||||||
# Example: %FSLAX24Y24*%
|
# Example: %FSLAX24Y24*%
|
||||||
|
# ###############################################################
|
||||||
# TODO: This is ignoring most of the format. Implement the rest.
|
# TODO: This is ignoring most of the format. Implement the rest.
|
||||||
match = self.fmt_re.search(gline)
|
match = self.fmt_re.search(gline)
|
||||||
if match:
|
if match:
|
||||||
@@ -2320,7 +2329,9 @@ class Gerber (Geometry):
|
|||||||
self.convert_units(match.group(1))
|
self.convert_units(match.group(1))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### Combined Number format and Mode --- Allegro does this
|
# ###############################################################
|
||||||
|
# Combined Number format and Mode --- Allegro does this #########
|
||||||
|
# ###############################################################
|
||||||
match = self.fmt_re_alt.search(gline)
|
match = self.fmt_re_alt.search(gline)
|
||||||
if match:
|
if match:
|
||||||
absolute = {'A': 'Absolute', 'I': 'Relative'}[match.group(2)]
|
absolute = {'A': 'Absolute', 'I': 'Relative'}[match.group(2)]
|
||||||
@@ -2339,7 +2350,9 @@ class Gerber (Geometry):
|
|||||||
self.convert_units(match.group(5))
|
self.convert_units(match.group(5))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### Search for OrCAD way for having Number format
|
# ###############################################################
|
||||||
|
# Search for OrCAD way for having Number format
|
||||||
|
# ###############################################################
|
||||||
match = self.fmt_re_orcad.search(gline)
|
match = self.fmt_re_orcad.search(gline)
|
||||||
if match:
|
if match:
|
||||||
if match.group(1) is not None:
|
if match.group(1) is not None:
|
||||||
@@ -2363,7 +2376,9 @@ class Gerber (Geometry):
|
|||||||
self.convert_units(match.group(5))
|
self.convert_units(match.group(5))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### Units (G70/1) OBSOLETE
|
# ###############################################################
|
||||||
|
# Units (G70/1) OBSOLETE
|
||||||
|
# ###############################################################
|
||||||
match = self.units_re.search(gline)
|
match = self.units_re.search(gline)
|
||||||
if match:
|
if match:
|
||||||
obs_gerber_units = {'0': 'IN', '1': 'MM'}[match.group(1)]
|
obs_gerber_units = {'0': 'IN', '1': 'MM'}[match.group(1)]
|
||||||
@@ -2372,17 +2387,21 @@ class Gerber (Geometry):
|
|||||||
self.convert_units({'0': 'IN', '1': 'MM'}[match.group(1)])
|
self.convert_units({'0': 'IN', '1': 'MM'}[match.group(1)])
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### Absolute/relative coordinates G90/1 OBSOLETE
|
# ###############################################################
|
||||||
|
# Absolute/relative coordinates G90/1 OBSOLETE ##########
|
||||||
|
# #######################################################
|
||||||
match = self.absrel_re.search(gline)
|
match = self.absrel_re.search(gline)
|
||||||
if match:
|
if match:
|
||||||
absolute = {'0': "Absolute", '1': "Relative"}[match.group(1)]
|
absolute = {'0': "Absolute", '1': "Relative"}[match.group(1)]
|
||||||
log.warning("Gerber obsolete coordinates type found = %s (Absolute or Relative) " % absolute)
|
log.warning("Gerber obsolete coordinates type found = %s (Absolute or Relative) " % absolute)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### Aperture Macros
|
# ###############################################################
|
||||||
|
# Aperture Macros #######################################
|
||||||
# Having this at the beginning will slow things down
|
# Having this at the beginning will slow things down
|
||||||
# but macros can have complicated statements than could
|
# but macros can have complicated statements than could
|
||||||
# be caught by other patterns.
|
# be caught by other patterns.
|
||||||
|
# ###############################################################
|
||||||
if current_macro is None: # No macro started yet
|
if current_macro is None: # No macro started yet
|
||||||
match = self.am1_re.search(gline)
|
match = self.am1_re.search(gline)
|
||||||
# Start macro if match, else not an AM, carry on.
|
# Start macro if match, else not an AM, carry on.
|
||||||
@@ -2416,49 +2435,51 @@ class Gerber (Geometry):
|
|||||||
self.aperture_parse(match.group(1), match.group(2), match.group(3))
|
self.aperture_parse(match.group(1), match.group(2), match.group(3))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### Operation code alone
|
# ###############################################################
|
||||||
|
# Operation code alone ########################
|
||||||
# Operation code alone, usually just D03 (Flash)
|
# Operation code alone, usually just D03 (Flash)
|
||||||
# self.opcode_re = re.compile(r'^D0?([123])\*$')
|
# self.opcode_re = re.compile(r'^D0?([123])\*$')
|
||||||
|
# ###############################################################
|
||||||
match = self.opcode_re.search(gline)
|
match = self.opcode_re.search(gline)
|
||||||
if match:
|
if match:
|
||||||
current_operation_code = int(match.group(1))
|
current_operation_code = int(match.group(1))
|
||||||
|
current_d = current_operation_code
|
||||||
|
|
||||||
if current_operation_code == 3:
|
if current_operation_code == 3:
|
||||||
|
|
||||||
## --- Buffered ---
|
# --- Buffered ---
|
||||||
try:
|
try:
|
||||||
log.debug("Bare op-code %d." % current_operation_code)
|
log.debug("Bare op-code %d." % current_operation_code)
|
||||||
# flash = Gerber.create_flash_geometry(Point(path[-1]),
|
|
||||||
# self.apertures[current_aperture])
|
geo_dict = dict()
|
||||||
flash = Gerber.create_flash_geometry(
|
flash = Gerber.create_flash_geometry(
|
||||||
Point(current_x, current_y), self.apertures[current_aperture],
|
Point(current_x, current_y), self.apertures[current_aperture],
|
||||||
int(self.steps_per_circle))
|
int(self.steps_per_circle))
|
||||||
|
|
||||||
if not flash.is_empty:
|
geo_dict['follow'] = Point([current_x, current_y])
|
||||||
geo_f = Point(current_x, current_y)
|
|
||||||
geo_s = flash
|
|
||||||
# follow_buffer.append(geo_f)
|
|
||||||
poly_buffer.append(geo_s)
|
|
||||||
|
|
||||||
geo_dict = dict()
|
if not flash.is_empty:
|
||||||
geo_dict['follow'] = geo_f
|
poly_buffer.append(flash)
|
||||||
if self.is_lpc:
|
if self.is_lpc is True:
|
||||||
geo_dict['clear'] = geo_s
|
geo_dict['clear'] = flash
|
||||||
else:
|
else:
|
||||||
geo_dict['solid'] = geo_s
|
geo_dict['solid'] = flash
|
||||||
try:
|
|
||||||
self.apertures[current_aperture]['geometry'].append(geo_dict)
|
if last_path_aperture not in self.apertures:
|
||||||
except KeyError:
|
self.apertures[current_aperture] = dict()
|
||||||
|
if 'geometry' not in self.apertures[current_aperture]:
|
||||||
self.apertures[current_aperture]['geometry'] = []
|
self.apertures[current_aperture]['geometry'] = []
|
||||||
self.apertures[current_aperture]['geometry'].append(geo_dict)
|
self.apertures[current_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||||
|
|
||||||
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))
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### Tool/aperture change
|
# ###############################################################
|
||||||
|
# Tool/aperture change
|
||||||
# Example: D12*
|
# Example: D12*
|
||||||
|
# ###############################################################
|
||||||
match = self.tool_re.search(gline)
|
match = self.tool_re.search(gline)
|
||||||
if match:
|
if match:
|
||||||
current_aperture = match.group(1)
|
current_aperture = match.group(1)
|
||||||
@@ -2475,96 +2496,134 @@ class Gerber (Geometry):
|
|||||||
|
|
||||||
# Take care of the current path with the previous tool
|
# Take care of the current path with the previous tool
|
||||||
if len(path) > 1:
|
if len(path) > 1:
|
||||||
if self.apertures[last_path_aperture]["type"] != 'R':
|
if self.apertures[last_path_aperture]["type"] == 'R':
|
||||||
width = self.apertures[last_path_aperture]["size"]
|
# do nothing because 'R' type moving aperture is none at once
|
||||||
|
pass
|
||||||
geo_f = LineString(path)
|
else:
|
||||||
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
|
||||||
follow_buffer.append(geo_f)
|
|
||||||
poly_buffer.append(geo_s)
|
|
||||||
|
|
||||||
geo_dict = dict()
|
geo_dict = dict()
|
||||||
geo_dict['follow'] = geo_f
|
geo_f = LineString(path)
|
||||||
if self.is_lpc:
|
if not geo_f.is_empty:
|
||||||
geo_dict['clear'] = geo_s
|
follow_buffer.append(geo_f)
|
||||||
else:
|
geo_dict['follow'] = geo_f
|
||||||
geo_dict['solid'] = geo_s
|
|
||||||
try:
|
# --- Buffered ----
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
width = self.apertures[last_path_aperture]["size"]
|
||||||
except KeyError:
|
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
||||||
|
if not geo_s.is_empty:
|
||||||
|
poly_buffer.append(geo_s)
|
||||||
|
if self.is_lpc is True:
|
||||||
|
geo_dict['clear'] = geo_s
|
||||||
|
else:
|
||||||
|
geo_dict['solid'] = geo_s
|
||||||
|
|
||||||
|
if last_path_aperture not in self.apertures:
|
||||||
|
self.apertures[last_path_aperture] = dict()
|
||||||
|
if 'geometry' not in self.apertures[last_path_aperture]:
|
||||||
self.apertures[last_path_aperture]['geometry'] = []
|
self.apertures[last_path_aperture]['geometry'] = []
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
self.apertures[last_path_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||||
|
|
||||||
path = [path[-1]]
|
path = [path[-1]]
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### G36* - Begin region
|
# ###############################################################
|
||||||
|
# G36* - Begin region
|
||||||
|
# ###############################################################
|
||||||
if self.regionon_re.search(gline):
|
if self.regionon_re.search(gline):
|
||||||
if '0' not in self.apertures:
|
|
||||||
self.apertures['0'] = {}
|
|
||||||
self.apertures['0']['type'] = 'REG'
|
|
||||||
self.apertures['0']['size'] = 0.0
|
|
||||||
self.apertures['0']['geometry'] = []
|
|
||||||
last_path_aperture = '0'
|
|
||||||
self.apertures[last_path_aperture]['type'] = 'REG'
|
|
||||||
|
|
||||||
if len(path) > 1:
|
if len(path) > 1:
|
||||||
# Take care of what is left in the path
|
# Take care of what is left in the path
|
||||||
width = self.apertures[last_path_aperture]["size"]
|
|
||||||
|
|
||||||
geo_f = LineString(path)
|
|
||||||
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
|
||||||
follow_buffer.append(geo_f)
|
|
||||||
poly_buffer.append(geo_s)
|
|
||||||
|
|
||||||
geo_dict = dict()
|
geo_dict = dict()
|
||||||
geo_dict['follow'] = geo_f
|
geo_f = LineString(path)
|
||||||
if self.is_lpc:
|
if not geo_f.is_empty:
|
||||||
geo_dict['clear'] = geo_s
|
follow_buffer.append(geo_f)
|
||||||
else:
|
geo_dict['follow'] = geo_f
|
||||||
geo_dict['solid'] = geo_s
|
|
||||||
|
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
# --- Buffered ----
|
||||||
|
width = self.apertures[last_path_aperture]["size"]
|
||||||
|
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
||||||
|
if not geo_s.is_empty:
|
||||||
|
poly_buffer.append(geo_s)
|
||||||
|
if self.is_lpc is True:
|
||||||
|
geo_dict['clear'] = geo_s
|
||||||
|
else:
|
||||||
|
geo_dict['solid'] = geo_s
|
||||||
|
|
||||||
|
if last_path_aperture not in self.apertures:
|
||||||
|
self.apertures[last_path_aperture] = dict()
|
||||||
|
if 'geometry' not in self.apertures[last_path_aperture]:
|
||||||
|
self.apertures[last_path_aperture]['geometry'] = []
|
||||||
|
self.apertures[last_path_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||||
|
|
||||||
path = [path[-1]]
|
path = [path[-1]]
|
||||||
|
|
||||||
making_region = True
|
making_region = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
### G37* - End region
|
# ###############################################################
|
||||||
|
# G37* - End region
|
||||||
|
# ###############################################################
|
||||||
if self.regionoff_re.search(gline):
|
if self.regionoff_re.search(gline):
|
||||||
making_region = False
|
making_region = False
|
||||||
|
|
||||||
|
if '0' not in self.apertures:
|
||||||
|
self.apertures['0'] = {}
|
||||||
|
self.apertures['0']['type'] = 'REG'
|
||||||
|
self.apertures['0']['size'] = 0.0
|
||||||
|
self.apertures['0']['geometry'] = []
|
||||||
|
|
||||||
# if D02 happened before G37 we now have a path with 1 element only so we have to add the current
|
# if D02 happened before G37 we now have a path with 1 element only so we have to add the current
|
||||||
# geo to the poly_buffer otherwise we loose it
|
# geo to the poly_buffer otherwise we loose it
|
||||||
# if current_operation_code == 2:
|
# if current_operation_code == 2:
|
||||||
|
# print(path)
|
||||||
|
# geo_dict = dict()
|
||||||
|
# if geo_f:
|
||||||
|
# if not geo_f.is_empty:
|
||||||
|
# follow_buffer.append(geo_f)
|
||||||
|
# geo_dict['follow'] = geo_f
|
||||||
|
# if geo_s:
|
||||||
|
# if not geo_s.is_empty:
|
||||||
|
# poly_buffer.append(geo_s)
|
||||||
|
# if self.is_lpc is True:
|
||||||
|
# geo_dict['clear'] = geo_s
|
||||||
|
# else:
|
||||||
|
# geo_dict['solid'] = geo_s
|
||||||
|
#
|
||||||
|
# if geo_s or geo_f:
|
||||||
|
# self.apertures['0']['geometry'].append(deepcopy(geo_dict))
|
||||||
|
#
|
||||||
|
# continue
|
||||||
|
|
||||||
# Only one path defines region?
|
# Only one path defines region?
|
||||||
# This can happen if D02 happened before G37 and
|
# This can happen if D02 happened before G37 and
|
||||||
# is not an error.
|
# is not and error.
|
||||||
if len(path) < 3:
|
if len(path) < 3:
|
||||||
|
# print "ERROR: Path contains less than 3 points:"
|
||||||
|
#path = [[current_x, current_y]]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# usually the D02 will add the path to the geo but if there is no D02 before G37 here comes the
|
# For regions we may ignore an aperture that is None
|
||||||
# rescue
|
|
||||||
geo_f = LineString(path)
|
|
||||||
geo_s = Polygon(path)
|
|
||||||
|
|
||||||
if not geo_s.is_valid:
|
|
||||||
geo_s = geo_s.buffer(0, int(self.steps_per_circle / 4))
|
|
||||||
if not geo_s.is_empty:
|
|
||||||
poly_buffer.append(geo_s)
|
|
||||||
follow_buffer.append(geo_f)
|
|
||||||
|
|
||||||
|
# --- Buffered ---
|
||||||
geo_dict = dict()
|
geo_dict = dict()
|
||||||
geo_dict['follow'] = geo_f
|
region_f = Polygon(path).exterior
|
||||||
if not geo_s.is_empty:
|
if not region_f.is_empty:
|
||||||
if self.is_lpc:
|
follow_buffer.append(region_f)
|
||||||
geo_dict['clear'] = geo_s
|
geo_dict['follow'] = region_f
|
||||||
else:
|
|
||||||
geo_dict['solid'] = geo_s
|
|
||||||
|
|
||||||
self.apertures['0']['geometry'].append(geo_dict)
|
region_s = Polygon(path)
|
||||||
|
if not region_s.is_valid:
|
||||||
|
region_s = region_s.buffer(0, int(self.steps_per_circle / 4))
|
||||||
|
|
||||||
|
if not region_s.is_empty:
|
||||||
|
poly_buffer.append(region_s)
|
||||||
|
if self.is_lpc is True:
|
||||||
|
geo_dict['clear'] = region_s
|
||||||
|
else:
|
||||||
|
geo_dict['solid'] = region_s
|
||||||
|
|
||||||
|
if not region_s.is_empty or not region_f.is_empty:
|
||||||
|
self.apertures['0']['geometry'].append(deepcopy(geo_dict))
|
||||||
|
|
||||||
path = [[current_x, current_y]] # Start new path
|
path = [[current_x, current_y]] # Start new path
|
||||||
continue
|
continue
|
||||||
@@ -2593,18 +2652,6 @@ class Gerber (Geometry):
|
|||||||
# NOTE: Letting it continue allows it to react to the
|
# NOTE: Letting it continue allows it to react to the
|
||||||
# operation code.
|
# operation code.
|
||||||
|
|
||||||
if current_aperture is None or last_path_aperture is None:
|
|
||||||
if '0' not in self.apertures:
|
|
||||||
self.apertures['0'] = {}
|
|
||||||
self.apertures['0']['type'] = 'REG'
|
|
||||||
self.apertures['0']['size'] = 0.0
|
|
||||||
self.apertures['0']['geometry'] = []
|
|
||||||
if current_aperture is None:
|
|
||||||
current_aperture = '0'
|
|
||||||
else:
|
|
||||||
last_path_aperture = '0'
|
|
||||||
width = 0
|
|
||||||
|
|
||||||
# Parse coordinates
|
# Parse coordinates
|
||||||
if match.group(2) is not None:
|
if match.group(2) is not None:
|
||||||
linear_x = parse_gerber_number(match.group(2),
|
linear_x = parse_gerber_number(match.group(2),
|
||||||
@@ -2628,11 +2675,7 @@ class Gerber (Geometry):
|
|||||||
# if linear_x or linear_y are None, ignore those
|
# if linear_x or linear_y are None, ignore those
|
||||||
if current_x is not None and current_y is not None:
|
if current_x is not None and current_y is not None:
|
||||||
# only add the point if it's a new one otherwise skip it (harder to process)
|
# only add the point if it's a new one otherwise skip it (harder to process)
|
||||||
# but if it's the first point in the path in may create an exception
|
if path[-1] != [current_x, current_y]:
|
||||||
try:
|
|
||||||
if path[-1] != [current_x, current_y]:
|
|
||||||
path.append([current_x, current_y])
|
|
||||||
except IndexError:
|
|
||||||
path.append([current_x, current_y])
|
path.append([current_x, current_y])
|
||||||
|
|
||||||
if making_region is False:
|
if making_region is False:
|
||||||
@@ -2647,42 +2690,29 @@ class Gerber (Geometry):
|
|||||||
maxx = max(path[0][0], path[1][0]) + width / 2
|
maxx = max(path[0][0], path[1][0]) + width / 2
|
||||||
miny = min(path[0][1], path[1][1]) - height / 2
|
miny = min(path[0][1], path[1][1]) - height / 2
|
||||||
maxy = max(path[0][1], path[1][1]) + height / 2
|
maxy = max(path[0][1], path[1][1]) + height / 2
|
||||||
# log.debug("Coords: %s - %s - %s - %s" % (minx, miny, maxx, maxy))
|
log.debug("Coords: %s - %s - %s - %s" % (minx, miny, maxx, maxy))
|
||||||
|
|
||||||
r_x = maxx - minx
|
|
||||||
r_y = maxy - miny
|
|
||||||
geo_f = Point(r_x, r_y)
|
|
||||||
geo_s = shply_box(minx, miny, maxx, maxy)
|
|
||||||
follow_buffer.append(geo_f)
|
|
||||||
poly_buffer.append(geo_s)
|
|
||||||
|
|
||||||
geo_dict = dict()
|
geo_dict = dict()
|
||||||
|
geo_f = Point([current_x, current_y])
|
||||||
|
follow_buffer.append(geo_f)
|
||||||
geo_dict['follow'] = geo_f
|
geo_dict['follow'] = geo_f
|
||||||
if self.is_lpc:
|
|
||||||
|
geo_s = shply_box(minx, miny, maxx, maxy)
|
||||||
|
poly_buffer.append(geo_s)
|
||||||
|
if self.is_lpc is True:
|
||||||
geo_dict['clear'] = geo_s
|
geo_dict['clear'] = geo_s
|
||||||
else:
|
else:
|
||||||
geo_dict['solid'] = geo_s
|
geo_dict['solid'] = geo_s
|
||||||
try:
|
|
||||||
self.apertures[current_aperture]['geometry'].append(geo_dict)
|
if current_aperture not in self.apertures:
|
||||||
except KeyError:
|
self.apertures[current_aperture] = dict()
|
||||||
|
if 'geometry' not in self.apertures[current_aperture]:
|
||||||
self.apertures[current_aperture]['geometry'] = []
|
self.apertures[current_aperture]['geometry'] = []
|
||||||
self.apertures[current_aperture]['geometry'].append(geo_dict)
|
self.apertures[current_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
last_path_aperture = current_aperture
|
last_path_aperture = current_aperture
|
||||||
else:
|
# we do this for the case that a region is done without having defined any aperture
|
||||||
last_path_aperture = '0'
|
|
||||||
|
|
||||||
else:
|
|
||||||
self.app.inform.emit(_("[WARNING] Coordinates missing, line ignored: %s") % str(gline))
|
|
||||||
self.app.inform.emit(_("[WARNING_NOTCL] GERBER file might be CORRUPT. Check the file !!!"))
|
|
||||||
|
|
||||||
elif current_operation_code == 2:
|
|
||||||
# finish current path
|
|
||||||
if len(path) > 1:
|
|
||||||
geo_s = None
|
|
||||||
geo_f = None
|
|
||||||
|
|
||||||
if last_path_aperture is None:
|
if last_path_aperture is None:
|
||||||
if '0' not in self.apertures:
|
if '0' not in self.apertures:
|
||||||
self.apertures['0'] = {}
|
self.apertures['0'] = {}
|
||||||
@@ -2690,41 +2720,87 @@ class Gerber (Geometry):
|
|||||||
self.apertures['0']['size'] = 0.0
|
self.apertures['0']['size'] = 0.0
|
||||||
self.apertures['0']['geometry'] = []
|
self.apertures['0']['geometry'] = []
|
||||||
last_path_aperture = '0'
|
last_path_aperture = '0'
|
||||||
width = 0
|
else:
|
||||||
else:
|
self.app.inform.emit(_("[WARNING] Coordinates missing, line ignored: %s") % str(gline))
|
||||||
width = self.apertures[last_path_aperture]["size"]
|
self.app.inform.emit(_("[WARNING_NOTCL] GERBER file might be CORRUPT. Check the file !!!"))
|
||||||
|
|
||||||
|
elif current_operation_code == 2:
|
||||||
|
if len(path) > 1:
|
||||||
|
geo_s = None
|
||||||
|
geo_f = None
|
||||||
|
|
||||||
|
geo_dict = dict()
|
||||||
|
# --- BUFFERED ---
|
||||||
|
# this treats the case when we are storing geometry as paths only
|
||||||
if making_region:
|
if making_region:
|
||||||
|
# we do this for the case that a region is done without having defined any aperture
|
||||||
|
if last_path_aperture is None:
|
||||||
|
if '0' not in self.apertures:
|
||||||
|
self.apertures['0'] = {}
|
||||||
|
self.apertures['0']['type'] = 'REG'
|
||||||
|
self.apertures['0']['size'] = 0.0
|
||||||
|
self.apertures['0']['geometry'] = []
|
||||||
|
last_path_aperture = '0'
|
||||||
|
geo_f = Polygon()
|
||||||
|
else:
|
||||||
|
geo_f = LineString(path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self.apertures[last_path_aperture]["type"] != 'R':
|
||||||
|
if not geo_f.is_empty:
|
||||||
|
follow_buffer.append(geo_f)
|
||||||
|
geo_dict['follow'] = geo_f
|
||||||
|
except Exception as e:
|
||||||
|
log.debug("camlib.Gerber.parse_lines() --> %s" % str(e))
|
||||||
|
if not geo_f.is_empty:
|
||||||
|
follow_buffer.append(geo_f)
|
||||||
|
geo_dict['follow'] = geo_f
|
||||||
|
|
||||||
|
# this treats the case when we are storing geometry as solids
|
||||||
|
if making_region:
|
||||||
|
# we do this for the case that a region is done without having defined any aperture
|
||||||
|
if last_path_aperture is None:
|
||||||
|
if '0' not in self.apertures:
|
||||||
|
self.apertures['0'] = {}
|
||||||
|
self.apertures['0']['type'] = 'REG'
|
||||||
|
self.apertures['0']['size'] = 0.0
|
||||||
|
self.apertures['0']['geometry'] = []
|
||||||
|
last_path_aperture = '0'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
geo_s = Polygon(path)
|
geo_s = Polygon(path)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
log.warning(
|
log.warning("Problem %s %s" % (gline, line_num))
|
||||||
"Not enough points in path to create a Polygon %s %s" % (gline, line_num))
|
self.app.inform.emit(_("[ERROR] Region does not have enough points. "
|
||||||
try:
|
"File will be processed but there are parser errors. "
|
||||||
geo_f = LineString(path)
|
"Line number: %s") % str(line_num))
|
||||||
except ValueError:
|
|
||||||
log.warning(
|
|
||||||
"Not enough points in path to create a LineString %s %s" % (gline, line_num))
|
|
||||||
else:
|
else:
|
||||||
|
if last_path_aperture is None:
|
||||||
|
log.warning("No aperture defined for curent path. (%d)" % line_num)
|
||||||
|
width = self.apertures[last_path_aperture]["size"] # TODO: WARNING this should fail!
|
||||||
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
||||||
geo_f = LineString(path)
|
|
||||||
|
|
||||||
if self.apertures[last_path_aperture]["type"] != 'R':
|
try:
|
||||||
poly_buffer.append(deepcopy(geo_s))
|
if self.apertures[last_path_aperture]["type"] != 'R':
|
||||||
follow_buffer.append(deepcopy(geo_f))
|
if not geo_s.is_empty:
|
||||||
|
poly_buffer.append(geo_s)
|
||||||
|
if self.is_lpc is True:
|
||||||
|
geo_dict['clear'] = geo_s
|
||||||
|
else:
|
||||||
|
geo_dict['solid'] = geo_s
|
||||||
|
except Exception as e:
|
||||||
|
log.debug("camlib.Gerber.parse_lines() --> %s" % str(e))
|
||||||
|
poly_buffer.append(geo_s)
|
||||||
|
if self.is_lpc is True:
|
||||||
|
geo_dict['clear'] = geo_s
|
||||||
|
else:
|
||||||
|
geo_dict['solid'] = geo_s
|
||||||
|
|
||||||
geo_dict = dict()
|
if last_path_aperture not in self.apertures:
|
||||||
geo_dict['follow'] = geo_f
|
self.apertures[last_path_aperture] = dict()
|
||||||
if geo_s:
|
if 'geometry' not in self.apertures[last_path_aperture]:
|
||||||
if self.is_lpc:
|
self.apertures[last_path_aperture]['geometry'] = []
|
||||||
geo_dict['clear'] = deepcopy(geo_s)
|
self.apertures[last_path_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||||
else:
|
|
||||||
geo_dict['solid'] = deepcopy(geo_s)
|
|
||||||
try:
|
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
|
||||||
except KeyError:
|
|
||||||
self.apertures[last_path_aperture]['geometry'] = []
|
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
|
||||||
|
|
||||||
# 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:
|
||||||
@@ -2737,52 +2813,76 @@ class Gerber (Geometry):
|
|||||||
# Not allowed in region mode.
|
# Not allowed in region mode.
|
||||||
elif current_operation_code == 3:
|
elif current_operation_code == 3:
|
||||||
|
|
||||||
width = self.apertures[last_path_aperture]["size"]
|
# Create path draw so far.
|
||||||
# finish the path draw until now
|
if len(path) > 1:
|
||||||
if len(path) > 1 and self.apertures[last_path_aperture]["type"] != 'R':
|
# --- Buffered ----
|
||||||
|
|
||||||
geo_f = LineString(path)
|
|
||||||
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
|
||||||
follow_buffer.append(geo_f)
|
|
||||||
poly_buffer.append(geo_s)
|
|
||||||
|
|
||||||
geo_dict = dict()
|
geo_dict = dict()
|
||||||
geo_dict['follow'] = geo_f
|
|
||||||
if self.is_lpc:
|
# this treats the case when we are storing geometry as paths
|
||||||
geo_dict['clear'] = geo_s
|
geo_f = LineString(path)
|
||||||
else:
|
if not geo_f.is_empty:
|
||||||
geo_dict['solid'] = geo_s
|
try:
|
||||||
try:
|
if self.apertures[last_path_aperture]["type"] != 'R':
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
follow_buffer.append(geo_f)
|
||||||
except KeyError:
|
geo_dict['follow'] = geo_f
|
||||||
|
except Exception as e:
|
||||||
|
log.debug("camlib.Gerber.parse_lines() --> G01 match D03 --> %s" % str(e))
|
||||||
|
follow_buffer.append(geo_f)
|
||||||
|
geo_dict['follow'] = geo_f
|
||||||
|
|
||||||
|
# this treats the case when we are storing geometry as solids
|
||||||
|
width = self.apertures[last_path_aperture]["size"]
|
||||||
|
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
||||||
|
if not geo_s.is_empty:
|
||||||
|
try:
|
||||||
|
if self.apertures[last_path_aperture]["type"] != 'R':
|
||||||
|
poly_buffer.append(geo_s)
|
||||||
|
if self.is_lpc is True:
|
||||||
|
geo_dict['clear'] = geo_s
|
||||||
|
else:
|
||||||
|
geo_dict['solid'] = geo_s
|
||||||
|
except:
|
||||||
|
poly_buffer.append(geo_s)
|
||||||
|
if self.is_lpc is True:
|
||||||
|
geo_dict['clear'] = geo_s
|
||||||
|
else:
|
||||||
|
geo_dict['solid'] = geo_s
|
||||||
|
|
||||||
|
if last_path_aperture not in self.apertures:
|
||||||
|
self.apertures[last_path_aperture] = dict()
|
||||||
|
if 'geometry' not in self.apertures[last_path_aperture]:
|
||||||
self.apertures[last_path_aperture]['geometry'] = []
|
self.apertures[last_path_aperture]['geometry'] = []
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
self.apertures[last_path_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||||
|
|
||||||
# Reset path starting point
|
# Reset path starting point
|
||||||
path = [[linear_x, linear_y]]
|
path = [[linear_x, linear_y]]
|
||||||
|
|
||||||
|
# --- BUFFERED ---
|
||||||
# Draw the flash
|
# Draw the flash
|
||||||
geo_f = Point(linear_x, linear_y)
|
# this treats the case when we are storing geometry as paths
|
||||||
geo_s = Gerber.create_flash_geometry(
|
geo_dict = dict()
|
||||||
Point([linear_x, linear_y]),
|
geo_flash = Point([linear_x, linear_y])
|
||||||
|
follow_buffer.append(geo_flash)
|
||||||
|
geo_dict['follow'] = geo_flash
|
||||||
|
|
||||||
|
# this treats the case when we are storing geometry as solids
|
||||||
|
flash = Gerber.create_flash_geometry(
|
||||||
|
Point( [linear_x, linear_y]),
|
||||||
self.apertures[current_aperture],
|
self.apertures[current_aperture],
|
||||||
int(self.steps_per_circle)
|
int(self.steps_per_circle)
|
||||||
)
|
)
|
||||||
follow_buffer.append(geo_f)
|
if not flash.is_empty:
|
||||||
if not geo_s.is_empty:
|
poly_buffer.append(flash)
|
||||||
poly_buffer.append(geo_s)
|
if self.is_lpc is True:
|
||||||
|
geo_dict['clear'] = flash
|
||||||
geo_dict = dict()
|
|
||||||
geo_dict['follow'] = geo_f
|
|
||||||
if not geo_s.is_empty:
|
|
||||||
if self.is_lpc:
|
|
||||||
geo_dict['clear'] = geo_s
|
|
||||||
else:
|
else:
|
||||||
geo_dict['solid'] = geo_s
|
geo_dict['solid'] = flash
|
||||||
try:
|
|
||||||
self.apertures[current_aperture]['geometry'].append(geo_dict)
|
if current_aperture not in self.apertures:
|
||||||
except KeyError:
|
self.apertures[current_aperture] = dict()
|
||||||
|
if 'geometry' not in self.apertures[current_aperture]:
|
||||||
self.apertures[current_aperture]['geometry'] = []
|
self.apertures[current_aperture]['geometry'] = []
|
||||||
self.apertures[current_aperture]['geometry'].append(geo_dict)
|
self.apertures[current_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||||
|
|
||||||
# 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
|
||||||
@@ -2853,41 +2953,35 @@ class Gerber (Geometry):
|
|||||||
# Nothing created! Pen Up.
|
# Nothing created! Pen Up.
|
||||||
if current_operation_code == 2:
|
if current_operation_code == 2:
|
||||||
log.warning("Arc with D2. (%d)" % line_num)
|
log.warning("Arc with D2. (%d)" % line_num)
|
||||||
|
|
||||||
# if we have something drawn until this moment, add it
|
|
||||||
if len(path) > 1:
|
if len(path) > 1:
|
||||||
# if last_path_aperture is None:
|
geo_dict = dict()
|
||||||
# log.warning("No aperture defined for curent path. (%d)" % line_num)
|
|
||||||
if last_path_aperture is None:
|
if last_path_aperture is None:
|
||||||
if '0' not in self.apertures:
|
log.warning("No aperture defined for curent path. (%d)" % line_num)
|
||||||
self.apertures['0'] = {}
|
|
||||||
self.apertures['0']['type'] = 'REG'
|
|
||||||
self.apertures['0']['size'] = 0.0
|
|
||||||
self.apertures['0']['geometry'] = []
|
|
||||||
last_path_aperture = '0'
|
|
||||||
width = 0
|
|
||||||
|
|
||||||
# --- BUFFERED ---
|
# --- BUFFERED ---
|
||||||
width = self.apertures[last_path_aperture]["size"]
|
width = self.apertures[last_path_aperture]["size"]
|
||||||
|
|
||||||
|
# this treats the case when we are storing geometry as paths
|
||||||
geo_f = LineString(path)
|
geo_f = LineString(path)
|
||||||
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
if not geo_f.is_empty:
|
||||||
if not geo_s.is_empty:
|
|
||||||
follow_buffer.append(geo_f)
|
follow_buffer.append(geo_f)
|
||||||
poly_buffer.append(geo_s)
|
geo_dict['follow'] = geo_f
|
||||||
|
|
||||||
geo_dict = dict()
|
# this treats the case when we are storing geometry as solids
|
||||||
geo_dict['follow'] = geo_f
|
buffered = LineString(path).buffer(width / 1.999, int(self.steps_per_circle))
|
||||||
if not geo_s.is_empty:
|
if not buffered.is_empty:
|
||||||
if self.is_lpc:
|
poly_buffer.append(buffered)
|
||||||
geo_dict['clear'] = geo_s
|
if self.is_lpc is True:
|
||||||
|
geo_dict['clear'] = buffered
|
||||||
else:
|
else:
|
||||||
geo_dict['solid'] = geo_s
|
geo_dict['solid'] = buffered
|
||||||
try:
|
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
if last_path_aperture not in self.apertures:
|
||||||
except KeyError:
|
self.apertures[last_path_aperture] = dict()
|
||||||
|
if 'geometry' not in self.apertures[last_path_aperture]:
|
||||||
self.apertures[last_path_aperture]['geometry'] = []
|
self.apertures[last_path_aperture]['geometry'] = []
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
self.apertures[last_path_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||||
|
|
||||||
current_x = circular_x
|
current_x = circular_x
|
||||||
current_y = circular_y
|
current_y = circular_y
|
||||||
@@ -2998,28 +3092,42 @@ class Gerber (Geometry):
|
|||||||
# In case that G01 (moving) aperture is rectangular, there is no need to still create
|
# In case that G01 (moving) aperture is rectangular, there is no need to still create
|
||||||
# another geo since we already created a shapely box using the start and end coordinates found in
|
# another geo since we already created a shapely box using the start and end coordinates found in
|
||||||
# path variable. We do it only for other apertures than 'R' type
|
# path variable. We do it only for other apertures than 'R' type
|
||||||
if self.apertures[last_path_aperture]["type"] != 'R':
|
if self.apertures[last_path_aperture]["type"] == 'R':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
# EOF, create shapely LineString if something still in path
|
# EOF, create shapely LineString if something still in path
|
||||||
width = self.apertures[last_path_aperture]["size"]
|
## --- Buffered ---
|
||||||
|
|
||||||
geo_f = LineString(path)
|
|
||||||
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
|
||||||
follow_buffer.append(geo_f)
|
|
||||||
if not geo_s.is_empty:
|
|
||||||
poly_buffer.append(geo_s)
|
|
||||||
|
|
||||||
geo_dict = dict()
|
geo_dict = dict()
|
||||||
geo_dict['follow'] = geo_f
|
# this treats the case when we are storing geometry as paths
|
||||||
|
geo_f = LineString(path)
|
||||||
|
if not geo_f.is_empty:
|
||||||
|
follow_buffer.append(geo_f)
|
||||||
|
geo_dict['follow'] = geo_f
|
||||||
|
|
||||||
|
# this treats the case when we are storing geometry as solids
|
||||||
|
width = self.apertures[last_path_aperture]["size"]
|
||||||
|
geo_s = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
|
||||||
if not geo_s.is_empty:
|
if not geo_s.is_empty:
|
||||||
if self.is_lpc:
|
poly_buffer.append(geo_s)
|
||||||
|
if self.is_lpc is True:
|
||||||
geo_dict['clear'] = geo_s
|
geo_dict['clear'] = geo_s
|
||||||
else:
|
else:
|
||||||
geo_dict['solid'] = geo_s
|
geo_dict['solid'] = geo_s
|
||||||
try:
|
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
if last_path_aperture not in self.apertures:
|
||||||
except KeyError:
|
self.apertures[last_path_aperture] = dict()
|
||||||
|
if 'geometry' not in self.apertures[last_path_aperture]:
|
||||||
self.apertures[last_path_aperture]['geometry'] = []
|
self.apertures[last_path_aperture]['geometry'] = []
|
||||||
self.apertures[last_path_aperture]['geometry'].append(geo_dict)
|
self.apertures[last_path_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||||
|
|
||||||
|
# TODO: make sure to keep track of units changes because right now it seems to happen in a weird way
|
||||||
|
# find out the conversion factor used to convert inside the self.apertures keys: size, width, height
|
||||||
|
file_units = gerber_units if gerber_units else 'IN'
|
||||||
|
app_units = self.app.defaults['units']
|
||||||
|
|
||||||
|
conversion_factor = 25.4 if file_units == 'IN' else (1/25.4) if file_units != app_units else 1
|
||||||
|
|
||||||
|
|
||||||
# --- Apply buffer ---
|
# --- Apply buffer ---
|
||||||
# this treats the case when we are storing geometry as paths
|
# this treats the case when we are storing geometry as paths
|
||||||
@@ -3028,6 +3136,9 @@ class Gerber (Geometry):
|
|||||||
# this treats the case when we are storing geometry as solids
|
# this treats the case when we are storing geometry as solids
|
||||||
log.warning("Joining %d polygons." % len(poly_buffer))
|
log.warning("Joining %d polygons." % len(poly_buffer))
|
||||||
|
|
||||||
|
for td in self.apertures:
|
||||||
|
print(td, self.apertures[td])
|
||||||
|
|
||||||
if len(poly_buffer) == 0:
|
if len(poly_buffer) == 0:
|
||||||
log.error("Object is not Gerber file or empty. Aborting Object creation.")
|
log.error("Object is not Gerber file or empty. Aborting Object creation.")
|
||||||
return 'fail'
|
return 'fail'
|
||||||
@@ -3283,6 +3394,15 @@ class Gerber (Geometry):
|
|||||||
|
|
||||||
self.app.inform.emit(_("[success] Gerber Scale done."))
|
self.app.inform.emit(_("[success] Gerber Scale done."))
|
||||||
|
|
||||||
|
|
||||||
|
## solid_geometry ???
|
||||||
|
# It's a cascaded union of objects.
|
||||||
|
# self.solid_geometry = affinity.scale(self.solid_geometry, factor,
|
||||||
|
# factor, origin=(0, 0))
|
||||||
|
|
||||||
|
# # Now buffered_paths, flash_geometry and solid_geometry
|
||||||
|
# self.create_geometry()
|
||||||
|
|
||||||
def offset(self, vect):
|
def offset(self, vect):
|
||||||
"""
|
"""
|
||||||
Offsets the objects' geometry on the XY plane by a given vector.
|
Offsets the objects' geometry on the XY plane by a given vector.
|
||||||
|
|||||||
@@ -3245,46 +3245,56 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("FlatCAMGrbEditor.edit_fcgerber() --> %s" % str(e))
|
log.debug("FlatCAMGrbEditor.edit_fcgerber() --> %s" % str(e))
|
||||||
|
|
||||||
|
# ###############################################################
|
||||||
|
# APPLY CLEAR_GEOMETRY on the SOLID_GEOMETRY
|
||||||
|
# ###############################################################
|
||||||
|
|
||||||
# # --- the following section is useful for Gerber editor only --- #
|
|
||||||
# log.warning("Applying clear geometry in the apertures dict.")
|
# log.warning("Applying clear geometry in the apertures dict.")
|
||||||
# # list of clear geos that are to be applied to the entire file
|
# list of clear geos that are to be applied to the entire file
|
||||||
# global_clear_geo = []
|
global_clear_geo = []
|
||||||
#
|
|
||||||
# for apid in self.apertures:
|
|
||||||
# if 'geometry' in self.apertures[apid]:
|
|
||||||
# for elem in self.apertures[apid]['geometry']:
|
|
||||||
# if 'clear' in elem:
|
|
||||||
# global_clear_geo.append(elem['clear'])
|
|
||||||
# log.warning("Found %d clear polygons." % len(global_clear_geo))
|
|
||||||
#
|
|
||||||
# for apid in self.apertures:
|
|
||||||
# geo_list = []
|
|
||||||
# if 'geometry' in self.apertures[apid]:
|
|
||||||
# for elem in self.apertures[apid]['geometry']:
|
|
||||||
# if 'solid' in elem:
|
|
||||||
# for clear_geo in global_clear_geo:
|
|
||||||
# new_elem = dict()
|
|
||||||
# # Make sure that the clear_geo is within the solid_geo otherwise we loose
|
|
||||||
# # the solid_geometry. We want for clear_geometry just to cut into solid_geometry not to
|
|
||||||
# # delete it
|
|
||||||
# if clear_geo.within(elem['solid']):
|
|
||||||
# new_elem['solid'] = elem['solid'].difference(clear_geo)
|
|
||||||
# else:
|
|
||||||
# new_elem['solid'] = elem['solid']
|
|
||||||
# if 'follow' in elem:
|
|
||||||
# new_elem['follow'] = elem['follow']
|
|
||||||
# if 'clear' in elem:
|
|
||||||
# new_elem['clear'] = elem['clear']
|
|
||||||
# geo_list.append(deepcopy(new_elem))
|
|
||||||
# self.apertures[apid]['geometry'] = deepcopy(geo_list)
|
|
||||||
# geo_list[:] = []
|
|
||||||
#
|
|
||||||
# log.warning("Polygon difference done for %d apertures." % len(self.apertures))
|
|
||||||
|
|
||||||
|
for apid in self.gerber_obj.apertures:
|
||||||
|
# first check if we have any clear_geometry (LPC) and if yes added it to the global_clear_geo
|
||||||
|
if 'geometry' in self.gerber_obj.apertures[apid]:
|
||||||
|
for elem in self.gerber_obj.apertures[apid]['geometry']:
|
||||||
|
if 'clear' in elem:
|
||||||
|
global_clear_geo.append(elem['clear'])
|
||||||
|
log.warning("Found %d clear polygons." % len(global_clear_geo))
|
||||||
|
|
||||||
|
for apid in self.gerber_obj.apertures:
|
||||||
|
temp_elem = []
|
||||||
|
if 'geometry' in self.gerber_obj.apertures[apid]:
|
||||||
|
for elem in self.gerber_obj.apertures[apid]['geometry']:
|
||||||
|
if 'solid' in elem:
|
||||||
|
solid_geo = elem['solid']
|
||||||
|
for clear_geo in global_clear_geo:
|
||||||
|
# Make sure that the clear_geo is within the solid_geo otherwise we loose
|
||||||
|
# the solid_geometry. We want for clear_geometry just to cut into solid_geometry not to
|
||||||
|
# delete it
|
||||||
|
if clear_geo.within(solid_geo):
|
||||||
|
solid_geo = solid_geo.difference(clear_geo)
|
||||||
|
try:
|
||||||
|
for poly in solid_geo:
|
||||||
|
new_elem = dict()
|
||||||
|
|
||||||
|
new_elem['solid'] = poly
|
||||||
|
if 'clear' in elem:
|
||||||
|
new_elem['clear'] = poly
|
||||||
|
if 'follow' in elem:
|
||||||
|
new_elem['follow'] = poly
|
||||||
|
temp_elem.append(deepcopy(new_elem))
|
||||||
|
except TypeError:
|
||||||
|
new_elem = dict()
|
||||||
|
new_elem['solid'] = solid_geo
|
||||||
|
if 'clear' in elem:
|
||||||
|
new_elem['clear'] = solid_geo
|
||||||
|
if 'follow' in elem:
|
||||||
|
new_elem['follow'] = solid_geo
|
||||||
|
temp_elem.append(deepcopy(new_elem))
|
||||||
|
self.gerber_obj.apertures[apid]['geometry'] = deepcopy(temp_elem)
|
||||||
|
log.warning("Polygon difference done for %d apertures." % len(self.gerber_obj.apertures))
|
||||||
|
|
||||||
# and then add it to the storage elements (each storage elements is a member of a list
|
# and then add it to the storage elements (each storage elements is a member of a list
|
||||||
|
|
||||||
def job_thread(self, apid):
|
def job_thread(self, apid):
|
||||||
with self.app.proc_container.new(_("Adding aperture: %s geo ...") % str(apid)):
|
with self.app.proc_container.new(_("Adding aperture: %s geo ...") % str(apid)):
|
||||||
storage_elem = []
|
storage_elem = []
|
||||||
@@ -3404,30 +3414,33 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||||||
for storage_apid, storage_val in local_storage_dict.items():
|
for storage_apid, storage_val in local_storage_dict.items():
|
||||||
grb_obj.apertures[storage_apid] = {}
|
grb_obj.apertures[storage_apid] = {}
|
||||||
|
|
||||||
for k, v in storage_val.items():
|
for k, val in storage_val.items():
|
||||||
if k == 'geometry':
|
if k == 'geometry':
|
||||||
grb_obj.apertures[storage_apid][k] = []
|
grb_obj.apertures[storage_apid][k] = []
|
||||||
for geo_el in v:
|
for geo_el in val:
|
||||||
new_geo = dict()
|
|
||||||
geometric_data = geo_el.geo
|
geometric_data = geo_el.geo
|
||||||
for key in geometric_data:
|
|
||||||
if key == 'solid':
|
|
||||||
new_geo[key] = geometric_data['solid']
|
|
||||||
poly_buffer.append(deepcopy(new_geo['solid']))
|
|
||||||
if key == 'follow':
|
|
||||||
if isinstance(geometric_data[key], Polygon):
|
|
||||||
buff_val = -(int(storage_apid) / 2)
|
|
||||||
geo_f = geo_el.geo.buffer(buff_val).exterior
|
|
||||||
new_geo[key] = geo_f
|
|
||||||
else:
|
|
||||||
new_geo[key] = geometric_data[key]
|
|
||||||
follow_buffer.append(deepcopy(new_geo['follow']))
|
|
||||||
if key == 'clear':
|
|
||||||
new_geo[key] = geometric_data['clear']
|
|
||||||
|
|
||||||
grb_obj.apertures[storage_apid][k].append(deepcopy(new_geo))
|
new_geo_el = dict()
|
||||||
|
if 'solid' in geometric_data:
|
||||||
|
new_geo_el['solid'] = geometric_data['solid']
|
||||||
|
poly_buffer.append(deepcopy(new_geo_el['solid']))
|
||||||
|
|
||||||
|
if 'follow' in geometric_data:
|
||||||
|
if isinstance(geometric_data['follow'], Polygon):
|
||||||
|
buff_val = -(int(storage_apid) / 2)
|
||||||
|
geo_f = (geometric_data['follow'].buffer(buff_val)).exterior
|
||||||
|
new_geo_el['follow'] = geo_f
|
||||||
|
else:
|
||||||
|
new_geo_el['follow'] = geometric_data['follow']
|
||||||
|
follow_buffer.append(deepcopy(new_geo_el['follow']))
|
||||||
|
|
||||||
|
if 'clear' in geometric_data:
|
||||||
|
new_geo_el['clear'] = geometric_data['clear']
|
||||||
|
|
||||||
|
if new_geo_el:
|
||||||
|
grb_obj.apertures[storage_apid][k].append(deepcopy(new_geo_el))
|
||||||
else:
|
else:
|
||||||
grb_obj.apertures[storage_apid][k] = v
|
grb_obj.apertures[storage_apid][k] = val
|
||||||
|
|
||||||
grb_obj.aperture_macros = deepcopy(self.gerber_obj.aperture_macros)
|
grb_obj.aperture_macros = deepcopy(self.gerber_obj.aperture_macros)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user