'''
Autor: Antonio de Jesús Anaya Hernández
Github: @kny5
Program: Parametric polygon shape generator for laser cutting with kerf and dxf output.
'''
import math
import ezdxf
import random
# Parameters
sides = random.randrange(3, 10, 1)
radius = 40
origin = (100,100)
slot_depth = radius/2
kerf = 0.2
material_thickness = 5
class dxf_file():
def __init__(self, __filename):
self.filename = __filename
self.file = None
self.create_dxf()
def create_dxf(self):
self.file = ezdxf.new('R2018')
self.file.saveas(self.filename)
def save_dxf(self):
self.file.saveas(self.filename)
def add_vectors_dxf(self, vectors):
self.model = self.file.modelspace()
for vector in vectors:
self.model.add_line(vector[0], vector[1])
self.save_dxf()
def rotate_point(point, pivot, angle):
x = ((point[0] - pivot[0]) * math.cos(angle)) - ((point[1] - pivot[1]) * math.sin(angle)) + pivot[0]
y = ((point[0] - pivot[0]) * math.sin(angle)) + ((point[1] - pivot[1]) * math.cos(angle)) + pivot[1]
return (x, y)
def line_intersection(line1, line2):
xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
def det(a, b):
return a[0] * b[1] - a[1] * b[0]
div = det(xdiff, ydiff)
if div == 0:
raise Exception('lines do not intersect')
d = (det(*line1), det(*line2))
x = det(d, xdiff) / div
y = det(d, ydiff) / div
return (x, y)
class workspace():
def __init__(self, __origin=(0,0), __width=1000, __height=1000):
self.origin = __origin
self.width = __width
self.height = __height
self.objects = []
def add_object(self, __object):
self.objects.append(__object)
# Should I sort this?
class polygon():
def __init__(self, __origin, __sides, __radius, __kerf=kerf):
self.kerf = __kerf
self.sides = __sides
# kerf parameter
self.radius = __radius + self.kerf
self.origin = __origin
self.points = []
self.vectors = []
self.angle = 360/self.sides
self.make()
self.get_vectors()
def make(self):
for side in range(0, self.sides):
__x = self.origin[0] + self.radius * math.cos(2 * math.pi * side / self.sides)
__y = self.origin[1] + self.radius * math.sin(2 * math.pi * side / self.sides)
self.points.append((__x, __y))
def get_vectors(self):
self.vectors = list(zip(self.points, self.points[1:] + self.points[:1]))
def slot(self, __width, __depth):
# kerf parameter
width = __width - self.kerf
depth = __depth - self.kerf
# Define points of slot shape:
__a = (self.origin[0] + self.radius - depth, self.origin[1] - (width / 2))
__b = (self.origin[0] + self.radius - depth, self.origin[1] + (width / 2))
__c = (self.origin[0] + self.radius, self.origin[1] + (width / 2))
__d = (self.origin[0] + self.radius, self.origin[1] - (width / 2))
# Set initial position rotate to initial position
__a = rotate_point(__a, self.origin, math.radians(self.angle / 2))
__b = rotate_point(__b, self.origin, math.radians(self.angle / 2))
__c = rotate_point(__c, self.origin, math.radians(self.angle / 2))
__d = rotate_point(__d, self.origin, math.radians(self.angle / 2))
# packing slot sides
slot_left_side_1 = (__b, __c)
slot_right_side_1 = (__a, __d)
# finding intersection point between slot sides and polygon face 1
right_inter = line_intersection(self.vectors[0], slot_right_side_1)
left_inter = line_intersection(self.vectors[0], slot_left_side_1)
# Manually ordering the points of the slot shape
output = [self.points[0]]
output.append(right_inter)
output.append(__a)
output.append(__a)
output.append(__b)
output.append(__b)
output.append(left_inter)
# index 7
# repeating the process radially for the number of faces.
for side in range(1, self.sides):
output.append(rotate_point(self.points[0], self.origin, math.radians(side * self.angle)))
output.append(rotate_point(right_inter, self.origin, math.radians(side * self.angle)))
output.append(rotate_point(__a, self.origin, math.radians(side *self.angle)))
output.append(rotate_point(__a, self.origin, math.radians(side *self.angle)))
output.append(rotate_point(__b, self.origin, math.radians(side *self.angle)))
output.append(rotate_point(__b, self.origin, math.radians(side *self.angle)))
output.append(rotate_point(left_inter, self.origin, math.radians(side * self.angle)))
# creating a vector list from the points list
self.output = list(zip(output, output[1:] + output[:1]))
# program test
# creating a random generated polygon
a = polygon(origin, sides, radius)
a.slot(material_thickness, slot_depth)
# creating a DXF document and adding slot output vectors
dxf_file_ = dxf_file("test.dxf")
a.get_vectors()
dxf_file_.add_vectors_dxf(a.output)