#include #include #include #include #include #include "c24lib/image/image.h" #include "c24lib/image/draw.h" #include "c24lib/image/pnm.h" #include "pcb_draw.h" #include "gp.h" #define DUMPDIR "/tmp/gpstroke/" #define STROKE_PENALTY 550 #define OPTIMIZE_FROM 5000 #define MAX_TH 12 #define MIN_TH 8 #define MAX_STROKES 16 #define MAX_POLYS 3 int max_strokes = 16; image_t *ref, *canvas; typedef struct { int x, y; } point_t; typedef struct { int len; point_t pt[MAX_STROKES]; int th; } polyline_t; typedef struct { polyline_t poly[MAX_POLYS]; } pcb_t; #include "pcb_common.h" static inline int pcb_num_strokes(pcb_t *p) { int pi, res = 0; for(pi = 0; pi < MAX_POLYS; pi++) res += p->poly[pi].len; return res; } static void pcb_dump_str(FILE *f, pcb_t *p) { int n, pi; for(pi = 0; pi < MAX_POLYS; pi++) { polyline_t *P = &p->poly[pi]; if (pi > 0) fprintf(f, "\n"); for(n = 1; n < P->len; n++) { fprintf(f,"stroke %d %d %d %d %d\n", P->pt[n-1].x, P->pt[n-1].y, P->pt[n].x, P->pt[n].y, clamp(P->th, MIN_TH, MAX_TH)); } } } static inline void pcb_draw(image_t *img, pcb_t *p) { int n, pi; draw_color(pixel_black); for(pi = 0; pi < MAX_POLYS; pi++) { polyline_t *P = &p->poly[pi]; for(n = 1; n < P->len; n++) draw_pcb_line(img, P->pt[n-1].x, P->pt[n-1].y, P->pt[n].x, P->pt[n].y, clamp(P->th, MIN_TH, MAX_TH)); } } static inline void rand_poly(polyline_t *p) { long loc = myrand(0, black_len-1); p->pt[0].x = image_x(ref, ref->pixmap+black[loc]); p->pt[0].y = image_y(ref, ref->pixmap+black[loc]); p->pt[1].x = p->pt[0].x + myrand(0, 3); p->pt[1].y = p->pt[0].y + myrand(0, 3); p->len = 2; p->th = myrand(MIN_TH, MAX_TH); } static pcb_t *load_str(char *fn) { #if 0 char line[256]; FILE *f = fopen(fn, "r"); pcb_t *p; if (f == NULL) return 0; p = calloc(sizeof(pcb_t), 1); while(fgets(line, sizeof(line), f) != NULL) { char *s = line; int x1, y1, x2, y2, th; if (strncmp(s, "stroke", 6) == 0) s+=6; if (sscanf(s, "%d %d %d %d %d", &x1, &y1, &x2, &y2, &th) == 5) { stroke_t *s = &p->str[p->len]; s->x1 = x1; s->y1 = y1; s->x2 = x2; s->y2 = y2; s->th = th; p->len++; } } fclose(f); return p; #endif return NULL; } void *pcb_create(void) { pcb_t *p = malloc(sizeof(pcb_t)); int n; if (default_new != NULL) { memcpy(p, default_new, sizeof(pcb_t)); return p; } for(n = 0; n < MAX_POLYS; n++) rand_poly(&p->poly[n]); return p; } static inline void pcb_mutate_append(polyline_t *p) { if (p->len >= MAX_STROKES) return; p->pt[p->len].x = p->pt[p->len-1].x + myrand(2, 10) - 5; p->pt[p->len].y = p->pt[p->len-1].y + myrand(2, 10) - 5; p->len++; } static inline void pcb_mutate_insert(polyline_t *p) { if (p->len >= MAX_STROKES) return; memmove(p->pt+1, p->pt, p->len * sizeof(point_t)); p->pt[0].x = p->pt[1].x + myrand(2, 10) - 5; p->pt[0].y = p->pt[1].y + myrand(2, 10) - 5; p->len++; } static inline void pcb_mutate_del(polyline_t *p) { int rem, idx; if (p->len < 3) return; idx = myrand(0, p->len-1); rem = p->len - idx - 1; if (rem > 0) memmove(p->pt+idx, p->pt+idx+1, rem*sizeof(point_t)); p->len--; } static inline void pcb_mutate_split(polyline_t *p) { int idx, rem; if (p->len >= MAX_STROKES) return; idx = myrand(1, p->len-1); rem = p->len - idx - 1; if (rem > 0) memmove(p->pt+idx+1, p->pt+idx, rem*sizeof(point_t)); p->pt[idx].x = (p->pt[idx-1].x + p->pt[idx+1].x)/2 + myrand(2, 10) - 5; p->pt[idx].y = (p->pt[idx-1].y + p->pt[idx+1].x)/2 + myrand(2, 10) - 5; } static inline void pcb_mutate_chg(polyline_t *p) { int dirx = (rand() % 3) - 1; int diry = (rand() % 3) - 1; int idx = myrand(0, p->len-1); tune(p->pt[idx].x, 0, ref->sx, dirx); tune(p->pt[idx].y, 0, ref->sy, diry); } void pcb_mutate(void *data) { pcb_t *p = data; int n = myrand(0, 100); int pi = myrand(0, MAX_POLYS-1); if (n > 65) pcb_mutate_chg(&p->poly[pi]); switch(n % 4) { case 0: pcb_mutate_append(&p->poly[pi]); break; case 1: pcb_mutate_insert(&p->poly[pi]); break; case 2: pcb_mutate_del(&p->poly[pi]); case 3: pcb_mutate_split(&p->poly[pi]); } } gp_pop_t pop = { .len = 16, .weak_kill = 5, .clone_times = 2, .create = pcb_create, .score = pcb_score, .mutate = pcb_mutate, .clone = pcb_clone, .dump = pcb_dump }; int main(int argc, char *argv[]) { int n; common_init(argc, argv); gp_setup(&pop); for(n = 0; n < 10000; n++) { gp_iterate(&pop); if ((pop.pop_cnt % 20) == 0) gp_dump(stdout, &pop, 1); } pnm_save(ref, DUMPDIR "ref.pnm"); free(black); }