31 #define PROJECTION_MARGIN 10 //arbitrary 51 inT16 half_pitch = pitch / 2 - 1;
57 else if (half_pitch < 0)
59 lead_flag = 1 << half_pitch;
63 sq_sum = offset * offset;
71 if (x == array_origin) {
74 for (ind = 0; ind <= half_pitch; ind++) {
77 fwd_balance |= lead_flag;
81 back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
82 back_balance &= lead_flag + lead_flag - 1;
85 fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
86 if (projection->
pile_count (x + half_pitch) > zero_count)
87 fwd_balance |= lead_flag;
106 float projection_scale,
122 inT16 half_pitch = pitch / 2 - 1;
127 else if (half_pitch < 0)
129 lead_flag = 1 << half_pitch;
131 back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
132 back_balance &= lead_flag + lead_flag - 1;
135 fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
136 if (projection->
pile_count (x + half_pitch) > zero_count)
137 fwd_balance |= lead_flag;
146 for (
index = x - pitch - pitch_error;
index <= x - pitch + pitch_error;
148 if (
index >= array_origin) {
149 segpt = &cutpts[
index - array_origin];
150 dist = x - segpt->xpos;
155 lead_flag = back_balance ^ segpt->fwd_balance;
157 while (lead_flag != 0) {
159 lead_flag &= lead_flag - 1;
163 for (balance_index = 0;
164 index + balance_index < x - balance_index;
176 r_index = segpt->region_index + 1;
177 total = segpt->mean_sum + dist;
178 balance_count += offset;
180 dist * dist + segpt->sq_sum + balance_count * balance_count;
181 mean = total / r_index;
182 factor = mean - pitch;
184 factor += sq_dist / (r_index) - mean * mean;
191 mid_cuts = segpt->mid_cuts + mid_cut;
192 region_index = r_index;
214 float projection_scale,
229 inT16 half_pitch = pitch / 2 - 1;
234 else if (half_pitch < 0)
236 lead_flag = 1 << half_pitch;
238 back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
239 back_balance &= lead_flag + lead_flag - 1;
242 fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
243 if (projection->
pile_count (x + half_pitch) > zero_count)
244 fwd_balance |= lead_flag;
254 if (
index >= array_origin) {
255 segpt = &cutpts[
index - array_origin];
256 dist = x - segpt->xpos;
260 lead_flag = back_balance ^ segpt->fwd_balance;
262 while (lead_flag != 0) {
264 lead_flag &= lead_flag - 1;
269 r_index = segpt->region_index + 1;
270 total = segpt->mean_sum + dist;
271 balance_count += offset;
273 dist * dist + segpt->sq_sum + balance_count * balance_count;
274 mean = total / r_index;
275 factor = mean - pitch;
277 factor += sq_dist / (r_index) - mean * mean;
283 mid_cuts = segpt->mid_cuts + mid_cut;
284 region_index = r_index;
299 BLOBNBOX_IT *blob_it,
304 inT16 projection_left,
305 inT16 projection_right,
306 float projection_scale,
307 inT16 &occupation_count,
308 FPSEGPT_LIST *seg_list,
321 inT16 best_left_x = 0;
322 inT16 best_right_x = 0;
333 FPSEGPT_IT seg_it = seg_list;
342 if ((pitch - 3) / 2 < pitch_error)
343 pitch_error = (pitch - 3) / 2;
354 for (left_edge = projection_left; projection->
pile_count (left_edge) == 0
355 && left_edge < projection_right; left_edge++);
356 for (right_edge = projection_right; projection->
pile_count (right_edge) == 0
357 && right_edge > left_edge; right_edge--);
359 if (pitsync_linear_version >= 4)
361 pitch, pitch_error, projection,
362 projection_scale, occupation_count, seg_list,
364 array_origin = left_edge - pitch;
367 for (x = array_origin; x < left_edge; x++)
369 cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, 0);
370 for (offset = 0; offset <= pitch_error; offset++, x++)
372 cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, offset);
380 while (x < right_edge - pitch_error) {
381 if (x > this_box.
right () + pitch_error && blob_index < blob_count) {
388 if (x <= this_box.
left ())
390 else if (x <= this_box.
left () + pitch_error)
391 offset = x - this_box.
left ();
392 else if (x >= this_box.
right ())
394 else if (x >= next_box.
left () && blob_index < blob_count) {
395 offset = x - next_box.
left ();
396 if (this_box.
right () - x < offset)
397 offset = this_box.
right () - x;
399 else if (x >= this_box.
right () - pitch_error)
400 offset = this_box.
right () - x;
410 cutpts[x - array_origin].
assign (cutpts, array_origin, x,
411 faking, mid_cut, offset, projection,
412 projection_scale, zero_count, pitch,
420 while (x < right_edge + pitch) {
421 offset = x < right_edge ? right_edge - x : 0;
422 cutpts[x - array_origin].
assign (cutpts, array_origin, x,
424 projection_scale, zero_count, pitch,
427 if (cutpts[x - array_origin].index () +
428 cutpts[x - array_origin].fake_count <= best_count + best_fake) {
429 if (cutpts[x - array_origin].fake_count < best_fake
430 || (cutpts[x - array_origin].fake_count == best_fake
431 && cutpts[x - array_origin].cost_function () < best_cost)) {
432 best_fake = cutpts[x - array_origin].
fake_count;
436 best_count = cutpts[x - array_origin].
index ();
438 else if (cutpts[x - array_origin].fake_count == best_fake
439 && x == best_right_x + 1
440 && cutpts[x - array_origin].cost_function () == best_cost) {
449 best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
452 for (x = left_edge - pitch; x < right_edge + pitch; x++) {
453 tprintf (
"x=%d, C=%g, s=%g, sq=%g, prev=%d\n",
454 x, cutpts[x - array_origin].cost_function (),
455 cutpts[x - array_origin].sum (),
456 cutpts[x - array_origin].squares (),
457 cutpts[x - array_origin].previous ()->position ());
460 occupation_count = -1;
462 for (x = best_end->
position () - pitch + pitch_error;
463 x < best_end->
position () - pitch_error
465 if (x < best_end->position () - pitch_error)
468 segpt =
new FPSEGPT (best_end);
469 seg_it.add_before_then_move (segpt);
472 while (best_end != NULL);
473 seg_it.move_to_last ();
474 mean_sum = seg_it.data ()->
sum ();
475 mean_sum = mean_sum * mean_sum / best_count;
476 if (seg_it.data ()->squares () - mean_sum < 0)
477 tprintf (
"Impossible sqsum=%g, mean=%g, total=%d\n",
478 seg_it.data ()->squares (), seg_it.data ()->sum (), best_count);
483 return seg_it.data ()->squares () - mean_sum;
496 inT16 projection_left,
497 inT16 projection_right,
502 float projection_scale,
503 inT16 &occupation_count,
504 FPSEGPT_LIST *seg_list,
515 inT16 projection_offset;
519 inT16 best_left_x = 0;
520 inT16 best_right_x = 0;
531 FPSEGPT_IT seg_it = seg_list;
533 end = (end - start) % pitch;
536 if ((pitch - 3) / 2 < pitch_error)
537 pitch_error = (pitch - 3) / 2;
540 for (left_edge = projection_left; projection->
pile_count (left_edge) == 0
541 && left_edge < projection_right; left_edge++);
542 for (right_edge = projection_right; projection->
pile_count (right_edge) == 0
543 && right_edge > left_edge; right_edge--);
544 array_origin = left_edge - pitch;
548 for (x = array_origin; x < left_edge; x++)
550 cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, 0);
551 prev_zero = left_edge - 1;
552 for (offset = 0; offset <= pitch_error; offset++, x++)
554 cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, offset);
558 for (offset = -pitch_error, minindex = 0; offset < pitch_error;
559 offset++, minindex++)
560 mins[minindex] = projection->
local_min (x + offset);
561 next_zero = x + zero_offset + 1;
562 for (offset = next_zero - 1; offset >= x; offset--) {
563 if (projection->
pile_count (offset) <= zero_count) {
568 while (x < right_edge - pitch_error) {
569 mins[minindex] = projection->
local_min (x + pitch_error);
571 if (minindex > pitch_error * 2)
576 if (projection->
pile_count (x) <= zero_count) {
580 for (offset = 1; offset <= pitch_error; offset++)
581 if (projection->
pile_count (x + offset) <= zero_count
582 || projection->
pile_count (x - offset) <= zero_count)
585 if (offset > pitch_error) {
586 if (x - prev_zero > zero_offset && next_zero - x > zero_offset) {
587 for (offset = 0; offset <= pitch_error; offset++) {
588 test_index = minindex + pitch_error + offset;
589 if (test_index > pitch_error * 2)
590 test_index -= pitch_error * 2 + 1;
591 if (mins[test_index])
593 test_index = minindex + pitch_error - offset;
594 if (test_index > pitch_error * 2)
595 test_index -= pitch_error * 2 + 1;
596 if (mins[test_index])
600 if (offset > pitch_error) {
607 if (projection_offset > offset)
608 offset = projection_offset;
612 if ((start == 0 && end == 0)
614 || (x - projection_left - start) % pitch <= end)
615 cutpts[x - array_origin].
assign (cutpts, array_origin, x,
616 faking, mid_cut, offset, projection,
617 projection_scale, zero_count, pitch,
620 cutpts[x - array_origin].
assign_cheap (cutpts, array_origin, x,
621 faking, mid_cut, offset,
622 projection, projection_scale,
626 if (next_zero < x || next_zero == x + zero_offset)
627 next_zero = x + zero_offset + 1;
628 if (projection->
pile_count (x + zero_offset) <= zero_count)
629 next_zero = x + zero_offset;
635 while (x < right_edge + pitch) {
636 offset = x < right_edge ? right_edge - x : 0;
637 cutpts[x - array_origin].
assign (cutpts, array_origin, x,
639 projection_scale, zero_count, pitch,
642 if (cutpts[x - array_origin].index () +
643 cutpts[x - array_origin].fake_count <= best_count + best_fake) {
644 if (cutpts[x - array_origin].fake_count < best_fake
645 || (cutpts[x - array_origin].fake_count == best_fake
646 && cutpts[x - array_origin].cost_function () < best_cost)) {
647 best_fake = cutpts[x - array_origin].
fake_count;
651 best_count = cutpts[x - array_origin].
index ();
653 else if (cutpts[x - array_origin].fake_count == best_fake
654 && x == best_right_x + 1
655 && cutpts[x - array_origin].cost_function () == best_cost) {
664 best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
673 occupation_count = -1;
675 for (x = best_end->
position () - pitch + pitch_error;
676 x < best_end->
position () - pitch_error
678 if (x < best_end->position () - pitch_error)
681 segpt =
new FPSEGPT (best_end);
682 seg_it.add_before_then_move (segpt);
685 while (best_end != NULL);
686 seg_it.move_to_last ();
687 mean_sum = seg_it.data ()->
sum ();
688 mean_sum = mean_sum * mean_sum / best_count;
689 if (seg_it.data ()->squares () - mean_sum < 0)
690 tprintf (
"Impossible sqsum=%g, mean=%g, total=%d\n",
691 seg_it.data ()->squares (), seg_it.data ()->sum (), best_count);
694 return seg_it.data ()->squares () - mean_sum;
bool local_min(inT32 x) const
void assign_cheap(FPCUTPT cutpts[], inT16 array_origin, inT16 x, BOOL8 faking, BOOL8 mid_cut, inT16 offset, STATS *projection, float projection_scale, inT16 zero_count, inT16 pitch, inT16 pitch_error)
EXTERN double pitsync_joined_edge
EXTERN double textord_balance_factor
void setup(FPCUTPT cutpts[], inT16 array_origin, STATS *projection, inT16 zero_count, inT16 pitch, inT16 x, inT16 offset)
void * alloc_mem(inT32 count)
TBOX box_next(BLOBNBOX_IT *it)
double check_pitch_sync2(BLOBNBOX_IT *blob_it, inT16 blob_count, inT16 pitch, inT16 pitch_error, STATS *projection, inT16 projection_left, inT16 projection_right, float projection_scale, inT16 &occupation_count, FPSEGPT_LIST *seg_list, inT16 start, inT16 end)
inT32 pile_count(inT32 value) const
void free_mem(void *oldchunk)
double check_pitch_sync3(inT16 projection_left, inT16 projection_right, inT16 zero_count, inT16 pitch, inT16 pitch_error, STATS *projection, float projection_scale, inT16 &occupation_count, FPSEGPT_LIST *seg_list, inT16 start, inT16 end)
void assign(FPCUTPT cutpts[], inT16 array_origin, inT16 x, BOOL8 faking, BOOL8 mid_cut, inT16 offset, STATS *projection, float projection_scale, inT16 zero_count, inT16 pitch, inT16 pitch_error)
EXTERN bool textord_fast_pitch_test