import math
def rotateToMatchVector(part,vecx,vecy):
length = sqrt(vecx*vecx + vecy*vecy)
if (length == 0):
return part
part = replace(part,'X','((COSANGLE)*X+(SINANGLE)*y)')
part = replace(part,'Y','(-(SINANGLE)*X+(COSANGLE)*y)')
part = replace(part,'y','Y')
part = replace(part,'COSANGLE',str(vecx/length))
part = replace(part,'SINANGLE',str(vecy/length))
return part
def lineWithThickness(x0,y0,x1,y1,w):
length = sqrt((y1-y0)*(y1-y0) + (x1-x0)*(x1-x0))
line = rectangle(0,length,-w/2,w/2)
line = rotateToMatchVector(line,x1-x0,y1-y0)
line = move(line,x0,y0)
return line
def getPointOnLine(point0,point1,distance):
x0 = point0.x
y0 = point0.y
z0 = point0.z
x1 = point1.x
y1 = point1.y
z1 = point1.z
length = sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0))
xdiff = x1-x0
ydiff = y1-y0
x = xdiff*distance/length
y = ydiff*distance/length
x = x + x0
y = y + y0
return point(x,y,z0)
def getPointInDirection(point0,angle,distance):
angle = positiveAngle(angle)
angle = angle*pi/180
x0 = point0.x
y0 = point0.y
z0 = point0.z
x = distance*cos(angle)
y = distance*sin(angle)
x = x + x0
y = y + y0
return point(x,y,z0)
def arc(centerX,centerY,innerRad,outerRad,startAngle,endAngle):
outer = circle(0,0,outerRad)
inner = circle(0,0,innerRad)
block1 = rectangle(-outerRad,outerRad,-outerRad,0)
block2 = rectangle(-outerRad,outerRad,0,outerRad)
block1 = rotate(block1,startAngle)
block2 = rotate(block2,endAngle)
part = subtract(outer,inner)
part = subtract(part,block1)
part = subtract(part,block2)
part = move(part,centerX,centerY)
return part
def positiveAngle(angle):
return (angle - 360 * floor(angle/360))
def polyline(width,cornerRadius,*points):
part = ""
previousEndPoint = None
previousLineAngle = None
for i in range(1,len(points)):
x0 = points[i-1].x
y0 = points[i-1].y
z0 = points[i-1].z
x1 = points[i].x
y1 = points[i].y
z1 = points[i].z
if (i==1):
omitFromStart = -width/2
else:
omitFromStart = cornerRadius + width/2
if (i == len(points)-1):
omitFromEnd = -width/2
else:
omitFromEnd = cornerRadius + width/2
startPoint = getPointOnLine(points[i-1],points[i],omitFromStart)
endPoint = getPointOnLine(points[i],points[i-1],omitFromEnd)
if (i==1):
part = lineWithThickness(startPoint.x,startPoint.y,endPoint.x,endPoint.y,width)
else:
part = add(part,lineWithThickness(startPoint.x,startPoint.y,endPoint.x,endPoint.y,width))
nextLineAngle = (math.atan2(y1-y0,x1-x0))*180/pi
if (previousLineAngle != None):
nextLineAngle = positiveAngle(nextLineAngle)
previousLineAngle = positiveAngle(previousLineAngle)
if (positiveAngle(nextLineAngle - previousLineAngle) < 180):
arcCenter = getPointInDirection(previousEndPoint,previousLineAngle+90,cornerRadius + width/2)
startAngle = previousLineAngle-90
endAngle = nextLineAngle-90
else:
arcCenter = getPointInDirection(previousEndPoint,previousLineAngle-90,cornerRadius + width/2)
startAngle = nextLineAngle+90
endAngle = previousLineAngle+90
part = add(part,arc(arcCenter.x,arcCenter.y,cornerRadius,cornerRadius+width,startAngle,endAngle))
previousLineAngle = nextLineAngle
previousEndPoint = endPoint
return part
def wire(pcb,width,*points):
newpoints = [points[0]]
for i in range(1,len(points)):
x0 = points[i-1].x
y0 = points[i-1].y
z0 = points[i-1].z
x1 = points[i].x
y1 = points[i].y
z1 = points[i].z
if (x0 != x1 and y0 != y1):
newpoints.append(point(x1,y0,z0))
newpoints.append(point(x1,y1,z0))
pcb.board = add(pcb.board,polyline(width,width,*newpoints))
return pcb