' Fractal tree and Koch snowflake with GDI LINE via DECLARE
#COMPILE EXE
#DIM ALL

DECLARE FUNCTION MoveToEx LIB "GDI32.DLL" (BYVAL hDC AS LONG, BYVAL x AS LONG, BYVAL y AS LONG, BYVAL lpPoint AS LONG) AS LONG
DECLARE FUNCTION LineTo LIB "GDI32.DLL" (BYVAL hDC AS LONG, BYVAL x AS LONG, BYVAL y AS LONG) AS LONG
DECLARE FUNCTION GetDC LIB "USER32.DLL" (BYVAL hWnd AS LONG) AS LONG
DECLARE FUNCTION ReleaseDC LIB "USER32.DLL" (BYVAL hWnd AS LONG, BYVAL hDC AS LONG) AS LONG

FUNCTION DegToRad(BYVAL deg AS LONG) AS DOUBLE
    FUNCTION = deg * 3.14159 / 180.0
END FUNCTION

SUB DrawTreeLine(BYVAL x1 AS LONG, BYVAL y1 AS LONG, BYVAL x2 AS LONG, BYVAL y2 AS LONG, BYVAL depth AS LONG)
    LOCAL i AS LONG
    FOR i = 1 TO depth
        PRINT "  "; i; ": line ("; x1; ","; y1; ") -> ("; x2; ","; y2; ")"
    NEXT i
END SUB

SUB FractalTree(BYVAL x AS LONG, BYVAL y AS LONG, BYVAL len AS LONG, BYVAL angle AS LONG, BYVAL depth AS LONG)
    IF depth = 0 OR len < 2 THEN
        EXIT SUB
    END IF
    LOCAL rad  AS LONG
    LOCAL x2  AS LONG
    LOCAL y2  AS LONG
    rad = DegToRad(angle)
    x2 = x + len * COS(rad)
    y2 = y - len * SIN(rad)
    DrawTreeLine(x, y, x2, y2, depth)
    FractalTree(x2, y2, len * 2 / 3, angle - 30, depth - 1)
    FractalTree(x2, y2, len * 2 / 3, angle + 20, depth - 1)
END SUB

SUB PrintTree(BYVAL depth AS LONG)
    PRINT "Fractal tree depth="; depth
    FractalTree(320, 400, 100, -90, depth)
    LOCAL lines AS LONG
    lines = (2 ^ depth) - 1
    PRINT "  lines: "; lines
END SUB

SUB SierpinskiTriangle(BYVAL x AS LONG, BYVAL y AS LONG, BYVAL side AS LONG, BYVAL depth AS LONG)
    IF depth = 0 THEN
        PRINT "  triangle at ("; x; ","; y; ") size="; side
        EXIT SUB
    END IF
    LOCAL half AS LONG
    half = side / 2
    SierpinskiTriangle(x, y, half, depth - 1)
    SierpinskiTriangle(x + half, y, half, depth - 1)
    SierpinskiTriangle(x + half / 2, y - half, half, depth - 1)
END SUB

SUB PrintSierpinski(BYVAL side AS LONG, BYVAL depth AS LONG)
    PRINT "Sierpinski triangle size="; side; " depth="; depth
    SierpinskiTriangle(10, 200, side, depth)
    LOCAL tris AS LONG
    tris = 3 ^ depth
    PRINT "  triangles: "; tris
END SUB

SUB KochSnowflakeLines(BYVAL side AS LONG, BYVAL depth AS LONG)
    PRINT "Koch snowflake depth="; depth
    LOCAL segs AS LONG
    segs = 3 * (4 ^ depth)
    PRINT "  segments: "; segs
    LOCAL segLen AS LONG
    segLen = side
    LOCAL i AS LONG
    FOR i = 1 TO depth
        segLen = segLen / 3
    NEXT i
    PRINT "  segment length: "; segLen
END SUB

SUB DragonCurveDecomp(BYVAL depth AS LONG)
    PRINT "Dragon curve depth="; depth
    LOCAL segs AS LONG
    segs = 2 ^ depth
    PRINT "  segments: "; segs
    LOCAL turns AS LONG
    turns = (2 ^ depth) - 1
    PRINT "  turns: "; turns
    LOCAL i AS LONG
    FOR i = 1 TO turns
        PRINT "    turn "; i; ": R"
    NEXT i
END SUB

SUB PrintCantor(BYVAL x AS LONG, BYVAL len AS LONG, BYVAL depth AS LONG)
    IF depth = 0 THEN
        PRINT "  cantor line ("; x; " to "; x + len; ")"
        EXIT SUB
    END IF
    LOCAL third AS LONG
    third = len / 3
    PrintCantor(x, third, depth - 1)
    PrintCantor(x + 2 * third, third, depth - 1)
END SUB

SUB CantorSet(BYVAL depth AS LONG)
    PRINT "Cantor set depth="; depth
    PrintCantor(0, 243, depth)
    LOCAL segs AS LONG
    segs = 2 ^ depth
    PRINT "  segments: "; segs
END SUB

FUNCTION PBMAIN() AS LONG
    PRINT "=== Fractal Drawing Demo ==="
    PRINT "GDI: MoveToEx + LineTo via DECLARE"
    PRINT ""
    PrintTree(4)
    PRINT ""
    PrintSierpinski(200, 3)
    PRINT ""
    KochSnowflakeLines(200, 3)
    PRINT ""
    DragonCurveDecomp(4)
    PRINT ""
    CantorSet(3)
    PRINT ""
    PRINT "=== End Fractal Demo ==="
    FUNCTION = 0
END FUNCTION
