###################################
### DM2_w25 # AGruber@tugraz.at ###
### ue_08  surface manipulation ###
###################################


##############################
import rhinoscriptsyntax as rs
import random, time, sys   ###
sys.path.append("P:/")     ###
sys.path.append("P:/WWW/dx6419/dm2/") ### *your* path to DM_lib.py                                            
import DM_lib as dm        ### 
############################## dm.reload_lib(dm)      

rs.UnitSystem(4)                                            # km = 5, meters = 4, cm = 3 etc
rs.ShowGrid(None, False)                                    # grid > 0 = off
rs.ShowGridAxes(None, False)                                # y/y/z axen display > 0/1 = off/on
#rs.ViewDisplayMode(rs.CurrentView(), "shaded")
rs.Command("cplane w t enter", False)						# cPlane World Top
dm.PointRadius(displayModeX=0, rad=3, styl=3)
dm.printDisplay(False)                                      # nomen est omen
rs.EnableRedraw(False)

###############################################
######## need file "dachstein_surface_demo.3dm"
###############################################


dm.newEmptyLayer("DEMO::pnts", [100,0,200])
rs.Redraw()

srfs = rs.ObjectsByName("040_*", 0)             ### filter by name
for srf in srfs:
    print rs.ObjectName( srf )


#rs.HideObjects( srfs[-2:] )
print "flip", rs.FlipSurface( srfs[1], 0)

coords = dm.getSurfacePoints( srfs[1] )         ### get coords of surface-Control-points !
print "len(coords)", len(coords)

############
coordsSorted = sorted(coords, key=lambda sKey: sKey[2]) ### that's essential ! (sort by z_coord)
############



#rs.AddPoints( coords )
#rs.AddCurve( coordsSorted, 3)
minZ = coordsSorted[0][2]
maxZ = coordsSorted[-1][2] ## hoher dachstein
print minZ, maxZ
linX = rs.AddLine( coordsSorted[0],  coordsSorted[-1] )
linY = rs.AddLine( coordsSorted[-1], coordsSorted[-2] )



######## filter sorted coordsLists / by z_value / by (projected !) distance
if 0: 
    dachsteinGipfel = coordsSorted[-1]
    coordsDachstein = [ cor for cor in coordsSorted if rs.Distance(cor, coordsSorted[-1]) < 200.0 ]
    #coordsDachstein = [ cor for cor in coordsSorted if cor[2] > maxZ-200 and rs.Distance(dm.pnt2XY0(cor), dm.pnt2XY0(coordsSorted[-1])) < 200.0 ]
    coordsRest = [ cor for cor in coordsSorted if cor not in coordsDachstein ]
    
    rs.AddPoints( coordsDachstein )
    #rs.AddPoints( coordsRest[0:300] )
    #rs.AddPoints( coordsRest[-100:] )
    
    coordsRest = sorted([ cor for cor in coordsSorted if cor not in coordsDachstein ], key=lambda sKey: sKey[2])
    mitterspitz = coordsRest[-1]
    
    rs.AddLine( dachsteinGipfel, mitterspitz )

######## manipulate surfaces .. surface"Grips" || ObjectGripLocations ||
if 0: 
    for i, cor in enumerate(coords): ## unsorted !
        #if cor[2] > maxZ-200:
        if rs.Distance(dm.pnt2XY0(cor), dm.pnt2XY0(coordsSorted[-1])) < 200.0:
            coords[i][2] =  maxZ-600
    if 1: ### so it goes
        rs.EnableObjectGrips(srfs[1], 1)
        rs.ObjectGripLocations( srfs[1], coords)
        rs.EnableObjectGrips(srfs[1], 0)
    else: ### smarter > library !
        dm.setSurfacePoints( srfs[1], coords )


######## farbverlauf via reMap(..) 
if 0: 
    for i,cor in enumerate(coordsSorted[0:]):
        zVal = cor[2]
        ### reMap( value_2_remap, in_Min, in_Max, out_Min, out_Max )
        col = dm.reMap(zVal, coordsSorted[0][2], coordsSorted[-1][2], 0, 255, limit=1) ### get newest library !!!
        #col = int(col)
        rs.ObjectColor( rs.AddPoint( cor ), [col, 200, col] )
        if i%2000==0:
            print int(zVal), [col, 100, col]
            rs.Redraw()



######## surface closest point
if 1:  
    rs.ViewDisplayMode(view=None, mode="wireframe")
    dm.newEmptyLayer("DEMO::crvs", [10,10,150])
    rs.ZoomBoundingBox(rs.BoundingBox(srfs[1]))
    coords = rs.DivideCurve(linX, 22, True)
    coordsU = []
    for cor in coords:
        dm.esc() ### stop/break executing
        params = rs.SurfaceClosestPoint(srfs[1], cor) ### returns: list(number, number): The U,V parameters of the closest point on the surface 
        # print params
        pntX = rs.EvaluateSurface(srfs[1], *params)
        rs.AddLine( cor, pntX )
        coordsU.append(pntX)
        if len(coordsU)>1:
            rs.AddLine( coordsU[-2], coordsU[-1] )
            rs.AddSrfPt( [cor, coordsU[-1], coordsU[-2]] )
        rs.Redraw()
    #rs.AddCurve( coordsU, 1)
    rs.ViewDisplayMode(view=None, mode="rendered")


########## EOS / EndOfScript
rs.EnableRedraw(True)      ### 4_the_MACs
dm.eDup(1)                 ### delete duplicate objects 
dm.printDisplay(state=True, scale=1000)
#dm.zA( 0.9 )
dm.newEmptyLayer("Default")

#################################################
# https://de.wikipedia.org/wiki/Schartenh%C3%B6he
# alpen: 100-300m
# 4_tausender: 30m lt. UIAA (Union Internationale des Associations d'Alpinisme)
# hymalaya: 500m