187 lines
8.8 KiB
Python
187 lines
8.8 KiB
Python
import numpy as np
|
|
import numpy.linalg as la
|
|
import svgwrite
|
|
from tracer_tool import AsymptoticTracer
|
|
|
|
class FabricationHelper:
|
|
|
|
def __init__(self, width, thickness, spacing, scale_length=1.0):
|
|
self.strips_width = width
|
|
self.strips_spacing = spacing
|
|
self.strips_thickness = thickness
|
|
self.scale_length = scale_length
|
|
self.flag_flatten = False
|
|
|
|
def generate_flatten_path(self, pathIndex, second_direction=False, position=np.array([0,0,0])):
|
|
|
|
length_direction = np.array([1,0,0])
|
|
width_direction = np.array([0,1,0]) * self.strips_width * 0.5
|
|
if second_direction:
|
|
width_direction *= -1
|
|
|
|
self.intersection_points[second_direction][pathIndex] = np.empty((0,3), float)
|
|
self.intersection_labels[second_direction][pathIndex] = []
|
|
|
|
intersections = self.intersections[second_direction][pathIndex]
|
|
paths_lengths = self.paths_lengths[second_direction][pathIndex]
|
|
length = np.trace(np.diag(paths_lengths)) * self.scale_length
|
|
|
|
path_forwards = np.empty((0,3), float)
|
|
path_backwards = np.empty((0,3), float)
|
|
path_intersection = np.empty((0,3), float)
|
|
|
|
# Add start point
|
|
start_position_forward = position + width_direction
|
|
start_position_backward = position - width_direction
|
|
end_position_forward = position + width_direction + length_direction * length
|
|
end_position_backward = position - width_direction + length_direction * length
|
|
path_forwards = np.append(path_forwards, np.array([start_position_forward]),axis=0)
|
|
path_backwards = np.append(path_backwards, np.array([start_position_backward]),axis=0)
|
|
|
|
# Connections
|
|
if len(intersections)>0:
|
|
for i in range(len(intersections)):
|
|
|
|
intersection_event = intersections[i]
|
|
# Store label
|
|
self.intersection_labels[second_direction][pathIndex].append(int(intersection_event[2]))
|
|
|
|
# Add intersection points
|
|
edge_index = int(intersection_event[0])
|
|
|
|
partial_length = (np.trace(np.diag(paths_lengths[:edge_index])) + paths_lengths[edge_index] * intersection_event[1]) * self.scale_length
|
|
|
|
p = position + length_direction * partial_length
|
|
|
|
path_intersection = np.append(path_intersection, np.array([p]), axis=0)
|
|
|
|
p += width_direction
|
|
|
|
vec_offset = length_direction * self.strips_thickness * 0.5
|
|
|
|
if partial_length - self.strips_thickness * 0.5 <= 0:
|
|
p0 = position
|
|
p1 = p + vec_offset - width_direction
|
|
p2 = p + vec_offset
|
|
path_forwards = np.array([p0, p1, p2])
|
|
elif partial_length + self.strips_thickness * 0.5 >= length:
|
|
p0 = p - vec_offset
|
|
p1 = p - vec_offset - width_direction
|
|
p2 = position + length_direction * length
|
|
path_forwards = np.append(path_forwards, np.array([p0, p1, p2]), axis=0)
|
|
else:
|
|
p0 = p - vec_offset
|
|
p1 = p - vec_offset - width_direction
|
|
p2 = p + vec_offset - width_direction
|
|
p3 = p + vec_offset
|
|
path_forwards = np.append(path_forwards, np.array([p0, p1, p2, p3]), axis=0)
|
|
|
|
if end_position_forward[0]>path_forwards[len(path_forwards)-1][0]:
|
|
path_forwards = np.append(path_forwards, np.array([end_position_forward]), axis=0)
|
|
path_backwards = np.append(path_backwards, np.array([end_position_backward]), axis=0)
|
|
else:
|
|
path_forwards = np.append(path_forwards, np.array([end_position_forward]), axis=0)
|
|
path_backwards = np.append(path_backwards, np.array([end_position_backward]), axis=0)
|
|
|
|
path = path_backwards[::-1]
|
|
|
|
# Combine paths
|
|
path = np.append(path, path_forwards, axis=0)
|
|
path = np.append(path, np.array([path[0]]), axis=0)
|
|
self.paths_flatten[second_direction][pathIndex] = path
|
|
self.intersection_points[second_direction][pathIndex] = path_intersection
|
|
|
|
return path, length
|
|
|
|
def generate_flatten_network(self, tracer):
|
|
self.paths_flatten = tracer.paths_flatten
|
|
self.paths_lengths = tracer.paths_lengths
|
|
self.intersection_points = tracer.paths_labels
|
|
self.intersection_labels = [[] for i in range(2) ]
|
|
self.intersections = tracer.intersections
|
|
self.strips_numA = len(tracer.paths_indexes[0])
|
|
self.strips_numB = len(tracer.paths_indexes[1])
|
|
# init labels
|
|
self.intersection_labels[0] = [[] for i in range(self.strips_numA)]
|
|
self.intersection_labels[1] = [[] for i in range(self.strips_numB)]
|
|
|
|
strips_num = self.strips_numA if self.strips_numA > self.strips_numB else self.strips_numB
|
|
|
|
# Generate flat strips
|
|
strips_added = 0
|
|
|
|
# Fabrication parameters
|
|
self.board_width = self.strips_width * (self.strips_numA+self.strips_numB) + self.strips_spacing * (self.strips_numA+self.strips_numB+1)
|
|
self.board_length = 0
|
|
|
|
for i in range(strips_num):
|
|
if i< self.strips_numA:
|
|
position = np.array([ self.strips_spacing, self.strips_width * 0.5 + self.strips_spacing + (self.strips_width + self.strips_spacing) * strips_added, 0 ] )
|
|
points, path_len = self.generate_flatten_path(i, False, position)
|
|
strips_added +=1
|
|
|
|
if path_len>self.board_length:
|
|
self.board_length = path_len
|
|
|
|
if i< self.strips_numB:
|
|
position = np.array([ self.strips_spacing, self.strips_width * 0.5 + self.strips_spacing + (self.strips_width + self.strips_spacing) * strips_added, 0 ] )
|
|
points, path_len = self.generate_flatten_path(i, True, position)
|
|
strips_added +=1
|
|
|
|
if path_len>self.board_length:
|
|
self.board_length = path_len
|
|
|
|
self.flag_flatten = True
|
|
|
|
def generate_svg_file(self, filename, font_size=1, cutting_color="red", engraving_color="black", length=None, width=None):
|
|
|
|
if length!=None:
|
|
self.board_length = length
|
|
if width!=None:
|
|
self.board_width = width
|
|
|
|
dwg = svgwrite.Drawing(filename,size=(str(self.board_length), str(self.board_width)), fill="none", stroke_width=".005cm")
|
|
|
|
strips_numA = len(self.paths_flatten[0])
|
|
strips_numB = len(self.paths_flatten[1])
|
|
strips_num = strips_numA if strips_numA > strips_numB else strips_numB
|
|
|
|
for i in range(strips_num):
|
|
if i< strips_numA:
|
|
pts = self.paths_flatten[0][i][:,[0,1]]
|
|
dwg.add(dwg.polyline(pts, stroke=cutting_color))
|
|
p0 = self.paths_flatten[0][i][0]
|
|
p1 = self.paths_flatten[0][i][len(self.paths_flatten[0][i])-2]
|
|
p2 = self.paths_flatten[0][i][len(self.paths_flatten[0][i])-3]
|
|
vecX = p1-p2
|
|
vecY = (p1-p0) * 0.5
|
|
vecX /= la.norm(vecX)
|
|
pos = p0 + vecY - vecX * self.strips_width * 0.9
|
|
dwg.add(dwg.text('A'+str(i), insert=pos, fill=engraving_color, font_family="Code Light" ,font_size=str(font_size)))
|
|
pts = self.intersection_points[0][i]
|
|
labels = self.intersection_labels[0][i]
|
|
for j in range(len(pts)):
|
|
pos = pts[j] - vecY * 0.5
|
|
dwg.add(dwg.text('c' + str(labels[j]), insert=pos, fill=engraving_color, font_family="Code Light" ,font_size=str(font_size * 0.7)))
|
|
|
|
if i< strips_numB:
|
|
pts = self.paths_flatten[1][i][:,[0,1]]
|
|
dwg.add(dwg.polyline(pts, stroke=cutting_color))
|
|
p0 = self.paths_flatten[1][i][0]
|
|
p1 = self.paths_flatten[1][i][len(self.paths_flatten[1][i])-2]
|
|
p2 = self.paths_flatten[1][i][len(self.paths_flatten[1][i])-3]
|
|
vecX = p1-p2
|
|
vecY = (p1-p0) * 0.5
|
|
vecX /= la.norm(vecX)
|
|
pos = p0 + vecY - vecX * self.strips_width * 0.9
|
|
dwg.add(dwg.text('B'+str(i), insert=pos, fill=engraving_color, font_family="Code Light" ,font_size=str(font_size)))
|
|
pts = self.intersection_points[1][i]
|
|
labels = self.intersection_labels[1][i]
|
|
for j in range(len(pts)):
|
|
pos = pts[j] - vecY * 0.5
|
|
dwg.add(dwg.text('c' + str(labels[j]), insert=pos, fill=engraving_color, font_family="Code Light" ,font_size=str(font_size * 0.7)))
|
|
#Board boundary
|
|
points = np.array([[0.,0.],[self.board_length,0.],[self.board_length, self.board_width],[0., self.board_width],[0.,0.]])
|
|
dwg.add(dwg.polyline(points, stroke=engraving_color))
|
|
dwg.save()
|