dump

Personagens Modulares

Numa primeira abordagem pareceu-me importante o desafio de pensar uma alternativa para o sistema de Identicons como forma de reconhecimento visual cujos resultados permitam identificação (no seu sentido total). Assim, mais do que pensar numa solução que resolvesse 300000 situações, prefiro não encontrar um limite tangível (apontar para o infinito?).

Os insectos surgiram rapidamente como o personagem que naturalmente oferece mais variações: são conhecidas milhares de espécies e outras tantas estão por descobrir. Por outro lado, no contexto digital/informático, estão sempre em relação com a ideia de “bug” (falha). Lembrei-me pouco depois que não era completamente inocente esta solução pois já tinha uma imagem em mente que acabei por identificar.

Avancei então com um gerador de insectos (ou antes, insectos e aranhas, que não são bem a mesma coisa). Tencionava também incluir estruturas semelhantes a minhocas, larvas e centopeias mas não tive tempo (ainda) e teria de contornar uma ou outra dificuldade no código (points e contours de path no shoebot).

Código nodebox/shoebot:

"""
Aranha (2 partes) ou Insecto (3 partes) de tamanho variável
6 ou 8 patas variáveis (8 se for aranha)
2 olhos variáveis ou mais se for aranha
1 a 3 pares variáveis de mandibulas
0 a 2 pares variáveis de antenas se for insecto
0 a 2 pares variáveis de asas se for insecto
"""
 
# devolve valor relativo a proporção (importado do Processing)
def map(value,istart,istop,ostart,ostop):
    return ostart+(ostop-ostart)*((value-istart)/(istop-istart))
# devolve a distancia entre dois pontos
def distance(x0,y0,x1,y1):
    from math import sqrt,pow
    return sqrt(pow(x1-x0,2)+pow(y1-y0,2))
# devolve coordenadas de um ponto a uma distancia e angulo de outro
def rel_coordinates(x0,y0,distance,angle):
    from math import radians,sin,cos
    x1=x0+cos(radians(angle))*distance
    y1=y0+sin(radians(angle))*distance
    return x1,y1
# devolve o angulo entre dois pontos
def angle(x0,y0,x1,y1):
    from math import degrees,atan2
    a=degrees( atan2(y1-y0,x1-x0) )
    return a
# oval a partir do centro
def oval_from_center(x,y,w,h,drawing=True):
    x=x-w/2
    y=y-h/2
    if drawing==True:
        oval(x,y,w,h)
    else:
        return oval(x,y,w,h,draw=False)
# devolve lista de partes, proporção (tamanho) de cada parte
def parts(parts_number,start_x,start_y,length,angle):
    parts=list() # (size_x,size_y,rad_size,brightness)
    head_size=random(.15,.45)/(parts_number-1)
    head_width=random(.9,1.1)*head_size
    head_rad=random(2.1,3.) # falsos radius (menores)
    parts.append((head_size,head_width,head_rad,random(-.25,.25)))
    tor_size=0
    if parts_number==3:
        tor_size=random(.1,.45)
        tor_width=random(.85,1.5)*head_size
        tor_rad=random(2.1,3.)
        parts.append((tor_size,tor_width,tor_rad,random(-.25,.25)))
    abd_size=1-head_size-tor_size
    abd_width=random(1.25*head_size,abd_size*.75)
    abd_rad=random(2.1,3.)
    parts.append((abd_size,abd_width,abd_rad,random(-.25,.25)))
    parts.reverse() # tails first
    return parts
 
size(400,400)
colormode(HSB)
background(1)
 
# Cores ternárias
main_color=random(0.,1.)
alt_color=main_color+.33 if main_color+.33<1 else main_color-.66
alt_color_2=main_color-.33 if main_color-.33>0 else main_color+.66
 
# Inicio e fim do insecto, opções
body_start=(random(0,WIDTH),random(0,HEIGHT))
body_end=None
while body_end==None or distance(body_start[0],body_start[1],body_end[0],body_end[1])<(WIDTH/3):
    body_end=(random(WIDTH/4,WIDTH*3/4),random(HEIGHT/4,HEIGHT*3/4))
parts_number=random(2,3)
 
# Dados principais
body_angle=angle(body_start[0],body_start[1],body_end[0],body_end[1])
body_length=distance(body_start[0],body_start[1],body_end[0],body_end[1])
parts=parts(parts_number,body_start[0],body_start[1],body_length,body_angle)
 
#PERNAS
stroke(main_color,0.5,0.1)
translate(body_start[0],body_start[1])
leg_center_part=1
leg_pairs_number=4 if len(parts)==2 else random(3,4)
leg_center=rel_coordinates(0,0,((2*((parts[0][0]*body_length)/parts[0][2]))+(parts[leg_center_part][0]*body_length)/parts[leg_center_part][2]),body_angle)
start_angle=body_angle+random(-100.,-80.)
leg_angle=random(30.,50.)
leg_angle_wide=leg_angle+random(30.,90.)
leg_angle_increment=leg_angle/(leg_pairs_number-1)
leg_angle_increment_wide=(leg_angle_wide/(leg_pairs_number-1))
leg_size=random(.8,1.25)*parts[leg_center_part-1][0]*body_length
leg_ratio=random(2.5,3.5)
leg_width=random(1,2)*3
for i in range(2):
    for j in range(leg_pairs_number):
        angle=(start_angle-leg_angle/2)+j*(leg_angle_increment*random(.9,1.1))
        angle_wide=(start_angle-leg_angle_wide/2)+j*(leg_angle_increment_wide*random(.9,1.1))
        angle_middle=angle+(angle_wide-angle)/random(1.9,2.1)
        leg_end_0=rel_coordinates(leg_center[0],leg_center[1],leg_size/3,angle)
        leg_end_1=rel_coordinates(leg_center[0],leg_center[1],leg_size*2/3,angle_middle)
        leg_end_2=rel_coordinates(leg_center[0],leg_center[1],leg_size,angle_wide)
        strokewidth(leg_width)
        line(leg_center[0],leg_center[1],leg_end_0[0],leg_end_0[1])
        strokewidth(leg_width*2/3)
        line(leg_end_0[0],leg_end_0[1],leg_end_1[0],leg_end_1[1])
        strokewidth(leg_width/3)
        line(leg_end_1[0],leg_end_1[1],leg_end_2[0],leg_end_2[1])
    start_angle+=180
 
#CORPO
nostroke()
reset()
transform(mode=CENTER)
translate(body_start[0],body_start[1])
for part in parts:
    part_rad=rel_coordinates(0,0,(part[0]*body_length)/part[2],body_angle)
    translate(part_rad[0],part_rad[1])
    push()
    rotate(-body_angle)
    fill(main_color,.3,.5+part[3])
    oval_from_center(0,0,part[0]*body_length,part[1]*body_length)
    pop()
    translate(part_rad[0],part_rad[1])
parts.reverse()
 
#HEAD
head_center=rel_coordinates(0,0,(parts[0][0]*body_length)/parts[0][2],180+body_angle)
translate(head_center[0],head_center[1])
 
#MANDIBULAS
stroke(main_color,.1,.1)
jaw_pairs=random(1,3)
for i in range(jaw_pairs):
    m=1
    jaws_angle=random(5.,40.)
    jaws_angle_inner=random(.2,.7)*jaws_angle
    jaws_size=random(.55,.7)*parts[0][1]*body_length
    jaws_closure=random(.75,1.25)
    for j in range(2):
        jaw_0=rel_coordinates(0,0,parts[0][0]*body_length/2,body_angle+m*jaws_angle/2)
        jaw_1=rel_coordinates(0,0,jaws_size*jaws_closure,body_angle+m*jaws_angle/2)
        jaw_2=rel_coordinates(0,0,jaws_size,body_angle+m*jaws_angle_inner/2)
        strokewidth(2)
        line(jaw_0[0],jaw_0[1],jaw_1[0],jaw_1[1])
        strokewidth(1)
        line(jaw_1[0],jaw_1[1],jaw_2[0],jaw_2[1])
        m*=-1 
 
#OLHOS
nostroke()
fill(alt_color,.5,.5)
eye_pairs=random(2,8) if len(parts)==2 else 1
eye_size=(random(.1,.45)*parts[0][1]*body_length)/eye_pairs
for i in range(eye_pairs):
    eye_angle=random(20.,160.)
    eye_d=random(.25,.5)*parts[0][1]*body_length
    eye_l=rel_coordinates(0,0,eye_d,body_angle+eye_angle/2)
    eye_r=rel_coordinates(0,0,eye_d,body_angle-eye_angle/2)
    oval_from_center(eye_l[0],eye_l[1],eye_size,eye_size)
    oval_from_center(eye_r[0],eye_r[1],eye_size,eye_size)
 
#ANTENAS
if len(parts)==3:
    stroke(main_color,.1,.1)
    nofill()
    antenna=random(0,1)
    if antenna==1:
        antenna_pairs=random(0,2)
        for i in range(antenna_pairs):
            antenna_d=random(.1,.2)*parts[0][1]*body_length
            antenna_size=random(.15,.4)*body_length
            antenna_angle=random(60.,100.)
            antenna_angle_2=antenna_angle+random(-20.,20.)
            antenna_ratio=random(.3,.8)
            m=1
            for j in range(2):
                antenna_0=rel_coordinates(0,0,antenna_d,body_angle+m*120)
                antenna_1=rel_coordinates(0,0,antenna_size*antenna_ratio,body_angle+m*antenna_angle_2/2)
                antenna_2=rel_coordinates(0,0,antenna_size,body_angle+m*antenna_angle/2)
                autoclosepath(False)
                path = findpath([(antenna_0[0],antenna_0[1]),(antenna_1[0],antenna_1[1]),(antenna_2[0],antenna_2[1])])
                drawpath(path)
                m*=-1
 
#ASAS
nostroke()
fill(alt_color_2,.2,1,.5)
if len(parts)==3 and random(0,1)==1:
    reset()
    translate(body_start[0]+leg_center[0],body_start[1]+leg_center[1])
    wing_pairs=random(1,2)
    for i in range(wing_pairs):
        wing_d=random(.1,.2)*parts[1][1]*body_length
        wing_size=random(.75,1.1)*body_length
        wing_width=random(.3,.6)*wing_size
        wing_angle=random(-20,70)
        m=1
        for j in range(2):
            wing_0=rel_coordinates(0,0,wing_size/2+wing_d,body_angle+m*90+m*wing_angle)
            push()
            translate(wing_0[0],wing_0[1])
            rotate(-body_angle+90-m*wing_angle)
            oval_from_center(0,0,wing_size,wing_width)
            pop()
            m*=-1

Deixar uma resposta