32 #define PROJECTION_MARGIN 10 //arbitrary
52 inT16 half_pitch = pitch / 2 - 1;
58 else if (half_pitch < 0)
60 lead_flag = 1 << half_pitch;
64 sq_sum = offset * offset;
72 if (x == array_origin) {
75 for (ind = 0; ind <= half_pitch; ind++) {
78 fwd_balance |= lead_flag;
82 back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
83 back_balance &= lead_flag + lead_flag - 1;
86 fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
87 if (projection->
pile_count (x + half_pitch) > zero_count)
88 fwd_balance |= lead_flag;
107 float projection_scale,
123 inT16 half_pitch = pitch / 2 - 1;
128 else if (half_pitch < 0)
130 lead_flag = 1 << half_pitch;
132 back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
133 back_balance &= lead_flag + lead_flag - 1;
136 fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
137 if (projection->
pile_count (x + half_pitch) > zero_count)
138 fwd_balance |= lead_flag;
147 for (index = x - pitch - pitch_error; index <= x - pitch + pitch_error;
149 if (index >= array_origin) {
150 segpt = &cutpts[index - array_origin];
151 dist = x - segpt->xpos;
156 lead_flag = back_balance ^ segpt->fwd_balance;
158 while (lead_flag != 0) {
160 lead_flag &= lead_flag - 1;
164 for (balance_index = 0;
165 index + balance_index < x - balance_index;
168 (projection->
pile_count (index + balance_index) <=
177 r_index = segpt->region_index + 1;
178 total = segpt->mean_sum + dist;
179 balance_count += offset;
181 dist * dist + segpt->sq_sum + balance_count * balance_count;
182 mean = total / r_index;
183 factor = mean - pitch;
185 factor += sq_dist / (r_index) - mean * mean;
192 mid_cuts = segpt->mid_cuts + mid_cut;
193 region_index = r_index;
215 float projection_scale,
230 inT16 half_pitch = pitch / 2 - 1;
235 else if (half_pitch < 0)
237 lead_flag = 1 << half_pitch;
239 back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
240 back_balance &= lead_flag + lead_flag - 1;
243 fwd_balance = cutpts[x - 1 - array_origin].fwd_balance >> 1;
244 if (projection->
pile_count (x + half_pitch) > zero_count)
245 fwd_balance |= lead_flag;
255 if (index >= array_origin) {
256 segpt = &cutpts[index - array_origin];
257 dist = x - segpt->xpos;
261 lead_flag = back_balance ^ segpt->fwd_balance;
263 while (lead_flag != 0) {
265 lead_flag &= lead_flag - 1;
270 r_index = segpt->region_index + 1;
271 total = segpt->mean_sum + dist;
272 balance_count += offset;
274 dist * dist + segpt->sq_sum + balance_count * balance_count;
275 mean = total / r_index;
276 factor = mean - pitch;
278 factor += sq_dist / (r_index) - mean * mean;
284 mid_cuts = segpt->mid_cuts + mid_cut;
285 region_index = r_index;
300 BLOBNBOX_IT *blob_it,
305 inT16 projection_left,
306 inT16 projection_right,
307 float projection_scale,
308 inT16 &occupation_count,
309 FPSEGPT_LIST *seg_list,
322 inT16 best_left_x = 0;
323 inT16 best_right_x = 0;
334 FPSEGPT_IT seg_it = seg_list;
343 if ((pitch - 3) / 2 < pitch_error)
344 pitch_error = (pitch - 3) / 2;
355 for (left_edge = projection_left; projection->
pile_count (left_edge) == 0
356 && left_edge < projection_right; left_edge++);
357 for (right_edge = projection_right; projection->
pile_count (right_edge) == 0
358 && right_edge > left_edge; right_edge--);
360 if (pitsync_linear_version >= 4)
362 pitch, pitch_error, projection,
363 projection_scale, occupation_count, seg_list,
365 array_origin = left_edge - pitch;
368 for (x = array_origin; x < left_edge; x++)
370 cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, 0);
371 for (offset = 0; offset <= pitch_error; offset++, x++)
373 cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, offset);
381 while (x < right_edge - pitch_error) {
382 if (x > this_box.
right () + pitch_error && blob_index < blob_count) {
389 if (x <= this_box.
left ())
391 else if (x <= this_box.
left () + pitch_error)
392 offset = x - this_box.
left ();
393 else if (x >= this_box.
right ())
395 else if (x >= next_box.
left () && blob_index < blob_count) {
396 offset = x - next_box.
left ();
397 if (this_box.
right () - x < offset)
398 offset = this_box.
right () - x;
400 else if (x >= this_box.
right () - pitch_error)
401 offset = this_box.
right () - x;
411 cutpts[x - array_origin].
assign (cutpts, array_origin, x,
412 faking, mid_cut, offset, projection,
413 projection_scale, zero_count, pitch,
421 while (x < right_edge + pitch) {
422 offset = x < right_edge ? right_edge - x : 0;
423 cutpts[x - array_origin].
assign (cutpts, array_origin, x,
425 projection_scale, zero_count, pitch,
428 if (cutpts[x - array_origin].index () +
429 cutpts[x - array_origin].fake_count <= best_count + best_fake) {
430 if (cutpts[x - array_origin].fake_count < best_fake
431 || (cutpts[x - array_origin].fake_count == best_fake
432 && cutpts[x - array_origin].cost_function () < best_cost)) {
433 best_fake = cutpts[x - array_origin].
fake_count;
437 best_count = cutpts[x - array_origin].
index ();
439 else if (cutpts[x - array_origin].fake_count == best_fake
440 && x == best_right_x + 1
441 && cutpts[x - array_origin].cost_function () == best_cost) {
450 best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
453 for (x = left_edge - pitch; x < right_edge + pitch; x++) {
454 tprintf (
"x=%d, C=%g, s=%g, sq=%g, prev=%d\n",
455 x, cutpts[x - array_origin].cost_function (),
456 cutpts[x - array_origin].sum (),
457 cutpts[x - array_origin].squares (),
458 cutpts[x - array_origin].previous ()->position ());
461 occupation_count = -1;
463 for (x = best_end->
position () - pitch + pitch_error;
464 x < best_end->
position () - pitch_error
466 if (x < best_end->position () - pitch_error)
469 segpt =
new FPSEGPT (best_end);
470 seg_it.add_before_then_move (segpt);
473 while (best_end !=
NULL);
474 seg_it.move_to_last ();
475 mean_sum = seg_it.data ()->
sum ();
476 mean_sum = mean_sum * mean_sum / best_count;
477 if (seg_it.data ()->squares () - mean_sum < 0)
478 tprintf (
"Impossible sqsum=%g, mean=%g, total=%d\n",
479 seg_it.data ()->squares (), seg_it.data ()->sum (), best_count);
484 return seg_it.data ()->squares () - mean_sum;
497 inT16 projection_left,
498 inT16 projection_right,
503 float projection_scale,
504 inT16 &occupation_count,
505 FPSEGPT_LIST *seg_list,
516 inT16 projection_offset;
520 inT16 best_left_x = 0;
521 inT16 best_right_x = 0;
532 FPSEGPT_IT seg_it = seg_list;
534 end = (end - start) % pitch;
537 if ((pitch - 3) / 2 < pitch_error)
538 pitch_error = (pitch - 3) / 2;
541 for (left_edge = projection_left; projection->
pile_count (left_edge) == 0
542 && left_edge < projection_right; left_edge++);
543 for (right_edge = projection_right; projection->
pile_count (right_edge) == 0
544 && right_edge > left_edge; right_edge--);
545 array_origin = left_edge - pitch;
549 for (x = array_origin; x < left_edge; x++)
551 cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, 0);
552 prev_zero = left_edge - 1;
553 for (offset = 0; offset <= pitch_error; offset++, x++)
555 cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, offset);
559 for (offset = -pitch_error, minindex = 0; offset < pitch_error;
560 offset++, minindex++)
561 mins[minindex] = projection->
local_min (x + offset);
562 next_zero = x + zero_offset + 1;
563 for (offset = next_zero - 1; offset >= x; offset--) {
564 if (projection->
pile_count (offset) <= zero_count) {
569 while (x < right_edge - pitch_error) {
570 mins[minindex] = projection->
local_min (x + pitch_error);
572 if (minindex > pitch_error * 2)
577 if (projection->
pile_count (x) <= zero_count) {
581 for (offset = 1; offset <= pitch_error; offset++)
582 if (projection->
pile_count (x + offset) <= zero_count
583 || projection->
pile_count (x - offset) <= zero_count)
586 if (offset > pitch_error) {
587 if (x - prev_zero > zero_offset && next_zero - x > zero_offset) {
588 for (offset = 0; offset <= pitch_error; offset++) {
589 test_index = minindex + pitch_error + offset;
590 if (test_index > pitch_error * 2)
591 test_index -= pitch_error * 2 + 1;
592 if (mins[test_index])
594 test_index = minindex + pitch_error - offset;
595 if (test_index > pitch_error * 2)
596 test_index -= pitch_error * 2 + 1;
597 if (mins[test_index])
601 if (offset > pitch_error) {
608 if (projection_offset > offset)
609 offset = projection_offset;
613 if ((start == 0 && end == 0)
615 || (x - projection_left - start) % pitch <= end)
616 cutpts[x - array_origin].
assign (cutpts, array_origin, x,
617 faking, mid_cut, offset, projection,
618 projection_scale, zero_count, pitch,
621 cutpts[x - array_origin].
assign_cheap (cutpts, array_origin, x,
622 faking, mid_cut, offset,
623 projection, projection_scale,
627 if (next_zero < x || next_zero == x + zero_offset)
628 next_zero = x + zero_offset + 1;
629 if (projection->
pile_count (x + zero_offset) <= zero_count)
630 next_zero = x + zero_offset;
636 while (x < right_edge + pitch) {
637 offset = x < right_edge ? right_edge - x : 0;
638 cutpts[x - array_origin].
assign (cutpts, array_origin, x,
640 projection_scale, zero_count, pitch,
643 if (cutpts[x - array_origin].index () +
644 cutpts[x - array_origin].fake_count <= best_count + best_fake) {
645 if (cutpts[x - array_origin].fake_count < best_fake
646 || (cutpts[x - array_origin].fake_count == best_fake
647 && cutpts[x - array_origin].cost_function () < best_cost)) {
648 best_fake = cutpts[x - array_origin].
fake_count;
652 best_count = cutpts[x - array_origin].
index ();
654 else if (cutpts[x - array_origin].fake_count == best_fake
655 && x == best_right_x + 1
656 && cutpts[x - array_origin].cost_function () == best_cost) {
665 best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
674 occupation_count = -1;
676 for (x = best_end->
position () - pitch + pitch_error;
677 x < best_end->
position () - pitch_error
679 if (x < best_end->position () - pitch_error)
682 segpt =
new FPSEGPT (best_end);
683 seg_it.add_before_then_move (segpt);
686 while (best_end !=
NULL);
687 seg_it.move_to_last ();
688 mean_sum = seg_it.data ()->
sum ();
689 mean_sum = mean_sum * mean_sum / best_count;
690 if (seg_it.data ()->squares () - mean_sum < 0)
691 tprintf (
"Impossible sqsum=%g, mean=%g, total=%d\n",
692 seg_it.data ()->squares (), seg_it.data ()->sum (), best_count);
695 return seg_it.data ()->squares () - mean_sum;