################################################
### Lukas Schmelzer Gruppe Gruber 1          ###
### hu_02 connect circle+square with springs ###
################################################


##############################
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:/TUGonlineUsernam/dm2/")     ### *your* path to DM_lib.py                                            
sys.path.append("P:/WWW/lukschme/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.ShowGrid(show=0)
rs.ShowGridAxes(show=0)
rs.ViewDisplayMode(mode="Wireframe")
rs.EnableRedraw(0)

dm.PointRadius(displayModeX=0, rad=2, styl=3)                   ### displayModeX=0="Wireframe" / rad=size of points / styl=pointStyle (try 0..5) / default 3, 3
dm.printDisplay(state=1, scale=0.2, thickness=1, color="Display") ### state=0/1 = off/on / for showing printWidth etc

rs.DeleteObjects(rs.AllObjects())

### BASIC SETUP / mandatory input:
### return_value of definition "dm.setUp_hu_02(..)" is 1 array containing 2 coord_arrays: [ [coordsCir], [coordsSqu] ] (circle & square)
### anzahl == number of coords: range from 8 to 1001 / 4*250 / default = 4*32 
### rotateSqu .. rotation of square_coords: may be set to/try (0, 0)..(-90,90) .. etc / default = (-90, 90)
allCoords = dm.setUp_hu_02( anzahl=4*24,  rotateSqu=random.uniform(-90,90) )
coordsCir=allCoords[0]
coordsSqu=allCoords[1]

##### check setup - just visualization of coords
##### don't execute  @ final version of homework
if 0: ### 0 for *your* final version !
    if 1:
        rs.AddPoints( coordsCir )
        rs.AddPoints( coordsSqu )
    if 0:
        rs.ObjectColor(dm.textDots(coordsCir), [111,0,11])
        rs.ObjectColor(dm.textDots(coordsSqu), [11,0,111])
    if 1:
        rs.AddCurve( coordsCir, 1)
        rs.AddCurve( coordsSqu, 1)
        for i in range( len(coordsSqu) ):
            p0  = coordsCir[i]
            p1  = coordsSqu[i]
            lin = rs.AddLine(p0, p1)
            rs.ObjectColor(lin, [222*(i!=0), 22*(i!=0), 222])
            rs.ObjectPrintWidth( lin, 1.0*(i==0) )
##### end check setup

#######################################
################ HERE YOU GO AS YOU GO:
    
anzahl   = len(coordsSqu) ### anzahl der Punkte des Quadrats
print ("Anzahl Punkte Square =", anzahl) ###Visualisierung im Interpreter


### Verbindung der Punkte vom Square zum Circle in Punkt fuer Punkt abfolge
allLines = [] ### leeres array
for i in range(anzahl):         ### Fuer jeden Punkt am Square
    p0 = coordsCir[i]           ### Anfangspunkt-Koordinaten
    p1 = coordsSqu[i]           ### Endpunkt-Koordinaten
    lin = rs.AddLine( p0, p1 )  ### rs.Addline generiert Linie und schreibt die Parameter der Linie auf lin
    allLines.append( lin )      ### die ID 'lin' an array allLines anhaengen
    rs.ZoomExtents()            ### Rauszoomen
    rs.Redraw()                 ### Nachzeichnen so das man es im Rhino sieht --> Nicht sprunghaft Ergebnis da



### Grenzlinien um Square und Circle
circle_line = rs.AddCurve( coordsCir, 1 )                  ### Eine Kurve entlang der Koordinaten vom Circle und dieser einer Var zuweisen
rs.ObjectPrintWidth( rs.AllObjects()[0], 0.5 )             ### Dickere Linie machen
square_line = rs.AddCurve( coordsSqu, 1 )                  ### Gleiches fuer Square nur mit Farbwahl je nach Winkel (<45=Gruen;>45=Rot)
angle_Sq_Ci = rs.Angle2(circle_line, square_line)[0]             ### Angle2 berechnet winkel von 2 Kurven
print("Rotation of square relative to circle =", angle_Sq_Ci)    ### Ausgabe des Winkels
if angle_Sq_Ci > 45:
    rs.ObjectColor( rs.AllObjects()[0], [255,0,0])         ### rs.AllObjects()[0] == zuletzt generiertes object
else:
        rs.ObjectColor( rs.AllObjects()[0], [0,255,0])
rs.ObjectPrintWidth( rs.AllObjects()[0], 0.5 )      




# Array deklaration
half_points = []    # store midpoint coords


#Mittelpunkt einzeichnen
for lin in allLines:
    # get midpoint coordinate
    half_point = rs.CurveMidPoint(lin)              ### Mittelpunkt herausfinden
    half_points.append(half_point)                  ### Mittelpunkt an Array anhaengen
    rs.AddPoint(half_point)                         ### Punkt zeichnen

#Trennen der Linien in der Mitte
    closest_point = rs.CurveClosestPoint(lin, half_point)   ### Hatte probleme mit SplitCurve, da anscheinend manchmal die Punkte nich genau auf der Linie sind und dann ist der Befehl nicht ausfuehrbar
    new_curves = rs.SplitCurve(lin, closest_point)      ### Oberer Befehl gibt naehesten Punkt zurueck mit welchem ich die Linie nun splitten kann
                                                            ### Split curve gibt mir eine Liste mit den neuen Kurven die durch das splitten entstanden sind, diese werden auf die Var new_curves geschrieben

#Eine Haelfte behalten die andere loeschen
    half_curve = new_curves[1]                      ### zweite Haelfte behalten und auf neue Var schreiben, da zweiter Eintrag von .SplitCurves
    rs.DeleteObject(new_curves[0])                  ### Loeschen der ersten Haelfte

#Start und Endpunkte der Haelften auf Vars schreiben
    start_point = rs.CurveStartPoint(half_curve)
    end_point = rs.CurveEndPoint(half_curve)

#Aktivieren wenn man die zweite Haelfte auch loeschen will
    if 0:
        rs.DeleteObject(half_curve)

#Erstellen der interpolierten Punkte fuer die geschwungene Linie
    num_points = 10                  ### Anzahl der Zwischenpunkte definieren
    points = [start_point]          ### Punkte Array mit Anfangspunkt anfangen lassen
    for i in range(num_points):     ### Schleife zum verteilen der Punkte entlang der Linie
        factor = i / float(num_points)  ### Faktor zum skalieren des Vektors damit man zb bei 10 Punkten einen Faktor von 0.1 0.2 0.3... usw erhaelt
        #print ("Faktor: ", factor)
        new_vector = rs.VectorCreate(end_point, start_point)      ### Neuen Vektor zwischen Start- und Endpunkt erstellen
        new_scaled_vector = rs.VectorScale(new_vector, factor)    ### Den neuen Vektor skalieren um die Punkte verteilt am Vektor zu erhalten
        new_point = rs.PointAdd(start_point, new_scaled_vector)   ### Neue Punkte immer vom Ende des Vektors erhalten
        if 0:
            rs.AddPoint(new_point)                                ### Neue Punkte zeichnen lassen, man sieht sie sind auf der Linie
        offset = [random.uniform(-0.2,0.2), random.uniform(-0.2,0.2), random.uniform(-0.2,0.2)]  ### Offset in alle drei Achsen um Punkte von Linie zu bekommen
        offset_point = rs.PointAdd(new_point, offset)  ### Neue Punkte kreiren, welche nicht auf der Linie sind
        if 0:
            rs.AddPoint(offset_point)                             ### Neue Punkte zeichnen lassen, man sieht sie sind nicht mehr auf der Linie
        points.append(offset_point) ### Punkte in Array einfuegen
    points.append(end_point)        ### Punkte Array mit Endpunkt aufhoren lassen

#Erstellen der geschwungenen Linie
    offset_curve = rs.AddInterpCurve(points, 7)  ### zeichnen der neuen Kurve
    rs.ZoomExtents()
    rs.Redraw()