ccstruct/polyblk.cpp

Go to the documentation of this file.
00001 
00020 #include    "mfcpch.h"
00021 #include    <stdio.h>
00022 #include          <ctype.h>
00023 #include          <math.h>
00024 #include          "elst.h"
00025 #include    "polyblk.h"
00026 
00027 #include          "hpddef.h"     //must be last (handpd.dll)
00028 
00029 #define PBLOCK_LABEL_SIZE 150
00030 #define INTERSECTING MAX_INT16
00031 
00032 int lessthan(const void *first, const void *second); 
00033 
00034 
00038 POLY_BLOCK::POLY_BLOCK(ICOORDELT_LIST *points, POLY_TYPE t) { 
00039   ICOORDELT_IT v = &vertices;
00040 
00041   vertices.clear ();
00042   v.move_to_first ();
00043   v.add_list_before (points);
00044   compute_bb(); 
00045   type = t;
00046 }
00047 
00048 /* ================== */
00052 void POLY_BLOCK::compute_bb() {  //constructor
00053   ICOORD ibl, itr;               //integer bb
00054   ICOORD botleft;                //bounding box
00055   ICOORD topright;
00056   ICOORD pos;                    //current pos;
00057   ICOORDELT_IT pts = &vertices;  //iterator
00058 
00059   botleft = *pts.data ();
00060   topright = botleft;
00061   do {
00062     pos = *pts.data ();
00063     if (pos.x () < botleft.x ())
00064                                  //get bounding box
00065       botleft = ICOORD (pos.x (), botleft.y ());
00066     if (pos.y () < botleft.y ())
00067       botleft = ICOORD (botleft.x (), pos.y ());
00068     if (pos.x () > topright.x ())
00069       topright = ICOORD (pos.x (), topright.y ());
00070     if (pos.y () > topright.y ())
00071       topright = ICOORD (topright.x (), pos.y ());
00072     pts.forward ();
00073   }
00074   while (!pts.at_first ());
00075   ibl = ICOORD (botleft.x (), botleft.y ());
00076   itr = ICOORD (topright.x (), topright.y ());
00077   box = BOX (ibl, itr);
00078 }
00079 
00080 
00081 /* ================== */
00085 INT16 POLY_BLOCK::winding_number(                     //winding number
00086                                  const ICOORD &point  //point to wind around
00087                                 ) {
00088   INT16 count;                   //winding count
00089   ICOORD pt;                     //current point
00090   ICOORD vec;                    //point to current point
00091   ICOORD vvec;                   //current point to next point
00092   INT32 cross;                   //cross product
00093   ICOORDELT_IT it = &vertices;   //iterator
00094 
00095   count = 0;
00096   do {
00097     pt = *it.data ();
00098     vec = pt - point;
00099     vvec = *it.data_relative (1) - pt;
00100                                  //crossing the line
00101     if (vec.y () <= 0 && vec.y () + vvec.y () > 0) {
00102       cross = vec * vvec;        //cross product
00103       if (cross > 0)
00104         count++;                 //crossing right half
00105       else if (cross == 0)
00106         return INTERSECTING;     //going through point
00107     }
00108     else if (vec.y () > 0 && vec.y () + vvec.y () <= 0) {
00109       cross = vec * vvec;
00110       if (cross < 0)
00111         count--;                 //crossing back
00112       else if (cross == 0)
00113         return INTERSECTING;     //illegal
00114     }
00115     else if (vec.y () == 0 && vec.x () == 0)
00116       return INTERSECTING;
00117     it.forward ();
00118   }
00119   while (!it.at_first ());
00120   return count;                  //winding number
00121 }
00122 
00123 
00124 /* ================== */
00128 BOOL8 POLY_BLOCK::contains(  //other outline
00129                            POLY_BLOCK *other) {
00130   INT16 count;                   //winding count
00131   ICOORDELT_IT it = &vertices;   //iterator
00132   ICOORD vertex;
00133 
00134   if (!box.overlap (*(other->bounding_box ())))
00135     return FALSE;                //can't be contained
00136 
00137   /* check that no vertex of this is inside other */
00138 
00139   do {
00140     vertex = *it.data ();
00141     //get winding number
00142     count = other->winding_number (vertex);
00143     if (count != INTERSECTING)
00144       if (count != 0)
00145         return (FALSE);
00146     it.forward ();
00147   }
00148   while (!it.at_first ());
00149 
00150   /* check that all vertices of other are inside this */
00151   it.set_to_list (other->points ()); //switch lists
00152   do {
00153     vertex = *it.data ();
00154                                  //try other way round
00155     count = winding_number (vertex);
00156     if (count != INTERSECTING)
00157       if (count == 0)
00158         return (FALSE);
00159     it.forward ();
00160   }
00161   while (!it.at_first ());
00162   return TRUE;
00163 }
00164 
00165 
00166 /* ================== */
00170 void POLY_BLOCK::rotate(                 //constructor
00171                         FCOORD rotation  //cos,sin of angle
00172                        ) {
00173   FCOORD pos;                    //current pos;
00174   ICOORDELT *pt;                 //current point
00175   ICOORDELT_IT pts = &vertices;  //iterator
00176 
00177   do {
00178     pt = pts.data ();
00179     pos.set_x (pt->x ());
00180     pos.set_y (pt->y ());
00181     pos.rotate (rotation);
00182     pt->set_x ((INT16) (floor (pos.x () + 0.5)));
00183     pt->set_y ((INT16) (floor (pos.y () + 0.5)));
00184     pts.forward ();
00185   }
00186   while (!pts.at_first ());
00187   compute_bb(); 
00188 }
00189 
00190 
00191 /* ================== */
00195 void POLY_BLOCK::move(              //constructor
00196                       ICOORD shift  //cos,sin of angle
00197                      ) {
00198   ICOORDELT *pt;                 //current point
00199   ICOORDELT_IT pts = &vertices;  //iterator
00200 
00201   do {
00202     pt = pts.data ();
00203     *pt += shift;
00204     pts.forward ();
00205   }
00206   while (!pts.at_first ());
00207   compute_bb(); 
00208 }
00209 
00210 
00211 /* ================== */
00215 #ifndef GRAPHICS_DISABLED
00216 void POLY_BLOCK::plot(WINDOW window, COLOUR colour, INT32 num) { 
00217   ICOORDELT_IT v = &vertices;
00218 
00219   line_color_index(window, colour); 
00220   v.move_to_first ();
00221 
00222   if (num > 0) {
00223     text_color_index(window, colour); 
00224     character_height (window, (float) 80);
00225     text_font_index (window, 6);
00226     char temp_buff[34];
00227     #ifdef __UNIX__
00228     sprintf(temp_buff, INT32FORMAT, num); 
00229     #else
00230     ltoa (num, temp_buff, 10);
00231     #endif
00232     text2d (window, v.data ()->x (), v.data ()->y (), temp_buff, 0, FALSE);
00233   }
00234   move2d (window, v.data ()->x (), v.data ()->y ());
00235   for (v.mark_cycle_pt (); !v.cycled_list (); v.forward ())
00236     draw2d (window, v.data ()->x (), v.data ()->y ());
00237   v.move_to_first ();
00238   draw2d (window, v.data ()->x (), v.data ()->y ());
00239 }
00240 
00241 
00242 /* ================== */
00246 void POLY_BLOCK::fill(WINDOW window, COLOUR colour) { 
00247   INT16 y;
00248   INT16 width;
00249   PB_LINE_IT *lines;
00250   ICOORDELT_LIST *segments;
00251   ICOORDELT_IT s_it;
00252 
00253   lines = new PB_LINE_IT (this);
00254 
00255   line_color_index(window, colour); 
00256 
00257   for (y = this->bounding_box ()->bottom ();
00258   y <= this->bounding_box ()->top (); y++) {
00259     segments = lines->get_line (y);
00260     if (!segments->empty ()) {
00261       s_it.set_to_list (segments);
00262       for (s_it.mark_cycle_pt (); !s_it.cycled_list (); s_it.forward ()) {
00263         // Note different use of ICOORDELT, x coord is x coord of pixel
00264         // at the start of line segment, y coord is length of line segment
00265         // Last pixel is start pixel + length.
00266         width = s_it.data ()->y ();
00267         move2d (window, s_it.data ()->x (), y);
00268         draw2d (window, s_it.data ()->x () + (float) width, y);
00269       }
00270     }
00271   }
00272 }
00273 #endif
00274 
00275 
00276 /* ================== */
00280 BOOL8 POLY_BLOCK::overlap(  // do polys overlap
00281                           POLY_BLOCK *other) {
00282   INT16 count;                   //winding count
00283   ICOORDELT_IT it = &vertices;   //iterator
00284   ICOORD vertex;
00285 
00286   if (!box.overlap (*(other->bounding_box ())))
00287     return FALSE;                //can't be any overlap
00288 
00289   /* see if a vertex of this is inside other */
00290   do {
00291     vertex = *it.data ();
00292     //get winding number
00293     count = other->winding_number (vertex);
00294     if (count != INTERSECTING)
00295       if (count != 0)
00296         return (TRUE);
00297     it.forward ();
00298   }
00299   while (!it.at_first ());
00300 
00301   /* see if a vertex of other is inside this */
00302 
00303   //switch lists
00304   it.set_to_list (other->points ());
00305   do {
00306     vertex = *it.data ();
00307     //try other way round
00308     count = winding_number (vertex);
00309     if (count != INTERSECTING)
00310       if (count != 0)
00311         return (TRUE);
00312     it.forward ();
00313   }
00314   while (!it.at_first ());
00315   return FALSE;
00316 }
00317 
00318 
00319 /* ================== */
00323 ICOORDELT_LIST *PB_LINE_IT::get_line(INT16 y) { 
00324   ICOORDELT_IT v, r;
00325   ICOORDELT_LIST *result;
00326   ICOORDELT *x, *current, *previous;
00327   float fy, fx;
00328 
00329   fy = (float) (y + 0.5);
00330   result = new ICOORDELT_LIST ();
00331   r.set_to_list (result);
00332   v.set_to_list (block->points ());
00333 
00334   for (v.mark_cycle_pt (); !v.cycled_list (); v.forward ()) {
00335     if (((v.data_relative (-1)->y () > y) && (v.data ()->y () <= y))
00336     || ((v.data_relative (-1)->y () <= y) && (v.data ()->y () > y))) {
00337       previous = v.data_relative (-1);
00338       current = v.data ();
00339       fx = (float) (0.5 + previous->x () +
00340         (current->x () - previous->x ()) * (fy -
00341         previous->y ()) /
00342         (current->y () - previous->y ()));
00343       x = new ICOORDELT ((INT16) fx, 0);
00344       r.add_to_end (x);
00345     }
00346   }
00347 
00348   if (!r.empty ()) {
00349     r.sort (lessthan);
00350     for (r.mark_cycle_pt (); !r.cycled_list (); r.forward ())
00351       x = r.data ();
00352     for (r.mark_cycle_pt (); !r.cycled_list (); r.forward ()) {
00353       r.data ()->set_y (r.data_relative (1)->x () - r.data ()->x ());
00354       r.forward ();
00355       delete (r.extract ());
00356     }
00357   }
00358 
00359   return result;
00360 }
00361 
00362 
00363 /* ================== */
00367 int lessthan(const void *first, const void *second) { 
00368   ICOORDELT *p1 = (*(ICOORDELT **) first);
00369   ICOORDELT *p2 = (*(ICOORDELT **) second);
00370 
00371   if (p1->x () < p2->x ())
00372     return (-1);
00373   else if (p1->x () > p2->x ())
00374     return (1);
00375   else
00376     return (0);
00377 }
00378 
00379 
00380 /* ================== */
00384 void POLY_BLOCK::serialise_asc(         //convert to ascii
00385                                FILE *f  //file to use
00386                               ) {
00387   vertices.serialise_asc (f);
00388   box.serialise_asc (f);
00389   serialise_INT32(f, type); 
00390 }
00391 
00392 
00393 /* ================== */
00397 void POLY_BLOCK::de_serialise_asc(         //convert from ascii
00398                                   FILE *f  //file to use
00399                                  ) {
00400   vertices.de_serialise_asc (f);
00401   box.de_serialise_asc (f);
00402   type = (POLY_TYPE) de_serialise_INT32 (f);
00403 }

Generated on Wed Feb 28 19:49:08 2007 for Tesseract by  doxygen 1.5.1