All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
pithsync.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * File: pithsync.cpp (Formerly pitsync2.c)
3  * Description: Code to find the optimum fixed pitch segmentation of some blobs.
4  * Author: Ray Smith
5  * Created: Thu Nov 19 11:48:05 GMT 1992
6  *
7  * (C) Copyright 1992, Hewlett-Packard Ltd.
8  ** Licensed under the Apache License, Version 2.0 (the "License");
9  ** you may not use this file except in compliance with the License.
10  ** You may obtain a copy of the License at
11  ** http://www.apache.org/licenses/LICENSE-2.0
12  ** Unless required by applicable law or agreed to in writing, software
13  ** distributed under the License is distributed on an "AS IS" BASIS,
14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  ** See the License for the specific language governing permissions and
16  ** limitations under the License.
17  *
18  **********************************************************************/
19 
20 #ifdef __UNIX__
21 #include <assert.h>
22 #endif
23 #include <math.h>
24 #include "memry.h"
25 #include "makerow.h"
26 #include "pitsync1.h"
27 #include "topitch.h"
28 #include "pithsync.h"
29 #include "tprintf.h"
30 
31 #define PROJECTION_MARGIN 10 //arbitrary
32 
33 #define EXTERN
34 
35 /**********************************************************************
36  * FPCUTPT::setup
37  *
38  * Constructor to make a new FPCUTPT.
39  **********************************************************************/
40 
41 void FPCUTPT::setup( //constructor
42  FPCUTPT *cutpts, //predecessors
43  inT16 array_origin, //start coord
44  STATS *projection, //vertical occupation
45  inT16 zero_count, //official zero
46  inT16 pitch, //proposed pitch
47  inT16 x, //position
48  inT16 offset //dist to gap
49  ) {
50  //half of pitch
51  inT16 half_pitch = pitch / 2 - 1;
52  uinT32 lead_flag; //new flag
53  inT32 ind; //current position
54 
55  if (half_pitch > 31)
56  half_pitch = 31;
57  else if (half_pitch < 0)
58  half_pitch = 0;
59  lead_flag = 1 << half_pitch;
60 
61  pred = NULL;
62  mean_sum = 0;
63  sq_sum = offset * offset;
64  cost = sq_sum;
65  faked = FALSE;
66  terminal = FALSE;
67  fake_count = 0;
68  xpos = x;
69  region_index = 0;
70  mid_cuts = 0;
71  if (x == array_origin) {
72  back_balance = 0;
73  fwd_balance = 0;
74  for (ind = 0; ind <= half_pitch; ind++) {
75  fwd_balance >>= 1;
76  if (projection->pile_count (ind) > zero_count)
77  fwd_balance |= lead_flag;
78  }
79  }
80  else {
81  back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
82  back_balance &= lead_flag + lead_flag - 1;
83  if (projection->pile_count (x) > zero_count)
84  back_balance |= 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;
88  }
89 }
90 
91 
92 /**********************************************************************
93  * FPCUTPT::assign
94  *
95  * Constructor to make a new FPCUTPT.
96  **********************************************************************/
97 
98 void FPCUTPT::assign( //constructor
99  FPCUTPT *cutpts, //predecessors
100  inT16 array_origin, //start coord
101  inT16 x, //position
102  BOOL8 faking, //faking this one
103  BOOL8 mid_cut, //cheap cut.
104  inT16 offset, //dist to gap
105  STATS *projection, //vertical occupation
106  float projection_scale, //scaling
107  inT16 zero_count, //official zero
108  inT16 pitch, //proposed pitch
109  inT16 pitch_error //allowed tolerance
110  ) {
111  int index; //test index
112  int balance_index; //for balance factor
113  inT16 balance_count; //ding factor
114  inT16 r_index; //test cut number
115  FPCUTPT *segpt; //segment point
116  inT32 dist; //from prev segment
117  double sq_dist; //squared distance
118  double mean; //mean pitch
119  double total; //total dists
120  double factor; //cost function
121  //half of pitch
122  inT16 half_pitch = pitch / 2 - 1;
123  uinT32 lead_flag; //new flag
124 
125  if (half_pitch > 31)
126  half_pitch = 31;
127  else if (half_pitch < 0)
128  half_pitch = 0;
129  lead_flag = 1 << half_pitch;
130 
131  back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
132  back_balance &= lead_flag + lead_flag - 1;
133  if (projection->pile_count (x) > zero_count)
134  back_balance |= 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;
138 
139  xpos = x;
140  cost = MAX_FLOAT32;
141  pred = NULL;
142  faked = faking;
143  terminal = FALSE;
144  region_index = 0;
146  for (index = x - pitch - pitch_error; index <= x - pitch + pitch_error;
147  index++) {
148  if (index >= array_origin) {
149  segpt = &cutpts[index - array_origin];
150  dist = x - segpt->xpos;
151  if (!segpt->terminal && segpt->fake_count < MAX_INT16) {
152  balance_count = 0;
153  if (textord_balance_factor > 0) {
155  lead_flag = back_balance ^ segpt->fwd_balance;
156  balance_count = 0;
157  while (lead_flag != 0) {
158  balance_count++;
159  lead_flag &= lead_flag - 1;
160  }
161  }
162  else {
163  for (balance_index = 0;
164  index + balance_index < x - balance_index;
165  balance_index++)
166  balance_count +=
167  (projection->pile_count (index + balance_index) <=
168  zero_count) ^ (projection->pile_count (x -
169  balance_index)
170  <= zero_count);
171  }
172  balance_count =
173  (inT16) (balance_count * textord_balance_factor /
174  projection_scale);
175  }
176  r_index = segpt->region_index + 1;
177  total = segpt->mean_sum + dist;
178  balance_count += offset;
179  sq_dist =
180  dist * dist + segpt->sq_sum + balance_count * balance_count;
181  mean = total / r_index;
182  factor = mean - pitch;
183  factor *= factor;
184  factor += sq_dist / (r_index) - mean * mean;
185  if (factor < cost && segpt->fake_count + faked <= fake_count) {
186  cost = factor; //find least cost
187  pred = segpt; //save path
188  mean_sum = total;
189  sq_sum = sq_dist;
190  fake_count = segpt->fake_count + faked;
191  mid_cuts = segpt->mid_cuts + mid_cut;
192  region_index = r_index;
193  }
194  }
195  }
196  }
197 }
198 
199 
200 /**********************************************************************
201  * FPCUTPT::assign_cheap
202  *
203  * Constructor to make a new FPCUTPT on the cheap.
204  **********************************************************************/
205 
206 void FPCUTPT::assign_cheap( //constructor
207  FPCUTPT *cutpts, //predecessors
208  inT16 array_origin, //start coord
209  inT16 x, //position
210  BOOL8 faking, //faking this one
211  BOOL8 mid_cut, //cheap cut.
212  inT16 offset, //dist to gap
213  STATS *projection, //vertical occupation
214  float projection_scale, //scaling
215  inT16 zero_count, //official zero
216  inT16 pitch, //proposed pitch
217  inT16 pitch_error //allowed tolerance
218  ) {
219  int index; //test index
220  inT16 balance_count; //ding factor
221  inT16 r_index; //test cut number
222  FPCUTPT *segpt; //segment point
223  inT32 dist; //from prev segment
224  double sq_dist; //squared distance
225  double mean; //mean pitch
226  double total; //total dists
227  double factor; //cost function
228  //half of pitch
229  inT16 half_pitch = pitch / 2 - 1;
230  uinT32 lead_flag; //new flag
231 
232  if (half_pitch > 31)
233  half_pitch = 31;
234  else if (half_pitch < 0)
235  half_pitch = 0;
236  lead_flag = 1 << half_pitch;
237 
238  back_balance = cutpts[x - 1 - array_origin].back_balance << 1;
239  back_balance &= lead_flag + lead_flag - 1;
240  if (projection->pile_count (x) > zero_count)
241  back_balance |= 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;
245 
246  xpos = x;
247  cost = MAX_FLOAT32;
248  pred = NULL;
249  faked = faking;
250  terminal = FALSE;
251  region_index = 0;
253  index = x - pitch;
254  if (index >= array_origin) {
255  segpt = &cutpts[index - array_origin];
256  dist = x - segpt->xpos;
257  if (!segpt->terminal && segpt->fake_count < MAX_INT16) {
258  balance_count = 0;
259  if (textord_balance_factor > 0) {
260  lead_flag = back_balance ^ segpt->fwd_balance;
261  balance_count = 0;
262  while (lead_flag != 0) {
263  balance_count++;
264  lead_flag &= lead_flag - 1;
265  }
266  balance_count = (inT16) (balance_count * textord_balance_factor
267  / projection_scale);
268  }
269  r_index = segpt->region_index + 1;
270  total = segpt->mean_sum + dist;
271  balance_count += offset;
272  sq_dist =
273  dist * dist + segpt->sq_sum + balance_count * balance_count;
274  mean = total / r_index;
275  factor = mean - pitch;
276  factor *= factor;
277  factor += sq_dist / (r_index) - mean * mean;
278  cost = factor; //find least cost
279  pred = segpt; //save path
280  mean_sum = total;
281  sq_sum = sq_dist;
282  fake_count = segpt->fake_count + faked;
283  mid_cuts = segpt->mid_cuts + mid_cut;
284  region_index = r_index;
285  }
286  }
287 }
288 
289 
290 /**********************************************************************
291  * check_pitch_sync
292  *
293  * Construct the lattice of possible segmentation points and choose the
294  * optimal path. Return the optimal path only.
295  * The return value is a measure of goodness of the sync.
296  **********************************************************************/
297 
298 double check_pitch_sync2( //find segmentation
299  BLOBNBOX_IT *blob_it, //blobs to do
300  inT16 blob_count, //no of blobs
301  inT16 pitch, //pitch estimate
302  inT16 pitch_error, //tolerance
303  STATS *projection, //vertical
304  inT16 projection_left, //edges //scale factor
305  inT16 projection_right,
306  float projection_scale,
307  inT16 &occupation_count, //no of occupied cells
308  FPSEGPT_LIST *seg_list, //output list
309  inT16 start, //start of good range
310  inT16 end //end of good range
311  ) {
312  BOOL8 faking; //illegal cut pt
313  BOOL8 mid_cut; //cheap cut pt.
314  inT16 x; //current coord
315  inT16 blob_index; //blob number
316  inT16 left_edge; //of word
317  inT16 right_edge; //of word
318  inT16 array_origin; //x coord of array
319  inT16 offset; //dist to legal area
320  inT16 zero_count; //projection zero
321  inT16 best_left_x = 0; //for equals
322  inT16 best_right_x = 0; //right edge
323  TBOX this_box; //bounding box
324  TBOX next_box; //box of next blob
325  FPSEGPT *segpt; //segment point
326  FPCUTPT *cutpts; //array of points
327  double best_cost; //best path
328  double mean_sum; //computes result
329  FPCUTPT *best_end; //end of best path
330  inT16 best_fake; //best fake level
331  inT16 best_count; //no of cuts
332  BLOBNBOX_IT this_it; //copy iterator
333  FPSEGPT_IT seg_it = seg_list; //output iterator
334 
335  // tprintf("Computing sync on word of %d blobs with pitch %d\n",
336  // blob_count, pitch);
337  // if (blob_count==8 && pitch==27)
338  // projection->print(stdout,TRUE);
339  zero_count = 0;
340  if (pitch < 3)
341  pitch = 3; //nothing ludicrous
342  if ((pitch - 3) / 2 < pitch_error)
343  pitch_error = (pitch - 3) / 2;
344  this_it = *blob_it;
345  this_box = box_next (&this_it);//get box
346  // left_edge=this_box.left(); //left of word
347  // right_edge=this_box.right();
348  // for (blob_index=1;blob_index<blob_count;blob_index++)
349  // {
350  // this_box=box_next(&this_it);
351  // if (this_box.right()>right_edge)
352  // right_edge=this_box.right();
353  // }
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--);
358  ASSERT_HOST (right_edge >= left_edge);
359  if (pitsync_linear_version >= 4)
360  return check_pitch_sync3 (projection_left, projection_right, zero_count,
361  pitch, pitch_error, projection,
362  projection_scale, occupation_count, seg_list,
363  start, end);
364  array_origin = left_edge - pitch;
365  cutpts = (FPCUTPT *) alloc_mem ((right_edge - left_edge + pitch * 2 + 1)
366  * sizeof (FPCUTPT));
367  for (x = array_origin; x < left_edge; x++)
368  //free cuts
369  cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, 0);
370  for (offset = 0; offset <= pitch_error; offset++, x++)
371  //not quite free
372  cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, offset);
373 
374  this_it = *blob_it;
375  best_cost = MAX_FLOAT32;
376  best_end = NULL;
377  this_box = box_next (&this_it);//first box
378  next_box = box_next (&this_it);//second box
379  blob_index = 1;
380  while (x < right_edge - pitch_error) {
381  if (x > this_box.right () + pitch_error && blob_index < blob_count) {
382  this_box = next_box;
383  next_box = box_next (&this_it);
384  blob_index++;
385  }
386  faking = FALSE;
387  mid_cut = FALSE;
388  if (x <= this_box.left ())
389  offset = 0;
390  else if (x <= this_box.left () + pitch_error)
391  offset = x - this_box.left ();
392  else if (x >= this_box.right ())
393  offset = 0;
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;
398  }
399  else if (x >= this_box.right () - pitch_error)
400  offset = this_box.right () - x;
401  else if (x - this_box.left () > pitch * pitsync_joined_edge
402  && this_box.right () - x > pitch * pitsync_joined_edge) {
403  mid_cut = TRUE;
404  offset = 0;
405  }
406  else {
407  faking = TRUE;
408  offset = projection->pile_count (x);
409  }
410  cutpts[x - array_origin].assign (cutpts, array_origin, x,
411  faking, mid_cut, offset, projection,
412  projection_scale, zero_count, pitch,
413  pitch_error);
414  x++;
415  }
416 
417  best_fake = MAX_INT16;
418  best_cost = MAX_INT32;
419  best_count = MAX_INT16;
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,
423  FALSE, FALSE, offset, projection,
424  projection_scale, zero_count, pitch,
425  pitch_error);
426  cutpts[x - array_origin].terminal = TRUE;
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;
433  best_cost = cutpts[x - array_origin].cost_function ();
434  best_left_x = x;
435  best_right_x = x;
436  best_count = cutpts[x - array_origin].index ();
437  }
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) {
441  //exactly equal
442  best_right_x = x;
443  }
444  }
445  x++;
446  }
447  ASSERT_HOST (best_fake < MAX_INT16);
448 
449  best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
450  if (this_box.right () == textord_test_x
451  && this_box.top () == textord_test_y) {
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 ());
458  }
459  }
460  occupation_count = -1;
461  do {
462  for (x = best_end->position () - pitch + pitch_error;
463  x < best_end->position () - pitch_error
464  && projection->pile_count (x) == 0; x++);
465  if (x < best_end->position () - pitch_error)
466  occupation_count++;
467  //copy it
468  segpt = new FPSEGPT (best_end);
469  seg_it.add_before_then_move (segpt);
470  best_end = best_end->previous ();
471  }
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);
479  free_mem(cutpts);
480  // tprintf("blob_count=%d, pitch=%d, sync=%g, occ=%d\n",
481  // blob_count,pitch,seg_it.data()->squares()-mean_sum,
482  // occupation_count);
483  return seg_it.data ()->squares () - mean_sum;
484 }
485 
486 
487 /**********************************************************************
488  * check_pitch_sync
489  *
490  * Construct the lattice of possible segmentation points and choose the
491  * optimal path. Return the optimal path only.
492  * The return value is a measure of goodness of the sync.
493  **********************************************************************/
494 
495 double check_pitch_sync3( //find segmentation
496  inT16 projection_left, //edges //to be considered 0
497  inT16 projection_right,
498  inT16 zero_count,
499  inT16 pitch, //pitch estimate
500  inT16 pitch_error, //tolerance
501  STATS *projection, //vertical
502  float projection_scale, //scale factor
503  inT16 &occupation_count, //no of occupied cells
504  FPSEGPT_LIST *seg_list, //output list
505  inT16 start, //start of good range
506  inT16 end //end of good range
507  ) {
508  BOOL8 faking; //illegal cut pt
509  BOOL8 mid_cut; //cheap cut pt.
510  inT16 left_edge; //of word
511  inT16 right_edge; //of word
512  inT16 x; //current coord
513  inT16 array_origin; //x coord of array
514  inT16 offset; //dist to legal area
515  inT16 projection_offset; //from scaled projection
516  inT16 prev_zero; //previous zero dist
517  inT16 next_zero; //next zero dist
518  inT16 zero_offset; //scan window
519  inT16 best_left_x = 0; //for equals
520  inT16 best_right_x = 0; //right edge
521  FPSEGPT *segpt; //segment point
522  FPCUTPT *cutpts; //array of points
523  BOOL8 *mins; //local min results
524  int minindex; //next input position
525  int test_index; //index to mins
526  double best_cost; //best path
527  double mean_sum; //computes result
528  FPCUTPT *best_end; //end of best path
529  inT16 best_fake; //best fake level
530  inT16 best_count; //no of cuts
531  FPSEGPT_IT seg_it = seg_list; //output iterator
532 
533  end = (end - start) % pitch;
534  if (pitch < 3)
535  pitch = 3; //nothing ludicrous
536  if ((pitch - 3) / 2 < pitch_error)
537  pitch_error = (pitch - 3) / 2;
538  //min dist of zero
539  zero_offset = (inT16) (pitch * pitsync_joined_edge);
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;
545  cutpts = (FPCUTPT *) alloc_mem ((right_edge - left_edge + pitch * 2 + 1)
546  * sizeof (FPCUTPT));
547  mins = (BOOL8 *) alloc_mem ((pitch_error * 2 + 1) * sizeof (BOOL8));
548  for (x = array_origin; x < left_edge; x++)
549  //free cuts
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++)
553  //not quite free
554  cutpts[x - array_origin].setup (cutpts, array_origin, projection, zero_count, pitch, x, offset);
555 
556  best_cost = MAX_FLOAT32;
557  best_end = NULL;
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) {
564  next_zero = offset;
565  break;
566  }
567  }
568  while (x < right_edge - pitch_error) {
569  mins[minindex] = projection->local_min (x + pitch_error);
570  minindex++;
571  if (minindex > pitch_error * 2)
572  minindex = 0;
573  faking = FALSE;
574  mid_cut = FALSE;
575  offset = 0;
576  if (projection->pile_count (x) <= zero_count) {
577  prev_zero = x;
578  }
579  else {
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)
583  break;
584  }
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])
592  break;
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])
597  break;
598  }
599  }
600  if (offset > pitch_error) {
601  offset = projection->pile_count (x);
602  faking = TRUE;
603  }
604  else {
605  projection_offset =
606  (inT16) (projection->pile_count (x) / projection_scale);
607  if (projection_offset > offset)
608  offset = projection_offset;
609  mid_cut = TRUE;
610  }
611  }
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,
618  pitch_error);
619  else
620  cutpts[x - array_origin].assign_cheap (cutpts, array_origin, x,
621  faking, mid_cut, offset,
622  projection, projection_scale,
623  zero_count, pitch,
624  pitch_error);
625  x++;
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;
630  }
631 
632  best_fake = MAX_INT16;
633  best_cost = MAX_INT32;
634  best_count = MAX_INT16;
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,
638  FALSE, FALSE, offset, projection,
639  projection_scale, zero_count, pitch,
640  pitch_error);
641  cutpts[x - array_origin].terminal = TRUE;
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;
648  best_cost = cutpts[x - array_origin].cost_function ();
649  best_left_x = x;
650  best_right_x = x;
651  best_count = cutpts[x - array_origin].index ();
652  }
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) {
656  //exactly equal
657  best_right_x = x;
658  }
659  }
660  x++;
661  }
662  ASSERT_HOST (best_fake < MAX_INT16);
663 
664  best_end = &cutpts[(best_left_x + best_right_x) / 2 - array_origin];
665  // for (x=left_edge-pitch;x<right_edge+pitch;x++)
666  // {
667  // tprintf("x=%d, C=%g, s=%g, sq=%g, prev=%d\n",
668  // x,cutpts[x-array_origin].cost_function(),
669  // cutpts[x-array_origin].sum(),
670  // cutpts[x-array_origin].squares(),
671  // cutpts[x-array_origin].previous()->position());
672  // }
673  occupation_count = -1;
674  do {
675  for (x = best_end->position () - pitch + pitch_error;
676  x < best_end->position () - pitch_error
677  && projection->pile_count (x) == 0; x++);
678  if (x < best_end->position () - pitch_error)
679  occupation_count++;
680  //copy it
681  segpt = new FPSEGPT (best_end);
682  seg_it.add_before_then_move (segpt);
683  best_end = best_end->previous ();
684  }
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);
692  free_mem(mins);
693  free_mem(cutpts);
694  return seg_it.data ()->squares () - mean_sum;
695 }
void setup(FPCUTPT cutpts[], inT16 array_origin, STATS *projection, inT16 zero_count, inT16 pitch, inT16 x, inT16 offset)
Definition: pithsync.cpp:41
double sum()
Definition: pithsync.h:78
void free_mem(void *oldchunk)
Definition: memry.cpp:55
#define tprintf(...)
Definition: tprintf.h:31
Definition: statistc.h:33
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)
Definition: pithsync.cpp:98
unsigned char BOOL8
Definition: host.h:113
FPCUTPT * previous()
Definition: pithsync.h:81
inT16 index() const
Definition: pithsync.h:87
inT16 right() const
Definition: rect.h:75
inT32 position()
Definition: pithsync.h:69
#define ASSERT_HOST(x)
Definition: errcode.h:84
bool local_min(inT32 x) const
Definition: statistc.cpp:266
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)
Definition: pithsync.cpp:495
BOOL8 faked
Definition: pithsync.h:91
unsigned int uinT32
Definition: host.h:103
inT16 fake_count
Definition: pithsync.h:93
inT16 left() const
Definition: rect.h:68
EXTERN bool textord_fast_pitch_test
Definition: topitch.cpp:48
EXTERN double textord_balance_factor
Definition: topitch.cpp:59
int textord_test_x
Definition: makerow.cpp:62
#define MAX_INT32
Definition: host.h:120
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)
Definition: pithsync.cpp:298
TBOX box_next(BLOBNBOX_IT *it)
Definition: blobbox.cpp:629
double cost_function()
Definition: pithsync.h:72
#define FALSE
Definition: capi.h:29
Definition: rect.h:30
#define TRUE
Definition: capi.h:28
#define MAX_INT16
Definition: host.h:119
BOOL8 terminal
Definition: pithsync.h:92
#define MAX_FLOAT32
Definition: host.h:124
inT32 pile_count(inT32 value) const
Definition: statistc.h:78
void * alloc_mem(inT32 count)
Definition: memry.cpp:47
#define NULL
Definition: host.h:144
EXTERN double pitsync_joined_edge
Definition: pitsync1.cpp:33
inT16 top() const
Definition: rect.h:54
int textord_test_y
Definition: makerow.cpp:63
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)
Definition: pithsync.cpp:206
short inT16
Definition: host.h:100
int inT32
Definition: host.h:102