|
tesseract 3.04.01
|
#include <coutln.h>
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 TBOX & | bounding_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 ICOORD & | start_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.
| |||||
| inT32 | count_transitions (inT32 threshold) | ||||
C_OUTLINE::operator< | |||||
| |||||
| BOOL8 | operator< (const C_OUTLINE &other) const | ||||
C_OUTLINE::winding_number | |||||
| |||||
| 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
| |||||
| 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.
| |||||
| void | plot (ScrollView *window, ScrollView::Color colour) const | ||||
| void | plot_normed (const DENORM &denorm, ScrollView::Color colour, ScrollView *window) const | ||||
Static Public Member Functions | |||||
| static C_OUTLINE * | deep_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.
| |||||
| 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
| |||||
| C_OUTLINE & | operator= (const C_OUTLINE &source) | ||||
| static ICOORD | chain_step (int chaindir) | ||||
| C_OUTLINE::C_OUTLINE | ( | ) | [inline] |
Definition at line 51 of file coutln.cpp.
: box (bot_left, top_right), start (startpt->pos), offsets(NULL) { inT16 stepindex; //index to step CRACKEDGE *edgept; //current point stepcount = length; //no of steps if (length == 0) { steps = NULL; return; } //get memory steps = (uinT8 *) alloc_mem (step_mem()); memset(steps, 0, step_mem()); edgept = startpt; for (stepindex = 0; stepindex < length; stepindex++) { //set compact step set_step (stepindex, edgept->stepdir); edgept = edgept->next; } }
Definition at line 80 of file coutln.cpp.
:start (startpt), offsets(NULL) {
inT8 dirdiff; //direction difference
DIR128 prevdir; //previous direction
DIR128 dir; //current direction
DIR128 lastdir; //dir of last step
TBOX new_box; //easy bounding
inT16 stepindex; //index to step
inT16 srcindex; //source steps
ICOORD pos; //current position
pos = startpt;
stepcount = length; // No. of steps.
ASSERT_HOST(length >= 0);
steps = reinterpret_cast<uinT8*>(alloc_mem(step_mem())); // Get memory.
memset(steps, 0, step_mem());
lastdir = new_steps[length - 1];
prevdir = lastdir;
for (stepindex = 0, srcindex = 0; srcindex < length;
stepindex++, srcindex++) {
new_box = TBOX (pos, pos);
box += new_box;
//copy steps
dir = new_steps[srcindex];
set_step(stepindex, dir);
dirdiff = dir - prevdir;
pos += step (stepindex);
if ((dirdiff == 64 || dirdiff == -64) && stepindex > 0) {
stepindex -= 2; //cancel there-and-back
prevdir = stepindex >= 0 ? step_dir (stepindex) : lastdir;
}
else
prevdir = dir;
}
ASSERT_HOST (pos.x () == startpt.x () && pos.y () == startpt.y ());
do {
dirdiff = step_dir (stepindex - 1) - step_dir (0);
if (dirdiff == 64 || dirdiff == -64) {
start += step (0);
stepindex -= 2; //cancel there-and-back
for (int i = 0; i < stepindex; ++i)
set_step(i, step_dir(i + 1));
}
}
while (stepindex > 1 && (dirdiff == 64 || dirdiff == -64));
stepcount = stepindex;
ASSERT_HOST (stepcount >= 4);
}
Definition at line 142 of file coutln.cpp.
: offsets(NULL) {
TBOX new_box; //easy bounding
inT16 stepindex; //index to step
inT16 dirdiff; //direction change
ICOORD pos; //current position
ICOORD prevpos; //previous dest point
ICOORD destpos; //destination point
inT16 destindex; //index to step
DIR128 dir; //coded direction
uinT8 new_step;
stepcount = srcline->stepcount * 2;
if (stepcount == 0) {
steps = NULL;
box = srcline->box;
box.rotate(rotation);
return;
}
//get memory
steps = (uinT8 *) alloc_mem (step_mem());
memset(steps, 0, step_mem());
for (int iteration = 0; iteration < 2; ++iteration) {
DIR128 round1 = iteration == 0 ? 32 : 0;
DIR128 round2 = iteration != 0 ? 32 : 0;
pos = srcline->start;
prevpos = pos;
prevpos.rotate (rotation);
start = prevpos;
box = TBOX (start, start);
destindex = 0;
for (stepindex = 0; stepindex < srcline->stepcount; stepindex++) {
pos += srcline->step (stepindex);
destpos = pos;
destpos.rotate (rotation);
// tprintf("%i %i %i %i ", destpos.x(), destpos.y(), pos.x(), pos.y());
while (destpos.x () != prevpos.x () || destpos.y () != prevpos.y ()) {
dir = DIR128 (FCOORD (destpos - prevpos));
dir += 64; //turn to step style
new_step = dir.get_dir ();
// tprintf(" %i\n", new_step);
if (new_step & 31) {
set_step(destindex++, dir + round1);
prevpos += step(destindex - 1);
if (destindex < 2
|| ((dirdiff =
step_dir (destindex - 1) - step_dir (destindex - 2)) !=
-64 && dirdiff != 64)) {
set_step(destindex++, dir + round2);
prevpos += step(destindex - 1);
} else {
prevpos -= step(destindex - 1);
destindex--;
prevpos -= step(destindex - 1);
set_step(destindex - 1, dir + round2);
prevpos += step(destindex - 1);
}
}
else {
set_step(destindex++, dir);
prevpos += step(destindex - 1);
}
while (destindex >= 2 &&
((dirdiff =
step_dir (destindex - 1) - step_dir (destindex - 2)) == -64 ||
dirdiff == 64)) {
prevpos -= step(destindex - 1);
prevpos -= step(destindex - 2);
destindex -= 2; // Forget u turn
}
//ASSERT_HOST(prevpos.x() == destpos.x() && prevpos.y() == destpos.y());
new_box = TBOX (destpos, destpos);
box += new_box;
}
}
ASSERT_HOST (destpos.x () == start.x () && destpos.y () == start.y ());
dirdiff = step_dir (destindex - 1) - step_dir (0);
while ((dirdiff == 64 || dirdiff == -64) && destindex > 1) {
start += step (0);
destindex -= 2;
for (int i = 0; i < destindex; ++i)
set_step(i, step_dir(i + 1));
dirdiff = step_dir (destindex - 1) - step_dir (0);
}
if (destindex >= 4)
break;
}
ASSERT_HOST(destindex <= stepcount);
stepcount = destindex;
destpos = start;
for (stepindex = 0; stepindex < stepcount; stepindex++) {
destpos += step (stepindex);
}
ASSERT_HOST (destpos.x () == start.x () && destpos.y () == start.y ());
}
| C_OUTLINE::~C_OUTLINE | ( | ) | [inline] |
| inT32 C_OUTLINE::area | ( | ) | const |
Definition at line 256 of file coutln.cpp.
{
int stepindex; //current step
inT32 total_steps; //steps to do
inT32 total; //total area
ICOORD pos; //position of point
ICOORD next_step; //step to next pix
// We aren't going to modify the list, or its contents, but there is
// no const iterator.
C_OUTLINE_IT it(const_cast<C_OUTLINE_LIST*>(&children));
pos = start_pos ();
total_steps = pathlength ();
total = 0;
for (stepindex = 0; stepindex < total_steps; stepindex++) {
//all intersected
next_step = step (stepindex);
if (next_step.x () < 0)
total += pos.y ();
else if (next_step.x () > 0)
total -= pos.y ();
pos += next_step;
}
for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
total += it.data ()->area ();//add areas of children
return total;
}
| const TBOX& C_OUTLINE::bounding_box | ( | ) | const [inline] |
| int C_OUTLINE::chain_code | ( | int | index | ) | const [inline] |
| ICOORD C_OUTLINE::chain_step | ( | int | chaindir | ) | [static] |
Definition at line 1067 of file coutln.cpp.
{
return step_coords[chaindir % 4];
}
| C_OUTLINE_LIST* C_OUTLINE::child | ( | ) | [inline] |
| 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.
{
delete [] offsets;
offsets = new EdgeOffset[stepcount];
// Count of the number of steps in each direction in the sliding window.
int dir_counts[4];
// Sum of the positions (y for a horizontal step, x for vertical) in each
// direction in the sliding window.
int pos_totals[4];
memset(dir_counts, 0, sizeof(dir_counts));
memset(pos_totals, 0, sizeof(pos_totals));
ICOORD pos = start;
ICOORD tail_pos = pos;
// tail_pos is the trailing position, with the next point to be lost from
// the window.
tail_pos -= step(stepcount - 1);
tail_pos -= step(stepcount - 2);
// head_pos is the leading position, with the next point to be added to the
// window.
ICOORD head_pos = tail_pos;
// Set up the initial window with 4 points in [-2, 2)
for (int s = -2; s < 2; ++s) {
increment_step(s, 1, &head_pos, dir_counts, pos_totals);
}
for (int s = 0; s < stepcount; pos += step(s++)) {
// At step s, s in in the middle of [s-2, s+2].
increment_step(s + 2, 1, &head_pos, dir_counts, pos_totals);
int dir_index = chain_code(s);
ICOORD step_vec = step(s);
int best_diff = 0;
int offset = 0;
// Use only steps that have a count of >=2 OR the strong U-turn with a
// single d and 2 at d-1 and 2 at d+1 (mod 4).
if (dir_counts[dir_index] >= 2 || (dir_counts[dir_index] == 1 &&
dir_counts[Modulo(dir_index - 1, 4)] == 2 &&
dir_counts[Modulo(dir_index + 1, 4)] == 2)) {
// Valid step direction.
best_diff = dir_counts[dir_index];
int edge_pos = step_vec.x() == 0 ? pos.x() : pos.y();
// The offset proposes that the actual step should be positioned at
// the mean position of the steps in the window of the same direction.
// See ASCII art above.
offset = pos_totals[dir_index] - best_diff * edge_pos;
}
offsets[s].offset_numerator =
static_cast<inT8>(ClipToRange(offset, -MAX_INT8, MAX_INT8));
offsets[s].pixel_diff = static_cast<uinT8>(ClipToRange(best_diff, 0 ,
MAX_UINT8));
// The direction is just the vector from start to end of the window.
FCOORD direction(head_pos.x() - tail_pos.x(), head_pos.y() - tail_pos.y());
offsets[s].direction = direction.to_direction();
increment_step(s - 2, -1, &tail_pos, dir_counts, pos_totals);
}
}
| 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.
{
if (pixGetDepth(pix) != 8) return;
const l_uint32* data = pixGetData(pix);
int wpl = pixGetWpl(pix);
int width = pixGetWidth(pix);
int height = pixGetHeight(pix);
bool negative = flag(COUT_INVERSE);
delete [] offsets;
offsets = new EdgeOffset[stepcount];
ICOORD pos = start;
ICOORD prev_gradient;
ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
&prev_gradient);
for (int s = 0; s < stepcount; ++s) {
ICOORD step_vec = step(s);
TPOINT pt1(pos);
pos += step_vec;
TPOINT pt2(pos);
ICOORD next_gradient;
ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
&next_gradient);
// Use the sum of the prev and next as the working gradient.
ICOORD gradient = prev_gradient + next_gradient;
// best_diff will be manipulated to be always positive.
int best_diff = 0;
// offset will be the extrapolation of the location of the greyscale
// threshold from the edge with the largest difference, relative to the
// location of the binary edge.
int offset = 0;
if (pt1.y == pt2.y && abs(gradient.y()) * 2 >= abs(gradient.x())) {
// Horizontal step. diff_sign == 1 indicates black above.
int diff_sign = (pt1.x > pt2.x) == negative ? 1 : -1;
int x = MIN(pt1.x, pt2.x);
int y = height - pt1.y;
int best_sum = 0;
int best_y = y;
EvaluateVerticalDiff(data, wpl, diff_sign, x, y, height,
&best_diff, &best_sum, &best_y);
// Find the strongest edge.
int test_y = y;
do {
++test_y;
} while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
&best_diff, &best_sum, &best_y));
test_y = y;
do {
--test_y;
} while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
&best_diff, &best_sum, &best_y));
offset = diff_sign * (best_sum / 2 - threshold) +
(y - best_y) * best_diff;
} else if (pt1.x == pt2.x && abs(gradient.x()) * 2 >= abs(gradient.y())) {
// Vertical step. diff_sign == 1 indicates black on the left.
int diff_sign = (pt1.y > pt2.y) == negative ? 1 : -1;
int x = pt1.x;
int y = height - MAX(pt1.y, pt2.y);
const l_uint32* line = pixGetData(pix) + y * wpl;
int best_sum = 0;
int best_x = x;
EvaluateHorizontalDiff(line, diff_sign, x, width,
&best_diff, &best_sum, &best_x);
// Find the strongest edge.
int test_x = x;
do {
++test_x;
} while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
&best_diff, &best_sum, &best_x));
test_x = x;
do {
--test_x;
} while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
&best_diff, &best_sum, &best_x));
offset = diff_sign * (threshold - best_sum / 2) +
(best_x - x) * best_diff;
}
offsets[s].offset_numerator =
static_cast<inT8>(ClipToRange(offset, -MAX_INT8, MAX_INT8));
offsets[s].pixel_diff = static_cast<uinT8>(ClipToRange(best_diff, 0 ,
MAX_UINT8));
if (negative) gradient = -gradient;
// Compute gradient angle quantized to 256 directions, rotated by 64 (pi/2)
// to convert from gradient direction to edge direction.
offsets[s].direction =
Modulo(FCOORD::binary_angle_plus_pi(gradient.angle()) + 64, 256);
prev_gradient = next_gradient;
}
}
Definition at line 343 of file coutln.cpp.
{
BOOL8 first_was_max_x; //what was first
BOOL8 first_was_max_y;
BOOL8 looking_for_max_x; //what is next
BOOL8 looking_for_min_x;
BOOL8 looking_for_max_y; //what is next
BOOL8 looking_for_min_y;
int stepindex; //current step
inT32 total_steps; //steps to do
//current limits
inT32 max_x, min_x, max_y, min_y;
inT32 initial_x, initial_y; //initial limits
inT32 total; //total changes
ICOORD pos; //position of point
ICOORD next_step; //step to next pix
pos = start_pos ();
total_steps = pathlength ();
total = 0;
max_x = min_x = pos.x ();
max_y = min_y = pos.y ();
looking_for_max_x = TRUE;
looking_for_min_x = TRUE;
looking_for_max_y = TRUE;
looking_for_min_y = TRUE;
first_was_max_x = FALSE;
first_was_max_y = FALSE;
initial_x = pos.x ();
initial_y = pos.y (); //stop uninit warning
for (stepindex = 0; stepindex < total_steps; stepindex++) {
//all intersected
next_step = step (stepindex);
pos += next_step;
if (next_step.x () < 0) {
if (looking_for_max_x && pos.x () < min_x)
min_x = pos.x ();
if (looking_for_min_x && max_x - pos.x () > threshold) {
if (looking_for_max_x) {
initial_x = max_x;
first_was_max_x = FALSE;
}
total++;
looking_for_max_x = TRUE;
looking_for_min_x = FALSE;
min_x = pos.x (); //reset min
}
}
else if (next_step.x () > 0) {
if (looking_for_min_x && pos.x () > max_x)
max_x = pos.x ();
if (looking_for_max_x && pos.x () - min_x > threshold) {
if (looking_for_min_x) {
initial_x = min_x; //remember first min
first_was_max_x = TRUE;
}
total++;
looking_for_max_x = FALSE;
looking_for_min_x = TRUE;
max_x = pos.x ();
}
}
else if (next_step.y () < 0) {
if (looking_for_max_y && pos.y () < min_y)
min_y = pos.y ();
if (looking_for_min_y && max_y - pos.y () > threshold) {
if (looking_for_max_y) {
initial_y = max_y; //remember first max
first_was_max_y = FALSE;
}
total++;
looking_for_max_y = TRUE;
looking_for_min_y = FALSE;
min_y = pos.y (); //reset min
}
}
else {
if (looking_for_min_y && pos.y () > max_y)
max_y = pos.y ();
if (looking_for_max_y && pos.y () - min_y > threshold) {
if (looking_for_min_y) {
initial_y = min_y; //remember first min
first_was_max_y = TRUE;
}
total++;
looking_for_max_y = FALSE;
looking_for_min_y = TRUE;
max_y = pos.y ();
}
}
}
if (first_was_max_x && looking_for_min_x) {
if (max_x - initial_x > threshold)
total++;
else
total--;
}
else if (!first_was_max_x && looking_for_max_x) {
if (initial_x - min_x > threshold)
total++;
else
total--;
}
if (first_was_max_y && looking_for_min_y) {
if (max_y - initial_y > threshold)
total++;
else
total--;
}
else if (!first_was_max_y && looking_for_max_y) {
if (initial_y - min_y > threshold)
total++;
else
total--;
}
return total;
}
| int C_OUTLINE::direction_at_index | ( | int | index | ) | const [inline] |
| int C_OUTLINE::edge_strength_at_index | ( | int | index | ) | const [inline] |
Definition at line 185 of file coutln.h.
{
if (offsets != NULL)
return offsets[index].pixel_diff;
return 1;
}
| void C_OUTLINE::FakeOutline | ( | const TBOX & | box, |
| C_OUTLINE_LIST * | outlines | ||
| ) | [static] |
Definition at line 240 of file coutln.cpp.
{
C_OUTLINE_IT ol_it(outlines);
// Make a C_OUTLINE from the bounds. This is a bit of a hack,
// as there is no outline, just a bounding box, but it works nicely.
CRACKEDGE start;
start.pos = box.topleft();
C_OUTLINE* outline = new C_OUTLINE(&start, box.topleft(), box.botright(), 0);
ol_it.add_to_end(outline);
}
| BOOL8 C_OUTLINE::flag | ( | C_OUTLINE_FLAGS | mask | ) | const [inline] |
| 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.
{
if (stepcount == 0) return true;
int parent_area = outer_area();
// We aren't going to modify the list, or its contents, but there is
// no const iterator.
C_OUTLINE_IT child_it(const_cast<C_OUTLINE_LIST*>(&children));
for (child_it.mark_cycle_pt(); !child_it.cycled_list(); child_it.forward()) {
const C_OUTLINE* child = child_it.data();
if (child->outer_area() * parent_area > 0 || !child->IsLegallyNested())
return false;
}
return true;
}
| void C_OUTLINE::move | ( | const ICOORD | vec | ) |
Definition at line 597 of file coutln.cpp.
{
C_OUTLINE_IT it(&children); // iterator
box.move (vec);
start += vec;
for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
it.data ()->move (vec); // move child outlines
}
Definition at line 471 of file coutln.cpp.
{
inT16 count = 0; //winding count
ICOORD pos; //position of point
inT32 stepindex; //index to cstep
if (!box.overlap (other.box))
return FALSE; //can't be contained
if (stepcount == 0)
return other.box.contains(this->box);
pos = start;
for (stepindex = 0; stepindex < stepcount
&& (count = other.winding_number (pos)) == INTERSECTING; stepindex++)
pos += step (stepindex); //try all points
if (count == INTERSECTING) {
//all intersected
pos = other.start;
for (stepindex = 0; stepindex < other.stepcount
&& (count = winding_number (pos)) == INTERSECTING; stepindex++)
//try other way round
pos += other.step (stepindex);
return count == INTERSECTING || count == 0;
}
return count != 0;
}
Definition at line 1027 of file coutln.cpp.
{
box = source.box;
start = source.start;
if (steps != NULL)
free_mem(steps);
stepcount = source.stepcount;
steps = (uinT8 *) alloc_mem (step_mem());
memmove (steps, source.steps, step_mem());
if (!children.empty ())
children.clear ();
children.deep_copy(&source.children, &deep_copy);
delete [] offsets;
if (source.offsets != NULL) {
offsets = new EdgeOffset[stepcount];
memcpy(offsets, source.offsets, stepcount * sizeof(*offsets));
} else {
offsets = NULL;
}
return *this;
}
| inT32 C_OUTLINE::outer_area | ( | ) | const |
Definition at line 310 of file coutln.cpp.
{
int stepindex; //current step
inT32 total_steps; //steps to do
inT32 total; //total area
ICOORD pos; //position of point
ICOORD next_step; //step to next pix
pos = start_pos ();
total_steps = pathlength ();
if (total_steps == 0)
return box.area();
total = 0;
for (stepindex = 0; stepindex < total_steps; stepindex++) {
//all intersected
next_step = step (stepindex);
if (next_step.x () < 0)
total += pos.y ();
else if (next_step.x () > 0)
total -= pos.y ();
pos += next_step;
}
return total;
}
| inT32 C_OUTLINE::pathlength | ( | ) | const [inline] |
| inT32 C_OUTLINE::perimeter | ( | ) | const |
Definition at line 290 of file coutln.cpp.
{
inT32 total_steps; // Return value.
// We aren't going to modify the list, or its contents, but there is
// no const iterator.
C_OUTLINE_IT it(const_cast<C_OUTLINE_LIST*>(&children));
total_steps = pathlength();
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward())
total_steps += it.data()->pathlength(); // Add perimeters of children.
return total_steps;
}
| void C_OUTLINE::plot | ( | ScrollView * | window, |
| ScrollView::Color | colour | ||
| ) | const |
Definition at line 957 of file coutln.cpp.
{
inT16 stepindex; // index to cstep
ICOORD pos; // current position
DIR128 stepdir; // direction of step
pos = start; // current position
window->Pen(colour);
if (stepcount == 0) {
window->Rectangle(box.left(), box.top(), box.right(), box.bottom());
return;
}
window->SetCursor(pos.x(), pos.y());
stepindex = 0;
while (stepindex < stepcount) {
pos += step(stepindex); // step to next
stepdir = step_dir(stepindex);
stepindex++; // count steps
// merge straight lines
while (stepindex < stepcount &&
stepdir.get_dir() == step_dir(stepindex).get_dir()) {
pos += step(stepindex);
stepindex++;
}
window->DrawTo(pos.x(), pos.y());
}
}
| 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.
{
window->Pen(colour);
if (stepcount == 0) {
window->Rectangle(box.left(), box.top(), box.right(), box.bottom());
return;
}
const DENORM* root_denorm = denorm.RootDenorm();
ICOORD pos = start; // current position
FCOORD f_pos = sub_pixel_pos_at_index(pos, 0);
FCOORD pos_normed;
denorm.NormTransform(root_denorm, f_pos, &pos_normed);
window->SetCursor(IntCastRounded(pos_normed.x()),
IntCastRounded(pos_normed.y()));
for (int s = 0; s < stepcount; pos += step(s++)) {
int edge_weight = edge_strength_at_index(s);
if (edge_weight == 0) {
// This point has conflicting gradient and step direction, so ignore it.
continue;
}
FCOORD f_pos = sub_pixel_pos_at_index(pos, s);
FCOORD pos_normed;
denorm.NormTransform(root_denorm, f_pos, &pos_normed);
window->DrawTo(IntCastRounded(pos_normed.x()),
IntCastRounded(pos_normed.y()));
}
}
| ICOORD C_OUTLINE::position_at_index | ( | int | index | ) | const [inline] |
| 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.
| min_size | minimum size for outline |
| it | outline iterator |
Definition at line 636 of file coutln.cpp.
{
if (box.width() < min_size || box.height() < min_size) {
ASSERT_HOST(this == it->data());
delete it->extract(); // Too small so get rid of it and any children.
} else if (!children.empty()) {
// Search the children of this, deleting any that are too small.
C_OUTLINE_IT child_it(&children);
for (child_it.mark_cycle_pt(); !child_it.cycled_list();
child_it.forward()) {
C_OUTLINE* child = child_it.data();
child->RemoveSmallRecursive(min_size, &child_it);
}
}
}
| 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.
{
ICOORD pos = start;
for (int stepindex = 0; stepindex < stepcount; ++stepindex) {
ICOORD next_step = step(stepindex);
if (next_step.y() < 0) {
pixRasterop(pix, 0, top - pos.y(), pos.x() - left, 1,
PIX_NOT(PIX_DST), NULL, 0, 0);
} else if (next_step.y() > 0) {
pixRasterop(pix, 0, top - pos.y() - 1, pos.x() - left, 1,
PIX_NOT(PIX_DST), NULL, 0, 0);
}
pos += next_step;
}
}
| 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.
| left | coord |
| top | coord |
| pix | the pix to outline |
Definition at line 931 of file coutln.cpp.
{
ICOORD pos = start;
for (int stepindex = 0; stepindex < stepcount; ++stepindex) {
ICOORD next_step = step(stepindex);
if (next_step.y() < 0) {
pixSetPixel(pix, pos.x() - left, top - pos.y(), 1);
} else if (next_step.y() > 0) {
pixSetPixel(pix, pos.x() - left - 1, top - pos.y() - 1, 1);
} else if (next_step.x() < 0) {
pixSetPixel(pix, pos.x() - left - 1, top - pos.y(), 1);
} else if (next_step.x() > 0) {
pixSetPixel(pix, pos.x() - left, top - pos.y() - 1, 1);
}
pos += next_step;
}
}
| void C_OUTLINE::reverse | ( | ) |
Definition at line 573 of file coutln.cpp.
{ //reverse drection
DIR128 halfturn = MODULUS / 2; //amount to shift
DIR128 stepdir; //direction of step
inT16 stepindex; //index to cstep
inT16 farindex; //index to other side
inT16 halfsteps; //half of stepcount
halfsteps = (stepcount + 1) / 2;
for (stepindex = 0; stepindex < halfsteps; stepindex++) {
farindex = stepcount - stepindex - 1;
stepdir = step_dir (stepindex);
set_step (stepindex, step_dir (farindex) + halfturn);
set_step (farindex, stepdir + halfturn);
}
}
| void C_OUTLINE::set_flag | ( | C_OUTLINE_FLAGS | mask, |
| BOOL8 | value | ||
| ) | [inline] |
| const ICOORD& C_OUTLINE::start_pos | ( | ) | const [inline] |
| ICOORD C_OUTLINE::step | ( | int | index | ) | const [inline] |
Definition at line 142 of file coutln.h.
{ // index of step
return step_coords[chain_code(index)];
}
| DIR128 C_OUTLINE::step_dir | ( | int | index | ) | const [inline] |
Definition at line 161 of file coutln.h.
{
const ICOORD& step_to_next(step(index));
FCOORD f_pos(pos.x() + step_to_next.x() / 2.0f,
pos.y() + step_to_next.y() / 2.0f);
if (offsets != NULL && offsets[index].pixel_diff > 0) {
float offset = offsets[index].offset_numerator;
offset /= offsets[index].pixel_diff;
if (step_to_next.x() != 0)
f_pos.set_y(f_pos.y() + offset);
else
f_pos.set_x(f_pos.x() + offset);
}
return f_pos;
}
| inT16 C_OUTLINE::turn_direction | ( | ) | const |
Definition at line 544 of file coutln.cpp.
{ //winding number
DIR128 prevdir; //previous direction
DIR128 dir; //current direction
inT16 stepindex; //index to cstep
inT8 dirdiff; //direction difference
inT16 count; //winding count
if (stepcount == 0)
return 128;
count = 0;
prevdir = step_dir (stepcount - 1);
for (stepindex = 0; stepindex < stepcount; stepindex++) {
dir = step_dir (stepindex);
dirdiff = dir - prevdir;
ASSERT_HOST (dirdiff == 0 || dirdiff == 32 || dirdiff == -32);
count += dirdiff;
prevdir = dir;
}
ASSERT_HOST (count == 128 || count == -128);
return count; //winding number
}
Definition at line 506 of file coutln.cpp.
{
inT16 stepindex; //index to cstep
inT16 count; //winding count
ICOORD vec; //to current point
ICOORD stepvec; //step vector
inT32 cross; //cross product
vec = start - point; //vector to it
count = 0;
for (stepindex = 0; stepindex < stepcount; stepindex++) {
stepvec = step (stepindex); //get the step
//crossing the line
if (vec.y () <= 0 && vec.y () + stepvec.y () > 0) {
cross = vec * stepvec; //cross product
if (cross > 0)
count++; //crossing right half
else if (cross == 0)
return INTERSECTING; //going through point
}
else if (vec.y () > 0 && vec.y () + stepvec.y () <= 0) {
cross = vec * stepvec;
if (cross < 0)
count--; //crossing back
else if (cross == 0)
return INTERSECTING; //illegal
}
vec += stepvec; //sum vectors
}
return count; //winding number
}
const int C_OUTLINE::kMaxOutlineLength = 16000 [static] |