ccstruct/poutline.cpp

Go to the documentation of this file.
00001 
00020 #include "mfcpch.h"
00021 #include          "poutline.h"
00022 
00023 ELISTIZE_S (OUTLINE)
00027 OUTLINE::OUTLINE (               //constructor
00028 const ICOORD & startpt,          //start position
00029 INT8 * compactloop,              //from Tess format
00030 BOOL8 invert,                    //reverse it
00031 ICOORD bot_left,                 //bounding box
00032 ICOORD top_right):
00033 box (bot_left, top_right),
00034 start(startpt) { 
00035   ICOORD pos;                    //current point
00036   ICOORD vec;                    //vector to next
00037   POLYPT *polypt;                //new point
00038   INT8 *vector;                  //compact loop
00039   POLYPT_IT it = &outline;       //iterator
00040 
00041   pos = startpt;
00042   vector = compactloop;
00043   do {
00044                                  //vector to next
00045     vec = ICOORD (*vector, *(vector + 1));
00046                                  //make a new one
00047     polypt = new POLYPT (FCOORD (pos), FCOORD (vec));
00048                                  //add to list
00049     it.add_after_then_move (polypt);
00050     pos += vec;                  //move to next
00051     vector += 2;
00052   }
00053   while (pos != startpt);
00054   if (invert)
00055     reverse();  //now reverse it
00056 }
00057 
00058 
00062 OUTLINE::OUTLINE(                    //constructor
00063                  POLYPT_IT *polypts  //input list
00064                 ) {
00065   POLYPT_IT other_it = *polypts; //end of list
00066 
00067   polypts->move_to_first ();
00068   other_it.move_to_last ();
00069                                  //put in outline
00070   outline.assign_to_sublist (polypts, &other_it);
00071   compute_bb(); 
00072 }
00073 
00074 
00078 void OUTLINE::compute_bb() {  //constructor
00079   ICOORD ibl, itr;               //integer bb
00080   FCOORD botleft;                //bounding box
00081   FCOORD topright;
00082   FCOORD pos;                    //current pos;
00083   POLYPT_IT polypts = &outline;  //iterator
00084 
00085   botleft = polypts.data ()->pos;
00086   topright = botleft;
00087   start = ICOORD ((INT16) botleft.x (), (INT16) botleft.y ());
00088   do {
00089     pos = polypts.data ()->pos;
00090     if (pos.x () < botleft.x ())
00091                                  //get bounding box
00092       botleft = FCOORD (pos.x (), botleft.y ());
00093     if (pos.y () < botleft.y ())
00094       botleft = FCOORD (botleft.x (), pos.y ());
00095     if (pos.x () > topright.x ())
00096       topright = FCOORD (pos.x (), topright.y ());
00097     if (pos.y () > topright.y ())
00098       topright = FCOORD (topright.x (), pos.y ());
00099     polypts.forward ();
00100   }
00101   while (!polypts.at_first ());
00102   ibl = ICOORD ((INT16) botleft.x (), (INT16) botleft.y ());
00103   itr = ICOORD ((INT16) topright.x () + 1, (INT16) topright.y () + 1);
00104   box = BOX (ibl, itr);
00105 }
00106 
00107 
00112 float OUTLINE::area() {  //constructor
00113   FCOORD origin;                 //startpt
00114   FCOORD prev_vec;               //previous value of vec
00115   FCOORD vec;                    //from start to current
00116   float total;                   //total area
00117   POLYPT_IT poly_it = polypts ();//iterator
00118                                  //child outline itertr
00119   OUTLINE_IT child_it(&children); 
00120 
00121   origin = poly_it.data ()->pos;
00122   poly_it.forward ();
00123   vec = poly_it.data ()->pos - origin;
00124   poly_it.forward ();
00125   total = 0.0f;
00126   while (!poly_it.at_first ()) {
00127     prev_vec = vec;
00128     vec = poly_it.data ()->pos - origin;
00129     total += prev_vec * vec;
00130     poly_it.forward ();
00131   }
00132   total /= 2;
00133   for (child_it.mark_cycle_pt (); !child_it.cycled_list ();
00134   child_it.forward ()) {
00135                                  //add ares of childrein
00136     total += child_it.data ()->area ();
00137   }
00138   return total;
00139 }
00140 
00141 
00145 BOOL8
00146 OUTLINE::operator< (             //winding number
00147 OUTLINE & other                  //other outline
00148 ) {
00149   INT16 count;                   //winding count
00150   POLYPT_IT it = &outline;       //iterator
00151 
00152   if (!box.overlap (other.box))
00153     return FALSE;                //can't be contained
00154 
00155   do {
00156     count = other.winding_number (FCOORD (it.data ()->pos));
00157     //get winding number
00158     if (count != INTERSECTING)
00159       return count != 0;
00160     it.forward ();
00161   }
00162   while (!it.at_first ());
00163 
00164                                  //switch lists
00165   it.set_to_list (&other.outline);
00166   do {
00167                                  //try other way round
00168     count = winding_number (FCOORD (it.data ()->pos));
00169     if (count != INTERSECTING)
00170       return count == 0;
00171     it.forward ();
00172   }
00173   while (!it.at_first ());
00174   return TRUE;
00175 }
00176 
00177 
00181 INT16 OUTLINE::winding_number(                     //winding number
00182                               const FCOORD &point  //point to wind around
00183                              ) {
00184   INT16 count;                   //winding count
00185   POLYPT *polypt;                //current point
00186   FCOORD vec;                    //to current point
00187   float cross;                   //cross product
00188   POLYPT_IT it = &outline;       //iterator
00189 
00190   count = 0;
00191   do {
00192     polypt = it.data ();
00193     vec = polypt->pos - point;
00194                                  //crossing the line
00195     if (vec.y () <= 0 && vec.y () + polypt->vec.y () > 0) {
00196       cross = vec * polypt->vec; //cross product
00197       if (cross > 0)
00198         count++;                 //crossing right half
00199       else if (cross == 0)
00200         return INTERSECTING;     //going through point
00201     }
00202     else if (vec.y () > 0 && vec.y () + polypt->vec.y () <= 0) {
00203       cross = vec * polypt->vec;
00204       if (cross < 0)
00205         count--;                 //crossing back
00206       else if (cross == 0)
00207         return INTERSECTING;     //illegal
00208     }
00209     it.forward ();
00210   }
00211   while (!it.at_first ());
00212   return count;                  //winding number
00213 }
00214 
00215 
00219 void OUTLINE::reverse() {  //reverse direction
00220   POLYPT_LIST back_list;         //reversed list
00221   POLYPT_IT dest_it = &back_list;//destination
00222   POLYPT_IT src_it = &outline;   //source list
00223   POLYPT *polypt;                //current point
00224 
00225   do {
00226     polypt = src_it.extract ();
00227                                  //copy in reverse
00228     dest_it.add_after_then_move (polypt);
00229     src_it.backward ();
00230   }
00231   while (!src_it.empty ());
00232   dest_it.move_to_first ();
00233   do {
00234     polypt = dest_it.data ();
00235     polypt->vec = dest_it.data_relative (1)->pos - polypt->pos;
00236     //vector to next
00237     dest_it.forward ();
00238   }
00239   while (!dest_it.at_first ());
00240   dest_it.backward ();
00241   src_it.set_to_list (&back_list);
00242                                  //put it back
00243   outline.assign_to_sublist (&src_it, &dest_it);
00244 }
00245 
00249 void OUTLINE::move(                  // reposition OUTLINE
00250                    const FCOORD vec  // by vector
00251                   ) {
00252                                  //child outline itertr
00253   OUTLINE_IT child_it(&children); 
00254   POLYPT_IT poly_it(&outline);  //outline point itertr
00255 
00256   box.move (vec);
00257 
00258   start.set_x ((INT16) floor (start.x () + vec.x () + 0.5));
00259   // ?? Why ICOORD?
00260   start.set_y ((INT16) floor (start.y () + vec.y () + 0.5));
00261   // ?? Why ICOORD?
00262 
00263   for (poly_it.mark_cycle_pt (); !poly_it.cycled_list (); poly_it.forward ())
00264     poly_it.data ()->pos += vec;
00265 
00266   for (child_it.mark_cycle_pt (); !child_it.cycled_list ();
00267     child_it.forward ())
00268   child_it.data ()->move (vec);  // move child outlines
00269 }
00270 
00271 
00275 void OUTLINE::scale(               // scale OUTLINE
00276                     const float f  // by multiplier
00277                    ) {
00278                                  //child outline itertr
00279   OUTLINE_IT child_it(&children); 
00280   POLYPT_IT poly_it(&outline);  //outline point itertr
00281   POLYPT *pt;
00282 
00283   box.scale (f);
00284 
00285                                  // ?? Why ICOORD?
00286   start.set_x ((INT16) floor (start.x () * f + 0.5));
00287                                  // ?? Why ICOORD?
00288   start.set_y ((INT16) floor (start.y () * f + 0.5));
00289 
00290   for (poly_it.mark_cycle_pt (); !poly_it.cycled_list (); poly_it.forward ()) {
00291     pt = poly_it.data ();
00292     pt->pos *= f;
00293     pt->vec *= f;
00294   }
00295 
00296   for (child_it.mark_cycle_pt (); !child_it.cycled_list ();
00297     child_it.forward ())
00298   child_it.data ()->scale (f);   //scale child outlines
00299 }
00300 
00301 
00305 void OUTLINE::scale(                     // scale OUTLINE
00306                     const FCOORD vector  //by fcoord
00307                    ) {
00308                                  //child outline itertr
00309   OUTLINE_IT child_it(&children); 
00310   POLYPT_IT poly_it(&outline);  //outline point itertr
00311   POLYPT *pt;
00312 
00313   box.scale (vector);
00314 
00315   start.set_x ((INT16) floor (start.x () * vector.x () + 0.5));
00316   // ?? Why ICOORD?
00317   start.set_y ((INT16) floor (start.y () * vector.y () + 0.5));
00318   // ?? Why ICOORD?
00319 
00320   for (poly_it.mark_cycle_pt (); !poly_it.cycled_list (); poly_it.forward ()) {
00321     pt = poly_it.data ();
00322     pt->pos =
00323       FCOORD (pt->pos.x () * vector.x (), pt->pos.y () * vector.y ());
00324     pt->vec =
00325       FCOORD (pt->vec.x () * vector.x (), pt->vec.y () * vector.y ());
00326   }
00327 
00328   for (child_it.mark_cycle_pt (); !child_it.cycled_list ();
00329     child_it.forward ())
00330                                  //scale child outlines
00331   child_it.data ()->scale (vector);
00332 }
00333 
00334 
00338 #ifndef GRAPHICS_DISABLED
00339 void OUTLINE::plot(                //draw it
00340                    WINDOW window,  //window to draw in
00341                    COLOUR colour   //colour to draw in
00342                   ) {
00343   POLYPT *polypt;                //current point
00344   POLYPT_IT it = &outline;       //iterator
00345 
00346   line_color_index(window, colour); 
00347   polypt = it.data ();
00348   move2d (window, polypt->pos.x (), polypt->pos.y ());
00349   do {
00350     it.forward ();
00351     polypt = it.data ();
00352     draw2d (window, polypt->pos.x (), polypt->pos.y ());
00353   }
00354   while (!it.at_first ());
00355 }
00356 
00357 
00361 OUTLINE & OUTLINE::operator= (   //assignment
00362 const OUTLINE & source           //from this
00363 ) {
00364   box = source.box;
00365   start = source.start;
00366   if (!outline.empty ())
00367     outline.clear ();
00368   outline.deep_copy (&source.outline);
00369   if (!children.empty ())
00370     children.clear ();
00371   children.deep_copy (&source.children);
00372   return *this;
00373 }
00374 #endif

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