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