Não creio ser difícil identificar três sub-problemas: desenhar um quadrado, desenhar três sectores e desenhar uma circunferência. A dependência neste caso é a posição relativa de cada uma das três componentes. Com base nesta abordagem podemos escrever um primeiro esboço de solução.
import turtle
def radioactividade():
# desenha quadrado
quadrado()
# desenha sectores
sectores()
#desenha circunferência
circunferencia()
def quadrado():
pass
def sectores():
pass
def circunferencia():
pass
if __name__ == '__main__':
radioactividade()
Esta solução já pode ser testada embora não faça nada! Note-se que as definições ainda não têm argumentos… Vamos tomar nova decisão: dar o máximo liberdade à resolução de cada um dos sub-problemas. Por exemplo, no caso do quadrado, vamos criar uma definição que permita desenhar um quadrado parametrizado pelo tamanho do lado, a posição, a orientação e a cor. Já sabemos como fazer isso.
import turtle
def radioactividade(lado,posx,posy,orientacao,cor):
# desenha quadrado
quadrado(lado,posx,posy,orientacao,cor)
# desenha sectores
sectores()
#desenha circunferência
circunferencia()
def quadrado(lado,posx,posy,orientacao,cor):
turtle.up()
turtle.goto(posx,posy)
turtle.setheading(orientacao)
turtle.pendown()
turtle.fillcolor(cor)
turtle.begin_fill()
for i in range(4):
turtle.forward(lado)
turtle.left(90)
turtle.end_fill()
turtle.hideturtle()
def sectores():
pass
def circunferencia():
pass
if __name__ == '__main__':
lado = 100
posx = -50
posy = -50
orientacao = 30
cor = 'yellow'
radioactividade(lado,posx,posy,orientacao,cor)
Podemos testar isoladamente a definição quadrado e/ou testá-la no contexto da definição do símbolo da radioactividade. O normal, em programas grandes é que o teste seja feito primeiro isoladamente e só depois no interior do programa principal. Trata-se de mais uma vantagem deste tipo de programação, apelidada de programação descendente, que conduz a soluções modulares. Para além de os testes serem mais fáceis de fazer, também ficamos com código reutilizável!Resolvida esta questão vamos escolher um dos dois sub-problemas restantes. Optamos pela circunferência. Também aqui já sabemos o que fazer.
def circunferencia(raio,posx,posy,orienta,cor):
turtle.penup()
turtle.goto(posx,posy)
turtle.setheading(orienta)
turtle.pendown()
turtle.fillcolor(cor)
turtle.begin_fill()
turtle.circle(raio)
turtle.end_fill()
turtle.hideturtle()
Se testarmos esta definição verificamos que está tudo funcional como pretendido. Naturalmente queremos testar esta solução no interior do nosso programa principal, e aqui, somos confrontados com o facto dos tamanhos (lado e raio), das posições e das orientações estarem relacionadas. Com um pouco de análise não será difícil chegar a uma solução aceitável.
import turtle
def radioactividade(lado,posx,posy,orientacao,cor, cor_c):
# desenha quadrado
quadrado(lado,posx,posy,orientacao,cor)
# desenha sectores
sectores()
#desenha circunferência
raio = lado/10
posx_c = posx + lado/2 + raio
posy_c = posy + lado/2
orientacao_c = orientacao + 90
circunferencia(raio,posx_c,posy_c,orientacao_c,cor_c)
def quadrado(lado,posx,posy,orientacao,cor):
turtle.up()
turtle.goto(posx,posy)
turtle.setheading(orientacao)
turtle.pendown()
turtle.fillcolor(cor)
turtle.begin_fill()
for i in range(4):
turtle.forward(lado)
turtle.left(90)
turtle.end_fill()
turtle.hideturtle()
def sectores():
pass
def circunferencia(raio,posx,posy,orienta,cor):
turtle.penup()
turtle.goto(posx,posy)
turtle.setheading(orienta)
turtle.pendown()
turtle.fillcolor(cor)
turtle.begin_fill()
turtle.circle(raio)
turtle.end_fill()
turtle.hideturtle()
if __name__ == '__main__':
lado = 100
posx = -50
posy = -50
orientacao = 0
cor = 'yellow'
raio = lado/10
cor_c = 'black'
#circunf(raio,posx,posy,orientacao,cor)
radioactividade(lado,posx,posy,orientacao,cor, cor_c)
turtle.exitonclick()
Como se pode ver o desenho da circunferência é precedido do cálculo dos valores apropriados para o tamanho do raio, a posição e a orientação. Repare que para que o centro da circunferência coincida com o centro do quadrado, a tartaruga tem que ser colocada numa posição em que veja esse centro à sua esquerda e à distância do raio! O leitor atento notará que a orientação inicial é de zero graus, pois é isto que nos é pedido. Caso o valor seja diferente o posicionamento do centro da circunferência também é diferente. Deixámos para o fim o problema dos sectores. Também aqui é possível decompor este problema em três sub-problemas equivalentes. Vejamos então como podemos desenhar um sector com total liberdade.
def sector(raio,posx,posy,orientacao,cor,amplitude):
turtle.penup()
turtle.goto(posx,posy)
turtle.setheading(orientacao)
turtle.color(cor)
turtle.pendown()
turtle.begin_fill()
turtle.forward(raio)
turtle.left(90)
turtle.circle(raio,amplitude)
turtle.left(90)
turtle.forward(raio)
turtle.end_fill()
turtle.setheading(orientacao)
turtle.hideturtle()
O desenho tem três partes: desenho do raio, desenho do arco, desenho do raio. Notar que no final queremos ter a tartaruga com a orientação inicial. Porquê?? Uma vez mais, um leitor atento pode ser levado a pensar que o desenho da circunferência e o desenho do sector poderiam ser unidos numa única definição. Afinal, parece que apenas diferem do parâmetro amplitude. Mas será mesmo assim? Quem quiser pode explorar esse caminho e verificar as questões que se colocam.Como desenhamos os três sectores? Não é difícil perceber que temos que repetir o desenho de um sector alterando apenas a orientação de 120 graus. Será que o facto de a tartaruga que desenha um sector terminar com a mesma orientação que a inicial ajudou???
def sectores(raio,posx,posy,orientacao,cor,amplitude):
for i in range(3):
sector(raio,posx,posy,orientacao,cor,amplitude)
orientacao = orientacao + 120
Para terminar o trabalho temos que incorporar esta solução no programa principal.
import turtle
def radioactividade(lado,posx,posy,orientacao,cor, cor_c, cor_s):
# desenha quadrado
quadrado(lado,posx,posy,orientacao,cor)
# desenha sectores
raio_s = lado/4
posx_s = posx + lado/2
posy_s = posy + lado/2
orientacao_s = orientacao
amplitude = 60
sectores(raio_s,posx_s,posy_s,orientacao_s,cor_s,amplitude)
#desenha circunferência
raio = lado/10
posx_c = posx + lado/2 + raio
posy_c = posy + lado/2
orientacao_c = orientacao + 90
circunferencia(raio,posx_c,posy_c,orientacao_c,cor_c)
def quadrado(lado,posx,posy,orientacao,cor):
turtle.up()
turtle.goto(posx,posy)
turtle.setheading(orientacao)
turtle.pendown()
turtle.fillcolor(cor)
turtle.begin_fill()
for i in range(4):
turtle.forward(lado)
turtle.left(90)
turtle.end_fill()
turtle.hideturtle()
def sectores(raio,posx,posy,orientacao,cor,amplitude):
for i in range(3):
sector(raio,posx,posy,orientacao,cor,amplitude)
orientacao = orientacao + 120
def sector(raio,posx,posy,orientacao,cor,amplitude):
turtle.penup()
turtle.goto(posx,posy)
turtle.setheading(orientacao)
turtle.color(cor)
turtle.pendown()
turtle.begin_fill()
turtle.forward(raio)
turtle.left(90)
turtle.circle(raio,amplitude)
turtle.left(90)
turtle.forward(raio)
turtle.end_fill()
turtle.setheading(orientacao)
turtle.hideturtle()
def circunferencia(raio,posx,posy,orienta,cor):
turtle.penup()
turtle.goto(posx,posy)
turtle.setheading(orienta)
turtle.pendown()
turtle.fillcolor(cor)
turtle.begin_fill()
turtle.circle(raio)
turtle.end_fill()
turtle.hideturtle()
if __name__ == '__main__':
lado = 100
posx = -50
posy = -50
orientacao = 0
cor = 'yellow'
raio = lado/10
cor_c = 'black'
raio_s = lado/4
cor_s = 'black'
amplitude = 60
#circunferencia(raio,posx,posy,orientacao,cor)
#sector(raio_s,posx,posy,orientacao,cor_s,amplitude)
#sectores(raio_s,posx,posy,orientacao,cor_s,amplitude)
radioactividade(lado,posx,posy,orientacao,cor, cor_c,cor_s)
turtle.exitonclick()
A definição de alguns parâmetros dos sectores em função dos parâmetros do quadrado não deve oferecer dúvidas. Se executarmos o programa verificamos que não aparece a separação entre a circunferência e os sectores. A solução desse problema é trivial e passa por colocar a cor da caneta da tartaruga, quando desenha a circunferência, a branco.
def circunferencia(raio,posx,posy,orienta,cor):
turtle.penup()
turtle.goto(posx,posy)
turtle.setheading(orienta)
turtle.pencolor('white')
turtle.pendown()
turtle.fillcolor(cor)
turtle.begin_fill()
turtle.circle(raio)
turtle.end_fill()
turtle.hideturtle()
Como dissemos atrás esta solução global funciona quando a orientação inicial é zero. Se for outra não funciona. Como alterar a nossa solução mexendo o mínimo possível, por forma ao programa funcionar mesmo quando o quadrado tem uma orientação qualquer? A solução passa por recalcular o centro da figura tendo a orientação em linha de conta. Para isso basta usar um pouco do nosso conhecimento de trigonometria.
import turtle
import math
def radioactividade(lado,posx,posy,orientacao,cor, cor_c, cor_s):
# desenha quadrado
quadrado(lado,posx,posy,orientacao,cor)
# desenha sectores
raio_s = lado/4
ang_base = (orientacao* math.pi / 180)
ang = ang_base + math.pi/4
posx_s = posx + lado/math.sqrt(2) * math.cos(ang)
posy_s = posy + lado/math.sqrt(2) * math.sin(ang)
orientacao_s = orientacao
amplitude = 60
sectores(raio_s,posx_s,posy_s,orientacao_s,cor_s,amplitude)
#desenha circunferência
raio = lado/10
posx_c = posx_s + raio * math.cos(ang_base)
posy_c = posy_s + raio * math.sin(ang_base)
orientacao_c = orientacao + 90
circunferencia(raio,posx_c,posy_c,orientacao_c,cor_c)
def quadrado(lado,posx,posy,orientacao,cor):
turtle.up()
turtle.goto(posx,posy)
turtle.setheading(orientacao)
turtle.pendown()
turtle.fillcolor(cor)
turtle.begin_fill()
for i in range(4):
turtle.forward(lado)
turtle.left(90)
turtle.end_fill()
turtle.hideturtle()
def sectores(raio,posx,posy,orientacao,cor,amplitude):
for i in range(3):
sector(raio,posx,posy,orientacao,cor,amplitude)
orientacao = orientacao + 120
def sector(raio,posx,posy,orientacao,cor,amplitude):
turtle.penup()
turtle.goto(posx,posy)
turtle.setheading(orientacao)
turtle.color(cor)
turtle.pendown()
turtle.begin_fill()
turtle.forward(raio)
turtle.left(90)
turtle.circle(raio,amplitude)
turtle.left(90)
turtle.forward(raio)
turtle.end_fill()
turtle.setheading(orientacao)
turtle.hideturtle()
def circunferencia(raio,posx,posy,orienta,cor):
turtle.penup()
turtle.goto(posx,posy)
turtle.setheading(orienta)
turtle.pencolor('white')
turtle.pendown()
turtle.fillcolor(cor)
turtle.begin_fill()
turtle.circle(raio)
turtle.end_fill()
turtle.hideturtle()
if __name__ == '__main__':
lado = 200
posx = -50
posy = -50
orientacao = 45
cor = 'yellow'
raio = lado/10
cor_c = 'black'
raio_s = lado/4
cor_s = 'black'
amplitude = 60
radioactividade(lado,posx,posy,orientacao,cor, cor_c,cor_s)
turtle.exitonclick()
Como se pode ver apenas mexemos no programa principal e em zonas localizadas do código, as zonas de definem a interacção entre as partes. E pronto. Espero que da próxima vez que programar procure usar este princípio da decomposição de um problema em sub-problemas!




Sem comentários:
Enviar um comentário