#!/usr/bin/env python # encoding: utf-8 import svgwrite as svg import numpy as np import IPython class PressKit: scale = 4 bounding_corners = [[0, 0], [0, 0]] drawing = None numsides = 4 #TODO: make this more general inset = 45 * scale width = 10 * scale height = 20 * scale slider_length = 150 * scale prong_height = width * 1.2 prong_tail = 8 * scale flexure_width = 3 * scale chamfer_angle = np.pi/3 def __init__(self, filename='test.svg'): self.drawing = svg.Drawing(filename) def get_center_y(self): return (self.get_y_min() + self.get_y_max())/2 def get_center_x(self): return (self.get_x_min() + self.get_x_max())/2 def get_y_min(self): return self.bounding_corners[0][1] def get_x_min(self): return self.bounding_corners[0][0] def get_x_max(self): return self.bounding_corners[1][0] def get_y_max(self): return self.bounding_corners[1][1] #TODO: let's come up with a good way to check for arbitrary geometry def __set_bounding_corners(self, point_list): for point in point_list: self.bounding_corners[0][0] = min(self.bounding_corners[0][0], point[0]) self.bounding_corners[0][1] = min(self.bounding_corners[0][1], point[1]) self.bounding_corners[1][0] = max(self.bounding_corners[1][0], point[0]) self.bounding_corners[1][1] = max(self.bounding_corners[1][1], point[1]) def print_points(self, point_list, color='black', polygon=True, opacity=1, fill='none', stroke_width=1.0): if polygon: polygon = svg.shapes.Polygon( point_list, stroke=color, stroke_width=stroke_width, fill=fill, opacity=1.0, stroke_opacity=1.0) self.drawing.add(polygon) else: polyline = svg.shapes.Polyline( point_list, stroke=color, stroke_width=stroke_width, fill=fill, opacity=1.0, stroke_opacity=1.0) self.drawing.add(polyline) def print_points_rotated(self, point_list, color='black',polygon=True,opacity=1,fill='none',stroke_width=1.0): center_x = self.get_center_x() center_y = self.get_center_y() for i in range(self.numsides): theta = 2*np.pi * i / self.numsides rotMatrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) new_points = [] for point in point_list: temp_point = point temp_point = np.array(temp_point) - np.array((center_x, center_y)) temp_point = np.dot(rotMatrix, temp_point) temp_point = np.array(temp_point) + np.array((center_x, center_y)) new_points.append(tuple(temp_point)) self.print_points(new_points, color=color, polygon=polygon,opacity=opacity, fill=fill, stroke_width=stroke_width) def create_perimeter(self, no_prongs=True): """This function always needs to be called for each object. It sets the object perimeter for cutting. It's probably important that I make this flexible. It will also set temporary final bounds""" #For now this is just going to be a square. In the future, a case statement xu = 300 * self.scale yu = 300 * self.scale xl = 0 * self.scale yl = 0 * self.scale center_x = (xu - xl) / 2 center_y = (yu - yl) / 2 p1 = (0, 0) point_list = [] if no_prongs: for i in range(self.numsides): theta = 2*np.pi * i / self.numsides rotMatrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) temp_point = p1 temp_point = np.array(temp_point) - np.array((center_x, center_y)) temp_point = np.dot(rotMatrix, temp_point) temp_point = np.array(temp_point) + np.array((center_x, center_y)) point_list.append(tuple(temp_point)) #and now we draw this: self.print_points(point_list, opacity=1.0) else: point_list = [(self.inset - self.width, 0), (0, 0), (0, self.inset - self.width)] for i in range(self.numsides): theta = 2*np.pi * i / self.numsides rotMatrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) new_points = [] for point in point_list: temp_point = point temp_point = np.array(temp_point) - np.array((center_x, center_y)) temp_point = np.dot(rotMatrix, temp_point) temp_point = np.array(temp_point) + np.array((center_x, center_y)) new_points.append(tuple(temp_point)) self.print_points(new_points, color='black', polygon=False,opacity=1.0, fill='none', stroke_width=1.0) point_list = [(yu - self.inset - self.width, 0), (self.inset + self.width, 0)] for i in range(self.numsides): theta = 2*np.pi * i / self.numsides rotMatrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) new_points = [] for point in point_list: temp_point = point temp_point = np.array(temp_point) - np.array((center_x, center_y)) temp_point = np.dot(rotMatrix, temp_point) temp_point = np.array(temp_point) + np.array((center_x, center_y)) new_points.append(tuple(temp_point)) self.print_points(new_points, color='black', polygon=False,opacity=1.0, fill='none', stroke_width=1.0) point_list = [] for i in range(self.numsides): theta = 2*np.pi * i / self.numsides rotMatrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) temp_point = p1 temp_point = np.array(temp_point) - np.array((center_x, center_y)) temp_point = np.dot(rotMatrix, temp_point) temp_point = np.array(temp_point) + np.array((center_x, center_y)) point_list.append(tuple(temp_point)) #first set the perimeter self.__set_bounding_corners([(xl, yl), (xu, yu)] ) def create_ortho_slots(self): #create four slots width = self.width height = self.height inset = self.inset center_x = self.get_center_x() center_y = self.get_center_y() y_min = self.get_y_min() #create four polygons and place them appropriately around the rectangle point_list = [(center_x - width/2, y_min - height/2 + inset), (center_x - width/2, y_min + height/2 + inset), (center_x + width/2, y_min + height/2 + inset), (center_x + width/2, y_min - height/2 + inset)] #now rotate this the appropriate number of times #self.print_points(point_list) self.print_points_rotated(point_list) def create_other_ortho_slots(self): #create four slots width = self.width height = self.height inset = self.inset center_x = self.get_center_x() center_y = self.get_center_y() y_min = self.get_y_min() x_min = self.get_x_min() x_max = self.get_x_max() #create four polygons and place them appropriately around the rectangle point_list = [(x_min - width/2 + inset, y_min - height/2 + inset), (x_min - width/2 + inset, y_min + height/2 + inset), (x_min + width/2 + inset, y_min + height/2 + inset), (x_min + width/2 + inset, y_min - height/2 + inset)] #now rotate this the appropriate number of times #self.print_points(point_list) self.print_points_rotated(point_list) point_list2 = [(x_max - width/2 - inset, y_min - height/2 + inset), (x_max - width/2 - inset, y_min + height/2 + inset), (x_max + width/2 - inset, y_min + height/2 + inset), (x_max + width/2 - inset, y_min - height/2 + inset)] #now rotate this the appropriate number of times #self.print_points(point_list) self.print_points_rotated(point_list2) def create_radial_slots(self): height = self.height width = self.width inset = self.inset y_min = self.bounding_corners[0][1] x_min = self.bounding_corners[0][0] center_y = self.get_center_y() center_x = self.get_center_x() separation = 50 degrees = 10 radians = np.radians(degrees) outer = (center_y - y_min) - inset - height / 2.0 inner = (center_y - y_min) - inset + height / 2.0 start_1x = center_x + inner - (1 - np.cos(radians)) * inner start_1y = center_y - np.sin(radians) * inner end_1x = center_x - inner + (1 - np.cos(radians)) * inner end_1y = center_y - np.sin(radians) * inner s1x = start_1x s1y = start_1y e1x = end_1x e1y = end_1y p = self.drawing.path(d="M%f,%f A%f,%f 0 0,0 %f,%f" % (start_1x, start_1y, inner, inner, end_1x, end_1y), fill="none", stroke="black", ) self.drawing.add(p) start_1x = center_x + outer - (1 - np.cos(radians)) * outer start_1y = center_y - np.sin(radians) * outer end_1x = center_x - outer + (1 - np.cos(radians)) * outer end_1y = center_y - np.sin(radians) * outer p = self.drawing.path(d="M%f,%f A%f,%f 0 0,0 %f,%f" % (start_1x, start_1y, outer, outer, end_1x, end_1y), fill="none", stroke="black", ) self.drawing.add(p) self.print_points([(s1x, s1y), (start_1x, start_1y)], polygon=False) self.print_points([(e1x, e1y), (end_1x, end_1y)], polygon=False) start_1x = center_x + inner - (1 - np.cos(radians)) * inner start_1y = center_y + np.sin(radians) * inner end_1x = center_x - inner + (1 - np.cos(radians)) * inner end_1y = center_y + np.sin(radians) * inner s1x = start_1x s1y = start_1y e1x = end_1x e1y = end_1y p = self.drawing.path(d="M%f,%f A%f,%f 0 0,1 %f,%f" % (start_1x, start_1y, inner, inner, end_1x, end_1y), fill="none", stroke="black", ) self.drawing.add(p) start_1x = center_x + outer - (1 - np.cos(radians)) * outer start_1y = center_y + np.sin(radians) * outer end_1x = center_x - outer + (1 - np.cos(radians)) * outer end_1y = center_y + np.sin(radians) * outer p = self.drawing.path(d="M%f,%f A%f,%f 0 0,1 %f,%f" % (start_1x, start_1y, outer, outer, end_1x, end_1y), fill="none", stroke="black", ) self.drawing.add(p) self.print_points([(s1x, s1y), (start_1x, start_1y)], polygon=False) self.print_points([(e1x, e1y), (end_1x, end_1y)], polygon=False) """ self.print_points([(center_x + inner, center_y + separation), (center_x + outer, center_y + separation)], polygon=False) self.print_points([(center_x - inner, center_y + separation), (center_x - outer, center_y + separation)], polygon=False) self.print_points([(center_x + inner, center_y - separation), (center_x + outer, center_y - separation)], polygon=False) self.print_points([(center_x - inner, center_y - separation), (center_x - outer, center_y - separation)], polygon=False) """ #self.drawing.add( svg.shapes.Circle(center=(center_x, center_y), r=outer, stroke='black', stroke_width=1, fill='none') ) #self.drawing.add( svg.shapes.Circle(center=(center_x, center_y), r=inner, stroke='black', stroke_width=1, fill='none') ) def create_rectangle_slots(self): #create four slots width = self.slider_length height = self.height inset = self.inset center_x = self.get_center_x() center_y = self.get_center_y() y_min = self.get_y_min() #create four polygons and place them appropriately around the rectangle point_list = [(center_x - width/2, y_min - height/2 + inset), (center_x - width/2, y_min + height/2 + inset), (center_x + width/2, y_min + height/2 + inset), (center_x + width/2, y_min - height/2 + inset)] #now rotate this the appropriate number of times #self.print_points(point_list) self.print_points_rotated(point_list) def create_prongs(self): #create four slots width = self.width height = self.height inset = self.inset prong_height = self.prong_height prong_tail = self.prong_tail chamfer_angle = self.chamfer_angle flexure_width = self.flexure_width center_x = self.get_center_x() center_y = self.get_center_y() y_min = self.get_y_min() y_max = self.get_y_max() x_min = self.get_x_min() #create two filanges #This is the first one point_list = [ ((y_min + height/2 + inset), x_min), ((y_min + height/2 + inset), x_min - prong_height), ((y_min + height/2 + inset + prong_tail), x_min - prong_height), ((y_min + height/2 + inset - np.cos(chamfer_angle)*prong_tail), x_min - prong_height - np.sin(chamfer_angle)*prong_tail), ((y_min - height/2 + inset + np.cos(chamfer_angle)*prong_tail), x_min - prong_height - np.sin(chamfer_angle)*prong_tail), ((y_min - height/2 + inset - prong_tail), x_min - prong_height), ((y_min - height/2 + inset), x_min - prong_height), ((y_min - height/2 + inset), x_min), ] self.print_points_rotated(point_list, color='black', polygon=False) point_list2 = [ (y_max - (y_min + height/2 + inset), x_min), (y_max - (y_min + height/2 + inset), x_min - prong_height), (y_max - (y_min + height/2 + inset + prong_tail), x_min - prong_height), (y_max - (y_min + height/2 + inset - np.cos(chamfer_angle)*prong_tail), x_min - prong_height - np.sin(chamfer_angle)*prong_tail), (y_max - (y_min - height/2 + inset + np.cos(chamfer_angle)*prong_tail), x_min - prong_height - np.sin(chamfer_angle)*prong_tail), (y_max - (y_min - height/2 + inset - prong_tail), x_min - prong_height), (y_max - (y_min - height/2 + inset), x_min - prong_height), (y_max - (y_min - height/2 + inset), x_min), ] self.print_points_rotated(point_list2, color='black', polygon=False) #TODO: cut out part of the original perimeter def save(self): self.drawing.viewbox(-1000, -1000, 2000, 2000) self.drawing.fit(horiz='left', vert='top') self.drawing.save() if __name__ == "__main__": """ pk = PressKit('prong_square.svg') pk.create_perimeter(False) pk.create_prongs() pk.create_other_ortho_slots() pk.save() """ """ pk = PressKit('octogon.svg') pk.create_perimeter(True) pk.create_ortho_slots() pk.save() """ pk = PressKit('revolute.svg') pk.create_perimeter(False) pk.create_prongs() pk.create_radial_slots() pk.save() """ pk = PressKit('prismatic.svg') pk.create_perimeter(False) pk.create_prongs() pk.create_rectangle_slots() pk.save() """