############################ HU_11 ############################
import rhinoscriptsyntax as rs
import sys, time, csv, ast
import random as rd
sys.path.append("P:\\WWW\\mraontu\\dm2")
import DM_lib as dm
#reload(dm)
rs.UnitSystem(4)# km = 5, meters = 4, cm = 3 etc
rs.ShowGrid(None, 0)
rs.ShowGridAxes(None, 0)
rs.ViewDisplayMode(rs.CurrentView(), "Rendered")
rs.DeleteObjects(rs.AllObjects())
rs.EnableRedraw(False)
############################
#dm.PointRadius(displayModeX=0, rad=1, styl=1)

### import csv datei ###
def import_closed_curves(file_path="P:\\WWW\\mraontu\\dm2\\09\\Lists\\kontur_curves.csv", layer_name="Imported_Kontur_Curves"):
    if not rs.IsLayer(layer_name):
        rs.AddLayer(layer_name, [0, 0, 0])

    with open(file_path, "r") as f:
        reader = csv.reader(f)
        for row in reader:
            points = [ast.literal_eval(pt) for pt in row]  # String-Koordinaten in Listen umwandeln
            crv = rs.AddCurve(points, degree=1)  # Kurve mit Grad 3 erstellen (anpassbar)
            if crv:
                rs.CloseCurve(crv)  # Sicherstellen, dass die Kurve geschlossen ist
                rs.ObjectLayer(crv, layer_name)

    print("fin import ")
import_closed_curves("P:\\WWW\\mraontu\\dm2\\09\\Lists\\kontur_curves.csv", "Imported_Kontur_Curves")           # CSV Datei import P:\WWW\mraontu\dm2\09\Lists

### MAIN CRV - volumen and path crv ###

curves = rs.ObjectsByLayer("Imported_Kontur_Curves")
ref_punkt = [-6517.71, 69205.71, 0]                # punkt wurde innerhalb der gesuchten crv gesetzt 
main_curve_layer = "main_curve"

if curves:
    main_crv = min(curves, key=lambda crv: rs.Distance(ref_punkt, rs.CurveAreaCentroid(crv)[0]))
    
    if not rs.IsLayer(main_curve_layer):
        rs.AddLayer(main_curve_layer, [255, 0, 0])  # layer main_curve
    rs.ObjectLayer(main_crv, main_curve_layer)


### Volumen 3D - simple building ### 3d extra minimal gehalten
# Parameter
h_volumen = 3.0  # Ebenen Hoehe
anz_geschosse = 10
building_layer = "building"
scale_range = (0, 0.8)    # scale range EG ,...
special_scale = 1.1       # scale Geschoss 2 und 10

if not rs.IsLayer(building_layer):
    rs.AddLayer(building_layer, [0, 0, 0]) # layer building 

for i in range(anz_geschosse):
    z_offset = i * h_volumen

    scale_factor = special_scale if i in [1, 9] else scale_range[1]  # 1 = Geschoss 2, 9 = Geschoss 10
    center = rs.CurveAreaCentroid(main_crv)[0] # kopie  main crv scale
    scaled_crv = rs.ScaleObject(main_crv, center, [scale_factor, scale_factor, 1], copy=True)

    rs.MoveObject(scaled_crv, [0, 0, z_offset]) #  crv Z verschieben

    volume = rs.ExtrudeCurveStraight(scaled_crv, [0, 0, z_offset], [0, 0, z_offset + h_volumen]) # extrudieren
    rs.CapPlanarHoles(volume)
    rs.ObjectLayer(volume, building_layer)

### PATH CRV - helix startpts ###

def create_path_curves(path_crv, Eckpunkte, path_layer="path_curves", z_offset=5, divisions=6):
    if not rs.IsLayer(path_layer):
        rs.AddLayer(path_layer, [255, 0, 0])

    all_points = rs.CurvePoints(path_crv)

    base_points = [all_points[i] for i in Eckpunkte if i < len(all_points)]  # Eckpunkte

    created_curves = []
    divided_points = []

    for i in range(len(base_points) - 1):
        p1_offset = [base_points[i][0], base_points[i][1], base_points[i][2] + z_offset]
        p2_offset = [base_points[i + 1][0], base_points[i + 1][1], base_points[i + 1][2] + z_offset]

        curve = rs.AddCurve([p1_offset, p2_offset])
        if curve:
            rs.ObjectLayer(curve, path_layer)
            created_curves.append(curve)

            if divisions > 0:
                div_pts = rs.DivideCurve(curve, divisions, create_points=True)
                divided_points.extend(div_pts)

    return created_curves, divided_points  # output path_crv + div pts = helix startpts

# Parameter
Eckpunkte = [ 2, 3, 4, 5]  # Welche Eckpunkte genutzt werden sollen
path_layer = "path_curve"
path_z_offset = 6          # z verschiebung path helix
anz_startpoints = 6                                     # set parameter path crv (anz startpts)

curves, helix_startpoints = create_path_curves(path_crv=main_crv,Eckpunkte=Eckpunkte,path_layer=path_layer, z_offset=path_z_offset,divisions=anz_startpoints) # erstellen von path crv fuer helix


########################### DNA - Doppelhelix ##################################

# Layers
A_color=[255, 37, 65]  # set colors  for Helix
B_color=[56, 90, 255]                    
C_color=[100, 0, 100]                      
dm.newEmptyLayer("Helix_A", color=A_color)
dm.newEmptyLayer("Helix_B", color=B_color)
dm.newEmptyLayer("Helix_Connections", color=C_color)
rs.LayerVisible("main_curve",False)
rs.LayerVisible("path_curve",False)

# Rotation um center pt
def rotate_point_around_origin(point, center, angle):
    vector = rs.VectorSubtract(point, center)
    rotated_vector = rs.VectorRotate(vector, angle, [0, 0, 1])
    return rs.VectorAdd(rotated_vector, center)

# Doppelhelix mit Rotation um center pt
def generate_doppel_helix(base_pt, spiral_size=28, z_scale_factor=1, anz_spiral=40, num_turns=4, radius=4, rotation_angle=0, A_color=A_color, B_color=B_color, C_color=C_color):
    vecX, vecY = [radius, 0, 0], [-radius, 0, 0]
    spiral_points_1, spiral_points_2 = [], []
    
    for i in range(anz_spiral):
        angle = (360 / anz_spiral) * num_turns * i
        z_shift = (i / float(anz_spiral)) * spiral_size * z_scale_factor
        
        rotated_vecX = rs.VectorRotate(vecX[:], angle, [0, 0, 1])
        rotated_vecX[2] = z_shift
        final_point_X = rotate_point_around_origin(rs.VectorAdd(base_pt, rotated_vecX), base_pt, rotation_angle)
        spiral_points_1.append(final_point_X)
        point_A = rs.AddPoint(final_point_X)
        rs.ObjectLayer(point_A, "Helix_A")
        rs.ObjectColor(point_A, A_color)
        
        rotated_vecY = rs.VectorRotate(vecY[:], angle, [0, 0, 1])
        rotated_vecY[2] = z_shift
        final_point_Y = rotate_point_around_origin(rs.VectorAdd(base_pt, rotated_vecY), base_pt, rotation_angle)
        spiral_points_2.append(final_point_Y)
        point_B = rs.AddPoint(final_point_Y)
        rs.ObjectLayer(point_B, "Helix_B")
        rs.ObjectColor(point_B, B_color)
    
    for i in range(len(spiral_points_1)):
        line = rs.AddLine(spiral_points_1[i], spiral_points_2[i])
        rs.ObjectLayer(line, "Helix_Connections")
        rs.ObjectColor(line, C_color)
    
    crv_A = rs.AddCurve(spiral_points_1, 1)
    rs.ObjectLayer(crv_A, "Helix_A")
    rs.ObjectColor(crv_A, A_color)
    
    crv_B = rs.AddCurve(spiral_points_2, 1)
    rs.ObjectLayer(crv_B, "Helix_B")
    rs.ObjectColor(crv_B, B_color)

# Kamera entlang Pfad
def move_camera_along_path(camera_curve, frame, total_frames):
    param = frame / float(total_frames)
    cam_pos = rs.EvaluateCurve(camera_curve, rs.CurveParameter(camera_curve, param))
    target_objects = rs.ObjectsByLayer("CameraTarget")
    target = rs.PointCoordinates(target_objects[0]) if target_objects else [0, 0, 0]
    dm.setCameraTarget(camera=cam_pos, target=target, lens=lense, rota=0, upVec=0, verbose=0)


### Parameter
# Helix
windungen = 4
anzahl_punkte = 60

# Animation  
frames = 10
max_rotation = 1440
lense = 35 
camera_curve = rs.ObjectsByLayer("cam")


for frame in range(frames):
    angle = (frame / float(frames)) * max_rotation       # rotation pro frame
    
    if "Helix_A" in rs.LayerNames():
        rs.DeleteObjects(rs.ObjectsByLayer("Helix_A"))
    if "Helix_B" in rs.LayerNames():
        rs.DeleteObjects(rs.ObjectsByLayer("Helix_B"))
    if "Helix_Connections" in rs.LayerNames():
        rs.DeleteObjects(rs.ObjectsByLayer("Helix_Connections"))
        
    for point in helix_startpoints:
        generate_doppel_helix(base_pt=point, spiral_size=21.3, z_scale_factor=1, anz_spiral=anzahl_punkte, num_turns=windungen, radius=1, rotation_angle=angle, A_color=A_color, B_color=B_color, C_color=C_color)  # set parameter helix  
    
    move_camera_along_path(camera_curve, frame, frames)
    # Export frames
    #dm.captureFrames(path="C:\\Users\\rothl\\dm2\\11\\animation\\", name="00_frame", fram=frame, Width=1600, Height=1200, Scale=1, format="jpg", trans=0)
    #dm.esc()
    rs.Redraw()
    time.sleep(0.05)

rs.EnableRedraw(True)

