/* * Module: sort_lines * * This file contains functions which sort the marks into a * "readable sequence" Sorts the marks by their y baseline then * by their x centroid. * * Author: * Stuart Inglis (singlis@internz.co.nz) * (c) 1998 */ #include #include #include #include "globals.h" #include "marklist.h" #include "sort_lines.h" #include "vector.h" #include "line.h" static int cmpint(const void *e1, const void *e2) { return ( ((int*)e1) - ((int*)e2) ); } static int CmpOnY(const void *e1, const void *e2) { return ( (((marktype*)e1)->ypos+((marktype*)e1)->h-1) - (((marktype*)e2)->ypos+((marktype*)e2)->h-1)); } /* a +ve rotation rotates anti-clockwise from east */ /* * (100,0) rotated 90 degrees is (100,0) * * (0,100) * | * | * | * | * | * --+---------- (100,0) * */ void rot(double *x, double *y, const double theta, const double cx, const double cy) { double xx,yy; *x-=cx; *y-=cy; xx=(*x)*cos(theta) - (*y)*sin(theta); yy=(*x)*sin(theta) + (*y)*cos(theta); *x=xx+cx; *y=yy+cy; } void rot_check() { double xx,yy; xx=100; yy=0; rot(&xx,&yy,DEG2RAD(90),0,0); if(!(fabs(xx-0)<1e-8) && (fabs(yy-100)<1e-8)){ fprintf(stderr,"rot() violated! %g %g\n",xx,yy); } xx=100; yy=0; rot(&xx,&yy,-DEG2RAD(90),0,0); if(!(fabs(xx-0)<1e-8) && (fabs(yy+100)<1e-8)){ fprintf(stderr,"rot() violated! %g %g\n",xx,yy); } } marklistptr sortmarks_random(const marklistptr listofmarks, const int imagew, const int imageh, const double rotated_angle, const int DPI) { marklistptr step,listret=NULL; marktype *row_of_marks=NULL; marktype *random_rows=NULL; int i,len,left; if(listofmarks==NULL) return NULL; if((imagew==0) || (imageh==0)) return listofmarks; assert((rotated_angle>=-180) &&(rotated_angle<=180)); assert(DPI); len=marklist_length(listofmarks); CALLOC(row_of_marks,len,marktype); CALLOC(random_rows,len,marktype); for(i=0,step=listofmarks; step ;i++,step=step->next){ row_of_marks[i]=marktype_copy(step->data); } listret=NULL; srandom(len); left=len; for(i=0;i=-180) &&(rotated_angle<=180)); assert(DPI); len=marklist_length(listofmarks); pixels=mm2pixels(globals.g_reading_parameter,DPI); assert(pixels<=10000); vector_alloc(&profile, imageh*3); for(step=listofmarks;step;step=step->next){ x=step->data.xpos; y=step->data.ypos+step->data.h-1; rot(&x,&y,DEG2RAD(-5),imagew/2.0,imageh/2.0); assert(imageh+(int)y >=0); assert(imageh+(int)y < profile.size); profile.v[imageh+(int)y]++; } for(i=0;inext){ double x,y; x=step->data.xpos; y=step->data.ypos+step->data.h-1; rot(&x,&y,DEG2RAD(-5),imagew/2.0,imageh/2.0); if((y>=start) && (ydata); } } } for(i=0;i=-180) &&(rotated_angle<=180)); assert(DPI); len=marklist_length(listofmarks); CALLOC(all_marks,len,marktype); for(i=0,step=listofmarks; step ;i++,step=step->next){ all_marks[i]=step->data; } qsort((void*)all_marks,(unsigned int)len,sizeof(marktype),CmpOnY); baseline=-1; for(i=0;i=0); /* if t is higher than the baseline */ if(t<=baseline){ /* on line */ line_addmark(&lines[num_lines-1],&all_marks[i]); } else { /* start of a new line */ NEW_LINE; baseline=all_marks[i].ypos+all_marks[i].h-1; line_addmark(&lines[num_lines-1],&all_marks[i]); } } for(i=0;inext){ double x,y,w,h,oldh; step->data.symnum=i; all_marks_rot[i]=step->data; x=step->data.xpos; y=step->data.ypos; /* it's -ve because you want to rotate it the opposite way */ /* but it's -ve that again, because y increases downwards */ rot(&x,&y,skew_of_page,imagew/2.0,imageh/2.0); all_marks_rot[i].xpos=ROUND(x); all_marks_rot[i].ypos=ROUND(y); w=step->data.w; h=step->data.h; assert(w && h); rot(&w,&h,skew_of_page,0,0); all_marks_rot[i].w=ROUND(w); if(all_marks_rot[i].w==0){ all_marks_rot[i].w++; } if(all_marks_rot[i].h==0){ all_marks_rot[i].h++; } all_marks_rot[i].start_of_line=0; } qsort((void*)all_marks_rot,(unsigned int)len,sizeof(marktype),CmpOnY); while(len>0){ act=MIN(TENTATIVE,len); for(i=0;i