#include #include #include #include #include #include "c24lib/image/image.h" #include "c24lib/image/draw.h" #include "c24lib/image/pnm.h" #include "pcb_draw.h" int stat[100]; static inline void ray(image_t *i, double x, double y, double dx, double dy, int *out) { pixel_t *p; int h = 0, xx, yy; do { x += dx; y += dy; xx = round(x); yy = round(y); p = &image_pix(i, xx, yy); h++; } while(p->r == 0); if (h < *out) *out = h; } static inline int height(image_t *i, int cx, int cy) { pixel_t *p; double dx, dy; int h = i->sx + i->sy; p = &image_pix(i, cx, cy); if (p->r != 0) return 0; for(dy = -1.0; dy <= 1.0; dy+=0.27) for(dx = -1.0; dx <= 1.0; dx+=0.27) ray(i, (double)cx, (double)cy, dx, dy, &h); return h; } static int near(int *hg, int my, double cx, double cy, int width, int clear) { int x1 = round(cx - 1), x2 = round(cx + 1); int y1 = round(cy - 1), y2 = round(cy + 1); int x, y; for(y = y1; y <= y2; y++) { for(x = x1; x <= x2; x++) { if (hg[x + y*width] == my) { if (clear) hg[x + y*width] = 0; return 1; } } } return 0; } static int find_line(image_t *trace, int *hg, int my, int cx, int cy, double ang, int width) { double dx, dy, x, y, ex, ey; int len = -2; dx = cos(ang); dy = sin(ang); x = cx; y = cy; do { len++; x += dx; y += dy; if (trace != NULL) { image_pix(trace, (int)round(x), (int)round(y)) = pixel_blue; hg[(int)round(x) + (int)round(y) * width] = 0; } } while(near(hg, my, x, y, width, trace != NULL)); ex = x; ey = y; x = cx; y = cy; do { len++; x -= dx; y -= dy; if (trace != NULL) { image_pix(trace, (int)round(x), (int)round(y)) = pixel_blue; hg[(int)round(x) + (int)round(y) * width] = 0; } } while(near(hg, my, x, y, width, trace != NULL)); if (trace != NULL) { printf("stroke %d %d %d %d\n", (int)round(ex), (int)round(ey), (int)round(x), (int)round(y)); } return len; } int main(int arc, char *argv[]) { image_t *ref; int *hg; int maxh = 0; int x, y, n, cutoff, end; char *ref_fn = "l.pnm"; if (argv[1] != NULL) ref_fn = argv[1]; ref = pnm_load(ref_fn); /* height map */ hg = calloc(sizeof(int), ref->sx * ref->sy); for(y = 1; y < ref->sy-1; y++) { for(x = 1; x < ref->sy-1; x++) { int h = height(ref, x, y); if (h > maxh) maxh = h; stat[h]++; printf("%d", h); hg[x + y*ref->sx] = h; } printf("\n"); } cutoff = 0; for(n = 1; n <= maxh; n++) { printf("h=%d %d\n", n, stat[n]); if ((n > 1) && (stat[n] < stat[n-1]/2) && (cutoff == 0)) { cutoff = n-1; } } printf("-- cutoff=%d\n", cutoff); end = ref->sx * ref->sy; for(n = 0; n < end; n++) { if (hg[n] == cutoff) { ref->pixmap[n] = pixel_red; } else if (ref->pixmap[n].r != 255) { ref->pixmap[n].r = 200; ref->pixmap[n].g = 200; ref->pixmap[n].b = 200; } } /* brute force lines */ for(;;) { int best_len = 0, bestx, besty; double besta; for(n = 0; n < end; n++) { if (hg[n] == cutoff) { double a; int x, y; x = image_x(ref, ref->pixmap+n); y = image_y(ref, ref->pixmap+n); for(a = 0; a < M_PI; a+=0.1) { int len = find_line(NULL, hg, cutoff, x, y, a, ref->sx); if (len > best_len) { best_len = len; bestx = x; besty = y; besta = a; } } } } if (best_len <= cutoff*3) break; printf("len=%d\n", best_len); find_line(ref, hg, cutoff, bestx, besty, besta, ref->sx); } pnm_save(ref, "OUT.pnm"); }