PEP 8 intentation
parent
e0bac6471f
commit
8f6059669d
180
layer.py
180
layer.py
|
@ -5,105 +5,105 @@
|
||||||
import math, mymath
|
import math, mymath
|
||||||
|
|
||||||
class Layer():
|
class Layer():
|
||||||
def __init__(self, dimensions, scale):
|
def __init__(self, dimensions, scale):
|
||||||
self.width, self.height = dimensions
|
self.width, self.height = dimensions
|
||||||
self.scale = scale
|
self.scale = scale
|
||||||
self.buckets = [[] for x in range(self.width * self.height)]
|
self.buckets = [[] for x in range(self.width * self.height)]
|
||||||
self.test = 0
|
self.test = 0
|
||||||
|
|
||||||
def aabb(self, line):
|
def aabb(self, line):
|
||||||
x1, y1, x2, y2, r, g = line
|
x1, y1, x2, y2, r, g = line
|
||||||
if x1 > x2:
|
if x1 > x2:
|
||||||
x1, x2 = x2, x1
|
x1, x2 = x2, x1
|
||||||
if y1 > y2:
|
if y1 > y2:
|
||||||
y1, y2 = y2, y1
|
y1, y2 = y2, y1
|
||||||
r += g
|
r += g
|
||||||
minx = int(math.floor((x1 - r) * self.scale))
|
minx = int(math.floor((x1 - r) * self.scale))
|
||||||
miny = int(math.floor((y1 - r) * self.scale))
|
miny = int(math.floor((y1 - r) * self.scale))
|
||||||
maxx = int(math.ceil((x2 + r) * self.scale))
|
maxx = int(math.ceil((x2 + r) * self.scale))
|
||||||
maxy = int(math.ceil((y2 + r) * self.scale))
|
maxy = int(math.ceil((y2 + r) * self.scale))
|
||||||
if minx < 0:
|
if minx < 0:
|
||||||
minx = 0
|
minx = 0
|
||||||
if miny < 0:
|
if miny < 0:
|
||||||
miny = 0
|
miny = 0
|
||||||
if maxx > self.width:
|
if maxx > self.width:
|
||||||
maxx = self.width
|
maxx = self.width
|
||||||
if maxy > self.height:
|
if maxy > self.height:
|
||||||
maxy = self.height
|
maxy = self.height
|
||||||
return (minx, miny, maxx, maxy)
|
return (minx, miny, maxx, maxy)
|
||||||
|
|
||||||
def all_buckets(self, aabb):
|
def all_buckets(self, aabb):
|
||||||
x1, y1, x2, y2 = aabb
|
x1, y1, x2, y2 = aabb
|
||||||
for y in range(y1, y2):
|
for y in range(y1, y2):
|
||||||
for x in range(x1, x2):
|
for x in range(x1, x2):
|
||||||
yield self.buckets[y * self.width + x]
|
yield self.buckets[y * self.width + x]
|
||||||
|
|
||||||
def all_not_empty_buckets(self, aabb):
|
def all_not_empty_buckets(self, aabb):
|
||||||
x1, y1, x2, y2 = aabb
|
x1, y1, x2, y2 = aabb
|
||||||
for y in range(y1, y2):
|
for y in range(y1, y2):
|
||||||
for x in range(x1, x2):
|
for x in range(x1, x2):
|
||||||
bucket = self.buckets[y * self.width + x]
|
bucket = self.buckets[y * self.width + x]
|
||||||
if bucket:
|
if bucket:
|
||||||
yield bucket
|
yield bucket
|
||||||
|
|
||||||
def add_line(self, line):
|
def add_line(self, line):
|
||||||
new_record = [0, line]
|
new_record = [0, line]
|
||||||
for bucket in self.all_buckets(self.aabb(line)):
|
for bucket in self.all_buckets(self.aabb(line)):
|
||||||
found = False
|
found = False
|
||||||
for record in bucket:
|
for record in bucket:
|
||||||
if record[1] == line:
|
if record[1] == line:
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
if not found:
|
if not found:
|
||||||
bucket.append(new_record)
|
bucket.append(new_record)
|
||||||
|
|
||||||
def sub_line(self, line):
|
def sub_line(self, line):
|
||||||
for bucket in self.all_not_empty_buckets(self.aabb(line)):
|
for bucket in self.all_not_empty_buckets(self.aabb(line)):
|
||||||
for i in range(len(bucket) - 1, -1, -1):
|
for i in range(len(bucket) - 1, -1, -1):
|
||||||
if bucket[i][1] == line:
|
if bucket[i][1] == line:
|
||||||
del bucket[i]
|
del bucket[i]
|
||||||
|
|
||||||
def hit_line(self, line):
|
def hit_line(self, line):
|
||||||
self.test += 1
|
self.test += 1
|
||||||
for bucket in self.all_not_empty_buckets(self.aabb(line)):
|
for bucket in self.all_not_empty_buckets(self.aabb(line)):
|
||||||
for record in bucket:
|
for record in bucket:
|
||||||
if record[0] != self.test:
|
if record[0] != self.test:
|
||||||
record[0] = self.test
|
record[0] = self.test
|
||||||
l1_p1x, l1_p1y, l1_p2x, l1_p2y, l1_r, l1_g = line
|
l1_p1x, l1_p1y, l1_p2x, l1_p2y, l1_r, l1_g = line
|
||||||
l2_p1x, l2_p1y, l2_p2x, l2_p2y, l2_r, l2_g = record[1]
|
l2_p1x, l2_p1y, l2_p2x, l2_p2y, l2_r, l2_g = record[1]
|
||||||
r = l1_r + l2_r + max(l1_g, l2_g)
|
r = l1_r + l2_r + max(l1_g, l2_g)
|
||||||
if mymath.collide_thick_lines_2d((l1_p1x, l1_p1y), (l1_p2x, l1_p2y), (l2_p1x, l2_p1y), (l2_p2x, l2_p2y), r):
|
if mymath.collide_thick_lines_2d((l1_p1x, l1_p1y), (l1_p2x, l1_p2y), (l2_p1x, l2_p1y), (l2_p2x, l2_p2y), r):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class Layers():
|
class Layers():
|
||||||
def __init__(self, dimensions, scale):
|
def __init__(self, dimensions, scale):
|
||||||
width, height, self.depth = dimensions
|
width, height, self.depth = dimensions
|
||||||
self.layers = [Layer((width, height), scale) for z in range(self.depth)]
|
self.layers = [Layer((width, height), scale) for z in range(self.depth)]
|
||||||
|
|
||||||
def all_layers(self, z1, z2):
|
def all_layers(self, z1, z2):
|
||||||
if z1 != z2:
|
if z1 != z2:
|
||||||
for z in range(self.depth):
|
for z in range(self.depth):
|
||||||
yield self.layers[z]
|
yield self.layers[z]
|
||||||
else:
|
else:
|
||||||
yield self.layers[int(z1)]
|
yield self.layers[int(z1)]
|
||||||
|
|
||||||
def add_line(self, p1, p2, r, g):
|
def add_line(self, p1, p2, r, g):
|
||||||
x1, y1, z1 = p1
|
x1, y1, z1 = p1
|
||||||
x2, y2, z2 = p2
|
x2, y2, z2 = p2
|
||||||
for layer in self.all_layers(z1, z2):
|
for layer in self.all_layers(z1, z2):
|
||||||
layer.add_line((x1, y1, x2, y2, r, g))
|
layer.add_line((x1, y1, x2, y2, r, g))
|
||||||
|
|
||||||
def sub_line(self, p1, p2, r, g):
|
def sub_line(self, p1, p2, r, g):
|
||||||
x1, y1, z1 = p1
|
x1, y1, z1 = p1
|
||||||
x2, y2, z2 = p2
|
x2, y2, z2 = p2
|
||||||
for layer in self.all_layers(z1, z2):
|
for layer in self.all_layers(z1, z2):
|
||||||
layer.sub_line((x1, y1, x2, y2, r, g))
|
layer.sub_line((x1, y1, x2, y2, r, g))
|
||||||
|
|
||||||
def hit_line(self, p1, p2, r, g):
|
def hit_line(self, p1, p2, r, g):
|
||||||
x1, y1, z1 = p1
|
x1, y1, z1 = p1
|
||||||
x2, y2, z2 = p2
|
x2, y2, z2 = p2
|
||||||
for layer in self.all_layers(z1, z2):
|
for layer in self.all_layers(z1, z2):
|
||||||
if layer.hit_line((x1, y1, x2, y2, r, g)):
|
if layer.hit_line((x1, y1, x2, y2, r, g)):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
478
mymath.py
478
mymath.py
|
@ -7,332 +7,332 @@ import math, random, itertools
|
||||||
#generic distance metric stuff
|
#generic distance metric stuff
|
||||||
|
|
||||||
def manhattan_distance(p1, p2):
|
def manhattan_distance(p1, p2):
|
||||||
return sum(abs(x - y) for x, y in zip(p1, p2))
|
return sum(abs(x - y) for x, y in zip(p1, p2))
|
||||||
|
|
||||||
def euclidean_distance(p1, p2):
|
def euclidean_distance(p1, p2):
|
||||||
return math.sqrt(sum((x - y) ** 2 for x, y in zip(p1, p2)))
|
return math.sqrt(sum((x - y) ** 2 for x, y in zip(p1, p2)))
|
||||||
|
|
||||||
def squared_euclidean_distance(p1, p2):
|
def squared_euclidean_distance(p1, p2):
|
||||||
return sum((x - y) ** 2 for x, y in zip(p1, p2))
|
return sum((x - y) ** 2 for x, y in zip(p1, p2))
|
||||||
|
|
||||||
def chebyshev_distance(p1, p2):
|
def chebyshev_distance(p1, p2):
|
||||||
return max(abs(x - y) for x, y in zip(p1, p2))
|
return max(abs(x - y) for x, y in zip(p1, p2))
|
||||||
|
|
||||||
def reciprical_distance(p1, p2):
|
def reciprical_distance(p1, p2):
|
||||||
d = manhattan_distance(p1, p2)
|
d = manhattan_distance(p1, p2)
|
||||||
return 1.0 / d if d != 0 else 1.0
|
return 1.0 / d if d != 0 else 1.0
|
||||||
|
|
||||||
def random_distance(p1, p2):
|
def random_distance(p1, p2):
|
||||||
return random.random()
|
return random.random()
|
||||||
|
|
||||||
#generic vector stuff
|
#generic vector stuff
|
||||||
|
|
||||||
def sign(x):
|
def sign(x):
|
||||||
if x == 0:
|
if x == 0:
|
||||||
return 0
|
return 0
|
||||||
if x < 0:
|
if x < 0:
|
||||||
return -1
|
return -1
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def equal(p1, p2):
|
def equal(p1, p2):
|
||||||
return manhattan_distance(p1, p2) == 0.0
|
return manhattan_distance(p1, p2) == 0.0
|
||||||
|
|
||||||
def add(p1, p2):
|
def add(p1, p2):
|
||||||
return tuple(x + y for x, y in zip(p1, p2))
|
return tuple(x + y for x, y in zip(p1, p2))
|
||||||
|
|
||||||
def sub(p1, p2):
|
def sub(p1, p2):
|
||||||
return tuple(x - y for x, y in zip(p1, p2))
|
return tuple(x - y for x, y in zip(p1, p2))
|
||||||
|
|
||||||
def scale(p, s):
|
def scale(p, s):
|
||||||
return tuple(x * s for x in p)
|
return tuple(x * s for x in p)
|
||||||
|
|
||||||
def dot(p1, p2):
|
def dot(p1, p2):
|
||||||
return sum(x * y for x, y in zip(p1, p2))
|
return sum(x * y for x, y in zip(p1, p2))
|
||||||
|
|
||||||
def length(p):
|
def length(p):
|
||||||
return math.sqrt(dot(p, p))
|
return math.sqrt(dot(p, p))
|
||||||
|
|
||||||
def distance(p1, p2):
|
def distance(p1, p2):
|
||||||
return length(sub(p2, p1))
|
return length(sub(p2, p1))
|
||||||
|
|
||||||
def distance_squared(p1, p2):
|
def distance_squared(p1, p2):
|
||||||
p = sub(p2, p1)
|
p = sub(p2, p1)
|
||||||
return dot(p, p)
|
return dot(p, p)
|
||||||
|
|
||||||
def norm(p):
|
def norm(p):
|
||||||
l = length(p)
|
l = length(p)
|
||||||
if l == 0:
|
if l == 0:
|
||||||
return scale(p, 0)
|
return scale(p, 0)
|
||||||
l = 1.0 / l
|
l = 1.0 / l
|
||||||
return scale(p, l)
|
return scale(p, l)
|
||||||
|
|
||||||
def distance_to_line(p, p1, p2):
|
def distance_to_line(p, p1, p2):
|
||||||
lv = sub(p2, p1)
|
lv = sub(p2, p1)
|
||||||
pv = sub(p, p1)
|
pv = sub(p, p1)
|
||||||
c1 = dot(pv, lv)
|
c1 = dot(pv, lv)
|
||||||
if c1 <= 0:
|
if c1 <= 0:
|
||||||
return distance(p, p1)
|
return distance(p, p1)
|
||||||
c2 = dot(lv, lv)
|
c2 = dot(lv, lv)
|
||||||
if c2 <= c1:
|
if c2 <= c1:
|
||||||
return distance(p, p2)
|
return distance(p, p2)
|
||||||
return distance(p, add(p1, scale(lv, c1 / float(c2))))
|
return distance(p, add(p1, scale(lv, c1 / float(c2))))
|
||||||
|
|
||||||
def distance_squared_to_line(p, p1, p2):
|
def distance_squared_to_line(p, p1, p2):
|
||||||
lv = sub(p2, p1)
|
lv = sub(p2, p1)
|
||||||
pv = sub(p, p1)
|
pv = sub(p, p1)
|
||||||
c1 = dot(pv, lv)
|
c1 = dot(pv, lv)
|
||||||
if c1 <= 0:
|
if c1 <= 0:
|
||||||
return distance_squared(p, p1)
|
return distance_squared(p, p1)
|
||||||
c2 = dot(lv, lv)
|
c2 = dot(lv, lv)
|
||||||
if c2 <= c1:
|
if c2 <= c1:
|
||||||
return distance_squared(p, p2)
|
return distance_squared(p, p2)
|
||||||
return distance_squared(p, add(p1, scale(lv, c1 / float(c2))))
|
return distance_squared(p, add(p1, scale(lv, c1 / float(c2))))
|
||||||
|
|
||||||
#specific vector stuff
|
#specific vector stuff
|
||||||
|
|
||||||
def add_2d(p1, p2):
|
def add_2d(p1, p2):
|
||||||
x1, y1 = p1
|
x1, y1 = p1
|
||||||
x2, y2 = p2
|
x2, y2 = p2
|
||||||
return x1 + x2, y1 + y2
|
return x1 + x2, y1 + y2
|
||||||
|
|
||||||
def add_3d(p1, p2):
|
def add_3d(p1, p2):
|
||||||
x1, y1, z1 = p1
|
x1, y1, z1 = p1
|
||||||
x2, y2, z2 = p2
|
x2, y2, z2 = p2
|
||||||
return x1 + x2, y1 + y2, z1 + z2
|
return x1 + x2, y1 + y2, z1 + z2
|
||||||
|
|
||||||
def sub_2d(p1, p2):
|
def sub_2d(p1, p2):
|
||||||
x1, y1 = p1
|
x1, y1 = p1
|
||||||
x2, y2 = p2
|
x2, y2 = p2
|
||||||
return x1 - x2, y1 - y2
|
return x1 - x2, y1 - y2
|
||||||
|
|
||||||
def sub_3d(p1, p2):
|
def sub_3d(p1, p2):
|
||||||
x1, y1, z1 = p1
|
x1, y1, z1 = p1
|
||||||
x2, y2, z2 = p2
|
x2, y2, z2 = p2
|
||||||
return x1 - x2, y1 - y2, z1 - z2
|
return x1 - x2, y1 - y2, z1 - z2
|
||||||
|
|
||||||
def scale_2d(p, s):
|
def scale_2d(p, s):
|
||||||
x, y = p
|
x, y = p
|
||||||
return x * s, y * s
|
return x * s, y * s
|
||||||
|
|
||||||
def scale_3d(p, s):
|
def scale_3d(p, s):
|
||||||
x, y, z = p
|
x, y, z = p
|
||||||
return x * s, y * s, z * s
|
return x * s, y * s, z * s
|
||||||
|
|
||||||
def perp_2d(p):
|
def perp_2d(p):
|
||||||
x, y = p
|
x, y = p
|
||||||
return y, -x
|
return y, -x
|
||||||
|
|
||||||
def cross_3d(p1, p2):
|
def cross_3d(p1, p2):
|
||||||
x1, y1, z1 = p1
|
x1, y1, z1 = p1
|
||||||
x2, y2, z2 = p2
|
x2, y2, z2 = p2
|
||||||
return (y1 * z2 - z1 * y2, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2)
|
return (y1 * z2 - z1 * y2, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2)
|
||||||
|
|
||||||
def dot_2d(p1, p2):
|
def dot_2d(p1, p2):
|
||||||
x1, y1 = p1
|
x1, y1 = p1
|
||||||
x2, y2 = p2
|
x2, y2 = p2
|
||||||
return x1 * x2 + y1 * y2
|
return x1 * x2 + y1 * y2
|
||||||
|
|
||||||
def dot_3d(p1, p2):
|
def dot_3d(p1, p2):
|
||||||
x1, y1, z1 = p1
|
x1, y1, z1 = p1
|
||||||
x2, y2, z2 = p2
|
x2, y2, z2 = p2
|
||||||
return x1 * x2 + y1 * y2 + z1 * z2
|
return x1 * x2 + y1 * y2 + z1 * z2
|
||||||
|
|
||||||
def length_2d(p):
|
def length_2d(p):
|
||||||
return math.sqrt(dot_2d(p, p))
|
return math.sqrt(dot_2d(p, p))
|
||||||
|
|
||||||
def length_3d(p):
|
def length_3d(p):
|
||||||
return math.sqrt(dot_3d(p, p))
|
return math.sqrt(dot_3d(p, p))
|
||||||
|
|
||||||
def norm_2d(p):
|
def norm_2d(p):
|
||||||
l = length_2d(p)
|
l = length_2d(p)
|
||||||
if l == 0:
|
if l == 0:
|
||||||
return (0, 0)
|
return (0, 0)
|
||||||
x, y = p
|
x, y = p
|
||||||
return (x / l, y / l)
|
return (x / l, y / l)
|
||||||
|
|
||||||
def norm_3d(p):
|
def norm_3d(p):
|
||||||
l = length_3d(p)
|
l = length_3d(p)
|
||||||
if l == 0:
|
if l == 0:
|
||||||
return (0, 0, 0)
|
return (0, 0, 0)
|
||||||
x, y, z = p
|
x, y, z = p
|
||||||
return (x / l, y / l, z / l)
|
return (x / l, y / l, z / l)
|
||||||
|
|
||||||
def distance_2d(p1, p2):
|
def distance_2d(p1, p2):
|
||||||
return length_2d(sub_2d(p2 - p1))
|
return length_2d(sub_2d(p2 - p1))
|
||||||
|
|
||||||
def distance_3d(p1, p2):
|
def distance_3d(p1, p2):
|
||||||
return length_3d(sub_3d(p2 - p1))
|
return length_3d(sub_3d(p2 - p1))
|
||||||
|
|
||||||
def distance_squared_2d(p1, p2):
|
def distance_squared_2d(p1, p2):
|
||||||
x1, y1 = p1
|
x1, y1 = p1
|
||||||
x2, y2 = p2
|
x2, y2 = p2
|
||||||
p = x2 - x1, y2 - y1
|
p = x2 - x1, y2 - y1
|
||||||
return dot_2d(p, p)
|
return dot_2d(p, p)
|
||||||
|
|
||||||
def distance_squared_3d(p1, p2):
|
def distance_squared_3d(p1, p2):
|
||||||
x1, y1, z1 = p1
|
x1, y1, z1 = p1
|
||||||
x2, y2, z2 = p2
|
x2, y2, z2 = p2
|
||||||
p = x2 - x1, y2 - y1, z2 - z1
|
p = x2 - x1, y2 - y1, z2 - z1
|
||||||
return dot_3d(p, p)
|
return dot_3d(p, p)
|
||||||
|
|
||||||
def distance_to_line_2d(p, p1, p2):
|
def distance_to_line_2d(p, p1, p2):
|
||||||
lv = sub_2d(p2, p1)
|
lv = sub_2d(p2, p1)
|
||||||
pv = sub_2d(p, p1)
|
pv = sub_2d(p, p1)
|
||||||
c1 = dot_2d(pv, lv)
|
c1 = dot_2d(pv, lv)
|
||||||
if c1 <= 0:
|
if c1 <= 0:
|
||||||
return distance_2d(p, p1)
|
return distance_2d(p, p1)
|
||||||
c2 = dot_2d(lv, lv)
|
c2 = dot_2d(lv, lv)
|
||||||
if c2 <= c1:
|
if c2 <= c1:
|
||||||
return distance_2d(p, p2)
|
return distance_2d(p, p2)
|
||||||
return distance_2d(p, add_2d(p1, scale_2d(lv, c1 / float(c2))))
|
return distance_2d(p, add_2d(p1, scale_2d(lv, c1 / float(c2))))
|
||||||
|
|
||||||
def distance_to_line_3d(p, p1, p2):
|
def distance_to_line_3d(p, p1, p2):
|
||||||
lv = sub_3d(p2, p1)
|
lv = sub_3d(p2, p1)
|
||||||
pv = sub_3d(p, p1)
|
pv = sub_3d(p, p1)
|
||||||
c1 = dot_3d(pv, lv)
|
c1 = dot_3d(pv, lv)
|
||||||
if c1 <= 0:
|
if c1 <= 0:
|
||||||
return distance_3d(p, p1)
|
return distance_3d(p, p1)
|
||||||
c2 = dot_3d(lv, lv)
|
c2 = dot_3d(lv, lv)
|
||||||
if c2 <= c1:
|
if c2 <= c1:
|
||||||
return distance_3d(p, p2)
|
return distance_3d(p, p2)
|
||||||
return distance_3d(p, add_3d(p1, scale_3d(lv, c1 / float(c2))))
|
return distance_3d(p, add_3d(p1, scale_3d(lv, c1 / float(c2))))
|
||||||
|
|
||||||
def distance_squared_to_line_2d(p, p1, p2):
|
def distance_squared_to_line_2d(p, p1, p2):
|
||||||
lv = sub_2d(p2, p1)
|
lv = sub_2d(p2, p1)
|
||||||
pv = sub_2d(p, p1)
|
pv = sub_2d(p, p1)
|
||||||
c1 = dot_2d(pv, lv)
|
c1 = dot_2d(pv, lv)
|
||||||
if c1 <= 0:
|
if c1 <= 0:
|
||||||
return distance_squared_2d(p, p1)
|
return distance_squared_2d(p, p1)
|
||||||
c2 = dot_2d(lv, lv)
|
c2 = dot_2d(lv, lv)
|
||||||
if c2 <= c1:
|
if c2 <= c1:
|
||||||
return distance_squared_2d(p, p2)
|
return distance_squared_2d(p, p2)
|
||||||
return distance_squared_2d(p, add_2d(p1, scale_2d(lv, c1 / float(c2))))
|
return distance_squared_2d(p, add_2d(p1, scale_2d(lv, c1 / float(c2))))
|
||||||
|
|
||||||
def distance_squared_to_line_3d(p, p1, p2):
|
def distance_squared_to_line_3d(p, p1, p2):
|
||||||
lv = sub_3d(p2, p1)
|
lv = sub_3d(p2, p1)
|
||||||
pv = sub_3d(p, p1)
|
pv = sub_3d(p, p1)
|
||||||
c1 = dot_3d(pv, lv)
|
c1 = dot_3d(pv, lv)
|
||||||
if c1 <= 0:
|
if c1 <= 0:
|
||||||
return distance_squared_3d(p, p1)
|
return distance_squared_3d(p, p1)
|
||||||
c2 = dot_3d(lv, lv)
|
c2 = dot_3d(lv, lv)
|
||||||
if c2 <= c1:
|
if c2 <= c1:
|
||||||
return distance_squared_3d(p, p2)
|
return distance_squared_3d(p, p2)
|
||||||
return distance_squared_3d(p, add_3d(p1, scale_3d(lv, c1 / float(c2))))
|
return distance_squared_3d(p, add_3d(p1, scale_3d(lv, c1 / float(c2))))
|
||||||
|
|
||||||
def collide_lines_2d(l1_p1, l1_p2, l2_p1, l2_p2):
|
def collide_lines_2d(l1_p1, l1_p2, l2_p1, l2_p2):
|
||||||
l1_x1, l1_y1 = l1_p1
|
l1_x1, l1_y1 = l1_p1
|
||||||
l1_x2, l1_y2 = l1_p2
|
l1_x2, l1_y2 = l1_p2
|
||||||
l2_x1, l2_y1 = l2_p1
|
l2_x1, l2_y1 = l2_p1
|
||||||
l2_x2, l2_y2 = l2_p2
|
l2_x2, l2_y2 = l2_p2
|
||||||
ax = l1_x2 - l1_x1
|
ax = l1_x2 - l1_x1
|
||||||
ay = l1_y2 - l1_y1
|
ay = l1_y2 - l1_y1
|
||||||
bx = l2_x1 - l2_x2
|
bx = l2_x1 - l2_x2
|
||||||
by = l2_y1 - l2_y2
|
by = l2_y1 - l2_y2
|
||||||
cx = l1_x1 - l2_x1
|
cx = l1_x1 - l2_x1
|
||||||
cy = l1_y1 - l2_y1
|
cy = l1_y1 - l2_y1
|
||||||
an = by * cx - bx * cy
|
an = by * cx - bx * cy
|
||||||
ad = ay * bx - ax * by
|
ad = ay * bx - ax * by
|
||||||
bn = ax * cy - ay * cx
|
bn = ax * cy - ay * cx
|
||||||
bd = ay * bx - ax * by
|
bd = ay * bx - ax * by
|
||||||
if (ad == 0 or bd == 0):
|
if (ad == 0 or bd == 0):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
if (ad > 0):
|
if (ad > 0):
|
||||||
if (an < 0 or an > ad):
|
if (an < 0 or an > ad):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
if (an > 0 or an < ad):
|
if (an > 0 or an < ad):
|
||||||
return False;
|
return False;
|
||||||
if (bd > 0):
|
if (bd > 0):
|
||||||
if (bn < 0 or bn > bd):
|
if (bn < 0 or bn > bd):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
if (bn > 0 or bn < bd):
|
if (bn > 0 or bn < bd):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def collide_thick_lines_2d(tl1_p1, tl1_p2, tl2_p1, tl2_p2, r):
|
def collide_thick_lines_2d(tl1_p1, tl1_p2, tl2_p1, tl2_p2, r):
|
||||||
if collide_lines_2d(tl1_p1, tl1_p2, tl2_p1, tl2_p2):
|
if collide_lines_2d(tl1_p1, tl1_p2, tl2_p1, tl2_p2):
|
||||||
return True
|
return True
|
||||||
r *= r
|
r *= r
|
||||||
if distance_squared_to_line_2d(tl2_p1, tl1_p1, tl1_p2) <= r:
|
if distance_squared_to_line_2d(tl2_p1, tl1_p1, tl1_p2) <= r:
|
||||||
return True
|
return True
|
||||||
if distance_squared_to_line_2d(tl2_p2, tl1_p1, tl1_p2) <= r:
|
if distance_squared_to_line_2d(tl2_p2, tl1_p1, tl1_p2) <= r:
|
||||||
return True
|
return True
|
||||||
if distance_squared_to_line_2d(tl1_p1, tl2_p1, tl2_p2) <= r:
|
if distance_squared_to_line_2d(tl1_p1, tl2_p1, tl2_p2) <= r:
|
||||||
return True
|
return True
|
||||||
if distance_squared_to_line_2d(tl1_p2, tl2_p1, tl2_p2) <= r:
|
if distance_squared_to_line_2d(tl1_p2, tl2_p1, tl2_p2) <= r:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
#generic path stuff
|
#generic path stuff
|
||||||
|
|
||||||
def thicken_path_2d(points, radius, capstyle, joinstyle):
|
def thicken_path_2d(points, radius, capstyle, joinstyle):
|
||||||
if radius == 0:
|
if radius == 0:
|
||||||
return points[:] + points[::-1]
|
return points[:] + points[::-1]
|
||||||
index = 0
|
index = 0
|
||||||
step = 1
|
step = 1
|
||||||
out_points = []
|
out_points = []
|
||||||
resolution = int(math.pi * radius) + 1
|
resolution = int(math.pi * radius) + 1
|
||||||
while True:
|
while True:
|
||||||
p1 = points[index]; index += step
|
p1 = points[index]; index += step
|
||||||
p2 = points[index]; index += step
|
p2 = points[index]; index += step
|
||||||
l2_v = sub_2d(p2, p1)
|
l2_v = sub_2d(p2, p1)
|
||||||
l2_pv = perp_2d(l2_v)
|
l2_pv = perp_2d(l2_v)
|
||||||
l2_npv = norm_2d(l2_pv)
|
l2_npv = norm_2d(l2_pv)
|
||||||
rv = scale_2d(l2_npv, radius)
|
rv = scale_2d(l2_npv, radius)
|
||||||
if capstyle == 0:
|
if capstyle == 0:
|
||||||
#butt cap
|
#butt cap
|
||||||
out_points.append(sub_2d(p1, rv))
|
out_points.append(sub_2d(p1, rv))
|
||||||
out_points.append(add_2d(p1, rv))
|
out_points.append(add_2d(p1, rv))
|
||||||
elif capstyle == 1:
|
elif capstyle == 1:
|
||||||
#square cap
|
#square cap
|
||||||
p0 = add_2d(p1, perp_2d(rv))
|
p0 = add_2d(p1, perp_2d(rv))
|
||||||
out_points.append(sub_2d(p0, rv))
|
out_points.append(sub_2d(p0, rv))
|
||||||
out_points.append(add_2d(p0, rv))
|
out_points.append(add_2d(p0, rv))
|
||||||
elif capstyle == 2:
|
elif capstyle == 2:
|
||||||
#triangle cap
|
#triangle cap
|
||||||
out_points.append(sub_2d(p1, rv))
|
out_points.append(sub_2d(p1, rv))
|
||||||
out_points.append(add_2d(p1, perp_2d(rv)))
|
out_points.append(add_2d(p1, perp_2d(rv)))
|
||||||
out_points.append(add_2d(p1, rv))
|
out_points.append(add_2d(p1, rv))
|
||||||
elif capstyle == 3:
|
elif capstyle == 3:
|
||||||
#round cap
|
#round cap
|
||||||
rvx, rvy = rv
|
rvx, rvy = rv
|
||||||
for i in range(resolution + 1):
|
for i in range(resolution + 1):
|
||||||
angle = (i * math.pi) / resolution
|
angle = (i * math.pi) / resolution
|
||||||
s = math.sin(angle)
|
s = math.sin(angle)
|
||||||
c = math.cos(angle)
|
c = math.cos(angle)
|
||||||
rv = rvx * c - rvy * s, rvx * s + rvy * c
|
rv = rvx * c - rvy * s, rvx * s + rvy * c
|
||||||
out_points.append(sub_2d(p1, rv))
|
out_points.append(sub_2d(p1, rv))
|
||||||
while index != -1 and index != len(points):
|
while index != -1 and index != len(points):
|
||||||
p1, l1_v, l1_npv = p2, l2_v, l2_npv
|
p1, l1_v, l1_npv = p2, l2_v, l2_npv
|
||||||
p2 = points[index]; index += step
|
p2 = points[index]; index += step
|
||||||
l2_v = sub_2d(p2, p1)
|
l2_v = sub_2d(p2, p1)
|
||||||
l2_pv = perp_2d(l2_v)
|
l2_pv = perp_2d(l2_v)
|
||||||
l2_npv = norm_2d(l2_pv)
|
l2_npv = norm_2d(l2_pv)
|
||||||
nbv = norm_2d(scale_2d(add_2d(l1_npv, l2_npv), 0.5))
|
nbv = norm_2d(scale_2d(add_2d(l1_npv, l2_npv), 0.5))
|
||||||
c = dot_2d(nbv, norm_2d(l1_v))
|
c = dot_2d(nbv, norm_2d(l1_v))
|
||||||
if c <= 0 or joinstyle == 0:
|
if c <= 0 or joinstyle == 0:
|
||||||
#mitre join
|
#mitre join
|
||||||
s = math.sin(math.acos(c))
|
s = math.sin(math.acos(c))
|
||||||
bv = scale_2d(nbv, radius / s)
|
bv = scale_2d(nbv, radius / s)
|
||||||
out_points.append(add_2d(p1, bv))
|
out_points.append(add_2d(p1, bv))
|
||||||
elif joinstyle == 1:
|
elif joinstyle == 1:
|
||||||
#bevel join
|
#bevel join
|
||||||
out_points.append(add_2d(p1, scale_2d(l1_npv, radius)))
|
out_points.append(add_2d(p1, scale_2d(l1_npv, radius)))
|
||||||
out_points.append(add_2d(p1, scale_2d(l2_npv, radius)))
|
out_points.append(add_2d(p1, scale_2d(l2_npv, radius)))
|
||||||
elif joinstyle == 2:
|
elif joinstyle == 2:
|
||||||
#round join
|
#round join
|
||||||
rvx, rvy = scale_2d(l1_npv, radius)
|
rvx, rvy = scale_2d(l1_npv, radius)
|
||||||
theta = math.acos(dot_2d(l1_npv, l2_npv))
|
theta = math.acos(dot_2d(l1_npv, l2_npv))
|
||||||
segs = int((theta / math.pi) * resolution) + 1
|
segs = int((theta / math.pi) * resolution) + 1
|
||||||
for i in range(segs + 1):
|
for i in range(segs + 1):
|
||||||
angle = (i * theta) / segs
|
angle = (i * theta) / segs
|
||||||
s = math.sin(angle)
|
s = math.sin(angle)
|
||||||
c = math.cos(angle)
|
c = math.cos(angle)
|
||||||
rv = rvx * c - rvy * s, rvx * s + rvy * c
|
rv = rvx * c - rvy * s, rvx * s + rvy * c
|
||||||
out_points.append(add_2d(p1, rv))
|
out_points.append(add_2d(p1, rv))
|
||||||
if step < 0:
|
if step < 0:
|
||||||
break
|
break
|
||||||
step = -step; index += step
|
step = -step; index += step
|
||||||
return out_points
|
return out_points
|
||||||
|
|
112
pcb.py
112
pcb.py
|
@ -9,67 +9,67 @@ from ast import literal_eval
|
||||||
from mymath import *
|
from mymath import *
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description = 'Pcb layout optimizer.', formatter_class = argparse.RawTextHelpFormatter)
|
parser = argparse.ArgumentParser(description = 'Pcb layout optimizer.', formatter_class = argparse.RawTextHelpFormatter)
|
||||||
parser.add_argument('infile', nargs = '?', type = argparse.FileType('r'), default = sys.stdin, help = 'filename, default stdin')
|
parser.add_argument('infile', nargs = '?', type = argparse.FileType('r'), default = sys.stdin, help = 'filename, default stdin')
|
||||||
parser.add_argument('--t', nargs = 1, type = int, default = [600], help = 'timeout in seconds, default 600')
|
parser.add_argument('--t', nargs = 1, type = int, default = [600], help = 'timeout in seconds, default 600')
|
||||||
parser.add_argument('--v', nargs = 1, type = int, default = [0], choices = range(0, 2), help = 'verbosity level 0..1, default 0')
|
parser.add_argument('--v', nargs = 1, type = int, default = [0], choices = range(0, 2), help = 'verbosity level 0..1, default 0')
|
||||||
parser.add_argument('--s', nargs = 1, type = int, default = [1], help = 'number of samples, default 1')
|
parser.add_argument('--s', nargs = 1, type = int, default = [1], help = 'number of samples, default 1')
|
||||||
parser.add_argument('--r', nargs = 1, type = int, default = [1], choices = range(1, 5), help = 'grid resolution 1..4, default 1')
|
parser.add_argument('--r', nargs = 1, type = int, default = [1], choices = range(1, 5), help = 'grid resolution 1..4, default 1')
|
||||||
parser.add_argument('--z', nargs = 1, type = int, default = [0], choices = range(0, 2), help = 'minimize vias 0..1, default 0')
|
parser.add_argument('--z', nargs = 1, type = int, default = [0], choices = range(0, 2), help = 'minimize vias 0..1, default 0')
|
||||||
parser.add_argument('--d', nargs = 1, type = int, default = [0], choices = range(0, 6), \
|
parser.add_argument('--d', nargs = 1, type = int, default = [0], choices = range(0, 6), \
|
||||||
help = 'distance metric 0..5, default 0.\n' \
|
help = 'distance metric 0..5, default 0.\n' \
|
||||||
'0 -> manhattan\n1 -> squared_euclidean\n2 -> euclidean\n3 -> chebyshev\n4 -> reciprocal\n5 -> random')
|
'0 -> manhattan\n1 -> squared_euclidean\n2 -> euclidean\n3 -> chebyshev\n4 -> reciprocal\n5 -> random')
|
||||||
parser.add_argument('--fr', nargs = 1, type = int, default = [2], choices = range(1, 6), help = 'flood range 1..5, default 2')
|
parser.add_argument('--fr', nargs = 1, type = int, default = [2], choices = range(1, 6), help = 'flood range 1..5, default 2')
|
||||||
parser.add_argument('--xr', nargs = 1, type = int, default = [1], choices = range(0, 6), help = 'even layer x range 0..5, default 1')
|
parser.add_argument('--xr', nargs = 1, type = int, default = [1], choices = range(0, 6), help = 'even layer x range 0..5, default 1')
|
||||||
parser.add_argument('--yr', nargs = 1, type = int, default = [1], choices = range(0, 6), help = 'odd layer y range 0..5, default 1')
|
parser.add_argument('--yr', nargs = 1, type = int, default = [1], choices = range(0, 6), help = 'odd layer y range 0..5, default 1')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
flood_range = args.fr[0]
|
flood_range = args.fr[0]
|
||||||
flood_range_x_even_layer = args.xr[0]
|
flood_range_x_even_layer = args.xr[0]
|
||||||
flood_range_y_odd_layer = args.yr[0]
|
flood_range_y_odd_layer = args.yr[0]
|
||||||
path_range = flood_range + 0
|
path_range = flood_range + 0
|
||||||
path_range_x_even_layer = flood_range_x_even_layer + 0
|
path_range_x_even_layer = flood_range_x_even_layer + 0
|
||||||
path_range_y_odd_layer = flood_range_y_odd_layer + 0
|
path_range_y_odd_layer = flood_range_y_odd_layer + 0
|
||||||
|
|
||||||
routing_flood_vectors = [[(x, y, 0) for x in range(-flood_range_x_even_layer, flood_range_x_even_layer + 1) for y in range(-flood_range, flood_range + 1) \
|
routing_flood_vectors = [[(x, y, 0) for x in range(-flood_range_x_even_layer, flood_range_x_even_layer + 1) for y in range(-flood_range, flood_range + 1) \
|
||||||
if length_2d((x, y)) > 0.1 and length_2d((x, y)) <= flood_range] + [(0, 0, -1), (0, 0, 1)], \
|
if length_2d((x, y)) > 0.1 and length_2d((x, y)) <= flood_range] + [(0, 0, -1), (0, 0, 1)], \
|
||||||
[(x, y, 0) for x in range(-flood_range, flood_range + 1) for y in range(-flood_range_y_odd_layer, flood_range_y_odd_layer + 1) \
|
[(x, y, 0) for x in range(-flood_range, flood_range + 1) for y in range(-flood_range_y_odd_layer, flood_range_y_odd_layer + 1) \
|
||||||
if length_2d((x, y)) > 0.1 and length_2d((x, y)) <= flood_range] + [(0, 0, -1), (0, 0, 1)]]
|
if length_2d((x, y)) > 0.1 and length_2d((x, y)) <= flood_range] + [(0, 0, -1), (0, 0, 1)]]
|
||||||
|
|
||||||
routing_path_vectors = [[(x, y, 0) for x in range(-path_range_x_even_layer, path_range_x_even_layer + 1) for y in range(-path_range, path_range + 1) \
|
routing_path_vectors = [[(x, y, 0) for x in range(-path_range_x_even_layer, path_range_x_even_layer + 1) for y in range(-path_range, path_range + 1) \
|
||||||
if length_2d((x, y)) > 0.1 and length_2d((x, y)) <= path_range] + [(0, 0, -1), (0, 0, 1)], \
|
if length_2d((x, y)) > 0.1 and length_2d((x, y)) <= path_range] + [(0, 0, -1), (0, 0, 1)], \
|
||||||
[(x, y, 0) for x in range(-path_range, path_range + 1) for y in range(-path_range_y_odd_layer, path_range_y_odd_layer + 1) \
|
[(x, y, 0) for x in range(-path_range, path_range + 1) for y in range(-path_range_y_odd_layer, path_range_y_odd_layer + 1) \
|
||||||
if length_2d((x, y)) > 0.1 and length_2d((x, y)) <= path_range] + [(0, 0, -1), (0, 0, 1)]]
|
if length_2d((x, y)) > 0.1 and length_2d((x, y)) <= path_range] + [(0, 0, -1), (0, 0, 1)]]
|
||||||
|
|
||||||
dfunc = [manhattan_distance, squared_euclidean_distance, euclidean_distance, \
|
dfunc = [manhattan_distance, squared_euclidean_distance, euclidean_distance, \
|
||||||
chebyshev_distance, reciprical_distance, random_distance][args.d[0]]
|
chebyshev_distance, reciprical_distance, random_distance][args.d[0]]
|
||||||
|
|
||||||
dimensions = literal_eval(args.infile.readline().strip())
|
dimensions = literal_eval(args.infile.readline().strip())
|
||||||
pcb = router.Pcb(dimensions, routing_flood_vectors, routing_path_vectors, dfunc, args.r[0], args.v[0], args.z[0])
|
pcb = router.Pcb(dimensions, routing_flood_vectors, routing_path_vectors, dfunc, args.r[0], args.v[0], args.z[0])
|
||||||
for line in args.infile:
|
for line in args.infile:
|
||||||
track = literal_eval(line.strip())
|
track = literal_eval(line.strip())
|
||||||
if not track:
|
if not track:
|
||||||
break
|
break
|
||||||
pcb.add_track(track)
|
pcb.add_track(track)
|
||||||
args.infile.close()
|
args.infile.close()
|
||||||
|
|
||||||
pcb.print_pcb()
|
pcb.print_pcb()
|
||||||
best_cost = None
|
best_cost = None
|
||||||
best_pcb = None
|
best_pcb = None
|
||||||
for i in range(args.s[0]):
|
for i in range(args.s[0]):
|
||||||
if not pcb.route(args.t[0]):
|
if not pcb.route(args.t[0]):
|
||||||
pcb.shuffle_netlist()
|
pcb.shuffle_netlist()
|
||||||
continue
|
continue
|
||||||
cost = pcb.cost()
|
cost = pcb.cost()
|
||||||
if best_cost == None or cost < best_cost:
|
if best_cost == None or cost < best_cost:
|
||||||
best_cost = cost
|
best_cost = cost
|
||||||
best_pcb = deepcopy(pcb)
|
best_pcb = deepcopy(pcb)
|
||||||
pcb.shuffle_netlist()
|
pcb.shuffle_netlist()
|
||||||
if best_pcb != None:
|
if best_pcb != None:
|
||||||
best_pcb.print_netlist()
|
best_pcb.print_netlist()
|
||||||
best_pcb.print_stats()
|
best_pcb.print_stats()
|
||||||
else:
|
else:
|
||||||
print([])
|
print([])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
510
router.py
510
router.py
|
@ -10,289 +10,289 @@ from mymath import *
|
||||||
from layer import *
|
from layer import *
|
||||||
|
|
||||||
def shift(l, n):
|
def shift(l, n):
|
||||||
n = n % len(l)
|
n = n % len(l)
|
||||||
head = l[:n]
|
head = l[:n]
|
||||||
del l[:n]
|
del l[:n]
|
||||||
l.extend(head)
|
l.extend(head)
|
||||||
return l
|
return l
|
||||||
|
|
||||||
class Pcb():
|
class Pcb():
|
||||||
def __init__(self, dimensions, routing_flood_vectors, routing_path_vectors, dfunc, resolution, verbosity, minz):
|
def __init__(self, dimensions, routing_flood_vectors, routing_path_vectors, dfunc, resolution, verbosity, minz):
|
||||||
self.dfunc = dfunc
|
self.dfunc = dfunc
|
||||||
self.verbosity = verbosity
|
self.verbosity = verbosity
|
||||||
self.routing_flood_vectors = routing_flood_vectors
|
self.routing_flood_vectors = routing_flood_vectors
|
||||||
self.routing_path_vectors = routing_path_vectors
|
self.routing_path_vectors = routing_path_vectors
|
||||||
self.layers = Layers(dimensions, 1.0 / resolution)
|
self.layers = Layers(dimensions, 1.0 / resolution)
|
||||||
self.width, self.height, self.depth = dimensions
|
self.width, self.height, self.depth = dimensions
|
||||||
self.resolution = resolution
|
self.resolution = resolution
|
||||||
self.minz = minz
|
self.minz = minz
|
||||||
self.width *= resolution
|
self.width *= resolution
|
||||||
self.height *= resolution
|
self.height *= resolution
|
||||||
self.stride = self.width * self.height
|
self.stride = self.width * self.height
|
||||||
self.nodes = array('i', [0 for x in range(self.stride * self.depth)])
|
self.nodes = array('i', [0 for x in range(self.stride * self.depth)])
|
||||||
self.netlist = []
|
self.netlist = []
|
||||||
self.deform = {}
|
self.deform = {}
|
||||||
|
|
||||||
def grid_to_space_point(self, node):
|
def grid_to_space_point(self, node):
|
||||||
if node in self.deform:
|
if node in self.deform:
|
||||||
return self.deform[node]
|
return self.deform[node]
|
||||||
return (float(node[0]), float(node[1]), float(node[2]))
|
return (float(node[0]), float(node[1]), float(node[2]))
|
||||||
|
|
||||||
def set_node(self, node, value):
|
def set_node(self, node, value):
|
||||||
self.nodes[(self.stride * node[2]) + (node[1] * self.width) + node[0]] = value
|
self.nodes[(self.stride * node[2]) + (node[1] * self.width) + node[0]] = value
|
||||||
|
|
||||||
def get_node(self, node):
|
def get_node(self, node):
|
||||||
return self.nodes[(self.stride * node[2]) + (node[1] * self.width) + node[0]]
|
return self.nodes[(self.stride * node[2]) + (node[1] * self.width) + node[0]]
|
||||||
|
|
||||||
def all_marked(self, vectors, node):
|
def all_marked(self, vectors, node):
|
||||||
x, y, z = node
|
x, y, z = node
|
||||||
for dx, dy, dz in vectors[z % 2]:
|
for dx, dy, dz in vectors[z % 2]:
|
||||||
nx = x + dx; ny = y + dy; nz = z + dz
|
nx = x + dx; ny = y + dy; nz = z + dz
|
||||||
if (0 <= nx < self.width) and (0 <= ny < self.height) and (0 <= nz < self.depth):
|
if (0 <= nx < self.width) and (0 <= ny < self.height) and (0 <= nz < self.depth):
|
||||||
mark = self.get_node((nx, ny, nz))
|
mark = self.get_node((nx, ny, nz))
|
||||||
if mark != 0:
|
if mark != 0:
|
||||||
yield (mark, (nx, ny, nz))
|
yield (mark, (nx, ny, nz))
|
||||||
|
|
||||||
def all_not_marked(self, vectors, node):
|
def all_not_marked(self, vectors, node):
|
||||||
x, y, z = node
|
x, y, z = node
|
||||||
for dx, dy, dz in vectors[z % 2]:
|
for dx, dy, dz in vectors[z % 2]:
|
||||||
nx = x + dx; ny = y + dy; nz = z + dz
|
nx = x + dx; ny = y + dy; nz = z + dz
|
||||||
if (0 <= nx < self.width) and (0 <= ny < self.height) and (0 <= nz < self.depth):
|
if (0 <= nx < self.width) and (0 <= ny < self.height) and (0 <= nz < self.depth):
|
||||||
if self.get_node((nx, ny, nz)) == 0:
|
if self.get_node((nx, ny, nz)) == 0:
|
||||||
yield (nx, ny, nz)
|
yield (nx, ny, nz)
|
||||||
|
|
||||||
def all_nearer_sorted(self, vectors, node, goal, func):
|
def all_nearer_sorted(self, vectors, node, goal, func):
|
||||||
distance = self.get_node(node)
|
distance = self.get_node(node)
|
||||||
sgoal = self.grid_to_space_point(goal)
|
sgoal = self.grid_to_space_point(goal)
|
||||||
nodes = [(func(self.grid_to_space_point(marked[1]), sgoal), marked[1]) \
|
nodes = [(func(self.grid_to_space_point(marked[1]), sgoal), marked[1]) \
|
||||||
for marked in self.all_marked(vectors, node) \
|
for marked in self.all_marked(vectors, node) \
|
||||||
if (distance - marked[0]) > 0]
|
if (distance - marked[0]) > 0]
|
||||||
nodes.sort()
|
nodes.sort()
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
yield node[1]
|
yield node[1]
|
||||||
|
|
||||||
def all_not_shorting(self, gather, params, node, radius, via, gap):
|
def all_not_shorting(self, gather, params, node, radius, via, gap):
|
||||||
np = self.grid_to_space_point(node)
|
np = self.grid_to_space_point(node)
|
||||||
for new_node in gather(*params):
|
for new_node in gather(*params):
|
||||||
nnp = self.grid_to_space_point(new_node)
|
nnp = self.grid_to_space_point(new_node)
|
||||||
if node[2] != new_node[2]:
|
if node[2] != new_node[2]:
|
||||||
if not self.layers.hit_line(np, nnp, via, gap):
|
if not self.layers.hit_line(np, nnp, via, gap):
|
||||||
yield new_node
|
yield new_node
|
||||||
else:
|
else:
|
||||||
if not self.layers.hit_line(np, nnp, radius, gap):
|
if not self.layers.hit_line(np, nnp, radius, gap):
|
||||||
yield new_node
|
yield new_node
|
||||||
|
|
||||||
def mark_distances(self, vectors, radius, via, gap, starts, ends = []):
|
def mark_distances(self, vectors, radius, via, gap, starts, ends = []):
|
||||||
distance = 1
|
distance = 1
|
||||||
nodes = list(starts)
|
nodes = list(starts)
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
self.set_node(node, distance)
|
self.set_node(node, distance)
|
||||||
while nodes:
|
while nodes:
|
||||||
distance += 1
|
distance += 1
|
||||||
new_nodes = []
|
new_nodes = []
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
for new_node in self.all_not_shorting(self.all_not_marked, (vectors, node), node, radius, via, gap):
|
for new_node in self.all_not_shorting(self.all_not_marked, (vectors, node), node, radius, via, gap):
|
||||||
self.set_node(new_node, distance)
|
self.set_node(new_node, distance)
|
||||||
new_nodes.append(new_node)
|
new_nodes.append(new_node)
|
||||||
nodes = new_nodes
|
nodes = new_nodes
|
||||||
if 0 not in [self.get_node(node) for node in ends]:
|
if 0 not in [self.get_node(node) for node in ends]:
|
||||||
break
|
break
|
||||||
|
|
||||||
def unmark_distances(self):
|
def unmark_distances(self):
|
||||||
self.nodes = array('i', [0 for x in range(self.stride * self.depth)])
|
self.nodes = array('i', [0 for x in range(self.stride * self.depth)])
|
||||||
|
|
||||||
def add_track(self, track):
|
def add_track(self, track):
|
||||||
radius, via, gap, net = track
|
radius, via, gap, net = track
|
||||||
self.netlist.append(Net(net, radius, via, gap, self))
|
self.netlist.append(Net(net, radius, via, gap, self))
|
||||||
|
|
||||||
def route(self, timeout):
|
def route(self, timeout):
|
||||||
self.remove_netlist()
|
self.remove_netlist()
|
||||||
self.unmark_distances()
|
self.unmark_distances()
|
||||||
now = time.time()
|
now = time.time()
|
||||||
self.netlist.sort(key = lambda i: i.radius, reverse = True)
|
self.netlist.sort(key = lambda i: i.radius, reverse = True)
|
||||||
index = 0
|
index = 0
|
||||||
while index < len(self.netlist):
|
while index < len(self.netlist):
|
||||||
if self.netlist[index].route(self.minz):
|
if self.netlist[index].route(self.minz):
|
||||||
index += 1
|
index += 1
|
||||||
else:
|
else:
|
||||||
if index == 0:
|
if index == 0:
|
||||||
self.shuffle_netlist()
|
self.shuffle_netlist()
|
||||||
else:
|
else:
|
||||||
self.netlist.insert(0, self.netlist.pop(index))
|
self.netlist.insert(0, self.netlist.pop(index))
|
||||||
while index != 0:
|
while index != 0:
|
||||||
self.netlist[index].remove()
|
self.netlist[index].remove()
|
||||||
self.netlist[index].shuffle_topology()
|
self.netlist[index].shuffle_topology()
|
||||||
index -= 1
|
index -= 1
|
||||||
if time.time() - now > timeout:
|
if time.time() - now > timeout:
|
||||||
return False
|
return False
|
||||||
if self.verbosity >= 1:
|
if self.verbosity >= 1:
|
||||||
self.print_netlist()
|
self.print_netlist()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def cost(self):
|
def cost(self):
|
||||||
return sum(len(path) for net in self.netlist for path in net.paths)
|
return sum(len(path) for net in self.netlist for path in net.paths)
|
||||||
|
|
||||||
def shuffle_netlist(self):
|
def shuffle_netlist(self):
|
||||||
for net in self.netlist:
|
for net in self.netlist:
|
||||||
net.remove()
|
net.remove()
|
||||||
net.shuffle_topology()
|
net.shuffle_topology()
|
||||||
shuffle(self.netlist)
|
shuffle(self.netlist)
|
||||||
|
|
||||||
def remove_netlist(self):
|
def remove_netlist(self):
|
||||||
for net in self.netlist:
|
for net in self.netlist:
|
||||||
net.remove()
|
net.remove()
|
||||||
|
|
||||||
def print_netlist(self):
|
def print_netlist(self):
|
||||||
for net in self.netlist:
|
for net in self.netlist:
|
||||||
net.print_net()
|
net.print_net()
|
||||||
print([])
|
print([])
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
def print_pcb(self):
|
def print_pcb(self):
|
||||||
scale = 1.0 / self.resolution
|
scale = 1.0 / self.resolution
|
||||||
print([self.width * scale, self.height * scale, self.depth])
|
print([self.width * scale, self.height * scale, self.depth])
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
def print_stats(self):
|
def print_stats(self):
|
||||||
num_vias = 0
|
num_vias = 0
|
||||||
num_terminals = 0
|
num_terminals = 0
|
||||||
num_nets = len(self.netlist)
|
num_nets = len(self.netlist)
|
||||||
for net in self.netlist:
|
for net in self.netlist:
|
||||||
num_terminals += len(net.terminals)
|
num_terminals += len(net.terminals)
|
||||||
for path in net.paths:
|
for path in net.paths:
|
||||||
for a, b in zip(path, islice(path, 1, None)):
|
for a, b in zip(path, islice(path, 1, None)):
|
||||||
if a[2] != b[2]:
|
if a[2] != b[2]:
|
||||||
num_vias += 1
|
num_vias += 1
|
||||||
print >> sys.stderr, "Number of Terminals:", num_terminals
|
print >> sys.stderr, "Number of Terminals:", num_terminals
|
||||||
print >> sys.stderr, "Number of Nets:", num_nets
|
print >> sys.stderr, "Number of Nets:", num_nets
|
||||||
print >> sys.stderr, "Number of Vias:", num_vias
|
print >> sys.stderr, "Number of Vias:", num_vias
|
||||||
|
|
||||||
class Net():
|
class Net():
|
||||||
def __init__(self, terminals, radius, via, gap, pcb):
|
def __init__(self, terminals, radius, via, gap, pcb):
|
||||||
self.pcb = pcb
|
self.pcb = pcb
|
||||||
self.terminals = [(r * pcb.resolution, g * pcb.resolution, \
|
self.terminals = [(r * pcb.resolution, g * pcb.resolution, \
|
||||||
(x * pcb.resolution, y * pcb.resolution, z), \
|
(x * pcb.resolution, y * pcb.resolution, z), \
|
||||||
[(cx * pcb.resolution, cy * pcb.resolution) for cx, cy in s]) \
|
[(cx * pcb.resolution, cy * pcb.resolution) for cx, cy in s]) \
|
||||||
for r, g, (x, y, z), s in terminals]
|
for r, g, (x, y, z), s in terminals]
|
||||||
self.radius = radius * pcb.resolution
|
self.radius = radius * pcb.resolution
|
||||||
self.via = via * pcb.resolution
|
self.via = via * pcb.resolution
|
||||||
self.gap = gap * pcb.resolution
|
self.gap = gap * pcb.resolution
|
||||||
self.paths = []
|
self.paths = []
|
||||||
self.remove()
|
self.remove()
|
||||||
for term in self.terminals:
|
for term in self.terminals:
|
||||||
for z in range(pcb.depth):
|
for z in range(pcb.depth):
|
||||||
pcb.deform[(int(term[2][0] + 0.5), int(term[2][1] + 0.5), z)] = (term[2][0], term[2][1], float(z))
|
pcb.deform[(int(term[2][0] + 0.5), int(term[2][1] + 0.5), z)] = (term[2][0], term[2][1], float(z))
|
||||||
|
|
||||||
def optimise_paths(self, paths):
|
def optimise_paths(self, paths):
|
||||||
opt_paths = []
|
opt_paths = []
|
||||||
for path in paths:
|
for path in paths:
|
||||||
opt_path = []
|
opt_path = []
|
||||||
d = (0, 0, 0)
|
d = (0, 0, 0)
|
||||||
for a, b in zip(path, islice(path, 1, None)):
|
for a, b in zip(path, islice(path, 1, None)):
|
||||||
p0 = self.pcb.grid_to_space_point(a)
|
p0 = self.pcb.grid_to_space_point(a)
|
||||||
p1 = self.pcb.grid_to_space_point(b)
|
p1 = self.pcb.grid_to_space_point(b)
|
||||||
d1 = norm_3d(sub_3d(p1, p0))
|
d1 = norm_3d(sub_3d(p1, p0))
|
||||||
if d1 != d:
|
if d1 != d:
|
||||||
opt_path.append(a)
|
opt_path.append(a)
|
||||||
d = d1
|
d = d1
|
||||||
opt_path.append(path[-1])
|
opt_path.append(path[-1])
|
||||||
opt_paths.append(opt_path)
|
opt_paths.append(opt_path)
|
||||||
return opt_paths
|
return opt_paths
|
||||||
|
|
||||||
def shuffle_topology(self):
|
def shuffle_topology(self):
|
||||||
shuffle(self.terminals)
|
shuffle(self.terminals)
|
||||||
|
|
||||||
def add_paths_collision_lines(self):
|
def add_paths_collision_lines(self):
|
||||||
for path in self.paths:
|
for path in self.paths:
|
||||||
for a, b in zip(path, islice(path, 1, None)):
|
for a, b in zip(path, islice(path, 1, None)):
|
||||||
p0 = self.pcb.grid_to_space_point(a)
|
p0 = self.pcb.grid_to_space_point(a)
|
||||||
p1 = self.pcb.grid_to_space_point(b)
|
p1 = self.pcb.grid_to_space_point(b)
|
||||||
if a[2] != b[2]:
|
if a[2] != b[2]:
|
||||||
self.pcb.layers.add_line(p0, p1, self.via, self.gap)
|
self.pcb.layers.add_line(p0, p1, self.via, self.gap)
|
||||||
else:
|
else:
|
||||||
self.pcb.layers.add_line(p0, p1, self.radius, self.gap)
|
self.pcb.layers.add_line(p0, p1, self.radius, self.gap)
|
||||||
|
|
||||||
def sub_paths_collision_lines(self):
|
def sub_paths_collision_lines(self):
|
||||||
for path in self.paths:
|
for path in self.paths:
|
||||||
for a, b in zip(path, islice(path, 1, None)):
|
for a, b in zip(path, islice(path, 1, None)):
|
||||||
p0 = self.pcb.grid_to_space_point(a)
|
p0 = self.pcb.grid_to_space_point(a)
|
||||||
p1 = self.pcb.grid_to_space_point(b)
|
p1 = self.pcb.grid_to_space_point(b)
|
||||||
if a[2] != b[2]:
|
if a[2] != b[2]:
|
||||||
self.pcb.layers.sub_line(p0, p1, self.via, self.gap)
|
self.pcb.layers.sub_line(p0, p1, self.via, self.gap)
|
||||||
else:
|
else:
|
||||||
self.pcb.layers.sub_line(p0, p1, self.radius, self.gap)
|
self.pcb.layers.sub_line(p0, p1, self.radius, self.gap)
|
||||||
|
|
||||||
def add_terminal_collision_lines(self):
|
def add_terminal_collision_lines(self):
|
||||||
for node in self.terminals:
|
for node in self.terminals:
|
||||||
r, g, (x, y, _), s = node
|
r, g, (x, y, _), s = node
|
||||||
if not s:
|
if not s:
|
||||||
self.pcb.layers.add_line((x, y, 0), (x, y, self.pcb.depth - 1), r, g)
|
self.pcb.layers.add_line((x, y, 0), (x, y, self.pcb.depth - 1), r, g)
|
||||||
else:
|
else:
|
||||||
for z in range(self.pcb.depth):
|
for z in range(self.pcb.depth):
|
||||||
for a, b in zip(s, islice(s, 1, None)):
|
for a, b in zip(s, islice(s, 1, None)):
|
||||||
self.pcb.layers.add_line((x + a[0], y + a[1], z), (x + b[0], y + b[1], z), r, g)
|
self.pcb.layers.add_line((x + a[0], y + a[1], z), (x + b[0], y + b[1], z), r, g)
|
||||||
|
|
||||||
def sub_terminal_collision_lines(self):
|
def sub_terminal_collision_lines(self):
|
||||||
for node in self.terminals:
|
for node in self.terminals:
|
||||||
r, g, (x, y, _), s = node
|
r, g, (x, y, _), s = node
|
||||||
if not s:
|
if not s:
|
||||||
self.pcb.layers.sub_line((x, y, 0), (x, y, self.pcb.depth - 1), r, g)
|
self.pcb.layers.sub_line((x, y, 0), (x, y, self.pcb.depth - 1), r, g)
|
||||||
else:
|
else:
|
||||||
for z in range(self.pcb.depth):
|
for z in range(self.pcb.depth):
|
||||||
for a, b in zip(s, islice(s, 1, None)):
|
for a, b in zip(s, islice(s, 1, None)):
|
||||||
self.pcb.layers.sub_line((x + a[0], y + a[1], z), (x + b[0], y + b[1], z), r, g)
|
self.pcb.layers.sub_line((x + a[0], y + a[1], z), (x + b[0], y + b[1], z), r, g)
|
||||||
|
|
||||||
def remove(self):
|
def remove(self):
|
||||||
self.sub_paths_collision_lines()
|
self.sub_paths_collision_lines()
|
||||||
self.sub_terminal_collision_lines()
|
self.sub_terminal_collision_lines()
|
||||||
self.paths = []
|
self.paths = []
|
||||||
self.add_terminal_collision_lines()
|
self.add_terminal_collision_lines()
|
||||||
|
|
||||||
def route(self, minz):
|
def route(self, minz):
|
||||||
try:
|
try:
|
||||||
self.paths = []
|
self.paths = []
|
||||||
self.sub_terminal_collision_lines()
|
self.sub_terminal_collision_lines()
|
||||||
visited = set()
|
visited = set()
|
||||||
for index in range(1, len(self.terminals)):
|
for index in range(1, len(self.terminals)):
|
||||||
visited |= set([(int(self.terminals[index - 1][2][0]+0.5), int(self.terminals[index - 1][2][1]+0.5), z) for z in range(self.pcb.depth)])
|
visited |= set([(int(self.terminals[index - 1][2][0]+0.5), int(self.terminals[index - 1][2][1]+0.5), z) for z in range(self.pcb.depth)])
|
||||||
ends = [(int(self.terminals[index][2][0]+0.5), int(self.terminals[index][2][1]+0.5), z) for z in range(self.pcb.depth)]
|
ends = [(int(self.terminals[index][2][0]+0.5), int(self.terminals[index][2][1]+0.5), z) for z in range(self.pcb.depth)]
|
||||||
self.pcb.mark_distances(self.pcb.routing_flood_vectors, self.radius, self.via, self.gap, visited, ends)
|
self.pcb.mark_distances(self.pcb.routing_flood_vectors, self.radius, self.via, self.gap, visited, ends)
|
||||||
ends = [(self.pcb.get_node(node), node) for node in ends]
|
ends = [(self.pcb.get_node(node), node) for node in ends]
|
||||||
ends.sort()
|
ends.sort()
|
||||||
_, end = ends[0]
|
_, end = ends[0]
|
||||||
path = [end]
|
path = [end]
|
||||||
while path[-1] not in visited:
|
while path[-1] not in visited:
|
||||||
nearer_nodes = self.pcb.all_not_shorting(self.pcb.all_nearer_sorted, \
|
nearer_nodes = self.pcb.all_not_shorting(self.pcb.all_nearer_sorted, \
|
||||||
(self.pcb.routing_path_vectors, path[-1], end, self.pcb.dfunc), path[-1], self.radius, self.via, self.gap)
|
(self.pcb.routing_path_vectors, path[-1], end, self.pcb.dfunc), path[-1], self.radius, self.via, self.gap)
|
||||||
next_node = next(nearer_nodes)
|
next_node = next(nearer_nodes)
|
||||||
if minz:
|
if minz:
|
||||||
for node in nearer_nodes:
|
for node in nearer_nodes:
|
||||||
if node[2] == path[-1][2]:
|
if node[2] == path[-1][2]:
|
||||||
next_node = node
|
next_node = node
|
||||||
break
|
break
|
||||||
path.append(next_node)
|
path.append(next_node)
|
||||||
visited |= set(path)
|
visited |= set(path)
|
||||||
self.paths.append(path)
|
self.paths.append(path)
|
||||||
self.pcb.unmark_distances()
|
self.pcb.unmark_distances()
|
||||||
self.paths = self.optimise_paths(self.paths)
|
self.paths = self.optimise_paths(self.paths)
|
||||||
self.add_paths_collision_lines()
|
self.add_paths_collision_lines()
|
||||||
self.add_terminal_collision_lines()
|
self.add_terminal_collision_lines()
|
||||||
return True
|
return True
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
self.pcb.unmark_distances()
|
self.pcb.unmark_distances()
|
||||||
self.remove()
|
self.remove()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def print_net(self):
|
def print_net(self):
|
||||||
scale = 1.0 / self.pcb.resolution
|
scale = 1.0 / self.pcb.resolution
|
||||||
spaths = []
|
spaths = []
|
||||||
for path in self.paths:
|
for path in self.paths:
|
||||||
spath = []
|
spath = []
|
||||||
for node in path:
|
for node in path:
|
||||||
spath += [self.pcb.grid_to_space_point(node)]
|
spath += [self.pcb.grid_to_space_point(node)]
|
||||||
spaths += [spath]
|
spaths += [spath]
|
||||||
print([self.radius * scale, self.via * scale, self.gap * scale, \
|
print([self.radius * scale, self.via * scale, self.gap * scale, \
|
||||||
[(r * scale, g * scale, (x * scale, y * scale, z), \
|
[(r * scale, g * scale, (x * scale, y * scale, z), \
|
||||||
[(cx * scale, cy * scale) for cx, cy in s]) for r, g, (x, y, z), s in self.terminals], \
|
[(cx * scale, cy * scale) for cx, cy in s]) for r, g, (x, y, z), s in self.terminals], \
|
||||||
[[(x * scale, y * scale, z) for x, y, z in spath] for spath in spaths]])
|
[[(x * scale, y * scale, z) for x, y, z in spath] for spath in spaths]])
|
||||||
|
|
||||||
|
|
372
view.py
372
view.py
|
@ -16,210 +16,210 @@ photo = None
|
||||||
image = None
|
image = None
|
||||||
|
|
||||||
def split_paths(paths):
|
def split_paths(paths):
|
||||||
new_paths = []
|
new_paths = []
|
||||||
for path in paths:
|
for path in paths:
|
||||||
new_path = []
|
new_path = []
|
||||||
for a, b in zip(path, islice(path, 1, None)):
|
for a, b in zip(path, islice(path, 1, None)):
|
||||||
_, _, za = a
|
_, _, za = a
|
||||||
_, _, zb = b
|
_, _, zb = b
|
||||||
if za != zb:
|
if za != zb:
|
||||||
if new_path:
|
if new_path:
|
||||||
new_path.append(a)
|
new_path.append(a)
|
||||||
new_paths.append(new_path)
|
new_paths.append(new_path)
|
||||||
new_paths.append([a, b])
|
new_paths.append([a, b])
|
||||||
new_path = []
|
new_path = []
|
||||||
else:
|
else:
|
||||||
new_path.append(a)
|
new_path.append(a)
|
||||||
if new_path:
|
if new_path:
|
||||||
new_path.append(path[-1])
|
new_path.append(path[-1])
|
||||||
new_paths.append(new_path)
|
new_paths.append(new_path)
|
||||||
return new_paths
|
return new_paths
|
||||||
|
|
||||||
def scale_and_split_tracks(tracks, scale):
|
def scale_and_split_tracks(tracks, scale):
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
track[0] *= scale
|
track[0] *= scale
|
||||||
track[1] *= scale
|
track[1] *= scale
|
||||||
track[2] *= scale
|
track[2] *= scale
|
||||||
track[4] = split_paths(track[4])
|
track[4] = split_paths(track[4])
|
||||||
for i in range(len(track[3])):
|
for i in range(len(track[3])):
|
||||||
r, g, (x, y, z), s = track[3][i]
|
r, g, (x, y, z), s = track[3][i]
|
||||||
track[3][i] = r * scale, g * scale, ((x + MARGIN) * scale, (y + MARGIN) * scale, z), [(cx * scale, cy * scale) for cx, cy in s]
|
track[3][i] = r * scale, g * scale, ((x + MARGIN) * scale, (y + MARGIN) * scale, z), [(cx * scale, cy * scale) for cx, cy in s]
|
||||||
for path in track[4]:
|
for path in track[4]:
|
||||||
for i in range(len(path)):
|
for i in range(len(path)):
|
||||||
x, y, z = path[i]
|
x, y, z = path[i]
|
||||||
path[i] = (x + MARGIN) * scale, (y + MARGIN) * scale, z
|
path[i] = (x + MARGIN) * scale, (y + MARGIN) * scale, z
|
||||||
|
|
||||||
def get_tracks():
|
def get_tracks():
|
||||||
tracks = []
|
tracks = []
|
||||||
while True:
|
while True:
|
||||||
line = args.infile.readline()
|
line = args.infile.readline()
|
||||||
if not line:
|
if not line:
|
||||||
tracks = []
|
tracks = []
|
||||||
break
|
break
|
||||||
track = literal_eval(line.strip())
|
track = literal_eval(line.strip())
|
||||||
if not track:
|
if not track:
|
||||||
break
|
break
|
||||||
tracks.append(track)
|
tracks.append(track)
|
||||||
return tracks
|
return tracks
|
||||||
|
|
||||||
def doframe(dimensions, root, canvas, poll):
|
def doframe(dimensions, root, canvas, poll):
|
||||||
global photo, image
|
global photo, image
|
||||||
|
|
||||||
tracks = get_tracks()
|
tracks = get_tracks()
|
||||||
if poll:
|
if poll:
|
||||||
while poll.poll(1):
|
while poll.poll(1):
|
||||||
new_tracks = get_tracks()
|
new_tracks = get_tracks()
|
||||||
if not new_tracks:
|
if not new_tracks:
|
||||||
break
|
break
|
||||||
tracks = new_tracks
|
tracks = new_tracks
|
||||||
if not tracks:
|
if not tracks:
|
||||||
return
|
return
|
||||||
|
|
||||||
pcb_width, pcb_height, pcb_depth = dimensions
|
pcb_width, pcb_height, pcb_depth = dimensions
|
||||||
scale = args.s[0]
|
scale = args.s[0]
|
||||||
scale_and_split_tracks(tracks, scale)
|
scale_and_split_tracks(tracks, scale)
|
||||||
pcb_width += MARGIN * 2; pcb_height += MARGIN * 2
|
pcb_width += MARGIN * 2; pcb_height += MARGIN * 2
|
||||||
img_width = int(pcb_width * scale)
|
img_width = int(pcb_width * scale)
|
||||||
if args.o[0] == 0:
|
if args.o[0] == 0:
|
||||||
img_height = int(pcb_height * scale)
|
img_height = int(pcb_height * scale)
|
||||||
else:
|
else:
|
||||||
img_height = int(pcb_height * pcb_depth * scale)
|
img_height = int(pcb_height * pcb_depth * scale)
|
||||||
|
|
||||||
canvas.delete("all")
|
canvas.delete("all")
|
||||||
image = Image.new("RGB", (img_width, img_height), "black")
|
image = Image.new("RGB", (img_width, img_height), "black")
|
||||||
ctx = aggdraw.Draw(image)
|
ctx = aggdraw.Draw(image)
|
||||||
black_brush = aggdraw.Brush('black', opacity = 255)
|
black_brush = aggdraw.Brush('black', opacity = 255)
|
||||||
white_brush = aggdraw.Brush('white', opacity = 255)
|
white_brush = aggdraw.Brush('white', opacity = 255)
|
||||||
red_brush = aggdraw.Brush('red', opacity = 255)
|
red_brush = aggdraw.Brush('red', opacity = 255)
|
||||||
|
|
||||||
if args.o[0] == 0:
|
if args.o[0] == 0:
|
||||||
colors = ['red', 'green', 'blue', 'yellow', 'fuchsia', 'aqua']
|
colors = ['red', 'green', 'blue', 'yellow', 'fuchsia', 'aqua']
|
||||||
for depth in range(pcb_depth - 1, -1, -1):
|
for depth in range(pcb_depth - 1, -1, -1):
|
||||||
brush = aggdraw.Brush(colors[depth % len(colors)], opacity = 128)
|
brush = aggdraw.Brush(colors[depth % len(colors)], opacity = 128)
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] == path[-1][2] == depth:
|
if path[0][2] == path[-1][2] == depth:
|
||||||
points = list(chain.from_iterable(thicken_path_2d([(x, y) for x, y, _ in path], radius, 3, 2)))
|
points = list(chain.from_iterable(thicken_path_2d([(x, y) for x, y, _ in path], radius, 3, 2)))
|
||||||
ctx.polygon(points, brush)
|
ctx.polygon(points, brush)
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] != path[-1][2]:
|
if path[0][2] != path[-1][2]:
|
||||||
x, y, _ = path[0]
|
x, y, _ = path[0]
|
||||||
ctx.ellipse((x - via, y - via, x + via, y + via), white_brush)
|
ctx.ellipse((x - via, y - via, x + via, y + via), white_brush)
|
||||||
for r, g, (x, y, _), s in terminals:
|
for r, g, (x, y, _), s in terminals:
|
||||||
if not s:
|
if not s:
|
||||||
ctx.ellipse((x - r, y - r, x + r, y + r), white_brush)
|
ctx.ellipse((x - r, y - r, x + r, y + r), white_brush)
|
||||||
else:
|
else:
|
||||||
if r != 0:
|
if r != 0:
|
||||||
points = list(chain.from_iterable(thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r, 3, 2)))
|
points = list(chain.from_iterable(thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r, 3, 2)))
|
||||||
ctx.polygon(points, white_brush)
|
ctx.polygon(points, white_brush)
|
||||||
else:
|
else:
|
||||||
points = list(chain.from_iterable([(cx + x, cy + y) for cx, cy in s]))
|
points = list(chain.from_iterable([(cx + x, cy + y) for cx, cy in s]))
|
||||||
ctx.polygon(points, white_brush)
|
ctx.polygon(points, white_brush)
|
||||||
else:
|
else:
|
||||||
for depth in range(pcb_depth):
|
for depth in range(pcb_depth):
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] == path[-1][2] == depth:
|
if path[0][2] == path[-1][2] == depth:
|
||||||
points = list(chain.from_iterable(thicken_path_2d([(x, y + depth * pcb_height * scale) for x, y, _ in path], radius + gap, 3, 2)))
|
points = list(chain.from_iterable(thicken_path_2d([(x, y + depth * pcb_height * scale) for x, y, _ in path], radius + gap, 3, 2)))
|
||||||
ctx.polygon(points, white_brush)
|
ctx.polygon(points, white_brush)
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] != path[-1][2]:
|
if path[0][2] != path[-1][2]:
|
||||||
x, y, _ = path[0]
|
x, y, _ = path[0]
|
||||||
y += depth * pcb_height * scale
|
y += depth * pcb_height * scale
|
||||||
ctx.ellipse((x - via - gap, y - via - gap, x + via + gap, y + via + gap), white_brush)
|
ctx.ellipse((x - via - gap, y - via - gap, x + via + gap, y + via + gap), white_brush)
|
||||||
for r, g, (x, y, _), s in terminals:
|
for r, g, (x, y, _), s in terminals:
|
||||||
y += depth * pcb_height * scale
|
y += depth * pcb_height * scale
|
||||||
if not s:
|
if not s:
|
||||||
ctx.ellipse((x - r - g, y - r - g, x + r + g, y + r + g), white_brush)
|
ctx.ellipse((x - r - g, y - r - g, x + r + g, y + r + g), white_brush)
|
||||||
else:
|
else:
|
||||||
points = list(chain.from_iterable(thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r + g, 3, 2)))
|
points = list(chain.from_iterable(thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r + g, 3, 2)))
|
||||||
ctx.polygon(points, white_brush)
|
ctx.polygon(points, white_brush)
|
||||||
if r == 0:
|
if r == 0:
|
||||||
points = list(chain.from_iterable([(cx + x, cy + y) for cx, cy in s]))
|
points = list(chain.from_iterable([(cx + x, cy + y) for cx, cy in s]))
|
||||||
ctx.polygon(points, white_brush)
|
ctx.polygon(points, white_brush)
|
||||||
for depth in range(pcb_depth):
|
for depth in range(pcb_depth):
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] == path[-1][2] == depth:
|
if path[0][2] == path[-1][2] == depth:
|
||||||
points = list(chain.from_iterable(thicken_path_2d([(x, y + depth * pcb_height * scale) for x, y, _ in path], radius, 3, 2)))
|
points = list(chain.from_iterable(thicken_path_2d([(x, y + depth * pcb_height * scale) for x, y, _ in path], radius, 3, 2)))
|
||||||
ctx.polygon(points, black_brush)
|
ctx.polygon(points, black_brush)
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] != path[-1][2]:
|
if path[0][2] != path[-1][2]:
|
||||||
x, y, _ = path[0]
|
x, y, _ = path[0]
|
||||||
y += depth * pcb_height * scale
|
y += depth * pcb_height * scale
|
||||||
ctx.ellipse((x - via, y - via, x + via, y + via), black_brush)
|
ctx.ellipse((x - via, y - via, x + via, y + via), black_brush)
|
||||||
for r, g, (x, y, _), s in terminals:
|
for r, g, (x, y, _), s in terminals:
|
||||||
y += depth * pcb_height * scale
|
y += depth * pcb_height * scale
|
||||||
if not s:
|
if not s:
|
||||||
ctx.ellipse((x - r, y - r, x + r, y + r), black_brush)
|
ctx.ellipse((x - r, y - r, x + r, y + r), black_brush)
|
||||||
else:
|
else:
|
||||||
if r != 0:
|
if r != 0:
|
||||||
points = list(chain.from_iterable(thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r, 3, 2)))
|
points = list(chain.from_iterable(thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r, 3, 2)))
|
||||||
ctx.polygon(points, black_brush)
|
ctx.polygon(points, black_brush)
|
||||||
else:
|
else:
|
||||||
points = list(chain.from_iterable([(cx + x, cy + y) for cx, cy in s]))
|
points = list(chain.from_iterable([(cx + x, cy + y) for cx, cy in s]))
|
||||||
ctx.polygon(points, black_brush)
|
ctx.polygon(points, black_brush)
|
||||||
ctx.flush()
|
ctx.flush()
|
||||||
photo = ImageTk.PhotoImage(image)
|
photo = ImageTk.PhotoImage(image)
|
||||||
canvas.create_image(0, 0, image = photo, anchor = tkinter.NW)
|
canvas.create_image(0, 0, image = photo, anchor = tkinter.NW)
|
||||||
root.update()
|
root.update()
|
||||||
root.after(0, doframe, dimensions, root, canvas, poll)
|
root.after(0, doframe, dimensions, root, canvas, poll)
|
||||||
|
|
||||||
def about_menu_handler():
|
def about_menu_handler():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global args, image
|
global args, image
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description = 'Pcb layout viewer.')
|
parser = argparse.ArgumentParser(description = 'Pcb layout viewer.')
|
||||||
parser.add_argument('infile', nargs = '?', type = argparse.FileType('r'), default = sys.stdin, help = 'filename, default stdin')
|
parser.add_argument('infile', nargs = '?', type = argparse.FileType('r'), default = sys.stdin, help = 'filename, default stdin')
|
||||||
parser.add_argument('--s', nargs = 1, type = int, default = [9], help = 'scale factor, default 9')
|
parser.add_argument('--s', nargs = 1, type = int, default = [9], help = 'scale factor, default 9')
|
||||||
parser.add_argument('--f', nargs = 1, type = float, default = [100.0], help = 'framerate, default 100.0')
|
parser.add_argument('--f', nargs = 1, type = float, default = [100.0], help = 'framerate, default 100.0')
|
||||||
parser.add_argument('--i', nargs = 1, default = ['pcb.png'], help = 'filename, default pcb.png')
|
parser.add_argument('--i', nargs = 1, default = ['pcb.png'], help = 'filename, default pcb.png')
|
||||||
parser.add_argument('--o', nargs = 1, type = int, default = [0], choices=range(0, 2), help = 'overlay modes 0..1, default 0')
|
parser.add_argument('--o', nargs = 1, type = int, default = [0], choices=range(0, 2), help = 'overlay modes 0..1, default 0')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
poll = 0
|
poll = 0
|
||||||
if os.name != 'nt':
|
if os.name != 'nt':
|
||||||
if args.infile == sys.stdin:
|
if args.infile == sys.stdin:
|
||||||
poll = select.poll()
|
poll = select.poll()
|
||||||
poll.register(args.infile, select.POLLIN)
|
poll.register(args.infile, select.POLLIN)
|
||||||
|
|
||||||
dimensions = literal_eval(args.infile.readline().strip())
|
dimensions = literal_eval(args.infile.readline().strip())
|
||||||
pcb_width, pcb_height, pcb_depth = dimensions
|
pcb_width, pcb_height, pcb_depth = dimensions
|
||||||
pcb_width += MARGIN * 2; pcb_height += MARGIN * 2
|
pcb_width += MARGIN * 2; pcb_height += MARGIN * 2
|
||||||
scale = args.s[0]
|
scale = args.s[0]
|
||||||
pcb_width = int(pcb_width * scale)
|
pcb_width = int(pcb_width * scale)
|
||||||
if args.o[0] == 0:
|
if args.o[0] == 0:
|
||||||
pcb_height = int(pcb_height * scale)
|
pcb_height = int(pcb_height * scale)
|
||||||
else:
|
else:
|
||||||
pcb_height = int(pcb_height * pcb_depth * scale)
|
pcb_height = int(pcb_height * pcb_depth * scale)
|
||||||
|
|
||||||
root = tkinter.Tk()
|
root = tkinter.Tk()
|
||||||
root.maxsize(pcb_width, pcb_height)
|
root.maxsize(pcb_width, pcb_height)
|
||||||
root.minsize(pcb_width, pcb_height)
|
root.minsize(pcb_width, pcb_height)
|
||||||
root.title("PCB Veiwer")
|
root.title("PCB Veiwer")
|
||||||
menu_bar = tkinter.Menu(root)
|
menu_bar = tkinter.Menu(root)
|
||||||
sub_menu = tkinter.Menu(menu_bar)
|
sub_menu = tkinter.Menu(menu_bar)
|
||||||
menu_bar.add_cascade(label = 'Help', menu = sub_menu)
|
menu_bar.add_cascade(label = 'Help', menu = sub_menu)
|
||||||
sub_menu.add_command(label = 'About', command = about_menu_handler)
|
sub_menu.add_command(label = 'About', command = about_menu_handler)
|
||||||
root['menu'] = menu_bar
|
root['menu'] = menu_bar
|
||||||
canvas = tkinter.Canvas(root, width = pcb_width, height = pcb_height)
|
canvas = tkinter.Canvas(root, width = pcb_width, height = pcb_height)
|
||||||
canvas['background'] = 'black'
|
canvas['background'] = 'black'
|
||||||
canvas.pack()
|
canvas.pack()
|
||||||
|
|
||||||
root.after(0, doframe, dimensions, root, canvas, poll)
|
root.after(0, doframe, dimensions, root, canvas, poll)
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
image.save(args.i[0])
|
image.save(args.i[0])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
366
view_mpl.py
366
view_mpl.py
|
@ -19,203 +19,203 @@ MARGIN = 2
|
||||||
args = None
|
args = None
|
||||||
|
|
||||||
def split_paths(paths):
|
def split_paths(paths):
|
||||||
new_paths = []
|
new_paths = []
|
||||||
for path in paths:
|
for path in paths:
|
||||||
new_path = []
|
new_path = []
|
||||||
for a, b in zip(path, islice(path, 1, None)):
|
for a, b in zip(path, islice(path, 1, None)):
|
||||||
_, _, za = a
|
_, _, za = a
|
||||||
_, _, zb = b
|
_, _, zb = b
|
||||||
if za != zb:
|
if za != zb:
|
||||||
if new_path:
|
if new_path:
|
||||||
new_path.append(a)
|
new_path.append(a)
|
||||||
new_paths.append(new_path)
|
new_paths.append(new_path)
|
||||||
new_paths.append([a, b])
|
new_paths.append([a, b])
|
||||||
new_path = []
|
new_path = []
|
||||||
else:
|
else:
|
||||||
new_path.append(a)
|
new_path.append(a)
|
||||||
if new_path:
|
if new_path:
|
||||||
new_path.append(path[-1])
|
new_path.append(path[-1])
|
||||||
new_paths.append(new_path)
|
new_paths.append(new_path)
|
||||||
return new_paths
|
return new_paths
|
||||||
|
|
||||||
def scale_and_split_tracks(tracks, scale):
|
def scale_and_split_tracks(tracks, scale):
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
track[0] *= scale
|
track[0] *= scale
|
||||||
track[1] *= scale
|
track[1] *= scale
|
||||||
track[2] *= scale
|
track[2] *= scale
|
||||||
track[4] = split_paths(track[4])
|
track[4] = split_paths(track[4])
|
||||||
for i in range(len(track[3])):
|
for i in range(len(track[3])):
|
||||||
r, g, (x, y, z), s = track[3][i]
|
r, g, (x, y, z), s = track[3][i]
|
||||||
track[3][i] = r * scale, g * scale, ((x + MARGIN) * scale, (y + MARGIN) * scale, z), [(cx * scale, cy * scale) for cx, cy in s]
|
track[3][i] = r * scale, g * scale, ((x + MARGIN) * scale, (y + MARGIN) * scale, z), [(cx * scale, cy * scale) for cx, cy in s]
|
||||||
for path in track[4]:
|
for path in track[4]:
|
||||||
for i in range(len(path)):
|
for i in range(len(path)):
|
||||||
x, y, z = path[i]
|
x, y, z = path[i]
|
||||||
path[i] = (x + MARGIN) * scale, (y + MARGIN) * scale, z
|
path[i] = (x + MARGIN) * scale, (y + MARGIN) * scale, z
|
||||||
|
|
||||||
def get_tracks():
|
def get_tracks():
|
||||||
tracks = []
|
tracks = []
|
||||||
while True:
|
while True:
|
||||||
line = args.infile.readline()
|
line = args.infile.readline()
|
||||||
if not line:
|
if not line:
|
||||||
tracks = []
|
tracks = []
|
||||||
break
|
break
|
||||||
track = literal_eval(line.strip())
|
track = literal_eval(line.strip())
|
||||||
if not track:
|
if not track:
|
||||||
break
|
break
|
||||||
tracks.append(track)
|
tracks.append(track)
|
||||||
return tracks
|
return tracks
|
||||||
|
|
||||||
def doframe(frame_num, dimensions, poll, fig, ax):
|
def doframe(frame_num, dimensions, poll, fig, ax):
|
||||||
tracks = get_tracks()
|
tracks = get_tracks()
|
||||||
if poll:
|
if poll:
|
||||||
while poll.poll(1):
|
while poll.poll(1):
|
||||||
new_tracks = get_tracks()
|
new_tracks = get_tracks()
|
||||||
if not new_tracks:
|
if not new_tracks:
|
||||||
break
|
break
|
||||||
tracks = new_tracks
|
tracks = new_tracks
|
||||||
if not tracks:
|
if not tracks:
|
||||||
return
|
return
|
||||||
|
|
||||||
pcb_width, pcb_height, pcb_depth = dimensions
|
pcb_width, pcb_height, pcb_depth = dimensions
|
||||||
scale = args.s[0]
|
scale = args.s[0]
|
||||||
scale_and_split_tracks(tracks, scale)
|
scale_and_split_tracks(tracks, scale)
|
||||||
pcb_width += MARGIN * 2; pcb_height += MARGIN * 2
|
pcb_width += MARGIN * 2; pcb_height += MARGIN * 2
|
||||||
img_width = int(pcb_width * scale)
|
img_width = int(pcb_width * scale)
|
||||||
if args.o[0] == 0:
|
if args.o[0] == 0:
|
||||||
img_height = int(pcb_height * scale)
|
img_height = int(pcb_height * scale)
|
||||||
else:
|
else:
|
||||||
img_height = int(pcb_height * pcb_depth * scale)
|
img_height = int(pcb_height * pcb_depth * scale)
|
||||||
|
|
||||||
ax.clear()
|
ax.clear()
|
||||||
pylab.subplots_adjust(left = 0.0, right = 1.0, bottom = 0.0, top = 1.0)
|
pylab.subplots_adjust(left = 0.0, right = 1.0, bottom = 0.0, top = 1.0)
|
||||||
ax.set_xlim([0, img_width])
|
ax.set_xlim([0, img_width])
|
||||||
ax.set_ylim([0, img_height][::-1])
|
ax.set_ylim([0, img_height][::-1])
|
||||||
ax.set(aspect = 1)
|
ax.set(aspect = 1)
|
||||||
ax.axis('off')
|
ax.axis('off')
|
||||||
|
|
||||||
if args.o[0] == 0:
|
if args.o[0] == 0:
|
||||||
colors = ['red', 'green', 'blue', 'yellow', 'fuchsia', 'aqua']
|
colors = ['red', 'green', 'blue', 'yellow', 'fuchsia', 'aqua']
|
||||||
for depth in range(pcb_depth - 1, -1, -1):
|
for depth in range(pcb_depth - 1, -1, -1):
|
||||||
brush = colors[depth % len(colors)]
|
brush = colors[depth % len(colors)]
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] == path[-1][2] == depth:
|
if path[0][2] == path[-1][2] == depth:
|
||||||
points = thicken_path_2d([(x, y) for x, y, _ in path], radius, 3, 2)
|
points = thicken_path_2d([(x, y) for x, y, _ in path], radius, 3, 2)
|
||||||
poly = plt.Polygon(points, facecolor = brush, edgecolor = 'none', alpha = 0.5)
|
poly = plt.Polygon(points, facecolor = brush, edgecolor = 'none', alpha = 0.5)
|
||||||
ax.add_patch(poly)
|
ax.add_patch(poly)
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] != path[-1][2]:
|
if path[0][2] != path[-1][2]:
|
||||||
x, y, _ = path[0]
|
x, y, _ = path[0]
|
||||||
circ = plt.Circle((x, y), radius = via, color = 'white')
|
circ = plt.Circle((x, y), radius = via, color = 'white')
|
||||||
ax.add_patch(circ)
|
ax.add_patch(circ)
|
||||||
for r, g, (x, y, _), s in terminals:
|
for r, g, (x, y, _), s in terminals:
|
||||||
if not s:
|
if not s:
|
||||||
circ = plt.Circle((x, y), radius = r, color = 'white')
|
circ = plt.Circle((x, y), radius = r, color = 'white')
|
||||||
ax.add_patch(circ)
|
ax.add_patch(circ)
|
||||||
else:
|
else:
|
||||||
if r !=0:
|
if r !=0:
|
||||||
points = thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r, 3, 2)
|
points = thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r, 3, 2)
|
||||||
poly = plt.Polygon(points, facecolor = 'white', edgecolor = 'none')
|
poly = plt.Polygon(points, facecolor = 'white', edgecolor = 'none')
|
||||||
ax.add_patch(poly)
|
ax.add_patch(poly)
|
||||||
else:
|
else:
|
||||||
points = [(cx + x, cy + y) for cx, cy in s]
|
points = [(cx + x, cy + y) for cx, cy in s]
|
||||||
poly = plt.Polygon(points, facecolor = 'white', edgecolor = 'none')
|
poly = plt.Polygon(points, facecolor = 'white', edgecolor = 'none')
|
||||||
ax.add_patch(poly)
|
ax.add_patch(poly)
|
||||||
else:
|
else:
|
||||||
for depth in range(pcb_depth):
|
for depth in range(pcb_depth):
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] == path[-1][2] == depth:
|
if path[0][2] == path[-1][2] == depth:
|
||||||
points = thicken_path_2d([(x, y + depth * pcb_height * scale) for x, y, _ in path], radius + gap, 3, 2)
|
points = thicken_path_2d([(x, y + depth * pcb_height * scale) for x, y, _ in path], radius + gap, 3, 2)
|
||||||
poly = plt.Polygon(points, facecolor = 'white', edgecolor = 'none')
|
poly = plt.Polygon(points, facecolor = 'white', edgecolor = 'none')
|
||||||
ax.add_patch(poly)
|
ax.add_patch(poly)
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] != path[-1][2]:
|
if path[0][2] != path[-1][2]:
|
||||||
x, y, _ = path[0]
|
x, y, _ = path[0]
|
||||||
y += depth * pcb_height * scale
|
y += depth * pcb_height * scale
|
||||||
circ = plt.Circle((x, y), radius = via + gap, color = 'white')
|
circ = plt.Circle((x, y), radius = via + gap, color = 'white')
|
||||||
ax.add_patch(circ)
|
ax.add_patch(circ)
|
||||||
for r, g, (x, y, _), s in terminals:
|
for r, g, (x, y, _), s in terminals:
|
||||||
y += depth * pcb_height * scale
|
y += depth * pcb_height * scale
|
||||||
if not s:
|
if not s:
|
||||||
circ = plt.Circle((x, y), radius = r + g, color = 'white')
|
circ = plt.Circle((x, y), radius = r + g, color = 'white')
|
||||||
ax.add_patch(circ)
|
ax.add_patch(circ)
|
||||||
else:
|
else:
|
||||||
points = thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r + g, 3, 2)
|
points = thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r + g, 3, 2)
|
||||||
poly = plt.Polygon(points, facecolor = 'white', edgecolor = 'none')
|
poly = plt.Polygon(points, facecolor = 'white', edgecolor = 'none')
|
||||||
ax.add_patch(poly)
|
ax.add_patch(poly)
|
||||||
if r ==0:
|
if r ==0:
|
||||||
points = [(cx + x, cy + y) for cx, cy in s]
|
points = [(cx + x, cy + y) for cx, cy in s]
|
||||||
poly = plt.Polygon(points, facecolor = 'white', edgecolor = 'none')
|
poly = plt.Polygon(points, facecolor = 'white', edgecolor = 'none')
|
||||||
ax.add_patch(poly)
|
ax.add_patch(poly)
|
||||||
for depth in range(pcb_depth):
|
for depth in range(pcb_depth):
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] == path[-1][2] == depth:
|
if path[0][2] == path[-1][2] == depth:
|
||||||
points = thicken_path_2d([(x, y + depth * pcb_height * scale) for x, y, _ in path], radius, 3, 2)
|
points = thicken_path_2d([(x, y + depth * pcb_height * scale) for x, y, _ in path], radius, 3, 2)
|
||||||
poly = plt.Polygon(points, facecolor = 'black', edgecolor = 'none')
|
poly = plt.Polygon(points, facecolor = 'black', edgecolor = 'none')
|
||||||
ax.add_patch(poly)
|
ax.add_patch(poly)
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
radius, via, gap, terminals, paths = track
|
radius, via, gap, terminals, paths = track
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path[0][2] != path[-1][2]:
|
if path[0][2] != path[-1][2]:
|
||||||
x, y, _ = path[0]
|
x, y, _ = path[0]
|
||||||
y += depth * pcb_height * scale
|
y += depth * pcb_height * scale
|
||||||
circ = plt.Circle((x, y), radius = via, color = 'black')
|
circ = plt.Circle((x, y), radius = via, color = 'black')
|
||||||
ax.add_patch(circ)
|
ax.add_patch(circ)
|
||||||
for r, g, (x, y, _), s in terminals:
|
for r, g, (x, y, _), s in terminals:
|
||||||
y += depth * pcb_height * scale
|
y += depth * pcb_height * scale
|
||||||
if not s:
|
if not s:
|
||||||
circ = plt.Circle((x, y), radius = r, color = 'black')
|
circ = plt.Circle((x, y), radius = r, color = 'black')
|
||||||
ax.add_patch(circ)
|
ax.add_patch(circ)
|
||||||
else:
|
else:
|
||||||
if r !=0:
|
if r !=0:
|
||||||
points = thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r, 3, 2)
|
points = thicken_path_2d([(cx + x, cy + y) for cx, cy in s], r, 3, 2)
|
||||||
poly = plt.Polygon(points, facecolor = 'black', edgecolor = 'none')
|
poly = plt.Polygon(points, facecolor = 'black', edgecolor = 'none')
|
||||||
ax.add_patch(poly)
|
ax.add_patch(poly)
|
||||||
else:
|
else:
|
||||||
points = [(cx + x, cy + y) for cx, cy in s]
|
points = [(cx + x, cy + y) for cx, cy in s]
|
||||||
poly = plt.Polygon(points, facecolor = 'black', edgecolor = 'none')
|
poly = plt.Polygon(points, facecolor = 'black', edgecolor = 'none')
|
||||||
ax.add_patch(poly)
|
ax.add_patch(poly)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global args
|
global args
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description = 'Pcb layout viewer.')
|
parser = argparse.ArgumentParser(description = 'Pcb layout viewer.')
|
||||||
parser.add_argument('infile', nargs = '?', type = argparse.FileType('r'), default = sys.stdin, help = 'filename, default stdin')
|
parser.add_argument('infile', nargs = '?', type = argparse.FileType('r'), default = sys.stdin, help = 'filename, default stdin')
|
||||||
parser.add_argument('--s', nargs = 1, type = int, default = [9], help = 'scale factor, default 9')
|
parser.add_argument('--s', nargs = 1, type = int, default = [9], help = 'scale factor, default 9')
|
||||||
parser.add_argument('--f', nargs = 1, type = float, default = [100.0], help = 'framerate, default 100.0')
|
parser.add_argument('--f', nargs = 1, type = float, default = [100.0], help = 'framerate, default 100.0')
|
||||||
parser.add_argument('--i', nargs = 1, default = ['pcb.png'], help = 'filename, default pcb.png')
|
parser.add_argument('--i', nargs = 1, default = ['pcb.png'], help = 'filename, default pcb.png')
|
||||||
parser.add_argument('--o', nargs = 1, type = int, default = [0], choices=range(0, 2), help = 'overlay modes 0..1, default 0')
|
parser.add_argument('--o', nargs = 1, type = int, default = [0], choices=range(0, 2), help = 'overlay modes 0..1, default 0')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
poll = None
|
poll = None
|
||||||
if os.name != 'nt':
|
if os.name != 'nt':
|
||||||
if args.infile == sys.stdin:
|
if args.infile == sys.stdin:
|
||||||
poll = select.poll()
|
poll = select.poll()
|
||||||
poll.register(args.infile, select.POLLIN)
|
poll.register(args.infile, select.POLLIN)
|
||||||
|
|
||||||
dimensions = literal_eval(args.infile.readline().strip())
|
dimensions = literal_eval(args.infile.readline().strip())
|
||||||
pcb_width, pcb_height, pcb_depth = dimensions
|
pcb_width, pcb_height, pcb_depth = dimensions
|
||||||
pcb_width += MARGIN * 2; pcb_height += MARGIN * 2
|
pcb_width += MARGIN * 2; pcb_height += MARGIN * 2
|
||||||
scale = args.s[0]
|
scale = args.s[0]
|
||||||
pcb_width = int(pcb_width * scale)
|
pcb_width = int(pcb_width * scale)
|
||||||
if args.o[0] == 0:
|
if args.o[0] == 0:
|
||||||
pcb_height = int(pcb_height * scale)
|
pcb_height = int(pcb_height * scale)
|
||||||
else:
|
else:
|
||||||
pcb_height = int(pcb_height * pcb_depth * scale)
|
pcb_height = int(pcb_height * pcb_depth * scale)
|
||||||
|
|
||||||
fig, ax = plt.subplots(frameon = True, facecolor = 'black')
|
fig, ax = plt.subplots(frameon = True, facecolor = 'black')
|
||||||
ani = animation.FuncAnimation(fig, doframe, fargs = (dimensions, poll, fig, ax), interval = 10, blit = False, repeat = True)
|
ani = animation.FuncAnimation(fig, doframe, fargs = (dimensions, poll, fig, ax), interval = 10, blit = False, repeat = True)
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Reference in New Issue