Mostrando postagens com marcador equação do círculo. Mostrar todas as postagens
Mostrando postagens com marcador equação do círculo. Mostrar todas as postagens

sábado, 28 de outubro de 2017

Desenhando com Pixels - parte 2

Na parte 1 de Desenhando com Pixels, criou-se funções para o desenho de pontos, retas, triângulos e quadrados. Ainda, naquele código usou-se o artifício de carregar um bitmap de fundo.

Agora, vamos acrescentar novas funções, como o desenho de círculos, bem como o desenho de figuras geométricas com preenchimento. Para o desenho dessa característica, usaremos o que foi aprendido no post sobre recursividade, ou seja, o preenchimento de uma figura pode ser obtido através de chamadas recursivas à própria função de desenho.

Na plotagem, criamos um novo atributo "espessura", possibilitando a geração de pontos maiores e, como todas as demais figuras são baseadas em pontos, a consequente geração de retas, quadrados, triângulos e círculos mais espessos.

Outra melhoria foi a alteração no modo de compor o fundo de desenho, sem a necessidade da carga de um bitmap gerado externamente, seja de um arquivo ou de uma string base64. Agora, o fundo foi implementado assim:
$img = New-Object System.Drawing.Bitmap($form.Width, $form.Height)
$form.BackgroundImage = $img
$form.BackgroundImageLayout = "None"


A implementação completa é demonstrada abaixo:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
##########################################################
Function plot([Int32]$x, [Int32] $y, [String] $cor, [Int32] $espessura) {
    for ([Int32]$ey=0;$ey -le $espessura;$ey++) {
        for ([Int32]$ex=0;$ex -le $espessura;$ex++) {
             $img.SetPixel($x+$ex, $y+$ey, $cor)
        }
    }
}
##########################################################
Function retaBresenham ([Int32]$x1, [Int32]$y1, [Int32]$x2, [Int32]$y2, [String]$cor, [Int32]$espessura) {
    [Int32] $dx = $x2 - $x1
    [Int32] $dy = $y2 - $y1
    [Int32] $stepx, $stepy

    if ($dy -lt 0) { 
        $dy = -$dy 
        $stepy = -1
    }
    else { $stepy = 1 }

    if ($dx -lt 0) { 
        $dx = -$dx 
        $stepx = -1
    }
    else { $stepx = 1 }

    $dy = $dy -shl 1
    $dx = $dx -shl 1

    plot $x1 $y1 $cor $espessura

    if ($dx -gt $dy) {
        [Int32] $fraction = $dy - ($dx -shr 1)
        while ($x1 -ne $x2) {
            if ($fraction -ge 0) {
                $y1 += $stepy
                $fraction -= $dx
            }
            $x1 += $stepx
            $fraction += $dy
            plot $x1 $y1 $cor $espessura
        }
    }
    else {
        [Int32] $fraction = $dx - ($dy -shr 1)
        while ($y1 -ne $y2) {
            if ($fraction -ge 0) {
                $x1 += $stepx
                $fraction -= $dy
            }
            $y1 += $stepy
            $fraction += $dx
            plot $x1 $y1 $cor $espessura
        }
    }
    
}

##########################################################
Function triangulo([Int32]$x1, [Int32]$y1, [Int32]$h, [String]$cor, [Int32]$espessura) {
    [Int32] $lado = ([math]::Sqrt(4*$h*$h/3))
    retaBresenham $x1 $y1 ($x1-($lado/2)) ($y1+$h) $cor $espessura
    retaBresenham $x1 $y1 ($x1+($lado/2)) ($y1+$h) $cor $espessura
    retaBresenham ($x1-($lado/2)) ($y1+$h) ($x1+($lado/2)) ($y1+$h) $cor $espessura
}

##########################################################
Function trianguloSolido([Int32]$x1, [Int32]$y1, [Int32]$h, [String]$cor) {
    ## Caso Base - Triângulo mínimo alcançado
    if ($h -lt 3) {
        triangulo $x1 $y1 $h $cor 2 
        return 
    }
    triangulo $x1 $y1 $h $cor 2
    return trianguloSolido $x1 ($y1+3) ($h-6) $cor
}

##########################################################
Function quadrado([Int32]$x1, [Int32]$y1, [Int32]$tam, [String]$cor, [Int32]$espessura) {
    retaBresenham $x1 $y1 ($x1+$tam) $y1 $cor $espessura
    retaBresenham $x1 $y1 $x1 ($y1+$tam) $cor $espessura
    retaBresenham $x1 ($y1+$tam) ($x1+$tam) ($y1+$tam) $cor $espessura
    retaBresenham ($x1+$tam) $y1 ($x1+$tam) ($y1+$tam) $cor $espessura
}

##########################################################
Function quadradoSolido([Int32]$x1, [Int32]$y1, [Int32]$tam, [String]$cor) {
    ## Caso Base - Quadrado mínimo alcançado
    if ($tam -lt 5) {
        quadrado $x1 $y1 $tam $cor 5
        return 
    }
    quadrado $x1 $y1 $tam $cor 5
    return quadradoSolido ($x1+5) ($y1+5) ($tam-10) $cor
}

##########################################################
Function circuloSolido([Int32]$xC, [Int32]$yC, [Int32]$r, [String]$cor) {
    ## Caso Base - Quadrado mínimo alcançado
    if ($r -lt 5) {
        plot $xC $yC $cor 5
        return
    }
    circulo $xC $yC $r $cor 5
    return circuloSolido $xC $yC ($r-5) $cor
}

##########################################################
Function circulo([Int32]$xC, [Int32]$yC, [Int32]$r, [String]$cor, [Int32]$espessura) {
    [Int32] $x = 0
    [Int32] $y = $r
    [Int32] $u = 1
    [Int32] $v = 2*$r-1
    [Int32] $E = 0

    while ($x -lt $y) {
        plot ($xC + $x) ($yC + $y) $cor $espessura ## NNE
        plot ($xC + $y) ($yC - $x) $cor $espessura ## ESE
        plot ($xC - $x) ($yC - $y) $cor $espessura ## SSW
        plot ($xC - $y) ($yC + $x) $cor $espessura ## WNW
        $x++
        $E += $u
        $u += 2
        if ($v -lt (2*$E)) {
            $y--
            $E -= $v
            $v -= 2
        }
        if ($x -gt $y) { return }
        plot ($xC + $y) ($yC + $x) $cor $espessura ## ENE
        plot ($xC + $x) ($yC - $y) $cor $espessura ## SSE
        plot ($xC - $y) ($yC - $x) $cor $espessura ## WSW
        plot ($xC - $x) ($yC + $y) $cor $espessura ## NNW
    }
}


Function bmpRefresh([System.Drawing.Bitmap]$img){
    $formGraphics.DrawImage($img,0,0,$img.Width,$img.Height)    
}

##########################################################
[Windows.Forms.Application]::EnableVisualStyles()
$form = New-Object Windows.Forms.Form
$form.Width = 600;
$form.Height = 480;
$img = New-Object System.Drawing.Bitmap($form.Width, $form.Height)
$form.BackgroundImage = $img
$form.BackgroundImageLayout = "None"
$formGraphics = $form.CreateGraphics()

$form.Add_Shown({

        ### Pontos
        for ([Int32]$x=30;$x -lt 55;$x+=5) {
            plot $x 50 'Red' 0
            plot $x 60 'Red' 1
            plot $x 70 'Red' 2
        }
        bmpRefresh($img)

        ### Reta
        retaBresenham 50 0 535 440 'Orange' 2
        retaBresenham 0 0 585 440 'Blue' 1
        bmpRefresh($img)

        ### Triângulo
        triangulo 100 100 100 'Green' 3
        triangulo 100 120 70 'Gray' 2
        bmpRefresh($img)

        ### Triângulo Sólido
        trianguloSolido 100 220 100 'Red'
        bmpRefresh($img)

        ### Quadrado
        quadrado 370 70 100 'Red' 5
        quadrado 390 90 60 'Black' 3
        quadrado 410 110 20 'blue' 2
        bmpRefresh($img)

        ### Quadrado Sólido
        quadradoSolido 250 70 100 'Green'
        bmpRefresh($img)

        ### Círculo
        circulo 200 380 40 'Black' 2
        bmpRefresh($img)

        circuloSolido 340 370 60 'Blue'
        bmpRefresh($img)
        
})

$form.ShowDialog()

O resultado: