several small fixes in polygon code polyok
authorMatthias Kramm <kramm@matthias-kramms-macbook-pro.local>
Mon, 25 May 2009 00:46:04 +0000 (17:46 -0700)
committerMatthias Kramm <kramm@matthias-kramms-macbook-pro.local>
Mon, 25 May 2009 00:46:04 +0000 (17:46 -0700)
lib/gfxpoly/active.c
lib/gfxpoly/convert.c
lib/gfxpoly/poly.c
lib/gfxpoly/test.c
lib/gfxtools.c
lib/gfxtools.h

index 5a2c451..340d5bc 100644 (file)
@@ -46,7 +46,7 @@ void actlist_verify(actlist_t*a, int32_t y)
                 /* we need to re-evaluate the x of the previous segment. if we
                    try to store it, it might end up being converted to a double,
                    which will make it non-equal to (and possibly larger than) the
                 /* we need to re-evaluate the x of the previous segment. if we
                    try to store it, it might end up being converted to a double,
                    which will make it non-equal to (and possibly larger than) the
-                   "long double" the FPU has in it's register. This only happens
+                   "long double" the FPU has in its register. This only happens
                    when compiler optimizations are turned on. */
                 assert((XPOS(s, y) - XPOS(l, y)) >= 0);
                 assert(XDIFF(s,l,y) >= 0);
                    when compiler optimizations are turned on. */
                 assert((XPOS(s, y) - XPOS(l, y)) >= 0);
                 assert(XDIFF(s,l,y) >= 0);
index 5619f79..ad884f1 100644 (file)
@@ -188,24 +188,20 @@ typedef struct _compactpoly {
     segment_dir_t dir;
 } compactpoly_t;
 
     segment_dir_t dir;
 } compactpoly_t;
 
-void add_segment(compactpoly_t*data, point_t start, segment_dir_t dir)
+void finish_segment(compactpoly_t*data)
 {
 {
+    if(data->num_points <= 1)
+       return;
     if(data->poly->num_strokes == data->strokes_size) {
        data->strokes_size <<= 1;
        assert(data->strokes_size > data->poly->num_strokes);
     if(data->poly->num_strokes == data->strokes_size) {
        data->strokes_size <<= 1;
        assert(data->strokes_size > data->poly->num_strokes);
-       data->poly->strokes = rfx_realloc(data->poly->strokes, data->strokes_size);
+       data->poly->strokes = rfx_realloc(data->poly->strokes, sizeof(gfxstroke_t)*data->strokes_size);
     }
     }
-    data->poly->strokes[data->poly->num_strokes].dir = dir;
-    data->points[0] = start;
-    data->num_points = 1;
-    data->dir = dir;
-}
-void finish_segment(compactpoly_t*data)
-{
-    if(data->num_points <= 1)
-       return;
     point_t*p = malloc(sizeof(point_t)*data->num_points);
     point_t*p = malloc(sizeof(point_t)*data->num_points);
-    data->poly->strokes[data->poly->num_strokes-1].points = p;
+    gfxstroke_t*s = &data->poly->strokes[data->poly->num_strokes];
+    s->num_points = data->num_points;
+    s->dir = data->dir;
+    s->points = p;
     if(data->dir == DIR_UP) {
        int t;
        int s = data->num_points;
     if(data->dir == DIR_UP) {
        int t;
        int s = data->num_points;
@@ -232,16 +228,17 @@ static void compactlineto(void*_data, double _x, double _y)
     point_t p;
     p.x = convert_coord(_x);
     p.y = convert_coord(_y);
     point_t p;
     p.x = convert_coord(_x);
     p.y = convert_coord(_y);
-    if(p.y < data->last.y && data->dir != DIR_UP ||
-       p.y > data->last.y && data->dir != DIR_DOWN) {
-       data->dir = p.y > data->last.y ? DIR_DOWN : DIR_UP;
+    if(p.y <  data->last.y && data->dir != DIR_UP ||
+       p.y >= data->last.y && data->dir != DIR_DOWN) {
        finish_segment(data);
        finish_segment(data);
-       add_segment(data, data->last, data->dir);
+       data->dir = p.y > data->last.y ? DIR_DOWN : DIR_UP;
+       data->points[0] = data->last;
+       data->num_points = 1;
     }
     if(data->points_size == data->num_points) {
        data->points_size <<= 1;
        assert(data->points_size > data->num_points);
     }
     if(data->points_size == data->num_points) {
        data->points_size <<= 1;
        assert(data->points_size > data->num_points);
-       data->points = rfx_realloc(data->points, data->points_size);
+       data->points = rfx_realloc(data->points, sizeof(point_t)*data->points_size);
     }
     data->points[data->num_points++] = p;
 }
     }
     data->points[data->num_points++] = p;
 }
@@ -259,13 +256,14 @@ static void compactinit(compactpoly_t*data, double gridsize)
     data->strokes_size = 16;
     data->num_points = 0;
     data->points_size = 16;
     data->strokes_size = 16;
     data->num_points = 0;
     data->points_size = 16;
+    data->dir = DIR_UNKNOWN;
     data->points = (point_t*)rfx_alloc(sizeof(point_t)*data->points_size);
     data->poly->strokes = (gfxstroke_t*)rfx_alloc(sizeof(gfxstroke_t)*data->strokes_size);
 }
 static gfxcompactpoly_t*compactfinish(compactpoly_t*data)
 {
     finish_segment(data);
     data->points = (point_t*)rfx_alloc(sizeof(point_t)*data->points_size);
     data->poly->strokes = (gfxstroke_t*)rfx_alloc(sizeof(gfxstroke_t)*data->strokes_size);
 }
 static gfxcompactpoly_t*compactfinish(compactpoly_t*data)
 {
     finish_segment(data);
-    data->poly->strokes = rfx_realloc(data->poly->strokes, sizeof(gfxstroke_t)*data->poly->num_strokes);
+    data->poly->strokes = (gfxstroke_t*)rfx_realloc(data->poly->strokes, sizeof(gfxstroke_t)*data->poly->num_strokes);
     free(data->points);
     return data->poly;
 }
     free(data->points);
     return data->poly;
 }
index 4bbd776..ca81be1 100644 (file)
 static gfxpoly_t*current_polygon = 0;
 void gfxpoly_fail(char*expr, char*file, int line, const char*function)
 {
 static gfxpoly_t*current_polygon = 0;
 void gfxpoly_fail(char*expr, char*file, int line, const char*function)
 {
-    if(!current_polygon) {fprintf(stderr, "error outside polygon\n");exit(1);}
+    if(!current_polygon) {
+       fprintf(stderr, "assert(%s) failed in %s in line %d: %s\n", expr, file, line, function);
+       exit(1);
+    }
 
     void*md5 = init_md5();
     
 
     void*md5 = init_md5();
     
@@ -110,15 +113,21 @@ static int compare_events(const void*_a,const void*_b)
     /* we need to schedule end after intersect (so that a segment about
        to end has a chance to tear up a few other segs first) and start
        events after end (in order not to confuse the intersection check, which
     /* we need to schedule end after intersect (so that a segment about
        to end has a chance to tear up a few other segs first) and start
        events after end (in order not to confuse the intersection check, which
-       assumes there's an actual y overlap between active segments)). 
+       assumes there's an actual y overlap between active segments, and 
+       because ending segments in the active list make it difficult to insert
+       starting segments at the right position)). 
        Horizontal lines come last, because the only purpose
        they have is to create snapping coordinates for the segments (still)
        existing in this scanline.
     */
     d = b->type - a->type;
     if(d) return d;
        Horizontal lines come last, because the only purpose
        they have is to create snapping coordinates for the segments (still)
        existing in this scanline.
     */
     d = b->type - a->type;
     if(d) return d;
-    d = b->p.x - a->p.x;
-    return d;
+    return 0;
+
+    /* I don't see any reason why we would need to order by x- at least as long
+       as we do horizontal lines in a seperate pass */
+    //d = b->p.x - a->p.x;
+    //return d;
 }
 
 gfxpoly_t* gfxpoly_new(double gridsize)
 }
 
 gfxpoly_t* gfxpoly_new(double gridsize)
@@ -186,6 +195,7 @@ void gfxpoly_dump(gfxpoly_t*poly)
 {
     edge_t* s = poly->edges;
     double g = poly->gridsize;
 {
     edge_t* s = poly->edges;
     double g = poly->gridsize;
+    fprintf(stderr, "polyon %08x (gridsize: %f)\n", poly, poly->gridsize);
     while(s) {
         fprintf(stderr, "(%f,%f) -> (%f,%f)\n", s->a.x*g, s->a.y*g, s->b.x*g, s->b.y*g);
         s = s->next;
     while(s) {
         fprintf(stderr, "(%f,%f) -> (%f,%f)\n", s->a.x*g, s->a.y*g, s->b.x*g, s->b.y*g);
         s = s->next;
@@ -358,7 +368,6 @@ static void schedule_crossing(status_t*status, segment_t*s1, segment_t*s2)
     /* the code that's required (and the checks you can perform) before
        it can be said with 100% certainty that we indeed have a valid crossing
        amazes me every time. -mk */
     /* the code that's required (and the checks you can perform) before
        it can be said with 100% certainty that we indeed have a valid crossing
        amazes me every time. -mk */
-
 #ifdef CHECKS
     assert(s1!=s2);
     assert(s1->right == s2);
 #ifdef CHECKS
     assert(s1!=s2);
     assert(s1->right == s2);
@@ -1046,12 +1055,11 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c
             x = e->p.x;
             fill ^= 1;//(before.is_filled != after.is_filled);
 #ifdef DEBUG
             x = e->p.x;
             fill ^= 1;//(before.is_filled != after.is_filled);
 #ifdef DEBUG
-            fprintf(stderr, "%d) event=%s[%d] left:[%d] x:%d before:%d after:%d\n",
+            fprintf(stderr, "%d) event=%s[%d] left:[%d] x:%d\n",
                     y, e->type==EVENT_START?"start":"end",
                     s->nr,
                     left?left->nr:-1,
                     y, e->type==EVENT_START?"start":"end",
                     s->nr,
                     left?left->nr:-1,
-                    x,
-                    before.is_filled, after.is_filled);
+                    x);
 #endif
 
             if(e->type == EVENT_END)
 #endif
 
             if(e->type == EVENT_END)
index 6a41566..c990ca2 100644 (file)
@@ -28,21 +28,17 @@ gfxline_t*mkstar(int x1, int y1, int x2, int y2)
 gfxline_t* mkrandomshape(int range, int n)
 {
     int i;
 gfxline_t* mkrandomshape(int range, int n)
 {
     int i;
-    gfxline_t* line = malloc(sizeof(gfxline_t)*n*2);
+    gfxline_t* line = malloc(sizeof(gfxline_t)*n);
     for(i=0;i<n;i++) {
         line[i].type = i?gfx_lineTo:gfx_moveTo;
         line[i].x = lrand48()%range - range/2;
         line[i].y = lrand48()%range - range/2;
         line[i].next = &line[i+1];
     for(i=0;i<n;i++) {
         line[i].type = i?gfx_lineTo:gfx_moveTo;
         line[i].x = lrand48()%range - range/2;
         line[i].y = lrand48()%range - range/2;
         line[i].next = &line[i+1];
-        line[n*2-i-1].type = gfx_lineTo;
-        line[n*2-i-1].x = line[i].x;
-        line[n*2-i-1].y = line[i].y;
-        line[n*2-i-1].next = &line[n*2-i];
     }
     }
-    line[n*2-1].next = 0;
     line[n-1].x = line[0].x;
     line[n-1].y = line[0].y;
     line[n-1].next = 0;
     line[n-1].x = line[0].x;
     line[n-1].y = line[0].y;
     line[n-1].next = 0;
+    return line;
 }
 
 gfxline_t* mkchessboard()
 }
 
 gfxline_t* mkchessboard()
@@ -102,16 +98,35 @@ gfxline_t* mkchessboard()
         l[4].y = y-sizey;
         gfxline_append(b, l);
     }
         l[4].y = y-sizey;
         gfxline_append(b, l);
     }
-    if(do_centerpiece)
-    for(t=0;t<5;t++) {
-        gfxline_t*l = gfxline_makerectangle(-9*spacing,-10,9*spacing,10);
-        gfxmatrix_t matrix;
-        memset(&matrix, 0, sizeof(gfxmatrix_t));
-        double ua=t*0.43;
-        matrix.m00=cos(ua);matrix.m10=sin(ua);
-        matrix.m01=-sin(ua);matrix.m11=cos(ua);
-        gfxline_transform(l, &matrix);
-        gfxline_append(b, l);
+    if(do_centerpiece) {
+       for(t=0;t<5;t++) {
+           gfxline_t*l = gfxline_makerectangle(-9*spacing,-10,9*spacing,10);
+           gfxmatrix_t matrix;
+           memset(&matrix, 0, sizeof(gfxmatrix_t));
+           double ua=t*0.43;
+           matrix.m00=cos(ua);matrix.m10=sin(ua);
+           matrix.m01=-sin(ua);matrix.m11=cos(ua);
+           gfxline_transform(l, &matrix);
+           gfxline_append(b, l);
+       }
+       gfxline_append(b, gfxline_makecircle(100,100,100,100));
+    }
+    return b;
+}
+
+gfxline_t* make_circles()
+{
+    gfxline_t*b = 0;
+    unsigned int c = 0;
+    int t;
+    for(t=0;t<30;t++) {
+        c = crc32_add_byte(c, t);
+       int x = c%200;
+       c = crc32_add_byte(c, t);
+       int y = c%200;;
+       c = crc32_add_byte(c, t^0x55);
+       int r = c%100;
+       b = gfxline_append(b, gfxline_makecircle(x,y,r,r));
     }
     return b;
 }
     }
     return b;
 }
@@ -120,26 +135,28 @@ static windcontext_t onepolygon = {1};
 
 int test0()
 {
 
 int test0()
 {
-    gfxline_t* b = mkchessboard();
+    //gfxline_t* b = mkchessboard();
+    //gfxline_t* b = mkrandomshape(100,7);
+    gfxline_t* b = gfxline_makecircle(100,100,100,100);
 
     gfxmatrix_t m;
     memset(&m, 0, sizeof(gfxmatrix_t));
     int t;
     for(t=0;t<360;t++) {
 
     gfxmatrix_t m;
     memset(&m, 0, sizeof(gfxmatrix_t));
     int t;
     for(t=0;t<360;t++) {
-    m.m00 = cos(t*M_PI/180.0);
-    m.m01 = sin(t*M_PI/180.0);
-    m.m10 = -sin(t*M_PI/180.0);
-    m.m11 = cos(t*M_PI/180.0);
-    m.tx = 400*1.41/2;
-    m.ty = 400*1.41/2;
-    gfxline_transform(b, &m);
-
-    gfxpoly_t*poly = gfxpoly_from_gfxline(b, 0.05);
+       m.m00 = cos(t*M_PI/180.0);
+       m.m01 = sin(t*M_PI/180.0);
+       m.m10 = -sin(t*M_PI/180.0);
+       m.m11 = cos(t*M_PI/180.0);
+       m.tx = 400*1.41/2;
+       m.ty = 400*1.41/2;
+       gfxline_transform(b, &m);
+       gfxpoly_t*poly = gfxpoly_from_gfxline(b, 0.05);
+
+       gfxpoly_t*poly2 = gfxpoly_process(poly, &windrule_evenodd, &onepolygon);
+       gfxpoly_destroy(poly2);
+       gfxpoly_destroy(poly);
+    }
     gfxline_free(b);
     gfxline_free(b);
-    gfxpoly_t*poly2 = gfxpoly_process(poly, &windrule_evenodd, &onepolygon);
-    gfxpoly_destroy(poly2);
-    gfxpoly_destroy(poly);
-}
 }
 
 int test1(int argn, char*argv[])
 }
 
 int test1(int argn, char*argv[])
@@ -230,9 +247,10 @@ void test3(int argn, char*argv[])
 
     //gfxline_t*line = mkrandomshape(RANGE, N);
     //windrule_t*rule = &windrule_circular;
 
     //gfxline_t*line = mkrandomshape(RANGE, N);
     //windrule_t*rule = &windrule_circular;
-    gfxline_t*line = mkchessboard();
-    //windrule_t*rule = &windrule_evenodd;
-    windrule_t*rule = &windrule_circular;
+    //gfxline_t*line = mkchessboard();
+    gfxline_t*line = make_circles();
+    windrule_t*rule = &windrule_evenodd;
+    //windrule_t*rule = &windrule_circular;
 
     gfxmatrix_t m;
     memset(&m, 0, sizeof(m));
 
     gfxmatrix_t m;
     memset(&m, 0, sizeof(m));
@@ -250,6 +268,7 @@ void test3(int argn, char*argv[])
 
     int t;
     for(t=0;t<360;t++) {
 
     int t;
     for(t=0;t<360;t++) {
+       fprintf(stderr, "%d\n", t);
         m.m00 = cos(t*M_PI/180.0);
         m.m01 = sin(t*M_PI/180.0);
         m.m10 = -sin(t*M_PI/180.0);
         m.m00 = cos(t*M_PI/180.0);
         m.m01 = sin(t*M_PI/180.0);
         m.m10 = -sin(t*M_PI/180.0);
@@ -409,19 +428,24 @@ void test4(int argn, char*argv[])
 
 void extract_polygons_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) 
 {
 
 void extract_polygons_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) 
 {
-    gfxcompactpoly_t*c = gfxcompactpoly_from_gfxline(line, 0.05);
-    gfxcompactpoly_free(c);
+    //gfxcompactpoly_t*c = gfxcompactpoly_from_gfxline(line, 0.05);
+    //gfxcompactpoly_free(c);
+
     gfxpoly_t*poly = gfxpoly_from_gfxline(line, 0.05);
     gfxpoly_t*poly = gfxpoly_from_gfxline(line, 0.05);
+
+    gfxline_dump(line, stderr, "");
+    gfxpoly_dump(poly);
+
     if(gfxpoly_size(poly)>100000) {
     if(gfxpoly_size(poly)>100000) {
-       printf("%d segments (skipping)\n", gfxpoly_size(poly));
+       fprintf(stderr, "%d segments (skipping)\n", gfxpoly_size(poly));
        return;
     } else {
        return;
     } else {
-       printf("%d segments\n", gfxpoly_size(poly));
+       //fprintf(stderr, "%d segments\n", gfxpoly_size(poly));
     }
 
     if(!gfxpoly_check(poly)) {
         gfxpoly_destroy(poly);
     }
 
     if(!gfxpoly_check(poly)) {
         gfxpoly_destroy(poly);
-        printf("bad polygon\n");
+        fprintf(stderr, "bad polygon\n");
         return;
     }
 
         return;
     }
 
@@ -431,7 +455,7 @@ void extract_polygons_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
     intbbox_t bbox = intbbox_from_polygon(poly, zoom);
     unsigned char*bitmap1 = render_polygon(poly, &bbox, zoom, rule, &onepolygon);
     if(!bitmap_ok(&bbox, bitmap1)) {
     intbbox_t bbox = intbbox_from_polygon(poly, zoom);
     unsigned char*bitmap1 = render_polygon(poly, &bbox, zoom, rule, &onepolygon);
     if(!bitmap_ok(&bbox, bitmap1)) {
-        printf("bad polygon or error in renderer\n");
+        fprintf(stderr, "bad polygon or error in renderer\n");
         return;
     }
     gfxpoly_t*poly2 = gfxpoly_process(poly, rule, &onepolygon);
         return;
     }
     gfxpoly_t*poly2 = gfxpoly_process(poly, rule, &onepolygon);
@@ -521,16 +545,21 @@ void test5(int argn, char*argv[])
             continue;
         char* filename = allocprintf("%s/%s", dir, file->d_name);
 
             continue;
         char* filename = allocprintf("%s/%s", dir, file->d_name);
 
+       if(argn>1) 
+           filename = argv[1];
+
         gfxdocument_t*doc = driver->open(driver, filename);
         gfxdevice_t*out = &extract_polygons;
         int t;
         for(t=1;t<=doc->num_pages;t++) {
         gfxdocument_t*doc = driver->open(driver, filename);
         gfxdevice_t*out = &extract_polygons;
         int t;
         for(t=1;t<=doc->num_pages;t++) {
-            printf("%s (page %d)\n", filename, t);
+            fprintf(stderr, "%s (page %d)\n", filename, t);
             gfxpage_t* page = doc->getpage(doc, t);
             page->render(page, out);
             page->destroy(page);
         }
         doc->destroy(doc);
             gfxpage_t* page = doc->getpage(doc, t);
             page->render(page, out);
             page->destroy(page);
         }
         doc->destroy(doc);
+       if(argn>1) 
+           break;
         free(filename);
     }
     closedir(_dir);
         free(filename);
     }
     closedir(_dir);
@@ -539,5 +568,6 @@ void test5(int argn, char*argv[])
 
 int main(int argn, char*argv[])
 {
 
 int main(int argn, char*argv[])
 {
-    test5(argn, argv);
+    test3(argn, argv);
 }
 }
+
index e79e6fe..8ee2ff4 100644 (file)
@@ -834,6 +834,37 @@ gfxline_t*gfxline_makerectangle(int x1,int y1,int x2, int y2)
     return line;
 }
 
     return line;
 }
 
+gfxline_t*gfxline_makecircle(double x,double y,double rx, double ry)
+{
+    double C1 = 0.2930;    
+    double C2 = 0.4140;   
+    double begin = 0.7070; 
+    gfxline_t* line = (gfxline_t*)rfx_calloc(sizeof(gfxline_t)*9);
+    int t;
+    line[0].type = gfx_moveTo;
+    line[0].x = x+begin*rx;
+    line[0].y = y+begin*ry;
+    for(t=1;t<9;t++) {
+       line[t-1].next = &line[t];
+       line[t].type = gfx_splineTo;
+    }
+    line[t].next = 0;
+#define R(nr,cx,cy,mx,my) \
+    line[nr].sx = line[nr-1].x + (cx); \
+    line[nr].sy = line[nr-1].y + (cy); \
+    line[nr].x = line[nr].sx + (mx); \
+    line[nr].y = line[nr].sy + (my);
+    R(1, -C1*rx,  C1*ry, -C2*rx,      0);
+    R(2, -C2*rx,      0, -C1*rx, -C1*ry);
+    R(3, -C1*rx, -C1*ry,      0, -C2*ry);
+    R(4,      0, -C2*ry,  C1*rx, -C1*ry);
+    R(5,  C1*rx, -C1*ry,  C2*rx,      0);
+    R(6,  C2*rx,      0,  C1*rx,  C1*ry);
+    R(7,  C1*rx,  C1*ry,      0,  C2*ry);
+    R(8,      0,  C2*ry, -C1*rx,  C1*ry);
+    return line;
+}
+
 gfxbbox_t* gfxline_isrectangle(gfxline_t*_l)
 {
     if(!_l)
 gfxbbox_t* gfxline_isrectangle(gfxline_t*_l)
 {
     if(!_l)
index ea511fa..7b7377d 100644 (file)
@@ -87,6 +87,7 @@ void gfxfontlist_free(gfxfontlist_t*list, char deletefonts);
 gfxbbox_t* gfxline_isrectangle(gfxline_t*_l);
 
 gfxline_t*gfxline_makerectangle(int x1, int y1, int x2, int y2);
 gfxbbox_t* gfxline_isrectangle(gfxline_t*_l);
 
 gfxline_t*gfxline_makerectangle(int x1, int y1, int x2, int y2);
+gfxline_t*gfxline_makecircle(double x,double y,double rx, double ry);
 void gfxline_show(gfxline_t*line, FILE*fi);
 
 #ifdef __cplusplus
 void gfxline_show(gfxline_t*line, FILE*fi);
 
 #ifdef __cplusplus