import py2rhino as p2r
#===============================================================================
# Parameters
#===============================================================================
sec1 = p2r.obj.NurbsSurface("7f72bdb7-ef4f-4b09-a7ba-6b9e3458a0b5")
sec2 = p2r.obj.NurbsSurface("4c136d1d-dbee-4a58-90fb-1371a480269d")
sec3 = p2r.obj.NurbsSurface("9f5599dd-c9a0-49a0-be23-8857372ed973")
sec4 = p2r.obj.NurbsSurface("ab8125c7-4524-4716-8cc1-ffb03b62e1b6")
sec5 = p2r.obj.NurbsSurface("44002bb6-e116-402b-b193-893b8e5902c9")
sec6 = p2r.obj.NurbsSurface("4514f287-4322-426f-b2d7-faf5e7de6977")
lower = p2r.obj.NurbsSurface("21399d5b-427a-43db-84a3-7f76b23d4b16")
upper = p2r.obj.NurbsSurface("19ce0362-2971-4536-a943-1d3185ac1416")
#===============================================================================
# Functions
#===============================================================================
def draw_line_between_crv(crv):
    start = crv.prop.start_pnt()
    end = crv.prop.end_pnt()
    line = p2r.obj.Line.create(start, end)
    return line
#------------------------------------------------------------------------------
def loft_curve(crv):
    line = draw_line_between_crv(crv)
    srf = p2r.obj.NurbsSurface.create_by_loft( (line, crv) )
    return srf
#------------------------------------------------------------------------------
def generate_roofs():
    num_sections = len(lower_secs)
    num_segments = num_sections - 1   
   
    roofs = []
    for sec_num in range(num_segments):
        roof = p2r.obj.NurbsSurface.create_by_loft( (lower_secs[sec_num], upper_secs[sec_num + 1]) )
        roofs.append(roof)
       
    return roofs
#------------------------------------------------------------------------------
def generate_shade(lower_roof, upper_roof, num_v):
    points_shade_edge = []
    points_shade_edge_projected = []
   
    u_domain_lower = lower_roof.prop.domain(0) #(0, 12.2)
    max_u_param_of_lower = u_domain_lower[1]
   
    u_domain_upper = upper_roof.prop.domain(0) #(0, 12.2)
    max_u_param_of_upper = u_domain_upper[1]
   
    v_domain_lower = lower_roof.prop.domain(1)
    v_domain_upper = upper_roof.prop.domain(1)
   
    v_range_lower = v_domain_lower[1] - v_domain_lower[0]
    v_range_upper = v_domain_upper[1] - v_domain_upper[0]
   
    v_lower_step = v_range_lower / num_v
    v_upper_step = v_range_upper / num_v
   
    for point_num in range(num_v + 1):
       
        param_lower = (max_u_param_of_lower, v_lower_step * point_num)
        param_upper = (0, v_upper_step * point_num)
        param_upper_2 = (max_u_param_of_upper, v_upper_step * point_num)
       
        point_lower = lower_roof.eval.evaluate(param_lower)
        point_upper = upper_roof.eval.evaluate(param_upper)
        point_upper_2 = upper_roof.eval.evaluate(param_upper_2)
        dist_vec = p2r.util.vector.create(point_lower, point_upper)
        dist = p2r.util.vector.length(dist_vec)
       
        dir_vec = p2r.util.vector.create(point_upper, point_upper_2)
        dir_vec = p2r.util.vector.unitize(dir_vec)
        dir_vec = p2r.util.vector.scale(dir_vec, dist)
       
        point_projected = p2r.util.point.add(point_upper, dir_vec)
       
        points_shade_edge.append(point_upper)
        points_shade_edge_projected.append(point_projected)
   
    pl1 = p2r.obj.Polyline.create(points_shade_edge)
    pl2 = p2r.obj.Polyline.create(points_shade_edge_projected)
    p2r.obj.NurbsSurface.create_by_loft( (pl1, pl2) )
   
#------------------------------------------------------------------------------
def generate_window(lower_roof, upper_roof, num_v):
   
    points_lower = []
    points_upper = []
   
    u_domain_lower = lower_roof.prop.domain(0) #(0, 12.2)
    u_param_of_lower = u_domain_lower[1]
   
    v_domain_lower = lower_roof.prop.domain(1)
    v_domain_upper = upper_roof.prop.domain(1)
   
    v_range_lower = v_domain_lower[1] - v_domain_lower[0]
    v_range_upper = v_domain_upper[1] - v_domain_upper[0]
   
    v_lower_step = v_range_lower / num_v
    v_upper_step = v_range_upper / num_v
   
    for point_num in range(num_v + 1):
       
        param_lower = (u_param_of_lower, v_lower_step * point_num)
        param_upper = (0, v_upper_step * point_num)
       
        point_lower = lower_roof.eval.evaluate(param_lower)
        points_lower.append(point_lower)
   
        point_upper = upper_roof.eval.evaluate(param_upper)
        points_upper.append(point_upper)
       
    pl1 = p2r.obj.Polyline.create(points_lower)
    pl2 = p2r.obj.Polyline.create(points_upper)
    p2r.obj.NurbsSurface.create_by_loft( (pl1, pl2) )
   
#------------------------------------------------------------------------------
def generate_windows(roofs, num_v):
    windows = []
    for roof_num in range(len(roofs) - 1):
        lower_roof = roofs[roof_num]
        upper_roof = roofs[roof_num + 1]
        generate_window(lower_roof,upper_roof, num_v)
        generate_shade(lower_roof,upper_roof, num_v)
    start_window = loft_curve(lower_secs[0])
    end_window = loft_curve(upper_secs[-1])
   
    windows.append(start_window)
    windows.append(end_window)
   
    return windows
#------------------------------------------------------------------------------
def generate_panels(roof, num_u, num_v):
   
    domain_u = roof.prop.domain(0)
    u_range = domain_u[1] - domain_u[0]
    u_step = u_range / num_u
    domain_v = roof.prop.domain(1)
    v_range = domain_v[1] - domain_v[0]
    v_step = v_range / num_v
   
    for v_panel_num in range(num_v):
        v_param = v_panel_num * v_step
       
        for u_panel_num in range(num_u):
           
            u_param = u_panel_num * u_step
           
            #parameters
            param_1 = (u_param,           v_param)
            param_2 = (param_1[0]+u_step, param_1[1])
            param_3 = (param_1[0]+u_step, param_1[1]+v_step)
            param_4 = (param_1[0]       , param_1[1]+v_step)           
           
            #points
            p1 = roof.eval.evaluate(param_1)
            p2 = roof.eval.evaluate(param_2)  
            p3 = roof.eval.evaluate(param_3)
            p4 = roof.eval.evaluate(param_4)         
           
            #draw a panel
            p2r.obj.NurbsSurface.create_by_corner_pnts( (p1, p2, p3, p4) )
#------------------------------------------------------------------------------
def generate_all_panels(roofs, num_u, num_v):
    for roof in roofs:
        generate_panels(roof, num_u, num_v)
        roof.modf.delete()
       
#===============================================================================
# Main Script
#===============================================================================
sec_list = (sec1, sec2, sec3, sec4, sec5, sec6)
lower_secs = []
for sec in sec_list:
    sec_crv = lower.func.intersect_2_srfs(sec, create=True)
    lower_secs.append(sec_crv[0])
   
upper_secs = []
for sec in sec_list:
    sec_crv = upper.func.intersect_2_srfs(sec, create=True)
    upper_secs.append(sec_crv[0])
roofs = generate_roofs()
windows = generate_windows(roofs, 6)
generate_all_panels(roofs, 2, 6)
print "done"