- Allowed the opening of certain types of damaged Gerber files (apertures not defines but used) but WARNINGS

This commit is contained in:
Marius Stanciu
2023-06-08 22:50:37 +03:00
parent 24806b3116
commit 598650d41e
4 changed files with 40 additions and 12 deletions

View File

@@ -10,6 +10,7 @@ CHANGELOG for FlatCAM Evo beta
8.06.2023
- Gerber Parser: minor changes, cleaning up the KiCAD junk lines if the Gerber file is made by KiCAD
- Allowed the opening of certain types of damaged Gerber files (apertures not defines but used) but WARNINGS
7.06.2023

View File

@@ -2055,12 +2055,20 @@ class AppIO(QtCore.QObject):
# # ## Object creation # ##
ret_val = self.app.app_obj.new_object("gerber", name, obj_init, autoselected=False, plot=plot)
if ret_val == "defective":
message = '[ERROR] %s' % \
_('The Gerber file is DAMAGED. We could open it but the file parsing PARTIALLY FAILED.\n'
'!!! CHECK THE FILE !!! --- SOME copper features (pads, traces etc) ARE MISSING !!!\n'
'!!! CHECK THE FILE !!! --- SOME copper features (pads, traces etc) ARE MISSING !!!\n'
'!!! CHECK THE FILE !!! --- SOME copper features (pads, traces etc) ARE MISSING !!!\n')
self.inform.emit(message)
return
if ret_val == 'fail':
if from_tcl:
filename = self.options['global_tcl_path'] + '/' + name
ret_val = self.app.app_obj.new_object("gerber", name, obj_init, autoselected=False, plot=plot)
if ret_val == 'fail':
self.inform.emit('[ERROR_NOTCL]%s' % _('Open Gerber failed. Probable not a Gerber file.'))
self.inform.emit('[ERROR_NOTCL] %s' % _('Open Gerber failed. Probable not a Gerber file.'))
return 'fail'
# Register recent file

View File

@@ -225,6 +225,9 @@ class AppObject(QtCore.QObject):
callback_params = []
self.object_created.emit(obj, obj_plot, obj_autoselected, callback, callback_params)
if return_value == "defective":
return "defective"
return obj
def on_object_created(self, obj, plot, auto_select, callback, callback_params):

View File

@@ -235,6 +235,9 @@ class Gerber(Geometry):
# in a Gerber file (normal or obsolete ones)
self.conversion_done = False
# Flag to detect if an aperture is used without definition
self.defective_aperture_detected = False
self.use_buffer_for_union = self.app.options["gerber_use_buffer_for_union"]
# Attributes to be included in serialization
@@ -383,6 +386,8 @@ class Gerber(Geometry):
if ret_val == 'fail':
return 'fail'
elif ret_val == "defective":
return "defective"
elif ret_val == 'drill':
return 'drill_gx2'
else:
@@ -687,11 +692,12 @@ class Gerber(Geometry):
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 there is a match, else not an AM, carry on.
@@ -733,7 +739,7 @@ class Gerber(Geometry):
# self.opcode_re = re.compile(r'^D0?([123])\*$')
# ################################################################
match = self.opcode_re.search(gline)
if match:
if match and current_aperture != "failure":
current_operation_code = int(match.group(1))
current_d = current_operation_code
@@ -775,6 +781,7 @@ class Gerber(Geometry):
# ################################################################
# ################ Tool/aperture change ########################
# ################ Example: D12* ########################
# self.tool_re = re.compile(r'^(?:G54)?D(\d\d+)\*$')
# ################################################################
match = self.tool_re.search(gline)
if match:
@@ -789,6 +796,12 @@ class Gerber(Geometry):
if current_aperture in self.tools and self.tools[current_aperture]["type"] != "AM":
if self.tools[current_aperture]["size"] == 0:
self.tools[current_aperture]["size"] = 10 ** -self.decimals
# if the detected aperture is not detected already then it means that we have a
if current_aperture not in self.tools:
current_aperture = "failure"
self.defective_aperture_detected = True
# self.app.log.debug(self.tools[current_aperture])
# Take care of the current path with the previous tool
@@ -835,7 +848,7 @@ class Gerber(Geometry):
# ################################################################
# ################ G36* - Begin region ########################
# ################################################################
if self.regionon_re.search(gline):
if self.regionon_re.search(gline) and current_aperture != "failure":
try:
path_length = len(path)
except TypeError:
@@ -909,7 +922,7 @@ class Gerber(Geometry):
# ################################################################
# ################ G37* - End region ########################
# ################################################################
if self.regionoff_re.search(gline):
if self.regionoff_re.search(gline) and current_aperture != "failure":
making_region = False
if 0 not in self.tools:
@@ -966,7 +979,7 @@ class Gerber(Geometry):
# path = [[current_x, current_y]]
continue
# For regions we may ignore an aperture that is None
# For Gerber regions, we may ignore an aperture that is None
# --- Buffered ---
geo_dict = {}
@@ -1075,7 +1088,7 @@ class Gerber(Geometry):
# REGEX: r'^(?:G0?(1))?(?:X(-?\d+))?(?:Y(-?\d+))?(?:D0([123]))?\*$'
# ################################################################
match = self.lin_re.search(gline)
if match:
if match and current_aperture != "failure":
# Dxx alone?
# if match.group(1) is None and match.group(2) is None and match.group(3) is None:
# try:
@@ -1118,9 +1131,7 @@ class Gerber(Geometry):
# treat the case when there is a flash inside a Gerber Region when the current_aperture
# is None
if current_aperture is None:
pass
else:
if current_aperture is not None:
# --- BUFFERED ---
# Draw the flash
# this treats the case when we are storing geometry as paths
@@ -1192,6 +1203,8 @@ class Gerber(Geometry):
self.tools[current_aperture]['geometry'].append(geo_dict)
except Exception:
pass
if current_aperture != "failure":
last_path_aperture = current_aperture
# we do this for the case that a region is done without having defined any aperture
if last_path_aperture is None:
@@ -1434,7 +1447,7 @@ class Gerber(Geometry):
# ######### X, Y coords are the coords of the End Point #########
# ################################################################
match = self.circ_re.search(gline)
if match:
if match and current_aperture != "failure":
arcdir = [None, None, "cw", "ccw"]
mode, circular_x, circular_y, i, j, d = match.groups()
@@ -1788,6 +1801,9 @@ class Gerber(Geometry):
# init this for the following operations
self.conversion_done = False
if self.defective_aperture_detected:
return "defective"
except Exception as err:
ex_type, ex, tb = sys.exc_info()
traceback.print_tb(tb)