- PDF Import tool: added support for detection of circular geometry drawn with white color which means actually invisible color. When detected, FlatCAM will build an Excellon file out of those geoms.
- PDF Import tool: fixed storing geometries in apertures with the right size (before they were all stored in aperture D10)
This commit is contained in:
parent
d66d914cc3
commit
82a0287f4d
|
@ -95,7 +95,7 @@ class App(QtCore.QObject):
|
||||||
|
|
||||||
# Version
|
# Version
|
||||||
version = 8.914
|
version = 8.914
|
||||||
version_date = "2019/04/22"
|
version_date = "2019/04/23"
|
||||||
beta = True
|
beta = True
|
||||||
|
|
||||||
# current date now
|
# current date now
|
||||||
|
|
|
@ -16,7 +16,8 @@ CAD program, and create G-Code for Isolation routing.
|
||||||
- PDF import tool: added support for save/restore Graphics stack. Only for scale and offset transformations and for the linewidth. This is the final fix for Microsoft PDF printer who saves in PDF format 1.7
|
- PDF import tool: added support for save/restore Graphics stack. Only for scale and offset transformations and for the linewidth. This is the final fix for Microsoft PDF printer who saves in PDF format 1.7
|
||||||
- PDF Import tool: added support for PDF files that embed multiple Gerber layers (top, bottom, outline, silkscreen etc). Each will be opened in it's own Gerber file. The requirement is that each one is drawn in a different color
|
- PDF Import tool: added support for PDF files that embed multiple Gerber layers (top, bottom, outline, silkscreen etc). Each will be opened in it's own Gerber file. The requirement is that each one is drawn in a different color
|
||||||
- PDF Import tool: fixed bugs when drag & dropping PDF files on canvas the files geometry previously opened was added to the new one. Also scaling issues. Solved.
|
- PDF Import tool: fixed bugs when drag & dropping PDF files on canvas the files geometry previously opened was added to the new one. Also scaling issues. Solved.
|
||||||
|
- PDF Import tool: added support for detection of circular geometry drawn with white color which means actually invisible color. When detected, FlatCAM will build an Excellon file out of those geoms.
|
||||||
|
- PDF Import tool: fixed storing geometries in apertures with the right size (before they were all stored in aperture D10)
|
||||||
|
|
||||||
21.04.2019
|
21.04.2019
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,12 @@ class ToolPDF(FlatCAMTool):
|
||||||
|
|
||||||
self.stream_re = re.compile(b'.*?FlateDecode.*?stream(.*?)endstream', re.S)
|
self.stream_re = re.compile(b'.*?FlateDecode.*?stream(.*?)endstream', re.S)
|
||||||
|
|
||||||
# detect color change; it means a new object to be created
|
# detect stroke color change; it means a new object to be created
|
||||||
self.color_re = re.compile(r'^\s*(\d+\.?\d*) (\d+\.?\d*) (\d+\.?\d*)\s*RG$')
|
self.stroke_color_re = re.compile(r'^\s*(\d+\.?\d*) (\d+\.?\d*) (\d+\.?\d*)\s*RG$')
|
||||||
|
|
||||||
|
# detect fill color change; we check here for white color (transparent geometry);
|
||||||
|
# if detected we create an Excellon from it
|
||||||
|
self.fill_color_re = re.compile(r'^\s*(\d+\.?\d*) (\d+\.?\d*) (\d+\.?\d*)\s*rg$')
|
||||||
|
|
||||||
# detect 're' command
|
# detect 're' command
|
||||||
self.rect_re = re.compile(r'^(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s*re$')
|
self.rect_re = re.compile(r'^(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s*re$')
|
||||||
|
@ -104,6 +108,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
|
|
||||||
self.obj_dict = dict()
|
self.obj_dict = dict()
|
||||||
self.pdf_parsed = ''
|
self.pdf_parsed = ''
|
||||||
|
self.parsed_obj_dict = dict()
|
||||||
|
|
||||||
# conversion factor to INCH
|
# conversion factor to INCH
|
||||||
self.point_to_unit_factor = 0.01388888888
|
self.point_to_unit_factor = 0.01388888888
|
||||||
|
@ -151,6 +156,8 @@ class ToolPDF(FlatCAMTool):
|
||||||
new_name = filename.split('/')[-1].split('\\')[-1]
|
new_name = filename.split('/')[-1].split('\\')[-1]
|
||||||
self.obj_dict.clear()
|
self.obj_dict.clear()
|
||||||
self.pdf_parsed = ''
|
self.pdf_parsed = ''
|
||||||
|
self.parsed_obj_dict = {}
|
||||||
|
obj_type = 'gerber'
|
||||||
|
|
||||||
# the UNITS in PDF files are points and here we set the factor to convert them to real units (either MM or INCH)
|
# the UNITS in PDF files are points and here we set the factor to convert them to real units (either MM or INCH)
|
||||||
if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
|
if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
|
||||||
|
@ -174,11 +181,66 @@ class ToolPDF(FlatCAMTool):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("ToolPDF.open_pdf().obj_init() --> %s" % str(e))
|
log.debug("ToolPDF.open_pdf().obj_init() --> %s" % str(e))
|
||||||
|
|
||||||
self.obj_dict = self.parse_pdf(pdf_content=self.pdf_parsed)
|
self.parsed_obj_dict = self.parse_pdf(pdf_content=self.pdf_parsed)
|
||||||
|
|
||||||
for k in self.obj_dict:
|
for k in self.parsed_obj_dict:
|
||||||
ap_dict = deepcopy(self.obj_dict[k])
|
ap_dict = deepcopy(self.parsed_obj_dict[k])
|
||||||
if ap_dict:
|
if ap_dict:
|
||||||
|
if k == 0:
|
||||||
|
# Excellon
|
||||||
|
obj_type = 'excellon'
|
||||||
|
|
||||||
|
new_name = new_name + "_exc"
|
||||||
|
# store the points here until reconstitution: keys are diameters and values are list of (x,y) coords
|
||||||
|
points = {}
|
||||||
|
|
||||||
|
def obj_init(exc_obj, app_obj):
|
||||||
|
# print(self.parsed_obj_dict[0])
|
||||||
|
|
||||||
|
for geo in self.parsed_obj_dict[0]['0']['solid_geometry']:
|
||||||
|
xmin, ymin, xmax, ymax = geo.bounds
|
||||||
|
center = (((xmax - xmin) / 2) + xmin, ((ymax - ymin) / 2) + ymin)
|
||||||
|
|
||||||
|
# for drill bits, even in INCH, it's enough 3 decimals
|
||||||
|
correction_factor = 0.974
|
||||||
|
dia = (xmax - xmin) * correction_factor
|
||||||
|
dia = round(dia, 3)
|
||||||
|
if dia in points:
|
||||||
|
points[dia].append(center)
|
||||||
|
else:
|
||||||
|
points[dia] = [center]
|
||||||
|
|
||||||
|
sorted_dia = sorted(points.keys())
|
||||||
|
|
||||||
|
name_tool = 0
|
||||||
|
for dia in sorted_dia:
|
||||||
|
name_tool += 1
|
||||||
|
|
||||||
|
# create tools dictionary
|
||||||
|
spec = {"C": dia}
|
||||||
|
spec['solid_geometry'] = []
|
||||||
|
exc_obj.tools[str(name_tool)] = spec
|
||||||
|
|
||||||
|
# create drill list of dictionaries
|
||||||
|
for dia_points in points:
|
||||||
|
if dia == dia_points:
|
||||||
|
for pt in points[dia_points]:
|
||||||
|
exc_obj.drills.append({'point': Point(pt), 'tool': str(name_tool)})
|
||||||
|
break
|
||||||
|
|
||||||
|
ret = exc_obj.create_geometry()
|
||||||
|
if ret == 'fail':
|
||||||
|
log.debug("Could not create geometry for Excellon object.")
|
||||||
|
return "fail"
|
||||||
|
for tool in exc_obj.tools:
|
||||||
|
if exc_obj.tools[tool]['solid_geometry']:
|
||||||
|
return
|
||||||
|
app_obj.inform.emit(_("[ERROR_NOTCL] No geometry found in file: %s") % new_name)
|
||||||
|
return "fail"
|
||||||
|
else:
|
||||||
|
# Gerber
|
||||||
|
obj_type = 'gerber'
|
||||||
|
|
||||||
def obj_init(grb_obj, app_obj):
|
def obj_init(grb_obj, app_obj):
|
||||||
|
|
||||||
grb_obj.apertures = ap_dict
|
grb_obj.apertures = ap_dict
|
||||||
|
@ -190,21 +252,25 @@ class ToolPDF(FlatCAMTool):
|
||||||
poly_buff += ap_dict[ap][k]
|
poly_buff += ap_dict[ap][k]
|
||||||
|
|
||||||
poly_buff = unary_union(poly_buff)
|
poly_buff = unary_union(poly_buff)
|
||||||
|
try:
|
||||||
poly_buff = poly_buff.buffer(0.0000001)
|
poly_buff = poly_buff.buffer(0.0000001)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
poly_buff = poly_buff.buffer(-0.0000001)
|
poly_buff = poly_buff.buffer(-0.0000001)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
grb_obj.solid_geometry = deepcopy(poly_buff)
|
grb_obj.solid_geometry = deepcopy(poly_buff)
|
||||||
|
|
||||||
with self.app.proc_container.new(_("Opening PDF layer #%d ...") % (int(k) - 2)):
|
with self.app.proc_container.new(_("Rendering PDF layer #%d ...") % (int(k) - 2)):
|
||||||
|
|
||||||
ret = self.app.new_object("gerber", new_name, obj_init, autoselected=False)
|
ret = self.app.new_object(obj_type, new_name, obj_init, autoselected=False)
|
||||||
if ret == 'fail':
|
if ret == 'fail':
|
||||||
self.app.inform.emit(_('[ERROR_NOTCL] Open PDF file failed.'))
|
self.app.inform.emit(_('[ERROR_NOTCL] Open PDF file failed.'))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Register recent file
|
# Register recent file
|
||||||
self.app.file_opened.emit("gerber", filename)
|
self.app.file_opened.emit(obj_type, filename)
|
||||||
|
|
||||||
# GUI feedback
|
# GUI feedback
|
||||||
self.app.inform.emit(_("[success] Opened: %s") % filename)
|
self.app.inform.emit(_("[success] Opened: %s") % filename)
|
||||||
|
|
||||||
|
@ -233,9 +299,6 @@ class ToolPDF(FlatCAMTool):
|
||||||
offset_geo = [0, 0]
|
offset_geo = [0, 0]
|
||||||
scale_geo = [1, 1]
|
scale_geo = [1, 1]
|
||||||
|
|
||||||
# initial aperture
|
|
||||||
aperture = 10
|
|
||||||
|
|
||||||
# store the objects to be transformed into Gerbers
|
# store the objects to be transformed into Gerbers
|
||||||
object_dict = {}
|
object_dict = {}
|
||||||
|
|
||||||
|
@ -245,14 +308,29 @@ class ToolPDF(FlatCAMTool):
|
||||||
# store the apertures here
|
# store the apertures here
|
||||||
apertures_dict = {}
|
apertures_dict = {}
|
||||||
|
|
||||||
|
# initial aperture
|
||||||
|
aperture = 10
|
||||||
|
|
||||||
|
# store the apertures with clear geometry here
|
||||||
|
# we are interested only in the circular geometry (drill holes) therefore we target only Bezier subpaths
|
||||||
|
clear_apertures_dict = dict()
|
||||||
|
# everything will be stored in the '0' aperture since we are dealing with clear polygons not strokes
|
||||||
|
clear_apertures_dict['0'] = dict()
|
||||||
|
clear_apertures_dict['0']['size'] = 0.0
|
||||||
|
clear_apertures_dict['0']['type'] = 'C'
|
||||||
|
clear_apertures_dict['0']['solid_geometry'] = []
|
||||||
|
|
||||||
# create first object
|
# create first object
|
||||||
object_dict[object_nr] = apertures_dict
|
object_dict[object_nr] = apertures_dict
|
||||||
object_nr += 1
|
object_nr += 1
|
||||||
|
|
||||||
# on color change we create a new apertures dictionary and store the old one in a storage from where it will be
|
# on stroke color change we create a new apertures dictionary and store the old one in a storage from where
|
||||||
# transformed into Gerber object
|
# it will be transformed into Gerber object
|
||||||
old_color = [None, None ,None]
|
old_color = [None, None ,None]
|
||||||
|
|
||||||
|
# signal that we have clear geometry and the geometry will be added to a special object_nr = 0
|
||||||
|
flag_clear_geo = False
|
||||||
|
|
||||||
line_nr = 0
|
line_nr = 0
|
||||||
lines = pdf_content.splitlines()
|
lines = pdf_content.splitlines()
|
||||||
|
|
||||||
|
@ -261,9 +339,12 @@ class ToolPDF(FlatCAMTool):
|
||||||
# log.debug("line %d: %s" % (line_nr, pline))
|
# log.debug("line %d: %s" % (line_nr, pline))
|
||||||
|
|
||||||
# COLOR DETECTION / OBJECT DETECTION
|
# COLOR DETECTION / OBJECT DETECTION
|
||||||
match = self.color_re.search(pline)
|
match = self.stroke_color_re.search(pline)
|
||||||
if match:
|
if match:
|
||||||
color = [float(match.group(1)), float(match.group(2)), float(match.group(3))]
|
color = [float(match.group(1)), float(match.group(2)), float(match.group(3))]
|
||||||
|
log.debug(
|
||||||
|
"ToolPDF.parse_pdf() --> STROKE Color change on line: %s --> RED=%f GREEN=%f BLUE=%f" %
|
||||||
|
(line_nr, color[0], color[1], color[2]))
|
||||||
|
|
||||||
if color[0] == old_color[0] and color[1] == old_color[1] and color[2] == old_color[2]:
|
if color[0] == old_color[0] and color[1] == old_color[1] and color[2] == old_color[2]:
|
||||||
# same color, do nothing
|
# same color, do nothing
|
||||||
|
@ -271,9 +352,28 @@ class ToolPDF(FlatCAMTool):
|
||||||
else:
|
else:
|
||||||
object_dict[object_nr] = deepcopy(apertures_dict)
|
object_dict[object_nr] = deepcopy(apertures_dict)
|
||||||
object_nr += 1
|
object_nr += 1
|
||||||
|
|
||||||
object_dict[object_nr] = dict()
|
object_dict[object_nr] = dict()
|
||||||
apertures_dict.clear()
|
apertures_dict = {}
|
||||||
old_color = copy(color)
|
old_color = copy(color)
|
||||||
|
# we make sure that the following geometry is added to the right storage
|
||||||
|
flag_clear_geo = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
# CLEAR GEOMETRY detection
|
||||||
|
match = self.fill_color_re.search(pline)
|
||||||
|
if match:
|
||||||
|
fill_color = [float(match.group(1)), float(match.group(2)), float(match.group(3))]
|
||||||
|
log.debug(
|
||||||
|
"ToolPDF.parse_pdf() --> FILL Color change on line: %s --> RED=%f GREEN=%f BLUE=%f" %
|
||||||
|
(line_nr, fill_color[0], fill_color[1], fill_color[2]))
|
||||||
|
# if the color is white we are seeing 'clear_geometry' that can't be seen. It may be that those
|
||||||
|
# geometries are actually holes from which we can make an Excellon file
|
||||||
|
if fill_color[0] == 1 and fill_color[1] == 1 and fill_color[2] == 1:
|
||||||
|
flag_clear_geo = True
|
||||||
|
else:
|
||||||
|
flag_clear_geo = False
|
||||||
|
continue
|
||||||
|
|
||||||
# TRANSFORMATIONS DETECTION #
|
# TRANSFORMATIONS DETECTION #
|
||||||
|
|
||||||
|
@ -366,7 +466,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
# add the start point to subpaths
|
# add the start point to subpaths
|
||||||
subpath['lines'].append(start_point)
|
subpath['lines'].append(start_point)
|
||||||
# subpath['bezier'].append(start_point)
|
# subpath['bezier'].append(start_point)
|
||||||
subpath['rectangle'].append(start_point)
|
# subpath['rectangle'].append(start_point)
|
||||||
current_point = start_point
|
current_point = start_point
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -440,7 +540,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
current_point = stop
|
current_point = stop
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Draw Rectangle 're
|
# Draw Rectangle 're'
|
||||||
match = self.rect_re.search(pline)
|
match = self.rect_re.search(pline)
|
||||||
if match:
|
if match:
|
||||||
current_subpath = 'rectangle'
|
current_subpath = 'rectangle'
|
||||||
|
@ -454,7 +554,6 @@ class ToolPDF(FlatCAMTool):
|
||||||
pt2 = (x+width, y)
|
pt2 = (x+width, y)
|
||||||
pt3 = (x+width, y+height)
|
pt3 = (x+width, y+height)
|
||||||
pt4 = (x, y+height)
|
pt4 = (x, y+height)
|
||||||
# TODO: I'm not sure if rectangles are a type of subpath that close by itself
|
|
||||||
subpath['rectangle'] += [pt1, pt2, pt3, pt4, pt1]
|
subpath['rectangle'] += [pt1, pt2, pt3, pt4, pt1]
|
||||||
current_point = pt1
|
current_point = pt1
|
||||||
continue
|
continue
|
||||||
|
@ -491,7 +590,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
path['bezier'].append(copy(subpath['bezier']))
|
path['bezier'].append(copy(subpath['bezier']))
|
||||||
subpath['bezier'] = []
|
subpath['bezier'] = []
|
||||||
elif current_subpath == 'rectangle':
|
elif current_subpath == 'rectangle':
|
||||||
subpath['rectangle'].append(start_point)
|
# subpath['rectangle'].append(start_point)
|
||||||
# since we are closing the subpath add it to the path, a path may have chained subpaths
|
# since we are closing the subpath add it to the path, a path may have chained subpaths
|
||||||
path['rectangle'].append(copy(subpath['rectangle']))
|
path['rectangle'].append(copy(subpath['rectangle']))
|
||||||
subpath['rectangle'] = []
|
subpath['rectangle'] = []
|
||||||
|
@ -566,12 +665,29 @@ class ToolPDF(FlatCAMTool):
|
||||||
path_geo.append(geo)
|
path_geo.append(geo)
|
||||||
subpath['rectangle'] = []
|
subpath['rectangle'] = []
|
||||||
|
|
||||||
try:
|
# store the found geometry
|
||||||
apertures_dict[str(aperture)]['solid_geometry'] += path_geo
|
found_aperture = None
|
||||||
except KeyError:
|
if apertures_dict:
|
||||||
# in case there is no stroke width yet therefore no aperture
|
for apid in apertures_dict:
|
||||||
|
# if we already have an aperture with the current size (rounded to 5 decimals)
|
||||||
|
if apertures_dict[apid]['size'] == round(applied_size, 5):
|
||||||
|
found_aperture = apid
|
||||||
|
break
|
||||||
|
|
||||||
|
if found_aperture:
|
||||||
|
apertures_dict[copy(found_aperture)]['solid_geometry'] += path_geo
|
||||||
|
found_aperture = None
|
||||||
|
else:
|
||||||
|
if str(aperture) in apertures_dict.keys():
|
||||||
|
aperture += 1
|
||||||
apertures_dict[str(aperture)] = {}
|
apertures_dict[str(aperture)] = {}
|
||||||
apertures_dict[str(aperture)]['size'] = applied_size
|
apertures_dict[str(aperture)]['size'] = round(applied_size, 5)
|
||||||
|
apertures_dict[str(aperture)]['type'] = 'C'
|
||||||
|
apertures_dict[str(aperture)]['solid_geometry'] = []
|
||||||
|
apertures_dict[str(aperture)]['solid_geometry'] += path_geo
|
||||||
|
else:
|
||||||
|
apertures_dict[str(aperture)] = {}
|
||||||
|
apertures_dict[str(aperture)]['size'] = round(applied_size, 5)
|
||||||
apertures_dict[str(aperture)]['type'] = 'C'
|
apertures_dict[str(aperture)]['type'] = 'C'
|
||||||
apertures_dict[str(aperture)]['solid_geometry'] = []
|
apertures_dict[str(aperture)]['solid_geometry'] = []
|
||||||
apertures_dict[str(aperture)]['solid_geometry'] += path_geo
|
apertures_dict[str(aperture)]['solid_geometry'] += path_geo
|
||||||
|
@ -583,8 +699,8 @@ class ToolPDF(FlatCAMTool):
|
||||||
if match:
|
if match:
|
||||||
# scale the size here; some PDF printers apply transformation after the size is declared
|
# scale the size here; some PDF printers apply transformation after the size is declared
|
||||||
applied_size = size * scale_geo[0] * self.point_to_unit_factor
|
applied_size = size * scale_geo[0] * self.point_to_unit_factor
|
||||||
|
|
||||||
path_geo = list()
|
path_geo = list()
|
||||||
|
|
||||||
if current_subpath == 'lines':
|
if current_subpath == 'lines':
|
||||||
if path['lines']:
|
if path['lines']:
|
||||||
for subp in path['lines']:
|
for subp in path['lines']:
|
||||||
|
@ -632,8 +748,8 @@ class ToolPDF(FlatCAMTool):
|
||||||
for subp in path['rectangle']:
|
for subp in path['rectangle']:
|
||||||
geo = copy(subp)
|
geo = copy(subp)
|
||||||
# close the subpath if it was not closed already
|
# close the subpath if it was not closed already
|
||||||
if close_subpath is False:
|
if close_subpath is False and start_point is not None:
|
||||||
geo.append(geo[0])
|
geo.append(start_point)
|
||||||
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
||||||
path_geo.append(geo_el)
|
path_geo.append(geo_el)
|
||||||
# the path was painted therefore initialize it
|
# the path was painted therefore initialize it
|
||||||
|
@ -650,6 +766,16 @@ class ToolPDF(FlatCAMTool):
|
||||||
# we finished painting and also closed the path if it was the case
|
# we finished painting and also closed the path if it was the case
|
||||||
close_subpath = True
|
close_subpath = True
|
||||||
|
|
||||||
|
# if there was a fill color change we look for circular geometries from which we can make drill holes
|
||||||
|
# for the Excellon file
|
||||||
|
if flag_clear_geo is True:
|
||||||
|
# we llok for circular geometries
|
||||||
|
if current_subpath == 'bezier':
|
||||||
|
# if there are geometries in the list
|
||||||
|
if path_geo:
|
||||||
|
clear_apertures_dict['0']['solid_geometry'] += path_geo
|
||||||
|
else:
|
||||||
|
# else, add the geometry as usual
|
||||||
try:
|
try:
|
||||||
apertures_dict['0']['solid_geometry'] += path_geo
|
apertures_dict['0']['solid_geometry'] += path_geo
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -661,13 +787,14 @@ class ToolPDF(FlatCAMTool):
|
||||||
apertures_dict['0']['solid_geometry'] += path_geo
|
apertures_dict['0']['solid_geometry'] += path_geo
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# fill and stroke the path
|
# Fill and Stroke the path
|
||||||
match = self.fill_stroke_path_re.search(pline)
|
match = self.fill_stroke_path_re.search(pline)
|
||||||
if match:
|
if match:
|
||||||
# scale the size here; some PDF printers apply transformation after the size is declared
|
# scale the size here; some PDF printers apply transformation after the size is declared
|
||||||
applied_size = size * scale_geo[0] * self.point_to_unit_factor
|
applied_size = size * scale_geo[0] * self.point_to_unit_factor
|
||||||
|
|
||||||
path_geo = list()
|
path_geo = list()
|
||||||
|
fill_geo = list()
|
||||||
|
|
||||||
if current_subpath == 'lines':
|
if current_subpath == 'lines':
|
||||||
if path['lines']:
|
if path['lines']:
|
||||||
# fill
|
# fill
|
||||||
|
@ -677,7 +804,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
if close_subpath is False:
|
if close_subpath is False:
|
||||||
geo.append(geo[0])
|
geo.append(geo[0])
|
||||||
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
||||||
path_geo.append(geo_el)
|
fill_geo.append(geo_el)
|
||||||
# stroke
|
# stroke
|
||||||
for subp in path['lines']:
|
for subp in path['lines']:
|
||||||
geo = copy(subp)
|
geo = copy(subp)
|
||||||
|
@ -692,7 +819,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
if close_subpath is False:
|
if close_subpath is False:
|
||||||
geo.append(start_point)
|
geo.append(start_point)
|
||||||
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
||||||
path_geo.append(geo_el)
|
fill_geo.append(geo_el)
|
||||||
# stroke
|
# stroke
|
||||||
geo = copy(subpath['lines'])
|
geo = copy(subpath['lines'])
|
||||||
geo = LineString(geo).buffer((float(applied_size) / 2), resolution=self.step_per_circles)
|
geo = LineString(geo).buffer((float(applied_size) / 2), resolution=self.step_per_circles)
|
||||||
|
@ -711,7 +838,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
if close_subpath is False:
|
if close_subpath is False:
|
||||||
geo.append(geo[0])
|
geo.append(geo[0])
|
||||||
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
||||||
path_geo.append(geo_el)
|
fill_geo.append(geo_el)
|
||||||
# stroke
|
# stroke
|
||||||
for subp in path['bezier']:
|
for subp in path['bezier']:
|
||||||
geo = []
|
geo = []
|
||||||
|
@ -728,7 +855,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
if close_subpath is False:
|
if close_subpath is False:
|
||||||
geo.append(start_point)
|
geo.append(start_point)
|
||||||
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
||||||
path_geo.append(geo_el)
|
fill_geo.append(geo_el)
|
||||||
# stroke
|
# stroke
|
||||||
geo = []
|
geo = []
|
||||||
for b in subpath['bezier']:
|
for b in subpath['bezier']:
|
||||||
|
@ -746,7 +873,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
if close_subpath is False:
|
if close_subpath is False:
|
||||||
geo.append(geo[0])
|
geo.append(geo[0])
|
||||||
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
||||||
path_geo.append(geo_el)
|
fill_geo.append(geo_el)
|
||||||
# stroke
|
# stroke
|
||||||
for subp in path['rectangle']:
|
for subp in path['rectangle']:
|
||||||
geo = copy(subp)
|
geo = copy(subp)
|
||||||
|
@ -761,7 +888,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
if close_subpath is False:
|
if close_subpath is False:
|
||||||
geo.append(start_point)
|
geo.append(start_point)
|
||||||
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
||||||
path_geo.append(geo_el)
|
fill_geo.append(geo_el)
|
||||||
# stroke
|
# stroke
|
||||||
geo = copy(subpath['rectangle'])
|
geo = copy(subpath['rectangle'])
|
||||||
geo = LineString(geo).buffer((float(applied_size) / 2), resolution=self.step_per_circles)
|
geo = LineString(geo).buffer((float(applied_size) / 2), resolution=self.step_per_circles)
|
||||||
|
@ -771,16 +898,53 @@ class ToolPDF(FlatCAMTool):
|
||||||
# we finished painting and also closed the path if it was the case
|
# we finished painting and also closed the path if it was the case
|
||||||
close_subpath = True
|
close_subpath = True
|
||||||
|
|
||||||
|
# store the found geometry for stroking the path
|
||||||
|
found_aperture = None
|
||||||
|
if apertures_dict:
|
||||||
|
for apid in apertures_dict:
|
||||||
|
# if we already have an aperture with the current size (rounded to 5 decimals)
|
||||||
|
if apertures_dict[apid]['size'] == round(applied_size, 5):
|
||||||
|
found_aperture = apid
|
||||||
|
break
|
||||||
|
|
||||||
|
if found_aperture:
|
||||||
|
apertures_dict[copy(found_aperture)]['solid_geometry'] += path_geo
|
||||||
|
found_aperture = None
|
||||||
|
else:
|
||||||
|
if str(aperture) in apertures_dict.keys():
|
||||||
|
aperture += 1
|
||||||
|
apertures_dict[str(aperture)] = {}
|
||||||
|
apertures_dict[str(aperture)]['size'] = round(applied_size, 5)
|
||||||
|
apertures_dict[str(aperture)]['type'] = 'C'
|
||||||
|
apertures_dict[str(aperture)]['solid_geometry'] = []
|
||||||
|
apertures_dict[str(aperture)]['solid_geometry'] += path_geo
|
||||||
|
else:
|
||||||
|
apertures_dict[str(aperture)] = {}
|
||||||
|
apertures_dict[str(aperture)]['size'] = round(applied_size, 5)
|
||||||
|
apertures_dict[str(aperture)]['type'] = 'C'
|
||||||
|
apertures_dict[str(aperture)]['solid_geometry'] = []
|
||||||
|
apertures_dict[str(aperture)]['solid_geometry'] += path_geo
|
||||||
|
|
||||||
|
# store the found geometry for filling the path
|
||||||
try:
|
try:
|
||||||
apertures_dict['0']['solid_geometry'] += path_geo
|
apertures_dict['0']['solid_geometry'] += fill_geo
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# in case there is no stroke width yet therefore no aperture
|
# in case there is no stroke width yet therefore no aperture
|
||||||
apertures_dict['0'] = {}
|
apertures_dict['0'] = {}
|
||||||
apertures_dict['0']['size'] = applied_size
|
apertures_dict['0']['size'] = round(applied_size, 5)
|
||||||
apertures_dict['0']['type'] = 'C'
|
apertures_dict['0']['type'] = 'C'
|
||||||
apertures_dict['0']['solid_geometry'] = []
|
apertures_dict['0']['solid_geometry'] = []
|
||||||
apertures_dict['0']['solid_geometry'] += path_geo
|
apertures_dict['0']['solid_geometry'] += fill_geo
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# tidy up. copy the current aperture dict to the object dict but only if it is not empty
|
||||||
|
if apertures_dict:
|
||||||
|
object_dict[object_nr] = deepcopy(apertures_dict)
|
||||||
|
|
||||||
|
if clear_apertures_dict['0']['solid_geometry']:
|
||||||
|
object_dict[0] = deepcopy(clear_apertures_dict)
|
||||||
|
|
||||||
return object_dict
|
return object_dict
|
||||||
|
|
||||||
def bezier_to_points(self, start, c1, c2, stop):
|
def bezier_to_points(self, start, c1, c2, stop):
|
||||||
|
|
Loading…
Reference in New Issue