Excellon to g-code and bed flattening features.
This commit is contained in:
254
camlib.py
254
camlib.py
@@ -129,27 +129,27 @@ class Gerber (Geometry):
|
|||||||
into dictionary of apertures.
|
into dictionary of apertures.
|
||||||
"""
|
"""
|
||||||
indexstar = gline.find("*")
|
indexstar = gline.find("*")
|
||||||
indexC = gline.find("C,")
|
indexc = gline.find("C,")
|
||||||
if indexC != -1: # Circle, example: %ADD11C,0.1*%
|
if indexc != -1: # Circle, example: %ADD11C,0.1*%
|
||||||
apid = gline[4:indexC]
|
apid = gline[4:indexc]
|
||||||
self.apertures[apid] = {"type": "C",
|
self.apertures[apid] = {"type": "C",
|
||||||
"size": float(gline[indexC+2:indexstar])}
|
"size": float(gline[indexc+2:indexstar])}
|
||||||
return apid
|
return apid
|
||||||
indexR = gline.find("R,")
|
indexr = gline.find("R,")
|
||||||
if indexR != -1: # Rectangle, example: %ADD15R,0.05X0.12*%
|
if indexr != -1: # Rectangle, example: %ADD15R,0.05X0.12*%
|
||||||
apid = gline[4:indexR]
|
apid = gline[4:indexr]
|
||||||
indexX = gline.find("X")
|
indexx = gline.find("X")
|
||||||
self.apertures[apid] = {"type": "R",
|
self.apertures[apid] = {"type": "R",
|
||||||
"width": float(gline[indexR+2:indexX]),
|
"width": float(gline[indexr+2:indexx]),
|
||||||
"height": float(gline[indexX+1:indexstar])}
|
"height": float(gline[indexx+1:indexstar])}
|
||||||
return apid
|
return apid
|
||||||
indexO = gline.find("O,")
|
indexo = gline.find("O,")
|
||||||
if indexO != -1: # Obround
|
if indexo != -1: # Obround
|
||||||
apid = gline[4:indexO]
|
apid = gline[4:indexo]
|
||||||
indexX = gline.find("X")
|
indexx = gline.find("X")
|
||||||
self.apertures[apid] = {"type": "O",
|
self.apertures[apid] = {"type": "O",
|
||||||
"width": float(gline[indexO+2:indexX]),
|
"width": float(gline[indexo+2:indexx]),
|
||||||
"height": float(gline[indexX+1:indexstar])}
|
"height": float(gline[indexx+1:indexstar])}
|
||||||
return apid
|
return apid
|
||||||
print "WARNING: Aperture not implemented:", gline
|
print "WARNING: Aperture not implemented:", gline
|
||||||
return None
|
return None
|
||||||
@@ -187,12 +187,12 @@ class Gerber (Geometry):
|
|||||||
path = [coord(gline, self.digits, self.fraction)]
|
path = [coord(gline, self.digits, self.fraction)]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
indexD3 = gline.find("D03*")
|
indexd3 = gline.find("D03*")
|
||||||
if indexD3 > 0: # Flash
|
if indexd3 > 0: # Flash
|
||||||
self.flashes.append({"loc": coord(gline, self.digits, self.fraction),
|
self.flashes.append({"loc": coord(gline, self.digits, self.fraction),
|
||||||
"aperture": current_aperture})
|
"aperture": current_aperture})
|
||||||
continue
|
continue
|
||||||
if indexD3 == 0: # Flash?
|
if indexd3 == 0: # Flash?
|
||||||
print "WARNING: Uninplemented flash style:", gline
|
print "WARNING: Uninplemented flash style:", gline
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -216,16 +216,16 @@ class Gerber (Geometry):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if gline.find("%FS") != -1: # Format statement
|
if gline.find("%FS") != -1: # Format statement
|
||||||
indexX = gline.find("X")
|
indexx = gline.find("X")
|
||||||
self.digits = int(gline[indexX + 1])
|
self.digits = int(gline[indexx + 1])
|
||||||
self.fraction = int(gline[indexX + 2])
|
self.fraction = int(gline[indexx + 2])
|
||||||
continue
|
continue
|
||||||
print "WARNING: Line ignored:", gline
|
print "WARNING: Line ignored:", gline
|
||||||
|
|
||||||
if len(path) > 1:
|
if len(path) > 1:
|
||||||
# EOF, create shapely LineString if something in path
|
# EOF, create shapely LineString if something in path
|
||||||
self.paths.append({"linestring":LineString(path),
|
self.paths.append({"linestring": LineString(path),
|
||||||
"aperture":last_path_aperture})
|
"aperture": last_path_aperture})
|
||||||
|
|
||||||
def do_flashes(self):
|
def do_flashes(self):
|
||||||
"""
|
"""
|
||||||
@@ -318,11 +318,11 @@ class Excellon(Geometry):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
## Drill
|
## Drill
|
||||||
indexX = eline.find("X")
|
indexx = eline.find("X")
|
||||||
indexY = eline.find("Y")
|
indexy = eline.find("Y")
|
||||||
if indexX != -1 and indexY != -1:
|
if indexx != -1 and indexy != -1:
|
||||||
x = float(int(eline[indexX+1:indexY])/10000.0)
|
x = float(int(eline[indexx+1:indexy])/10000.0)
|
||||||
y = float(int(eline[indexY+1:-1])/10000.0)
|
y = float(int(eline[indexy+1:-1])/10000.0)
|
||||||
self.drills.append({'point': Point((x, y)), 'tool': current_tool})
|
self.drills.append({'point': Point((x, y)), 'tool': current_tool})
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -342,29 +342,28 @@ class Excellon(Geometry):
|
|||||||
class CNCjob(Geometry):
|
class CNCjob(Geometry):
|
||||||
def __init__(self, units="in", kind="generic", z_move=0.1,
|
def __init__(self, units="in", kind="generic", z_move=0.1,
|
||||||
feedrate=3.0, z_cut=-0.002, tooldia=0.0):
|
feedrate=3.0, z_cut=-0.002, tooldia=0.0):
|
||||||
|
"""
|
||||||
# Options
|
|
||||||
|
@param units:
|
||||||
|
@param kind:
|
||||||
|
@param z_move:
|
||||||
|
@param feedrate:
|
||||||
|
@param z_cut:
|
||||||
|
@param tooldia:
|
||||||
|
"""
|
||||||
|
Geometry.__init__(self)
|
||||||
self.kind = kind
|
self.kind = kind
|
||||||
self.units = units
|
self.units = units
|
||||||
self.z_cut = z_cut
|
self.z_cut = z_cut
|
||||||
self.z_move = z_move
|
self.z_move = z_move
|
||||||
self.feedrate = feedrate
|
self.feedrate = feedrate
|
||||||
self.tooldia = tooldia
|
self.tooldia = tooldia
|
||||||
|
|
||||||
# Constants
|
|
||||||
self.unitcode = {"in": "G20", "mm": "G21"}
|
self.unitcode = {"in": "G20", "mm": "G21"}
|
||||||
self.pausecode = "G04 P1"
|
self.pausecode = "G04 P1"
|
||||||
self.feedminutecode = "G94"
|
self.feedminutecode = "G94"
|
||||||
self.absolutecode = "G90"
|
self.absolutecode = "G90"
|
||||||
|
|
||||||
# Input/Output G-Code
|
|
||||||
self.gcode = ""
|
self.gcode = ""
|
||||||
|
|
||||||
# Bounds of geometry given to CNCjob.generate_from_geometry()
|
|
||||||
self.input_geometry_bounds = None
|
self.input_geometry_bounds = None
|
||||||
|
|
||||||
# Output generated by CNCjob.create_gcode_geometry()
|
|
||||||
#self.G_geometry = None
|
|
||||||
self.gcode_parsed = None
|
self.gcode_parsed = None
|
||||||
|
|
||||||
def generate_from_excellon(self, exobj):
|
def generate_from_excellon(self, exobj):
|
||||||
@@ -377,13 +376,12 @@ class CNCjob(Geometry):
|
|||||||
self.gcode = []
|
self.gcode = []
|
||||||
|
|
||||||
t = "G00 X%.4fY%.4f\n"
|
t = "G00 X%.4fY%.4f\n"
|
||||||
down = "G01 Z%.4f\n"%self.z_cut
|
down = "G01 Z%.4f\n" % self.z_cut
|
||||||
up = "G01 Z%.4f\n"%self.z_move
|
up = "G01 Z%.4f\n" % self.z_move
|
||||||
|
|
||||||
for tool in exobj.tools:
|
for tool in exobj.tools:
|
||||||
|
|
||||||
points = []
|
points = []
|
||||||
gcode = ""
|
|
||||||
|
|
||||||
for drill in exobj.drill:
|
for drill in exobj.drill:
|
||||||
if drill['tool'] == tool:
|
if drill['tool'] == tool:
|
||||||
@@ -392,79 +390,111 @@ class CNCjob(Geometry):
|
|||||||
gcode = self.unitcode[self.units] + "\n"
|
gcode = self.unitcode[self.units] + "\n"
|
||||||
gcode += self.absolutecode + "\n"
|
gcode += self.absolutecode + "\n"
|
||||||
gcode += self.feedminutecode + "\n"
|
gcode += self.feedminutecode + "\n"
|
||||||
gcode += "F%.2f\n"%self.feedrate
|
gcode += "F%.2f\n" % self.feedrate
|
||||||
gcode += "G00 Z%.4f\n"%self.z_move # Move to travel height
|
gcode += "G00 Z%.4f\n" % self.z_move # Move to travel height
|
||||||
gcode += "M03\n" # Spindle start
|
gcode += "M03\n" # Spindle start
|
||||||
gcode += self.pausecode + "\n"
|
gcode += self.pausecode + "\n"
|
||||||
|
|
||||||
for point in points:
|
for point in points:
|
||||||
gcode += t%point
|
gcode += t % point
|
||||||
gcode += down + up
|
gcode += down + up
|
||||||
|
|
||||||
gcode += t%(0, 0)
|
gcode += t % (0, 0)
|
||||||
gcode += "M05\n" # Spindle stop
|
gcode += "M05\n" # Spindle stop
|
||||||
|
|
||||||
self.gcode.append(gcode)
|
self.gcode.append(gcode)
|
||||||
|
|
||||||
|
def generate_from_excellon_by_tool(self, exobj, tools="all"):
|
||||||
|
"""
|
||||||
|
Creates gcode for this object from an Excellon object
|
||||||
|
for the specified tools.
|
||||||
|
@param exobj: Excellon object to process
|
||||||
|
@type exobj: Excellon
|
||||||
|
@param tools: Comma separated tool names
|
||||||
|
@type: tools: str
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
|
print "Creating CNC Job from Excellon..."
|
||||||
|
if tools == "all":
|
||||||
|
tools = [tool for tool in exobj.tools]
|
||||||
|
else:
|
||||||
|
tools = [x.strip() for x in tools.split(",")]
|
||||||
|
tools = filter(lambda y: y in exobj.tools, tools)
|
||||||
|
print "Tools are:", tools
|
||||||
|
|
||||||
|
points = []
|
||||||
|
for drill in exobj.drills:
|
||||||
|
if drill['tool'] in tools:
|
||||||
|
points.append(drill['point'])
|
||||||
|
|
||||||
|
print "Found %d drills." % len(points)
|
||||||
|
#self.kind = "drill"
|
||||||
|
self.gcode = []
|
||||||
|
|
||||||
|
t = "G00 X%.4fY%.4f\n"
|
||||||
|
down = "G01 Z%.4f\n" % self.z_cut
|
||||||
|
up = "G01 Z%.4f\n" % self.z_move
|
||||||
|
|
||||||
|
gcode = self.unitcode[self.units] + "\n"
|
||||||
|
gcode += self.absolutecode + "\n"
|
||||||
|
gcode += self.feedminutecode + "\n"
|
||||||
|
gcode += "F%.2f\n" % self.feedrate
|
||||||
|
gcode += "G00 Z%.4f\n" % self.z_move # Move to travel height
|
||||||
|
gcode += "M03\n" # Spindle start
|
||||||
|
gcode += self.pausecode + "\n"
|
||||||
|
|
||||||
|
for point in points:
|
||||||
|
x, y = point.coords.xy
|
||||||
|
gcode += t % (x[0], y[0])
|
||||||
|
gcode += down + up
|
||||||
|
|
||||||
|
gcode += t % (0, 0)
|
||||||
|
gcode += "M05\n" # Spindle stop
|
||||||
|
|
||||||
|
self.gcode = gcode
|
||||||
|
|
||||||
def generate_from_geometry(self, geometry, append=True, tooldia=None):
|
def generate_from_geometry(self, geometry, append=True, tooldia=None):
|
||||||
"""
|
"""
|
||||||
Generates G-Code for geometry (Shapely collection).
|
Generates G-Code from a Geometry object.
|
||||||
"""
|
"""
|
||||||
if tooldia is None:
|
if tooldia is not None:
|
||||||
tooldia = self.tooldia
|
|
||||||
else:
|
|
||||||
self.tooldia = tooldia
|
self.tooldia = tooldia
|
||||||
|
|
||||||
self.input_geometry_bounds = geometry.bounds
|
self.input_geometry_bounds = geometry.bounds()
|
||||||
|
|
||||||
if not append:
|
if not append:
|
||||||
self.gcode = ""
|
self.gcode = ""
|
||||||
t = "G0%d X%.4fY%.4f\n"
|
|
||||||
self.gcode = self.unitcode[self.units] + "\n"
|
self.gcode = self.unitcode[self.units] + "\n"
|
||||||
self.gcode += self.absolutecode + "\n"
|
self.gcode += self.absolutecode + "\n"
|
||||||
self.gcode += self.feedminutecode + "\n"
|
self.gcode += self.feedminutecode + "\n"
|
||||||
self.gcode += "F%.2f\n"%self.feedrate
|
self.gcode += "F%.2f\n" % self.feedrate
|
||||||
self.gcode += "G00 Z%.4f\n"%self.z_move # Move to travel height
|
self.gcode += "G00 Z%.4f\n" % self.z_move # Move to travel height
|
||||||
self.gcode += "M03\n" # Spindle start
|
self.gcode += "M03\n" # Spindle start
|
||||||
self.gcode += self.pausecode + "\n"
|
self.gcode += self.pausecode + "\n"
|
||||||
|
|
||||||
for geo in geometry:
|
for geo in geometry.solid_geometry:
|
||||||
|
|
||||||
if type(geo) == Polygon:
|
if type(geo) == Polygon:
|
||||||
path = list(geo.exterior.coords) # Polygon exterior
|
self.gcode += self.polygon2gcode(geo)
|
||||||
self.gcode += t%(0, path[0][0], path[0][1]) # Move to first point
|
|
||||||
self.gcode += "G01 Z%.4f\n"%self.z_cut # Start cutting
|
|
||||||
for pt in path[1:]:
|
|
||||||
self.gcode += t%(1, pt[0], pt[1]) # Linear motion to point
|
|
||||||
self.gcode += "G00 Z%.4f\n"%self.z_move # Stop cutting
|
|
||||||
for ints in geo.interiors: # Polygon interiors
|
|
||||||
path = list(ints.coords)
|
|
||||||
self.gcode += t%(0, path[0][0], path[0][1]) # Move to first point
|
|
||||||
self.gcode += "G01 Z%.4f\n"%self.z_cut # Start cutting
|
|
||||||
for pt in path[1:]:
|
|
||||||
self.gcode += t%(1, pt[0], pt[1]) # Linear motion to point
|
|
||||||
self.gcode += "G00 Z%.4f\n"%self.z_move # Stop cutting
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if type(geo) == LineString or type(geo) == LinearRing:
|
if type(geo) == LineString or type(geo) == LinearRing:
|
||||||
path = list(geo.coords)
|
self.gcode += self.linear2gcode(geo)
|
||||||
self.gcode += t%(0, path[0][0], path[0][1]) # Move to first point
|
|
||||||
self.gcode += "G01 Z%.4f\n"%self.z_cut # Start cutting
|
|
||||||
for pt in path[1:]:
|
|
||||||
self.gcode += t%(1, pt[0], pt[1]) # Linear motion to point
|
|
||||||
self.gcode += "G00 Z%.4f\n"%self.z_move # Stop cutting
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if type(geo) == Point:
|
if type(geo) == Point:
|
||||||
path = list(geo.coords)
|
self.gcode += self.point2gcode(geo)
|
||||||
self.gcode += t%(0, path[0][0], path[0][1]) # Move to first point
|
|
||||||
self.gcode += "G01 Z%.4f\n"%self.z_cut # Start cutting
|
|
||||||
self.gcode += "G00 Z%.4f\n"%self.z_move # Stop cutting
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print "WARNING: G-code generation not implemented for %s"%(str(type(geo)))
|
if type(geo) == MultiPolygon:
|
||||||
|
for poly in geo:
|
||||||
|
self.gcode += self.polygon2gcode(poly)
|
||||||
|
continue
|
||||||
|
|
||||||
|
print "WARNING: G-code generation not implemented for %s" % (str(type(geo)))
|
||||||
|
|
||||||
self.gcode += "G00 Z%.4f\n"%self.z_move # Stop cutting
|
self.gcode += "G00 Z%.4f\n" % self.z_move # Stop cutting
|
||||||
self.gcode += "G00 X0Y0\n"
|
self.gcode += "G00 X0Y0\n"
|
||||||
self.gcode += "M05\n" # Spindle stop
|
self.gcode += "M05\n" # Spindle stop
|
||||||
|
|
||||||
@@ -475,8 +505,10 @@ class CNCjob(Geometry):
|
|||||||
fast or feedrate speed.
|
fast or feedrate speed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# TODO: Make this a parameter
|
||||||
steps_per_circ = 20
|
steps_per_circ = 20
|
||||||
|
|
||||||
|
# Results go here
|
||||||
geometry = []
|
geometry = []
|
||||||
|
|
||||||
# TODO: ???? bring this into the class??
|
# TODO: ???? bring this into the class??
|
||||||
@@ -523,8 +555,8 @@ class CNCjob(Geometry):
|
|||||||
if current['G'] in [2, 3]: # arc
|
if current['G'] in [2, 3]: # arc
|
||||||
center = [gobj['I'] + current['X'], gobj['J'] + current['Y']]
|
center = [gobj['I'] + current['X'], gobj['J'] + current['Y']]
|
||||||
radius = sqrt(gobj['I']**2 + gobj['J']**2)
|
radius = sqrt(gobj['I']**2 + gobj['J']**2)
|
||||||
start = arctan2( -gobj['J'], -gobj['I'])
|
start = arctan2(-gobj['J'], -gobj['I'])
|
||||||
stop = arctan2(-center[1]+y, -center[0]+x)
|
stop = arctan2(-center[1]+y, -center[0]+x)
|
||||||
geometry.append({'geom': arc(center, radius, start, stop,
|
geometry.append({'geom': arc(center, radius, start, stop,
|
||||||
arcdir[current['G']],
|
arcdir[current['G']],
|
||||||
steps_per_circ),
|
steps_per_circ),
|
||||||
@@ -601,6 +633,49 @@ class CNCjob(Geometry):
|
|||||||
def create_geometry(self):
|
def create_geometry(self):
|
||||||
self.solid_geometry = cascaded_union([geo['geom'] for geo in self.gcode_parsed])
|
self.solid_geometry = cascaded_union([geo['geom'] for geo in self.gcode_parsed])
|
||||||
|
|
||||||
|
def polygon2gcode(self, polygon):
|
||||||
|
"""
|
||||||
|
Creates G-Code for the exterior and all interior paths
|
||||||
|
of a polygon.
|
||||||
|
@param polygon: A Shapely.Polygon
|
||||||
|
@type polygon: Shapely.Polygon
|
||||||
|
"""
|
||||||
|
gcode = ""
|
||||||
|
t = "G0%d X%.4fY%.4f\n"
|
||||||
|
path = list(polygon.exterior.coords) # Polygon exterior
|
||||||
|
gcode += t % (0, path[0][0], path[0][1]) # Move to first point
|
||||||
|
gcode += "G01 Z%.4f\n" % self.z_cut # Start cutting
|
||||||
|
for pt in path[1:]:
|
||||||
|
gcode += t % (1, pt[0], pt[1]) # Linear motion to point
|
||||||
|
gcode += "G00 Z%.4f\n" % self.z_move # Stop cutting
|
||||||
|
for ints in polygon.interiors: # Polygon interiors
|
||||||
|
path = list(ints.coords)
|
||||||
|
gcode += t % (0, path[0][0], path[0][1]) # Move to first point
|
||||||
|
gcode += "G01 Z%.4f\n" % self.z_cut # Start cutting
|
||||||
|
for pt in path[1:]:
|
||||||
|
gcode += t % (1, pt[0], pt[1]) # Linear motion to point
|
||||||
|
gcode += "G00 Z%.4f\n" % self.z_move # Stop cutting
|
||||||
|
return gcode
|
||||||
|
|
||||||
|
def linear2gcode(self, linear):
|
||||||
|
gcode = ""
|
||||||
|
t = "G0%d X%.4fY%.4f\n"
|
||||||
|
path = list(linear.coords)
|
||||||
|
gcode += t%(0, path[0][0], path[0][1]) # Move to first point
|
||||||
|
gcode += "G01 Z%.4f\n" % self.z_cut # Start cutting
|
||||||
|
for pt in path[1:]:
|
||||||
|
gcode += t % (1, pt[0], pt[1]) # Linear motion to point
|
||||||
|
gcode += "G00 Z%.4f\n" % self.z_move # Stop cutting
|
||||||
|
return gcode
|
||||||
|
|
||||||
|
def point2gcode(self, point):
|
||||||
|
gcode = ""
|
||||||
|
t = "G0%d X%.4fY%.4f\n"
|
||||||
|
path = list(point.coords)
|
||||||
|
gcode += t % (0, path[0][0], path[0][1]) # Move to first point
|
||||||
|
gcode += "G01 Z%.4f\n" % self.z_cut # Start cutting
|
||||||
|
gcode += "G00 Z%.4f\n" % self.z_move # Stop cutting
|
||||||
|
|
||||||
|
|
||||||
def gparse1b(gtext):
|
def gparse1b(gtext):
|
||||||
"""
|
"""
|
||||||
@@ -653,7 +728,8 @@ def get_bounds(geometry_set):
|
|||||||
ymin = Inf
|
ymin = Inf
|
||||||
xmax = -Inf
|
xmax = -Inf
|
||||||
ymax = -Inf
|
ymax = -Inf
|
||||||
|
|
||||||
|
print "Getting bounds of:", str(geometry_set)
|
||||||
for gs in geometry_set:
|
for gs in geometry_set:
|
||||||
gxmin, gymin, gxmax, gymax = geometry_set[gs].bounds()
|
gxmin, gymin, gxmax, gymax = geometry_set[gs].bounds()
|
||||||
xmin = min([xmin, gxmin])
|
xmin = min([xmin, gxmin])
|
||||||
@@ -699,7 +775,7 @@ def arc(center, radius, start, stop, direction, steps_per_circ):
|
|||||||
return LineString(points)
|
return LineString(points)
|
||||||
|
|
||||||
|
|
||||||
def clear_poly(poly, tooldia, overlap = 0.1):
|
def clear_poly(poly, tooldia, overlap=0.1):
|
||||||
"""
|
"""
|
||||||
Creates a list of Shapely geometry objects covering the inside
|
Creates a list of Shapely geometry objects covering the inside
|
||||||
of a Shapely.Polygon. Use for removing all the copper in a region
|
of a Shapely.Polygon. Use for removing all the copper in a region
|
||||||
|
|||||||
311
cirkuix.py
311
cirkuix.py
@@ -21,15 +21,8 @@ class CirkuixObj:
|
|||||||
by the user in their respective forms.
|
by the user in their respective forms.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
form_getters = {}
|
|
||||||
|
|
||||||
form_setters = {}
|
|
||||||
|
|
||||||
# Instance of the application to which these are related.
|
# Instance of the application to which these are related.
|
||||||
# The app should set this value.
|
# The app should set this value.
|
||||||
# TODO: Move the definitions of form_getters and form_setters
|
|
||||||
# TODO: to their respective classes and use app to reference
|
|
||||||
# TODO: the builder.
|
|
||||||
app = None
|
app = None
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
@@ -41,11 +34,25 @@ class CirkuixObj:
|
|||||||
self.kind = None # Override with proper name
|
self.kind = None # Override with proper name
|
||||||
|
|
||||||
def setup_axes(self, figure):
|
def setup_axes(self, figure):
|
||||||
|
"""
|
||||||
|
1) Creates axes if they don't exist. 2) Clears axes. 3) Attaches
|
||||||
|
them to figure if not part of the figure. 4) Sets transparent
|
||||||
|
background. 5) Sets 1:1 scale aspect ratio.
|
||||||
|
@param figure: A Matplotlib.Figure on which to add/configure axes.
|
||||||
|
@type figure: matplotlib.figure.Figure
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
if self.axes is None:
|
if self.axes is None:
|
||||||
|
print "New axes"
|
||||||
self.axes = figure.add_axes([0.05, 0.05, 0.9, 0.9],
|
self.axes = figure.add_axes([0.05, 0.05, 0.9, 0.9],
|
||||||
label=self.options["name"])
|
label=self.options["name"])
|
||||||
elif self.axes not in figure.axes:
|
elif self.axes not in figure.axes:
|
||||||
|
print "Clearing and attaching axes"
|
||||||
|
self.axes.cla()
|
||||||
figure.add_axes(self.axes)
|
figure.add_axes(self.axes)
|
||||||
|
else:
|
||||||
|
print "Clearing Axes"
|
||||||
|
self.axes.cla()
|
||||||
|
|
||||||
self.axes.patch.set_visible(False) # No background
|
self.axes.patch.set_visible(False) # No background
|
||||||
self.axes.set_aspect(1)
|
self.axes.set_aspect(1)
|
||||||
@@ -62,7 +69,11 @@ class CirkuixObj:
|
|||||||
self.set_form_item(option)
|
self.set_form_item(option)
|
||||||
|
|
||||||
def read_form(self):
|
def read_form(self):
|
||||||
for option in self.form_getters:
|
"""
|
||||||
|
Reads form into self.options
|
||||||
|
@rtype : None
|
||||||
|
"""
|
||||||
|
for option in self.options:
|
||||||
self.read_form_item(option)
|
self.read_form_item(option)
|
||||||
|
|
||||||
def build_ui(self):
|
def build_ui(self):
|
||||||
@@ -114,7 +125,7 @@ class CirkuixObj:
|
|||||||
fname = fkind + "_" + self.kind + "_" + option
|
fname = fkind + "_" + self.kind + "_" + option
|
||||||
|
|
||||||
if fkind == 'entry_text':
|
if fkind == 'entry_text':
|
||||||
self.options[option] = self.app.builder(fname).get_text()
|
self.options[option] = self.app.builder.get_object(fname).get_text()
|
||||||
return
|
return
|
||||||
if fkind == 'entry_eval':
|
if fkind == 'entry_eval':
|
||||||
self.options[option] = self.app.get_eval(fname)
|
self.options[option] = self.app.get_eval(fname)
|
||||||
@@ -127,6 +138,18 @@ class CirkuixObj:
|
|||||||
return
|
return
|
||||||
print "Unknown kind of form item:", fkind
|
print "Unknown kind of form item:", fkind
|
||||||
|
|
||||||
|
def plot(self, figure):
|
||||||
|
"""
|
||||||
|
Extend this method! Sets up axes if needed and
|
||||||
|
clears them. Descendants must do the actual plotting.
|
||||||
|
"""
|
||||||
|
# Creates the axes if necessary and sets them up.
|
||||||
|
self.setup_axes(figure)
|
||||||
|
|
||||||
|
# Clear axes.
|
||||||
|
# self.axes.cla()
|
||||||
|
# return
|
||||||
|
|
||||||
|
|
||||||
class CirkuixGerber(CirkuixObj, Gerber):
|
class CirkuixGerber(CirkuixObj, Gerber):
|
||||||
"""
|
"""
|
||||||
@@ -149,9 +172,12 @@ class CirkuixGerber(CirkuixObj, Gerber):
|
|||||||
"cutoutmargin": 0.2,
|
"cutoutmargin": 0.2,
|
||||||
"cutoutgapsize": 0.15,
|
"cutoutgapsize": 0.15,
|
||||||
"gaps": "tb",
|
"gaps": "tb",
|
||||||
"noncoppermargin": 0.0
|
"noncoppermargin": 0.0,
|
||||||
|
"bboxmargin": 0.0,
|
||||||
|
"bboxrounded": False
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# The 'name' is already in self.form_kinds
|
||||||
self.form_kinds.update({
|
self.form_kinds.update({
|
||||||
"plot": "cb",
|
"plot": "cb",
|
||||||
"mergepolys": "cb",
|
"mergepolys": "cb",
|
||||||
@@ -161,14 +187,16 @@ class CirkuixGerber(CirkuixObj, Gerber):
|
|||||||
"cutoutmargin": "entry_eval",
|
"cutoutmargin": "entry_eval",
|
||||||
"cutoutgapsize": "entry_eval",
|
"cutoutgapsize": "entry_eval",
|
||||||
"gaps": "radio",
|
"gaps": "radio",
|
||||||
"noncoppermargin": "entry_eval"
|
"noncoppermargin": "entry_eval",
|
||||||
|
"bboxmargin": "entry_eval",
|
||||||
|
"bboxrounded": "cb"
|
||||||
})
|
})
|
||||||
|
|
||||||
self.radios = {"gaps": {"rb_2tb": "tb", "rb_2lr": "lr", "rb_4": "4"}}
|
self.radios = {"gaps": {"rb_2tb": "tb", "rb_2lr": "lr", "rb_4": "4"}}
|
||||||
self.radios_inv = {"gaps": {"tb": "rb_2tb", "lr": "rb_2lr", "4": "rb_4"}}
|
self.radios_inv = {"gaps": {"tb": "rb_2tb", "lr": "rb_2lr", "4": "rb_4"}}
|
||||||
|
|
||||||
def plot(self, figure):
|
def plot(self, figure):
|
||||||
self.setup_axes(figure)
|
CirkuixObj.plot(self, figure)
|
||||||
|
|
||||||
self.create_geometry()
|
self.create_geometry()
|
||||||
|
|
||||||
@@ -208,15 +236,25 @@ class CirkuixExcellon(CirkuixObj, Excellon):
|
|||||||
self.options.update({
|
self.options.update({
|
||||||
"plot": True,
|
"plot": True,
|
||||||
"solid": False,
|
"solid": False,
|
||||||
"multicolored": False
|
"multicolored": False,
|
||||||
|
"drillz": -0.1,
|
||||||
|
"travelz": 0.1,
|
||||||
|
"feedrate": 5.0,
|
||||||
|
"toolselection": ""
|
||||||
})
|
})
|
||||||
|
|
||||||
self.form_kinds.update({
|
self.form_kinds.update({
|
||||||
"plot": "cb",
|
"plot": "cb",
|
||||||
"solid": "cb",
|
"solid": "cb",
|
||||||
"multicolored": "cb"
|
"multicolored": "cb",
|
||||||
|
"drillz": "entry_eval",
|
||||||
|
"travelz": "entry_eval",
|
||||||
|
"feedrate": "entry_eval",
|
||||||
|
"toolselection": "entry_text"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
self.tool_cbs = {}
|
||||||
|
|
||||||
def plot(self, figure):
|
def plot(self, figure):
|
||||||
self.setup_axes(figure)
|
self.setup_axes(figure)
|
||||||
self.create_geometry()
|
self.create_geometry()
|
||||||
@@ -229,6 +267,30 @@ class CirkuixExcellon(CirkuixObj, Excellon):
|
|||||||
x, y = ints.coords.xy
|
x, y = ints.coords.xy
|
||||||
self.axes.plot(x, y, 'g-')
|
self.axes.plot(x, y, 'g-')
|
||||||
|
|
||||||
|
def show_tool_chooser(self):
|
||||||
|
win = Gtk.Window()
|
||||||
|
box = Gtk.Box(spacing=2)
|
||||||
|
box.set_orientation(Gtk.Orientation(1))
|
||||||
|
win.add(box)
|
||||||
|
for tool in self.tools:
|
||||||
|
self.tool_cbs[tool] = Gtk.CheckButton(label=tool+": "+self.tools[tool])
|
||||||
|
box.pack_start(self.tool_cbs[tool], False, False, 1)
|
||||||
|
button = Gtk.Button(label="Accept")
|
||||||
|
box.pack_start(button, False, False, 1)
|
||||||
|
win.show_all()
|
||||||
|
|
||||||
|
def on_accept(widget):
|
||||||
|
win.destroy()
|
||||||
|
tool_list = []
|
||||||
|
for tool in self.tool_cbs:
|
||||||
|
if self.tool_cbs[tool].get_active():
|
||||||
|
tool_list.append(tool)
|
||||||
|
self.options["toolselection"] = ", ".join(tool_list)
|
||||||
|
self.to_form()
|
||||||
|
|
||||||
|
button.connect("activate", on_accept)
|
||||||
|
button.connect("clicked", on_accept)
|
||||||
|
|
||||||
|
|
||||||
class CirkuixCNCjob(CirkuixObj, CNCjob):
|
class CirkuixCNCjob(CirkuixObj, CNCjob):
|
||||||
"""
|
"""
|
||||||
@@ -245,7 +307,7 @@ class CirkuixCNCjob(CirkuixObj, CNCjob):
|
|||||||
self.options.update({
|
self.options.update({
|
||||||
"plot": True,
|
"plot": True,
|
||||||
"solid": False,
|
"solid": False,
|
||||||
"multicolored": "cb",
|
"multicolored": False,
|
||||||
"tooldia": 0.4/25.4 # 0.4mm in inches
|
"tooldia": 0.4/25.4 # 0.4mm in inches
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -259,6 +321,7 @@ class CirkuixCNCjob(CirkuixObj, CNCjob):
|
|||||||
def plot(self, figure):
|
def plot(self, figure):
|
||||||
self.setup_axes(figure)
|
self.setup_axes(figure)
|
||||||
self.plot2(self.axes, tooldia=self.options["tooldia"])
|
self.plot2(self.axes, tooldia=self.options["tooldia"])
|
||||||
|
app.canvas.queue_draw()
|
||||||
|
|
||||||
|
|
||||||
class CirkuixGeometry(CirkuixObj, Geometry):
|
class CirkuixGeometry(CirkuixObj, Geometry):
|
||||||
@@ -279,8 +342,10 @@ class CirkuixGeometry(CirkuixObj, Geometry):
|
|||||||
"cutz": -0.002,
|
"cutz": -0.002,
|
||||||
"travelz": 0.1,
|
"travelz": 0.1,
|
||||||
"feedrate": 5.0,
|
"feedrate": 5.0,
|
||||||
|
"cnctooldia": 0.4/25.4,
|
||||||
"painttooldia": 0.0625,
|
"painttooldia": 0.0625,
|
||||||
"paintoverlap": 0.15
|
"paintoverlap": 0.15,
|
||||||
|
"paintmargin": 0.01
|
||||||
})
|
})
|
||||||
|
|
||||||
self.form_kinds.update({
|
self.form_kinds.update({
|
||||||
@@ -290,13 +355,20 @@ class CirkuixGeometry(CirkuixObj, Geometry):
|
|||||||
"cutz": "entry_eval",
|
"cutz": "entry_eval",
|
||||||
"travelz": "entry_eval",
|
"travelz": "entry_eval",
|
||||||
"feedrate": "entry_eval",
|
"feedrate": "entry_eval",
|
||||||
|
"cnctooldia": "entry_eval",
|
||||||
"painttooldia": "entry_eval",
|
"painttooldia": "entry_eval",
|
||||||
"paintoverlap": "entry_eval"
|
"paintoverlap": "entry_eval",
|
||||||
|
"paintmargin": "entry_eval"
|
||||||
})
|
})
|
||||||
|
|
||||||
def plot(self, figure):
|
def plot(self, figure):
|
||||||
self.setup_axes(figure)
|
self.setup_axes(figure)
|
||||||
|
|
||||||
|
try:
|
||||||
|
_ = iter(self.solid_geometry)
|
||||||
|
except TypeError:
|
||||||
|
self.solid_geometry = [self.solid_geometry]
|
||||||
|
|
||||||
for geo in self.solid_geometry:
|
for geo in self.solid_geometry:
|
||||||
|
|
||||||
if type(geo) == Polygon:
|
if type(geo) == Polygon:
|
||||||
@@ -312,6 +384,17 @@ class CirkuixGeometry(CirkuixObj, Geometry):
|
|||||||
self.axes.plot(x, y, 'r-')
|
self.axes.plot(x, y, 'r-')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if type(geo) == MultiPolygon:
|
||||||
|
for poly in geo:
|
||||||
|
x, y = poly.exterior.coords.xy
|
||||||
|
self.axes.plot(x, y, 'r-')
|
||||||
|
for ints in poly.interiors:
|
||||||
|
x, y = ints.coords.xy
|
||||||
|
self.axes.plot(x, y, 'r-')
|
||||||
|
continue
|
||||||
|
|
||||||
|
print "WARNING: Did not plot:", str(type(geo))
|
||||||
|
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
## App ##
|
## App ##
|
||||||
@@ -332,9 +415,7 @@ class App:
|
|||||||
GObject.threads_init()
|
GObject.threads_init()
|
||||||
#Gdk.threads_init()
|
#Gdk.threads_init()
|
||||||
|
|
||||||
########################################
|
## GUI ##
|
||||||
## GUI ##
|
|
||||||
########################################
|
|
||||||
self.gladefile = "cirkuix.ui"
|
self.gladefile = "cirkuix.ui"
|
||||||
self.builder = Gtk.Builder()
|
self.builder = Gtk.Builder()
|
||||||
self.builder.add_from_file(self.gladefile)
|
self.builder.add_from_file(self.gladefile)
|
||||||
@@ -359,9 +440,7 @@ class App:
|
|||||||
self.setup_component_viewer()
|
self.setup_component_viewer()
|
||||||
self.setup_component_editor()
|
self.setup_component_editor()
|
||||||
|
|
||||||
########################################
|
## DATA ##
|
||||||
## DATA ##
|
|
||||||
########################################
|
|
||||||
self.setup_obj_classes()
|
self.setup_obj_classes()
|
||||||
self.stuff = {} # CirkuixObj's by name
|
self.stuff = {} # CirkuixObj's by name
|
||||||
self.mouse = None # Mouse coordinates over plot
|
self.mouse = None # Mouse coordinates over plot
|
||||||
@@ -634,12 +713,107 @@ class App:
|
|||||||
########################################
|
########################################
|
||||||
## EVENT HANDLERS ##
|
## EVENT HANDLERS ##
|
||||||
########################################
|
########################################
|
||||||
|
def on_generate_gerber_bounding_box(self, widget):
|
||||||
|
gerber = self.stuff[self.selected_item_name]
|
||||||
|
gerber.read_form()
|
||||||
|
name = self.selected_item_name + "_bbox"
|
||||||
|
|
||||||
|
def geo_init(geo_obj, app_obj):
|
||||||
|
assert isinstance(geo_obj, CirkuixGeometry)
|
||||||
|
bounding_box = gerber.solid_geometry.envelope.buffer(gerber.options["bboxmargin"])
|
||||||
|
if not gerber.options["bboxrounded"]:
|
||||||
|
bounding_box = bounding_box.envelope
|
||||||
|
geo_obj.solid_geometry = bounding_box
|
||||||
|
|
||||||
|
self.new_object("geometry", name, geo_init)
|
||||||
|
|
||||||
|
def on_update_plot(self, widget):
|
||||||
|
"""
|
||||||
|
Callback for button on form for all kinds of objects.
|
||||||
|
Re-plot the current object only.
|
||||||
|
@param widget: The widget from which this was called.
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
|
self.stuff[self.selected_item_name].read_form()
|
||||||
|
self.stuff[self.selected_item_name].plot(self.figure)
|
||||||
|
|
||||||
|
def on_generate_excellon_cncjob(self, widget):
|
||||||
|
"""
|
||||||
|
Callback for button active/click on Excellon form to
|
||||||
|
create a CNC Job for the Excellon file.
|
||||||
|
@param widget: The widget from which this was called.
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
|
|
||||||
|
job_name = self.selected_item_name + "_cnc"
|
||||||
|
excellon = self.stuff[self.selected_item_name]
|
||||||
|
assert isinstance(excellon, CirkuixExcellon)
|
||||||
|
excellon.read_form()
|
||||||
|
|
||||||
|
# Object initialization function for app.new_object()
|
||||||
|
def job_init(job_obj, app_obj):
|
||||||
|
excellon_ = self.stuff[self.selected_item_name]
|
||||||
|
assert isinstance(excellon_, CirkuixExcellon)
|
||||||
|
assert isinstance(job_obj, CirkuixCNCjob)
|
||||||
|
|
||||||
|
GLib.idle_add(lambda: app_obj.set_progress_bar(0.2, "Creating CNC Job..."))
|
||||||
|
job_obj.z_cut = excellon_.options["drillz"]
|
||||||
|
job_obj.z_move = excellon_.options["travelz"]
|
||||||
|
job_obj.feedrate = excellon_.options["feedrate"]
|
||||||
|
# There could be more than one drill size...
|
||||||
|
# job_obj.tooldia = # TODO: duplicate variable!
|
||||||
|
# job_obj.options["tooldia"] =
|
||||||
|
job_obj.generate_from_excellon_by_tool(excellon_, excellon_.options["toolselection"])
|
||||||
|
|
||||||
|
GLib.idle_add(lambda: app_obj.set_progress_bar(0.5, "Parsing G-Code..."))
|
||||||
|
job_obj.gcode_parse()
|
||||||
|
|
||||||
|
GLib.idle_add(lambda: app_obj.set_progress_bar(0.6, "Creating New Geometry..."))
|
||||||
|
job_obj.create_geometry()
|
||||||
|
|
||||||
|
GLib.idle_add(lambda: app_obj.set_progress_bar(0.8, "Plotting..."))
|
||||||
|
|
||||||
|
# To be run in separate thread
|
||||||
|
def job_thread(app_obj):
|
||||||
|
app_obj.new_object("cncjob", job_name, job_init)
|
||||||
|
GLib.idle_add(lambda: app_obj.set_progress_bar(1.0, "Done!"))
|
||||||
|
GLib.timeout_add_seconds(1, lambda: app_obj.set_progress_bar(0.0, ""))
|
||||||
|
|
||||||
|
# Start the thread
|
||||||
|
t = threading.Thread(target=job_thread, args=(self,))
|
||||||
|
t.daemon = True
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def on_excellon_tool_choose(self, widget):
|
||||||
|
"""
|
||||||
|
Callback for button on Excellon form to open up a window for
|
||||||
|
selecting tools.
|
||||||
|
@param widget: The widget from which this was called.
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
|
excellon = self.stuff[self.selected_item_name]
|
||||||
|
assert isinstance(excellon, CirkuixExcellon)
|
||||||
|
excellon.show_tool_chooser()
|
||||||
|
|
||||||
|
def on_entry_eval_activate(self, widget):
|
||||||
|
self.on_eval_update(widget)
|
||||||
|
obj = self.stuff[self.selected_item_name]
|
||||||
|
assert isinstance(obj, CirkuixObj)
|
||||||
|
obj.read_form()
|
||||||
|
|
||||||
def on_gerber_generate_noncopper(self, widget):
|
def on_gerber_generate_noncopper(self, widget):
|
||||||
|
"""
|
||||||
|
Callback for button on Gerber form to create a geometry object
|
||||||
|
with polygons covering the area without copper or negative of the
|
||||||
|
Gerber.
|
||||||
|
@param widget: The widget from which this was called.
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
name = self.selected_item_name + "_noncopper"
|
name = self.selected_item_name + "_noncopper"
|
||||||
|
|
||||||
def geo_init(geo_obj, app_obj):
|
def geo_init(geo_obj, app_obj):
|
||||||
assert isinstance(geo_obj, CirkuixGeometry)
|
assert isinstance(geo_obj, CirkuixGeometry)
|
||||||
gerber = app_obj.stuff[self.selected_item_name]
|
gerber = app_obj.stuff[app_obj.selected_item_name]
|
||||||
assert isinstance(gerber, CirkuixGerber)
|
assert isinstance(gerber, CirkuixGerber)
|
||||||
gerber.read_form()
|
gerber.read_form()
|
||||||
bounding_box = gerber.solid_geometry.envelope.buffer(gerber.options["noncoppermargin"])
|
bounding_box = gerber.solid_geometry.envelope.buffer(gerber.options["noncoppermargin"])
|
||||||
@@ -650,6 +824,12 @@ class App:
|
|||||||
self.new_object("geometry", name, geo_init)
|
self.new_object("geometry", name, geo_init)
|
||||||
|
|
||||||
def on_gerber_generate_cutout(self, widget):
|
def on_gerber_generate_cutout(self, widget):
|
||||||
|
"""
|
||||||
|
Callback for button on Gerber form to create geometry with lines
|
||||||
|
for cutting off the board.
|
||||||
|
@param widget: The widget from which this was called.
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
name = self.selected_item_name + "_cutout"
|
name = self.selected_item_name + "_cutout"
|
||||||
|
|
||||||
def geo_init(geo_obj, app_obj):
|
def geo_init(geo_obj, app_obj):
|
||||||
@@ -696,11 +876,18 @@ class App:
|
|||||||
Modifies the content of a Gtk.Entry by running
|
Modifies the content of a Gtk.Entry by running
|
||||||
eval() on its contents and puting it back as a
|
eval() on its contents and puting it back as a
|
||||||
string.
|
string.
|
||||||
|
@param widget: The widget from which this was called.
|
||||||
|
@return: None
|
||||||
"""
|
"""
|
||||||
# TODO: error handling here
|
# TODO: error handling here
|
||||||
widget.set_text(str(eval(widget.get_text())))
|
widget.set_text(str(eval(widget.get_text())))
|
||||||
|
|
||||||
def on_generate_isolation(self, widget):
|
def on_generate_isolation(self, widget):
|
||||||
|
"""
|
||||||
|
Callback for button on Gerber form to create isolation routing geometry.
|
||||||
|
@param widget: The widget from which this was called.
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
print "Generating Isolation Geometry:"
|
print "Generating Isolation Geometry:"
|
||||||
iso_name = self.selected_item_name + "_iso"
|
iso_name = self.selected_item_name + "_iso"
|
||||||
|
|
||||||
@@ -714,45 +901,75 @@ class App:
|
|||||||
self.new_object("geometry", iso_name, iso_init)
|
self.new_object("geometry", iso_name, iso_init)
|
||||||
|
|
||||||
def on_generate_cncjob(self, widget):
|
def on_generate_cncjob(self, widget):
|
||||||
|
"""
|
||||||
|
Callback for button on geometry form to generate CNC job.
|
||||||
|
@param widget: The widget from which this was called.
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
print "Generating CNC job"
|
print "Generating CNC job"
|
||||||
|
|
||||||
job_name = self.selected_item_name + "_cnc"
|
job_name = self.selected_item_name + "_cnc"
|
||||||
|
|
||||||
|
# Object initialization function for app.new_object()
|
||||||
def job_init(job_obj, app_obj):
|
def job_init(job_obj, app_obj):
|
||||||
# TODO: Object must be updated on form change and the options
|
|
||||||
# TODO: read from the object.
|
|
||||||
z_cut = app_obj.get_eval("entry_eval_geometry_cutz")
|
|
||||||
z_move = app_obj.get_eval("entry_eval_geometry_travelz")
|
|
||||||
feedrate = app_obj.get_eval("entry_eval_geometry_feedrate")
|
|
||||||
|
|
||||||
geometry = app_obj.stuff[app_obj.selected_item_name]
|
|
||||||
assert isinstance(job_obj, CirkuixCNCjob)
|
assert isinstance(job_obj, CirkuixCNCjob)
|
||||||
job_obj.z_cut = z_cut
|
geometry = app_obj.stuff[app_obj.selected_item_name]
|
||||||
job_obj.z_move = z_move
|
assert isinstance(geometry, CirkuixGeometry)
|
||||||
job_obj.feedrate = feedrate
|
geometry.read_form()
|
||||||
job_obj.generate_from_geometry(geometry.solid_geometry)
|
|
||||||
|
GLib.idle_add(lambda: app_obj.set_progress_bar(0.2, "Creating CNC Job..."))
|
||||||
|
job_obj.z_cut = geometry.options["cutz"]
|
||||||
|
job_obj.z_move = geometry.options["travelz"]
|
||||||
|
job_obj.feedrate = geometry.options["feedrate"]
|
||||||
|
job_obj.options["tooldia"] = geometry.options["cnctooldia"]
|
||||||
|
|
||||||
|
GLib.idle_add(lambda: app_obj.set_progress_bar(0.4, "Analyzing Geometry..."))
|
||||||
|
job_obj.generate_from_geometry(geometry)
|
||||||
|
|
||||||
|
GLib.idle_add(lambda: app_obj.set_progress_bar(0.5, "Parsing G-Code..."))
|
||||||
job_obj.gcode_parse()
|
job_obj.gcode_parse()
|
||||||
|
|
||||||
|
GLib.idle_add(lambda: app_obj.set_progress_bar(0.6, "Creating New Geometry..."))
|
||||||
job_obj.create_geometry()
|
job_obj.create_geometry()
|
||||||
|
|
||||||
self.new_object("cncjob", job_name, job_init)
|
GLib.idle_add(lambda: app_obj.set_progress_bar(0.8, "Plotting..."))
|
||||||
|
|
||||||
|
# To be run in separate thread
|
||||||
|
def job_thread(app_obj):
|
||||||
|
app_obj.new_object("cncjob", job_name, job_init)
|
||||||
|
GLib.idle_add(lambda: app_obj.set_progress_bar(1.0, "Done!"))
|
||||||
|
GLib.timeout_add_seconds(1, lambda: app_obj.set_progress_bar(0.0, ""))
|
||||||
|
|
||||||
|
# Start the thread
|
||||||
|
t = threading.Thread(target=job_thread, args=(self,))
|
||||||
|
t.daemon = True
|
||||||
|
t.start()
|
||||||
|
|
||||||
def on_generate_paintarea(self, widget):
|
def on_generate_paintarea(self, widget):
|
||||||
|
"""
|
||||||
|
Callback for button on geometry form.
|
||||||
|
Subscribes to the "Click on plot" event and continues
|
||||||
|
after the click. Finds the polygon containing
|
||||||
|
the clicked point and runs clear_poly() on it, resulting
|
||||||
|
in a new CirkuixGeometry object.
|
||||||
|
"""
|
||||||
self.info("Click inside the desired polygon.")
|
self.info("Click inside the desired polygon.")
|
||||||
geo = self.stuff[self.selected_item_name]
|
geo = self.stuff[self.selected_item_name]
|
||||||
geo.read_form()
|
geo.read_form()
|
||||||
tooldia = geo.options["painttooldia"]
|
tooldia = geo.options["painttooldia"]
|
||||||
overlap = geo.options["paintoverlap"]
|
overlap = geo.options["paintoverlap"]
|
||||||
|
|
||||||
|
# To be called after clicking on the plot.
|
||||||
def doit(event):
|
def doit(event):
|
||||||
self.plot_click_subscribers.pop("generate_paintarea")
|
self.plot_click_subscribers.pop("generate_paintarea")
|
||||||
self.info("")
|
self.info("")
|
||||||
point = [event.xdata, event.ydata]
|
point = [event.xdata, event.ydata]
|
||||||
poly = find_polygon(geo.solid_geometry, point)
|
poly = find_polygon(geo.solid_geometry, point)
|
||||||
|
|
||||||
|
# Initializes the new geometry object
|
||||||
def gen_paintarea(geo_obj, app_obj):
|
def gen_paintarea(geo_obj, app_obj):
|
||||||
assert isinstance(geo_obj, CirkuixGeometry)
|
assert isinstance(geo_obj, CirkuixGeometry)
|
||||||
assert isinstance(app_obj, App)
|
assert isinstance(app_obj, App)
|
||||||
cp = clear_poly(poly, tooldia, overlap)
|
cp = clear_poly(poly.buffer(-geo.options["paintmargin"]), tooldia, overlap)
|
||||||
geo_obj.solid_geometry = cp
|
geo_obj.solid_geometry = cp
|
||||||
|
|
||||||
name = self.selected_item_name + "_paint"
|
name = self.selected_item_name + "_paint"
|
||||||
@@ -760,12 +977,6 @@ class App:
|
|||||||
|
|
||||||
self.plot_click_subscribers["generate_paintarea"] = doit
|
self.plot_click_subscribers["generate_paintarea"] = doit
|
||||||
|
|
||||||
def on_cncjob_tooldia_activate(self, widget):
|
|
||||||
job = self.stuff[self.selected_item_name]
|
|
||||||
tooldia = self.get_eval("entry_eval_cncjob_tooldia")
|
|
||||||
job.tooldia = tooldia
|
|
||||||
print "Changing tool diameter to:", tooldia
|
|
||||||
|
|
||||||
def on_cncjob_exportgcode(self, widget):
|
def on_cncjob_exportgcode(self, widget):
|
||||||
def on_success(self, filename):
|
def on_success(self, filename):
|
||||||
cncjob = self.stuff[self.selected_item_name]
|
cncjob = self.stuff[self.selected_item_name]
|
||||||
@@ -840,10 +1051,10 @@ class App:
|
|||||||
Gtk.main_quit()
|
Gtk.main_quit()
|
||||||
|
|
||||||
def file_chooser_action(self, on_success):
|
def file_chooser_action(self, on_success):
|
||||||
'''
|
"""
|
||||||
Opens the file chooser and runs on_success on a separate thread
|
Opens the file chooser and runs on_success on a separate thread
|
||||||
upon completion of valid file choice.
|
upon completion of valid file choice.
|
||||||
'''
|
"""
|
||||||
dialog = Gtk.FileChooserDialog("Please choose a file", self.window,
|
dialog = Gtk.FileChooserDialog("Please choose a file", self.window,
|
||||||
Gtk.FileChooserAction.OPEN,
|
Gtk.FileChooserAction.OPEN,
|
||||||
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
||||||
@@ -979,7 +1190,7 @@ class App:
|
|||||||
|
|
||||||
for subscriber in self.plot_click_subscribers:
|
for subscriber in self.plot_click_subscribers:
|
||||||
self.plot_click_subscribers[subscriber](event)
|
self.plot_click_subscribers[subscriber](event)
|
||||||
except:
|
except Exception, e:
|
||||||
print "Outside plot!"
|
print "Outside plot!"
|
||||||
|
|
||||||
def on_zoom_in(self, event):
|
def on_zoom_in(self, event):
|
||||||
@@ -1045,15 +1256,15 @@ class App:
|
|||||||
def on_key_over_plot(self, event):
|
def on_key_over_plot(self, event):
|
||||||
print 'you pressed', event.key, event.xdata, event.ydata
|
print 'you pressed', event.key, event.xdata, event.ydata
|
||||||
|
|
||||||
if event.key == '1': # 1
|
if event.key == '1': # 1
|
||||||
self.on_zoom_fit(None)
|
self.on_zoom_fit(None)
|
||||||
return
|
return
|
||||||
|
|
||||||
if event.key == '2': # 2
|
if event.key == '2': # 2
|
||||||
self.zoom(1/1.5, self.mouse)
|
self.zoom(1/1.5, self.mouse)
|
||||||
return
|
return
|
||||||
|
|
||||||
if event.key == '3': # 3
|
if event.key == '3': # 3
|
||||||
self.zoom(1.5, self.mouse)
|
self.zoom(1.5, self.mouse)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
439
cirkuix.ui
439
cirkuix.ui
@@ -94,6 +94,7 @@
|
|||||||
<object class="GtkLabel" id="label19">
|
<object class="GtkLabel" id="label19">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="ypad">3</property>
|
<property name="ypad">3</property>
|
||||||
<property name="label" translatable="yes">Plot Options:</property>
|
<property name="label" translatable="yes">Plot Options:</property>
|
||||||
@@ -179,7 +180,7 @@
|
|||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="invisible_char">●</property>
|
<property name="invisible_char">●</property>
|
||||||
<property name="invisible_char_set">True</property>
|
<property name="invisible_char_set">True</property>
|
||||||
<signal name="activate" handler="on_cncjob_tooldia_activate" swapped="no"/>
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
@@ -194,6 +195,21 @@
|
|||||||
<property name="position">6</property>
|
<property name="position">6</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="button11">
|
||||||
|
<property name="label" translatable="yes">Update Plot</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="activate" handler="on_update_plot" swapped="no"/>
|
||||||
|
<signal name="clicked" handler="on_update_plot" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">7</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="label26">
|
<object class="GtkLabel" id="label26">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
@@ -209,7 +225,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">7</property>
|
<property name="position">8</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -224,12 +240,9 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">8</property>
|
<property name="position">9</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
@@ -375,16 +388,206 @@
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<object class="GtkButton" id="button12">
|
||||||
|
<property name="label" translatable="yes">Update Plot</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="activate" handler="on_update_plot" swapped="no"/>
|
||||||
|
<signal name="clicked" handler="on_update_plot" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">6</property>
|
||||||
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<object class="GtkLabel" id="label36">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="ypad">3</property>
|
||||||
|
<property name="label" translatable="yes">Create CNC Job:</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="semibold"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">7</property>
|
||||||
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<object class="GtkGrid" id="grid6">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="row_spacing">2</property>
|
||||||
|
<property name="column_spacing">4</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="entry_eval_excellon_drillz">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="entry_eval_excellon_travelz">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="entry_eval_excellon_feedrate">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label37">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">Drill Z:</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label38">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">Travel Z:</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label39">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">Feed rate:</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label40">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">Tools:</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">3</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="box3">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="entry_text_excellon_toolselection">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="button8">
|
||||||
|
<property name="label" translatable="yes">Choose</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="activate" handler="on_excellon_tool_choose" swapped="no"/>
|
||||||
|
<signal name="clicked" handler="on_excellon_tool_choose" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">3</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">8</property>
|
||||||
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<object class="GtkButton" id="button7">
|
||||||
|
<property name="label" translatable="yes">Generate</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="activate" handler="on_generate_excellon_cncjob" swapped="no"/>
|
||||||
|
<signal name="clicked" handler="on_generate_excellon_cncjob" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">9</property>
|
||||||
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
@@ -531,6 +734,21 @@
|
|||||||
<property name="position">5</property>
|
<property name="position">5</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="button13">
|
||||||
|
<property name="label" translatable="yes">Update Plot</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="activate" handler="on_update_plot" swapped="no"/>
|
||||||
|
<signal name="clicked" handler="on_update_plot" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">6</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="label21">
|
<object class="GtkLabel" id="label21">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
@@ -546,7 +764,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">6</property>
|
<property name="position">7</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -561,6 +779,7 @@
|
|||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="invisible_char">●</property>
|
<property name="invisible_char">●</property>
|
||||||
<property name="invisible_char_set">True</property>
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
@@ -575,6 +794,7 @@
|
|||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="invisible_char">●</property>
|
<property name="invisible_char">●</property>
|
||||||
<property name="invisible_char_set">True</property>
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
@@ -589,6 +809,7 @@
|
|||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="invisible_char">●</property>
|
<property name="invisible_char">●</property>
|
||||||
<property name="invisible_char_set">True</property>
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
@@ -639,11 +860,40 @@
|
|||||||
<property name="height">1</property>
|
<property name="height">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label34">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">Tool diam:</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">3</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="entry_eval_geometry_cnctooldia">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">3</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">7</property>
|
<property name="position">8</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -658,7 +908,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">8</property>
|
<property name="position">9</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -676,7 +926,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">9</property>
|
<property name="position">10</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -705,6 +955,7 @@
|
|||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="invisible_char">●</property>
|
<property name="invisible_char">●</property>
|
||||||
<property name="invisible_char_set">True</property>
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
@@ -733,6 +984,7 @@
|
|||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="invisible_char">●</property>
|
<property name="invisible_char">●</property>
|
||||||
<property name="invisible_char_set">True</property>
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
@@ -741,11 +993,40 @@
|
|||||||
<property name="height">1</property>
|
<property name="height">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label35">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">Margin:</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="entry_eval_geometry_paintmargin">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_entry_eval_activate" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">10</property>
|
<property name="position">11</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -760,15 +1041,12 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">11</property>
|
<property name="position">12</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<placeholder/>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
@@ -854,6 +1132,7 @@
|
|||||||
<object class="GtkLabel" id="label9">
|
<object class="GtkLabel" id="label9">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="ypad">3</property>
|
<property name="ypad">3</property>
|
||||||
<property name="label" translatable="yes">Plot Options:</property>
|
<property name="label" translatable="yes">Plot Options:</property>
|
||||||
@@ -929,6 +1208,21 @@
|
|||||||
<property name="position">6</property>
|
<property name="position">6</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="button9">
|
||||||
|
<property name="label" translatable="yes">Update Plot</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="activate" handler="on_update_plot" swapped="no"/>
|
||||||
|
<signal name="clicked" handler="on_update_plot" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">7</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="label13">
|
<object class="GtkLabel" id="label13">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
@@ -944,7 +1238,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">7</property>
|
<property name="position">8</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -990,7 +1284,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">8</property>
|
<property name="position">9</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -1005,7 +1299,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">9</property>
|
<property name="position">10</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -1023,7 +1317,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">10</property>
|
<property name="position">11</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -1171,7 +1465,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">11</property>
|
<property name="position">12</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -1186,7 +1480,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">12</property>
|
<property name="position">13</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -1204,7 +1498,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">13</property>
|
<property name="position">14</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -1246,7 +1540,7 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">14</property>
|
<property name="position">15</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -1261,11 +1555,98 @@
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">15</property>
|
<property name="position">16</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<object class="GtkLabel" id="label41">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="ypad">3</property>
|
||||||
|
<property name="label" translatable="yes">Bounding box:</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="semibold"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">17</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="box4">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">4</property>
|
||||||
|
<property name="margin_bottom">4</property>
|
||||||
|
<property name="spacing">1</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label42">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">Boundary margin: </property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="entry_eval_gerber_bboxmargin">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="width_chars">14</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
<signal name="activate" handler="on_eval_update" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">18</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="cb_gerber_bboxrounded">
|
||||||
|
<property name="label" translatable="yes">Rounded corners</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="draw_indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">19</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="button10">
|
||||||
|
<property name="label" translatable="yes">Generate Bounding Box</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<signal name="activate" handler="on_generate_gerber_bounding_box" swapped="no"/>
|
||||||
|
<signal name="clicked" handler="on_generate_gerber_bounding_box" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">20</property>
|
||||||
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<placeholder/>
|
<placeholder/>
|
||||||
|
|||||||
Reference in New Issue
Block a user