|
@@ -107,6 +107,9 @@ class Gerber (Geometry):
|
|
|
# Flashes [{'loc':[float,float], 'aperture':dict}]
|
|
# Flashes [{'loc':[float,float], 'aperture':dict}]
|
|
|
self.flashes = []
|
|
self.flashes = []
|
|
|
|
|
|
|
|
|
|
+ # Geometry from flashes
|
|
|
|
|
+ self.flash_geometry = []
|
|
|
|
|
+
|
|
|
def fix_regions(self):
|
|
def fix_regions(self):
|
|
|
'''
|
|
'''
|
|
|
Overwrites the region polygons with fixed
|
|
Overwrites the region polygons with fixed
|
|
@@ -227,17 +230,14 @@ class Gerber (Geometry):
|
|
|
# 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 create_geometry(self):
|
|
|
|
|
- if len(self.buffered_paths) == 0:
|
|
|
|
|
- self.buffer_paths()
|
|
|
|
|
- self.fix_regions()
|
|
|
|
|
- flash_polys = []
|
|
|
|
|
|
|
+
|
|
|
|
|
+ def do_flashes(self):
|
|
|
|
|
+ self.flash_geometry = []
|
|
|
for flash in self.flashes:
|
|
for flash in self.flashes:
|
|
|
aperture = self.apertures[flash['aperture']]
|
|
aperture = self.apertures[flash['aperture']]
|
|
|
if aperture['type'] == 'C': # Circles
|
|
if aperture['type'] == 'C': # Circles
|
|
|
circle = Point(flash['loc']).buffer(aperture['size']/2)
|
|
circle = Point(flash['loc']).buffer(aperture['size']/2)
|
|
|
- flash_polys.append(circle)
|
|
|
|
|
|
|
+ self.flash_geometry.append(circle)
|
|
|
continue
|
|
continue
|
|
|
if aperture['type'] == 'R': # Rectangles
|
|
if aperture['type'] == 'R': # Rectangles
|
|
|
loc = flash['loc']
|
|
loc = flash['loc']
|
|
@@ -248,14 +248,20 @@ class Gerber (Geometry):
|
|
|
miny = loc[1] - height/2
|
|
miny = loc[1] - height/2
|
|
|
maxy = loc[1] + height/2
|
|
maxy = loc[1] + height/2
|
|
|
rectangle = shply_box(minx, miny, maxx, maxy)
|
|
rectangle = shply_box(minx, miny, maxx, maxy)
|
|
|
- flash_polys.append(rectangle)
|
|
|
|
|
|
|
+ self.flash_geometry.append(rectangle)
|
|
|
continue
|
|
continue
|
|
|
- print "WARNING: Aperture type %s not implemented"%(aperture['type'])
|
|
|
|
|
#TODO: Add support for type='O'
|
|
#TODO: Add support for type='O'
|
|
|
|
|
+ print "WARNING: Aperture type %s not implemented"%(aperture['type'])
|
|
|
|
|
+
|
|
|
|
|
+ def create_geometry(self):
|
|
|
|
|
+ if len(self.buffered_paths) == 0:
|
|
|
|
|
+ self.buffer_paths()
|
|
|
|
|
+ self.fix_regions()
|
|
|
|
|
+ self.do_flashes()
|
|
|
self.solid_geometry = cascaded_union(
|
|
self.solid_geometry = cascaded_union(
|
|
|
self.buffered_paths +
|
|
self.buffered_paths +
|
|
|
[poly['polygon'] for poly in self.regions] +
|
|
[poly['polygon'] for poly in self.regions] +
|
|
|
- flash_polys)
|
|
|
|
|
|
|
+ self.flash_geometry)
|
|
|
|
|
|
|
|
class CNCjob:
|
|
class CNCjob:
|
|
|
def __init__(self, units="in", kind="generic", z_move = 0.1,
|
|
def __init__(self, units="in", kind="generic", z_move = 0.1,
|
|
@@ -546,75 +552,8 @@ class Excellon(Geometry):
|
|
|
for drill in self.drills:
|
|
for drill in self.drills:
|
|
|
poly = Point(drill['point']).buffer(sizes[drill['tool']]/2.0)
|
|
poly = Point(drill['point']).buffer(sizes[drill['tool']]/2.0)
|
|
|
self.solid_geometry.append(poly)
|
|
self.solid_geometry.append(poly)
|
|
|
-
|
|
|
|
|
-def fix_poly(poly):
|
|
|
|
|
- '''
|
|
|
|
|
- Fixes polygons with internal cutouts by identifying
|
|
|
|
|
- loops and touching segments. Loops are extracted
|
|
|
|
|
- as individual polygons. If a smaller loop is still
|
|
|
|
|
- not a valid Polygon, fix_poly2() adds vertices such
|
|
|
|
|
- that fix_poly() can continue to extract smaller loops.
|
|
|
|
|
- '''
|
|
|
|
|
- if poly.is_valid: # Nothing to do
|
|
|
|
|
- return [poly]
|
|
|
|
|
-
|
|
|
|
|
- coords = poly.exterior.coords[:]
|
|
|
|
|
- n_points = len(coords)
|
|
|
|
|
- i = 0
|
|
|
|
|
- result = []
|
|
|
|
|
- while i<n_points:
|
|
|
|
|
- if coords[i] in coords[:i]: # closed a loop
|
|
|
|
|
- j = coords[:i].index(coords[i]) # index of repeated point
|
|
|
|
|
-
|
|
|
|
|
- if i-j>1: # points do not repeat in 1 step
|
|
|
|
|
- sub_poly = Polygon(coords[j:i+1])
|
|
|
|
|
- if sub_poly.is_valid:
|
|
|
|
|
- result.append(sub_poly)
|
|
|
|
|
- elif sub_poly.area > 0:
|
|
|
|
|
- sub_poly = fix_poly2(sub_poly)
|
|
|
|
|
- result += fix_poly(sub_poly) # try again
|
|
|
|
|
-
|
|
|
|
|
- # Preserve the repeated point such as not to break the
|
|
|
|
|
- # remaining geometry
|
|
|
|
|
- remaining = coords[:j+1]+coords[i+1:n_points+1]
|
|
|
|
|
- rem_poly = Polygon(remaining)
|
|
|
|
|
- if len(remaining)>2 and rem_poly.area > 0:
|
|
|
|
|
- result += fix_poly(rem_poly)
|
|
|
|
|
- break
|
|
|
|
|
- i += 1
|
|
|
|
|
- return result
|
|
|
|
|
-
|
|
|
|
|
-def fix_poly2(poly):
|
|
|
|
|
- coords = poly.exterior.coords[:]
|
|
|
|
|
- n_points = len(coords)
|
|
|
|
|
- ls = None
|
|
|
|
|
- i = 1
|
|
|
|
|
- while i<n_points:
|
|
|
|
|
- ls = LineString(coords[i-1:i+1])
|
|
|
|
|
- other_points = coords[:i-1]+coords[i+1:] # i=3 ... [0:2] + [4:]
|
|
|
|
|
- if ls.intersects(MultiPoint(other_points)):
|
|
|
|
|
- # Add a copy of that point to the segment
|
|
|
|
|
- isect = ls.intersection(MultiPoint(other_points))
|
|
|
|
|
- if type(isect) == Point:
|
|
|
|
|
- if isect.coords[0] != coords[i-1] and isect.coords[0] != coords[i]:
|
|
|
|
|
- coords = coords[:i] + [isect.coords[0]] + coords[i:]
|
|
|
|
|
- if type(isect) == MultiPoint:
|
|
|
|
|
- for p in isect:
|
|
|
|
|
- if p.coords[0] != coords[i-1] and p.coords[0] != coords[i]:
|
|
|
|
|
- coords = coords[:i] + [p.coords[0]] + coords[i:]
|
|
|
|
|
- return Polygon(coords)
|
|
|
|
|
- return Polygon(coords)
|
|
|
|
|
|
|
+ self.solid_geometry = cascaded_union(self.solid_geometry)
|
|
|
|
|
|
|
|
-def fix_poly3(polylist):
|
|
|
|
|
- mp = MultiPolygon(polylist)
|
|
|
|
|
- interior = None
|
|
|
|
|
- exterior = None
|
|
|
|
|
- for i in range(len(polylist)):
|
|
|
|
|
- if polylist[i].contains(mp):
|
|
|
|
|
- exterior = polylist[i]
|
|
|
|
|
- interior = polylist[:i]+polylist[i+1:]
|
|
|
|
|
- return Polygon(exterior.exterior.coords[:],
|
|
|
|
|
- [p.exterior.coords[:] for p in interior])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class motion:
|
|
class motion:
|
|
@@ -815,277 +754,6 @@ def gparse2(gcmds):
|
|
|
|
|
|
|
|
return xmin, xmax, ymin, ymax, motions
|
|
return xmin, xmax, ymin, ymax, motions
|
|
|
|
|
|
|
|
-class canvas:
|
|
|
|
|
- def __init__(self):
|
|
|
|
|
- self.surface = None
|
|
|
|
|
- self.context = None
|
|
|
|
|
- self.origin = [0, 0] # Pixel coordinate
|
|
|
|
|
- self.resolution = 200.0 # Pixels per unit.
|
|
|
|
|
- self.pixel_height = 0
|
|
|
|
|
- self.pixel_width = 0
|
|
|
|
|
-
|
|
|
|
|
- def create_surface(self, width, height):
|
|
|
|
|
- self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
|
|
|
|
|
-
|
|
|
|
|
- def crosshair(self, x, y, s):
|
|
|
|
|
- cr = self.context
|
|
|
|
|
- cr.set_line_width (1.0/self.resolution)
|
|
|
|
|
- cr.set_line_cap(cairo.LINE_CAP_ROUND)
|
|
|
|
|
- cr.set_source_rgba (1, 0, 0, 1)
|
|
|
|
|
- cr.move_to(x-s, y-s)
|
|
|
|
|
- cr.line_to(x+s, y+s)
|
|
|
|
|
- cr.stroke()
|
|
|
|
|
- cr.move_to(x-s, y+s)
|
|
|
|
|
- cr.line_to(x+s, y-s)
|
|
|
|
|
- cr.stroke()
|
|
|
|
|
-
|
|
|
|
|
- def draw_motions(self, motions, linewidth, margin=10):
|
|
|
|
|
- # Has many things in common with draw boundaries, merge.
|
|
|
|
|
- # Analyze motions
|
|
|
|
|
- X = 0
|
|
|
|
|
- Y = 1
|
|
|
|
|
- xmin = Inf
|
|
|
|
|
- xmax = -Inf
|
|
|
|
|
- ymin = Inf
|
|
|
|
|
- ymax = -Inf
|
|
|
|
|
- for mot in motions:
|
|
|
|
|
- if mot.start[X] < xmin:
|
|
|
|
|
- xmin = mot.start[X]
|
|
|
|
|
- if mot.end[X] < xmin:
|
|
|
|
|
- xmin = mot.end[X]
|
|
|
|
|
- if mot.start[X] > xmax:
|
|
|
|
|
- xmax = mot.end[X]
|
|
|
|
|
- if mot.end[X] > xmax:
|
|
|
|
|
- xmax = mot.end[X]
|
|
|
|
|
- if mot.start[Y] < ymin:
|
|
|
|
|
- ymin = mot.start[Y]
|
|
|
|
|
- if mot.end[Y] < ymin:
|
|
|
|
|
- ymin = mot.end[Y]
|
|
|
|
|
- if mot.start[Y] > ymax:
|
|
|
|
|
- ymax = mot.end[Y]
|
|
|
|
|
- if mot.end[Y] > ymax:
|
|
|
|
|
- ymax = mot.end[Y]
|
|
|
|
|
- width = xmax - xmin
|
|
|
|
|
- height = ymax - ymin
|
|
|
|
|
- print "x in", xmin, xmax
|
|
|
|
|
- print "y in", ymin, ymax
|
|
|
|
|
- print "width", width
|
|
|
|
|
- print "heigh", height
|
|
|
|
|
-
|
|
|
|
|
- # Create surface if it doesn't exist
|
|
|
|
|
- if self.surface == None:
|
|
|
|
|
- self.pixel_width = int(width*self.resolution + 2*margin)
|
|
|
|
|
- self.pixel_height = int(height*self.resolution + 2*margin)
|
|
|
|
|
- self.create_surface(self.pixel_width, self.pixel_height)
|
|
|
|
|
- self.origin = [int(-xmin*self.resolution + margin),
|
|
|
|
|
- int(-ymin*self.resolution + margin)]
|
|
|
|
|
- print "Created surface: %d x %d"%(self.pixel_width, self.pixel_height)
|
|
|
|
|
- print "Origin: %d, %d"%(self.origin[X], self.origin[Y])
|
|
|
|
|
-
|
|
|
|
|
- # Context
|
|
|
|
|
- # Flip and shift
|
|
|
|
|
- self.context = cairo.Context(self.surface)
|
|
|
|
|
- cr = self.context
|
|
|
|
|
-
|
|
|
|
|
- cr.set_source_rgb(0.9, 0.9, 0.9)
|
|
|
|
|
- cr.rectangle(0,0, self.pixel_width, self.pixel_height)
|
|
|
|
|
- cr.fill()
|
|
|
|
|
-
|
|
|
|
|
- cr.scale(self.resolution, -self.resolution)
|
|
|
|
|
- cr.translate(self.origin[X]/self.resolution,
|
|
|
|
|
- (-self.pixel_height+self.origin[Y])/self.resolution)
|
|
|
|
|
-
|
|
|
|
|
- # Draw
|
|
|
|
|
- cr.move_to(0,0)
|
|
|
|
|
- cr.set_line_width (linewidth)
|
|
|
|
|
- cr.set_line_cap(cairo.LINE_CAP_ROUND)
|
|
|
|
|
- n = len(motions)
|
|
|
|
|
- for i in range(0, n):
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- #if motions[i].depth<0 and i>0 and motions[i-1].depth>0:
|
|
|
|
|
- if motions[i].depth <= 0:
|
|
|
|
|
- # change to cutting
|
|
|
|
|
- #print "x",
|
|
|
|
|
- # Draw previous travel
|
|
|
|
|
- cr.set_source_rgba (0.3, 0.2, 0.1, 1.0) # Solid color
|
|
|
|
|
- #cr.stroke()
|
|
|
|
|
- #if motions[i].depth >0 and i>0 and motions[i-1].depth<0:
|
|
|
|
|
- if motions[i].depth > 0:
|
|
|
|
|
- # change to cutting
|
|
|
|
|
- #print "-",
|
|
|
|
|
- # Draw previous cut
|
|
|
|
|
- cr.set_source_rgba (0.3, 0.2, 0.5, 0.2)
|
|
|
|
|
- #cr.stroke()
|
|
|
|
|
-
|
|
|
|
|
- if motions[i].typ == 'line':
|
|
|
|
|
- cr.move_to(motions[i].start[0], motions[i].start[1])
|
|
|
|
|
- cr.line_to(motions[i].end[0], motions[i].end[1])
|
|
|
|
|
- cr.stroke()
|
|
|
|
|
- #print 'cr.line_to(%f, %f)'%(motions[i].end[0], motions[i].end[0]),
|
|
|
|
|
-
|
|
|
|
|
- if motions[i].typ == 'arcacw':
|
|
|
|
|
- c = (motions[i].offset[0]+motions[i].start[0],
|
|
|
|
|
- motions[i].offset[1]+motions[i].start[1])
|
|
|
|
|
- r = sqrt(motions[i].offset[0]**2 + motions[i].offset[1]**2)
|
|
|
|
|
- ts = arctan2(-motions[i].offset[1], -motions[i].offset[0])
|
|
|
|
|
- te = arctan2(-c[1]+motions[i].end[1], -c[0]+motions[i].end[0])
|
|
|
|
|
- if te <= ts:
|
|
|
|
|
- te += 2*pi
|
|
|
|
|
- cr.arc(c[0], c[1], r, ts, te)
|
|
|
|
|
- cr.stroke()
|
|
|
|
|
-
|
|
|
|
|
- if motions[i].typ == 'arccw':
|
|
|
|
|
- c = (motions[i].offset[0]+motions[i].start[0],
|
|
|
|
|
- motions[i].offset[1]+motions[i].start[1])
|
|
|
|
|
- r = sqrt(motions[i].offset[0]**2 + motions[i].offset[1]**2)
|
|
|
|
|
- ts = arctan2(-motions[i].offset[1], -motions[i].offset[0])
|
|
|
|
|
- te = arctan2(-c[1]+motions[i].end[1], -c[0]+motions[i].end[0])
|
|
|
|
|
- if te <= ts:
|
|
|
|
|
- te += 2*pi
|
|
|
|
|
- cr.arc(c[0], c[1], r, te, ts)
|
|
|
|
|
- cr.stroke()
|
|
|
|
|
-
|
|
|
|
|
- def draw_boundaries(self, boundaries, linewidth, margin=10):
|
|
|
|
|
- '''
|
|
|
|
|
- margin Margin in pixels.
|
|
|
|
|
- '''
|
|
|
|
|
- # Analyze boundaries
|
|
|
|
|
- X = 0
|
|
|
|
|
- Y = 1
|
|
|
|
|
- #Z = 2
|
|
|
|
|
- xmin = Inf
|
|
|
|
|
- xmax = -Inf
|
|
|
|
|
- ymin = Inf
|
|
|
|
|
- ymax = -Inf
|
|
|
|
|
- for seg in boundaries[0]:
|
|
|
|
|
- for vertex in seg:
|
|
|
|
|
- try:
|
|
|
|
|
- if vertex[X] < xmin:
|
|
|
|
|
- xmin = vertex[X]
|
|
|
|
|
- if vertex[X] > xmax:
|
|
|
|
|
- xmax = vertex[X]
|
|
|
|
|
- if vertex[Y] < ymin:
|
|
|
|
|
- ymin = vertex[Y]
|
|
|
|
|
- if vertex[Y] > ymax:
|
|
|
|
|
- ymax = vertex[Y]
|
|
|
|
|
- except:
|
|
|
|
|
- print "Woops! vertex = [", [x for x in vertex], "]"
|
|
|
|
|
- width = xmax - xmin
|
|
|
|
|
- height = ymax - ymin
|
|
|
|
|
- print "x in", xmin, xmax
|
|
|
|
|
- print "y in", ymin, ymax
|
|
|
|
|
- print "width", width
|
|
|
|
|
- print "heigh", height
|
|
|
|
|
-
|
|
|
|
|
- # Create surface if it doesn't exist
|
|
|
|
|
- if self.surface == None:
|
|
|
|
|
- self.pixel_width = int(width*self.resolution + 2*margin)
|
|
|
|
|
- self.pixel_height = int(height*self.resolution + 2*margin)
|
|
|
|
|
- self.create_surface(self.pixel_width, self.pixel_height)
|
|
|
|
|
- self.origin = [int(-xmin*self.resolution + margin),
|
|
|
|
|
- int(-ymin*self.resolution + margin)]
|
|
|
|
|
- print "Created surface: %d x %d"%(self.pixel_width, self.pixel_height)
|
|
|
|
|
- print "Origin: %d, %d"%(self.origin[X], self.origin[Y])
|
|
|
|
|
-
|
|
|
|
|
- # Context
|
|
|
|
|
- # Flip and shift
|
|
|
|
|
- self.context = cairo.Context(self.surface)
|
|
|
|
|
- cr = self.context
|
|
|
|
|
-
|
|
|
|
|
- cr.set_source_rgb(0.9, 0.9, 0.9)
|
|
|
|
|
- cr.rectangle(0,0, self.pixel_width, self.pixel_height)
|
|
|
|
|
- cr.fill()
|
|
|
|
|
-
|
|
|
|
|
- cr.scale(self.resolution, -self.resolution)
|
|
|
|
|
- cr.translate(self.origin[X]/self.resolution,
|
|
|
|
|
- (-self.pixel_height+self.origin[Y])/self.resolution)
|
|
|
|
|
-
|
|
|
|
|
- # Draw
|
|
|
|
|
-
|
|
|
|
|
- cr.set_line_width (linewidth)
|
|
|
|
|
- cr.set_line_cap(cairo.LINE_CAP_ROUND)
|
|
|
|
|
- cr.set_source_rgba (0.3, 0.2, 0.5, 1)
|
|
|
|
|
- for seg in boundaries[0]:
|
|
|
|
|
- #print "segment"
|
|
|
|
|
- cr.move_to(seg[0][X],seg[0][Y])
|
|
|
|
|
- for i in range(1,len(seg)):
|
|
|
|
|
- #print seg[i][X],seg[i][Y]
|
|
|
|
|
- cr.line_to(seg[i][X], seg[i][Y])
|
|
|
|
|
- cr.stroke()
|
|
|
|
|
-
|
|
|
|
|
-def plotby(b, res, linewidth, ims=None):
|
|
|
|
|
- '''
|
|
|
|
|
- Creates a Cairo image object for the "boundarys" object
|
|
|
|
|
- generated by read_gerber().
|
|
|
|
|
- '''
|
|
|
|
|
- X = 0
|
|
|
|
|
- Y = 1
|
|
|
|
|
- xmin = Inf
|
|
|
|
|
- xmax = -Inf
|
|
|
|
|
- ymin = Inf
|
|
|
|
|
- ymax = -Inf
|
|
|
|
|
- for seg in b[0]:
|
|
|
|
|
- for vertex in seg:
|
|
|
|
|
- try:
|
|
|
|
|
- if vertex[X] < xmin:
|
|
|
|
|
- xmin = vertex[X]
|
|
|
|
|
- if vertex[X] > xmax:
|
|
|
|
|
- xmax = vertex[X]
|
|
|
|
|
- if vertex[Y] < ymin:
|
|
|
|
|
- ymin = vertex[Y]
|
|
|
|
|
- if vertex[Y] > ymax:
|
|
|
|
|
- ymax = vertex[Y]
|
|
|
|
|
- except:
|
|
|
|
|
- print "Woops! vertex = [", [x for x in vertex], "]"
|
|
|
|
|
-
|
|
|
|
|
- width = xmax - xmin
|
|
|
|
|
- height = ymax - ymin
|
|
|
|
|
- print "x in", xmin, xmax
|
|
|
|
|
- print "y in", ymin, ymax
|
|
|
|
|
- print "width", width
|
|
|
|
|
- print "heigh", height
|
|
|
|
|
-
|
|
|
|
|
- WIDTH = int((xmax-xmin)*res)
|
|
|
|
|
- HEIGHT = int((ymax-ymin)*res)
|
|
|
|
|
- # Create a new image if none given
|
|
|
|
|
- if ims == None:
|
|
|
|
|
- ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
|
|
|
|
|
- cr = cairo.Context(ims)
|
|
|
|
|
- cr.scale(res, -res)
|
|
|
|
|
- #cr.scale(res, res)
|
|
|
|
|
- #cr.translate(0, -(ymax-ymin))
|
|
|
|
|
- #cr.translate(-xmin, -ymin)
|
|
|
|
|
- cr.translate(-xmin, -(ymax))
|
|
|
|
|
- cr.set_line_width (linewidth)
|
|
|
|
|
- cr.set_line_cap(cairo.LINE_CAP_ROUND)
|
|
|
|
|
- cr.set_source_rgba (0.3, 0.2, 0.5, 1)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- for seg in b[0]:
|
|
|
|
|
- #print "segment"
|
|
|
|
|
- cr.move_to(seg[0][X],seg[0][Y])
|
|
|
|
|
- for i in range(1,len(seg)):
|
|
|
|
|
- #print seg[i][X],seg[i][Y]
|
|
|
|
|
- cr.line_to(seg[i][X], seg[i][Y])
|
|
|
|
|
- cr.stroke()
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- cr.scale(1,-1)
|
|
|
|
|
- cr.translate(-xmin, -(ymax))
|
|
|
|
|
- cr.set_source_rgba (1, 0, 0, 1)
|
|
|
|
|
- cr.select_font_face("Arial", cairo.FONT_SLANT_NORMAL,
|
|
|
|
|
- cairo.FONT_WEIGHT_NORMAL)
|
|
|
|
|
- cr.set_font_size(0.1)
|
|
|
|
|
- cr.move_to(0, 0)
|
|
|
|
|
- cr.show_text("(0,0)")
|
|
|
|
|
- cr.move_to(1, 1)
|
|
|
|
|
- cr.show_text("(1,1)")
|
|
|
|
|
-
|
|
|
|
|
- return ims
|
|
|
|
|
-
|
|
|
|
|
############### cam.py ####################
|
|
############### cam.py ####################
|
|
|
def coord(gstr,digits,fraction):
|
|
def coord(gstr,digits,fraction):
|
|
|
'''
|
|
'''
|
|
@@ -1108,1397 +776,5 @@ def coord(gstr,digits,fraction):
|
|
|
gerby = y
|
|
gerby = y
|
|
|
return [x,y]
|
|
return [x,y]
|
|
|
|
|
|
|
|
-def read_Gerber_Shapely(filename, nverts=10):
|
|
|
|
|
- '''
|
|
|
|
|
- Gerber parser.
|
|
|
|
|
- '''
|
|
|
|
|
- EPS = 1e-20
|
|
|
|
|
- TYPE = 0
|
|
|
|
|
- SIZE = 1
|
|
|
|
|
- WIDTH = 1
|
|
|
|
|
- HEIGHT = 2
|
|
|
|
|
-
|
|
|
|
|
- gfile = open(filename, 'r')
|
|
|
|
|
- gstr = gfile.readlines()
|
|
|
|
|
- gfile.close()
|
|
|
|
|
- segment = -1
|
|
|
|
|
- xold = []
|
|
|
|
|
- yold = []
|
|
|
|
|
- boundary = []
|
|
|
|
|
- macros = []
|
|
|
|
|
- N_macros = 0
|
|
|
|
|
- apertures = [[] for i in range(1000)]
|
|
|
|
|
- for gline in gstr:
|
|
|
|
|
- if (find(gline, "%FS") != -1):
|
|
|
|
|
- ### format statement ###
|
|
|
|
|
- index = find(gline, "X")
|
|
|
|
|
- digits = int(gline[index + 1])
|
|
|
|
|
- fraction = int(gline[index + 2])
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "%AM") != -1):
|
|
|
|
|
- ### aperture macro ###
|
|
|
|
|
- index = find(gline, "%AM")
|
|
|
|
|
- index1 = find(gline, "*")
|
|
|
|
|
- macros.append([])
|
|
|
|
|
- macros[-1] = gline[index + 3:index1]
|
|
|
|
|
- N_macros += 1
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "%MOIN*%") != -1):
|
|
|
|
|
- # inches
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "G01*") != -1):
|
|
|
|
|
- ### linear interpolation ###
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "G70*") != -1):
|
|
|
|
|
- ### inches ###
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "G75*") != -1):
|
|
|
|
|
- ### circular interpolation ###
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "%ADD") != -1):
|
|
|
|
|
- ### aperture definition ###
|
|
|
|
|
- index = find(gline, "%ADD")
|
|
|
|
|
- parse = 0
|
|
|
|
|
- if (find(gline, "C,") != -1):
|
|
|
|
|
- ## circle ##
|
|
|
|
|
- index = find(gline, "C,")
|
|
|
|
|
- index1 = find(gline, "*")
|
|
|
|
|
- aperture = int(gline[4:index])
|
|
|
|
|
- size = float(gline[index + 2:index1])
|
|
|
|
|
- apertures[aperture] = ["C", size]
|
|
|
|
|
- print " read aperture", aperture, ": circle diameter", size
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "O,") != -1):
|
|
|
|
|
- ## obround ##
|
|
|
|
|
- index = find(gline, "O,")
|
|
|
|
|
- aperture = int(gline[4:index])
|
|
|
|
|
- index1 = find(gline, ",", index)
|
|
|
|
|
- index2 = find(gline, "X", index)
|
|
|
|
|
- index3 = find(gline, "*", index)
|
|
|
|
|
- width = float(gline[index1 + 1:index2])
|
|
|
|
|
- height = float(gline[index2 + 1:index3])
|
|
|
|
|
- apertures[aperture] = ["O", width, height]
|
|
|
|
|
- print " read aperture", aperture, ": obround", width, "x", height
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "R,") != -1):
|
|
|
|
|
- ## rectangle ##
|
|
|
|
|
- index = find(gline, "R,")
|
|
|
|
|
- aperture = int(gline[4:index])
|
|
|
|
|
- index1 = find(gline, ",", index)
|
|
|
|
|
- index2 = find(gline, "X", index)
|
|
|
|
|
- index3 = find(gline, "*", index)
|
|
|
|
|
- width = float(gline[index1 + 1:index2])
|
|
|
|
|
- height = float(gline[index2 + 1:index3])
|
|
|
|
|
- apertures[aperture] = ["R", width, height]
|
|
|
|
|
- print " read aperture", aperture, ": rectangle", width, "x", height
|
|
|
|
|
- continue
|
|
|
|
|
- for macro in range(N_macros):
|
|
|
|
|
- ## macros ##
|
|
|
|
|
- index = find(gline, macros[macro] + ',')
|
|
|
|
|
- if (index != -1):
|
|
|
|
|
- # hack: assume macros can be approximated by
|
|
|
|
|
- # a circle, and has a size parameter
|
|
|
|
|
- aperture = int(gline[4:index])
|
|
|
|
|
- index1 = find(gline, ",", index)
|
|
|
|
|
- index2 = find(gline, "*", index)
|
|
|
|
|
- size = float(gline[index1 + 1:index2])
|
|
|
|
|
- apertures[aperture] = ["C", size]
|
|
|
|
|
- print " read aperture", aperture, ": macro (assuming circle) diameter", size
|
|
|
|
|
- parse = 1
|
|
|
|
|
- continue
|
|
|
|
|
- if (parse == 0):
|
|
|
|
|
- print " aperture not implemented:", gline
|
|
|
|
|
- return
|
|
|
|
|
- # End of if aperture definition
|
|
|
|
|
- elif (find(gline, "D01*") != -1):
|
|
|
|
|
- ### pen down ###
|
|
|
|
|
- [xnew, ynew] = coord(gline, digits, fraction)
|
|
|
|
|
- if (size > EPS):
|
|
|
|
|
- if ((abs(xnew - xold) > EPS) | (abs(ynew - yold) > EPS)):
|
|
|
|
|
- newpath = stroke(xold, yold, xnew, ynew, size, nverts=nverts)
|
|
|
|
|
- boundary.append(newpath)
|
|
|
|
|
- segment += 1
|
|
|
|
|
- else:
|
|
|
|
|
- boundary[segment].append([xnew, ynew, []])
|
|
|
|
|
- xold = xnew
|
|
|
|
|
- yold = ynew
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "D02*") != -1):
|
|
|
|
|
- ### pen up ###
|
|
|
|
|
- [xold, yold] = coord(gline, digits, fraction)
|
|
|
|
|
- if (size < EPS):
|
|
|
|
|
- boundary.append([])
|
|
|
|
|
- segment += 1
|
|
|
|
|
- boundary[segment].append([xold, yold, []])
|
|
|
|
|
- newpath = []
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "D03*") != -1):
|
|
|
|
|
- ### flash ###
|
|
|
|
|
- if (find(gline, "D03*") == 0):
|
|
|
|
|
- # coordinates on preceeding line
|
|
|
|
|
- [xnew, ynew] = [xold, yold]
|
|
|
|
|
- else:
|
|
|
|
|
- # coordinates on this line
|
|
|
|
|
- [xnew, ynew] = coord(gline, digits, fraction)
|
|
|
|
|
- if (apertures[aperture][TYPE] == "C"):
|
|
|
|
|
- # circle
|
|
|
|
|
- boundary.append([])
|
|
|
|
|
- segment += 1
|
|
|
|
|
- size = apertures[aperture][SIZE]
|
|
|
|
|
- for i in range(nverts):
|
|
|
|
|
- angle = i * 2.0 * pi / (nverts - 1.0)
|
|
|
|
|
- x = xnew + (size / 2.0) * cos(angle)
|
|
|
|
|
- y = ynew + (size / 2.0) * sin(angle)
|
|
|
|
|
- boundary[segment].append([x, y, []])
|
|
|
|
|
- elif (apertures[aperture][TYPE] == "R"):
|
|
|
|
|
- # rectangle
|
|
|
|
|
- boundary.append([])
|
|
|
|
|
- segment += 1
|
|
|
|
|
- width = apertures[aperture][WIDTH] / 2.0
|
|
|
|
|
- height = apertures[aperture][HEIGHT] / 2.0
|
|
|
|
|
- boundary[segment].append([xnew - width, ynew - height, []])
|
|
|
|
|
- boundary[segment].append([xnew + width, ynew - height, []])
|
|
|
|
|
- boundary[segment].append([xnew + width, ynew + height, []])
|
|
|
|
|
- boundary[segment].append([xnew - width, ynew + height, []])
|
|
|
|
|
- boundary[segment].append([xnew - width, ynew - height, []])
|
|
|
|
|
- elif (apertures[aperture][TYPE] == "O"):
|
|
|
|
|
- # obround
|
|
|
|
|
- boundary.append([])
|
|
|
|
|
- segment += 1
|
|
|
|
|
- width = apertures[aperture][WIDTH]
|
|
|
|
|
- height = apertures[aperture][HEIGHT]
|
|
|
|
|
- if (width > height):
|
|
|
|
|
- for i in range(nverts / 2):
|
|
|
|
|
- angle = i * pi / (nverts / 2 - 1.0) + pi / 2.0
|
|
|
|
|
- x = xnew - (width - height) / 2.0 + (height / 2.0) * cos(angle)
|
|
|
|
|
- y = ynew + (height / 2.0) * sin(angle)
|
|
|
|
|
- boundary[segment].append([x, y, []])
|
|
|
|
|
- for i in range(nverts / 2):
|
|
|
|
|
- angle = i * pi / (nverts / 2 - 1.0) - pi / 2.0
|
|
|
|
|
- x = xnew + (width - height) / 2.0 + (height / 2.0) * cos(angle)
|
|
|
|
|
- y = ynew + (height / 2.0) * sin(angle)
|
|
|
|
|
- boundary[segment].append([x, y, []])
|
|
|
|
|
- else:
|
|
|
|
|
- for i in range(nverts / 2):
|
|
|
|
|
- angle = i * pi / (nverts / 2 - 1.0) + pi
|
|
|
|
|
- x = xnew + (width / 2.0) * cos(angle)
|
|
|
|
|
- y = ynew - (height - width) / 2.0 + (width / 2.0) * sin(angle)
|
|
|
|
|
- boundary[segment].append([x, y, []])
|
|
|
|
|
- for i in range(nverts / 2):
|
|
|
|
|
- angle = i * pi / (nverts / 2 - 1.0)
|
|
|
|
|
- x = xnew + (width / 2.0) * cos(angle)
|
|
|
|
|
- y = ynew + (height - width) / 2.0 + (width / 2.0) * sin(angle)
|
|
|
|
|
- boundary[segment].append([x, y, []])
|
|
|
|
|
- boundary[segment].append(boundary[segment][0])
|
|
|
|
|
- else:
|
|
|
|
|
- print " aperture", apertures[aperture][TYPE], "is not implemented"
|
|
|
|
|
- return
|
|
|
|
|
- xold = xnew
|
|
|
|
|
- yold = ynew
|
|
|
|
|
- continue # End of flash
|
|
|
|
|
- elif (find(gline, "D") == 0):
|
|
|
|
|
- ### change aperture ###
|
|
|
|
|
- index = find(gline, '*')
|
|
|
|
|
- aperture = int(gline[1:index])
|
|
|
|
|
- size = apertures[aperture][SIZE]
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "G54D") == 0):
|
|
|
|
|
- ### change aperture ###
|
|
|
|
|
- index = find(gline, '*')
|
|
|
|
|
- aperture = int(gline[4:index])
|
|
|
|
|
- size = apertures[aperture][SIZE]
|
|
|
|
|
- continue
|
|
|
|
|
- else:
|
|
|
|
|
- print " not parsed:", gline
|
|
|
|
|
|
|
|
|
|
- boundarys[0] = boundary
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-def read_Gerber(filename, nverts=10):
|
|
|
|
|
- '''
|
|
|
|
|
- Gerber parser.
|
|
|
|
|
- '''
|
|
|
|
|
- global boundarys
|
|
|
|
|
- EPS = 1e-20
|
|
|
|
|
- TYPE = 0
|
|
|
|
|
- SIZE = 1
|
|
|
|
|
- WIDTH = 1
|
|
|
|
|
- HEIGHT = 2
|
|
|
|
|
-
|
|
|
|
|
- gfile = open(filename, 'r')
|
|
|
|
|
- gstr = gfile.readlines()
|
|
|
|
|
- gfile.close()
|
|
|
|
|
- segment = -1
|
|
|
|
|
- xold = []
|
|
|
|
|
- yold = []
|
|
|
|
|
- boundary = []
|
|
|
|
|
- macros = []
|
|
|
|
|
- N_macros = 0
|
|
|
|
|
- apertures = [[] for i in range(1000)]
|
|
|
|
|
- for gline in gstr:
|
|
|
|
|
- if (find(gline, "%FS") != -1):
|
|
|
|
|
- ### format statement ###
|
|
|
|
|
- index = find(gline, "X")
|
|
|
|
|
- digits = int(gline[index + 1])
|
|
|
|
|
- fraction = int(gline[index + 2])
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "%AM") != -1):
|
|
|
|
|
- ### aperture macro ###
|
|
|
|
|
- index = find(gline, "%AM")
|
|
|
|
|
- index1 = find(gline, "*")
|
|
|
|
|
- macros.append([])
|
|
|
|
|
- macros[-1] = gline[index + 3:index1]
|
|
|
|
|
- N_macros += 1
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "%MOIN*%") != -1):
|
|
|
|
|
- # inches
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "G01*") != -1):
|
|
|
|
|
- ### linear interpolation ###
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "G70*") != -1):
|
|
|
|
|
- ### inches ###
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "G75*") != -1):
|
|
|
|
|
- ### circular interpolation ###
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "%ADD") != -1):
|
|
|
|
|
- ### aperture definition ###
|
|
|
|
|
- index = find(gline, "%ADD")
|
|
|
|
|
- parse = 0
|
|
|
|
|
- if (find(gline, "C,") != -1):
|
|
|
|
|
- ## circle ##
|
|
|
|
|
- index = find(gline, "C,")
|
|
|
|
|
- index1 = find(gline, "*")
|
|
|
|
|
- aperture = int(gline[4:index])
|
|
|
|
|
- size = float(gline[index + 2:index1])
|
|
|
|
|
- apertures[aperture] = ["C", size]
|
|
|
|
|
- print " read aperture", aperture, ": circle diameter", size
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "O,") != -1):
|
|
|
|
|
- ## obround ##
|
|
|
|
|
- index = find(gline, "O,")
|
|
|
|
|
- aperture = int(gline[4:index])
|
|
|
|
|
- index1 = find(gline, ",", index)
|
|
|
|
|
- index2 = find(gline, "X", index)
|
|
|
|
|
- index3 = find(gline, "*", index)
|
|
|
|
|
- width = float(gline[index1 + 1:index2])
|
|
|
|
|
- height = float(gline[index2 + 1:index3])
|
|
|
|
|
- apertures[aperture] = ["O", width, height]
|
|
|
|
|
- print " read aperture", aperture, ": obround", width, "x", height
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "R,") != -1):
|
|
|
|
|
- ## rectangle ##
|
|
|
|
|
- index = find(gline, "R,")
|
|
|
|
|
- aperture = int(gline[4:index])
|
|
|
|
|
- index1 = find(gline, ",", index)
|
|
|
|
|
- index2 = find(gline, "X", index)
|
|
|
|
|
- index3 = find(gline, "*", index)
|
|
|
|
|
- width = float(gline[index1 + 1:index2])
|
|
|
|
|
- height = float(gline[index2 + 1:index3])
|
|
|
|
|
- apertures[aperture] = ["R", width, height]
|
|
|
|
|
- print " read aperture", aperture, ": rectangle", width, "x", height
|
|
|
|
|
- continue
|
|
|
|
|
- for macro in range(N_macros):
|
|
|
|
|
- ## macros ##
|
|
|
|
|
- index = find(gline, macros[macro] + ',')
|
|
|
|
|
- if (index != -1):
|
|
|
|
|
- # hack: assume macros can be approximated by
|
|
|
|
|
- # a circle, and has a size parameter
|
|
|
|
|
- aperture = int(gline[4:index])
|
|
|
|
|
- index1 = find(gline, ",", index)
|
|
|
|
|
- index2 = find(gline, "*", index)
|
|
|
|
|
- size = float(gline[index1 + 1:index2])
|
|
|
|
|
- apertures[aperture] = ["C", size]
|
|
|
|
|
- print " read aperture", aperture, ": macro (assuming circle) diameter", size
|
|
|
|
|
- parse = 1
|
|
|
|
|
- continue
|
|
|
|
|
- if (parse == 0):
|
|
|
|
|
- print " aperture not implemented:", gline
|
|
|
|
|
- return
|
|
|
|
|
- # End of if aperture definition
|
|
|
|
|
- elif (find(gline, "D01*") != -1):
|
|
|
|
|
- ### pen down ###
|
|
|
|
|
- [xnew, ynew] = coord(gline, digits, fraction)
|
|
|
|
|
- if (size > EPS):
|
|
|
|
|
- if ((abs(xnew - xold) > EPS) | (abs(ynew - yold) > EPS)):
|
|
|
|
|
- newpath = stroke(xold, yold, xnew, ynew, size, nverts=nverts)
|
|
|
|
|
- boundary.append(newpath)
|
|
|
|
|
- segment += 1
|
|
|
|
|
- else:
|
|
|
|
|
- boundary[segment].append([xnew, ynew, []])
|
|
|
|
|
- xold = xnew
|
|
|
|
|
- yold = ynew
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "D02*") != -1):
|
|
|
|
|
- ### pen up ###
|
|
|
|
|
- [xold, yold] = coord(gline, digits, fraction)
|
|
|
|
|
- if (size < EPS):
|
|
|
|
|
- boundary.append([])
|
|
|
|
|
- segment += 1
|
|
|
|
|
- boundary[segment].append([xold, yold, []])
|
|
|
|
|
- newpath = []
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "D03*") != -1):
|
|
|
|
|
- ### flash ###
|
|
|
|
|
- if (find(gline, "D03*") == 0):
|
|
|
|
|
- # coordinates on preceeding line
|
|
|
|
|
- [xnew, ynew] = [xold, yold]
|
|
|
|
|
- else:
|
|
|
|
|
- # coordinates on this line
|
|
|
|
|
- [xnew, ynew] = coord(gline, digits, fraction)
|
|
|
|
|
- if (apertures[aperture][TYPE] == "C"):
|
|
|
|
|
- # circle
|
|
|
|
|
- boundary.append([])
|
|
|
|
|
- segment += 1
|
|
|
|
|
- size = apertures[aperture][SIZE]
|
|
|
|
|
- for i in range(nverts):
|
|
|
|
|
- angle = i * 2.0 * pi / (nverts - 1.0)
|
|
|
|
|
- x = xnew + (size / 2.0) * cos(angle)
|
|
|
|
|
- y = ynew + (size / 2.0) * sin(angle)
|
|
|
|
|
- boundary[segment].append([x, y, []])
|
|
|
|
|
- elif (apertures[aperture][TYPE] == "R"):
|
|
|
|
|
- # rectangle
|
|
|
|
|
- boundary.append([])
|
|
|
|
|
- segment += 1
|
|
|
|
|
- width = apertures[aperture][WIDTH] / 2.0
|
|
|
|
|
- height = apertures[aperture][HEIGHT] / 2.0
|
|
|
|
|
- boundary[segment].append([xnew - width, ynew - height, []])
|
|
|
|
|
- boundary[segment].append([xnew + width, ynew - height, []])
|
|
|
|
|
- boundary[segment].append([xnew + width, ynew + height, []])
|
|
|
|
|
- boundary[segment].append([xnew - width, ynew + height, []])
|
|
|
|
|
- boundary[segment].append([xnew - width, ynew - height, []])
|
|
|
|
|
- elif (apertures[aperture][TYPE] == "O"):
|
|
|
|
|
- # obround
|
|
|
|
|
- boundary.append([])
|
|
|
|
|
- segment += 1
|
|
|
|
|
- width = apertures[aperture][WIDTH]
|
|
|
|
|
- height = apertures[aperture][HEIGHT]
|
|
|
|
|
- if (width > height):
|
|
|
|
|
- for i in range(nverts / 2):
|
|
|
|
|
- angle = i * pi / (nverts / 2 - 1.0) + pi / 2.0
|
|
|
|
|
- x = xnew - (width - height) / 2.0 + (height / 2.0) * cos(angle)
|
|
|
|
|
- y = ynew + (height / 2.0) * sin(angle)
|
|
|
|
|
- boundary[segment].append([x, y, []])
|
|
|
|
|
- for i in range(nverts / 2):
|
|
|
|
|
- angle = i * pi / (nverts / 2 - 1.0) - pi / 2.0
|
|
|
|
|
- x = xnew + (width - height) / 2.0 + (height / 2.0) * cos(angle)
|
|
|
|
|
- y = ynew + (height / 2.0) * sin(angle)
|
|
|
|
|
- boundary[segment].append([x, y, []])
|
|
|
|
|
- else:
|
|
|
|
|
- for i in range(nverts / 2):
|
|
|
|
|
- angle = i * pi / (nverts / 2 - 1.0) + pi
|
|
|
|
|
- x = xnew + (width / 2.0) * cos(angle)
|
|
|
|
|
- y = ynew - (height - width) / 2.0 + (width / 2.0) * sin(angle)
|
|
|
|
|
- boundary[segment].append([x, y, []])
|
|
|
|
|
- for i in range(nverts / 2):
|
|
|
|
|
- angle = i * pi / (nverts / 2 - 1.0)
|
|
|
|
|
- x = xnew + (width / 2.0) * cos(angle)
|
|
|
|
|
- y = ynew + (height - width) / 2.0 + (width / 2.0) * sin(angle)
|
|
|
|
|
- boundary[segment].append([x, y, []])
|
|
|
|
|
- boundary[segment].append(boundary[segment][0])
|
|
|
|
|
- else:
|
|
|
|
|
- print " aperture", apertures[aperture][TYPE], "is not implemented"
|
|
|
|
|
- return
|
|
|
|
|
- xold = xnew
|
|
|
|
|
- yold = ynew
|
|
|
|
|
- continue # End of flash
|
|
|
|
|
- elif (find(gline, "D") == 0):
|
|
|
|
|
- ### change aperture ###
|
|
|
|
|
- index = find(gline, '*')
|
|
|
|
|
- aperture = int(gline[1:index])
|
|
|
|
|
- size = apertures[aperture][SIZE]
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(gline, "G54D") == 0):
|
|
|
|
|
- ### change aperture ###
|
|
|
|
|
- index = find(gline, '*')
|
|
|
|
|
- aperture = int(gline[4:index])
|
|
|
|
|
- size = apertures[aperture][SIZE]
|
|
|
|
|
- continue
|
|
|
|
|
- else:
|
|
|
|
|
- print " not parsed:", gline
|
|
|
|
|
-
|
|
|
|
|
- boundarys[0] = boundary
|
|
|
|
|
-
|
|
|
|
|
-def read_Excellon(filename):
|
|
|
|
|
- global boundarys
|
|
|
|
|
- #
|
|
|
|
|
- # Excellon parser
|
|
|
|
|
- #
|
|
|
|
|
- file = open(filename,'r')
|
|
|
|
|
- str = file.readlines()
|
|
|
|
|
- file.close()
|
|
|
|
|
- segment = -1
|
|
|
|
|
- line = 0
|
|
|
|
|
- nlines = len(str)
|
|
|
|
|
- boundary = []
|
|
|
|
|
- #header = TRUE
|
|
|
|
|
- drills = [[] for i in range(1000)]
|
|
|
|
|
- while line < nlines:
|
|
|
|
|
- if ((find(str[line],"T") != -1) & (find(str[line],"C") != -1) \
|
|
|
|
|
- & (find(str[line],"F") != -1)):
|
|
|
|
|
- #
|
|
|
|
|
- # alternate drill definition style
|
|
|
|
|
- #
|
|
|
|
|
- index = find(str[line],"T")
|
|
|
|
|
- index1 = find(str[line],"C")
|
|
|
|
|
- index2 = find(str[line],"F")
|
|
|
|
|
- drill = int(str[line][1:index1])
|
|
|
|
|
- print str[line][index1+1:index2]
|
|
|
|
|
- size = float(str[line][index1+1:index2])
|
|
|
|
|
- drills[drill] = ["C",size]
|
|
|
|
|
- print " read drill",drill,"size:",size
|
|
|
|
|
- line += 1
|
|
|
|
|
- continue
|
|
|
|
|
- if ((find(str[line],"T") != -1) & (find(str[line]," ") != -1) \
|
|
|
|
|
- & (find(str[line],"in") != -1)):
|
|
|
|
|
- #
|
|
|
|
|
- # alternate drill definition style
|
|
|
|
|
- #
|
|
|
|
|
- index = find(str[line],"T")
|
|
|
|
|
- index1 = find(str[line]," ")
|
|
|
|
|
- index2 = find(str[line],"in")
|
|
|
|
|
- drill = int(str[line][1:index1])
|
|
|
|
|
- print str[line][index1+1:index2]
|
|
|
|
|
- size = float(str[line][index1+1:index2])
|
|
|
|
|
- drills[drill] = ["C",size]
|
|
|
|
|
- print " read drill",drill,"size:",size
|
|
|
|
|
- line += 1
|
|
|
|
|
- continue
|
|
|
|
|
- elif ((find(str[line],"T") != -1) & (find(str[line],"C") != -1)):
|
|
|
|
|
- #
|
|
|
|
|
- # alternate drill definition style
|
|
|
|
|
- #
|
|
|
|
|
- index = find(str[line],"T")
|
|
|
|
|
- index1 = find(str[line],"C")
|
|
|
|
|
- drill = int(str[line][1:index1])
|
|
|
|
|
- size = float(str[line][index1+1:-1])
|
|
|
|
|
- drills[drill] = ["C",size]
|
|
|
|
|
- print " read drill",drill,"size:",size
|
|
|
|
|
- line += 1
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(str[line],"T") == 0):
|
|
|
|
|
- #
|
|
|
|
|
- # change drill
|
|
|
|
|
- #
|
|
|
|
|
- index = find(str[line],'T')
|
|
|
|
|
- drill = int(str[line][index+1:-1])
|
|
|
|
|
- size = drills[drill][SIZE]
|
|
|
|
|
- line += 1
|
|
|
|
|
- continue
|
|
|
|
|
- elif (find(str[line],"X") != -1):
|
|
|
|
|
- #
|
|
|
|
|
- # drill location
|
|
|
|
|
- #
|
|
|
|
|
- index = find(str[line],"X")
|
|
|
|
|
- index1 = find(str[line],"Y")
|
|
|
|
|
- x0 = float(int(str[line][index+1:index1])/10000.0)
|
|
|
|
|
- y0 = float(int(str[line][index1+1:-1])/10000.0)
|
|
|
|
|
- line += 1
|
|
|
|
|
- boundary.append([])
|
|
|
|
|
- segment += 1
|
|
|
|
|
- size = drills[drill][SIZE]
|
|
|
|
|
- for i in range(nverts):
|
|
|
|
|
- angle = -i*2.0*pi/(nverts-1.0)
|
|
|
|
|
- x = x0 + (size/2.0)*cos(angle)
|
|
|
|
|
- y = y0 + (size/2.0)*sin(angle)
|
|
|
|
|
- boundary[segment].append([x,y,[]])
|
|
|
|
|
- continue
|
|
|
|
|
- else:
|
|
|
|
|
- print " not parsed:",str[line]
|
|
|
|
|
- line += 1
|
|
|
|
|
- boundarys[0] = boundary
|
|
|
|
|
-
|
|
|
|
|
-def stroke(x0,y0,x1,y1,width, nverts=10):
|
|
|
|
|
- #
|
|
|
|
|
- # stroke segment with width
|
|
|
|
|
- #
|
|
|
|
|
- #print "stroke:",x0,y0,x1,y1,width
|
|
|
|
|
- X = 0
|
|
|
|
|
- Y = 1
|
|
|
|
|
- dx = x1 - x0
|
|
|
|
|
- dy = y1 - y0
|
|
|
|
|
- d = sqrt(dx*dx + dy*dy)
|
|
|
|
|
- dxpar = dx / d
|
|
|
|
|
- dypar = dy / d
|
|
|
|
|
- dxperp = dypar
|
|
|
|
|
- dyperp = -dxpar
|
|
|
|
|
- dx = -dxperp * width/2.0
|
|
|
|
|
- dy = -dyperp * width/2.0
|
|
|
|
|
- angle = pi/(nverts/2-1.0)
|
|
|
|
|
- c = cos(angle)
|
|
|
|
|
- s = sin(angle)
|
|
|
|
|
- newpath = []
|
|
|
|
|
- for i in range(nverts/2):
|
|
|
|
|
- newpath.append([x0+dx,y0+dy,0])
|
|
|
|
|
- [dx,dy] = [c*dx-s*dy, s*dx+c*dy]
|
|
|
|
|
- dx = dxperp * width/2.0
|
|
|
|
|
- dy = dyperp * width/2.0
|
|
|
|
|
- for i in range(nverts/2):
|
|
|
|
|
- newpath.append([x1+dx,y1+dy,0])
|
|
|
|
|
- [dx,dy] = [c*dx-s*dy, s*dx+c*dy]
|
|
|
|
|
- x0 = newpath[0][X]
|
|
|
|
|
- y0 = newpath[0][Y]
|
|
|
|
|
- newpath.append([x0,y0,0])
|
|
|
|
|
- return newpath
|
|
|
|
|
-
|
|
|
|
|
-def contour(event):
|
|
|
|
|
- '''
|
|
|
|
|
- Uses displace() and adjust_contours()
|
|
|
|
|
- '''
|
|
|
|
|
- global boundarys, toolpaths, contours
|
|
|
|
|
- #
|
|
|
|
|
- # contour boundary to find toolpath
|
|
|
|
|
- #
|
|
|
|
|
- print "contouring boundary ..."
|
|
|
|
|
- xyscale = float(sxyscale.get())
|
|
|
|
|
- undercut = float(sundercut.get())
|
|
|
|
|
- if (undercut != 0.0):
|
|
|
|
|
- print " undercutting contour by",undercut
|
|
|
|
|
- N_contour = 1
|
|
|
|
|
- if (len(boundarys) == 1):
|
|
|
|
|
- #
|
|
|
|
|
- # 2D contour
|
|
|
|
|
- #
|
|
|
|
|
- toolpaths[0] = []
|
|
|
|
|
- for n in range(N_contour):
|
|
|
|
|
- toolrad = (n+1)*(float(sdia.get())/2.0-undercut)/xyscale
|
|
|
|
|
- contours[0] = displace(boundarys[0],toolrad)
|
|
|
|
|
- altern = ialtern.get();
|
|
|
|
|
- if (altern == TRUE):
|
|
|
|
|
- contours[0] = adjust_contour(contours[0],boundarys[0],toolrad)
|
|
|
|
|
- else:
|
|
|
|
|
- contours[0] = prune(contours[0],-1,event)
|
|
|
|
|
- toolpaths[0].extend(contours[0])
|
|
|
|
|
- plot(event)
|
|
|
|
|
- else:
|
|
|
|
|
- #
|
|
|
|
|
- # 3D contour
|
|
|
|
|
- #
|
|
|
|
|
- for layer in range(len(boundarys)):
|
|
|
|
|
- toolpaths[layer] = []
|
|
|
|
|
- contours[layer] = []
|
|
|
|
|
- if (boundarys[layer] != []):
|
|
|
|
|
- [xindex,yindex,zindex,z] = orient(boundarys[layer])
|
|
|
|
|
- for n in range(N_contour):
|
|
|
|
|
- toolrad = (n+1)*(float(sdia.get())/2.0-undercut)/xyscale
|
|
|
|
|
- path = project(boundarys[layer],xindex,yindex)
|
|
|
|
|
- contour = displace(path,toolrad)
|
|
|
|
|
- contour = prune(contour,-1,event)
|
|
|
|
|
- contours[layer] = lift(contour,xindex,yindex,zindex,z)
|
|
|
|
|
- toolpaths[layer].extend(contours[layer])
|
|
|
|
|
- plot(event)
|
|
|
|
|
- print " done"
|
|
|
|
|
-
|
|
|
|
|
-def adjust_contour(path, boundary, toolrad):
|
|
|
|
|
- print " adjust_contour ..."
|
|
|
|
|
- newpath = []
|
|
|
|
|
- for seg in range(len(path)):
|
|
|
|
|
- newpath.append([])
|
|
|
|
|
-# print "points"
|
|
|
|
|
-# for vert in range(len(path[seg])):
|
|
|
|
|
-# Px = boundary[seg][vert][X]
|
|
|
|
|
-# Py = boundary[seg][vert][Y]
|
|
|
|
|
-# print "%2i : %5.2f,%5.2f" % (vert, Px, Py)
|
|
|
|
|
-
|
|
|
|
|
-# print "len(path[seg]): ", len(path[seg])
|
|
|
|
|
-# print "len(boundary[seg]: ", len(boundary[seg])
|
|
|
|
|
- for vert in range(len(path[seg])):
|
|
|
|
|
- Px = path[seg][vert][X]
|
|
|
|
|
- Py = path[seg][vert][Y]
|
|
|
|
|
- avgvalue = []
|
|
|
|
|
- avgvalue.append(0.0)
|
|
|
|
|
- avgvalue.append(0.0)
|
|
|
|
|
- changed = 1
|
|
|
|
|
- iteration = 0
|
|
|
|
|
- avg = []
|
|
|
|
|
- while ((iteration < MAXITER) & (changed != 0)):
|
|
|
|
|
- changed = 0
|
|
|
|
|
-
|
|
|
|
|
- for orgvert in range(len(boundary[seg]) - 1):
|
|
|
|
|
-# if (orgvert == 0):
|
|
|
|
|
-# x0 = boundary[seg][len(boundary[seg]) - 1][X]
|
|
|
|
|
-# y0 = boundary[seg][len(boundary[seg]) - 1][Y]
|
|
|
|
|
-# else:
|
|
|
|
|
- x0 = boundary[seg][orgvert][X]
|
|
|
|
|
- y0 = boundary[seg][orgvert][Y]
|
|
|
|
|
-
|
|
|
|
|
- x1 = boundary[seg][orgvert + 1][X]
|
|
|
|
|
- y1 = boundary[seg][orgvert + 1][Y]
|
|
|
|
|
-
|
|
|
|
|
- #print ' A %5.2f,%5.2f B %5.2f,%5.2f' % (x0, y0, x1, y1)
|
|
|
|
|
-
|
|
|
|
|
- dx = x1 - x0
|
|
|
|
|
- dy = y1 - y0
|
|
|
|
|
-
|
|
|
|
|
- nx = dy;
|
|
|
|
|
- ny = -dx;
|
|
|
|
|
-
|
|
|
|
|
- d = abs(((nx * Px + ny * Py) - (nx * x0 + ny * y0) ) / \
|
|
|
|
|
- sqrt( nx * nx + ny * ny ))
|
|
|
|
|
-
|
|
|
|
|
- pre = orgvert - 1
|
|
|
|
|
-
|
|
|
|
|
- if (pre < 0):
|
|
|
|
|
- pre = len(boundary[seg]) - 2
|
|
|
|
|
- post = orgvert + 2
|
|
|
|
|
- if (post == len(boundary[seg])):
|
|
|
|
|
- post = 1
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- #print " distance %5.2f" % d
|
|
|
|
|
- #print "toolrad ", toolrad
|
|
|
|
|
- if (d - toolrad < - NOISE):
|
|
|
|
|
-# if (x0 < 1000000000):
|
|
|
|
|
- #print " low distance"
|
|
|
|
|
- # check if inside
|
|
|
|
|
- pre = orgvert - 1
|
|
|
|
|
- if (pre < 0):
|
|
|
|
|
- pre = len(boundary[seg]) - 2
|
|
|
|
|
- post = orgvert + 2
|
|
|
|
|
- if (post == len(boundary[seg])):
|
|
|
|
|
- post = 1
|
|
|
|
|
-
|
|
|
|
|
- diff_d_pre_x = x1 - boundary[seg][pre][X]
|
|
|
|
|
- diff_d_pre_y = y1 - boundary[seg][pre][Y]
|
|
|
|
|
- diff_d_post_x = boundary[seg][post][X] - x0
|
|
|
|
|
- diff_d_post_y = boundary[seg][post][Y] - y0
|
|
|
|
|
-
|
|
|
|
|
- #print "diff_pre %5.2f,%5.2f" % (diff_d_pre_x, diff_d_pre_y)
|
|
|
|
|
- #print "diff_post %5.2f,%5.2f" % (diff_d_post_x, diff_d_post_y)
|
|
|
|
|
-
|
|
|
|
|
- #n_pre_x = diff_d_pre_y
|
|
|
|
|
- #n_pre_y = -diff_d_pre_x
|
|
|
|
|
- #n_post_x = diff_d_post_y
|
|
|
|
|
- #n_post_y = -diff_d_post_x
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- diff_px0 = Px - x0
|
|
|
|
|
- diff_py0 = Py - y0
|
|
|
|
|
- diff_px1 = Px - x1
|
|
|
|
|
- diff_py1 = Py - y1
|
|
|
|
|
-
|
|
|
|
|
- #print "diff p0 %5.2f,%5.2f" % (diff_px0, diff_py0)
|
|
|
|
|
- #print "diff p1 %5.2f,%5.2f" % (diff_px1, diff_py1)
|
|
|
|
|
-
|
|
|
|
|
- pre_x = boundary[seg][pre][X]
|
|
|
|
|
- pre_y = boundary[seg][pre][Y]
|
|
|
|
|
- post_x = boundary[seg][post][X]
|
|
|
|
|
- post_y = boundary[seg][post][Y]
|
|
|
|
|
-
|
|
|
|
|
- v0_x = x0 - pre_x
|
|
|
|
|
- v0_y = y0 - pre_y
|
|
|
|
|
-
|
|
|
|
|
- v1_x = post_x - x0
|
|
|
|
|
- v1_y = post_y - y0
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- if ((v0_x * nx + v0_y * ny) > -NOISE): #angle > 180
|
|
|
|
|
- #print "XXXXXXXXXXXXXXXXXXX pre > 180"
|
|
|
|
|
- value0 = diff_d_pre_x * diff_px0 + diff_d_pre_y * diff_py0
|
|
|
|
|
- #value0 = diff_px0 * dx + diff_py0 * dy
|
|
|
|
|
- else:
|
|
|
|
|
- value0 = diff_px0 * dx + diff_py0 * dy
|
|
|
|
|
-
|
|
|
|
|
- if (-(v1_x * nx + v1_y * ny) > -NOISE): #angle > 180
|
|
|
|
|
- #print "XXXXXXXXXXXXXXXXXXX post > 180"
|
|
|
|
|
- value1 = diff_d_post_x * diff_px1 + diff_d_post_y * diff_py1
|
|
|
|
|
- #value1 = diff_px1 * dx + diff_py1 * dy
|
|
|
|
|
- else:
|
|
|
|
|
- value1 = diff_px1 * dx + diff_py1 * dy
|
|
|
|
|
-
|
|
|
|
|
- #if ((value0 > -NOISE) & (value1 < NOISE)):
|
|
|
|
|
- #print " P %5.2f,%5.2f a %5.2f,%5.2f b %5.2f,%5.2f - inside (%8.5f & %8.5f)" % (Px, Py, x0, y0, x1, y1, value0, value1)
|
|
|
|
|
- #else:
|
|
|
|
|
- #print " P %5.2f,%5.2f a %5.2f,%5.2f b %5.2f,%5.2f - outside (%8.5f & %8.5f)" % (Px, Py, x0, y0, x1, y1, value0, value1)
|
|
|
|
|
-
|
|
|
|
|
-# if (vert == 3) & (orgvert == 2):
|
|
|
|
|
-# print "-p1 %5.2f,%5.2f p2 %5.2f,%5.2f P %5.2f,%5.2f " % (x0, y0, x1, y1, Px, Py)
|
|
|
|
|
-# print "d %5.2f,%5.2f" % (dx, dy)
|
|
|
|
|
-# print "n %5.2f,%5.2f" % (nx, ny)
|
|
|
|
|
-# print "di0 %5.2f,%5.2f" % (diff_px0, diff_py0)
|
|
|
|
|
-# print "di1 %5.2f,%5.2f" % (diff_px1, diff_py1)
|
|
|
|
|
-# print "val %5.2f,%5.2f" % (value0, value1)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-# if ((value0 == 0) | (value1 == 0)):
|
|
|
|
|
-# #print " fix me"
|
|
|
|
|
-# value = value1
|
|
|
|
|
-# else:
|
|
|
|
|
- if ((value0 > -NOISE) & (value1 < NOISE)):
|
|
|
|
|
- #value = value1 * value0;
|
|
|
|
|
- #if (value < 0 ):
|
|
|
|
|
- #print 'P %5.2f,%5.2f' % (Px, Py)
|
|
|
|
|
- #print ' A %5.2f,%5.2f B %5.2f,%5.2f' % (x0, y0, x1, y1)
|
|
|
|
|
- #print " distance %5.2f" % d
|
|
|
|
|
- #print " move"
|
|
|
|
|
- ln = sqrt((nx * nx) + (ny * ny))
|
|
|
|
|
- Px = Px + (nx / ln) * (toolrad - d);
|
|
|
|
|
- Py = Py + (ny / ln) * (toolrad - d);
|
|
|
|
|
- changed += 1
|
|
|
|
|
- iteration += 1
|
|
|
|
|
-# print ' new %5.2f,%5.2f' % (Px, Py)
|
|
|
|
|
- if (iteration > MAXITER - AVGITER):
|
|
|
|
|
-# print "ii %2i %7.4f,%7.4f" % (iteration, Px,Py)
|
|
|
|
|
- avgvalue[X] += Px
|
|
|
|
|
- avgvalue[Y] += Py
|
|
|
|
|
-# if (iteration > 1):
|
|
|
|
|
-# print iteration
|
|
|
|
|
- if (iteration >= MAXITER):
|
|
|
|
|
-# print " diff", (iteration - (MAXITER - AVGITER))
|
|
|
|
|
- avgvalue[X] /= float(iteration - (MAXITER - AVGITER))
|
|
|
|
|
- avgvalue[Y] /= float(iteration - (MAXITER - AVGITER))
|
|
|
|
|
- newpath[seg].append([avgvalue[X],avgvalue[Y],[]])
|
|
|
|
|
-# print "NEW : %7.4f,%7.4f" % (avgvalue[X], avgvalue[Y])
|
|
|
|
|
- else:
|
|
|
|
|
- newpath[seg].append([Px,Py,[]])
|
|
|
|
|
-
|
|
|
|
|
-# for vert in range(len(path[seg])):
|
|
|
|
|
-# Px = newpath[seg][vert][X]
|
|
|
|
|
-# Py = newpath[seg][vert][Y]
|
|
|
|
|
-# print "NEW %2i : %5.2f,%5.2f" % (vert, Px, Py)
|
|
|
|
|
-
|
|
|
|
|
- return newpath
|
|
|
|
|
-
|
|
|
|
|
-def displace(path,toolrad):
|
|
|
|
|
- '''
|
|
|
|
|
- Uses offset()
|
|
|
|
|
- '''
|
|
|
|
|
- #
|
|
|
|
|
- # displace path inwards by tool radius
|
|
|
|
|
- #
|
|
|
|
|
- print " displacing ..."
|
|
|
|
|
- newpath = []
|
|
|
|
|
- for seg in range(len(path)):
|
|
|
|
|
- newpath.append([])
|
|
|
|
|
- if (len(path[seg]) > 2):
|
|
|
|
|
- for vert1 in range(len(path[seg])-1):
|
|
|
|
|
- if (vert1 == 0):
|
|
|
|
|
- vert0 = len(path[seg]) - 2
|
|
|
|
|
- else:
|
|
|
|
|
- vert0 = vert1 - 1
|
|
|
|
|
- vert2 = vert1 + 1
|
|
|
|
|
- x0 = path[seg][vert0][X]
|
|
|
|
|
- x1 = path[seg][vert1][X]
|
|
|
|
|
- x2 = path[seg][vert2][X]
|
|
|
|
|
- y0 = path[seg][vert0][Y]
|
|
|
|
|
- y1 = path[seg][vert1][Y]
|
|
|
|
|
- y2 = path[seg][vert2][Y]
|
|
|
|
|
- [dx,dy] = offset(x0,x1,x2,y0,y1,y2,toolrad)
|
|
|
|
|
- if (dx != []):
|
|
|
|
|
- newpath[seg].append([(x1+dx),(y1+dy),[]])
|
|
|
|
|
- x0 = newpath[seg][0][X]
|
|
|
|
|
- y0 = newpath[seg][0][Y]
|
|
|
|
|
- newpath[seg].append([x0,y0,[]])
|
|
|
|
|
- elif (len(path[seg]) == 2):
|
|
|
|
|
- x0 = path[seg][0][X]
|
|
|
|
|
- y0 = path[seg][0][Y]
|
|
|
|
|
- x1 = path[seg][1][X]
|
|
|
|
|
- y1 = path[seg][1][Y]
|
|
|
|
|
- x2 = 2*x1 - x0
|
|
|
|
|
- y2 = 2*y1 - y0
|
|
|
|
|
- [dx,dy] = offset(x0,x1,x2,y0,y1,y2,toolrad)
|
|
|
|
|
- if (dx != []):
|
|
|
|
|
- newpath[seg].append([x0+dx,y0+dy,[]])
|
|
|
|
|
- newpath[seg].append([x1+dx,y1+dy,[]])
|
|
|
|
|
- else:
|
|
|
|
|
- newpath[seg].append([x0,y0,[]])
|
|
|
|
|
- newpath[seg].append([x1,y1,[]])
|
|
|
|
|
- else:
|
|
|
|
|
- print " displace: shouldn't happen"
|
|
|
|
|
- return newpath
|
|
|
|
|
-
|
|
|
|
|
-def offset(x0,x1,x2,y0,y1,y2,r):
|
|
|
|
|
- #
|
|
|
|
|
- # calculate offset by r for vertex 1
|
|
|
|
|
- #
|
|
|
|
|
- dx0 = x1 - x0
|
|
|
|
|
- dx1 = x2 - x1
|
|
|
|
|
- dy0 = y1 - y0
|
|
|
|
|
- dy1 = y2 - y1
|
|
|
|
|
- d0 = sqrt(dx0*dx0 + dy0*dy0)
|
|
|
|
|
- d1 = sqrt(dx1*dx1 + dy1*dy1)
|
|
|
|
|
- if ((d0 == 0) | (d1 == 0)):
|
|
|
|
|
- return [[],[]]
|
|
|
|
|
- dx0par = dx0 / d0
|
|
|
|
|
- dy0par = dy0 / d0
|
|
|
|
|
- dx0perp = dy0 / d0
|
|
|
|
|
- dy0perp = -dx0 / d0
|
|
|
|
|
- dx1perp = dy1 / d1
|
|
|
|
|
- dy1perp = -dx1 / d1
|
|
|
|
|
- #print "offset points:",x0,x1,x2,y0,y1,y2
|
|
|
|
|
- #print "offset normals:",dx0perp,dx1perp,dy0perp,dy1perp
|
|
|
|
|
- if ((abs(dx0perp*dy1perp - dx1perp*dy0perp) < EPS) | \
|
|
|
|
|
- (abs(dy0perp*dx1perp - dy1perp*dx0perp) < EPS)):
|
|
|
|
|
- dx = r * dx1perp
|
|
|
|
|
- dy = r * dy1perp
|
|
|
|
|
- #print " offset planar:",dx,dy
|
|
|
|
|
- elif ((abs(dx0perp+dx1perp) < EPS) & (abs(dy0perp+dy1perp) < EPS)):
|
|
|
|
|
- dx = r * dx1par
|
|
|
|
|
- dy = r * dy1par
|
|
|
|
|
- #print " offset hairpin:",dx,dy
|
|
|
|
|
- else:
|
|
|
|
|
- dx = r*(dy1perp - dy0perp) / \
|
|
|
|
|
- (dx0perp*dy1perp - dx1perp*dy0perp)
|
|
|
|
|
- dy = r*(dx1perp - dx0perp) / \
|
|
|
|
|
- (dy0perp*dx1perp - dy1perp*dx0perp)
|
|
|
|
|
- #print " offset OK:",dx,dy
|
|
|
|
|
- return [dx,dy]
|
|
|
|
|
-
|
|
|
|
|
-def prune(path,sign,event):
|
|
|
|
|
- '''
|
|
|
|
|
- Uses add_intersections() and union()
|
|
|
|
|
- '''
|
|
|
|
|
- #
|
|
|
|
|
- # prune path intersections
|
|
|
|
|
- #
|
|
|
|
|
- # first find the intersections
|
|
|
|
|
- #
|
|
|
|
|
- print " intersecting ..."
|
|
|
|
|
- [path, intersections, seg_intersections] = add_intersections(path)
|
|
|
|
|
- #print 'path:',path
|
|
|
|
|
- #print 'intersections:',intersections
|
|
|
|
|
- #print 'seg_intersections:',seg_intersections
|
|
|
|
|
- #
|
|
|
|
|
- # then copy non-intersecting segments to new path
|
|
|
|
|
- #
|
|
|
|
|
- newpath = []
|
|
|
|
|
- for seg in range(len(seg_intersections)):
|
|
|
|
|
- #print "non-int"
|
|
|
|
|
- if (seg_intersections[seg] == []):
|
|
|
|
|
- newpath.append(path[seg])
|
|
|
|
|
- #
|
|
|
|
|
- # finally follow and remove the intersections
|
|
|
|
|
- #
|
|
|
|
|
- print " pruning ..."
|
|
|
|
|
- i = 0
|
|
|
|
|
- newseg = 0
|
|
|
|
|
- while (i < len(intersections)):
|
|
|
|
|
- if (intersections[i] == []):
|
|
|
|
|
- #
|
|
|
|
|
- # skip null intersections
|
|
|
|
|
- #
|
|
|
|
|
- i += 1
|
|
|
|
|
- #print "null"
|
|
|
|
|
- else:
|
|
|
|
|
- istart = i
|
|
|
|
|
- intersection = istart
|
|
|
|
|
- #
|
|
|
|
|
- # skip interior intersections
|
|
|
|
|
- #
|
|
|
|
|
- oldseg = -1
|
|
|
|
|
- interior = TRUE
|
|
|
|
|
- while 1:
|
|
|
|
|
- #print 'testing intersection',intersection,':',intersections[intersection]
|
|
|
|
|
- if (intersections[intersection] == []):
|
|
|
|
|
- #seg == oldseg
|
|
|
|
|
- seg = oldseg
|
|
|
|
|
- else:
|
|
|
|
|
- [seg,vert] = union(intersection,path,intersections,sign)
|
|
|
|
|
- #print ' seg',seg,'vert',vert,'oldseg',oldseg
|
|
|
|
|
- if (seg == oldseg):
|
|
|
|
|
- #print " remove interior intersection",istart
|
|
|
|
|
- seg0 = intersections[istart][0][SEG]
|
|
|
|
|
- vert0 = intersections[istart][0][VERT]
|
|
|
|
|
- path[seg0][vert0][INTERSECT] = -1
|
|
|
|
|
- seg1 = intersections[istart][1][SEG]
|
|
|
|
|
- vert1 = intersections[istart][1][VERT]
|
|
|
|
|
- path[seg1][vert1][INTERSECT] = -1
|
|
|
|
|
- intersections[istart] = []
|
|
|
|
|
- break
|
|
|
|
|
- elif (seg == []):
|
|
|
|
|
- seg = intersections[intersection][0][SEG]
|
|
|
|
|
- vert = intersections[intersection][0][SEG]
|
|
|
|
|
- oldseg = []
|
|
|
|
|
- else:
|
|
|
|
|
- oldseg = seg
|
|
|
|
|
- intersection = []
|
|
|
|
|
- while (intersection == []):
|
|
|
|
|
- if (vert < (len(path[seg])-1)):
|
|
|
|
|
- vert += 1
|
|
|
|
|
- else:
|
|
|
|
|
- vert = 0
|
|
|
|
|
- intersection = path[seg][vert][INTERSECT]
|
|
|
|
|
- if (intersection == -1):
|
|
|
|
|
- intersection = istart
|
|
|
|
|
- break
|
|
|
|
|
- elif (intersection == istart):
|
|
|
|
|
- #print ' back to',istart
|
|
|
|
|
- interior = FALSE
|
|
|
|
|
- intersection = istart
|
|
|
|
|
- break
|
|
|
|
|
- #
|
|
|
|
|
- # save path if valid boundary intersection
|
|
|
|
|
- #
|
|
|
|
|
- if (interior == FALSE):
|
|
|
|
|
- newseg = len(newpath)
|
|
|
|
|
- newpath.append([])
|
|
|
|
|
- while 1:
|
|
|
|
|
- #print 'keeping intersection',intersection,':',intersections[intersection]
|
|
|
|
|
- [seg,vert] = union(intersection,path,intersections,sign)
|
|
|
|
|
- if (seg == []):
|
|
|
|
|
- seg = intersections[intersection][0][SEG]
|
|
|
|
|
- vert = intersections[intersection][0][VERT]
|
|
|
|
|
- #print ' seg',seg,'vert',vert
|
|
|
|
|
- intersections[intersection] = []
|
|
|
|
|
- intersection = []
|
|
|
|
|
- while (intersection == []):
|
|
|
|
|
- if (vert < (len(path[seg])-1)):
|
|
|
|
|
- x = path[seg][vert][X]
|
|
|
|
|
- y = path[seg][vert][Y]
|
|
|
|
|
- newpath[newseg].append([x,y,[]])
|
|
|
|
|
- vert += 1
|
|
|
|
|
- else:
|
|
|
|
|
- vert = 0
|
|
|
|
|
- intersection = path[seg][vert][INTERSECT]
|
|
|
|
|
- if (intersection == istart):
|
|
|
|
|
- #print ' back to',istart
|
|
|
|
|
- x = path[seg][vert][X]
|
|
|
|
|
- y = path[seg][vert][Y]
|
|
|
|
|
- newpath[newseg].append([x,y,[]])
|
|
|
|
|
- break
|
|
|
|
|
- i += 1
|
|
|
|
|
- return newpath
|
|
|
|
|
-
|
|
|
|
|
-def add_intersections(path):
|
|
|
|
|
- '''
|
|
|
|
|
- Uses intersect() and insert() (FIX THIS, BELONG TO OTHER LIBRARY)
|
|
|
|
|
- '''
|
|
|
|
|
- #
|
|
|
|
|
- # add vertices at path intersections
|
|
|
|
|
- #
|
|
|
|
|
- events = []
|
|
|
|
|
- active = []
|
|
|
|
|
- #
|
|
|
|
|
- # lexicographic sort segments
|
|
|
|
|
- #
|
|
|
|
|
- for seg in range(len(path)):
|
|
|
|
|
- nverts = len(path[seg])
|
|
|
|
|
- for vert in range(nverts-1):
|
|
|
|
|
- x0 = path[seg][vert][X]
|
|
|
|
|
- y0 = path[seg][vert][Y]
|
|
|
|
|
- x1 = path[seg][vert+1][X]
|
|
|
|
|
- y1 = path[seg][vert+1][Y]
|
|
|
|
|
- if (x1 < x0):
|
|
|
|
|
- [x0, x1] = [x1, x0]
|
|
|
|
|
- [y0, y1] = [y1, y0]
|
|
|
|
|
- if ((x1 == x0) & (y1 < y0)):
|
|
|
|
|
- [y0, y1] = [y1, y0]
|
|
|
|
|
- events.append([x0,y0,START,seg,vert])
|
|
|
|
|
- events.append([x1,y1,END,seg,vert])
|
|
|
|
|
- events.sort()
|
|
|
|
|
- #
|
|
|
|
|
- # find intersections with a sweep line
|
|
|
|
|
- #
|
|
|
|
|
- intersection = 0
|
|
|
|
|
- verts = []
|
|
|
|
|
- for event in range(len(events)):
|
|
|
|
|
-# status.set(" edge "+str(event)+"/"+str(len(events)-1)+" ")
|
|
|
|
|
-# outframe.update()
|
|
|
|
|
- #
|
|
|
|
|
- # loop over start/end points
|
|
|
|
|
- #
|
|
|
|
|
- type = events[event][INDEX]
|
|
|
|
|
- seg0 = events[event][EVENT_SEG]
|
|
|
|
|
- vert0 = events[event][EVENT_VERT]
|
|
|
|
|
- n0 = len(path[seg0])
|
|
|
|
|
- if (events[event][INDEX] == START):
|
|
|
|
|
- #
|
|
|
|
|
- # loop over active points
|
|
|
|
|
- #
|
|
|
|
|
- for point in range(len(active)):
|
|
|
|
|
- sega = active[point][SEG]
|
|
|
|
|
- verta = active[point][VERT]
|
|
|
|
|
- if ((sega == seg0) & \
|
|
|
|
|
- ((abs(vert0-verta) == 1) | (abs(vert0-verta) == (n0-2)))):
|
|
|
|
|
- #print seg0,vert0,verta,n0
|
|
|
|
|
- continue
|
|
|
|
|
- [xloc,yloc] = intersect(path,seg0,vert0,sega,verta)
|
|
|
|
|
- if (xloc != []):
|
|
|
|
|
- #
|
|
|
|
|
- # found intersection, save it
|
|
|
|
|
- #
|
|
|
|
|
- d0 = (path[seg0][vert0][X]-xloc)**2 + (path[seg0][vert0][Y]-yloc)**2
|
|
|
|
|
- verts.append([seg0,vert0,d0,xloc,yloc,intersection])
|
|
|
|
|
- da = (path[sega][verta][X]-xloc)**2 + (path[sega][verta][Y]-yloc)**2
|
|
|
|
|
- verts.append([sega,verta,da,xloc,yloc,intersection])
|
|
|
|
|
- intersection += 1
|
|
|
|
|
- active.append([seg0,vert0])
|
|
|
|
|
- else:
|
|
|
|
|
- active.remove([seg0,vert0])
|
|
|
|
|
- print " found",intersection,"intersections"
|
|
|
|
|
- #
|
|
|
|
|
- # add vertices at path intersections
|
|
|
|
|
- #
|
|
|
|
|
- verts.sort()
|
|
|
|
|
- verts.reverse()
|
|
|
|
|
- for vertex in range(len(verts)):
|
|
|
|
|
- seg = verts[vertex][SEG]
|
|
|
|
|
- vert = verts[vertex][VERT]
|
|
|
|
|
- intersection = verts[vertex][IINTERSECT]
|
|
|
|
|
- x = verts[vertex][XINTERSECT]
|
|
|
|
|
- y = verts[vertex][YINTERSECT]
|
|
|
|
|
- insert(path,x,y,seg,vert,intersection)
|
|
|
|
|
- #
|
|
|
|
|
- # make vertex table and segment list of intersections
|
|
|
|
|
- #
|
|
|
|
|
-# status.set(namedate)
|
|
|
|
|
-# outframe.update()
|
|
|
|
|
- nintersections = len(verts)/2
|
|
|
|
|
- intersections = [[] for i in range(nintersections)]
|
|
|
|
|
- for seg in range(len(path)):
|
|
|
|
|
- for vert in range(len(path[seg])):
|
|
|
|
|
- intersection = path[seg][vert][INTERSECT]
|
|
|
|
|
- if (intersection != []):
|
|
|
|
|
- intersections[intersection].append([seg,vert])
|
|
|
|
|
- seg_intersections = [[] for i in path]
|
|
|
|
|
- for i in range(len(intersections)):
|
|
|
|
|
- if (len(intersections[i]) != 2):
|
|
|
|
|
- print " shouldn't happen: i",i,intersections[i]
|
|
|
|
|
- else:
|
|
|
|
|
- seg_intersections[intersections[i][0][SEG]].append(i)
|
|
|
|
|
- seg_intersections[intersections[i][A][SEG]].append(i)
|
|
|
|
|
- return [path, intersections, seg_intersections]
|
|
|
|
|
-
|
|
|
|
|
-def intersect(path,seg0,vert0,sega,verta):
|
|
|
|
|
- #
|
|
|
|
|
- # test and return edge intersection
|
|
|
|
|
- #
|
|
|
|
|
- if ((seg0 == sega) & (vert0 == 0) & (verta == (len(path[sega])-2))):
|
|
|
|
|
- #print " return (0-end)"
|
|
|
|
|
- return [[],[]]
|
|
|
|
|
- x0 = path[seg0][vert0][X]
|
|
|
|
|
- y0 = path[seg0][vert0][Y]
|
|
|
|
|
- x1 = path[seg0][vert0+1][X]
|
|
|
|
|
- y1 = path[seg0][vert0+1][Y]
|
|
|
|
|
- dx01 = x1 - x0
|
|
|
|
|
- dy01 = y1 - y0
|
|
|
|
|
- d01 = sqrt(dx01*dx01 + dy01*dy01)
|
|
|
|
|
- if (d01 == 0):
|
|
|
|
|
- #
|
|
|
|
|
- # zero-length segment, return no intersection
|
|
|
|
|
- #
|
|
|
|
|
- #print "zero-length segment"
|
|
|
|
|
- return [[],[]]
|
|
|
|
|
- dxpar01 = dx01 / d01
|
|
|
|
|
- dypar01 = dy01 / d01
|
|
|
|
|
- dxperp01 = dypar01
|
|
|
|
|
- dyperp01 = -dxpar01
|
|
|
|
|
- xa = path[sega][verta][X]
|
|
|
|
|
- ya = path[sega][verta][Y]
|
|
|
|
|
- xb = path[sega][verta+1][X]
|
|
|
|
|
- yb = path[sega][verta+1][Y]
|
|
|
|
|
- dx0a = xa - x0
|
|
|
|
|
- dy0a = ya - y0
|
|
|
|
|
- dpar0a = dx0a*dxpar01 + dy0a*dypar01
|
|
|
|
|
- dperp0a = dx0a*dxperp01 + dy0a*dyperp01
|
|
|
|
|
- dx0b = xb - x0
|
|
|
|
|
- dy0b = yb - y0
|
|
|
|
|
- dpar0b = dx0b*dxpar01 + dy0b*dypar01
|
|
|
|
|
- dperp0b = dx0b*dxperp01 + dy0b*dyperp01
|
|
|
|
|
- #if (dperp0a*dperp0b > EPS):
|
|
|
|
|
- if (((dperp0a > EPS) & (dperp0b > EPS)) | \
|
|
|
|
|
- ((dperp0a < -EPS) & (dperp0b < -EPS))):
|
|
|
|
|
- #
|
|
|
|
|
- # vertices on same side, return no intersection
|
|
|
|
|
- #
|
|
|
|
|
- #print " same side"
|
|
|
|
|
- return [[],[]]
|
|
|
|
|
- elif ((abs(dperp0a) < EPS) & (abs(dperp0b) < EPS)):
|
|
|
|
|
- #
|
|
|
|
|
- # edges colinear, return no intersection
|
|
|
|
|
- #
|
|
|
|
|
- #d0a = (xa-x0)*dxpar01 + (ya-y0)*dypar01
|
|
|
|
|
- #d0b = (xb-x0)*dxpar01 + (yb-y0)*dypar01
|
|
|
|
|
- #print " colinear"
|
|
|
|
|
- return [[],[]]
|
|
|
|
|
- #
|
|
|
|
|
- # calculation distance to intersection
|
|
|
|
|
- #
|
|
|
|
|
- d = (dpar0a*abs(dperp0b)+dpar0b*abs(dperp0a))/(abs(dperp0a)+abs(dperp0b))
|
|
|
|
|
- if ((d < -EPS) | (d > (d01+EPS))):
|
|
|
|
|
- #
|
|
|
|
|
- # intersection outside segment, return no intersection
|
|
|
|
|
- #
|
|
|
|
|
- #print " found intersection outside segment"
|
|
|
|
|
- return [[],[]]
|
|
|
|
|
- else:
|
|
|
|
|
- #
|
|
|
|
|
- # intersection in segment, return intersection
|
|
|
|
|
- #
|
|
|
|
|
- #print " found intersection in segment s0 v0 sa va",seg0,vert0,sega,verta
|
|
|
|
|
- xloc = x0 + dxpar01*d
|
|
|
|
|
- yloc = y0 + dypar01*d
|
|
|
|
|
- return [xloc,yloc]
|
|
|
|
|
-
|
|
|
|
|
-def insert(path,x,y,seg,vert,intersection):
|
|
|
|
|
- #
|
|
|
|
|
- # insert a vertex at x,y in seg,vert, if needed
|
|
|
|
|
- #
|
|
|
|
|
- d0 = (path[seg][vert][X]-x)**2 + (path[seg][vert][Y]-y)**2
|
|
|
|
|
- d1 = (path[seg][vert+1][X]-x)**2 + (path[seg][vert+1][Y]-y)**2
|
|
|
|
|
- #print "check insert seg",seg,"vert",vert,"intersection",intersection
|
|
|
|
|
- if ((d0 > EPS) & (d1 > EPS)):
|
|
|
|
|
- #print " added intersection vertex",vert+1
|
|
|
|
|
- path[seg].insert((vert+1),[x,y,intersection])
|
|
|
|
|
- return 1
|
|
|
|
|
- elif (d0 < EPS):
|
|
|
|
|
- if (path[seg][vert][INTERSECT] == []):
|
|
|
|
|
- path[seg][vert][INTERSECT] = intersection
|
|
|
|
|
- #print " added d0",vert
|
|
|
|
|
- return 0
|
|
|
|
|
- elif (d1 < EPS):
|
|
|
|
|
- if (path[seg][vert+1][INTERSECT] == []):
|
|
|
|
|
- path[seg][vert+1][INTERSECT] = intersection
|
|
|
|
|
- #print " added d1",vert+1
|
|
|
|
|
- return 0
|
|
|
|
|
- else:
|
|
|
|
|
- #print " shouldn't happen: d0",d0,"d1",d1
|
|
|
|
|
- return 0
|
|
|
|
|
-
|
|
|
|
|
-def union(i,path,intersections,sign):
|
|
|
|
|
- #
|
|
|
|
|
- # return edge to exit intersection i for a union
|
|
|
|
|
- #
|
|
|
|
|
- #print "union: intersection",i,"in",intersections
|
|
|
|
|
- seg0 = intersections[i][0][SEG]
|
|
|
|
|
- #print "seg0",seg0
|
|
|
|
|
- vert0 = intersections[i][0][VERT]
|
|
|
|
|
- x0 = path[seg0][vert0][X]
|
|
|
|
|
- y0 = path[seg0][vert0][Y]
|
|
|
|
|
- if (vert0 < (len(path[seg0])-1)):
|
|
|
|
|
- vert1 = vert0 + 1
|
|
|
|
|
- else:
|
|
|
|
|
- vert1 = 0
|
|
|
|
|
- x1 = path[seg0][vert1][X]
|
|
|
|
|
- y1 = path[seg0][vert1][Y]
|
|
|
|
|
- dx01 = x1-x0
|
|
|
|
|
- dy01 = y1-y0
|
|
|
|
|
- sega = intersections[i][A][SEG]
|
|
|
|
|
- verta = intersections[i][A][VERT]
|
|
|
|
|
- xa = path[sega][verta][X]
|
|
|
|
|
- ya = path[sega][verta][Y]
|
|
|
|
|
- if (verta < (len(path[sega])-1)):
|
|
|
|
|
- vertb = verta + 1
|
|
|
|
|
- else:
|
|
|
|
|
- vertb = 0
|
|
|
|
|
- xb = path[sega][vertb][X]
|
|
|
|
|
- yb = path[sega][vertb][Y]
|
|
|
|
|
- dxab = xb-xa
|
|
|
|
|
- dyab = yb-ya
|
|
|
|
|
- dot = dxab*dy01 - dyab*dx01
|
|
|
|
|
- #print " dot",dot
|
|
|
|
|
- if (abs(dot) <= EPS):
|
|
|
|
|
- print " colinear"
|
|
|
|
|
- seg = []
|
|
|
|
|
- vert= []
|
|
|
|
|
- elif (dot > EPS):
|
|
|
|
|
- seg = intersections[i][(1-sign)/2][SEG]
|
|
|
|
|
- vert = intersections[i][(1-sign)/2][VERT]
|
|
|
|
|
- else:
|
|
|
|
|
- seg = intersections[i][(1+sign)/2][SEG]
|
|
|
|
|
- vert = intersections[i][(1+sign)/2][VERT]
|
|
|
|
|
- return [seg,vert]
|
|
|
|
|
-
|
|
|
|
|
-# MODIFIED
|
|
|
|
|
-def read(filename): #MOD
|
|
|
|
|
- event = None #MOD
|
|
|
|
|
- print "read(event)"
|
|
|
|
|
- global vertices, faces, boundarys, toolpaths, contours, slices,\
|
|
|
|
|
- xmin, xmax, ymin, ymax, zmin, zmax, noise_flag
|
|
|
|
|
- #
|
|
|
|
|
- # read file
|
|
|
|
|
- #
|
|
|
|
|
- faces = []
|
|
|
|
|
- contours = [[]]
|
|
|
|
|
- boundarys = [[]]
|
|
|
|
|
- toolpaths = [[]]
|
|
|
|
|
- slices = [[]]
|
|
|
|
|
- #filename = infile.get() #MOD
|
|
|
|
|
- if ((find(filename,".cmp") != -1) | (find(filename,".CMP")!= -1) \
|
|
|
|
|
- | (find(filename,".sol")!= -1) | (find(filename,".SOL") != -1) \
|
|
|
|
|
- | (find(filename,".plc")!= -1) | (find(filename,".PLC")!= -1) \
|
|
|
|
|
- | (find(filename,".sts")!= -1) | (find(filename,".STS")!= -1) \
|
|
|
|
|
- | (find(filename,".gtl")!= -1) | (find(filename,".GTL")!= -1) \
|
|
|
|
|
- | (find(filename,".stc")!= -1) | (find(filename,".STC")!= -1)):
|
|
|
|
|
- print "reading Gerber file",filename
|
|
|
|
|
- read_Gerber(filename)
|
|
|
|
|
- elif ((find(filename,".drl") != -1) | (find(filename,".DRL") != -1) | \
|
|
|
|
|
- (find(filename,".drd") != -1) | (find(filename,".DRD") != -1)):
|
|
|
|
|
- print "reading Excellon file",filename
|
|
|
|
|
- read_Excellon(filename)
|
|
|
|
|
- elif ((find(filename,".dxf") != -1) | (find(filename,".DXF") != -1)):
|
|
|
|
|
- print "reading DXF file",filename
|
|
|
|
|
- read_DXF(filename)
|
|
|
|
|
- elif (find(filename,".stl") != -1):
|
|
|
|
|
- print "reading STL file",filename
|
|
|
|
|
- read_STL(filename)
|
|
|
|
|
- elif (find(filename,".jpg") != -1):
|
|
|
|
|
- print "reading image file",filename
|
|
|
|
|
- read_image(filename)
|
|
|
|
|
- elif (find(filename,".svg") != -1):
|
|
|
|
|
- print "reading SVG file",filename
|
|
|
|
|
- read_SVG(filename)
|
|
|
|
|
- else:
|
|
|
|
|
- print "unsupported file type"
|
|
|
|
|
- return
|
|
|
|
|
- xmin = HUGE
|
|
|
|
|
- xmax = -HUGE
|
|
|
|
|
- ymin = HUGE
|
|
|
|
|
- ymax = -HUGE
|
|
|
|
|
- zmin = HUGE
|
|
|
|
|
- zmax = -HUGE
|
|
|
|
|
- if (len(boundarys) == 1):
|
|
|
|
|
- #
|
|
|
|
|
- # 2D file
|
|
|
|
|
- #
|
|
|
|
|
- boundary = boundarys[0]
|
|
|
|
|
- sum = 0
|
|
|
|
|
- for segment in range(len(boundary)):
|
|
|
|
|
- sum += len(boundary[segment])
|
|
|
|
|
- for vertex in range(len(boundary[segment])):
|
|
|
|
|
- x = boundary[segment][vertex][X]
|
|
|
|
|
- y = boundary[segment][vertex][Y]
|
|
|
|
|
- if (x < xmin): xmin = x
|
|
|
|
|
- if (x > xmax): xmax = x
|
|
|
|
|
- if (y < ymin): ymin = y
|
|
|
|
|
- if (y > ymax): ymax = y
|
|
|
|
|
- print " found",len(boundary),"polygons,",sum,"vertices"
|
|
|
|
|
- print " xmin: %0.3g "%xmin,"xmax: %0.3g "%xmax,"dx: %0.3g "%(xmax-xmin)
|
|
|
|
|
- print " ymin: %0.3g "%ymin,"ymax: %0.3g "%ymax,"dy: %0.3g "%(ymax-ymin)
|
|
|
|
|
- if (noise_flag == 1):
|
|
|
|
|
- if ((xmax-xmin) < (ymax-ymin)):
|
|
|
|
|
- delta = (xmax-xmin)*NOISE
|
|
|
|
|
- else:
|
|
|
|
|
- delta = (ymax-ymin)*NOISE
|
|
|
|
|
- for segment in range(len(boundary)):
|
|
|
|
|
- for vertex in range(len(boundary[segment])):
|
|
|
|
|
- boundary[segment][vertex][X] += gauss(0,delta)
|
|
|
|
|
- boundary[segment][vertex][Y] += gauss(0,delta)
|
|
|
|
|
- print " added %.3g perturbation"%delta
|
|
|
|
|
- boundarys[0] = boundary
|
|
|
|
|
- elif (len(boundarys) > 1):
|
|
|
|
|
- #
|
|
|
|
|
- # 3D layers
|
|
|
|
|
- #
|
|
|
|
|
- for layer in range(len(boundarys)):
|
|
|
|
|
- boundary = boundarys[layer]
|
|
|
|
|
- sum = 0
|
|
|
|
|
- for segment in range(len(boundary)):
|
|
|
|
|
- sum += len(boundary[segment])
|
|
|
|
|
- for vertex in range(len(boundary[segment])):
|
|
|
|
|
- x = boundary[segment][vertex][X3]
|
|
|
|
|
- y = boundary[segment][vertex][Y3]
|
|
|
|
|
- z = boundary[segment][vertex][Z3]
|
|
|
|
|
- if (x < xmin): xmin = x
|
|
|
|
|
- if (x > xmax): xmax = x
|
|
|
|
|
- if (y < ymin): ymin = y
|
|
|
|
|
- if (y > ymax): ymax = y
|
|
|
|
|
- if (z < zmin): zmin = z
|
|
|
|
|
- if (z > zmax): zmax = z
|
|
|
|
|
- print " layer",layer,"found",len(boundary),"polygon(s),",sum,"vertices"
|
|
|
|
|
- if (noise_flag == 1):
|
|
|
|
|
- if ((xmax-xmin) < (ymax-ymin)):
|
|
|
|
|
- delta = (xmax-xmin)*NOISE
|
|
|
|
|
- else:
|
|
|
|
|
- delta = (ymax-ymin)*NOISE
|
|
|
|
|
- for segment in range(len(boundary)):
|
|
|
|
|
- for vertex in range(len(boundary[segment])):
|
|
|
|
|
- boundary[segment][vertex][X3] += gauss(0,delta)
|
|
|
|
|
- boundary[segment][vertex][Y3] += gauss(0,delta)
|
|
|
|
|
- boundary[segment][vertex][Z3] += gauss(0,delta)
|
|
|
|
|
- boundarys[layer] = boundary
|
|
|
|
|
- print " xmin: %0.3g "%xmin,"xmax: %0.3g "%xmax,"dx: %0.3g "%(xmax-xmin)
|
|
|
|
|
- print " ymin: %0.3g "%ymin,"ymax: %0.3g "%ymax,"dy: %0.3g "%(ymax-ymin)
|
|
|
|
|
- print " zmin: %0.3g "%zmin,"zmax: %0.3g "%zmax,"dy: %0.3g "%(zmax-zmin)
|
|
|
|
|
- print " added %.3g perturbation"%delta
|
|
|
|
|
- elif (faces != []):
|
|
|
|
|
- #
|
|
|
|
|
- # 3D faces
|
|
|
|
|
- #
|
|
|
|
|
- for vertex in range(len(vertices)):
|
|
|
|
|
- x = vertices[vertex][X]
|
|
|
|
|
- y = vertices[vertex][Y]
|
|
|
|
|
- z = vertices[vertex][Z]
|
|
|
|
|
- if (x < xmin): xmin = x
|
|
|
|
|
- if (x > xmax): xmax = x
|
|
|
|
|
- if (y < ymin): ymin = y
|
|
|
|
|
- if (y > ymax): ymax = y
|
|
|
|
|
- if (z < zmin): zmin = z
|
|
|
|
|
- if (z > zmax): zmax = z
|
|
|
|
|
- print " found",len(vertices),"vertices,",len(faces),"faces"
|
|
|
|
|
- print " xmin: %0.3g "%xmin,"xmax: %0.3g "%xmax,"dx: %0.3g "%(xmax-xmin)
|
|
|
|
|
- print " ymin: %0.3g "%ymin,"ymax: %0.3g "%ymax,"dy: %0.3g "%(ymax-ymin)
|
|
|
|
|
- print " zmin: %0.3g "%zmin,"zmax: %0.3g "%zmax,"dz: %0.3g "%(zmax-zmin)
|
|
|
|
|
- if (noise_flag == 1):
|
|
|
|
|
- delta = (zmax-zmin)*NOISE
|
|
|
|
|
- for vertex in range(len(vertices)):
|
|
|
|
|
- vertices[vertex][X] += gauss(0,delta)
|
|
|
|
|
- vertices[vertex][Y] += gauss(0,delta)
|
|
|
|
|
- vertices[vertex][Z] += gauss(0,delta)
|
|
|
|
|
- print " added %.3g perturbation"%delta
|
|
|
|
|
- else:
|
|
|
|
|
- print "shouldn't happen in read"
|
|
|
|
|
- #camselect(event) MOD
|
|
|
|
|
- print "End read(event)"
|
|
|
|
|
-
|
|
|
|
|
-def write_G(boundarys, toolpaths, scale=1.0, thickness=1.0, feed=1, zclear=0.1, zcut=-0.005):
|
|
|
|
|
- X = 0
|
|
|
|
|
- Y = 1
|
|
|
|
|
- #global boundarys, toolpaths, xmin, ymin, zmin, zmax
|
|
|
|
|
- #
|
|
|
|
|
- # G code output
|
|
|
|
|
- #
|
|
|
|
|
- #xyscale = float(sxyscale.get())
|
|
|
|
|
- xyscale = scale
|
|
|
|
|
- #zscale = float(sxyscale.get())
|
|
|
|
|
- #zscale = scale
|
|
|
|
|
- #dlayer = float(sthickness.get())/zscale
|
|
|
|
|
- #dlayer = thickness/zscale
|
|
|
|
|
- #feed = float(sfeed.get())
|
|
|
|
|
- #xoff = float(sxmin.get()) - xmin*xyscale
|
|
|
|
|
- #yoff = float(symin.get()) - ymin*xyscale
|
|
|
|
|
- #cool = icool.get()
|
|
|
|
|
- #text = outfile.get()
|
|
|
|
|
-
|
|
|
|
|
- output = "" #file = open(text, 'w')
|
|
|
|
|
- output += "%\n" #file.write("%\n")
|
|
|
|
|
- output += "O1234\n" #file.write("O1234\n")
|
|
|
|
|
- #file.write("T"+stool.get()+"M06\n") # tool
|
|
|
|
|
- output += "G90G54\n" #file.write("G90G54\n") # absolute positioning with respect to set origin
|
|
|
|
|
- output += "F%0.3f\n"%feed #file.write("F%0.3f\n"%feed) # feed rate
|
|
|
|
|
- #file.write("S"+sspindle.get()+"\n") # spindle speed
|
|
|
|
|
- #if (cool == TRUE): file.write("M08\n") # coolant on
|
|
|
|
|
- output += "G00Z%.4f\n"%zclear #file.write("G00Z"+szup.get()+"\n") # move up before starting spindle
|
|
|
|
|
- output += "M03\n" #file.write("M03\n") # spindle on clockwise
|
|
|
|
|
- nsegment = 0
|
|
|
|
|
- for layer in range((len(boundarys)-1),-1,-1):
|
|
|
|
|
- if (toolpaths[layer] == []):
|
|
|
|
|
- path = boundarys[layer]
|
|
|
|
|
- else:
|
|
|
|
|
- path = toolpaths[layer]
|
|
|
|
|
- #if (szdown.get() == " "):
|
|
|
|
|
- # zdown = zoff + zmin + (layer-0.50)*dlayer
|
|
|
|
|
- #else:
|
|
|
|
|
- # zdown = float(szdown.get())
|
|
|
|
|
- for segment in range(len(path)):
|
|
|
|
|
- nsegment += 1
|
|
|
|
|
- vertex = 0
|
|
|
|
|
- x = path[segment][vertex][X]*xyscale #+ xoff
|
|
|
|
|
- y = path[segment][vertex][Y]*xyscale #+ yoff
|
|
|
|
|
- output += "G00X%0.4f"%x+"Y%0.4f"%y+"Z%.4f"%zclear+"\n" #file.write("G00X%0.4f"%x+"Y%0.4f"%y+"Z"+szup.get()+"\n") # rapid motion
|
|
|
|
|
- output += "G01Z%0.4f"%zcut+"\n" #file.write("G01Z%0.4f"%zdown+"\n") # linear motion
|
|
|
|
|
- for vertex in range(1,len(path[segment])):
|
|
|
|
|
- x = path[segment][vertex][X]*xyscale #+ xoff
|
|
|
|
|
- y = path[segment][vertex][Y]*xyscale #+ yoff
|
|
|
|
|
- output += "X%0.4f"%x+"Y%0.4f"%y+"\n" #file.write("X%0.4f"%x+"Y%0.4f"%y+"\n")
|
|
|
|
|
- output += "Z%.4f\n"%zclear #file.write("Z"+szup.get()+"\n")
|
|
|
|
|
- output += "G00Z%.4f\n"%zclear #file.write("G00Z"+szup.get()+"\n") # move up before stopping spindle
|
|
|
|
|
- output += "M05\n" #file.write("M05\n") # spindle stop
|
|
|
|
|
- #if (cool == TRUE): file.write("M09\n") # coolant off
|
|
|
|
|
- output += "M30\n" #file.write("M30\n") # program end and reset
|
|
|
|
|
- output += "%\n" #file.write("%\n")
|
|
|
|
|
- #file.close()
|
|
|
|
|
- print "wrote",nsegment,"G code toolpath segments"
|
|
|
|
|
- return output
|
|
|
|
|
################ end of cam.py #############
|
|
################ end of cam.py #############
|