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 + 120Para 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