Scripts/hilbert-spectrum.ps1

# Unique Concept: Order-5 Hilbert curve traced with corner-aware box drawing and spectral progression along the path.


$ErrorActionPreference = 'Stop'
$esc = [char]27
$reset = "$esc[0m"

function Convert-HsvToRgb {
    param(
        [double]$Hue,
        [double]$Saturation,
        [double]$Value
    )

    $h = ($Hue % 1) * 6
    $sector = [math]::Floor($h)
    $fraction = $h - $sector

    $p = $Value * (1 - $Saturation)
    $q = $Value * (1 - $fraction * $Saturation)
    $t = $Value * (1 - (1 - $fraction) * $Saturation)

    switch ($sector) {
        0 { $r = $Value; $g = $t; $b = $p }
        1 { $r = $q; $g = $Value; $b = $p }
        2 { $r = $p; $g = $Value; $b = $t }
        3 { $r = $p; $g = $q; $b = $Value }
        4 { $r = $t; $g = $p; $b = $Value }
        default { $r = $Value; $g = $p; $b = $q }
    }

    return @([int][math]::Round($r * 255), [int][math]::Round($g * 255), [int][math]::Round($b * 255))
}

function Clamp {
    param(
        [double]$Value,
        [double]$Min,
        [double]$Max
    )

    if ($Value -lt $Min) { return $Min }
    if ($Value -gt $Max) { return $Max }
    return $Value
}

function Get-HilbertPoint {
    param(
        [int]$Index,
        [int]$Order
    )

    $x = 0
    $y = 0
    $t = $Index
    $n = 1 -shl $Order

    for ($s = 1; $s -lt $n; $s = $s * 2) {
        $rx = ($t -band 2) -shr 1
        $ry = (($t -band 1) -bxor $rx)

        if ($ry -eq 0) {
            if ($rx -eq 1) {
                $x = $s - 1 - $x
                $y = $s - 1 - $y
            }
            $swap = $x
            $x = $y
            $y = $swap
        }

        $x += $rx * $s
        $y += $ry * $s
        $t = $t -shr 2
    }

    return [pscustomobject]@{ X = $x; Y = $y }
}

$order = 5
$size = 1 -shl $order
$total = $size * $size
$xs = New-Object 'int[]' $total
$ys = New-Object 'int[]' $total

for ($i = 0; $i -lt $total; $i++) {
    $pt = Get-HilbertPoint -Index $i -Order $order
    $xs[$i] = $pt.X
    $ys[$i] = $pt.Y
}

$grid = @{}
for ($i = 0; $i -lt $total; $i++) {
    $x = $xs[$i]
    $y = $ys[$i]
    if (-not $grid.ContainsKey("$x,$y")) {
        $prevX = if ($i -gt 0) { $x - $xs[$i - 1] } else { 0 }
        $prevY = if ($i -gt 0) { $y - $ys[$i - 1] } else { 0 }
        $nextX = if ($i -lt $total - 1) { $xs[$i + 1] - $x } else { 0 }
        $nextY = if ($i -lt $total - 1) { $ys[$i + 1] - $y } else { 0 }

        $grid["$x,$y"] = [pscustomobject]@{
            Index = $i
            PrevX = $prevX
            PrevY = $prevY
            NextX = $nextX
            NextY = $nextY
        }
    }
}

$cornerMap = @{
    '-1,0|0,1'  = '┛'
    '-1,0|0,-1' = '┓'
    '1,0|0,1'   = '┗'
    '1,0|0,-1'  = '┏'
    '0,1|1,0'   = '┏'
    '0,1|-1,0'  = '┓'
    '0,-1|1,0'  = '┗'
    '0,-1|-1,0' = '┛'
}

for ($row = $size - 1; $row -ge 0; $row--) {
    $sb = [System.Text.StringBuilder]::new()
    for ($col = 0; $col -lt $size; $col++) {
        $key = "$col,$row"
        if ($grid.ContainsKey($key)) {
            $cell = $grid[$key]
            $progress = $cell.Index / [double]($total - 1)

            $entryX = - $cell.PrevX
            $entryY = - $cell.PrevY
            $exitX = $cell.NextX
            $exitY = $cell.NextY

            if ($entryX -eq 0 -and $entryY -eq 0) {
                $symbol = '●'
            }
            elseif ($exitX -eq 0 -and $exitY -eq 0) {
                $symbol = '◎'
            }
            elseif ($entryY -eq 0 -and $exitY -eq 0) {
                $symbol = '━'
            }
            elseif ($entryX -eq 0 -and $exitX -eq 0) {
                $symbol = '┃'
            }
            else {
                $lookup = "$entryX,$entryY|$exitX,$exitY"
                if ($cornerMap.ContainsKey($lookup)) {
                    $symbol = $cornerMap[$lookup]
                }
                else {
                    $symbol = '╳'
                }
            }

            $hue = ($progress + 0.18 * [math]::Sin(($col + $row) * 0.28) + 0.12 * [math]::Cos(($col - $row) * 0.31)) % 1
            if ($hue -lt 0) { $hue += 1 }
            $saturation = Clamp -Value (0.5 + 0.42 * [math]::Sin($progress * [math]::PI)) -Min 0 -Max 1
            $value = Clamp -Value (0.28 + 0.7 * [math]::Pow($progress, 0.6)) -Min 0.25 -Max 1

            $rgb = Convert-HsvToRgb -Hue $hue -Saturation $saturation -Value $value
            $token = "$esc[38;2;$($rgb[0]);$($rgb[1]);$($rgb[2])m$symbol"
            $null = $sb.Append($token)
            $null = $sb.Append($token)
        }
        else {
            $null = $sb.Append("$esc[38;2;8;9;12m ")
        }
    }
    Write-Host ($sb.ToString() + $reset)
}

Write-Host $reset