from koko.lib.shapes import *
from numpy import *

def filleted_rectangle(x0,x1,y0,y1,r):
    rect = rectangle(x0,x1,y0,y1)
    rect = rect - (rectangle(x0,x0+r,y0,y0+r) - circle(x0+r,y0+r,r))
    rect =  rect - (rectangle(x0,x0+r,y1-r,y1) - circle(x0+r,y1-r,r))
    rect =  rect - (rectangle(x1-r,x1,y0,y0+r) - circle(x1-r,y0+r,r))
    rect =  rect - (rectangle(x1-r,x1,y1-r,y1) - circle(x1-r,y1-r,r))
    return rect

def edge(p0,p1,t):
    l = sqrt((p1[0]-p0[0])**2 + (p1[1]-p0[1])**2)
    a = atan2((p1[1]-p0[1]),(p1[0]-p0[0]))
    r = filleted_rectangle(-.5*t,l+.5*t,-.5*t,.5*t,.5*t)
    r = rotate(r,180*a/pi)
    r = move(r,p0[0],p0[1])
    return r

def sharp_edge(p0,p1,t):
    l = sqrt((p1[0]-p0[0])**2 + (p1[1]-p0[1])**2)
    a = atan2((p1[1]-p0[1]),(p1[0]-p0[0]))
    r = rectangle(0.,l,-.5*t,.5*t)
    r = rotate(r,180*a/pi)
    r = move(r,p0[0],p0[1])
    return r

def D_1206(x,y,r=0):
   #
   # 1206 diode
   #
    pad_1206 = rectangle(-.032,.032,-.034,.034)

    shape = move(pad_1206,-.06,0)
    shape += move(pad_1206,.06,0)
    shape = rotate(shape,r)
    shape = move(shape,x,y)
    rad = r*pi/180.
    pads = array([[-.055*cos(rad)+x,-.055*sin(rad)+y],[.055*cos(rad)+x,.055*sin(rad)+y]])
    return shape,pads

def diode_edge(p0,p1,t):
    mid_x = .5*(p0[0]+p1[0])
    mid_y = .5*(p0[1]+p1[1])
    a = atan2((p1[1]-p0[1]),(p1[0]-p0[0]))
    a = 180.*a/pi
    diode = D_1206(mid_x,mid_y,a)
    return sharp_edge(p0,diode[1][0],t) + diode[0] + sharp_edge(diode[1][1],p1,t)

#points
t = array([
    [6,60],
    [11,59],
    [15,57],
    [19,54],

    [5,53], 
    [10,52],
    [15,50],
    [20,48],

    [4,45],
    [10,45],
    [16,43],
    [21,43],

    [6,38],
    [11,38],
    [16,37],
    [21,37],

    [10,30],
    [18,30],
    [10,22],
    [16,22],

    [9,15],
    [16,15],
    [8,8],
    [15,8]])
t = t/5.9  #scale factor to my foot

#connectivity
edges_x = array([
    [0,1],
    [1,2],
    [2,3],

    [4,5],
    [5,6],
    [6,7],

    [8,9],
    [9,10],
    [10,11],

    [12,13],
    [13,14],
    [14,15],

    [16,17],
    [17,19],
    [18,19],

    [20,21],
    [23,21],
    [22,23]
])
edges_y = array([
    [0,4],
    [1,5],
    [2,6],
    [3,7],

    [4,8],
    [5,9],
    [6,10],
    [7,11],

    [8,12],
    [9,13],
    [10,14],
    [11,15],

    [12,16],
    [13,18,.3],#here we need some jogging
    [14,19,-.3],
    [15,17],

    [16,20,-.3],
    [17,21,.3],
    [18,22,.5],
    [19,23,-.4]
])
def instance(g,a):
    result = 0
    for x in a:
        result += move(g,x[0],x[1])
    return result   
def make_array(pad):
    return instance(pad,t)
def make_edges_x(d):
    ee = 0
    for e in edges_x:
        if len(e)==2:
            ee += edge(t[e[0]],t[e[1]],d)
        elif len(e)==3:
            p = [e[2]+.5*(t[e[0]][0] + t[e[1]][0]), .5*(t[e[0]][1] + t[e[1]][1])]
            ee += edge(t[e[0]],p,d)
            ee += edge(p,t[e[1]],d)
    return ee
def make_edges_y(d):
    ee = 0
    for e in edges_y:
        if len(e)==2:
            ee += edge(t[e[0]],t[e[1]],d)
        elif len(e)==3:
            p = [e[2]+.5*(t[e[0]][0] + t[e[1]][0]), .5*(t[e[0]][1] + t[e[1]][1])]
            ee += edge(t[e[0]],p,d)
            ee += edge(p,t[e[1]],d)
    return ee
def make_diode_edges_y(d):
    ee = 0
    for e in edges_y:
        if len(e)==2:
            ee += diode_edge(t[e[0]],t[e[1]],d)
        elif len(e)==3:
            p = [e[2]+.5*(t[e[0]][0] + t[e[1]][0]), .5*(t[e[0]][1] + t[e[1]][1])]
            ee += diode_edge(t[e[0]],p,d)
            ee += edge(p,t[e[1]],d)
    return ee
def make_paths(a,t):
    ee = 0
    for row in a:
        for i in range(len(row)-1):
            ee += edge(row[i],row[i+1],t)
    return ee

pad_d = .5
fil = .08
offset = .2
trace_d = .1
solder_d = .1
marker_d = .25
layer = 0 #0 for x, 1 for y

pad = filleted_rectangle(-.5*pad_d,.5*pad_d,-.5*pad_d,.5*pad_d,fil)
pads = make_array(pad)

paper = filleted_rectangle(-.5*pad_d-offset,.5*pad_d+offset,-.5*pad_d-offset,.5*pad_d+offset,fil+offset)
paper = make_array(paper)
paper += make_edges_x(offset+trace_d) + make_edges_y(offset+trace_d)

line_x = make_edges_x(trace_d)

line_y = make_diode_edges_y(trace_d)
j = rectangle(-trace_d,trace_d,-trace_d,trace_d)
jya = array([
    [[1.5,.8],[.95,1.],[.95,1.7],t[-4]],
    [[1.8,.8],t[-2]],
    [[2.4,.8],t[-1]],
    [[2.7,.8],[2.95,1.],[2.95,1.7],t[-3]],
    [[2.1,.8],[2.1,1.4]]
    ])
jy = make_paths(jya,trace_d)
jy += instance(j,[jya[0][0],jya[1][0],jya[2][0],jya[3][0],jya[4][0]])
line_y += jy

#jxa = array([
#    [[1.1,.8],[.8,1.0],[.9,3.8],[1.2,5.2],[.6,6.2],t[8]],
#    [[1.6,.8],[1.,1.1],[1.1,3.8],[1.35,5.2],t[12]],
#    [[1.9,.8],t[-1]],
#    [[2.2,.8],[2.35,1.],[2.85,1.],[3.05,2.2],[3.05,3.2],t[-5]],
#    [[2.7,.8],[3.15,1.],[3.15,1.8],t[3]],
#    [[3.,.8],[3.3,1.],[3.3,1.8],t[7]]
#    ])
jxa = array([
    [[1.2,.9]],
    [[1.5,.9]],
    [[1.8,.9],[1.8,1.3],t[-2]],
    [[2.1,.9]],
    [[2.4,.9]],
    [[2.7,.9]]
    ])
jx = make_paths(jxa,trace_d)
jx += instance(j,[jxa[0][0],jxa[1][0],jxa[2][0],jxa[3][0],jxa[4][0],jxa[5][0]])
line_x += jx

paper += make_paths(jxa,trace_d+offset)
paper += make_paths(jya,trace_d+offset)
jp = filleted_rectangle(-trace_d-.5*offset,trace_d+.5*offset,-trace_d-.5*offset,trace_d+offset,.5*trace_d)
paper += instance(jp,[jxa[0][0],jxa[1][0],jxa[2][0],jxa[3][0],jxa[4][0],jxa[5][0]])



show = 'x'
if show == "x":
    show_line = line_x
elif show == "y":
    show_line = line_y

shield = filleted_rectangle(-.5*pad_d-.5*offset,.5*pad_d+.5*offset,-.5*pad_d-.5*offset,.5*pad_d+.5*offset,fil+offset)
shield = make_array(shield)
shield += make_edges_x(.5*offset+trace_d) + make_edges_y(.5*offset+trace_d)

output = 'all'
output = 'paper'
#output = 'x'
#output = 'y'
#output = 'shield'
#output = 'silicone'

if output == 'all':
    cad.type = 'RGB'
    cad.function = color(white,pads) + color(brown,paper) + color(green,show_line) + color(red,shield-pads-line_x-line_y)
if output == 'paper':
    cad.function = paper
if output == 'x':
    cad.function = pads + line_x
if output == 'y':
    cad.function = pads + line_y
if output == 'shield':
    cad.function = shield
if output == 'silicone':
    cad.function = pad

print (t[1][1]+1)*25.4
xmax = t[3][0]+1.

#mirroring?
cad.function = reflect_x(cad.function,.5*xmax)

# Render boundaries
cad.xmin = 0.
cad.xmax = t[3][0]+1.
cad.ymin = 0.
cad.ymax = t[1][1]+1.
cad.mm_per_unit = 25.4 # inch units