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: