############################
### diag @ IAM @ DM2_w25 ###
### hu_04 dmLodge_startUP_00
############################

##############################
import rhinoscriptsyntax as rs
import random, time, sys   ###
sys.path.append("P:/")     ###                  ### diag's path to DM_lib.py  .. please keep it !                                               
sys.path.append("P:/dx6419/dm2/")     ### *your* path to DM_lib.py                                            
sys.path.append("P:/WWW/dx6419/dm2/") ### *your* path to DM_lib.py                                            
sys.path.append("/Users/macpro/Desktop/DM2")    ### *your* path to DM_lib.py      
import DM_lib as dm        ###                  ### "dm" is alias for DM_lib / for adressing definitions etc in "DM_lib.py"
############################## reload( dm )


rs.UnitSystem(4)                                        # km = 5, meters = 4, cm = 3 etc
rs.ShowGrid(None, 0)                                    # grid > 0 = off
rs.ShowGridAxes(None, 1)                                # y/y/z axen display > 0/1 = off/on
rs.ViewDisplayMode(view=None, mode="wireframe")			# shadeMode fuer current view
rs.AppearanceColor(item=0, color=[230, 230, 230])       ### item=0 => backgroundColor [R,G,B] | 230/230/230 == lightgray
rs.Command("cplane w t enter", 0)						# cPlane World Top
dm.printDisplay(0)                                      # nomen est omen

rs.EnableRedraw(0)                                      ### 4_the_MACs: try 0/1 !
rs.UnselectAllObjects()
dm.newEmptyLayer( "Default")                            
dm.newEmptyLayer( "LODGE", [32, 32, 32] )
dm.newEmptyLayer( "LODGE::setUp",  [11,  11, 111] )    ### newEmtyLayer ist 'current'
dm.newEmptyLayer( "LODGE::crv", [200,  20, 20] )
dm.newEmptyLayer( "LODGE::pnt", [ 100,  100, 100] )
rs.Redraw()
wait = 1

def info():
    ##############################################
    """ LODGE
    Generate a small archetypal house, distorted along perspective algorithms
    A setup for the development of individual panels
    Inspired by
      Albrecht Duerer's "Underweysung" (1525)
      https://de.wikipedia.org/wiki/Perspektive#Geschichte
      https://en.wikipedia.org/wiki/Albrecht_Duerer
    And
      MVRDVs "Porterlodges for the National Park De Hoge Veluwe" (1996)
      https://mvrdv.com/projects/167/hoenderloo-lodge?photo=15877
    Parameters:
      p_width (float, optional): Approx. panel width in units
      l_dist (float, optional): Approx. length of the lodge in units
      d_dist (float, optional): Approx. depth of the lodge in units
      h_dist (float, optional): Approx. height of the lodge in units
      x_pos (float, optional): Move origin of the lodge in x
      y_pos (float, optional): Move origin of the lodge in y
      d_grid (boolean, optional): Fixed depth grid on the the small sides
      d_distord (boolean, optional): Distord basic section of the house
      demo (boolean, optional): Run demo to get an object
      verbose (int, optional): talk & sleep / Print and depict generation of the lodge
    Returns:
      return[0] = list[][][] of all panels, containing groups of 4 points
      return[1] = list[][][] of just the sleeve's panels
      return[2] = list[][][] of just the right section's panels
      return[3] = list[][][] of just the left section's panels
      return[4] = list[][][] of the sections, containing groups of 5 points
      return[5] = list[][] of all the cvs on the sleeve
      return[6] = list[][] of all the cvs on the right section
      return[7] = list[][] of all the cvs on the left section
    Example:
      allData = dm.getLodge( verbose=1000, demo=1 )
      panels = allData[0]
      panels_sleeve = allData[1] // sleeve ~= hull
      panels_right = allData[2]
      panels_left = allData[3]
        sections = allData[4]
        cvs_sleeve= allData[5]
        cvs_right= allData[6]
        cvs_left= allData[7]
    ### allData = dm.getLodge( p_width=1.2, l_dist=10, d_dist=8, h_dist=6, pos_x=0, pos_y=0, d_grid=0, d_distord=1, demo=0, verbose=0 )
    """


### exec whenever ##################################
dm.allLodgeData = dm.getLodge( demo=1, verbose=0 )      ### activate this to get a new set of data
allLodgeData    = dm.allLodgeData              ### this set of data is generated @ startUp (when DM_lib is loaded)
panels = allLodgeData[1]                   
####################################################    ### allLodgeData = [ panels, panels_sleeve, panels_right, panels_left, sections, cvs_sleeve, cvs_right, cvs_left ]

'''
' check setup - just visualization of setUp >> dont execute @ final version of homework <<                                      '
'''


wait = 0                                        ### wait some milliseconds => s.EOS rs.Sleep(..)

def jitterPoint(pt, max_shift=0.3):
    return (
        pt[0] + random.uniform(-max_shift, max_shift),                  #Zufallige kleine Verschiebung
        pt[1] + random.uniform(-max_shift, max_shift),
        pt[2] + random.uniform(-max_shift, max_shift)
    )

def drawDistortedQuad(panelPts, layers=3, distort=0.2, inner_lines=3):
    if not panelPts or len(panelPts) < 4:
        return

    p0, p1, p2, p3 = panelPts

    basePts = [jitterPoint(p, distort) for p in [p0, p1, p2, p3]]
    rs.AddCurve(basePts + [basePts[0]], 1)


    for i in range(1, layers + 1):               # Generate inner quads
        t = i / float(layers + 1)
        inner = []
        for p in basePts:
            cx = sum(pt[0] for pt in basePts) / 4.0
            cy = sum(pt[1] for pt in basePts) / 4.0
            cz = sum(pt[2] for pt in basePts) / 4.0
            inner.append((
                p[0] * (1 - t) + cx * t + random.uniform(-distort, distort) * 0.3,
                p[1] * (1 - t) + cy * t + random.uniform(-distort, distort) * 0.3,
                p[2] * (1 - t) + cz * t + random.uniform(-distort, distort) * 0.3
            ))
        rs.AddCurve(inner + [inner[0]], 1)


    for i in range(inner_lines):         # Add crossing inner lines for structure
        s = random.random() 
        e = random.random()
        a = rs.PointAdd(p0, rs.VectorScale(rs.VectorCreate(p1, p0), s))
        b = rs.PointAdd(p3, rs.VectorScale(rs.VectorCreate(p2, p3), e))
        a, b = jitterPoint(a, 0.1), jitterPoint(b, 0.1)
        rs.AddCurve([a, b], 1)


def connectDistortedPanels(panelA, panelB, layers=2, distort=0.3):    
    #Connect two quads with slightly distorted line meshes
    if not panelA or not panelB or len(panelA) < 4 or len(panelB) < 4:
        return

    for i in range(4):
        pA1 = jitterPoint(panelA[i], distort)
        pA2 = jitterPoint(panelA[(i + 1) % 4], distort)
        pB1 = jitterPoint(panelB[i], distort)
        pB2 = jitterPoint(panelB[(i + 1) % 4], distort)

        for j in range(1, layers + 1):
            t = j / float(layers + 1)
            sA = rs.PointAdd(pA1, rs.VectorScale(rs.VectorCreate(pB1, pA1), t))
            sB = rs.PointAdd(pA2, rs.VectorScale(rs.VectorCreate(pB2, pA2), t))
            sA, sB = jitterPoint(sA, distort * 0.3), jitterPoint(sB, distort * 0.3)
            rs.AddCurve([sA, sB], 1)
'''              
' end check setup                                                                                                                   ' 
'''


#######################################
################ HERE YOU GO AS YOU GO:
rs.CurrentLayer("LODGE")                          ### or LODGE::... sublayer !

for panel in panels:
    drawDistortedQuad(panel, layers=3, distort=0.15, inner_lines=4)

rs.CurrentLayer("LODGE::crv")
for i in range(len(panels) - 1):
    connectDistortedPanels(panels[i], panels[i + 1], layers=2, distort=0.2)



########################## HERE YOU END
#######################################


########## EOS / EndOfScript
rs.EnableRedraw(1)          ### 4_the_MACs
#dm.eDup( 1 )               ### delete duplicate objects 
dm.printDisplay(1)
dm.zA( 0.9 )
rs.CurrentLayer("Default")
if wait:
    rs.Sleep( wait )
    rs.LayerVisible("LODGE::setUp", 0)
