tesseract  4.0.0-1-g2a2b
C_OUTLINE Class Reference

#include <coutln.h>

Inheritance diagram for C_OUTLINE:
ELIST_LINK

Public Member Functions

 C_OUTLINE ()
 
 ~C_OUTLINE ()
 
bool flag (C_OUTLINE_FLAGS mask) const
 
void set_flag (C_OUTLINE_FLAGS mask, bool value)
 
C_OUTLINE_LIST * child ()
 
const TBOXbounding_box () const
 
void set_step (int16_t stepindex, int8_t stepdir)
 
void set_step (int16_t stepindex, DIR128 stepdir)
 
int32_t 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
 
bool operator> (C_OUTLINE &other) const
 
C_OUTLINE::area

Compute the area of the outline.

int32_t area () const
 
C_OUTLINE::perimeter

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

int32_t perimeter () const
 
C_OUTLINE::outer_area

Compute the area of the outline.

int32_t 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_t count_transitions (int32_t threshold)
 
C_OUTLINE::operator<
Returns
TRUE if the left operand is inside the right one.
Parameters
otherother outline
bool 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_t winding_number (ICOORD testpt) const
 
int16_t 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_t length)
 
 C_OUTLINE (ICOORD startpt, DIR128 *new_steps, int16_t 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 72 of file coutln.h.

Constructor & Destructor Documentation

◆ C_OUTLINE() [1/4]

C_OUTLINE::C_OUTLINE ( )
inline

Definition at line 74 of file coutln.h.

74  {
75  stepcount = 0;
76  steps = nullptr;
77  offsets = nullptr;
78  }

◆ C_OUTLINE() [2/4]

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

Definition at line 55 of file coutln.cpp.

57  : box(bot_left, top_right), start(startpt->pos), offsets(nullptr) {
58  int16_t stepindex; //index to step
59  CRACKEDGE *edgept; //current point
60 
61  stepcount = length; //no of steps
62  if (length == 0) {
63  steps = nullptr;
64  return;
65  }
66  //get memory
67  steps = (uint8_t *)calloc(step_mem(), 1);
68  edgept = startpt;
69 
70  for (stepindex = 0; stepindex < length; stepindex++) {
71  //set compact step
72  set_step (stepindex, edgept->stepdir);
73  edgept = edgept->next;
74  }
75 }
void set_step(int16_t stepindex, int8_t stepdir)
Definition: coutln.h:116
int8_t stepdir
Definition: crakedge.h:33
ICOORD pos
Definition: crakedge.h:30
CRACKEDGE * next
Definition: crakedge.h:35

◆ C_OUTLINE() [3/4]

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

Definition at line 82 of file coutln.cpp.

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

◆ C_OUTLINE() [4/4]

C_OUTLINE::C_OUTLINE ( C_OUTLINE srcline,
FCOORD  rotation 
)

Definition at line 143 of file coutln.cpp.

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

◆ ~C_OUTLINE()

C_OUTLINE::~C_OUTLINE ( )
inline

Definition at line 93 of file coutln.h.

93  { //destructor
94  free(steps);
95  delete [] offsets;
96  }

Member Function Documentation

◆ area()

int32_t C_OUTLINE::area ( ) const

Definition at line 256 of file coutln.cpp.

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

◆ bounding_box()

const TBOX& C_OUTLINE::bounding_box ( ) const
inline

Definition at line 113 of file coutln.h.

113  {
114  return box;
115  }

◆ chain_code()

int C_OUTLINE::chain_code ( int  index) const
inline

Definition at line 195 of file coutln.h.

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

◆ chain_step()

ICOORD C_OUTLINE::chain_step ( int  chaindir)
static

Definition at line 1050 of file coutln.cpp.

1050  {
1051  return step_coords[chaindir % 4];
1052 }

◆ child()

C_OUTLINE_LIST* C_OUTLINE::child ( )
inline

Definition at line 108 of file coutln.h.

108  { //get child list
109  return &children;
110  }

◆ 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 838 of file coutln.cpp.

838  {
839  delete [] offsets;
840  offsets = new EdgeOffset[stepcount];
841  // Count of the number of steps in each direction in the sliding window.
842  int dir_counts[4];
843  // Sum of the positions (y for a horizontal step, x for vertical) in each
844  // direction in the sliding window.
845  int pos_totals[4];
846  memset(dir_counts, 0, sizeof(dir_counts));
847  memset(pos_totals, 0, sizeof(pos_totals));
848  ICOORD pos = start;
849  ICOORD tail_pos = pos;
850  // tail_pos is the trailing position, with the next point to be lost from
851  // the window.
852  tail_pos -= step(stepcount - 1);
853  tail_pos -= step(stepcount - 2);
854  // head_pos is the leading position, with the next point to be added to the
855  // window.
856  ICOORD head_pos = tail_pos;
857  // Set up the initial window with 4 points in [-2, 2)
858  for (int s = -2; s < 2; ++s) {
859  increment_step(s, 1, &head_pos, dir_counts, pos_totals);
860  }
861  for (int s = 0; s < stepcount; pos += step(s++)) {
862  // At step s, s in in the middle of [s-2, s+2].
863  increment_step(s + 2, 1, &head_pos, dir_counts, pos_totals);
864  int dir_index = chain_code(s);
865  ICOORD step_vec = step(s);
866  int best_diff = 0;
867  int offset = 0;
868  // Use only steps that have a count of >=2 OR the strong U-turn with a
869  // single d and 2 at d-1 and 2 at d+1 (mod 4).
870  if (dir_counts[dir_index] >= 2 || (dir_counts[dir_index] == 1 &&
871  dir_counts[Modulo(dir_index - 1, 4)] == 2 &&
872  dir_counts[Modulo(dir_index + 1, 4)] == 2)) {
873  // Valid step direction.
874  best_diff = dir_counts[dir_index];
875  int edge_pos = step_vec.x() == 0 ? pos.x() : pos.y();
876  // The offset proposes that the actual step should be positioned at
877  // the mean position of the steps in the window of the same direction.
878  // See ASCII art above.
879  offset = pos_totals[dir_index] - best_diff * edge_pos;
880  }
881  offsets[s].offset_numerator =
882  ClipToRange<int>(offset, -INT8_MAX, INT8_MAX);
883  offsets[s].pixel_diff = ClipToRange<int>(best_diff, 0, UINT8_MAX);
884  // The direction is just the vector from start to end of the window.
885  FCOORD direction(head_pos.x() - tail_pos.x(), head_pos.y() - tail_pos.y());
886  offsets[s].direction = direction.to_direction();
887  increment_step(s - 2, -1, &tail_pos, dir_counts, pos_totals);
888  }
889 }
int16_t y() const
access_function
Definition: points.h:57
int Modulo(int a, int b)
Definition: helpers.h:153
int direction(EDGEPT *point)
Definition: vecfuncs.cpp:43
integer coordinate
Definition: points.h:32
int16_t x() const
access function
Definition: points.h:53
uint8_t pixel_diff
Definition: coutln.h:64
Definition: points.h:189
uint8_t direction
Definition: coutln.h:65
int chain_code(int index) const
Definition: coutln.h:195
int8_t offset_numerator
Definition: coutln.h:63
ICOORD step(int index) const
Definition: coutln.h:144

◆ 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 722 of file coutln.cpp.

722  {
723  if (pixGetDepth(pix) != 8) return;
724  const l_uint32* data = pixGetData(pix);
725  int wpl = pixGetWpl(pix);
726  int width = pixGetWidth(pix);
727  int height = pixGetHeight(pix);
728  bool negative = flag(COUT_INVERSE);
729  delete [] offsets;
730  offsets = new EdgeOffset[stepcount];
731  ICOORD pos = start;
732  ICOORD prev_gradient;
733  ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
734  &prev_gradient);
735  for (int s = 0; s < stepcount; ++s) {
736  ICOORD step_vec = step(s);
737  TPOINT pt1(pos);
738  pos += step_vec;
739  TPOINT pt2(pos);
740  ICOORD next_gradient;
741  ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
742  &next_gradient);
743  // Use the sum of the prev and next as the working gradient.
744  ICOORD gradient = prev_gradient + next_gradient;
745  // best_diff will be manipulated to be always positive.
746  int best_diff = 0;
747  // offset will be the extrapolation of the location of the greyscale
748  // threshold from the edge with the largest difference, relative to the
749  // location of the binary edge.
750  int offset = 0;
751  if (pt1.y == pt2.y && abs(gradient.y()) * 2 >= abs(gradient.x())) {
752  // Horizontal step. diff_sign == 1 indicates black above.
753  int diff_sign = (pt1.x > pt2.x) == negative ? 1 : -1;
754  int x = std::min(pt1.x, pt2.x);
755  int y = height - pt1.y;
756  int best_sum = 0;
757  int best_y = y;
758  EvaluateVerticalDiff(data, wpl, diff_sign, x, y, height,
759  &best_diff, &best_sum, &best_y);
760  // Find the strongest edge.
761  int test_y = y;
762  do {
763  ++test_y;
764  } while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
765  &best_diff, &best_sum, &best_y));
766  test_y = y;
767  do {
768  --test_y;
769  } while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
770  &best_diff, &best_sum, &best_y));
771  offset = diff_sign * (best_sum / 2 - threshold) +
772  (y - best_y) * best_diff;
773  } else if (pt1.x == pt2.x && abs(gradient.x()) * 2 >= abs(gradient.y())) {
774  // Vertical step. diff_sign == 1 indicates black on the left.
775  int diff_sign = (pt1.y > pt2.y) == negative ? 1 : -1;
776  int x = pt1.x;
777  int y = height - std::max(pt1.y, pt2.y);
778  const l_uint32* line = pixGetData(pix) + y * wpl;
779  int best_sum = 0;
780  int best_x = x;
781  EvaluateHorizontalDiff(line, diff_sign, x, width,
782  &best_diff, &best_sum, &best_x);
783  // Find the strongest edge.
784  int test_x = x;
785  do {
786  ++test_x;
787  } while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
788  &best_diff, &best_sum, &best_x));
789  test_x = x;
790  do {
791  --test_x;
792  } while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
793  &best_diff, &best_sum, &best_x));
794  offset = diff_sign * (threshold - best_sum / 2) +
795  (best_x - x) * best_diff;
796  }
797  offsets[s].offset_numerator =
798  ClipToRange<int>(offset, -INT8_MAX, INT8_MAX);
799  offsets[s].pixel_diff = ClipToRange<int>(best_diff, 0, UINT8_MAX);
800  if (negative) gradient = -gradient;
801  // Compute gradient angle quantized to 256 directions, rotated by 64 (pi/2)
802  // to convert from gradient direction to edge direction.
803  offsets[s].direction =
804  Modulo(FCOORD::binary_angle_plus_pi(gradient.angle()) + 64, 256);
805  prev_gradient = next_gradient;
806  }
807 }
int16_t y() const
access_function
Definition: points.h:57
int Modulo(int a, int b)
Definition: helpers.h:153
bool flag(C_OUTLINE_FLAGS mask) const
Definition: coutln.h:98
static uint8_t binary_angle_plus_pi(double angle)
Definition: points.cpp:123
integer coordinate
Definition: points.h:32
int16_t x() const
access function
Definition: points.h:53
uint8_t pixel_diff
Definition: coutln.h:64
uint8_t direction
Definition: coutln.h:65
Definition: blobs.h:57
int8_t offset_numerator
Definition: coutln.h:63
ICOORD step(int index) const
Definition: coutln.h:144

◆ count_transitions()

int32_t C_OUTLINE::count_transitions ( int32_t  threshold)

Definition at line 341 of file coutln.cpp.

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

◆ deep_copy()

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

Definition at line 261 of file coutln.h.

261  {
262  C_OUTLINE* outline = new C_OUTLINE;
263  *outline = *src;
264  return outline;
265  }
C_OUTLINE()
Definition: coutln.h:74

◆ direction_at_index()

int C_OUTLINE::direction_at_index ( int  index) const
inline

Definition at line 178 of file coutln.h.

178  {
179  if (offsets != nullptr && offsets[index].pixel_diff > 0)
180  return offsets[index].direction;
181  return -1;
182  }
uint8_t direction
Definition: coutln.h:65

◆ edge_strength_at_index()

int C_OUTLINE::edge_strength_at_index ( int  index) const
inline

Definition at line 187 of file coutln.h.

187  {
188  if (offsets != nullptr)
189  return offsets[index].pixel_diff;
190  return 1;
191  }
uint8_t pixel_diff
Definition: coutln.h:64

◆ FakeOutline()

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

Definition at line 240 of file coutln.cpp.

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

◆ flag()

bool C_OUTLINE::flag ( C_OUTLINE_FLAGS  mask) const
inline

Definition at line 98 of file coutln.h.

99  { //flag to test
100  return flags.bit(mask);
101  }
bool bit(uint8_t bit_num) const
Definition: bits16.h:57

◆ 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 605 of file coutln.cpp.

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

◆ move()

void C_OUTLINE::move ( const ICOORD  vec)

Definition at line 589 of file coutln.cpp.

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

◆ operator<()

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

Definition at line 468 of file coutln.cpp.

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

◆ operator=()

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

Definition at line 1011 of file coutln.cpp.

1011  {
1012  box = source.box;
1013  start = source.start;
1014  free(steps);
1015  stepcount = source.stepcount;
1016  steps = (uint8_t *)malloc(step_mem());
1017  memmove (steps, source.steps, step_mem());
1018  if (!children.empty ())
1019  children.clear ();
1020  children.deep_copy(&source.children, &deep_copy);
1021  delete [] offsets;
1022  if (source.offsets != nullptr) {
1023  offsets = new EdgeOffset[stepcount];
1024  memcpy(offsets, source.offsets, stepcount * sizeof(*offsets));
1025  } else {
1026  offsets = nullptr;
1027  }
1028  return *this;
1029 }
static C_OUTLINE * deep_copy(const C_OUTLINE *src)
Definition: coutln.h:261

◆ operator>()

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

Definition at line 207 of file coutln.h.

209  {
210  return other < *this; //use the < to do it
211  }

◆ outer_area()

int32_t C_OUTLINE::outer_area ( ) const

Definition at line 309 of file coutln.cpp.

309  {
310  int stepindex; //current step
311  int32_t total_steps; //steps to do
312  int32_t total; //total area
313  ICOORD pos; //position of point
314  ICOORD next_step; //step to next pix
315 
316  pos = start_pos ();
317  total_steps = pathlength ();
318  if (total_steps == 0)
319  return box.area();
320  total = 0;
321  for (stepindex = 0; stepindex < total_steps; stepindex++) {
322  //all intersected
323  next_step = step (stepindex);
324  if (next_step.x () < 0)
325  total += pos.y ();
326  else if (next_step.x () > 0)
327  total -= pos.y ();
328  pos += next_step;
329  }
330 
331  return total;
332 }
int16_t y() const
access_function
Definition: points.h:57
const ICOORD & start_pos() const
Definition: coutln.h:148
integer coordinate
Definition: points.h:32
int16_t x() const
access function
Definition: points.h:53
int32_t pathlength() const
Definition: coutln.h:135
int32_t area() const
Definition: rect.h:122
ICOORD step(int index) const
Definition: coutln.h:144

◆ pathlength()

int32_t C_OUTLINE::pathlength ( ) const
inline

Definition at line 135 of file coutln.h.

135  { //get path length
136  return stepcount;
137  }

◆ perimeter()

int32_t C_OUTLINE::perimeter ( ) const

Definition at line 290 of file coutln.cpp.

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

◆ plot()

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

Definition at line 943 of file coutln.cpp.

943  {
944  int16_t stepindex; // index to cstep
945  ICOORD pos; // current position
946  DIR128 stepdir; // direction of step
947 
948  pos = start; // current position
949  window->Pen(colour);
950  if (stepcount == 0) {
951  window->Rectangle(box.left(), box.top(), box.right(), box.bottom());
952  return;
953  }
954  window->SetCursor(pos.x(), pos.y());
955 
956  stepindex = 0;
957  while (stepindex < stepcount) {
958  pos += step(stepindex); // step to next
959  stepdir = step_dir(stepindex);
960  stepindex++; // count steps
961  // merge straight lines
962  while (stepindex < stepcount &&
963  stepdir.get_dir() == step_dir(stepindex).get_dir()) {
964  pos += step(stepindex);
965  stepindex++;
966  }
967  window->DrawTo(pos.x(), pos.y());
968  }
969 }
void DrawTo(int x, int y)
Definition: scrollview.cpp:527
int16_t y() const
access_function
Definition: points.h:57
void SetCursor(int x, int y)
Definition: scrollview.cpp:521
int16_t left() const
Definition: rect.h:72
int16_t top() const
Definition: rect.h:58
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
int16_t right() const
Definition: rect.h:79
DIR128 step_dir(int index) const
Definition: coutln.h:139
void Rectangle(int x1, int y1, int x2, int y2)
Definition: scrollview.cpp:602
void Pen(Color color)
Definition: scrollview.cpp:722
int16_t bottom() const
Definition: rect.h:65
ICOORD step(int index) const
Definition: coutln.h:144

◆ 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 975 of file coutln.cpp.

976  {
977  window->Pen(colour);
978  if (stepcount == 0) {
979  window->Rectangle(box.left(), box.top(), box.right(), box.bottom());
980  return;
981  }
982  const DENORM* root_denorm = denorm.RootDenorm();
983  ICOORD pos = start; // current position
984  FCOORD f_pos = sub_pixel_pos_at_index(pos, 0);
985  FCOORD pos_normed;
986  denorm.NormTransform(root_denorm, f_pos, &pos_normed);
987  window->SetCursor(IntCastRounded(pos_normed.x()),
988  IntCastRounded(pos_normed.y()));
989  for (int s = 0; s < stepcount; pos += step(s++)) {
990  int edge_weight = edge_strength_at_index(s);
991  if (edge_weight == 0) {
992  // This point has conflicting gradient and step direction, so ignore it.
993  continue;
994  }
995  FCOORD f_pos = sub_pixel_pos_at_index(pos, s);
996  FCOORD pos_normed;
997  denorm.NormTransform(root_denorm, f_pos, &pos_normed);
998  window->DrawTo(IntCastRounded(pos_normed.x()),
999  IntCastRounded(pos_normed.y()));
1000  }
1001 }
void NormTransform(const DENORM *first_norm, const TPOINT &pt, TPOINT *transformed) const
Definition: normalis.cpp:335
void DrawTo(int x, int y)
Definition: scrollview.cpp:527
const DENORM * RootDenorm() const
Definition: normalis.h:258
FCOORD sub_pixel_pos_at_index(const ICOORD &pos, int index) const
Definition: coutln.h:163
void SetCursor(int x, int y)
Definition: scrollview.cpp:521
int16_t left() const
Definition: rect.h:72
int16_t top() const
Definition: rect.h:58
integer coordinate
Definition: points.h:32
int edge_strength_at_index(int index) const
Definition: coutln.h:187
int IntCastRounded(double x)
Definition: helpers.h:168
Definition: points.h:189
int16_t right() const
Definition: rect.h:79
float x() const
Definition: points.h:208
void Rectangle(int x1, int y1, int x2, int y2)
Definition: scrollview.cpp:602
void Pen(Color color)
Definition: scrollview.cpp:722
int16_t bottom() const
Definition: rect.h:65
ICOORD step(int index) const
Definition: coutln.h:144
float y() const
Definition: points.h:211

◆ position_at_index()

ICOORD C_OUTLINE::position_at_index ( int  index) const
inline

Definition at line 153 of file coutln.h.

153  {
154  ICOORD pos = start;
155  for (int i = 0; i < index; ++i)
156  pos += step(i);
157  return pos;
158  }
integer coordinate
Definition: points.h:32
ICOORD step(int index) const
Definition: coutln.h:144

◆ 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 628 of file coutln.cpp.

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

◆ 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 895 of file coutln.cpp.

895  {
896  ICOORD pos = start;
897  for (int stepindex = 0; stepindex < stepcount; ++stepindex) {
898  ICOORD next_step = step(stepindex);
899  if (next_step.y() < 0) {
900  pixRasterop(pix, 0, top - pos.y(), pos.x() - left, 1,
901  PIX_NOT(PIX_DST), nullptr, 0, 0);
902  } else if (next_step.y() > 0) {
903  pixRasterop(pix, 0, top - pos.y() - 1, pos.x() - left, 1,
904  PIX_NOT(PIX_DST), nullptr, 0, 0);
905  }
906  pos += next_step;
907  }
908 }
int16_t y() const
access_function
Definition: points.h:57
integer coordinate
Definition: points.h:32
int16_t x() const
access function
Definition: points.h:53
ICOORD step(int index) const
Definition: coutln.h:144

◆ 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 917 of file coutln.cpp.

917  {
918  ICOORD pos = start;
919  for (int stepindex = 0; stepindex < stepcount; ++stepindex) {
920  ICOORD next_step = step(stepindex);
921  if (next_step.y() < 0) {
922  pixSetPixel(pix, pos.x() - left, top - pos.y(), 1);
923  } else if (next_step.y() > 0) {
924  pixSetPixel(pix, pos.x() - left - 1, top - pos.y() - 1, 1);
925  } else if (next_step.x() < 0) {
926  pixSetPixel(pix, pos.x() - left - 1, top - pos.y(), 1);
927  } else if (next_step.x() > 0) {
928  pixSetPixel(pix, pos.x() - left, top - pos.y() - 1, 1);
929  }
930  pos += next_step;
931  }
932 }
int16_t y() const
access_function
Definition: points.h:57
integer coordinate
Definition: points.h:32
int16_t x() const
access function
Definition: points.h:53
ICOORD step(int index) const
Definition: coutln.h:144

◆ reverse()

void C_OUTLINE::reverse ( )

Definition at line 566 of file coutln.cpp.

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

◆ set_flag()

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

Definition at line 102 of file coutln.h.

104  { //value to set
105  flags.set_bit(mask, value);
106  }
void set_bit(uint8_t bit_num, bool value)
Definition: bits16.h:48

◆ set_step() [1/2]

void C_OUTLINE::set_step ( int16_t  stepindex,
int8_t  stepdir 
)
inline

Definition at line 116 of file coutln.h.

118  { //chain code
119  int shift = stepindex%4 * 2;
120  uint8_t mask = 3 << shift;
121  steps[stepindex/4] = ((stepdir << shift) & mask) |
122  (steps[stepindex/4] & ~mask);
123  //squeeze 4 into byte
124  }

◆ set_step() [2/2]

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

Definition at line 125 of file coutln.h.

127  { //direction
128  //clean it
129  int8_t chaindir = stepdir.get_dir() >> (DIRBITS - 2);
130  //difference
131  set_step(stepindex, chaindir);
132  //squeeze 4 into byte
133  }
void set_step(int16_t stepindex, int8_t stepdir)
Definition: coutln.h:116
int8_t get_dir() const
Definition: mod128.h:76
#define DIRBITS
Definition: mod128.h:26

◆ start_pos()

const ICOORD& C_OUTLINE::start_pos ( ) const
inline

Definition at line 148 of file coutln.h.

148  {
149  return start;
150  }

◆ step()

ICOORD C_OUTLINE::step ( int  index) const
inline

Definition at line 144 of file coutln.h.

144  { // index of step
145  return step_coords[chain_code(index)];
146  }
int chain_code(int index) const
Definition: coutln.h:195

◆ step_dir()

DIR128 C_OUTLINE::step_dir ( int  index) const
inline

Definition at line 139 of file coutln.h.

139  {
140  return DIR128((int16_t)(((steps[index/4] >> (index%4 * 2)) & STEP_MASK) <<
141  (DIRBITS - 2)));
142  }
Definition: mod128.h:29
#define DIRBITS
Definition: mod128.h:26
#define STEP_MASK
Definition: coutln.h:38

◆ sub_pixel_pos_at_index()

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

Definition at line 163 of file coutln.h.

163  {
164  const ICOORD& step_to_next(step(index));
165  FCOORD f_pos(pos.x() + step_to_next.x() / 2.0f,
166  pos.y() + step_to_next.y() / 2.0f);
167  if (offsets != nullptr && offsets[index].pixel_diff > 0) {
168  float offset = offsets[index].offset_numerator;
169  offset /= offsets[index].pixel_diff;
170  if (step_to_next.x() != 0)
171  f_pos.set_y(f_pos.y() + offset);
172  else
173  f_pos.set_x(f_pos.x() + offset);
174  }
175  return f_pos;
176  }
int16_t y() const
access_function
Definition: points.h:57
integer coordinate
Definition: points.h:32
int16_t x() const
access function
Definition: points.h:53
uint8_t pixel_diff
Definition: coutln.h:64
Definition: points.h:189
int8_t offset_numerator
Definition: coutln.h:63
ICOORD step(int index) const
Definition: coutln.h:144

◆ turn_direction()

int16_t C_OUTLINE::turn_direction ( ) const

C_OUTLINE::turn_direction

Returns
the sum direction delta of the outline.

Definition at line 538 of file coutln.cpp.

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

◆ winding_number()

int16_t C_OUTLINE::winding_number ( ICOORD  testpt) const

Definition at line 501 of file coutln.cpp.

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

Member Data Documentation

◆ kMaxOutlineLength

const int C_OUTLINE::kMaxOutlineLength = 16000
static

Definition at line 273 of file coutln.h.


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