tesseract  4.0.0-1-g2a2b
polyaprx.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * File: polyaprx.cpp (Formerly polygon.c)
3  * Description: Code for polygonal approximation from old edgeprog.
4  * Author: Ray Smith
5  * Created: Thu Nov 25 11:42:04 GMT 1993
6  *
7  * (C) Copyright 1993, Hewlett-Packard Ltd.
8  ** Licensed under the Apache License, Version 2.0 (the "License");
9  ** you may not use this file except in compliance with the License.
10  ** You may obtain a copy of the License at
11  ** http://www.apache.org/licenses/LICENSE-2.0
12  ** Unless required by applicable law or agreed to in writing, software
13  ** distributed under the License is distributed on an "AS IS" BASIS,
14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  ** See the License for the specific language governing permissions and
16  ** limitations under the License.
17  *
18  **********************************************************************/
19 
20 #include "polyaprx.h"
21 #include <cstdint> // for INT16_MAX, int8_t
22 #include "blobs.h" // for EDGEPT, TPOINT, VECTOR, TESSLINE
23 #include "coutln.h" // for C_OUTLINE
24 #include "errcode.h" // for ASSERT_HOST
25 #include "host.h" // for FALSE, TRUE
26 #include "mod128.h" // for DIR128
27 #include "params.h" // for BoolParam, BOOL_VAR
28 #include "points.h" // for ICOORD
29 #include "rect.h" // for TBOX
30 #include "tprintf.h" // for tprintf
31 #include "vecfuncs.h" // for LENGTH, point_diff, CROSS
32 
33 #define EXTERN
34 #define FASTEDGELENGTH 256
35 
36 EXTERN BOOL_VAR(poly_debug, FALSE, "Debug old poly");
38  "More accurate approx on wide things");
39 
40 #define FIXED 4 /*OUTLINE point is fixed */
41 
42 #define RUNLENGTH 1 /*length of run */
43 
44 #define DIR 2 /*direction of run */
45 
46 #define FLAGS 0
47 
48 #define fixed_dist 20 //really an int_variable
49 #define approx_dist 15 //really an int_variable
50 
51 const int par1 = 4500 / (approx_dist * approx_dist);
52 const int par2 = 6750 / (approx_dist * approx_dist);
53 
54 
55 /**********************************************************************
56  * tesspoly_outline
57  *
58  * Approximate an outline from chain codes form using the old tess algorithm.
59  * If allow_detailed_fx is true, the EDGEPTs in the returned TBLOB
60  * contain pointers to the input C_OUTLINEs that enable higher-resolution
61  * feature extraction that does not use the polygonal approximation.
62  **********************************************************************/
63 
64 
65 TESSLINE* ApproximateOutline(bool allow_detailed_fx, C_OUTLINE* c_outline) {
66  TBOX loop_box; // bounding box
67  int32_t area; // loop area
68  EDGEPT stack_edgepts[FASTEDGELENGTH]; // converted path
69  EDGEPT* edgepts = stack_edgepts;
70 
71  // Use heap memory if the stack buffer is not big enough.
72  if (c_outline->pathlength() > FASTEDGELENGTH)
73  edgepts = new EDGEPT[c_outline->pathlength()];
74 
75  loop_box = c_outline->bounding_box();
76  area = loop_box.height();
77  if (!poly_wide_objects_better && loop_box.width() > area)
78  area = loop_box.width();
79  area *= area;
80  edgesteps_to_edgepts(c_outline, edgepts);
81  fix2(edgepts, area);
82  EDGEPT* edgept = poly2(edgepts, area); // 2nd approximation.
83  EDGEPT* startpt = edgept;
84  EDGEPT* result = nullptr;
85  EDGEPT* prev_result = nullptr;
86  do {
87  EDGEPT* new_pt = new EDGEPT;
88  new_pt->pos = edgept->pos;
89  new_pt->prev = prev_result;
90  if (prev_result == nullptr) {
91  result = new_pt;
92  } else {
93  prev_result->next = new_pt;
94  new_pt->prev = prev_result;
95  }
96  if (allow_detailed_fx) {
97  new_pt->src_outline = edgept->src_outline;
98  new_pt->start_step = edgept->start_step;
99  new_pt->step_count = edgept->step_count;
100  }
101  prev_result = new_pt;
102  edgept = edgept->next;
103  }
104  while (edgept != startpt);
105  prev_result->next = result;
106  result->prev = prev_result;
107  if (edgepts != stack_edgepts)
108  delete [] edgepts;
109  return TESSLINE::BuildFromOutlineList(result);
110 }
111 
112 
113 /**********************************************************************
114  * edgesteps_to_edgepts
115  *
116  * Convert a C_OUTLINE to EDGEPTs.
117  **********************************************************************/
118 
119 EDGEPT *
120 edgesteps_to_edgepts ( //convert outline
121 C_OUTLINE * c_outline, //input
122 EDGEPT edgepts[] //output is array
123 ) {
124  int32_t length; //steps in path
125  ICOORD pos; //current coords
126  int32_t stepindex; //current step
127  int32_t stepinc; //increment
128  int32_t epindex; //current EDGEPT
129  int32_t count; //repeated steps
130  ICOORD vec; //for this 8 step
131  ICOORD prev_vec;
132  int8_t epdir; //of this step
133  DIR128 prevdir; //prvious dir
134  DIR128 dir; //of this step
135 
136  pos = c_outline->start_pos (); //start of loop
137  length = c_outline->pathlength ();
138  stepindex = 0;
139  epindex = 0;
140  prevdir = -1;
141  count = 0;
142  int prev_stepindex = 0;
143  do {
144  dir = c_outline->step_dir (stepindex);
145  vec = c_outline->step (stepindex);
146  if (stepindex < length - 1
147  && c_outline->step_dir (stepindex + 1) - dir == -32) {
148  dir += 128 - 16;
149  vec += c_outline->step (stepindex + 1);
150  stepinc = 2;
151  }
152  else
153  stepinc = 1;
154  if (count == 0) {
155  prevdir = dir;
156  prev_vec = vec;
157  }
158  if (prevdir.get_dir () != dir.get_dir ()) {
159  edgepts[epindex].pos.x = pos.x ();
160  edgepts[epindex].pos.y = pos.y ();
161  prev_vec *= count;
162  edgepts[epindex].vec.x = prev_vec.x ();
163  edgepts[epindex].vec.y = prev_vec.y ();
164  pos += prev_vec;
165  edgepts[epindex].flags[RUNLENGTH] = count;
166  edgepts[epindex].prev = &edgepts[epindex - 1];
167  edgepts[epindex].flags[FLAGS] = 0;
168  edgepts[epindex].next = &edgepts[epindex + 1];
169  prevdir += 64;
170  epdir = (DIR128) 0 - prevdir;
171  epdir >>= 4;
172  epdir &= 7;
173  edgepts[epindex].flags[DIR] = epdir;
174  edgepts[epindex].src_outline = c_outline;
175  edgepts[epindex].start_step = prev_stepindex;
176  edgepts[epindex].step_count = stepindex - prev_stepindex;
177  epindex++;
178  prevdir = dir;
179  prev_vec = vec;
180  count = 1;
181  prev_stepindex = stepindex;
182  }
183  else
184  count++;
185  stepindex += stepinc;
186  }
187  while (stepindex < length);
188  edgepts[epindex].pos.x = pos.x ();
189  edgepts[epindex].pos.y = pos.y ();
190  prev_vec *= count;
191  edgepts[epindex].vec.x = prev_vec.x ();
192  edgepts[epindex].vec.y = prev_vec.y ();
193  pos += prev_vec;
194  edgepts[epindex].flags[RUNLENGTH] = count;
195  edgepts[epindex].flags[FLAGS] = 0;
196  edgepts[epindex].src_outline = c_outline;
197  edgepts[epindex].start_step = prev_stepindex;
198  edgepts[epindex].step_count = stepindex - prev_stepindex;
199  edgepts[epindex].prev = &edgepts[epindex - 1];
200  edgepts[epindex].next = &edgepts[0];
201  prevdir += 64;
202  epdir = (DIR128) 0 - prevdir;
203  epdir >>= 4;
204  epdir &= 7;
205  edgepts[epindex].flags[DIR] = epdir;
206  edgepts[0].prev = &edgepts[epindex];
207  ASSERT_HOST (pos.x () == c_outline->start_pos ().x ()
208  && pos.y () == c_outline->start_pos ().y ());
209  return &edgepts[0];
210 }
211 
212 
213 /**********************************************************************
214  *fix2(start,area) fixes points on the outline according to a trial method*
215  **********************************************************************/
216 
217 //#pragma OPT_LEVEL 1 /*stop compiler bugs*/
218 
219 void fix2( //polygonal approx
220  EDGEPT *start, /*loop to approimate */
221  int area) {
222  EDGEPT *edgept; /*current point */
223  EDGEPT *edgept1;
224  EDGEPT *loopstart; /*modified start of loop */
225  EDGEPT *linestart; /*start of line segment */
226  int dir1, dir2; /*directions of line */
227  int sum1, sum2; /*lengths in dir1,dir2 */
228  int stopped; /*completed flag */
229  int fixed_count; //no of fixed points
230  int d01, d12, d23, gapmin;
231  TPOINT d01vec, d12vec, d23vec;
232  EDGEPT *edgefix, *startfix;
233  EDGEPT *edgefix0, *edgefix1, *edgefix2, *edgefix3;
234 
235  edgept = start; /*start of loop */
236  while (((edgept->flags[DIR] - edgept->prev->flags[DIR] + 1) & 7) < 3
237  && (dir1 =
238  (edgept->prev->flags[DIR] - edgept->next->flags[DIR]) & 7) != 2
239  && dir1 != 6)
240  edgept = edgept->next; /*find suitable start */
241  loopstart = edgept; /*remember start */
242 
243  stopped = 0; /*not finished yet */
244  edgept->flags[FLAGS] |= FIXED; /*fix it */
245  do {
246  linestart = edgept; /*possible start of line */
247  dir1 = edgept->flags[DIR]; /*first direction */
248  /*length of dir1 */
249  sum1 = edgept->flags[RUNLENGTH];
250  edgept = edgept->next;
251  dir2 = edgept->flags[DIR]; /*2nd direction */
252  /*length in dir2 */
253  sum2 = edgept->flags[RUNLENGTH];
254  if (((dir1 - dir2 + 1) & 7) < 3) {
255  while (edgept->prev->flags[DIR] == edgept->next->flags[DIR]) {
256  edgept = edgept->next; /*look at next */
257  if (edgept->flags[DIR] == dir1)
258  /*sum lengths */
259  sum1 += edgept->flags[RUNLENGTH];
260  else
261  sum2 += edgept->flags[RUNLENGTH];
262  }
263 
264  if (edgept == loopstart)
265  stopped = 1; /*finished */
266  if (sum2 + sum1 > 2
267  && linestart->prev->flags[DIR] == dir2
268  && (linestart->prev->flags[RUNLENGTH] >
269  linestart->flags[RUNLENGTH] || sum2 > sum1)) {
270  /*start is back one */
271  linestart = linestart->prev;
272  linestart->flags[FLAGS] |= FIXED;
273  }
274 
275  if (((edgept->next->flags[DIR] - edgept->flags[DIR] + 1) & 7) >= 3
276  || (edgept->flags[DIR] == dir1 && sum1 >= sum2)
277  || ((edgept->prev->flags[RUNLENGTH] < edgept->flags[RUNLENGTH]
278  || (edgept->flags[DIR] == dir2 && sum2 >= sum1))
279  && linestart->next != edgept))
280  edgept = edgept->next;
281  }
282  /*sharp bend */
283  edgept->flags[FLAGS] |= FIXED;
284  }
285  /*do whole loop */
286  while (edgept != loopstart && !stopped);
287 
288  edgept = start;
289  do {
290  if (((edgept->flags[RUNLENGTH] >= 8) &&
291  (edgept->flags[DIR] != 2) && (edgept->flags[DIR] != 6)) ||
292  ((edgept->flags[RUNLENGTH] >= 8) &&
293  ((edgept->flags[DIR] == 2) || (edgept->flags[DIR] == 6)))) {
294  edgept->flags[FLAGS] |= FIXED;
295  edgept1 = edgept->next;
296  edgept1->flags[FLAGS] |= FIXED;
297  }
298  edgept = edgept->next;
299  }
300  while (edgept != start);
301 
302  edgept = start;
303  do {
304  /*single fixed step */
305  if (edgept->flags[FLAGS] & FIXED && edgept->flags[RUNLENGTH] == 1
306  /*and neighours free */
307  && edgept->next->flags[FLAGS] & FIXED && (edgept->prev->flags[FLAGS] & FIXED) == 0
308  /*same pair of dirs */
309  && (edgept->next->next->flags[FLAGS] & FIXED) == 0 && edgept->prev->flags[DIR] == edgept->next->flags[DIR] && edgept->prev->prev->flags[DIR] == edgept->next->next->flags[DIR]
310  && ((edgept->prev->flags[DIR] - edgept->flags[DIR] + 1) & 7) < 3) {
311  /*unfix it */
312  edgept->flags[FLAGS] &= ~FIXED;
313  edgept->next->flags[FLAGS] &= ~FIXED;
314  }
315  edgept = edgept->next; /*do all points */
316  }
317  while (edgept != start); /*until finished */
318 
319  stopped = 0;
320  if (area < 450)
321  area = 450;
322 
323  gapmin = area * fixed_dist * fixed_dist / 44000;
324 
325  edgept = start;
326  fixed_count = 0;
327  do {
328  if (edgept->flags[FLAGS] & FIXED)
329  fixed_count++;
330  edgept = edgept->next;
331  }
332  while (edgept != start);
333  while ((edgept->flags[FLAGS] & FIXED) == 0)
334  edgept = edgept->next;
335  edgefix0 = edgept;
336 
337  edgept = edgept->next;
338  while ((edgept->flags[FLAGS] & FIXED) == 0)
339  edgept = edgept->next;
340  edgefix1 = edgept;
341 
342  edgept = edgept->next;
343  while ((edgept->flags[FLAGS] & FIXED) == 0)
344  edgept = edgept->next;
345  edgefix2 = edgept;
346 
347  edgept = edgept->next;
348  while ((edgept->flags[FLAGS] & FIXED) == 0)
349  edgept = edgept->next;
350  edgefix3 = edgept;
351 
352  startfix = edgefix2;
353 
354  do {
355  if (fixed_count <= 3)
356  break; //already too few
357  point_diff (d12vec, edgefix1->pos, edgefix2->pos);
358  d12 = LENGTH (d12vec);
359  // TODO(rays) investigate this change:
360  // Only unfix a point if it is part of a low-curvature section
361  // of outline and the total angle change of the outlines is
362  // less than 90 degrees, ie the scalar product is positive.
363  // if (d12 <= gapmin && SCALAR(edgefix0->vec, edgefix2->vec) > 0) {
364  if (d12 <= gapmin) {
365  point_diff (d01vec, edgefix0->pos, edgefix1->pos);
366  d01 = LENGTH (d01vec);
367  point_diff (d23vec, edgefix2->pos, edgefix3->pos);
368  d23 = LENGTH (d23vec);
369  if (d01 > d23) {
370  edgefix2->flags[FLAGS] &= ~FIXED;
371  fixed_count--;
372  }
373  else {
374  edgefix1->flags[FLAGS] &= ~FIXED;
375  fixed_count--;
376  edgefix1 = edgefix2;
377  }
378  }
379  else {
380  edgefix0 = edgefix1;
381  edgefix1 = edgefix2;
382  }
383  edgefix2 = edgefix3;
384  edgept = edgept->next;
385  while ((edgept->flags[FLAGS] & FIXED) == 0) {
386  if (edgept == startfix)
387  stopped = 1;
388  edgept = edgept->next;
389  }
390  edgefix3 = edgept;
391  edgefix = edgefix2;
392  }
393  while ((edgefix != startfix) && (!stopped));
394 }
395 
396 
397 //#pragma OPT_LEVEL 2 /*stop compiler bugs*/
398 
399 /**********************************************************************
400  *poly2(startpt,area,path) applies a second approximation to the outline
401  *using the points which have been fixed by the first approximation*
402  **********************************************************************/
403 
404 EDGEPT *poly2( //second poly
405  EDGEPT *startpt, /*start of loop */
406  int area /*area of blob box */
407  ) {
408  EDGEPT *edgept; /*current outline point */
409  EDGEPT *loopstart; /*starting point */
410  EDGEPT *linestart; /*start of line */
411  int edgesum; /*correction count */
412 
413  if (area < 1200)
414  area = 1200; /*minimum value */
415 
416  loopstart = nullptr; /*not found it yet */
417  edgept = startpt; /*start of loop */
418 
419  do {
420  /*current point fixed */
421  if (edgept->flags[FLAGS] & FIXED
422  /*and next not */
423  && (edgept->next->flags[FLAGS] & FIXED) == 0) {
424  loopstart = edgept; /*start of repoly */
425  break;
426  }
427  edgept = edgept->next; /*next point */
428  }
429  while (edgept != startpt); /*until found or finished */
430 
431  if (loopstart == nullptr && (startpt->flags[FLAGS] & FIXED) == 0) {
432  /*fixed start of loop */
433  startpt->flags[FLAGS] |= FIXED;
434  loopstart = startpt; /*or start of loop */
435  }
436  if (loopstart) {
437  do {
438  edgept = loopstart; /*first to do */
439  do {
440  linestart = edgept;
441  edgesum = 0; /*sum of lengths */
442  do {
443  /*sum lengths */
444  edgesum += edgept->flags[RUNLENGTH];
445  edgept = edgept->next; /*move on */
446  }
447  while ((edgept->flags[FLAGS] & FIXED) == 0
448  && edgept != loopstart && edgesum < 126);
449  if (poly_debug)
450  tprintf
451  ("Poly2:starting at (%d,%d)+%d=(%d,%d),%d to (%d,%d)\n",
452  linestart->pos.x, linestart->pos.y, linestart->flags[DIR],
453  linestart->vec.x, linestart->vec.y, edgesum, edgept->pos.x,
454  edgept->pos.y);
455  /*reapproximate */
456  cutline(linestart, edgept, area);
457 
458  while ((edgept->next->flags[FLAGS] & FIXED)
459  && edgept != loopstart)
460  edgept = edgept->next; /*look for next non-fixed */
461  }
462  /*do all the loop */
463  while (edgept != loopstart);
464  edgesum = 0;
465  do {
466  if (edgept->flags[FLAGS] & FIXED)
467  edgesum++;
468  edgept = edgept->next;
469  }
470  //count fixed pts
471  while (edgept != loopstart);
472  if (edgesum < 3)
473  area /= 2; //must have 3 pts
474  }
475  while (edgesum < 3);
476  do {
477  linestart = edgept;
478  do {
479  edgept = edgept->next;
480  }
481  while ((edgept->flags[FLAGS] & FIXED) == 0);
482  linestart->next = edgept;
483  edgept->prev = linestart;
484  linestart->vec.x = edgept->pos.x - linestart->pos.x;
485  linestart->vec.y = edgept->pos.y - linestart->pos.y;
486  }
487  while (edgept != loopstart);
488  }
489  else
490  edgept = startpt; /*start of loop */
491 
492  loopstart = edgept; /*new start */
493  return loopstart; /*correct exit */
494 }
495 
496 
497 /**********************************************************************
498  *cutline(first,last,area) straightens out a line by partitioning
499  *and joining the ends by a straight line*
500  **********************************************************************/
501 
502 void cutline( //recursive refine
503  EDGEPT *first, /*ends of line */
504  EDGEPT *last,
505  int area /*area of object */
506  ) {
507  EDGEPT *edge; /*current edge */
508  TPOINT vecsum; /*vector sum */
509  int vlen; /*approx length of vecsum */
510  TPOINT vec; /*accumulated vector */
511  EDGEPT *maxpoint; /*worst point */
512  int maxperp; /*max deviation */
513  int perp; /*perp distance */
514  int ptcount; /*no of points */
515  int squaresum; /*sum of perps */
516 
517  edge = first; /*start of line */
518  if (edge->next == last)
519  return; /*simple line */
520 
521  /*vector sum */
522  vecsum.x = last->pos.x - edge->pos.x;
523  vecsum.y = last->pos.y - edge->pos.y;
524  if (vecsum.x == 0 && vecsum.y == 0) {
525  /*special case */
526  vecsum.x = -edge->prev->vec.x;
527  vecsum.y = -edge->prev->vec.y;
528  }
529  /*absolute value */
530  vlen = vecsum.x > 0 ? vecsum.x : -vecsum.x;
531  if (vecsum.y > vlen)
532  vlen = vecsum.y; /*maximum */
533  else if (-vecsum.y > vlen)
534  vlen = -vecsum.y; /*absolute value */
535 
536  vec.x = edge->vec.x; /*accumulated vector */
537  vec.y = edge->vec.y;
538  maxperp = 0; /*none yet */
539  squaresum = ptcount = 0;
540  edge = edge->next; /*move to actual point */
541  maxpoint = edge; /*in case there isn't one */
542  do {
543  perp = CROSS (vec, vecsum); /*get perp distance */
544  if (perp != 0) {
545  perp *= perp; /*squared deviation */
546  }
547  squaresum += perp; /*sum squares */
548  ptcount++; /*count points */
549  if (poly_debug)
550  tprintf ("Cutline:Final perp=%d\n", perp);
551  if (perp > maxperp) {
552  maxperp = perp;
553  maxpoint = edge; /*find greatest deviation */
554  }
555  vec.x += edge->vec.x; /*accumulate vectors */
556  vec.y += edge->vec.y;
557  edge = edge->next;
558  }
559  while (edge != last); /*test all line */
560 
561  perp = LENGTH (vecsum);
562  ASSERT_HOST (perp != 0);
563 
564  if (maxperp < 256 * INT16_MAX) {
565  maxperp <<= 8;
566  maxperp /= perp; /*true max perp */
567  }
568  else {
569  maxperp /= perp;
570  maxperp <<= 8; /*avoid overflow */
571  }
572  if (squaresum < 256 * INT16_MAX)
573  /*mean squared perp */
574  perp = (squaresum << 8) / (perp * ptcount);
575  else
576  /*avoid overflow */
577  perp = (squaresum / perp << 8) / ptcount;
578 
579  if (poly_debug)
580  tprintf ("Cutline:A=%d, max=%.2f(%.2f%%), msd=%.2f(%.2f%%)\n",
581  area, maxperp / 256.0, maxperp * 200.0 / area,
582  perp / 256.0, perp * 300.0 / area);
583  if (maxperp * par1 >= 10 * area || perp * par2 >= 10 * area || vlen >= 126) {
584  maxpoint->flags[FLAGS] |= FIXED;
585  /*partitions */
586  cutline(first, maxpoint, area);
587  cutline(maxpoint, last, area);
588  }
589 }
#define point_diff(p, p1, p2)
Definition: vecfuncs.h:42
int step_count
Definition: blobs.h:181
#define TRUE
Definition: capi.h:51
#define BOOL_VAR(name, val, comment)
Definition: params.h:279
TPOINT pos
Definition: blobs.h:170
#define FASTEDGELENGTH
Definition: polyaprx.cpp:34
int count(LIST var_list)
Definition: oldlist.cpp:98
LIST last(LIST var_list)
Definition: oldlist.cpp:242
#define DIR
Definition: polyaprx.cpp:44
int16_t y() const
access_function
Definition: points.h:57
Definition: rect.h:34
#define CROSS(a, b)
Definition: vecfuncs.h:52
const ICOORD & start_pos() const
Definition: coutln.h:148
const int par2
Definition: polyaprx.cpp:52
int start_step
Definition: blobs.h:180
#define approx_dist
Definition: polyaprx.cpp:49
#define LENGTH(a)
Definition: vecfuncs.h:70
EDGEPT * edgesteps_to_edgepts(C_OUTLINE *c_outline, EDGEPT edgepts[])
Definition: polyaprx.cpp:120
void fix2(EDGEPT *start, int area)
Definition: polyaprx.cpp:219
int16_t width() const
Definition: rect.h:115
EXTERN bool poly_debug
Definition: polyaprx.cpp:36
#define RUNLENGTH
Definition: polyaprx.cpp:42
int8_t get_dir() const
Definition: mod128.h:76
integer coordinate
Definition: points.h:32
int16_t x() const
access function
Definition: points.h:53
Definition: mod128.h:29
#define FALSE
Definition: capi.h:52
#define FLAGS
Definition: polyaprx.cpp:46
VECTOR vec
Definition: blobs.h:171
Definition: blobs.h:83
int32_t pathlength() const
Definition: coutln.h:135
EDGEPT * prev
Definition: blobs.h:177
#define FIXED
Definition: polyaprx.cpp:40
const TBOX & bounding_box() const
Definition: coutln.h:113
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:37
#define fixed_dist
Definition: polyaprx.cpp:48
int16_t x
Definition: blobs.h:78
C_OUTLINE * src_outline
Definition: blobs.h:178
EDGEPT * poly2(EDGEPT *startpt, int area)
Definition: polyaprx.cpp:404
char flags[EDGEPTFLAGS]
Definition: blobs.h:175
DIR128 step_dir(int index) const
Definition: coutln.h:139
void cutline(EDGEPT *first, EDGEPT *last, int area)
Definition: polyaprx.cpp:502
#define EXTERN
Definition: polyaprx.cpp:33
const int par1
Definition: polyaprx.cpp:51
Definition: blobs.h:57
int16_t y
Definition: blobs.h:79
EXTERN bool poly_wide_objects_better
Definition: polyaprx.cpp:38
static TESSLINE * BuildFromOutlineList(EDGEPT *outline)
Definition: blobs.cpp:104
EDGEPT * next
Definition: blobs.h:176
ICOORD step(int index) const
Definition: coutln.h:144
int16_t height() const
Definition: rect.h:108
TESSLINE * ApproximateOutline(bool allow_detailed_fx, C_OUTLINE *c_outline)
Definition: polyaprx.cpp:65
#define ASSERT_HOST(x)
Definition: errcode.h:84