Files
epfl-archive/cs457-gc/assignment_3_3/src/fabrication_helper.py
2022-04-07 18:46:57 +02:00

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()