Tesseract  3.02
tesseract-ocr/wordrec/outlines.cpp
Go to the documentation of this file.
00001 /* -*-C-*-
00002  ********************************************************************************
00003  *
00004  * File:        outlines.c  (Formerly outlines.c)
00005  * Description:  Combinatorial Splitter
00006  * Author:       Mark Seaman, OCR Technology
00007  * Created:      Thu Jul 27 08:59:01 1989
00008  * Modified:     Wed Jul 10 14:56:49 1991 (Mark Seaman) marks@hpgrlt
00009  * Language:     C
00010  * Package:      N/A
00011  * Status:       Experimental (Do Not Distribute)
00012  *
00013  * (c) Copyright 1989, Hewlett-Packard Company.
00014  ** Licensed under the Apache License, Version 2.0 (the "License");
00015  ** you may not use this file except in compliance with the License.
00016  ** You may obtain a copy of the License at
00017  ** http://www.apache.org/licenses/LICENSE-2.0
00018  ** Unless required by applicable law or agreed to in writing, software
00019  ** distributed under the License is distributed on an "AS IS" BASIS,
00020  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00021  ** See the License for the specific language governing permissions and
00022  ** limitations under the License.
00023  *
00024  ********************************************************************************
00025  * Revision 1.2  89/09/15  09:24:41  09:24:41  marks (Mark Seaman)
00026  * First released version of Combinatorial splitter code
00027 **/
00028 /*----------------------------------------------------------------------
00029               I n c l u d e s
00030 ----------------------------------------------------------------------*/
00031 #include "outlines.h"
00032 #include "wordrec.h"
00033 
00034 #ifdef __UNIX__
00035 #include <assert.h>
00036 #endif
00037 
00038 namespace tesseract {
00039 /*----------------------------------------------------------------------
00040               F u n c t i o n s
00041 ----------------------------------------------------------------------*/
00042 /**********************************************************************
00043  * crosses_outline
00044  *
00045  * Check to see if this line crosses over this outline.  If it does
00046  * return TRUE.
00047  **********************************************************************/
00048 int Wordrec::crosses_outline(EDGEPT *p0,         /* Start of line */
00049                              EDGEPT *p1,         /* End of line */
00050                              EDGEPT *outline) {  /* Outline to check */
00051   EDGEPT *pt = outline;
00052   do {
00053     if (is_crossed (p0->pos, p1->pos, pt->pos, pt->next->pos))
00054       return (TRUE);
00055     pt = pt->next;
00056   }
00057   while (pt != outline);
00058   return (FALSE);
00059 }
00060 
00061 
00062 /**********************************************************************
00063  * is_crossed
00064  *
00065  * Return TRUE when the two line segments cross each other.  Find out
00066  * where the projected lines would cross and then check to see if the
00067  * point of intersection lies on both of the line segments. If it does
00068  * then these two segments cross.
00069  **********************************************************************/
00070 int Wordrec::is_crossed(TPOINT a0, TPOINT a1, TPOINT b0, TPOINT b1) {
00071   int b0a1xb0b1, b0b1xb0a0;
00072   int a1b1xa1a0, a1a0xa1b0;
00073 
00074   TPOINT b0a1, b0a0, a1b1, b0b1, a1a0;
00075 
00076   b0a1.x = a1.x - b0.x;
00077   b0a0.x = a0.x - b0.x;
00078   a1b1.x = b1.x - a1.x;
00079   b0b1.x = b1.x - b0.x;
00080   a1a0.x = a0.x - a1.x;
00081   b0a1.y = a1.y - b0.y;
00082   b0a0.y = a0.y - b0.y;
00083   a1b1.y = b1.y - a1.y;
00084   b0b1.y = b1.y - b0.y;
00085   a1a0.y = a0.y - a1.y;
00086 
00087   b0a1xb0b1 = CROSS (b0a1, b0b1);
00088   b0b1xb0a0 = CROSS (b0b1, b0a0);
00089   a1b1xa1a0 = CROSS (a1b1, a1a0);
00090                                  /*a1a0xa1b0=CROSS(a1a0,a1b0); */
00091   a1a0xa1b0 = -CROSS (a1a0, b0a1);
00092 
00093   return ((b0a1xb0b1 > 0 && b0b1xb0a0 > 0)
00094     || (b0a1xb0b1 < 0 && b0b1xb0a0 < 0))
00095     && ((a1b1xa1a0 > 0 && a1a0xa1b0 > 0) || (a1b1xa1a0 < 0 && a1a0xa1b0 < 0));
00096 }
00097 
00098 
00099 /**********************************************************************
00100  * is_same_edgept
00101  *
00102  * Return true if the points are identical.
00103  **********************************************************************/
00104 int Wordrec::is_same_edgept(EDGEPT *p1, EDGEPT *p2) {
00105   return (p1 == p2);
00106 }
00107 
00108 
00109 /**********************************************************************
00110  * near_point
00111  *
00112  * Find the point on a line segment that is closest to a point not on
00113  * the line segment.  Return that point in near_pt.  Returns whether
00114  * near_pt was newly created.
00115  **********************************************************************/
00116 bool Wordrec::near_point(EDGEPT *point,
00117                          EDGEPT *line_pt_0, EDGEPT *line_pt_1,
00118                          EDGEPT **near_pt) {
00119   TPOINT p;
00120 
00121   float slope;
00122   float intercept;
00123 
00124   float x0 = line_pt_0->pos.x;
00125   float x1 = line_pt_1->pos.x;
00126   float y0 = line_pt_0->pos.y;
00127   float y1 = line_pt_1->pos.y;
00128 
00129   if (x0 == x1) {
00130                                  /* Handle vertical line */
00131     p.x = (inT16) x0;
00132     p.y = point->pos.y;
00133   }
00134   else {
00135     /* Slope and intercept */
00136     slope = (y0 - y1) / (x0 - x1);
00137     intercept = y1 - x1 * slope;
00138 
00139     /* Find perpendicular */
00140     p.x = (inT16) ((point->pos.x + (point->pos.y - intercept) * slope) /
00141       (slope * slope + 1));
00142     p.y = (inT16) (slope * p.x + intercept);
00143   }
00144 
00145   if (is_on_line (p, line_pt_0->pos, line_pt_1->pos) &&
00146     (!same_point (p, line_pt_0->pos)) && (!same_point (p, line_pt_1->pos))) {
00147     /* Intersection on line */
00148     *near_pt = make_edgept(p.x, p.y, line_pt_1, line_pt_0);
00149     return true;
00150   } else {                           /* Intersection not on line */
00151     *near_pt = closest(point, line_pt_0, line_pt_1);
00152     return false;
00153   }
00154 }
00155 
00156 
00157 /**********************************************************************
00158  * reverse_outline
00159  *
00160  * Change the direction of the outline.  If it was clockwise make it
00161  * counter-clockwise and vice versa.  Do this by swapping each of the
00162  * next and prev fields of each edge point.
00163  **********************************************************************/
00164 void Wordrec::reverse_outline(EDGEPT *outline) {
00165   EDGEPT *edgept = outline;
00166   EDGEPT *temp;
00167 
00168   do {
00169                                  /* Swap next and prev */
00170     temp = edgept->prev;
00171     edgept->prev = edgept->next;
00172     edgept->next = temp;
00173     /* Set up vec field */
00174     edgept->vec.x = edgept->next->pos.x - edgept->pos.x;
00175     edgept->vec.y = edgept->next->pos.y - edgept->pos.y;
00176 
00177     edgept = edgept->prev;       /* Go to next point */
00178   }
00179   while (edgept != outline);
00180 }
00181 
00182 }  // namespace tesseract