Leptonica  1.82.0
Image processing and image analysis suite
boxfunc1.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
82 #ifdef HAVE_CONFIG_H
83 #include <config_auto.h>
84 #endif /* HAVE_CONFIG_H */
85 
86 #include "allheaders.h"
87 
88 static l_int32 boxHasOverlapInXorY(l_int32 c1, l_int32 s1, l_int32 c2,
89  l_int32 s2);
90 static l_int32 boxGetDistanceInXorY(l_int32 c1, l_int32 s1, l_int32 c2,
91  l_int32 s2);
92 
93 
94 /*---------------------------------------------------------------------*
95  * Box geometry *
96  *---------------------------------------------------------------------*/
105 l_ok
107  BOX *box2,
108  l_int32 *presult)
109 {
110 l_int32 x1, y1, w1, h1, x2, y2, w2, h2, valid1, valid2;
111 
112  PROCNAME("boxContains");
113 
114  if (!presult)
115  return ERROR_INT("&result not defined", procName, 1);
116  *presult = 0;
117  if (!box1 || !box2)
118  return ERROR_INT("boxes not both defined", procName, 1);
119  boxIsValid(box1, &valid1);
120  boxIsValid(box2, &valid2);
121  if (!valid1 || !valid2)
122  return ERROR_INT("boxes not both valid", procName, 1);
123 
124  boxGetGeometry(box1, &x1, &y1, &w1, &h1);
125  boxGetGeometry(box2, &x2, &y2, &w2, &h2);
126  if (x1 <= x2 && y1 <= y2 && (x1 + w1 >= x2 + w2) && (y1 + h1 >= y2 + h2))
127  *presult = 1;
128  return 0;
129 }
130 
131 
140 l_ok
142  BOX *box2,
143  l_int32 *presult)
144 {
145 l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2, valid1, valid2;
146 
147  PROCNAME("boxIntersects");
148 
149  if (!presult)
150  return ERROR_INT("&result not defined", procName, 1);
151  *presult = 0;
152  if (!box1 || !box2)
153  return ERROR_INT("boxes not both defined", procName, 1);
154  boxIsValid(box1, &valid1);
155  boxIsValid(box2, &valid2);
156  if (!valid1 || !valid2)
157  return ERROR_INT("boxes not both valid", procName, 1);
158 
159  boxGetGeometry(box1, &l1, &t1, &w1, &h1);
160  boxGetGeometry(box2, &l2, &t2, &w2, &h2);
161  r1 = l1 + w1 - 1;
162  r2 = l2 + w2 - 1;
163  b1 = t1 + h1 - 1;
164  b2 = t2 + h2 - 1;
165  if (b2 < t1 || b1 < t2 || r1 < l2 || r2 < l1)
166  *presult = 0;
167  else
168  *presult = 1;
169  return 0;
170 }
171 
172 
187 BOXA *
189  BOX *box)
190 {
191 l_int32 i, n, val, valid;
192 BOX *box1;
193 BOXA *boxad;
194 
195  PROCNAME("boxaContainedInBox");
196 
197  if (!boxas)
198  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
199  if (!box)
200  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
201  n = boxaGetCount(boxas);
202  boxIsValid(box, &valid);
203  if (n == 0 || !valid)
204  return boxaCreate(1); /* empty */
205 
206  boxad = boxaCreate(0);
207  for (i = 0; i < n; i++) {
208  if ((box1 = boxaGetValidBox(boxas, i, L_CLONE)) == NULL)
209  continue;
210  boxContains(box, box1, &val);
211  if (val == 1)
212  boxaAddBox(boxad, box1, L_COPY);
213  boxDestroy(&box1); /* destroy the clone */
214  }
215 
216  return boxad;
217 }
218 
219 
233 l_ok
235  BOX *box,
236  l_int32 *pcount)
237 {
238 l_int32 i, n, val, valid;
239 BOX *box1;
240 
241  PROCNAME("boxaContainedInBoxCount");
242 
243  if (!pcount)
244  return ERROR_INT("&count not defined", procName, 1);
245  *pcount = 0;
246  if (!boxa)
247  return ERROR_INT("boxa not defined", procName, 1);
248  if (!box)
249  return ERROR_INT("box not defined", procName, 1);
250  n = boxaGetCount(boxa);
251  boxIsValid(box, &valid);
252  if (n == 0 || !valid)
253  return 0;
254 
255  for (i = 0; i < n; i++) {
256  if ((box1 = boxaGetValidBox(boxa, i, L_CLONE)) == NULL)
257  continue;
258  boxContains(box, box1, &val);
259  if (val == 1)
260  (*pcount)++;
261  boxDestroy(&box1);
262  }
263  return 0;
264 }
265 
266 
275 l_ok
277  BOXA *boxa2,
278  l_int32 *pcontained)
279 {
280 l_int32 i, j, n1, n2, cont, result;
281 BOX *box1, *box2;
282 
283  PROCNAME("boxaContainedInBoxa");
284 
285  if (!pcontained)
286  return ERROR_INT("&contained not defined", procName, 1);
287  *pcontained = 0;
288  if (!boxa1 || !boxa2)
289  return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
290 
291  n1 = boxaGetCount(boxa1);
292  n2 = boxaGetCount(boxa2);
293  for (i = 0; i < n2; i++) {
294  if ((box2 = boxaGetValidBox(boxa2, i, L_CLONE)) == NULL)
295  continue;
296  cont = 0;
297  for (j = 0; j < n1; j++) {
298  if ((box1 = boxaGetValidBox(boxa1, j, L_CLONE)) == NULL)
299  continue;
300  boxContains(box1, box2, &result);
301  boxDestroy(&box1);
302  if (result) {
303  cont = 1;
304  break;
305  }
306  }
307  boxDestroy(&box2);
308  if (!cont) return 0;
309  }
310 
311  *pcontained = 1;
312  return 0;
313 }
314 
315 
330 BOXA *
332  BOX *box)
333 {
334 l_int32 i, n, val, valid;
335 BOX *box1;
336 BOXA *boxad;
337 
338  PROCNAME("boxaIntersectsBox");
339 
340  if (!boxas)
341  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
342  if (!box)
343  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
344  n = boxaGetCount(boxas);
345  boxIsValid(box, &valid);
346  if (n == 0 || !valid)
347  return boxaCreate(1); /* empty */
348 
349  boxad = boxaCreate(0);
350  for (i = 0; i < n; i++) {
351  if ((box1 = boxaGetValidBox(boxas, i, L_CLONE)) == NULL)
352  continue;
353  boxIntersects(box, box1, &val);
354  if (val == 1)
355  boxaAddBox(boxad, box1, L_COPY);
356  boxDestroy(&box1); /* destroy the clone */
357  }
358 
359  return boxad;
360 }
361 
362 
371 l_ok
373  BOX *box,
374  l_int32 *pcount)
375 {
376 l_int32 i, n, val, valid;
377 BOX *box1;
378 
379  PROCNAME("boxaIntersectsBoxCount");
380 
381  if (!pcount)
382  return ERROR_INT("&count not defined", procName, 1);
383  *pcount = 0;
384  if (!boxa)
385  return ERROR_INT("boxa not defined", procName, 1);
386  if (!box)
387  return ERROR_INT("box not defined", procName, 1);
388  n = boxaGetCount(boxa);
389  boxIsValid(box, &valid);
390  if (n == 0 || !valid)
391  return 0;
392 
393  for (i = 0; i < n; i++) {
394  if ((box1 = boxaGetValidBox(boxa, i, L_CLONE)) == NULL)
395  continue;
396  boxIntersects(box, box1, &val);
397  if (val == 1)
398  (*pcount)++;
399  boxDestroy(&box1);
400  }
401  return 0;
402 }
403 
404 
418 BOXA *
420  BOX *box)
421 {
422 l_int32 i, n, valid;
423 BOX *box1, *boxo;
424 BOXA *boxad;
425 
426  PROCNAME("boxaClipToBox");
427 
428  if (!boxas)
429  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
430  if (!box)
431  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
432  n = boxaGetCount(boxas);
433  boxIsValid(box, &valid);
434  if (n == 0 || !valid)
435  return boxaCreate(1); /* empty */
436 
437  boxad = boxaCreate(0);
438  for (i = 0; i < n; i++) {
439  if ((box1 = boxaGetValidBox(boxas, i, L_CLONE)) == NULL)
440  continue;
441  if ((boxo = boxOverlapRegion(box, box1)) != NULL)
442  boxaAddBox(boxad, boxo, L_INSERT);
443  boxDestroy(&box1);
444  }
445 
446  return boxad;
447 }
448 
449 
477 BOXA *
479  PIXA *pixadb)
480 {
481 l_int32 i, j, w, h, n1, n2, overlap, niters;
482 BOX *box1, *box2, *box3;
483 BOXA *boxa1, *boxa2;
484 PIX *pix1;
485 
486  PROCNAME("boxaCombineOverlaps");
487 
488  if (!boxas)
489  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
490 
491  if (pixadb) boxaGetExtent(boxas, &w, &h, NULL);
492 
493  boxa1 = boxaCopy(boxas, L_COPY);
494  n1 = boxaGetCount(boxa1);
495  niters = 0;
496  while (1) { /* loop until no change from previous iteration */
497  niters++;
498  if (pixadb) {
499  pix1 = pixCreate(w + 5, h + 5, 32);
500  pixSetAll(pix1);
501  pixRenderBoxaArb(pix1, boxa1, 2, 255, 0, 0);
502  pixaAddPix(pixadb, pix1, L_COPY);
503  }
504 
505  /* Combine overlaps for this iteration */
506  for (i = 0; i < n1; i++) {
507  if ((box1 = boxaGetValidBox(boxa1, i, L_COPY)) == NULL)
508  continue;
509  for (j = i + 1; j < n1; j++) {
510  if ((box2 = boxaGetValidBox(boxa1, j, L_COPY)) == NULL)
511  continue;
512  boxIntersects(box1, box2, &overlap);
513  if (overlap) {
514  box3 = boxBoundingRegion(box1, box2);
515  boxaReplaceBox(boxa1, i, box3);
516  boxaReplaceBox(boxa1, j, boxCreate(0, 0, 0, 0));
517  boxDestroy(&box1);
518  box1 = boxCopy(box3);
519  }
520  boxDestroy(&box2);
521  }
522  boxDestroy(&box1);
523  }
524  boxa2 = boxaSaveValid(boxa1, L_COPY);
525  n2 = boxaGetCount(boxa2);
526  boxaDestroy(&boxa1);
527  boxa1 = boxa2;
528  if (n1 == n2) {
529  if (pixadb) pixDestroy(&pix1);
530  break;
531  }
532  n1 = n2;
533  if (pixadb) {
534  pixRenderBoxaArb(pix1, boxa1, 2, 0, 255, 0);
535  pixaAddPix(pixadb, pix1, L_INSERT);
536  }
537  }
538 
539  if (pixadb)
540  L_INFO("number of iterations: %d\n", procName, niters);
541  return boxa1;
542 }
543 
544 
571 l_ok
573  BOXA *boxas2,
574  BOXA **pboxad1,
575  BOXA **pboxad2,
576  PIXA *pixadb)
577 {
578 l_int32 i, j, w, h, w2, h2, n1, n2, n1i, n2i, niters;
579 l_int32 overlap, bigger, area1, area2;
580 BOX *box1, *box2, *box3;
581 BOXA *boxa1, *boxa2, *boxac1, *boxac2;
582 PIX *pix1;
583 
584  PROCNAME("boxaCombineOverlapsInPair");
585 
586  if (pboxad1) *pboxad1 = NULL;
587  if (pboxad2) *pboxad2 = NULL;
588  if (!boxas1 || !boxas2)
589  return ERROR_INT("boxas1 and boxas2 not both defined", procName, 1);
590  if (!pboxad1 || !pboxad2)
591  return ERROR_INT("&boxad1 and &boxad2 not both defined", procName, 1);
592 
593  if (pixadb) {
594  boxaGetExtent(boxas1, &w, &h, NULL);
595  boxaGetExtent(boxas2, &w2, &h2, NULL);
596  w = L_MAX(w, w2);
597  h = L_MAX(h, w2);
598  }
599 
600  /* Let the boxa with the largest area have first crack at the other */
601  boxaGetArea(boxas1, &area1);
602  boxaGetArea(boxas2, &area2);
603  if (area1 >= area2) {
604  boxac1 = boxaCopy(boxas1, L_COPY);
605  boxac2 = boxaCopy(boxas2, L_COPY);
606  } else {
607  boxac1 = boxaCopy(boxas2, L_COPY);
608  boxac2 = boxaCopy(boxas1, L_COPY);
609  }
610 
611  n1i = boxaGetCount(boxac1);
612  n2i = boxaGetCount(boxac2);
613  niters = 0;
614  while (1) {
615  niters++;
616  if (pixadb) {
617  pix1 = pixCreate(w + 5, h + 5, 32);
618  pixSetAll(pix1);
619  pixRenderBoxaArb(pix1, boxac1, 2, 255, 0, 0);
620  pixRenderBoxaArb(pix1, boxac2, 2, 0, 255, 0);
621  pixaAddPix(pixadb, pix1, L_INSERT);
622  }
623 
624  /* First combine boxes in each set */
625  boxa1 = boxaCombineOverlaps(boxac1, NULL);
626  boxa2 = boxaCombineOverlaps(boxac2, NULL);
627 
628  /* Now combine boxes between sets */
629  n1 = boxaGetCount(boxa1);
630  n2 = boxaGetCount(boxa2);
631  for (i = 0; i < n1; i++) { /* 1 eats 2 */
632  if ((box1 = boxaGetValidBox(boxa1, i, L_COPY)) == NULL)
633  continue;
634  for (j = 0; j < n2; j++) {
635  if ((box2 = boxaGetValidBox(boxa2, j, L_COPY)) == NULL)
636  continue;
637  boxIntersects(box1, box2, &overlap);
638  boxCompareSize(box1, box2, L_SORT_BY_AREA, &bigger);
639  if (overlap && (bigger == 1)) {
640  box3 = boxBoundingRegion(box1, box2);
641  boxaReplaceBox(boxa1, i, box3);
642  boxaReplaceBox(boxa2, j, boxCreate(0, 0, 0, 0));
643  boxDestroy(&box1);
644  box1 = boxCopy(box3);
645  }
646  boxDestroy(&box2);
647  }
648  boxDestroy(&box1);
649  }
650  for (i = 0; i < n2; i++) { /* 2 eats 1 */
651  if ((box2 = boxaGetValidBox(boxa2, i, L_COPY)) == NULL)
652  continue;
653  for (j = 0; j < n1; j++) {
654  if ((box1 = boxaGetValidBox(boxa1, j, L_COPY)) == NULL)
655  continue;
656  boxIntersects(box1, box2, &overlap);
657  boxCompareSize(box2, box1, L_SORT_BY_AREA, &bigger);
658  if (overlap && (bigger == 1)) {
659  box3 = boxBoundingRegion(box1, box2);
660  boxaReplaceBox(boxa2, i, box3);
661  boxaReplaceBox(boxa1, j, boxCreate(0, 0, 0, 0));
662  boxDestroy(&box2);
663  box2 = boxCopy(box3);
664  }
665  boxDestroy(&box1);
666  }
667  boxDestroy(&box2);
668  }
669  boxaDestroy(&boxac1);
670  boxaDestroy(&boxac2);
671  boxac1 = boxaSaveValid(boxa1, L_COPY); /* remove invalid boxes */
672  boxac2 = boxaSaveValid(boxa2, L_COPY);
673  boxaDestroy(&boxa1);
674  boxaDestroy(&boxa2);
675  n1 = boxaGetCount(boxac1);
676  n2 = boxaGetCount(boxac2);
677  if (n1 == n1i && n2 == n2i) break;
678  n1i = n1;
679  n2i = n2;
680  if (pixadb) {
681  pix1 = pixCreate(w + 5, h + 5, 32);
682  pixSetAll(pix1);
683  pixRenderBoxaArb(pix1, boxac1, 2, 255, 0, 0);
684  pixRenderBoxaArb(pix1, boxac2, 2, 0, 255, 0);
685  pixaAddPix(pixadb, pix1, L_INSERT);
686  }
687  }
688 
689  if (pixadb)
690  L_INFO("number of iterations: %d\n", procName, niters);
691  *pboxad1 = boxac1;
692  *pboxad2 = boxac2;
693  return 0;
694 }
695 
696 
709 BOX *
711  BOX *box2)
712 {
713 l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2, ld, td, rd, bd;
714 l_int32 valid1, valid2;
715 
716  PROCNAME("boxOverlapRegion");
717 
718  if (!box1 || !box2)
719  return (BOX *)ERROR_PTR("boxes not both defined", procName, NULL);
720  boxIsValid(box1, &valid1);
721  boxIsValid(box2, &valid2);
722  if (!valid1 || !valid2) {
723  L_WARNING("at least one box is invalid\n", procName);
724  return NULL;
725  }
726 
727  boxGetGeometry(box1, &l1, &t1, &w1, &h1);
728  boxGetGeometry(box2, &l2, &t2, &w2, &h2);
729  r1 = l1 + w1 - 1;
730  r2 = l2 + w2 - 1;
731  b1 = t1 + h1 - 1;
732  b2 = t2 + h2 - 1;
733  if (b2 < t1 || b1 < t2 || r1 < l2 || r2 < l1)
734  return NULL;
735 
736  ld = L_MAX(l1, l2);
737  td = L_MAX(t1, t2);
738  rd = L_MIN(r1, r2);
739  bd = L_MIN(b1, b2);
740  return boxCreate(ld, td, rd - ld + 1, bd - td + 1);
741 }
742 
743 
759 BOX *
761  BOX *box2)
762 {
763 l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2, ld, td, rd, bd;
764 l_int32 valid1, valid2;
765 
766  PROCNAME("boxBoundingRegion");
767 
768  if (!box1 || !box2)
769  return (BOX *)ERROR_PTR("boxes not both defined", procName, NULL);
770  boxIsValid(box1, &valid1);
771  boxIsValid(box2, &valid2);
772  if (!valid1 && !valid2) {
773  L_WARNING("both boxes are invalid\n", procName);
774  return boxCreate(0, 0, 0, 0);
775  }
776  if (valid1 && !valid2)
777  return boxCopy(box1);
778  if (!valid1 && valid2)
779  return boxCopy(box2);
780 
781  boxGetGeometry(box1, &l1, &t1, &w1, &h1);
782  boxGetGeometry(box2, &l2, &t2, &w2, &h2);
783  r1 = l1 + w1 - 1;
784  r2 = l2 + w2 - 1;
785  b1 = t1 + h1 - 1;
786  b2 = t2 + h2 - 1;
787  ld = L_MIN(l1, l2);
788  td = L_MIN(t1, t2);
789  rd = L_MAX(r1, r2);
790  bd = L_MAX(b1, b2);
791  return boxCreate(ld, td, rd - ld + 1, bd - td + 1);
792 }
793 
794 
809 l_ok
811  BOX *box2,
812  l_float32 *pfract)
813 {
814 l_int32 w2, h2, w, h, valid1, valid2;
815 BOX *boxo;
816 
817  PROCNAME("boxOverlapFraction");
818 
819  if (!pfract)
820  return ERROR_INT("&fract not defined", procName, 1);
821  *pfract = 0.0;
822  if (!box1 || !box2)
823  return ERROR_INT("boxes not both defined", procName, 1);
824  boxIsValid(box1, &valid1);
825  boxIsValid(box2, &valid2);
826  if (!valid1 || !valid2) {
827  L_WARNING("boxes not both valid\n", procName);
828  return 0;
829  }
830 
831  if ((boxo = boxOverlapRegion(box1, box2)) == NULL) /* no overlap */
832  return 0;
833 
834  boxGetGeometry(box2, NULL, NULL, &w2, &h2);
835  boxGetGeometry(boxo, NULL, NULL, &w, &h);
836  *pfract = (l_float32)(w * h) / (l_float32)(w2 * h2);
837  boxDestroy(&boxo);
838  return 0;
839 }
840 
841 
849 l_ok
851  BOX *box2,
852  l_int32 *parea)
853 {
854 l_int32 w, h, valid1, valid2;
855 BOX *box;
856 
857  PROCNAME("boxOverlapArea");
858 
859  if (!parea)
860  return ERROR_INT("&area not defined", procName, 1);
861  *parea = 0;
862  if (!box1 || !box2)
863  return ERROR_INT("boxes not both defined", procName, 1);
864  boxIsValid(box1, &valid1);
865  boxIsValid(box2, &valid2);
866  if (!valid1 || !valid2)
867  return ERROR_INT("boxes not both valid", procName, 1);
868 
869  if ((box = boxOverlapRegion(box1, box2)) == NULL) /* no overlap */
870  return 0;
871 
872  boxGetGeometry(box, NULL, NULL, &w, &h);
873  *parea = w * h;
874  boxDestroy(&box);
875  return 0;
876 }
877 
878 
913 BOXA *
915  l_int32 op,
916  l_int32 range,
917  l_float32 min_overlap,
918  l_float32 max_ratio,
919  NUMA **pnamap)
920 {
921 l_int32 i, j, n, w, h, area1, area2, val;
922 l_int32 overlap_area;
923 l_float32 overlap_ratio, area_ratio;
924 BOX *box1, *box2, *box3;
925 BOXA *boxat, *boxad;
926 NUMA *namap;
927 
928  PROCNAME("boxaHandleOverlaps");
929 
930  if (pnamap) *pnamap = NULL;
931  if (!boxas)
932  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
933  if (op != L_COMBINE && op != L_REMOVE_SMALL)
934  return (BOXA *)ERROR_PTR("invalid op", procName, NULL);
935 
936  n = boxaGetCount(boxas);
937  if (n == 0)
938  return boxaCreate(1); /* empty */
939  if (range == 0) {
940  L_WARNING("range is 0\n", procName);
941  return boxaCopy(boxas, L_COPY);
942  }
943 
944  /* Identify smaller boxes in overlap pairs, and mark to eliminate. */
945  namap = numaMakeConstant(-1, n);
946  for (i = 0; i < n; i++) {
947  if ((box1 = boxaGetValidBox(boxas, i, L_CLONE)) == NULL)
948  continue;
949  boxGetGeometry(box1, NULL, NULL, &w, &h);
950  area1 = w * h;
951  if (area1 == 0) {
952  boxDestroy(&box1);
953  continue;
954  }
955  for (j = i + 1; j < i + 1 + range && j < n; j++) {
956  if ((box2 = boxaGetValidBox(boxas, j, L_CLONE)) == NULL)
957  continue;
958  boxOverlapArea(box1, box2, &overlap_area);
959  if (overlap_area > 0) {
960  boxGetGeometry(box2, NULL, NULL, &w, &h);
961  area2 = w * h;
962  if (area2 == 0) {
963  /* do nothing */
964  } else if (area1 >= area2) {
965  overlap_ratio = (l_float32)overlap_area / (l_float32)area2;
966  area_ratio = (l_float32)area2 / (l_float32)area1;
967  if (overlap_ratio >= min_overlap &&
968  area_ratio <= max_ratio) {
969  numaSetValue(namap, j, i);
970  }
971  } else {
972  overlap_ratio = (l_float32)overlap_area / (l_float32)area1;
973  area_ratio = (l_float32)area1 / (l_float32)area2;
974  if (overlap_ratio >= min_overlap &&
975  area_ratio <= max_ratio) {
976  numaSetValue(namap, i, j);
977  }
978  }
979  }
980  boxDestroy(&box2);
981  }
982  boxDestroy(&box1);
983  }
984 
985  boxat = boxaCopy(boxas, L_COPY);
986  if (op == L_COMBINE) {
987  /* Resize the larger of the pair to the bounding region */
988  for (i = 0; i < n; i++) {
989  numaGetIValue(namap, i, &val);
990  if (val >= 0) {
991  box1 = boxaGetBox(boxas, i, L_CLONE); /* smaller */
992  box2 = boxaGetBox(boxas, val, L_CLONE); /* larger */
993  box3 = boxBoundingRegion(box1, box2);
994  boxaReplaceBox(boxat, val, box3);
995  boxDestroy(&box1);
996  boxDestroy(&box2);
997  }
998  }
999  }
1000 
1001  /* Remove the smaller of the pairs */
1002  boxad = boxaCreate(n);
1003  for (i = 0; i < n; i++) {
1004  numaGetIValue(namap, i, &val);
1005  if (val == -1) {
1006  box1 = boxaGetBox(boxat, i, L_COPY);
1007  boxaAddBox(boxad, box1, L_INSERT);
1008  }
1009  }
1010  boxaDestroy(&boxat);
1011  if (pnamap)
1012  *pnamap = namap;
1013  else
1014  numaDestroy(&namap);
1015  return boxad;
1016 }
1017 
1018 
1043 l_ok
1045  BOX *box2,
1046  l_int32 *ph_ovl,
1047  l_int32 *pv_ovl)
1048 {
1049 l_int32 l1, t1, w1, h1, r1, b1, l2, t2, w2, h2, r2, b2, valid1, valid2;
1050 
1051  PROCNAME("boxOverlapDistance");
1052 
1053  if (!ph_ovl && !pv_ovl)
1054  return ERROR_INT("nothing to do", procName, 1);
1055  if (ph_ovl) *ph_ovl = 0;
1056  if (pv_ovl) *pv_ovl = 0;
1057  if (!box1 || !box2)
1058  return ERROR_INT("boxes not both defined", procName, 1);
1059  boxIsValid(box1, &valid1);
1060  boxIsValid(box2, &valid2);
1061  if (!valid1 || !valid2)
1062  return ERROR_INT("boxes not both valid", procName, 1);
1063 
1064  if (ph_ovl) {
1065  boxGetGeometry(box1, &l1, NULL, &w1, NULL);
1066  boxGetGeometry(box2, &l2, NULL, &w2, NULL);
1067  r1 = l1 + w1; /* 1 pixel to the right of box 1 */
1068  r2 = l2 + w2;
1069  if (l2 >= l1)
1070  *ph_ovl = r1 - l2;
1071  else
1072  *ph_ovl = r2 - l1;
1073  }
1074  if (pv_ovl) {
1075  boxGetGeometry(box1, NULL, &t1, NULL, &h1);
1076  boxGetGeometry(box2, NULL, &t2, NULL, &h2);
1077  b1 = t1 + h1; /* 1 pixel below box 1 */
1078  b2 = t2 + h2;
1079  if (t2 >= t1)
1080  *pv_ovl = b1 - t2;
1081  else
1082  *pv_ovl = b2 - t1;
1083  }
1084  return 0;
1085 }
1086 
1087 
1116 l_ok
1118  BOX *box2,
1119  l_int32 *ph_sep,
1120  l_int32 *pv_sep)
1121 {
1122 l_int32 h_ovl, v_ovl, valid1, valid2;
1123 
1124  PROCNAME("boxSeparationDistance");
1125 
1126  if (ph_sep) *ph_sep = 0;
1127  if (pv_sep) *pv_sep = 0;
1128  if (!ph_sep || !pv_sep)
1129  return ERROR_INT("&h_sep and &v_sep not both defined", procName, 1);
1130  if (!box1 || !box2)
1131  return ERROR_INT("boxes not both defined", procName, 1);
1132  boxIsValid(box1, &valid1);
1133  boxIsValid(box2, &valid2);
1134  if (!valid1 || !valid2)
1135  return ERROR_INT("boxes not both valid", procName, 1);
1136 
1137  boxOverlapDistance(box1, box2, &h_ovl, &v_ovl);
1138  if (h_ovl <= 0)
1139  *ph_sep = -h_ovl + 1;
1140  if (v_ovl <= 0)
1141  *pv_sep = -v_ovl + 1;
1142  return 0;
1143 }
1144 
1145 
1161 l_ok
1163  BOX *box2,
1164  l_int32 type,
1165  l_int32 *prel)
1166 {
1167 l_int32 w1, h1, w2, h2, size1, size2, valid1, valid2;
1168 
1169  PROCNAME("boxCompareSize");
1170 
1171  if (!prel)
1172  return ERROR_INT("&rel not defined", procName, 1);
1173  *prel = 0;
1174  if (!box1 || !box2)
1175  return ERROR_INT("boxes not both defined", procName, 1);
1176  boxIsValid(box1, &valid1);
1177  boxIsValid(box2, &valid2);
1178  if (!valid1 || !valid2)
1179  return ERROR_INT("boxes not both valid", procName, 1);
1180  if (type != L_SORT_BY_WIDTH && type != L_SORT_BY_HEIGHT &&
1181  type != L_SORT_BY_MAX_DIMENSION && type != L_SORT_BY_PERIMETER &&
1182  type != L_SORT_BY_AREA)
1183  return ERROR_INT("invalid compare type", procName, 1);
1184 
1185  boxGetGeometry(box1, NULL, NULL, &w1, &h1);
1186  boxGetGeometry(box2, NULL, NULL, &w2, &h2);
1187  if (type == L_SORT_BY_WIDTH) {
1188  *prel = (w1 > w2) ? 1 : ((w1 == w2) ? 0 : -1);
1189  } else if (type == L_SORT_BY_HEIGHT) {
1190  *prel = (h1 > h2) ? 1 : ((h1 == h2) ? 0 : -1);
1191  } else if (type == L_SORT_BY_MAX_DIMENSION) {
1192  size1 = L_MAX(w1, h1);
1193  size2 = L_MAX(w2, h2);
1194  *prel = (size1 > size2) ? 1 : ((size1 == size2) ? 0 : -1);
1195  } else if (type == L_SORT_BY_PERIMETER) {
1196  size1 = w1 + h1;
1197  size2 = w2 + h2;
1198  *prel = (size1 > size2) ? 1 : ((size1 == size2) ? 0 : -1);
1199  } else if (type == L_SORT_BY_AREA) {
1200  size1 = w1 * h1;
1201  size2 = w2 * h2;
1202  *prel = (size1 > size2) ? 1 : ((size1 == size2) ? 0 : -1);
1203  }
1204  return 0;
1205 }
1206 
1207 
1216 l_ok
1218  l_float32 x,
1219  l_float32 y,
1220  l_int32 *pcontains)
1221 {
1222 l_int32 bx, by, bw, bh;
1223 
1224  PROCNAME("boxContainsPt");
1225 
1226  if (!pcontains)
1227  return ERROR_INT("&contains not defined", procName, 1);
1228  *pcontains = 0;
1229  if (!box)
1230  return ERROR_INT("&box not defined", procName, 1);
1231  boxGetGeometry(box, &bx, &by, &bw, &bh);
1232  if (x >= bx && x < bx + bw && y >= by && y < by + bh)
1233  *pcontains = 1;
1234  return 0;
1235 }
1236 
1237 
1251 BOX *
1253  l_int32 x,
1254  l_int32 y)
1255 {
1256 l_int32 i, n, minindex;
1257 l_float32 delx, dely, dist, mindist, cx, cy;
1258 BOX *box;
1259 
1260  PROCNAME("boxaGetNearestToPt");
1261 
1262  if (!boxa)
1263  return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
1264  if ((n = boxaGetCount(boxa)) == 0)
1265  return (BOX *)ERROR_PTR("n = 0", procName, NULL);
1266 
1267  mindist = 1000000000.;
1268  minindex = 0;
1269  for (i = 0; i < n; i++) {
1270  if ((box = boxaGetValidBox(boxa, i, L_CLONE)) == NULL)
1271  continue;
1272  boxGetCenter(box, &cx, &cy);
1273  delx = (l_float32)(cx - x);
1274  dely = (l_float32)(cy - y);
1275  dist = delx * delx + dely * dely;
1276  if (dist < mindist) {
1277  minindex = i;
1278  mindist = dist;
1279  }
1280  boxDestroy(&box);
1281  }
1282 
1283  return boxaGetBox(boxa, minindex, L_COPY);
1284 }
1285 
1286 
1304 BOX *
1306  l_int32 x,
1307  l_int32 y)
1308 {
1309 l_int32 i, n, minindex;
1310 l_float32 dist, mindist, cx, cy;
1311 BOX *box;
1312 
1313  PROCNAME("boxaGetNearestToLine");
1314 
1315  if (!boxa)
1316  return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
1317  if ((n = boxaGetCount(boxa)) == 0)
1318  return (BOX *)ERROR_PTR("n = 0", procName, NULL);
1319  if (y >= 0 && x >= 0)
1320  return (BOX *)ERROR_PTR("either x or y must be < 0", procName, NULL);
1321  if (y < 0 && x < 0)
1322  return (BOX *)ERROR_PTR("either x or y must be >= 0", procName, NULL);
1323 
1324  mindist = 1000000000.;
1325  minindex = 0;
1326  for (i = 0; i < n; i++) {
1327  if ((box = boxaGetValidBox(boxa, i, L_CLONE)) == NULL)
1328  continue;
1329  boxGetCenter(box, &cx, &cy);
1330  if (x >= 0)
1331  dist = L_ABS(cx - (l_float32)x);
1332  else /* y >= 0 */
1333  dist = L_ABS(cy - (l_float32)y);
1334  if (dist < mindist) {
1335  minindex = i;
1336  mindist = dist;
1337  }
1338  boxDestroy(&box);
1339  }
1340 
1341  return boxaGetBox(boxa, minindex, L_COPY);
1342 }
1343 
1344 
1362 l_ok
1364  l_int32 dist_select,
1365  l_int32 range,
1366  NUMAA **pnaaindex,
1367  NUMAA **pnaadist)
1368 {
1369 l_int32 i, n, index, dist;
1370 NUMA *nai, *nad;
1371 NUMAA *naai, *naad;
1372 
1373  PROCNAME("boxaFindNearestBoxes");
1374 
1375  if (pnaaindex) *pnaaindex = NULL;
1376  if (pnaadist) *pnaadist = NULL;
1377  if (!pnaaindex)
1378  return ERROR_INT("&naaindex not defined", procName, 1);
1379  if (!pnaadist)
1380  return ERROR_INT("&naadist not defined", procName, 1);
1381  if (!boxa)
1382  return ERROR_INT("boxa not defined", procName, 1);
1383 
1384  n = boxaGetCount(boxa);
1385  naai = numaaCreate(n);
1386  naad = numaaCreate(n);
1387  *pnaaindex = naai;
1388  *pnaadist = naad;
1389  for (i = 0; i < n; i++) {
1390  nai = numaCreate(4);
1391  nad = numaCreate(4);
1392  boxaGetNearestByDirection(boxa, i, L_FROM_LEFT, dist_select,
1393  range, &index, &dist);
1394  numaAddNumber(nai, index);
1395  numaAddNumber(nad, dist);
1396  boxaGetNearestByDirection(boxa, i, L_FROM_RIGHT, dist_select,
1397  range, &index, &dist);
1398  numaAddNumber(nai, index);
1399  numaAddNumber(nad, dist);
1400  boxaGetNearestByDirection(boxa, i, L_FROM_TOP, dist_select,
1401  range, &index, &dist);
1402  numaAddNumber(nai, index);
1403  numaAddNumber(nad, dist);
1404  boxaGetNearestByDirection(boxa, i, L_FROM_BOT, dist_select,
1405  range, &index, &dist);
1406  numaAddNumber(nai, index);
1407  numaAddNumber(nad, dist);
1408  numaaAddNuma(naai, nai, L_INSERT);
1409  numaaAddNuma(naad, nad, L_INSERT);
1410  }
1411  return 0;
1412 }
1413 
1414 
1443 l_ok
1445  l_int32 i,
1446  l_int32 dir,
1447  l_int32 dist_select,
1448  l_int32 range,
1449  l_int32 *pindex,
1450  l_int32 *pdist)
1451 {
1452 l_int32 j, jmin, jmax, n, mindist, dist, index;
1453 l_int32 x, y, w, h, bx, by, bw, bh;
1454 
1455  PROCNAME("boxaGetNearestByDirection");
1456 
1457  if (pindex) *pindex = -1;
1458  if (pdist) *pdist = 100000;
1459  if (!pindex)
1460  return ERROR_INT("&index not defined", procName, 1);
1461  if (!pdist)
1462  return ERROR_INT("&dist not defined", procName, 1);
1463  if (!boxa)
1464  return ERROR_INT("boxa not defined", procName, 1);
1465  if (dir != L_FROM_LEFT && dir != L_FROM_RIGHT &&
1466  dir != L_FROM_TOP && dir != L_FROM_BOT)
1467  return ERROR_INT("invalid dir", procName, 1);
1468  if (dist_select != L_NON_NEGATIVE && dist_select != L_ALL)
1469  return ERROR_INT("invalid dist_select", procName, 1);
1470  n = boxaGetCount(boxa);
1471  if (i < 0 || i >= n)
1472  return ERROR_INT("invalid box index", procName, 1);
1473 
1474  jmin = (range <= 0) ? 0 : L_MAX(0, i - range);
1475  jmax = (range <= 0) ? n - 1 : L_MIN(n -1, i + range);
1476  boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
1477  mindist = 100000;
1478  index = -1;
1479  if (dir == L_FROM_LEFT || dir == L_FROM_RIGHT) {
1480  for (j = jmin; j <= jmax; j++) {
1481  if (j == i) continue;
1482  boxaGetBoxGeometry(boxa, j, &bx, &by, &bw, &bh);
1483  if ((bx >= x && dir == L_FROM_LEFT) || /* not to the left */
1484  (x >= bx && dir == L_FROM_RIGHT)) /* not to the right */
1485  continue;
1486  if (boxHasOverlapInXorY(y, h, by, bh) == 1) {
1487  dist = boxGetDistanceInXorY(x, w, bx, bw);
1488  if (dist_select == L_NON_NEGATIVE && dist < 0) continue;
1489  if (dist < mindist) {
1490  mindist = dist;
1491  index = j;
1492  }
1493  }
1494  }
1495  } else if (dir == L_FROM_TOP || dir == L_FROM_BOT) {
1496  for (j = jmin; j <= jmax; j++) {
1497  if (j == i) continue;
1498  boxaGetBoxGeometry(boxa, j, &bx, &by, &bw, &bh);
1499  if ((by >= y && dir == L_FROM_TOP) || /* not above */
1500  (y >= by && dir == L_FROM_BOT)) /* not below */
1501  continue;
1502  if (boxHasOverlapInXorY(x, w, bx, bw) == 1) {
1503  dist = boxGetDistanceInXorY(y, h, by, bh);
1504  if (dist_select == L_NON_NEGATIVE && dist < 0) continue;
1505  if (dist < mindist) {
1506  mindist = dist;
1507  index = j;
1508  }
1509  }
1510  }
1511  }
1512  *pindex = index;
1513  *pdist = mindist;
1514  return 0;
1515 }
1516 
1517 
1533 static l_int32
1535  l_int32 s1,
1536  l_int32 c2,
1537  l_int32 s2)
1538 {
1539 l_int32 ovlp;
1540 
1541  if (c1 > c2)
1542  ovlp = c2 + s2 - 1 - c1;
1543  else
1544  ovlp = c1 + s1 - 1 - c2;
1545  return (ovlp < 0) ? 0 : 1;
1546 }
1547 
1548 
1559 static l_int32
1561  l_int32 s1,
1562  l_int32 c2,
1563  l_int32 s2)
1564 {
1565 l_int32 dist;
1566 
1567  if (c1 > c2)
1568  dist = c1 - (c2 + s2 - 1);
1569  else
1570  dist = c2 - (c1 + s1 - 1);
1571  return dist;
1572 }
1573 
1574 
1582 l_ok
1584  l_float32 *pcx,
1585  l_float32 *pcy)
1586 {
1587 l_int32 x, y, w, h;
1588 
1589  PROCNAME("boxGetCenter");
1590 
1591  if (pcx) *pcx = 0;
1592  if (pcy) *pcy = 0;
1593  if (!pcx || !pcy)
1594  return ERROR_INT("&cx, &cy not both defined", procName, 1);
1595  if (!box)
1596  return ERROR_INT("box not defined", procName, 1);
1597  boxGetGeometry(box, &x, &y, &w, &h);
1598  if (w == 0 || h == 0) return 1;
1599  *pcx = (l_float32)(x + 0.5 * w);
1600  *pcy = (l_float32)(y + 0.5 * h);
1601 
1602  return 0;
1603 }
1604 
1605 
1624 l_ok
1626  l_int32 x,
1627  l_int32 y,
1628  l_float32 slope,
1629  l_int32 *px1,
1630  l_int32 *py1,
1631  l_int32 *px2,
1632  l_int32 *py2,
1633  l_int32 *pn)
1634 {
1635 l_int32 bx, by, bw, bh, xp, yp, xt, yt, i, n;
1636 l_float32 invslope;
1637 PTA *pta;
1638 
1639  PROCNAME("boxIntersectByLine");
1640 
1641  if (px1) *px1 = 0;
1642  if (px2) *px2 = 0;
1643  if (py1) *py1 = 0;
1644  if (py2) *py2 = 0;
1645  if (pn) *pn = 0;
1646  if (!px1 || !py1 || !px2 || !py2)
1647  return ERROR_INT("&x1, &y1, &x2, &y2 not all defined", procName, 1);
1648  if (!pn)
1649  return ERROR_INT("&n not defined", procName, 1);
1650  if (!box)
1651  return ERROR_INT("box not defined", procName, 1);
1652  boxGetGeometry(box, &bx, &by, &bw, &bh);
1653  if (bw == 0 || bh == 0) return 1;
1654 
1655  if (slope == 0.0) {
1656  if (y >= by && y < by + bh) {
1657  *py1 = *py2 = y;
1658  *px1 = bx;
1659  *px2 = bx + bw - 1;
1660  }
1661  return 0;
1662  }
1663 
1664  if (slope > 1000000.0) {
1665  if (x >= bx && x < bx + bw) {
1666  *px1 = *px2 = x;
1667  *py1 = by;
1668  *py2 = by + bh - 1;
1669  }
1670  return 0;
1671  }
1672 
1673  /* Intersection with top and bottom lines of box */
1674  pta = ptaCreate(2);
1675  invslope = 1.0 / slope;
1676  xp = (l_int32)(x + invslope * (y - by));
1677  if (xp >= bx && xp < bx + bw)
1678  ptaAddPt(pta, xp, by);
1679  xp = (l_int32)(x + invslope * (y - by - bh + 1));
1680  if (xp >= bx && xp < bx + bw)
1681  ptaAddPt(pta, xp, by + bh - 1);
1682 
1683  /* Intersection with left and right lines of box */
1684  yp = (l_int32)(y + slope * (x - bx));
1685  if (yp >= by && yp < by + bh)
1686  ptaAddPt(pta, bx, yp);
1687  yp = (l_int32)(y + slope * (x - bx - bw + 1));
1688  if (yp >= by && yp < by + bh)
1689  ptaAddPt(pta, bx + bw - 1, yp);
1690 
1691  /* There is a maximum of 2 unique points; remove duplicates. */
1692  n = ptaGetCount(pta);
1693  if (n > 0) {
1694  ptaGetIPt(pta, 0, px1, py1); /* accept the first one */
1695  *pn = 1;
1696  }
1697  for (i = 1; i < n; i++) {
1698  ptaGetIPt(pta, i, &xt, &yt);
1699  if ((*px1 != xt) || (*py1 != yt)) {
1700  *px2 = xt;
1701  *py2 = yt;
1702  *pn = 2;
1703  break;
1704  }
1705  }
1706 
1707  ptaDestroy(&pta);
1708  return 0;
1709 }
1710 
1711 
1727 BOX *
1729  l_int32 wi,
1730  l_int32 hi)
1731 {
1732 BOX *boxd;
1733 
1734  PROCNAME("boxClipToRectangle");
1735 
1736  if (!box)
1737  return (BOX *)ERROR_PTR("box not defined", procName, NULL);
1738  if (box->x >= wi || box->y >= hi ||
1739  box->x + box->w <= 0 || box->y + box->h <= 0)
1740  return (BOX *)ERROR_PTR("box outside rectangle", procName, NULL);
1741 
1742  boxd = boxCopy(box);
1743  if (boxd->x < 0) {
1744  boxd->w += boxd->x;
1745  boxd->x = 0;
1746  }
1747  if (boxd->y < 0) {
1748  boxd->h += boxd->y;
1749  boxd->y = 0;
1750  }
1751  if (boxd->x + boxd->w > wi)
1752  boxd->w = wi - boxd->x;
1753  if (boxd->y + boxd->h > hi)
1754  boxd->h = hi - boxd->y;
1755  return boxd;
1756 }
1757 
1758 
1784 l_ok
1786  l_int32 w,
1787  l_int32 h,
1788  l_int32 *pxstart,
1789  l_int32 *pystart,
1790  l_int32 *pxend,
1791  l_int32 *pyend,
1792  l_int32 *pbw,
1793  l_int32 *pbh)
1794 {
1795 l_int32 bw, bh;
1796 BOX *boxc;
1797 
1798  PROCNAME("boxClipToRectangleParams");
1799 
1800  if (pxstart) *pxstart = 0;
1801  if (pystart) *pystart = 0;
1802  if (pxend) *pxend = w;
1803  if (pyend) *pyend = h;
1804  if (pbw) *pbw = w;
1805  if (pbh) *pbh = h;
1806  if (!pxstart || !pystart || !pxend || !pyend)
1807  return ERROR_INT("invalid ptr input", procName, 1);
1808  if (!box) return 0;
1809 
1810  if ((boxc = boxClipToRectangle(box, w, h)) == NULL)
1811  return ERROR_INT("box outside image", procName, 1);
1812  boxGetGeometry(boxc, pxstart, pystart, &bw, &bh);
1813  boxDestroy(&boxc);
1814 
1815  if (pbw) *pbw = bw;
1816  if (pbh) *pbh = bh;
1817  if (bw == 0 || bh == 0)
1818  return ERROR_INT("invalid clipping box", procName, 1);
1819  *pxend = *pxstart + bw; /* 1 past the end */
1820  *pyend = *pystart + bh; /* 1 past the end */
1821  return 0;
1822 }
1823 
1824 
1846 BOX *
1848  BOX *boxs,
1849  l_int32 loc,
1850  l_int32 sideflag)
1851 {
1852 l_int32 x, y, w, h;
1853 
1854  PROCNAME("boxRelocateOneSide");
1855 
1856  if (!boxs)
1857  return (BOX *)ERROR_PTR("boxs not defined", procName, NULL);
1858  if (!boxd)
1859  boxd = boxCopy(boxs);
1860 
1861  boxGetGeometry(boxs, &x, &y, &w, &h);
1862  if (w == 0 || h == 0)
1863  return boxd;
1864  if (sideflag == L_FROM_LEFT)
1865  boxSetGeometry(boxd, loc, -1, w + x - loc, -1);
1866  else if (sideflag == L_FROM_RIGHT)
1867  boxSetGeometry(boxd, -1, -1, loc - x + 1, -1);
1868  else if (sideflag == L_FROM_TOP)
1869  boxSetGeometry(boxd, -1, loc, -1, h + y - loc);
1870  else if (sideflag == L_FROM_BOT)
1871  boxSetGeometry(boxd, -1, -1, -1, loc - y + 1);
1872  return boxd;
1873 }
1874 
1875 
1892 BOXA *
1894  l_int32 delleft,
1895  l_int32 delright,
1896  l_int32 deltop,
1897  l_int32 delbot)
1898 {
1899 l_int32 n, i, x, y;
1900 BOX *box1, *box2;
1901 BOXA *boxad;
1902 
1903  PROCNAME("boxaAdjustSides");
1904 
1905  if (!boxas)
1906  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
1907 
1908  n = boxaGetCount(boxas);
1909  boxad = boxaCreate(n);
1910  for (i = 0; i < n; i++) {
1911  box1 = boxaGetBox(boxas, i, L_COPY);
1912  box2 = boxAdjustSides(NULL, box1, delleft, delright, deltop, delbot);
1913  if (!box2) {
1914  boxGetGeometry(box1, &x, &y, NULL, NULL);
1915  box2 = boxCreate(x, y, 1, 1);
1916  }
1917  boxaAddBox(boxad, box2, L_INSERT);
1918  boxDestroy(&box1);
1919  }
1920 
1921  return boxad;
1922 }
1923 
1924 
1942 l_ok
1944  l_int32 index,
1945  l_int32 delleft,
1946  l_int32 delright,
1947  l_int32 deltop,
1948  l_int32 delbot)
1949 {
1950 BOX *box;
1951 
1952  PROCNAME("boxaAdjustBoxSides");
1953 
1954  if (!boxa)
1955  return ERROR_INT("boxa not defined", procName, 1);
1956 
1957  if ((box = boxaGetBox(boxa, index, L_CLONE)) == NULL)
1958  return ERROR_INT("invalid index", procName, 1);
1959 
1960  boxAdjustSides(box, box, delleft, delright, deltop, delbot);
1961  boxDestroy(&box); /* the clone */
1962  return 0;
1963 }
1964 
1965 
1990 BOX *
1992  BOX *boxs,
1993  l_int32 delleft,
1994  l_int32 delright,
1995  l_int32 deltop,
1996  l_int32 delbot)
1997 {
1998 l_int32 x, y, w, h, xl, xr, yt, yb, wnew, hnew;
1999 
2000  PROCNAME("boxAdjustSides");
2001 
2002  if (!boxs)
2003  return (BOX *)ERROR_PTR("boxs not defined", procName, NULL);
2004 
2005  boxGetGeometry(boxs, &x, &y, &w, &h);
2006  xl = L_MAX(0, x + delleft);
2007  yt = L_MAX(0, y + deltop);
2008  xr = x + w + delright; /* one pixel beyond right edge */
2009  yb = y + h + delbot; /* one pixel below bottom edge */
2010  wnew = xr - xl;
2011  hnew = yb - yt;
2012 
2013  if (wnew < 1 || hnew < 1)
2014  return (BOX *)ERROR_PTR("boxd has 0 area", procName, NULL);
2015  if (!boxd)
2016  return boxCreate(xl, yt, wnew, hnew);
2017 
2018  boxSetGeometry(boxd, xl, yt, wnew, hnew);
2019  return boxd;
2020 }
2021 
2022 
2042 BOXA *
2044  BOXA *boxas,
2045  l_int32 side,
2046  l_int32 val,
2047  l_int32 thresh)
2048 {
2049 l_int32 n, i;
2050 BOX *box;
2051 
2052  PROCNAME("boxaSetSide");
2053 
2054  if (!boxas)
2055  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
2056  if (boxad && (boxas != boxad))
2057  return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
2058  if (side != L_SET_LEFT && side != L_SET_RIGHT &&
2059  side != L_SET_TOP && side != L_SET_BOT)
2060  return (BOXA *)ERROR_PTR("invalid side", procName, NULL);
2061  if (val < 0)
2062  return (BOXA *)ERROR_PTR("val < 0", procName, NULL);
2063 
2064  if (!boxad)
2065  boxad = boxaCopy(boxas, L_COPY);
2066  n = boxaGetCount(boxad);
2067  for (i = 0; i < n; i++) {
2068  box = boxaGetBox(boxad, i, L_CLONE);
2069  boxSetSide(box, side, val, thresh);
2070  boxDestroy(&box); /* the clone */
2071  }
2072 
2073  return boxad;
2074 }
2075 
2076 
2092 l_ok
2094  l_int32 side,
2095  l_int32 val,
2096  l_int32 thresh)
2097 {
2098 l_int32 x, y, w, h, diff;
2099 
2100  PROCNAME("boxSetSide");
2101 
2102  if (!boxs)
2103  return ERROR_INT("box not defined", procName, 1);
2104  if (side != L_SET_LEFT && side != L_SET_RIGHT &&
2105  side != L_SET_TOP && side != L_SET_BOT)
2106  return ERROR_INT("invalid side", procName, 1);
2107  if (val < 0)
2108  return ERROR_INT("val < 0", procName, 1);
2109 
2110  boxGetGeometry(boxs, &x, &y, &w, &h);
2111  if (side == L_SET_LEFT) {
2112  diff = x - val;
2113  if (L_ABS(diff) >= thresh)
2114  boxSetGeometry(boxs, val, y, w + diff, h);
2115  } else if (side == L_SET_RIGHT) {
2116  diff = x + w -1 - val;
2117  if (L_ABS(diff) >= thresh)
2118  boxSetGeometry(boxs, x, y, val - x + 1, h);
2119  } else if (side == L_SET_TOP) {
2120  diff = y - val;
2121  if (L_ABS(diff) >= thresh)
2122  boxSetGeometry(boxs, x, val, w, h + diff);
2123  } else { /* side == L_SET_BOT */
2124  diff = y + h - 1 - val;
2125  if (L_ABS(diff) >= thresh)
2126  boxSetGeometry(boxs, x, y, w, val - y + 1);
2127  }
2128 
2129  return 0;
2130 }
2131 
2132 
2154 BOXA *
2156  BOXA *boxas,
2157  l_int32 sides,
2158  l_int32 target,
2159  l_int32 thresh)
2160 {
2161 l_int32 x, y, w, h, n, i, diff;
2162 BOX *box;
2163 
2164  PROCNAME("boxaAdjustWidthToTarget");
2165 
2166  if (!boxas)
2167  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
2168  if (boxad && (boxas != boxad))
2169  return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
2170  if (sides != L_ADJUST_LEFT && sides != L_ADJUST_RIGHT &&
2171  sides != L_ADJUST_LEFT_AND_RIGHT)
2172  return (BOXA *)ERROR_PTR("invalid sides", procName, NULL);
2173  if (target < 1)
2174  return (BOXA *)ERROR_PTR("target < 1", procName, NULL);
2175 
2176  if (!boxad)
2177  boxad = boxaCopy(boxas, L_COPY);
2178  n = boxaGetCount(boxad);
2179  for (i = 0; i < n; i++) {
2180  if ((box = boxaGetValidBox(boxad, i, L_CLONE)) == NULL)
2181  continue;
2182  boxGetGeometry(box, &x, &y, &w, &h);
2183  diff = w - target;
2184  if (sides == L_ADJUST_LEFT) {
2185  if (L_ABS(diff) >= thresh)
2186  boxSetGeometry(box, L_MAX(0, x + diff), y, target, h);
2187  } else if (sides == L_ADJUST_RIGHT) {
2188  if (L_ABS(diff) >= thresh)
2189  boxSetGeometry(box, x, y, target, h);
2190  } else { /* sides == L_ADJUST_LEFT_AND_RIGHT */
2191  if (L_ABS(diff) >= thresh)
2192  boxSetGeometry(box, L_MAX(0, x + diff/2), y, target, h);
2193  }
2194  boxDestroy(&box);
2195  }
2196 
2197  return boxad;
2198 }
2199 
2200 
2222 BOXA *
2224  BOXA *boxas,
2225  l_int32 sides,
2226  l_int32 target,
2227  l_int32 thresh)
2228 {
2229 l_int32 x, y, w, h, n, i, diff;
2230 BOX *box;
2231 
2232  PROCNAME("boxaAdjustHeightToTarget");
2233 
2234  if (!boxas)
2235  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
2236  if (boxad && (boxas != boxad))
2237  return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
2238  if (sides != L_ADJUST_TOP && sides != L_ADJUST_BOT &&
2239  sides != L_ADJUST_TOP_AND_BOT)
2240  return (BOXA *)ERROR_PTR("invalid sides", procName, NULL);
2241  if (target < 1)
2242  return (BOXA *)ERROR_PTR("target < 1", procName, NULL);
2243 
2244  if (!boxad)
2245  boxad = boxaCopy(boxas, L_COPY);
2246  n = boxaGetCount(boxad);
2247  for (i = 0; i < n; i++) {
2248  if ((box = boxaGetValidBox(boxad, i, L_CLONE)) == NULL)
2249  continue;
2250  boxGetGeometry(box, &x, &y, &w, &h);
2251  diff = h - target;
2252  if (sides == L_ADJUST_TOP) {
2253  if (L_ABS(diff) >= thresh)
2254  boxSetGeometry(box, x, L_MAX(0, y + diff), w, target);
2255  } else if (sides == L_ADJUST_BOT) {
2256  if (L_ABS(diff) >= thresh)
2257  boxSetGeometry(box, x, y, w, target);
2258  } else { /* sides == L_ADJUST_TOP_AND_BOT */
2259  if (L_ABS(diff) >= thresh)
2260  boxSetGeometry(box, x, L_MAX(0, y + diff/2), w, target);
2261  }
2262  boxDestroy(&box);
2263  }
2264 
2265  return boxad;
2266 }
2267 
2268 
2277 l_ok
2279  BOX *box2,
2280  l_int32 *psame)
2281 {
2282  PROCNAME("boxEqual");
2283 
2284  if (!psame)
2285  return ERROR_INT("&same not defined", procName, 1);
2286  *psame = 0;
2287  if (!box1 || !box2)
2288  return ERROR_INT("boxes not both defined", procName, 1);
2289  if (box1->x == box2->x && box1->y == box2->y &&
2290  box1->w == box2->w && box1->h == box2->h)
2291  *psame = 1;
2292  return 0;
2293 }
2294 
2295 
2324 l_ok
2326  BOXA *boxa2,
2327  l_int32 maxdist,
2328  NUMA **pnaindex,
2329  l_int32 *psame)
2330 {
2331 l_int32 i, j, n, jstart, jend, found, samebox;
2332 l_int32 *countarray;
2333 BOX *box1, *box2;
2334 NUMA *na;
2335 
2336  PROCNAME("boxaEqual");
2337 
2338  if (pnaindex) *pnaindex = NULL;
2339  if (!psame)
2340  return ERROR_INT("&same not defined", procName, 1);
2341  *psame = 0;
2342  if (!boxa1 || !boxa2)
2343  return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
2344  n = boxaGetCount(boxa1);
2345  if (n != boxaGetCount(boxa2))
2346  return 0;
2347 
2348  if ((countarray = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32))) == NULL)
2349  return ERROR_INT("calloc fail for countarray", procName, 1);
2350  na = numaMakeConstant(0.0, n);
2351 
2352  for (i = 0; i < n; i++) {
2353  box1 = boxaGetBox(boxa1, i, L_CLONE);
2354  jstart = L_MAX(0, i - maxdist);
2355  jend = L_MIN(n-1, i + maxdist);
2356  found = FALSE;
2357  for (j = jstart; j <= jend; j++) {
2358  box2 = boxaGetBox(boxa2, j, L_CLONE);
2359  boxEqual(box1, box2, &samebox);
2360  if (samebox && countarray[j] == 0) {
2361  countarray[j] = 1;
2362  numaReplaceNumber(na, i, j);
2363  found = TRUE;
2364  boxDestroy(&box2);
2365  break;
2366  }
2367  boxDestroy(&box2);
2368  }
2369  boxDestroy(&box1);
2370  if (!found) {
2371  numaDestroy(&na);
2372  LEPT_FREE(countarray);
2373  return 0;
2374  }
2375  }
2376 
2377  *psame = 1;
2378  if (pnaindex)
2379  *pnaindex = na;
2380  else
2381  numaDestroy(&na);
2382  LEPT_FREE(countarray);
2383  return 0;
2384 }
2385 
2386 
2403 l_ok
2405  BOX *box2,
2406  l_int32 leftdiff,
2407  l_int32 rightdiff,
2408  l_int32 topdiff,
2409  l_int32 botdiff,
2410  l_int32 *psimilar)
2411 {
2412 l_int32 l1, l2, r1, r2, t1, t2, b1, b2, valid1, valid2;
2413 
2414  PROCNAME("boxSimilar");
2415 
2416  if (!psimilar)
2417  return ERROR_INT("&similar not defined", procName, 1);
2418  *psimilar = 0;
2419  if (!box1 || !box2)
2420  return ERROR_INT("boxes not both defined", procName, 1);
2421  boxIsValid(box1, &valid1);
2422  boxIsValid(box2, &valid2);
2423  if (!valid1 || !valid2)
2424  return ERROR_INT("boxes not both valid", procName, 1);
2425 
2426  boxGetSideLocations(box1, &l1, &r1, &t1, &b1);
2427  boxGetSideLocations(box2, &l2, &r2, &t2, &b2);
2428  if (L_ABS(l1 - l2) > leftdiff)
2429  return 0;
2430  if (L_ABS(r1 - r2) > rightdiff)
2431  return 0;
2432  if (L_ABS(t1 - t2) > topdiff)
2433  return 0;
2434  if (L_ABS(b1 - b2) > botdiff)
2435  return 0;
2436 
2437  *psimilar = 1;
2438  return 0;
2439 }
2440 
2441 
2462 l_ok
2464  BOXA *boxa2,
2465  l_int32 leftdiff,
2466  l_int32 rightdiff,
2467  l_int32 topdiff,
2468  l_int32 botdiff,
2469  l_int32 debug,
2470  l_int32 *psimilar,
2471  NUMA **pnasim)
2472 {
2473 l_int32 i, n1, n2, match, mismatch;
2474 BOX *box1, *box2;
2475 
2476  PROCNAME("boxaSimilar");
2477 
2478  if (psimilar) *psimilar = 0;
2479  if (pnasim) *pnasim = NULL;
2480  if (!boxa1 || !boxa2)
2481  return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
2482  if (!psimilar)
2483  return ERROR_INT("&similar not defined", procName, 1);
2484  n1 = boxaGetCount(boxa1);
2485  n2 = boxaGetCount(boxa2);
2486  if (n1 != n2) {
2487  L_ERROR("boxa counts differ: %d vs %d\n", procName, n1, n2);
2488  return 1;
2489  }
2490  if (pnasim) *pnasim = numaCreate(n1);
2491 
2492  mismatch = FALSE;
2493  for (i = 0; i < n1; i++) {
2494  box1 = boxaGetBox(boxa1, i, L_CLONE);
2495  box2 = boxaGetBox(boxa2, i, L_CLONE);
2496  boxSimilar(box1, box2, leftdiff, rightdiff, topdiff, botdiff,
2497  &match);
2498  boxDestroy(&box1);
2499  boxDestroy(&box2);
2500  if (pnasim)
2501  numaAddNumber(*pnasim, match);
2502  if (!match) {
2503  mismatch = TRUE;
2504  if (!debug && pnasim == NULL)
2505  return 0;
2506  else if (debug)
2507  L_INFO("box %d not similar\n", procName, i);
2508  }
2509  }
2510 
2511  if (!mismatch) *psimilar = 1;
2512  return 0;
2513 }
2514 
2515 
2516 /*----------------------------------------------------------------------*
2517  * Boxa combine and split *
2518  *----------------------------------------------------------------------*/
2536 l_ok
2538  BOXA *boxas,
2539  l_int32 istart,
2540  l_int32 iend)
2541 {
2542 l_int32 n, i;
2543 BOX *box;
2544 
2545  PROCNAME("boxaJoin");
2546 
2547  if (!boxad)
2548  return ERROR_INT("boxad not defined", procName, 1);
2549  if (!boxas || ((n = boxaGetCount(boxas)) == 0))
2550  return 0;
2551 
2552  if (istart < 0)
2553  istart = 0;
2554  if (iend < 0 || iend >= n)
2555  iend = n - 1;
2556  if (istart > iend)
2557  return ERROR_INT("istart > iend; nothing to add", procName, 1);
2558 
2559  for (i = istart; i <= iend; i++) {
2560  box = boxaGetBox(boxas, i, L_CLONE);
2561  boxaAddBox(boxad, box, L_INSERT);
2562  }
2563 
2564  return 0;
2565 }
2566 
2567 
2585 l_ok
2587  BOXAA *baas,
2588  l_int32 istart,
2589  l_int32 iend)
2590 {
2591 l_int32 n, i;
2592 BOXA *boxa;
2593 
2594  PROCNAME("boxaaJoin");
2595 
2596  if (!baad)
2597  return ERROR_INT("baad not defined", procName, 1);
2598  if (!baas)
2599  return 0;
2600 
2601  if (istart < 0)
2602  istart = 0;
2603  n = boxaaGetCount(baas);
2604  if (iend < 0 || iend >= n)
2605  iend = n - 1;
2606  if (istart > iend)
2607  return ERROR_INT("istart > iend; nothing to add", procName, 1);
2608 
2609  for (i = istart; i <= iend; i++) {
2610  boxa = boxaaGetBoxa(baas, i, L_CLONE);
2611  boxaaAddBoxa(baad, boxa, L_INSERT);
2612  }
2613 
2614  return 0;
2615 }
2616 
2617 
2635 l_ok
2637  l_int32 fillflag,
2638  BOXA **pboxae,
2639  BOXA **pboxao)
2640 {
2641 l_int32 i, n;
2642 BOX *box, *box1;
2643 
2644  PROCNAME("boxaSplitEvenOdd");
2645 
2646  if (pboxae) *pboxae = NULL;
2647  if (pboxao) *pboxao = NULL;
2648  if (!pboxae || !pboxao)
2649  return ERROR_INT("&boxae and &boxao not both defined", procName, 1);
2650  if (!boxa)
2651  return ERROR_INT("boxa not defined", procName, 1);
2652 
2653  n = boxaGetCount(boxa);
2654  *pboxae = boxaCreate(n);
2655  *pboxao = boxaCreate(n);
2656  if (fillflag == 0) {
2657  /* don't fill with invalid boxes; end up with half-size boxa */
2658  for (i = 0; i < n; i++) {
2659  box = boxaGetBox(boxa, i, L_COPY);
2660  if ((i & 1) == 0)
2661  boxaAddBox(*pboxae, box, L_INSERT);
2662  else
2663  boxaAddBox(*pboxao, box, L_INSERT);
2664  }
2665  } else {
2666  for (i = 0; i < n; i++) {
2667  box = boxaGetBox(boxa, i, L_COPY);
2668  box1 = boxCreate(0, 0, 0, 0); /* empty placeholder */
2669  if ((i & 1) == 0) {
2670  boxaAddBox(*pboxae, box, L_INSERT);
2671  boxaAddBox(*pboxao, box1, L_INSERT);
2672  } else {
2673  boxaAddBox(*pboxae, box1, L_INSERT);
2674  boxaAddBox(*pboxao, box, L_INSERT);
2675  }
2676  }
2677  }
2678  return 0;
2679 }
2680 
2681 
2699 BOXA *
2701  BOXA *boxao,
2702  l_int32 fillflag)
2703 {
2704 l_int32 i, n, ne, no;
2705 BOX *box;
2706 BOXA *boxad;
2707 
2708  PROCNAME("boxaMergeEvenOdd");
2709 
2710  if (!boxae || !boxao)
2711  return (BOXA *)ERROR_PTR("boxae and boxao not defined", procName, NULL);
2712  ne = boxaGetCount(boxae);
2713  no = boxaGetCount(boxao);
2714  if (ne < no || ne > no + 1)
2715  return (BOXA *)ERROR_PTR("boxa sizes invalid", procName, NULL);
2716 
2717  boxad = boxaCreate(ne);
2718  if (fillflag == 0) { /* both are approx. half-sized; all valid boxes */
2719  n = ne + no;
2720  for (i = 0; i < n; i++) {
2721  if ((i & 1) == 0)
2722  box = boxaGetBox(boxae, i / 2, L_COPY);
2723  else
2724  box = boxaGetBox(boxao, i / 2, L_COPY);
2725  boxaAddBox(boxad, box, L_INSERT);
2726  }
2727  } else { /* both are full size and have invalid placeholders */
2728  for (i = 0; i < ne; i++) {
2729  if ((i & 1) == 0)
2730  box = boxaGetBox(boxae, i, L_COPY);
2731  else
2732  box = boxaGetBox(boxao, i, L_COPY);
2733  boxaAddBox(boxad, box, L_INSERT);
2734  }
2735  }
2736  return boxad;
2737 }
BOXA * boxaSaveValid(BOXA *boxas, l_int32 copyflag)
boxaSaveValid()
Definition: boxbasic.c:1116
BOXA * boxaCopy(BOXA *boxa, l_int32 copyflag)
boxaCopy()
Definition: boxbasic.c:537
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
l_ok boxGetSideLocations(BOX *box, l_int32 *pl, l_int32 *pr, l_int32 *pt, l_int32 *pb)
boxGetSideLocations()
Definition: boxbasic.c:374
l_ok boxaReplaceBox(BOXA *boxa, l_int32 index, BOX *box)
boxaReplaceBox()
Definition: boxbasic.c:962
l_int32 boxaaGetCount(BOXAA *baa)
boxaaGetCount()
Definition: boxbasic.c:1454
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:879
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:734
l_ok boxaaAddBoxa(BOXAA *baa, BOXA *ba, l_int32 copyflag)
boxaaAddBoxa()
Definition: boxbasic.c:1346
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:313
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:620
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:583
l_ok boxIsValid(BOX *box, l_int32 *pvalid)
boxIsValid()
Definition: boxbasic.c:475
l_ok boxSetGeometry(BOX *box, l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxSetGeometry()
Definition: boxbasic.c:343
BOX * boxaGetValidBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetValidBox()
Definition: boxbasic.c:818
BOXA * boxaaGetBoxa(BOXAA *baa, l_int32 index, l_int32 accessflag)
boxaaGetBoxa()
Definition: boxbasic.c:1501
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
BOX * boxCopy(BOX *box)
boxCopy()
Definition: boxbasic.c:235
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:502
BOX * boxaGetNearestToLine(BOXA *boxa, l_int32 x, l_int32 y)
boxaGetNearestToLine()
Definition: boxfunc1.c:1305
l_ok boxEqual(BOX *box1, BOX *box2, l_int32 *psame)
boxEqual()
Definition: boxfunc1.c:2278
l_ok boxCompareSize(BOX *box1, BOX *box2, l_int32 type, l_int32 *prel)
boxCompareSize()
Definition: boxfunc1.c:1162
BOX * boxaGetNearestToPt(BOXA *boxa, l_int32 x, l_int32 y)
boxaGetNearestToPt()
Definition: boxfunc1.c:1252
BOX * boxRelocateOneSide(BOX *boxd, BOX *boxs, l_int32 loc, l_int32 sideflag)
boxRelocateOneSide()
Definition: boxfunc1.c:1847
BOXA * boxaMergeEvenOdd(BOXA *boxae, BOXA *boxao, l_int32 fillflag)
boxaMergeEvenOdd()
Definition: boxfunc1.c:2700
BOXA * boxaContainedInBox(BOXA *boxas, BOX *box)
boxaContainedInBox()
Definition: boxfunc1.c:188
l_ok boxGetCenter(BOX *box, l_float32 *pcx, l_float32 *pcy)
boxGetCenter()
Definition: boxfunc1.c:1583
BOXA * boxaSetSide(BOXA *boxad, BOXA *boxas, l_int32 side, l_int32 val, l_int32 thresh)
boxaSetSide()
Definition: boxfunc1.c:2043
l_ok boxaGetNearestByDirection(BOXA *boxa, l_int32 i, l_int32 dir, l_int32 dist_select, l_int32 range, l_int32 *pindex, l_int32 *pdist)
boxaGetNearestByDirection()
Definition: boxfunc1.c:1444
BOXA * boxaAdjustHeightToTarget(BOXA *boxad, BOXA *boxas, l_int32 sides, l_int32 target, l_int32 thresh)
boxaAdjustHeightToTarget()
Definition: boxfunc1.c:2223
BOX * boxClipToRectangle(BOX *box, l_int32 wi, l_int32 hi)
boxClipToRectangle()
Definition: boxfunc1.c:1728
l_ok boxaEqual(BOXA *boxa1, BOXA *boxa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame)
boxaEqual()
Definition: boxfunc1.c:2325
l_ok boxaAdjustBoxSides(BOXA *boxa, l_int32 index, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxaAdjustBoxSides()
Definition: boxfunc1.c:1943
l_ok boxaJoin(BOXA *boxad, BOXA *boxas, l_int32 istart, l_int32 iend)
boxaJoin()
Definition: boxfunc1.c:2537
BOXA * boxaIntersectsBox(BOXA *boxas, BOX *box)
boxaIntersectsBox()
Definition: boxfunc1.c:331
l_ok boxaCombineOverlapsInPair(BOXA *boxas1, BOXA *boxas2, BOXA **pboxad1, BOXA **pboxad2, PIXA *pixadb)
boxaCombineOverlapsInPair()
Definition: boxfunc1.c:572
l_ok boxOverlapDistance(BOX *box1, BOX *box2, l_int32 *ph_ovl, l_int32 *pv_ovl)
boxOverlapDistance()
Definition: boxfunc1.c:1044
l_ok boxSimilar(BOX *box1, BOX *box2, l_int32 leftdiff, l_int32 rightdiff, l_int32 topdiff, l_int32 botdiff, l_int32 *psimilar)
boxSimilar()
Definition: boxfunc1.c:2404
l_ok boxIntersects(BOX *box1, BOX *box2, l_int32 *presult)
boxIntersects()
Definition: boxfunc1.c:141
l_ok boxaContainedInBoxa(BOXA *boxa1, BOXA *boxa2, l_int32 *pcontained)
boxaContainedInBoxa()
Definition: boxfunc1.c:276
l_ok boxaFindNearestBoxes(BOXA *boxa, l_int32 dist_select, l_int32 range, NUMAA **pnaaindex, NUMAA **pnaadist)
boxaFindNearestBoxes()
Definition: boxfunc1.c:1363
l_ok boxaSimilar(BOXA *boxa1, BOXA *boxa2, l_int32 leftdiff, l_int32 rightdiff, l_int32 topdiff, l_int32 botdiff, l_int32 debug, l_int32 *psimilar, NUMA **pnasim)
boxaSimilar()
Definition: boxfunc1.c:2463
BOX * boxOverlapRegion(BOX *box1, BOX *box2)
boxOverlapRegion()
Definition: boxfunc1.c:710
BOXA * boxaAdjustSides(BOXA *boxas, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxaAdjustSides()
Definition: boxfunc1.c:1893
BOXA * boxaClipToBox(BOXA *boxas, BOX *box)
boxaClipToBox()
Definition: boxfunc1.c:419
l_ok boxaContainedInBoxCount(BOXA *boxa, BOX *box, l_int32 *pcount)
boxaContainedInBoxCount()
Definition: boxfunc1.c:234
l_ok boxOverlapArea(BOX *box1, BOX *box2, l_int32 *parea)
boxOverlapArea()
Definition: boxfunc1.c:850
l_ok boxaIntersectsBoxCount(BOXA *boxa, BOX *box, l_int32 *pcount)
boxaIntersectsBoxCount()
Definition: boxfunc1.c:372
l_ok boxContains(BOX *box1, BOX *box2, l_int32 *presult)
boxContains()
Definition: boxfunc1.c:106
l_ok boxSetSide(BOX *boxs, l_int32 side, l_int32 val, l_int32 thresh)
boxSetSide()
Definition: boxfunc1.c:2093
static l_int32 boxHasOverlapInXorY(l_int32 c1, l_int32 s1, l_int32 c2, l_int32 s2)
boxHasOverlapInXorY()
Definition: boxfunc1.c:1534
BOXA * boxaHandleOverlaps(BOXA *boxas, l_int32 op, l_int32 range, l_float32 min_overlap, l_float32 max_ratio, NUMA **pnamap)
boxaHandleOverlaps()
Definition: boxfunc1.c:914
l_ok boxIntersectByLine(BOX *box, l_int32 x, l_int32 y, l_float32 slope, l_int32 *px1, l_int32 *py1, l_int32 *px2, l_int32 *py2, l_int32 *pn)
boxIntersectByLine()
Definition: boxfunc1.c:1625
l_ok boxContainsPt(BOX *box, l_float32 x, l_float32 y, l_int32 *pcontains)
boxContainsPt()
Definition: boxfunc1.c:1217
BOX * boxBoundingRegion(BOX *box1, BOX *box2)
boxBoundingRegion()
Definition: boxfunc1.c:760
l_ok boxSeparationDistance(BOX *box1, BOX *box2, l_int32 *ph_sep, l_int32 *pv_sep)
boxSeparationDistance()
Definition: boxfunc1.c:1117
l_ok boxaaJoin(BOXAA *baad, BOXAA *baas, l_int32 istart, l_int32 iend)
boxaaJoin()
Definition: boxfunc1.c:2586
static l_int32 boxGetDistanceInXorY(l_int32 c1, l_int32 s1, l_int32 c2, l_int32 s2)
boxGetDistanceInXorY()
Definition: boxfunc1.c:1560
BOX * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1991
l_ok boxClipToRectangleParams(BOX *box, l_int32 w, l_int32 h, l_int32 *pxstart, l_int32 *pystart, l_int32 *pxend, l_int32 *pyend, l_int32 *pbw, l_int32 *pbh)
boxClipToRectangleParams()
Definition: boxfunc1.c:1785
BOXA * boxaCombineOverlaps(BOXA *boxas, PIXA *pixadb)
boxaCombineOverlaps()
Definition: boxfunc1.c:478
BOXA * boxaAdjustWidthToTarget(BOXA *boxad, BOXA *boxas, l_int32 sides, l_int32 target, l_int32 thresh)
boxaAdjustWidthToTarget()
Definition: boxfunc1.c:2155
l_ok boxOverlapFraction(BOX *box1, BOX *box2, l_float32 *pfract)
boxOverlapFraction()
Definition: boxfunc1.c:810
l_ok boxaSplitEvenOdd(BOXA *boxa, l_int32 fillflag, BOXA **pboxae, BOXA **pboxao)
boxaSplitEvenOdd()
Definition: boxfunc1.c:2636
l_ok boxaGetArea(BOXA *boxa, l_int32 *parea)
boxaGetArea()
Definition: boxfunc4.c:1287
l_ok boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition: boxfunc4.c:953
l_ok pixRenderBoxaArb(PIX *pix, BOXA *boxa, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderBoxaArb()
Definition: graphics.c:1772
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
l_ok numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:627
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
NUMAA * numaaCreate(l_int32 n)
numaaCreate()
Definition: numabasic.c:1407
l_ok numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
Definition: numabasic.c:786
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
l_ok numaaAddNuma(NUMAA *naa, NUMA *na, l_int32 copyflag)
numaaAddNuma()
Definition: numabasic.c:1546
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:851
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
@ L_SORT_BY_AREA
Definition: pix.h:744
@ L_SORT_BY_PERIMETER
Definition: pix.h:743
@ L_SORT_BY_WIDTH
Definition: pix.h:739
@ L_SORT_BY_HEIGHT
Definition: pix.h:740
@ L_SORT_BY_MAX_DIMENSION
Definition: pix.h:742
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_INSERT
Definition: pix.h:711
@ L_SET_RIGHT
Definition: pix.h:1060
@ L_SET_LEFT
Definition: pix.h:1059
@ L_ADJUST_LEFT
Definition: pix.h:1051
@ L_SET_BOT
Definition: pix.h:1062
@ L_ADJUST_LEFT_AND_RIGHT
Definition: pix.h:1053
@ L_ADJUST_RIGHT
Definition: pix.h:1052
@ L_ADJUST_BOT
Definition: pix.h:1055
@ L_ADJUST_TOP
Definition: pix.h:1054
@ L_SET_TOP
Definition: pix.h:1061
@ L_ADJUST_TOP_AND_BOT
Definition: pix.h:1056
@ L_FROM_BOT
Definition: pix.h:1037
@ L_FROM_LEFT
Definition: pix.h:1034
@ L_FROM_RIGHT
Definition: pix.h:1035
@ L_FROM_TOP
Definition: pix.h:1036
@ L_REMOVE_SMALL
Definition: pix.h:1088
@ L_COMBINE
Definition: pix.h:1087
@ L_NON_NEGATIVE
Definition: pix.h:956
@ L_ALL
Definition: pix.h:960
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:578
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:343
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:527
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
Definition: pix.h:481
l_int32 y
Definition: pix.h:483
l_int32 x
Definition: pix.h:482
l_int32 w
Definition: pix.h:484
l_int32 h
Definition: pix.h:485
Definition: pix.h:492
Definition: pix.h:502
Definition: array.h:71
Definition: array.h:83
Definition: pix.h:139
Definition: pix.h:456
Definition: pix.h:517