6 #include "c24lib/image/image.h"
7 #include "c24lib/image/draw.h"
8 #include "c24lib/image/pnm.h"
13 #define DUMPDIR "/tmp/gpstroke/"
17 #define OPTIMIZE_FROM 5000
18 #define COOL_PERIOD 2000
21 #define ITERATIONS 21000
22 #define STROKE_PENALTY 1000
26 #define MAX_STROKES 64
28 image_t
*ref
, *canvas
;
31 int x1
, y1
, x2
, y2
, th
;
36 stroke_t str
[MAX_STROKES
];
39 #include "pcb_common.h"
41 static inline int pcb_num_strokes(pcb_t
*p
)
46 static void pcb_dump_str(FILE *f
, pcb_t
*p
)
49 for(n
= 0; n
< p
->len
; n
++)
50 fprintf(f
,"stroke %d %d %d %d %d\n", p
->str
[n
].x1
, p
->str
[n
].y1
, p
->str
[n
].x2
, p
->str
[n
].y2
, p
->str
[n
].th
);
54 static inline void pcb_draw(image_t
*img
, pcb_t
*p
)
58 draw_color(pixel_black
);
59 for(n
= 0; n
< p
->len
; n
++)
60 draw_pcb_line(img
, p
->str
[n
].x1
, p
->str
[n
].y1
, p
->str
[n
].x2
, p
->str
[n
].y2
, clamp(p
->str
[n
].th
, MIN_TH
, MAX_TH
));
63 static inline void rand_stroke(stroke_t
*s
)
65 s
->x1
= myrand(0, ref
->sx
-1);
66 s
->x2
= myrand(0, ref
->sx
-1);
67 s
->y1
= myrand(0, ref
->sy
-1);
68 s
->y2
= myrand(0, ref
->sy
-1);
69 s
->th
= myrand(1, MAX_TH
);
72 static pcb_t
*load_str(char *fn
)
75 FILE *f
= fopen(fn
, "r");
79 p
= calloc(sizeof(pcb_t
), 1);
80 while(fgets(line
, sizeof(line
), f
) != NULL
) {
82 int x1
, y1
, x2
, y2
, th
;
83 if (strncmp(s
, "stroke", 6) == 0)
86 if (sscanf(s
, "%d %d %d %d %d", &x1
, &y1
, &x2
, &y2
, &th
) == 5) {
87 stroke_t
*s
= &p
->str
[p
->len
];
100 void *pcb_create(void)
102 pcb_t
*p
= malloc(sizeof(pcb_t
));
105 if (default_new
!= NULL
) {
106 memcpy(p
, default_new
, sizeof(pcb_t
));
110 p
->len
= myrand(1, max_strokes
/2);
111 for(n
= 0; n
< p
->len
; n
++)
112 rand_stroke(&p
->str
[n
]);
117 static inline void pcb_mutate_add(pcb_t
*p
)
120 if (p
->len
>= MAX_STROKES
)
123 loc
= myrand(0, black_len
-1);
125 x
= image_x(ref
, ref
->pixmap
+black
[loc
]);
126 y
= image_y(ref
, ref
->pixmap
+black
[loc
]);
128 p
->str
[p
->len
].x1
= x
;
129 p
->str
[p
->len
].y1
= y
;
130 p
->str
[p
->len
].x2
= x
+ myrand(2, 20) - 10;
131 p
->str
[p
->len
].y2
= y
+ myrand(2, 20) - 10;
132 p
->str
[p
->len
].th
= myrand(3, 10);
136 static inline void pcb_del_stroke(pcb_t
*p
, int idx
)
139 rem
= p
->len
- idx
- 1;
141 memmove(p
->str
+idx
, p
->str
+idx
+1, rem
*sizeof(stroke_t
));
146 static inline void pcb_mutate_del(pcb_t
*p
)
151 pcb_del_stroke(p
, myrand(0, p
->len
-1));
154 static inline void pcb_mutate_chg(pcb_t
*p
)
156 int idx
= myrand(0, p
->len
-1);
157 int fld
= myrand(0, 5);
158 int dirx
= (rand() % 3) - 1;
159 int diry
= (rand() % 3) - 1;
160 int dir
= (rand() % 2) ? 1 : -1;
165 tune(p
->str
[idx
].x1
, 0, ref
->sx
, dirx
);
166 tune(p
->str
[idx
].y1
, 0, ref
->sy
, diry
);
169 tune(p
->str
[idx
].x2
, 0, ref
->sx
, dirx
);
170 tune(p
->str
[idx
].y2
, 0, ref
->sy
, diry
);
172 case 2: tune(p
->str
[idx
].th
, MIN_TH
, MAX_TH
, dir
); break;
173 case 3: rand_stroke(&p
->str
[idx
]); break;
175 tmp
= p
->str
[idx
].x1
;
176 p
->str
[idx
].x1
= p
->str
[idx
].x2
;
177 p
->str
[idx
].x2
= tmp
;
180 tmp
= p
->str
[idx
].y1
;
181 p
->str
[idx
].y1
= p
->str
[idx
].y2
;
182 p
->str
[idx
].y2
= tmp
;
187 #define sqr(a) ((a) * (a))
189 #define dist2(s1, i1, s2, i2) \
190 (sqr(s1.x ## i1 - s2.x ## i2) + sqr(s1.y ## i1 - s2.y ## i2))
192 static inline void pcb_mutate_merge(pcb_t
*p
)
194 int idx1
= myrand(0, p
->len
-1);
195 int idx2
= myrand(0, p
->len
-1);
196 int n
, best
, bestn
, dst
[4];
201 /* merge the closest points */
202 dst
[0] = dist2(p
->str
[idx1
], 1, p
->str
[idx2
], 1);
203 dst
[1] = dist2(p
->str
[idx1
], 1, p
->str
[idx2
], 2);
204 dst
[2] = dist2(p
->str
[idx1
], 2, p
->str
[idx2
], 1);
205 dst
[3] = dist2(p
->str
[idx1
], 2, p
->str
[idx2
], 2);
207 best
= sqr(ref
->sx
+ ref
->sy
);
208 for(n
= 0; n
< 4; n
++) {
217 p
->str
[idx1
].x2
= p
->str
[idx2
].x1
;
218 p
->str
[idx1
].y2
= p
->str
[idx2
].y1
;
221 p
->str
[idx1
].x2
= p
->str
[idx2
].x2
;
222 p
->str
[idx1
].y2
= p
->str
[idx2
].y2
;
225 p
->str
[idx1
].x1
= p
->str
[idx2
].x1
;
226 p
->str
[idx1
].y1
= p
->str
[idx2
].y1
;
229 p
->str
[idx1
].x1
= p
->str
[idx2
].x2
;
230 p
->str
[idx1
].y1
= p
->str
[idx2
].y2
;
233 pcb_del_stroke(p
, idx2
);
236 void pcb_mutate(void *data
)
238 int n
=myrand(0, 100);
240 pcb_mutate_chg(data
);
242 case 0: pcb_mutate_add(data
); break;
243 case 1: pcb_mutate_del(data
); break;
244 case 2: pcb_mutate_merge(data
); break;
252 .create
= pcb_create
,
254 .mutate
= pcb_mutate
,
259 int main(int argc
, char *argv
[])
261 int n
, last_best
= -1;
263 common_init(argc
, argv
);
267 for(n
= 0; n
< ITERATIONS
; n
++) {
269 if ((n
>= OPTIMIZE_FROM
) && ((n
% COOL_PERIOD
) == 0)) {
270 stroke_penalty
*= 1.1;
274 if (((pop
.pop_cnt
% 50) == 0) && (pop
.indiv
[0].fitness
!= last_best
)) {
275 gp_dump(stdout
, &pop
, 1);
276 last_best
= pop
.indiv
[0].fitness
;
279 pnm_save(ref
, DUMPDIR
"ref.pnm");