tesseract  4.00.00dev
C_OUTLINE Class Reference

#include <coutln.h>

Inheritance diagram for C_OUTLINE:
ELIST_LINK

Public Member Functions

 C_OUTLINE ()
 
 ~C_OUTLINE ()
 
BOOL8 flag (C_OUTLINE_FLAGS mask) const
 
void set_flag (C_OUTLINE_FLAGS mask, BOOL8 value)
 
C_OUTLINE_LIST * child ()
 
const TBOXbounding_box () const
 
void set_step (inT16 stepindex, inT8 stepdir)
 
void set_step (inT16 stepindex, DIR128 stepdir)
 
inT32 pathlength () const
 
DIR128 step_dir (int index) const
 
ICOORD step (int index) const
 
const ICOORDstart_pos () const
 
ICOORD position_at_index (int index) const
 
FCOORD sub_pixel_pos_at_index (const ICOORD &pos, int index) const
 
int direction_at_index (int index) const
 
int edge_strength_at_index (int index) const
 
int chain_code (int index) const
 
BOOL8 operator> (C_OUTLINE &other) const
 
C_OUTLINE::area

Compute the area of the outline.

inT32 area () const
 
C_OUTLINE::perimeter

Compute the perimeter of the outline and its first level children.

inT32 perimeter () const
 
C_OUTLINE::outer_area

Compute the area of the outline.

inT32 outer_area () const
 
C_OUTLINE::count_transitions

Compute the number of x and y maxes and mins in the outline.

Parameters
thresholdwinding number on size
inT32 count_transitions (inT32 threshold)
 
C_OUTLINE::operator<
Returns
TRUE if the left operand is inside the right one.
Parameters
otherother outline
BOOL8 operator< (const C_OUTLINE &other) const
 
C_OUTLINE::winding_number
Returns
the winding number of the outline around the given point.
Parameters
pointpoint to wind around
inT16 winding_number (ICOORD testpt) const
 
inT16 turn_direction () const
 
C_OUTLINE::reverse

Reverse the direction of an outline.

void reverse ()
 
C_OUTLINE::move

Move C_OUTLINE by vector

Parameters
vecvector to reposition OUTLINE by
void move (const ICOORD vec)
 
bool IsLegallyNested () const
 
void RemoveSmallRecursive (int min_size, C_OUTLINE_IT *it)
 
void ComputeEdgeOffsets (int threshold, Pix *pix)
 
void ComputeBinaryOffsets ()
 
void render (int left, int top, Pix *pix) const
 
void render_outline (int left, int top, Pix *pix) const
 
C_OUTLINE::plot

Draw the outline in the given colour.

Parameters
windowwindow to draw in
colourcolour to draw in
void plot (ScrollView *window, ScrollView::Color colour) const
 
void plot_normed (const DENORM &denorm, ScrollView::Color colour, ScrollView *window) const
 
- Public Member Functions inherited from ELIST_LINK
 ELIST_LINK ()
 
 ELIST_LINK (const ELIST_LINK &)
 
void operator= (const ELIST_LINK &)
 

Static Public Member Functions

static C_OUTLINEdeep_copy (const C_OUTLINE *src)
 

Static Public Attributes

static const int kMaxOutlineLength = 16000
 

C_OUTLINE::C_OUTLINE

Constructor to build a C_OUTLINE from a rotation of a C_OUTLINE.

Parameters
srclineoutline to rotate
rotationrotate to coord
 C_OUTLINE (CRACKEDGE *startpt, ICOORD bot_left, ICOORD top_right, inT16 length)
 
 C_OUTLINE (ICOORD startpt, DIR128 *new_steps, inT16 length)
 
 C_OUTLINE (C_OUTLINE *srcline, FCOORD rotation)
 
static void FakeOutline (const TBOX &box, C_OUTLINE_LIST *outlines)
 

C_OUTLINE::operator=

Assignment - deep copy data

Parameters
sourceassign from this
C_OUTLINEoperator= (const C_OUTLINE &source)
 
static ICOORD chain_step (int chaindir)
 

Detailed Description

Definition at line 69 of file coutln.h.

Constructor & Destructor Documentation

◆ C_OUTLINE() [1/4]

C_OUTLINE::C_OUTLINE ( )
inline

Definition at line 71 of file coutln.h.

71  { //empty constructor
72  steps = NULL;
73  offsets = NULL;
74  }

◆ C_OUTLINE() [2/4]

C_OUTLINE::C_OUTLINE ( CRACKEDGE startpt,
ICOORD  bot_left,
ICOORD  top_right,
inT16  length 
)

Definition at line 51 of file coutln.cpp.

53  : box(bot_left, top_right), start(startpt->pos), offsets(NULL) {
54  inT16 stepindex; //index to step
55  CRACKEDGE *edgept; //current point
56 
57  stepcount = length; //no of steps
58  if (length == 0) {
59  steps = NULL;
60  return;
61  }
62  //get memory
63  steps = (uinT8 *) alloc_mem (step_mem());
64  memset(steps, 0, step_mem());
65  edgept = startpt;
66 
67  for (stepindex = 0; stepindex < length; stepindex++) {
68  //set compact step
69  set_step (stepindex, edgept->stepdir);
70  edgept = edgept->next;
71  }
72 }
void set_step(inT16 stepindex, inT8 stepdir)
Definition: coutln.h:114
int16_t inT16
Definition: host.h:36
inT8 stepdir
Definition: crakedge.h:33
CRACKEDGE * next
Definition: crakedge.h:35
void * alloc_mem(inT32 count)
Definition: memry.cpp:39
ICOORD pos
Definition: crakedge.h:30
uint8_t uinT8
Definition: host.h:35

◆ C_OUTLINE() [3/4]

C_OUTLINE::C_OUTLINE ( ICOORD  startpt,
DIR128 new_steps,
inT16  length 
)

Definition at line 79 of file coutln.cpp.

84  :start (startpt), offsets(NULL) {
85  inT8 dirdiff; //direction difference
86  DIR128 prevdir; //previous direction
87  DIR128 dir; //current direction
88  DIR128 lastdir; //dir of last step
89  TBOX new_box; //easy bounding
90  inT16 stepindex; //index to step
91  inT16 srcindex; //source steps
92  ICOORD pos; //current position
93 
94  pos = startpt;
95  stepcount = length; // No. of steps.
96  ASSERT_HOST(length >= 0);
97  steps = static_cast<uinT8*>(alloc_mem(step_mem())); // Get memory.
98  memset(steps, 0, step_mem());
99 
100  lastdir = new_steps[length - 1];
101  prevdir = lastdir;
102  for (stepindex = 0, srcindex = 0; srcindex < length;
103  stepindex++, srcindex++) {
104  new_box = TBOX (pos, pos);
105  box += new_box;
106  //copy steps
107  dir = new_steps[srcindex];
108  set_step(stepindex, dir);
109  dirdiff = dir - prevdir;
110  pos += step (stepindex);
111  if ((dirdiff == 64 || dirdiff == -64) && stepindex > 0) {
112  stepindex -= 2; //cancel there-and-back
113  prevdir = stepindex >= 0 ? step_dir (stepindex) : lastdir;
114  }
115  else
116  prevdir = dir;
117  }
118  ASSERT_HOST (pos.x () == startpt.x () && pos.y () == startpt.y ());
119  do {
120  dirdiff = step_dir (stepindex - 1) - step_dir (0);
121  if (dirdiff == 64 || dirdiff == -64) {
122  start += step (0);
123  stepindex -= 2; //cancel there-and-back
124  for (int i = 0; i < stepindex; ++i)
125  set_step(i, step_dir(i + 1));
126  }
127  }
128  while (stepindex > 1 && (dirdiff == 64 || dirdiff == -64));
129  stepcount = stepindex;
130  ASSERT_HOST (stepcount >= 4);
131 }
void set_step(inT16 stepindex, inT8 stepdir)
Definition: coutln.h:114
inT16 x() const
access function
Definition: points.h:52
int16_t inT16
Definition: host.h:36
#define ASSERT_HOST(x)
Definition: errcode.h:84
inT16 y() const
access_function
Definition: points.h:56
void * alloc_mem(inT32 count)
Definition: memry.cpp:39
DIR128 step_dir(int index) const
Definition: coutln.h:137
Definition: rect.h:30
int8_t inT8
Definition: host.h:34
ICOORD step(int index) const
Definition: coutln.h:142
uint8_t uinT8
Definition: host.h:35
Definition: mod128.h:29
integer coordinate
Definition: points.h:30

◆ C_OUTLINE() [4/4]

C_OUTLINE::C_OUTLINE ( C_OUTLINE srcline,
FCOORD  rotation 
)

Definition at line 141 of file coutln.cpp.

141  : offsets(NULL) {
142  TBOX new_box; //easy bounding
143  inT16 stepindex; //index to step
144  inT16 dirdiff; //direction change
145  ICOORD pos; //current position
146  ICOORD prevpos; //previous dest point
147 
148  ICOORD destpos; //destination point
149  inT16 destindex; //index to step
150  DIR128 dir; //coded direction
151  uinT8 new_step;
152 
153  stepcount = srcline->stepcount * 2;
154  if (stepcount == 0) {
155  steps = NULL;
156  box = srcline->box;
157  box.rotate(rotation);
158  return;
159  }
160  //get memory
161  steps = (uinT8 *) alloc_mem (step_mem());
162  memset(steps, 0, step_mem());
163 
164  for (int iteration = 0; iteration < 2; ++iteration) {
165  DIR128 round1 = iteration == 0 ? 32 : 0;
166  DIR128 round2 = iteration != 0 ? 32 : 0;
167  pos = srcline->start;
168  prevpos = pos;
169  prevpos.rotate (rotation);
170  start = prevpos;
171  box = TBOX (start, start);
172  destindex = 0;
173  for (stepindex = 0; stepindex < srcline->stepcount; stepindex++) {
174  pos += srcline->step (stepindex);
175  destpos = pos;
176  destpos.rotate (rotation);
177  // tprintf("%i %i %i %i ", destpos.x(), destpos.y(), pos.x(), pos.y());
178  while (destpos.x () != prevpos.x () || destpos.y () != prevpos.y ()) {
179  dir = DIR128 (FCOORD (destpos - prevpos));
180  dir += 64; //turn to step style
181  new_step = dir.get_dir ();
182  // tprintf(" %i\n", new_step);
183  if (new_step & 31) {
184  set_step(destindex++, dir + round1);
185  prevpos += step(destindex - 1);
186  if (destindex < 2
187  || ((dirdiff =
188  step_dir (destindex - 1) - step_dir (destindex - 2)) !=
189  -64 && dirdiff != 64)) {
190  set_step(destindex++, dir + round2);
191  prevpos += step(destindex - 1);
192  } else {
193  prevpos -= step(destindex - 1);
194  destindex--;
195  prevpos -= step(destindex - 1);
196  set_step(destindex - 1, dir + round2);
197  prevpos += step(destindex - 1);
198  }
199  }
200  else {
201  set_step(destindex++, dir);
202  prevpos += step(destindex - 1);
203  }
204  while (destindex >= 2 &&
205  ((dirdiff =
206  step_dir (destindex - 1) - step_dir (destindex - 2)) == -64 ||
207  dirdiff == 64)) {
208  prevpos -= step(destindex - 1);
209  prevpos -= step(destindex - 2);
210  destindex -= 2; // Forget u turn
211  }
212  //ASSERT_HOST(prevpos.x() == destpos.x() && prevpos.y() == destpos.y());
213  new_box = TBOX (destpos, destpos);
214  box += new_box;
215  }
216  }
217  ASSERT_HOST (destpos.x () == start.x () && destpos.y () == start.y ());
218  dirdiff = step_dir (destindex - 1) - step_dir (0);
219  while ((dirdiff == 64 || dirdiff == -64) && destindex > 1) {
220  start += step (0);
221  destindex -= 2;
222  for (int i = 0; i < destindex; ++i)
223  set_step(i, step_dir(i + 1));
224  dirdiff = step_dir (destindex - 1) - step_dir (0);
225  }
226  if (destindex >= 4)
227  break;
228  }
229  ASSERT_HOST(destindex <= stepcount);
230  stepcount = destindex;
231  destpos = start;
232  for (stepindex = 0; stepindex < stepcount; stepindex++) {
233  destpos += step (stepindex);
234  }
235  ASSERT_HOST (destpos.x () == start.x () && destpos.y () == start.y ());
236 }
void rotate(const FCOORD &vec)
Definition: ipoints.h:241
void set_step(inT16 stepindex, inT8 stepdir)
Definition: coutln.h:114
Definition: points.h:189
inT16 x() const
access function
Definition: points.h:52
int16_t inT16
Definition: host.h:36
#define ASSERT_HOST(x)
Definition: errcode.h:84
inT16 y() const
access_function
Definition: points.h:56
void * alloc_mem(inT32 count)
Definition: memry.cpp:39
DIR128 step_dir(int index) const
Definition: coutln.h:137
Definition: rect.h:30
ICOORD step(int index) const
Definition: coutln.h:142
uint8_t uinT8
Definition: host.h:35
inT8 get_dir() const
Definition: mod128.h:77
Definition: mod128.h:29
void rotate(const FCOORD &vec)
Definition: rect.h:189
integer coordinate
Definition: points.h:30

◆ ~C_OUTLINE()

C_OUTLINE::~C_OUTLINE ( )
inline

Definition at line 89 of file coutln.h.

89  { //destructor
90  if (steps != NULL)
91  free_mem(steps);
92  steps = NULL;
93  delete [] offsets;
94  }
void free_mem(void *oldchunk)
Definition: memry.cpp:47

Member Function Documentation

◆ area()

inT32 C_OUTLINE::area ( ) const

Definition at line 255 of file coutln.cpp.

255  {
256  int stepindex; //current step
257  inT32 total_steps; //steps to do
258  inT32 total; //total area
259  ICOORD pos; //position of point
260  ICOORD next_step; //step to next pix
261  // We aren't going to modify the list, or its contents, but there is
262  // no const iterator.
263  C_OUTLINE_IT it(const_cast<C_OUTLINE_LIST*>(&children));
264 
265  pos = start_pos ();
266  total_steps = pathlength ();
267  total = 0;
268  for (stepindex = 0; stepindex < total_steps; stepindex++) {
269  //all intersected
270  next_step = step (stepindex);
271  if (next_step.x () < 0)
272  total += pos.y ();
273  else if (next_step.x () > 0)
274  total -= pos.y ();
275  pos += next_step;
276  }
277  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
278  total += it.data ()->area ();//add areas of children
279 
280  return total;
281 }
int32_t inT32
Definition: host.h:38
inT16 x() const
access function
Definition: points.h:52
inT16 y() const
access_function
Definition: points.h:56
ICOORD step(int index) const
Definition: coutln.h:142
const ICOORD & start_pos() const
Definition: coutln.h:146
inT32 pathlength() const
Definition: coutln.h:133
integer coordinate
Definition: points.h:30

◆ bounding_box()

const TBOX& C_OUTLINE::bounding_box ( ) const
inline

Definition at line 111 of file coutln.h.

111  {
112  return box;
113  }

◆ chain_code()

int C_OUTLINE::chain_code ( int  index) const
inline

Definition at line 193 of file coutln.h.

193  { // index of step
194  return (steps[index / 4] >> (index % 4 * 2)) & STEP_MASK;
195  }
#define STEP_MASK
Definition: coutln.h:35

◆ chain_step()

ICOORD C_OUTLINE::chain_step ( int  chaindir)
static

Definition at line 1064 of file coutln.cpp.

1064  {
1065  return step_coords[chaindir % 4];
1066 }

◆ child()

C_OUTLINE_LIST* C_OUTLINE::child ( )
inline

Definition at line 106 of file coutln.h.

106  { //get child list
107  return &children;
108  }

◆ ComputeBinaryOffsets()

void C_OUTLINE::ComputeBinaryOffsets ( )

Adds sub-pixel resolution EdgeOffsets for the outline using only a binary image source.

Runs a sliding window of 5 edge steps over the outline, maintaining a count of the number of steps in each of the 4 directions in the window, and a sum of the x or y position of each step (as appropriate to its direction.) Ignores single-count steps EXCEPT the sharp U-turn and smoothes out the perpendicular direction. Eg

* ___              ___       Chain code from the left:
*    |___    ___   ___|      222122212223221232223000
*        |___|  |_|          Corresponding counts of each direction:
*                          0   00000000000000000123
*                          1   11121111001111100000
*                          2   44434443443333343321
*                          3   00000001111111112111
* Count of direction at center 41434143413313143313
* Step gets used?              YNYYYNYYYNYYNYNYYYyY (y= U-turn exception)
* Path redrawn showing only the used points:
* ___              ___
*     ___    ___   ___|
*         ___    _
* 

Sub-pixel edge position cannot be shown well with ASCII-art, but each horizontal step's y position is the mean of the y positions of the steps in the same direction in the sliding window, which makes a much smoother outline, without losing important detail.

Definition at line 850 of file coutln.cpp.

850  {
851  delete [] offsets;
852  offsets = new EdgeOffset[stepcount];
853  // Count of the number of steps in each direction in the sliding window.
854  int dir_counts[4];
855  // Sum of the positions (y for a horizontal step, x for vertical) in each
856  // direction in the sliding window.
857  int pos_totals[4];
858  memset(dir_counts, 0, sizeof(dir_counts));
859  memset(pos_totals, 0, sizeof(pos_totals));
860  ICOORD pos = start;
861  ICOORD tail_pos = pos;
862  // tail_pos is the trailing position, with the next point to be lost from
863  // the window.
864  tail_pos -= step(stepcount - 1);
865  tail_pos -= step(stepcount - 2);
866  // head_pos is the leading position, with the next point to be added to the
867  // window.
868  ICOORD head_pos = tail_pos;
869  // Set up the initial window with 4 points in [-2, 2)
870  for (int s = -2; s < 2; ++s) {
871  increment_step(s, 1, &head_pos, dir_counts, pos_totals);
872  }
873  for (int s = 0; s < stepcount; pos += step(s++)) {
874  // At step s, s in in the middle of [s-2, s+2].
875  increment_step(s + 2, 1, &head_pos, dir_counts, pos_totals);
876  int dir_index = chain_code(s);
877  ICOORD step_vec = step(s);
878  int best_diff = 0;
879  int offset = 0;
880  // Use only steps that have a count of >=2 OR the strong U-turn with a
881  // single d and 2 at d-1 and 2 at d+1 (mod 4).
882  if (dir_counts[dir_index] >= 2 || (dir_counts[dir_index] == 1 &&
883  dir_counts[Modulo(dir_index - 1, 4)] == 2 &&
884  dir_counts[Modulo(dir_index + 1, 4)] == 2)) {
885  // Valid step direction.
886  best_diff = dir_counts[dir_index];
887  int edge_pos = step_vec.x() == 0 ? pos.x() : pos.y();
888  // The offset proposes that the actual step should be positioned at
889  // the mean position of the steps in the window of the same direction.
890  // See ASCII art above.
891  offset = pos_totals[dir_index] - best_diff * edge_pos;
892  }
893  offsets[s].offset_numerator =
894  static_cast<inT8>(ClipToRange(offset, -MAX_INT8, MAX_INT8));
895  offsets[s].pixel_diff = static_cast<uinT8>(ClipToRange(best_diff, 0 ,
896  MAX_UINT8));
897  // The direction is just the vector from start to end of the window.
898  FCOORD direction(head_pos.x() - tail_pos.x(), head_pos.y() - tail_pos.y());
899  offsets[s].direction = direction.to_direction();
900  increment_step(s - 2, -1, &tail_pos, dir_counts, pos_totals);
901  }
902 }
Definition: points.h:189
uinT8 direction
Definition: coutln.h:62
#define MAX_UINT8
Definition: host.h:63
inT16 x() const
access function
Definition: points.h:52
int direction(EDGEPT *point)
Definition: vecfuncs.cpp:43
voidpf uLong offset
Definition: ioapi.h:42
inT16 y() const
access_function
Definition: points.h:56
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:122
int8_t inT8
Definition: host.h:34
ICOORD step(int index) const
Definition: coutln.h:142
uint8_t uinT8
Definition: host.h:35
inT8 offset_numerator
Definition: coutln.h:60
int chain_code(int index) const
Definition: coutln.h:193
#define MAX_INT8
Definition: host.h:60
uinT8 pixel_diff
Definition: coutln.h:61
int Modulo(int a, int b)
Definition: helpers.h:164
integer coordinate
Definition: points.h:30

◆ ComputeEdgeOffsets()

void C_OUTLINE::ComputeEdgeOffsets ( int  threshold,
Pix *  pix 
)

Adds sub-pixel resolution EdgeOffsets for the outline if the supplied pix is 8-bit. Does nothing otherwise. Operation: Consider the following near-horizontal line:

*   _________
*            |________
*                     |________
* 

At every position along this line, the gradient direction will be close to vertical. Extrapoaltion/interpolation of the position of the threshold that was used to binarize the image gives a more precise vertical position for each horizontal step, and the conflict in step direction and gradient direction can be used to ignore the vertical steps.

Definition at line 733 of file coutln.cpp.

733  {
734  if (pixGetDepth(pix) != 8) return;
735  const l_uint32* data = pixGetData(pix);
736  int wpl = pixGetWpl(pix);
737  int width = pixGetWidth(pix);
738  int height = pixGetHeight(pix);
739  bool negative = flag(COUT_INVERSE);
740  delete [] offsets;
741  offsets = new EdgeOffset[stepcount];
742  ICOORD pos = start;
743  ICOORD prev_gradient;
744  ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
745  &prev_gradient);
746  for (int s = 0; s < stepcount; ++s) {
747  ICOORD step_vec = step(s);
748  TPOINT pt1(pos);
749  pos += step_vec;
750  TPOINT pt2(pos);
751  ICOORD next_gradient;
752  ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
753  &next_gradient);
754  // Use the sum of the prev and next as the working gradient.
755  ICOORD gradient = prev_gradient + next_gradient;
756  // best_diff will be manipulated to be always positive.
757  int best_diff = 0;
758  // offset will be the extrapolation of the location of the greyscale
759  // threshold from the edge with the largest difference, relative to the
760  // location of the binary edge.
761  int offset = 0;
762  if (pt1.y == pt2.y && abs(gradient.y()) * 2 >= abs(gradient.x())) {
763  // Horizontal step. diff_sign == 1 indicates black above.
764  int diff_sign = (pt1.x > pt2.x) == negative ? 1 : -1;
765  int x = MIN(pt1.x, pt2.x);
766  int y = height - pt1.y;
767  int best_sum = 0;
768  int best_y = y;
769  EvaluateVerticalDiff(data, wpl, diff_sign, x, y, height,
770  &best_diff, &best_sum, &best_y);
771  // Find the strongest edge.
772  int test_y = y;
773  do {
774  ++test_y;
775  } while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
776  &best_diff, &best_sum, &best_y));
777  test_y = y;
778  do {
779  --test_y;
780  } while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
781  &best_diff, &best_sum, &best_y));
782  offset = diff_sign * (best_sum / 2 - threshold) +
783  (y - best_y) * best_diff;
784  } else if (pt1.x == pt2.x && abs(gradient.x()) * 2 >= abs(gradient.y())) {
785  // Vertical step. diff_sign == 1 indicates black on the left.
786  int diff_sign = (pt1.y > pt2.y) == negative ? 1 : -1;
787  int x = pt1.x;
788  int y = height - MAX(pt1.y, pt2.y);
789  const l_uint32* line = pixGetData(pix) + y * wpl;
790  int best_sum = 0;
791  int best_x = x;
792  EvaluateHorizontalDiff(line, diff_sign, x, width,
793  &best_diff, &best_sum, &best_x);
794  // Find the strongest edge.
795  int test_x = x;
796  do {
797  ++test_x;
798  } while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
799  &best_diff, &best_sum, &best_x));
800  test_x = x;
801  do {
802  --test_x;
803  } while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
804  &best_diff, &best_sum, &best_x));
805  offset = diff_sign * (threshold - best_sum / 2) +
806  (best_x - x) * best_diff;
807  }
808  offsets[s].offset_numerator =
809  static_cast<inT8>(ClipToRange(offset, -MAX_INT8, MAX_INT8));
810  offsets[s].pixel_diff = static_cast<uinT8>(ClipToRange(best_diff, 0 ,
811  MAX_UINT8));
812  if (negative) gradient = -gradient;
813  // Compute gradient angle quantized to 256 directions, rotated by 64 (pi/2)
814  // to convert from gradient direction to edge direction.
815  offsets[s].direction =
816  Modulo(FCOORD::binary_angle_plus_pi(gradient.angle()) + 64, 256);
817  prev_gradient = next_gradient;
818  }
819 }
static uinT8 binary_angle_plus_pi(double angle)
Definition: points.cpp:124
uinT8 direction
Definition: coutln.h:62
#define MAX_UINT8
Definition: host.h:63
BOOL8 flag(C_OUTLINE_FLAGS mask) const
Definition: coutln.h:96
inT16 x() const
access function
Definition: points.h:52
voidpf uLong offset
Definition: ioapi.h:42
inT16 y() const
access_function
Definition: points.h:56
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:122
#define MAX(x, y)
Definition: ndminx.h:24
int8_t inT8
Definition: host.h:34
#define MIN(x, y)
Definition: ndminx.h:28
ICOORD step(int index) const
Definition: coutln.h:142
Definition: blobs.h:50
uint8_t uinT8
Definition: host.h:35
inT8 offset_numerator
Definition: coutln.h:60
#define MAX_INT8
Definition: host.h:60
uinT8 pixel_diff
Definition: coutln.h:61
int Modulo(int a, int b)
Definition: helpers.h:164
integer coordinate
Definition: points.h:30

◆ count_transitions()

inT32 C_OUTLINE::count_transitions ( inT32  threshold)

Definition at line 340 of file coutln.cpp.

340  {
341  BOOL8 first_was_max_x; //what was first
342  BOOL8 first_was_max_y;
343  BOOL8 looking_for_max_x; //what is next
344  BOOL8 looking_for_min_x;
345  BOOL8 looking_for_max_y; //what is next
346  BOOL8 looking_for_min_y;
347  int stepindex; //current step
348  inT32 total_steps; //steps to do
349  //current limits
350  inT32 max_x, min_x, max_y, min_y;
351  inT32 initial_x, initial_y; //initial limits
352  inT32 total; //total changes
353  ICOORD pos; //position of point
354  ICOORD next_step; //step to next pix
355 
356  pos = start_pos ();
357  total_steps = pathlength ();
358  total = 0;
359  max_x = min_x = pos.x ();
360  max_y = min_y = pos.y ();
361  looking_for_max_x = TRUE;
362  looking_for_min_x = TRUE;
363  looking_for_max_y = TRUE;
364  looking_for_min_y = TRUE;
365  first_was_max_x = FALSE;
366  first_was_max_y = FALSE;
367  initial_x = pos.x ();
368  initial_y = pos.y (); //stop uninit warning
369  for (stepindex = 0; stepindex < total_steps; stepindex++) {
370  //all intersected
371  next_step = step (stepindex);
372  pos += next_step;
373  if (next_step.x () < 0) {
374  if (looking_for_max_x && pos.x () < min_x)
375  min_x = pos.x ();
376  if (looking_for_min_x && max_x - pos.x () > threshold) {
377  if (looking_for_max_x) {
378  initial_x = max_x;
379  first_was_max_x = FALSE;
380  }
381  total++;
382  looking_for_max_x = TRUE;
383  looking_for_min_x = FALSE;
384  min_x = pos.x (); //reset min
385  }
386  }
387  else if (next_step.x () > 0) {
388  if (looking_for_min_x && pos.x () > max_x)
389  max_x = pos.x ();
390  if (looking_for_max_x && pos.x () - min_x > threshold) {
391  if (looking_for_min_x) {
392  initial_x = min_x; //remember first min
393  first_was_max_x = TRUE;
394  }
395  total++;
396  looking_for_max_x = FALSE;
397  looking_for_min_x = TRUE;
398  max_x = pos.x ();
399  }
400  }
401  else if (next_step.y () < 0) {
402  if (looking_for_max_y && pos.y () < min_y)
403  min_y = pos.y ();
404  if (looking_for_min_y && max_y - pos.y () > threshold) {
405  if (looking_for_max_y) {
406  initial_y = max_y; //remember first max
407  first_was_max_y = FALSE;
408  }
409  total++;
410  looking_for_max_y = TRUE;
411  looking_for_min_y = FALSE;
412  min_y = pos.y (); //reset min
413  }
414  }
415  else {
416  if (looking_for_min_y && pos.y () > max_y)
417  max_y = pos.y ();
418  if (looking_for_max_y && pos.y () - min_y > threshold) {
419  if (looking_for_min_y) {
420  initial_y = min_y; //remember first min
421  first_was_max_y = TRUE;
422  }
423  total++;
424  looking_for_max_y = FALSE;
425  looking_for_min_y = TRUE;
426  max_y = pos.y ();
427  }
428  }
429 
430  }
431  if (first_was_max_x && looking_for_min_x) {
432  if (max_x - initial_x > threshold)
433  total++;
434  else
435  total--;
436  }
437  else if (!first_was_max_x && looking_for_max_x) {
438  if (initial_x - min_x > threshold)
439  total++;
440  else
441  total--;
442  }
443  if (first_was_max_y && looking_for_min_y) {
444  if (max_y - initial_y > threshold)
445  total++;
446  else
447  total--;
448  }
449  else if (!first_was_max_y && looking_for_max_y) {
450  if (initial_y - min_y > threshold)
451  total++;
452  else
453  total--;
454  }
455 
456  return total;
457 }
#define TRUE
Definition: capi.h:45
int32_t inT32
Definition: host.h:38
inT16 x() const
access function
Definition: points.h:52
unsigned char BOOL8
Definition: host.h:44
#define FALSE
Definition: capi.h:46
inT16 y() const
access_function
Definition: points.h:56
ICOORD step(int index) const
Definition: coutln.h:142
const ICOORD & start_pos() const
Definition: coutln.h:146
inT32 pathlength() const
Definition: coutln.h:133
integer coordinate
Definition: points.h:30

◆ deep_copy()

static C_OUTLINE* C_OUTLINE::deep_copy ( const C_OUTLINE src)
inlinestatic

Definition at line 259 of file coutln.h.

259  {
260  C_OUTLINE* outline = new C_OUTLINE;
261  *outline = *src;
262  return outline;
263  }
C_OUTLINE()
Definition: coutln.h:71

◆ direction_at_index()

int C_OUTLINE::direction_at_index ( int  index) const
inline

Definition at line 176 of file coutln.h.

176  {
177  if (offsets != NULL && offsets[index].pixel_diff > 0)
178  return offsets[index].direction;
179  return -1;
180  }
uinT8 direction
Definition: coutln.h:62

◆ edge_strength_at_index()

int C_OUTLINE::edge_strength_at_index ( int  index) const
inline

Definition at line 185 of file coutln.h.

185  {
186  if (offsets != NULL)
187  return offsets[index].pixel_diff;
188  return 1;
189  }
uinT8 pixel_diff
Definition: coutln.h:61

◆ FakeOutline()

void C_OUTLINE::FakeOutline ( const TBOX box,
C_OUTLINE_LIST *  outlines 
)
static

Definition at line 239 of file coutln.cpp.

239  {
240  C_OUTLINE_IT ol_it(outlines);
241  // Make a C_OUTLINE from the bounds. This is a bit of a hack,
242  // as there is no outline, just a bounding box, but it works nicely.
243  CRACKEDGE start;
244  start.pos = box.topleft();
245  C_OUTLINE* outline = new C_OUTLINE(&start, box.topleft(), box.botright(), 0);
246  ol_it.add_to_end(outline);
247 }
ICOORD topleft() const
Definition: rect.h:96
ICOORD pos
Definition: crakedge.h:30
ICOORD botright() const
Definition: rect.h:92
C_OUTLINE()
Definition: coutln.h:71

◆ flag()

BOOL8 C_OUTLINE::flag ( C_OUTLINE_FLAGS  mask) const
inline

Definition at line 96 of file coutln.h.

97  { //flag to test
98  return flags.bit (mask);
99  }
BOOL8 bit(uinT8 bit_num) const
Definition: bits16.h:56

◆ IsLegallyNested()

bool C_OUTLINE::IsLegallyNested ( ) const

Returns true if *this and its children are legally nested. The outer area of a child should have the opposite sign to the parent. If not, it means we have discarded an outline in between (probably due to excessive length).

Definition at line 604 of file coutln.cpp.

604  {
605  if (stepcount == 0) return true;
606  int parent_area = outer_area();
607  // We aren't going to modify the list, or its contents, but there is
608  // no const iterator.
609  C_OUTLINE_IT child_it(const_cast<C_OUTLINE_LIST*>(&children));
610  for (child_it.mark_cycle_pt(); !child_it.cycled_list(); child_it.forward()) {
611  const C_OUTLINE* child = child_it.data();
612  if (child->outer_area() * parent_area > 0 || !child->IsLegallyNested())
613  return false;
614  }
615  return true;
616 }
C_OUTLINE_LIST * child()
Definition: coutln.h:106
inT32 outer_area() const
Definition: coutln.cpp:308
bool IsLegallyNested() const
Definition: coutln.cpp:604

◆ move()

void C_OUTLINE::move ( const ICOORD  vec)

Definition at line 588 of file coutln.cpp.

588  {
589  C_OUTLINE_IT it(&children); // iterator
590 
591  box.move (vec);
592  start += vec;
593 
594  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
595  it.data ()->move (vec); // move child outlines
596 }
void move(const ICOORD vec)
Definition: rect.h:153

◆ operator<()

BOOL8 C_OUTLINE::operator< ( const C_OUTLINE other) const

Definition at line 467 of file coutln.cpp.

467  {
468  inT16 count = 0; //winding count
469  ICOORD pos; //position of point
470  inT32 stepindex; //index to cstep
471 
472  if (!box.overlap (other.box))
473  return FALSE; //can't be contained
474  if (stepcount == 0)
475  return other.box.contains(this->box);
476 
477  pos = start;
478  for (stepindex = 0; stepindex < stepcount
479  && (count = other.winding_number (pos)) == INTERSECTING; stepindex++)
480  pos += step (stepindex); //try all points
481  if (count == INTERSECTING) {
482  //all intersected
483  pos = other.start;
484  for (stepindex = 0; stepindex < other.stepcount
485  && (count = winding_number (pos)) == INTERSECTING; stepindex++)
486  //try other way round
487  pos += other.step (stepindex);
488  return count == INTERSECTING || count == 0;
489  }
490  return count != 0;
491 }
bool overlap(const TBOX &box) const
Definition: rect.h:345
int32_t inT32
Definition: host.h:38
#define INTERSECTING
Definition: coutln.h:32
int16_t inT16
Definition: host.h:36
#define FALSE
Definition: capi.h:46
inT16 winding_number(ICOORD testpt) const
Definition: coutln.cpp:500
bool contains(const FCOORD pt) const
Definition: rect.h:323
ICOORD step(int index) const
Definition: coutln.h:142
int count(LIST var_list)
Definition: oldlist.cpp:103
integer coordinate
Definition: points.h:30

◆ operator=()

C_OUTLINE & C_OUTLINE::operator= ( const C_OUTLINE source)

Definition at line 1024 of file coutln.cpp.

1024  {
1025  box = source.box;
1026  start = source.start;
1027  if (steps != NULL)
1028  free_mem(steps);
1029  stepcount = source.stepcount;
1030  steps = (uinT8 *) alloc_mem (step_mem());
1031  memmove (steps, source.steps, step_mem());
1032  if (!children.empty ())
1033  children.clear ();
1034  children.deep_copy(&source.children, &deep_copy);
1035  delete [] offsets;
1036  if (source.offsets != NULL) {
1037  offsets = new EdgeOffset[stepcount];
1038  memcpy(offsets, source.offsets, stepcount * sizeof(*offsets));
1039  } else {
1040  offsets = NULL;
1041  }
1042  return *this;
1043 }
void free_mem(void *oldchunk)
Definition: memry.cpp:47
void * alloc_mem(inT32 count)
Definition: memry.cpp:39
static C_OUTLINE * deep_copy(const C_OUTLINE *src)
Definition: coutln.h:259
uint8_t uinT8
Definition: host.h:35

◆ operator>()

BOOL8 C_OUTLINE::operator> ( C_OUTLINE other) const
inline

Definition at line 205 of file coutln.h.

207  {
208  return other < *this; //use the < to do it
209  }

◆ outer_area()

inT32 C_OUTLINE::outer_area ( ) const

Definition at line 308 of file coutln.cpp.

308  {
309  int stepindex; //current step
310  inT32 total_steps; //steps to do
311  inT32 total; //total area
312  ICOORD pos; //position of point
313  ICOORD next_step; //step to next pix
314 
315  pos = start_pos ();
316  total_steps = pathlength ();
317  if (total_steps == 0)
318  return box.area();
319  total = 0;
320  for (stepindex = 0; stepindex < total_steps; stepindex++) {
321  //all intersected
322  next_step = step (stepindex);
323  if (next_step.x () < 0)
324  total += pos.y ();
325  else if (next_step.x () > 0)
326  total -= pos.y ();
327  pos += next_step;
328  }
329 
330  return total;
331 }
int32_t inT32
Definition: host.h:38
inT32 area() const
Definition: rect.h:118
inT16 x() const
access function
Definition: points.h:52
inT16 y() const
access_function
Definition: points.h:56
ICOORD step(int index) const
Definition: coutln.h:142
const ICOORD & start_pos() const
Definition: coutln.h:146
inT32 pathlength() const
Definition: coutln.h:133
integer coordinate
Definition: points.h:30

◆ pathlength()

inT32 C_OUTLINE::pathlength ( ) const
inline

Definition at line 133 of file coutln.h.

133  { //get path length
134  return stepcount;
135  }

◆ perimeter()

inT32 C_OUTLINE::perimeter ( ) const

Definition at line 289 of file coutln.cpp.

289  {
290  inT32 total_steps; // Return value.
291  // We aren't going to modify the list, or its contents, but there is
292  // no const iterator.
293  C_OUTLINE_IT it(const_cast<C_OUTLINE_LIST*>(&children));
294 
295  total_steps = pathlength();
296  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward())
297  total_steps += it.data()->pathlength(); // Add perimeters of children.
298 
299  return total_steps;
300 }
int32_t inT32
Definition: host.h:38
inT32 pathlength() const
Definition: coutln.h:133

◆ plot()

void C_OUTLINE::plot ( ScrollView window,
ScrollView::Color  colour 
) const

Definition at line 956 of file coutln.cpp.

956  {
957  inT16 stepindex; // index to cstep
958  ICOORD pos; // current position
959  DIR128 stepdir; // direction of step
960 
961  pos = start; // current position
962  window->Pen(colour);
963  if (stepcount == 0) {
964  window->Rectangle(box.left(), box.top(), box.right(), box.bottom());
965  return;
966  }
967  window->SetCursor(pos.x(), pos.y());
968 
969  stepindex = 0;
970  while (stepindex < stepcount) {
971  pos += step(stepindex); // step to next
972  stepdir = step_dir(stepindex);
973  stepindex++; // count steps
974  // merge straight lines
975  while (stepindex < stepcount &&
976  stepdir.get_dir() == step_dir(stepindex).get_dir()) {
977  pos += step(stepindex);
978  stepindex++;
979  }
980  window->DrawTo(pos.x(), pos.y());
981  }
982 }
inT16 x() const
access function
Definition: points.h:52
int16_t inT16
Definition: host.h:36
void SetCursor(int x, int y)
Definition: scrollview.cpp:525
inT16 left() const
Definition: rect.h:68
void Rectangle(int x1, int y1, int x2, int y2)
Definition: scrollview.cpp:606
inT16 y() const
access_function
Definition: points.h:56
inT16 top() const
Definition: rect.h:54
DIR128 step_dir(int index) const
Definition: coutln.h:137
ICOORD step(int index) const
Definition: coutln.h:142
inT16 right() const
Definition: rect.h:75
inT8 get_dir() const
Definition: mod128.h:77
inT16 bottom() const
Definition: rect.h:61
Definition: mod128.h:29
void Pen(Color color)
Definition: scrollview.cpp:726
void DrawTo(int x, int y)
Definition: scrollview.cpp:531
integer coordinate
Definition: points.h:30

◆ plot_normed()

void C_OUTLINE::plot_normed ( const DENORM denorm,
ScrollView::Color  colour,
ScrollView window 
) const

Draws the outline in the given colour, normalized using the given denorm, making use of sub-pixel accurate information if available.

Definition at line 988 of file coutln.cpp.

989  {
990  window->Pen(colour);
991  if (stepcount == 0) {
992  window->Rectangle(box.left(), box.top(), box.right(), box.bottom());
993  return;
994  }
995  const DENORM* root_denorm = denorm.RootDenorm();
996  ICOORD pos = start; // current position
997  FCOORD f_pos = sub_pixel_pos_at_index(pos, 0);
998  FCOORD pos_normed;
999  denorm.NormTransform(root_denorm, f_pos, &pos_normed);
1000  window->SetCursor(IntCastRounded(pos_normed.x()),
1001  IntCastRounded(pos_normed.y()));
1002  for (int s = 0; s < stepcount; pos += step(s++)) {
1003  int edge_weight = edge_strength_at_index(s);
1004  if (edge_weight == 0) {
1005  // This point has conflicting gradient and step direction, so ignore it.
1006  continue;
1007  }
1008  FCOORD f_pos = sub_pixel_pos_at_index(pos, s);
1009  FCOORD pos_normed;
1010  denorm.NormTransform(root_denorm, f_pos, &pos_normed);
1011  window->DrawTo(IntCastRounded(pos_normed.x()),
1012  IntCastRounded(pos_normed.y()));
1013  }
1014 }
const DENORM * RootDenorm() const
Definition: normalis.h:260
Definition: points.h:189
void NormTransform(const DENORM *first_norm, const TPOINT &pt, TPOINT *transformed) const
Definition: normalis.cpp:334
int IntCastRounded(double x)
Definition: helpers.h:179
void SetCursor(int x, int y)
Definition: scrollview.cpp:525
inT16 left() const
Definition: rect.h:68
void Rectangle(int x1, int y1, int x2, int y2)
Definition: scrollview.cpp:606
int edge_strength_at_index(int index) const
Definition: coutln.h:185
inT16 top() const
Definition: rect.h:54
ICOORD step(int index) const
Definition: coutln.h:142
FCOORD sub_pixel_pos_at_index(const ICOORD &pos, int index) const
Definition: coutln.h:161
float y() const
Definition: points.h:212
inT16 right() const
Definition: rect.h:75
inT16 bottom() const
Definition: rect.h:61
float x() const
Definition: points.h:209
void Pen(Color color)
Definition: scrollview.cpp:726
void DrawTo(int x, int y)
Definition: scrollview.cpp:531
integer coordinate
Definition: points.h:30

◆ position_at_index()

ICOORD C_OUTLINE::position_at_index ( int  index) const
inline

Definition at line 151 of file coutln.h.

151  {
152  ICOORD pos = start;
153  for (int i = 0; i < index; ++i)
154  pos += step(i);
155  return pos;
156  }
ICOORD step(int index) const
Definition: coutln.h:142
integer coordinate
Definition: points.h:30

◆ RemoveSmallRecursive()

void C_OUTLINE::RemoveSmallRecursive ( int  min_size,
C_OUTLINE_IT *  it 
)

If this outline is smaller than the given min_size, delete this and remove from its list, via *it, after checking that *it points to this. Otherwise, if any children of this are too small, delete them. On entry, *it must be an iterator pointing to this. If this gets deleted then this is extracted from *it, so an iteration can continue.

Parameters
min_sizeminimum size for outline
itoutline iterator

Definition at line 627 of file coutln.cpp.

627  {
628  if (box.width() < min_size || box.height() < min_size) {
629  ASSERT_HOST(this == it->data());
630  delete it->extract(); // Too small so get rid of it and any children.
631  } else if (!children.empty()) {
632  // Search the children of this, deleting any that are too small.
633  C_OUTLINE_IT child_it(&children);
634  for (child_it.mark_cycle_pt(); !child_it.cycled_list();
635  child_it.forward()) {
636  C_OUTLINE* child = child_it.data();
637  child->RemoveSmallRecursive(min_size, &child_it);
638  }
639  }
640 }
C_OUTLINE_LIST * child()
Definition: coutln.h:106
void RemoveSmallRecursive(int min_size, C_OUTLINE_IT *it)
Definition: coutln.cpp:627
#define ASSERT_HOST(x)
Definition: errcode.h:84
inT16 height() const
Definition: rect.h:104
inT16 width() const
Definition: rect.h:111

◆ render()

void C_OUTLINE::render ( int  left,
int  top,
Pix *  pix 
) const

Renders the outline to the given pix, with left and top being the coords of the upper-left corner of the pix.

Definition at line 908 of file coutln.cpp.

908  {
909  ICOORD pos = start;
910  for (int stepindex = 0; stepindex < stepcount; ++stepindex) {
911  ICOORD next_step = step(stepindex);
912  if (next_step.y() < 0) {
913  pixRasterop(pix, 0, top - pos.y(), pos.x() - left, 1,
914  PIX_NOT(PIX_DST), NULL, 0, 0);
915  } else if (next_step.y() > 0) {
916  pixRasterop(pix, 0, top - pos.y() - 1, pos.x() - left, 1,
917  PIX_NOT(PIX_DST), NULL, 0, 0);
918  }
919  pos += next_step;
920  }
921 }
inT16 x() const
access function
Definition: points.h:52
inT16 y() const
access_function
Definition: points.h:56
ICOORD step(int index) const
Definition: coutln.h:142
integer coordinate
Definition: points.h:30

◆ render_outline()

void C_OUTLINE::render_outline ( int  left,
int  top,
Pix *  pix 
) const

Renders just the outline to the given pix (no fill), with left and top being the coords of the upper-left corner of the pix.

Parameters
leftcoord
topcoord
pixthe pix to outline

Definition at line 930 of file coutln.cpp.

930  {
931  ICOORD pos = start;
932  for (int stepindex = 0; stepindex < stepcount; ++stepindex) {
933  ICOORD next_step = step(stepindex);
934  if (next_step.y() < 0) {
935  pixSetPixel(pix, pos.x() - left, top - pos.y(), 1);
936  } else if (next_step.y() > 0) {
937  pixSetPixel(pix, pos.x() - left - 1, top - pos.y() - 1, 1);
938  } else if (next_step.x() < 0) {
939  pixSetPixel(pix, pos.x() - left - 1, top - pos.y(), 1);
940  } else if (next_step.x() > 0) {
941  pixSetPixel(pix, pos.x() - left, top - pos.y() - 1, 1);
942  }
943  pos += next_step;
944  }
945 }
inT16 x() const
access function
Definition: points.h:52
inT16 y() const
access_function
Definition: points.h:56
ICOORD step(int index) const
Definition: coutln.h:142
integer coordinate
Definition: points.h:30

◆ reverse()

void C_OUTLINE::reverse ( )

Definition at line 565 of file coutln.cpp.

565  { //reverse drection
566  DIR128 halfturn = MODULUS / 2; //amount to shift
567  DIR128 stepdir; //direction of step
568  inT16 stepindex; //index to cstep
569  inT16 farindex; //index to other side
570  inT16 halfsteps; //half of stepcount
571 
572  halfsteps = (stepcount + 1) / 2;
573  for (stepindex = 0; stepindex < halfsteps; stepindex++) {
574  farindex = stepcount - stepindex - 1;
575  stepdir = step_dir (stepindex);
576  set_step (stepindex, step_dir (farindex) + halfturn);
577  set_step (farindex, stepdir + halfturn);
578  }
579 }
void set_step(inT16 stepindex, inT8 stepdir)
Definition: coutln.h:114
int16_t inT16
Definition: host.h:36
#define MODULUS
Definition: mod128.h:25
DIR128 step_dir(int index) const
Definition: coutln.h:137
Definition: mod128.h:29

◆ set_flag()

void C_OUTLINE::set_flag ( C_OUTLINE_FLAGS  mask,
BOOL8  value 
)
inline

Definition at line 100 of file coutln.h.

102  { //value to set
103  flags.set_bit (mask, value);
104  }
void set_bit(uinT8 bit_num, BOOL8 value)
Definition: bits16.h:47

◆ set_step() [1/2]

void C_OUTLINE::set_step ( inT16  stepindex,
inT8  stepdir 
)
inline

Definition at line 114 of file coutln.h.

116  { //chain code
117  int shift = stepindex%4 * 2;
118  uinT8 mask = 3 << shift;
119  steps[stepindex/4] = ((stepdir << shift) & mask) |
120  (steps[stepindex/4] & ~mask);
121  //squeeze 4 into byte
122  }
uint8_t uinT8
Definition: host.h:35

◆ set_step() [2/2]

void C_OUTLINE::set_step ( inT16  stepindex,
DIR128  stepdir 
)
inline

Definition at line 123 of file coutln.h.

125  { //direction
126  //clean it
127  inT8 chaindir = stepdir.get_dir() >> (DIRBITS - 2);
128  //difference
129  set_step(stepindex, chaindir);
130  //squeeze 4 into byte
131  }
void set_step(inT16 stepindex, inT8 stepdir)
Definition: coutln.h:114
#define DIRBITS
Definition: mod128.h:26
int8_t inT8
Definition: host.h:34
inT8 get_dir() const
Definition: mod128.h:77

◆ start_pos()

const ICOORD& C_OUTLINE::start_pos ( ) const
inline

Definition at line 146 of file coutln.h.

146  {
147  return start;
148  }

◆ step()

ICOORD C_OUTLINE::step ( int  index) const
inline

Definition at line 142 of file coutln.h.

142  { // index of step
143  return step_coords[chain_code(index)];
144  }
int chain_code(int index) const
Definition: coutln.h:193

◆ step_dir()

DIR128 C_OUTLINE::step_dir ( int  index) const
inline

Definition at line 137 of file coutln.h.

137  {
138  return DIR128((inT16)(((steps[index/4] >> (index%4 * 2)) & STEP_MASK) <<
139  (DIRBITS - 2)));
140  }
#define STEP_MASK
Definition: coutln.h:35
int16_t inT16
Definition: host.h:36
#define DIRBITS
Definition: mod128.h:26
Definition: mod128.h:29

◆ sub_pixel_pos_at_index()

FCOORD C_OUTLINE::sub_pixel_pos_at_index ( const ICOORD pos,
int  index 
) const
inline

Definition at line 161 of file coutln.h.

161  {
162  const ICOORD& step_to_next(step(index));
163  FCOORD f_pos(pos.x() + step_to_next.x() / 2.0f,
164  pos.y() + step_to_next.y() / 2.0f);
165  if (offsets != NULL && offsets[index].pixel_diff > 0) {
166  float offset = offsets[index].offset_numerator;
167  offset /= offsets[index].pixel_diff;
168  if (step_to_next.x() != 0)
169  f_pos.set_y(f_pos.y() + offset);
170  else
171  f_pos.set_x(f_pos.x() + offset);
172  }
173  return f_pos;
174  }
Definition: points.h:189
inT16 x() const
access function
Definition: points.h:52
voidpf uLong offset
Definition: ioapi.h:42
inT16 y() const
access_function
Definition: points.h:56
ICOORD step(int index) const
Definition: coutln.h:142
inT8 offset_numerator
Definition: coutln.h:60
uinT8 pixel_diff
Definition: coutln.h:61
integer coordinate
Definition: points.h:30

◆ turn_direction()

inT16 C_OUTLINE::turn_direction ( ) const

C_OUTLINE::turn_direction

Returns
the sum direction delta of the outline.

Definition at line 537 of file coutln.cpp.

537  { //winding number
538  DIR128 prevdir; //previous direction
539  DIR128 dir; //current direction
540  inT16 stepindex; //index to cstep
541  inT8 dirdiff; //direction difference
542  inT16 count; //winding count
543 
544  if (stepcount == 0)
545  return 128;
546  count = 0;
547  prevdir = step_dir (stepcount - 1);
548  for (stepindex = 0; stepindex < stepcount; stepindex++) {
549  dir = step_dir (stepindex);
550  dirdiff = dir - prevdir;
551  ASSERT_HOST (dirdiff == 0 || dirdiff == 32 || dirdiff == -32);
552  count += dirdiff;
553  prevdir = dir;
554  }
555  ASSERT_HOST (count == 128 || count == -128);
556  return count; //winding number
557 }
int16_t inT16
Definition: host.h:36
#define ASSERT_HOST(x)
Definition: errcode.h:84
DIR128 step_dir(int index) const
Definition: coutln.h:137
int8_t inT8
Definition: host.h:34
Definition: mod128.h:29
int count(LIST var_list)
Definition: oldlist.cpp:103

◆ winding_number()

inT16 C_OUTLINE::winding_number ( ICOORD  testpt) const

Definition at line 500 of file coutln.cpp.

500  {
501  inT16 stepindex; //index to cstep
502  inT16 count; //winding count
503  ICOORD vec; //to current point
504  ICOORD stepvec; //step vector
505  inT32 cross; //cross product
506 
507  vec = start - point; //vector to it
508  count = 0;
509  for (stepindex = 0; stepindex < stepcount; stepindex++) {
510  stepvec = step (stepindex); //get the step
511  //crossing the line
512  if (vec.y () <= 0 && vec.y () + stepvec.y () > 0) {
513  cross = vec * stepvec; //cross product
514  if (cross > 0)
515  count++; //crossing right half
516  else if (cross == 0)
517  return INTERSECTING; //going through point
518  }
519  else if (vec.y () > 0 && vec.y () + stepvec.y () <= 0) {
520  cross = vec * stepvec;
521  if (cross < 0)
522  count--; //crossing back
523  else if (cross == 0)
524  return INTERSECTING; //illegal
525  }
526  vec += stepvec; //sum vectors
527  }
528  return count; //winding number
529 }
int32_t inT32
Definition: host.h:38
#define INTERSECTING
Definition: coutln.h:32
int16_t inT16
Definition: host.h:36
inT16 y() const
access_function
Definition: points.h:56
ICOORD step(int index) const
Definition: coutln.h:142
int count(LIST var_list)
Definition: oldlist.cpp:103
integer coordinate
Definition: points.h:30

Member Data Documentation

◆ kMaxOutlineLength

const int C_OUTLINE::kMaxOutlineLength = 16000
static

Definition at line 271 of file coutln.h.


The documentation for this class was generated from the following files: