#######################
#-*- coding: utf-8 -*-


######## DM*
######## agruber@tugraz.at
######## library



################
######## basic library data and functions
################


import rhinoscriptsyntax as rs
import scriptcontext as sc


######## import
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
import RhinoPython.Host as _host
from datetime import datetime
import random
import time
import math
import os
from itertools import combinations
from itertools import permutations
from itertools import product
import System, System.DateTime
import scriptcontext

rs.UnitAbsoluteTolerance(tolerance=0.00001, in_model_units=True)


pi = math.pi
global timeX
timeX = time.time()




def setUp_hu_02( anzahl=64, rotateSqu=0 ):
    rCircle = random.uniform(4,12)
    aCube   = random.uniform(4,12)
    mCube   = [0,0,random.uniform(4,12)]
    mCircle = [ 0, 0, 0]
    anz = anzahl
    if anz < 4: anz=4
    anz -= anz%4
    vecRadial = [-rCircle*.5, -rCircle*.5, 0]
    coordsCir = []
    dAng = 360.0/anz
    #print anz, dAng, dAng*anz
    for i in range(anz):
        vec = rs.VectorRotate(vecRadial, dAng*i, [0,0,1] )
        coordsCir.append( vec)
    movCube = random.choice(coordsCir)
    #rs.AddLine(mCircle, mCube)
    coordsCub = []
    dA = aCube/(anz/4)
    
    for i in range( int(anz/4)+1 ):
        vec = [mCube[0]-aCube*0.5 + dA*i, mCube[1]-aCube*0.5, mCube[2]]
        coordsCub.append( vec)
    for vec in coordsCub[0:int(anz/4)]:
        vec= rs.VectorAdd(rs.VectorRotate(vec, 90, [0,0,1] ),[0,dA, 0])
        coordsCub.append( vec)
    for vec in coordsCub[1:int(anz/2)]:
        vec= rs.VectorRotate(vec, 180, [0,0,1] )
        coordsCub.append( vec)
    
    rota = 0
    rvec = [0,0,1]
    if rotateSqu:
        rota = random.randint(-90,90)
        rvec = [random.uniform(-0.1*rotateSqu,0.1*rotateSqu), random.uniform(-0.1*rotateSqu,0.1*rotateSqu), 1.00]
        for i,vec in enumerate(coordsCub):
            coordsCub[i] = rs.VectorRotate(vec, rota, rvec)
    movCube = rs.VectorSubtract(random.choice(coordsCir), random.choice(coordsCub))
    movCube = rs.VectorSubtract(coordsCir[0], coordsCub[0])
    movCube[2] = 0

    for i,vec in enumerate(coordsCub):
        pass
        coordsCub[i] = rs.VectorAdd(vec, movCube)
    if 1:
        print "    *** *********** *********** *** DM2_w25 / hu_02 / square_&_circle"
        print "    *** setUp_hu_02("+str(anzahl)+") returned 2 arrays with", anz, "pointCoords each: [coordsCir, coordsSqu]"
        print "    *** coordsSqu are rotated "+str(rota)+".0Â° @ axis [", round(rvec[0],2), ",",round(rvec[1],2),",", rvec[2],"]"
        print "    *** ********* *********** *** ************************* *****"
    return[coordsCir, coordsCub]


def textDots(coordList, strX="", justName=0):
    RDstate = rs.EnableRedraw(0)
    lis = []
    if len(coordList):
        for i, pt in enumerate(coordList):
            if not justName: 
                lis.append(rs.AddTextDot(str(i)+strX, pt))
            else:
                lis.append(rs.AddTextDot(strX, pt))
    else:
        print "***________no list > no textDots"
    rs.EnableRedraw(RDstate)
    return lis
    
######## get a point between two points
def pntInbetween( coord0, coord1, fac=.5 ) :
    vec = rs.VectorSubtract( coord1, coord0 )
    vec = rs.VectorScale( vec, fac )
    coord = rs.VectorAdd( coord0, vec )
    return coord

### experimental
def PointRadius(displayModeX=0, rad=3, styl=3,  verbose=0 ):
    '''
        arguments:
                displayModeX: int .. number of displayMode
                rad  = 3 : point radius
                styl = 3 : point style
                verbose : quasselig
                point style:
                    https://developer.rhino3d.com/api/rhinocommon/rhino.display.pointstyle
                    0 ControlPoint "square with center"
                    1 RoundControlPoint "round with center"
                    2 Simple "solid square"
                    3 RoundSimple "solid circle"
        Standard displayModes_numbers
        0 Wireframe
        1 Shaded
        2 Rendered
        3 Ghosted
        4 XRay
        5 Technical
        6 Artistic
        7 Pen
        8 Arctic
        9 Raytraced
        10 etc ! 
    '''
    display_modes = Rhino.Display.DisplayModeDescription.GetDisplayModes()
    if styl>12:
        print "!!! print nix style>12 > set_2 \"3\""
        styl = 3
    if styl==0: styx = Rhino.Display.PointStyle.ControlPoint
    if styl==1: styx = Rhino.Display.PointStyle.RoundControlPoint
    if styl==2: styx = Rhino.Display.PointStyle.Simple
    if styl==3: styx = Rhino.Display.PointStyle.RoundSimple
    if styl==4: styx = Rhino.Display.PointStyle.ActivePoint
    if styl==5: styx = Rhino.Display.PointStyle.RoundActivePoint
    if styl==6: styx = Rhino.Display.PointStyle.ArrowTip
    if styl==7: styx = Rhino.Display.PointStyle.Heart
    if styl==8: styx = Rhino.Display.PointStyle.Chevron
    if styl==9: styx = Rhino.Display.PointStyle.Triangle
    if styl==10: styx = Rhino.Display.PointStyle.X
    if styl==11: styx = Rhino.Display.PointStyle.Pin
    if styl==12: styx = Rhino.Display.PointStyle.Asterisk

    #print display_modes[displayModeX].EnglishName+"("+str(displayModeX)+") >> pointStyle", "\""+str(styx)+"\""
    if displayModeX != "all" and displayModeX <= len(Rhino.Display.DisplayModeDescription.GetDisplayModes()):
        selected_description = Rhino.Display.DisplayModeDescription.GetDisplayModes()[int(displayModeX)]
        selected_description.DisplayAttributes.PointRadius =  rad
        selected_description.DisplayAttributes.PointStyle = styx # Rhino.Display.PointStyle.Simple
        Rhino.Display.DisplayModeDescription.UpdateDisplayMode(selected_description)
        if 0 or verbose : print "*** style \""+(display_modes[int(displayModeX)].EnglishName+"\":::::::::::::: ")[0:15]+" PointRadius =", rad, "geaendert, danke Eszter & danke Andi fuer PointStyle = \""+str(styx)+"\""
    else:
        #if 0 or verbose : print "ALL"
        for displayModeX in range(len(display_modes)):
            selected_description = display_modes[displayModeX]
            selected_description.DisplayAttributes.PointRadius =  rad
            selected_description.DisplayAttributes.PointStyle = styx # Rhino.Display.PointStyle.Simple
            Rhino.Display.DisplayModeDescription.UpdateDisplayMode(selected_description)
            #if 0 or verbose : print "*** style \""+(display_modes[displayModeX].EnglishName+"\":::::::::::::: ")[0:15]+" PointRadius =", rad, "geaendert, danke Eszter & danke Andi fuer PointStyle = \""+str(styx)+"\""
    if 1:
        ###DISPLAY_MODE##
        #print displayModeX
        if isinstance(displayModeX, int) and int(displayModeX) < 11:
            selected_description = display_modes[int(displayModeX)]
        ###RADIUS POINTS###
        disX = displayModeX
        if verbose:
            print "PointStyle 0: square outline"
            print "PointStyle 1: circle outline"
            print "PointStyle 2: square solid"
            print "PointStyle 3: circle solid"
            print "PointStyle 4: square ActivePoint"
            print "PointStyle 5: round ActivePoint"
        for i, disX in enumerate(display_modes):
            english_name = disX.EnglishName
            english_name = english_name.translate(None, "_ -,.")
            if 0 or verbose:
                num = str(i)
                if i<10:num= " "+num
                print num+" = "+(str(english_name)[0:]+":::::::::::::::::")[0:13],
                print "pointRadius=", int(display_modes[i].DisplayAttributes.PointRadius),
                print "/ pointStyle =", display_modes[i].DisplayAttributes.PointStyle

def printDisplay(state=1, scale=100, thickness=500, color="Display"):
    rs.Command("_PrintDisplay State=Off _enter", 0)
    if state: 
        cmd = "_PrintDisplay State=On Color="+str(color)+" Scale="+str(scale)+" _enter"
        #print cmd
        rs.Command(cmd, 0)


global timeX
timeX = time.time()

def setTime():
    global timeX
    timeX = time.time()

def getTime(verbose=0):
    global timeX
    tim = float(time.time())
    tim -=  float(timeX)
    if verbose:
        print str(round(tim,2))+"s"
    return round(tim,0)

def preNull( val, sign="0", sollLen=1 ): # leading zero
    anz = sollLen-len(str(val))
    if anz>0:# and val < pow(10, anz):
        for i in range(anz): val = sign+str(val)
    return str(val)


######## very simple remapping of a value
def reMap(i, iMin, iMax, oMin, oMax, limit=0):
    inFac  = float(i-iMin)/float(iMax-iMin)# 
    outFac = (oMax-oMin)
    if limit and (oMin + outFac*inFac) < oMin:
        return oMin
    if limit and  (oMin + outFac*inFac) > oMax:
        return oMax
    return (oMin + outFac*inFac)
    
######## list mixxing  / diag
def permutate( list, num):
    return [ perm for perm in permutations(list, num) ]
    
def combinate( list, num):
    return [ comb for comb in combinations(list, num) ]


####################################################################
version = "'''  ver 20251010 by _diag 4 DM* @ I OI III @ TUGraz '''"

print     "'''''''''''''''''''''''''''''''''''''''''CC by-nc-sa '''"
print     "'''  DM_lib mini version imported in %ss            ''' \n%s" % (getTime(0), version) 
print     "''''''''''''''''''''''''''''''''''''''''''''''''''''''''"
####################################################################