All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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::C_OUTLINE ( )
inline

Definition at line 71 of file coutln.h.

71  { //empty constructor
72  steps = NULL;
73  offsets = NULL;
74  }
#define NULL
Definition: host.h:144
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
ICOORD pos
Definition: crakedge.h:30
inT8 stepdir
Definition: crakedge.h:33
void * alloc_mem(inT32 count)
Definition: memry.cpp:47
#define NULL
Definition: host.h:144
CRACKEDGE * next
Definition: crakedge.h:35
short inT16
Definition: host.h:100
unsigned char uinT8
Definition: host.h:99
C_OUTLINE::C_OUTLINE ( ICOORD  startpt,
DIR128 new_steps,
inT16  length 
)

Definition at line 80 of file coutln.cpp.

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

Definition at line 142 of file coutln.cpp.

142  : offsets(NULL) {
143  TBOX new_box; //easy bounding
144  inT16 stepindex; //index to step
145  inT16 dirdiff; //direction change
146  ICOORD pos; //current position
147  ICOORD prevpos; //previous dest point
148 
149  ICOORD destpos; //destination point
150  inT16 destindex; //index to step
151  DIR128 dir; //coded direction
152  uinT8 new_step;
153 
154  stepcount = srcline->stepcount * 2;
155  if (stepcount == 0) {
156  steps = NULL;
157  box = srcline->box;
158  box.rotate(rotation);
159  return;
160  }
161  //get memory
162  steps = (uinT8 *) alloc_mem (step_mem());
163  memset(steps, 0, step_mem());
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 set_step(inT16 stepindex, inT8 stepdir)
Definition: coutln.h:114
#define ASSERT_HOST(x)
Definition: errcode.h:84
void rotate(const FCOORD &vec)
Definition: ipoints.h:241
Definition: mod128.h:29
inT16 y() const
access_function
Definition: points.h:56
integer coordinate
Definition: points.h:30
DIR128 step_dir(int index) const
Definition: coutln.h:137
inT16 x() const
access function
Definition: points.h:52
Definition: rect.h:30
ICOORD step(int index) const
Definition: coutln.h:142
void * alloc_mem(inT32 count)
Definition: memry.cpp:47
#define NULL
Definition: host.h:144
inT8 get_dir() const
Definition: mod128.h:77
Definition: points.h:189
short inT16
Definition: host.h:100
void rotate(const FCOORD &vec)
Definition: rect.h:189
unsigned char uinT8
Definition: host.h:99
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:55
#define NULL
Definition: host.h:144

Member Function Documentation

inT32 C_OUTLINE::area ( ) const

Definition at line 256 of file coutln.cpp.

256  {
257  int stepindex; //current step
258  inT32 total_steps; //steps to do
259  inT32 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 }
const ICOORD & start_pos() const
Definition: coutln.h:146
inT32 pathlength() const
Definition: coutln.h:133
inT16 y() const
access_function
Definition: points.h:56
integer coordinate
Definition: points.h:30
inT16 x() const
access function
Definition: points.h:52
ICOORD step(int index) const
Definition: coutln.h:142
int inT32
Definition: host.h:102
const TBOX& C_OUTLINE::bounding_box ( ) const
inline

Definition at line 111 of file coutln.h.

111  {
112  return box;
113  }
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
ICOORD C_OUTLINE::chain_step ( int  chaindir)
static

Definition at line 1067 of file coutln.cpp.

1067  {
1068  return step_coords[chaindir % 4];
1069 }
C_OUTLINE_LIST* C_OUTLINE::child ( )
inline

Definition at line 106 of file coutln.h.

106  { //get child list
107  return &children;
108  }
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 851 of file coutln.cpp.

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

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

Definition at line 343 of file coutln.cpp.

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

613  {
614  if (stepcount == 0) return true;
615  int parent_area = outer_area();
616  // We aren't going to modify the list, or its contents, but there is
617  // no const iterator.
618  C_OUTLINE_IT child_it(const_cast<C_OUTLINE_LIST*>(&children));
619  for (child_it.mark_cycle_pt(); !child_it.cycled_list(); child_it.forward()) {
620  const C_OUTLINE* child = child_it.data();
621  if (child->outer_area() * parent_area > 0 || !child->IsLegallyNested())
622  return false;
623  }
624  return true;
625 }
bool IsLegallyNested() const
Definition: coutln.cpp:613
inT32 outer_area() const
Definition: coutln.cpp:310
C_OUTLINE_LIST * child()
Definition: coutln.h:106
void C_OUTLINE::move ( const ICOORD  vec)

Definition at line 597 of file coutln.cpp.

597  {
598  C_OUTLINE_IT it(&children); // iterator
599 
600  box.move (vec);
601  start += vec;
602 
603  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
604  it.data ()->move (vec); // move child outlines
605 }
void move(const ICOORD vec)
Definition: rect.h:153
BOOL8 C_OUTLINE::operator< ( const C_OUTLINE other) const

Definition at line 471 of file coutln.cpp.

472 {
473  inT16 count = 0; //winding count
474  ICOORD pos; //position of point
475  inT32 stepindex; //index to cstep
476 
477  if (!box.overlap (other.box))
478  return FALSE; //can't be contained
479  if (stepcount == 0)
480  return other.box.contains(this->box);
481 
482  pos = start;
483  for (stepindex = 0; stepindex < stepcount
484  && (count = other.winding_number (pos)) == INTERSECTING; stepindex++)
485  pos += step (stepindex); //try all points
486  if (count == INTERSECTING) {
487  //all intersected
488  pos = other.start;
489  for (stepindex = 0; stepindex < other.stepcount
490  && (count = winding_number (pos)) == INTERSECTING; stepindex++)
491  //try other way round
492  pos += other.step (stepindex);
493  return count == INTERSECTING || count == 0;
494  }
495  return count != 0;
496 }
#define INTERSECTING
Definition: coutln.h:32
inT16 winding_number(ICOORD testpt) const
Definition: coutln.cpp:506
integer coordinate
Definition: points.h:30
#define FALSE
Definition: capi.h:29
int count(LIST var_list)
Definition: oldlist.cpp:108
bool contains(const FCOORD pt) const
Definition: rect.h:323
ICOORD step(int index) const
Definition: coutln.h:142
bool overlap(const TBOX &box) const
Definition: rect.h:345
short inT16
Definition: host.h:100
int inT32
Definition: host.h:102
C_OUTLINE & C_OUTLINE::operator= ( const C_OUTLINE source)

Definition at line 1027 of file coutln.cpp.

1027  {
1028  box = source.box;
1029  start = source.start;
1030  if (steps != NULL)
1031  free_mem(steps);
1032  stepcount = source.stepcount;
1033  steps = (uinT8 *) alloc_mem (step_mem());
1034  memmove (steps, source.steps, step_mem());
1035  if (!children.empty ())
1036  children.clear ();
1037  children.deep_copy(&source.children, &deep_copy);
1038  delete [] offsets;
1039  if (source.offsets != NULL) {
1040  offsets = new EdgeOffset[stepcount];
1041  memcpy(offsets, source.offsets, stepcount * sizeof(*offsets));
1042  } else {
1043  offsets = NULL;
1044  }
1045  return *this;
1046 }
void free_mem(void *oldchunk)
Definition: memry.cpp:55
void * alloc_mem(inT32 count)
Definition: memry.cpp:47
#define NULL
Definition: host.h:144
unsigned char uinT8
Definition: host.h:99
static C_OUTLINE * deep_copy(const C_OUTLINE *src)
Definition: coutln.h:259
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  }
inT32 C_OUTLINE::outer_area ( ) const

Definition at line 310 of file coutln.cpp.

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

Definition at line 133 of file coutln.h.

133  { //get path length
134  return stepcount;
135  }
inT32 C_OUTLINE::perimeter ( ) const

Definition at line 290 of file coutln.cpp.

290  {
291  inT32 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 pathlength() const
Definition: coutln.h:133
int inT32
Definition: host.h:102
void C_OUTLINE::plot ( ScrollView window,
ScrollView::Color  colour 
) const

Definition at line 957 of file coutln.cpp.

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

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

636  {
637  if (box.width() < min_size || box.height() < min_size) {
638  ASSERT_HOST(this == it->data());
639  delete it->extract(); // Too small so get rid of it and any children.
640  } else if (!children.empty()) {
641  // Search the children of this, deleting any that are too small.
642  C_OUTLINE_IT child_it(&children);
643  for (child_it.mark_cycle_pt(); !child_it.cycled_list();
644  child_it.forward()) {
645  C_OUTLINE* child = child_it.data();
646  child->RemoveSmallRecursive(min_size, &child_it);
647  }
648  }
649 }
void RemoveSmallRecursive(int min_size, C_OUTLINE_IT *it)
Definition: coutln.cpp:636
#define ASSERT_HOST(x)
Definition: errcode.h:84
inT16 height() const
Definition: rect.h:104
inT16 width() const
Definition: rect.h:111
C_OUTLINE_LIST * child()
Definition: coutln.h:106
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 909 of file coutln.cpp.

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

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

Definition at line 573 of file coutln.cpp.

573  { //reverse drection
574  DIR128 halfturn = MODULUS / 2; //amount to shift
575  DIR128 stepdir; //direction of step
576  inT16 stepindex; //index to cstep
577  inT16 farindex; //index to other side
578  inT16 halfsteps; //half of stepcount
579 
580  halfsteps = (stepcount + 1) / 2;
581  for (stepindex = 0; stepindex < halfsteps; stepindex++) {
582  farindex = stepcount - stepindex - 1;
583  stepdir = step_dir (stepindex);
584  set_step (stepindex, step_dir (farindex) + halfturn);
585  set_step (farindex, stepdir + halfturn);
586  }
587 }
void set_step(inT16 stepindex, inT8 stepdir)
Definition: coutln.h:114
#define MODULUS
Definition: mod128.h:25
Definition: mod128.h:29
DIR128 step_dir(int index) const
Definition: coutln.h:137
short inT16
Definition: host.h:100
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
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  }
unsigned char uinT8
Definition: host.h:99
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
SIGNED char inT8
Definition: host.h:98
inT8 get_dir() const
Definition: mod128.h:77
const ICOORD& C_OUTLINE::start_pos ( ) const
inline

Definition at line 146 of file coutln.h.

146  {
147  return start;
148  }
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
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
#define DIRBITS
Definition: mod128.h:26
Definition: mod128.h:29
short inT16
Definition: host.h:100
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  }
inT8 offset_numerator
Definition: coutln.h:60
inT16 y() const
access_function
Definition: points.h:56
uinT8 pixel_diff
Definition: coutln.h:61
integer coordinate
Definition: points.h:30
inT16 x() const
access function
Definition: points.h:52
ICOORD step(int index) const
Definition: coutln.h:142
#define NULL
Definition: host.h:144
Definition: points.h:189
inT16 C_OUTLINE::turn_direction ( ) const

C_OUTLINE::turn_direction

Returns
the sum direction delta of the outline.

Definition at line 544 of file coutln.cpp.

544  { //winding number
545  DIR128 prevdir; //previous direction
546  DIR128 dir; //current direction
547  inT16 stepindex; //index to cstep
548  inT8 dirdiff; //direction difference
549  inT16 count; //winding count
550 
551  if (stepcount == 0)
552  return 128;
553  count = 0;
554  prevdir = step_dir (stepcount - 1);
555  for (stepindex = 0; stepindex < stepcount; stepindex++) {
556  dir = step_dir (stepindex);
557  dirdiff = dir - prevdir;
558  ASSERT_HOST (dirdiff == 0 || dirdiff == 32 || dirdiff == -32);
559  count += dirdiff;
560  prevdir = dir;
561  }
562  ASSERT_HOST (count == 128 || count == -128);
563  return count; //winding number
564 }
#define ASSERT_HOST(x)
Definition: errcode.h:84
Definition: mod128.h:29
int count(LIST var_list)
Definition: oldlist.cpp:108
DIR128 step_dir(int index) const
Definition: coutln.h:137
SIGNED char inT8
Definition: host.h:98
short inT16
Definition: host.h:100
inT16 C_OUTLINE::winding_number ( ICOORD  testpt) const

Definition at line 506 of file coutln.cpp.

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

Member Data Documentation

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: