Leptonica  1.73
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 
79 #include "allheaders.h"
80 
81 static l_int32 boxHasOverlapInXorY(l_int32 c1, l_int32 s1, l_int32 c2,
82  l_int32 s2);
83 static l_int32 boxGetDistanceInXorY(l_int32 c1, l_int32 s1, l_int32 c2,
84  l_int32 s2);
85 
86 
87 /*---------------------------------------------------------------------*
88  * Box geometry *
89  *---------------------------------------------------------------------*/
98 l_int32
100  BOX *box2,
101  l_int32 *presult)
102 {
103 l_int32 x1, y1, w1, h1, x2, y2, w2, h2;
104 
105  PROCNAME("boxContains");
106 
107  if (!presult)
108  return ERROR_INT("&result not defined", procName, 1);
109  *presult = 0;
110  if (!box1 || !box2)
111  return ERROR_INT("box1 and box2 not both defined", procName, 1);
112 
113  boxGetGeometry(box1, &x1, &y1, &w1, &h1);
114  boxGetGeometry(box2, &x2, &y2, &w2, &h2);
115  if (x1 <= x2 && y1 <= y2 && (x1 + w1 >= x2 + w2) && (y1 + h1 >= y2 + h2))
116  *presult = 1;
117  return 0;
118 }
119 
120 
129 l_int32
131  BOX *box2,
132  l_int32 *presult)
133 {
134 l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2;
135 
136  PROCNAME("boxIntersects");
137 
138  if (!presult)
139  return ERROR_INT("&result not defined", procName, 1);
140  *presult = 0;
141  if (!box1 || !box2)
142  return ERROR_INT("box1 and box2 not both defined", procName, 1);
143 
144  boxGetGeometry(box1, &l1, &t1, &w1, &h1);
145  boxGetGeometry(box2, &l2, &t2, &w2, &h2);
146  r1 = l1 + w1 - 1;
147  r2 = l2 + w2 - 1;
148  b1 = t1 + h1 - 1;
149  b2 = t2 + h2 - 1;
150  if (b2 < t1 || b1 < t2 || r1 < l2 || r2 < l1)
151  *presult = 0;
152  else
153  *presult = 1;
154  return 0;
155 }
156 
157 
171 BOXA *
173  BOX *box)
174 {
175 l_int32 i, n, val;
176 BOX *boxt;
177 BOXA *boxad;
178 
179  PROCNAME("boxaContainedInBox");
180 
181  if (!boxas)
182  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
183  if (!box)
184  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
185  if ((n = boxaGetCount(boxas)) == 0)
186  return boxaCreate(1); /* empty */
187 
188  boxad = boxaCreate(0);
189  for (i = 0; i < n; i++) {
190  boxt = boxaGetBox(boxas, i, L_CLONE);
191  boxContains(box, boxt, &val);
192  if (val == 1)
193  boxaAddBox(boxad, boxt, L_COPY);
194  boxDestroy(&boxt); /* destroy the clone */
195  }
196 
197  return boxad;
198 }
199 
200 
209 l_int32
211  BOX *box,
212  l_int32 *pcount)
213 {
214 l_int32 i, n, val;
215 BOX *box1;
216 
217  PROCNAME("boxaContainedInBoxCount");
218 
219  if (!pcount)
220  return ERROR_INT("&count not defined", procName, 1);
221  *pcount = 0;
222  if (!boxa)
223  return ERROR_INT("boxa not defined", procName, 1);
224  if (!box)
225  return ERROR_INT("box not defined", procName, 1);
226  if ((n = boxaGetCount(boxa)) == 0)
227  return 0;
228 
229  for (i = 0; i < n; i++) {
230  box1 = boxaGetBox(boxa, i, L_CLONE);
231  boxContains(box, box1, &val);
232  if (val == 1)
233  (*pcount)++;
234  boxDestroy(&box1);
235  }
236  return 0;
237 }
238 
239 
248 l_int32
250  BOXA *boxa2,
251  l_int32 *pcontained)
252 {
253 l_int32 i, j, n1, n2, cont, result;
254 BOX *box1, *box2;
255 
256  PROCNAME("boxaContainedInBoxa");
257 
258  if (!pcontained)
259  return ERROR_INT("&contained not defined", procName, 1);
260  *pcontained = 0;
261  if (!boxa1 || !boxa2)
262  return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
263 
264  n1 = boxaGetCount(boxa1);
265  n2 = boxaGetCount(boxa2);
266  for (i = 0; i < n2; i++) {
267  box2 = boxaGetBox(boxa2, i, L_CLONE);
268  cont = 0;
269  for (j = 0; j < n1; j++) {
270  box1 = boxaGetBox(boxa1, j, L_CLONE);
271  boxContains(box1, box2, &result);
272  boxDestroy(&box1);
273  if (result) {
274  cont = 1;
275  break;
276  }
277  }
278  boxDestroy(&box2);
279  if (!cont) return 0;
280  }
281 
282  *pcontained = 1;
283  return 0;
284 }
285 
286 
301 BOXA *
303  BOX *box)
304 {
305 l_int32 i, n, val;
306 BOX *boxt;
307 BOXA *boxad;
308 
309  PROCNAME("boxaIntersectsBox");
310 
311  if (!boxas)
312  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
313  if (!box)
314  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
315  if ((n = boxaGetCount(boxas)) == 0)
316  return boxaCreate(1); /* empty */
317 
318  boxad = boxaCreate(0);
319  for (i = 0; i < n; i++) {
320  boxt = boxaGetBox(boxas, i, L_CLONE);
321  boxIntersects(box, boxt, &val);
322  if (val == 1)
323  boxaAddBox(boxad, boxt, L_COPY);
324  boxDestroy(&boxt); /* destroy the clone */
325  }
326 
327  return boxad;
328 }
329 
330 
339 l_int32
341  BOX *box,
342  l_int32 *pcount)
343 {
344 l_int32 i, n, val;
345 BOX *box1;
346 
347  PROCNAME("boxaIntersectsBoxCount");
348 
349  if (!pcount)
350  return ERROR_INT("&count not defined", procName, 1);
351  *pcount = 0;
352  if (!boxa)
353  return ERROR_INT("boxa not defined", procName, 1);
354  if (!box)
355  return ERROR_INT("box not defined", procName, 1);
356  if ((n = boxaGetCount(boxa)) == 0)
357  return 0;
358 
359  for (i = 0; i < n; i++) {
360  box1 = boxaGetBox(boxa, i, L_CLONE);
361  boxIntersects(box, box1, &val);
362  if (val == 1)
363  (*pcount)++;
364  boxDestroy(&box1);
365  }
366  return 0;
367 }
368 
369 
384 BOXA *
386  BOX *box)
387 {
388 l_int32 i, n;
389 BOX *boxt, *boxo;
390 BOXA *boxad;
391 
392  PROCNAME("boxaClipToBox");
393 
394  if (!boxas)
395  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
396  if (!box)
397  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
398  if ((n = boxaGetCount(boxas)) == 0)
399  return boxaCreate(1); /* empty */
400 
401  boxad = boxaCreate(0);
402  for (i = 0; i < n; i++) {
403  boxt = boxaGetBox(boxas, i, L_CLONE);
404  if ((boxo = boxOverlapRegion(box, boxt)) != NULL)
405  boxaAddBox(boxad, boxo, L_INSERT);
406  boxDestroy(&boxt);
407  }
408 
409  return boxad;
410 }
411 
412 
441 BOXA *
443  PIXA *pixadb)
444 {
445 l_int32 i, j, w, h, n1, n2, overlap, niters;
446 BOX *box1, *box2, *box3;
447 BOXA *boxa1, *boxa2;
448 PIX *pix1;
449 
450  PROCNAME("boxaCombineOverlaps");
451 
452  if (!boxas)
453  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
454 
455  if (pixadb) boxaGetExtent(boxas, &w, &h, NULL);
456 
457  boxa1 = boxaCopy(boxas, L_COPY);
458  n1 = boxaGetCount(boxa1);
459  niters = 0;
460  while (1) { /* loop until no change from previous iteration */
461  niters++;
462  if (pixadb) {
463  pix1 = pixCreate(w + 5, h + 5, 32);
464  pixSetAll(pix1);
465  pixRenderBoxaArb(pix1, boxa1, 2, 255, 0, 0);
466  pixaAddPix(pixadb, pix1, L_COPY);
467  }
468 
469  /* Combine overlaps for this iteration */
470  for (i = 0; i < n1; i++) {
471  if ((box1 = boxaGetValidBox(boxa1, i, L_COPY)) == NULL)
472  continue;
473  for (j = i + 1; j < n1; j++) {
474  if ((box2 = boxaGetValidBox(boxa1, j, L_COPY)) == NULL)
475  continue;
476  boxIntersects(box1, box2, &overlap);
477  if (overlap) {
478  box3 = boxBoundingRegion(box1, box2);
479  boxaReplaceBox(boxa1, i, box3);
480  boxaReplaceBox(boxa1, j, boxCreate(0, 0, 0, 0));
481  boxDestroy(&box1);
482  box1 = boxCopy(box3);
483  }
484  boxDestroy(&box2);
485  }
486  boxDestroy(&box1);
487  }
488  boxa2 = boxaSaveValid(boxa1, L_COPY);
489  n2 = boxaGetCount(boxa2);
490  boxaDestroy(&boxa1);
491  boxa1 = boxa2;
492  if (n1 == n2) {
493  if (pixadb) pixDestroy(&pix1);
494  break;
495  }
496  n1 = n2;
497  if (pixadb) {
498  pixRenderBoxaArb(pix1, boxa1, 2, 0, 255, 0);
499  pixaAddPix(pixadb, pix1, L_INSERT);
500  }
501  }
502 
503  if (pixadb)
504  L_INFO("number of iterations: %d\n", procName, niters);
505  return boxa1;
506 }
507 
508 
535 l_int32
537  BOXA *boxas2,
538  BOXA **pboxad1,
539  BOXA **pboxad2,
540  PIXA *pixadb)
541 {
542 l_int32 i, j, w, h, w2, h2, n1, n2, n1i, n2i, niters;
543 l_int32 overlap, bigger, area1, area2;
544 BOX *box1, *box2, *box3;
545 BOXA *boxa1, *boxa2, *boxac1, *boxac2;
546 PIX *pix1;
547 
548  PROCNAME("boxaCombineOverlapsInPair");
549 
550  if (pboxad1) *pboxad1 = NULL;
551  if (pboxad2) *pboxad2 = NULL;
552  if (!boxas1 || !boxas2)
553  return ERROR_INT("boxas1 and boxas2 not both defined", procName, 1);
554  if (!pboxad1 || !pboxad2)
555  return ERROR_INT("&boxad1 and &boxad2 not both defined", procName, 1);
556 
557  if (pixadb) {
558  boxaGetExtent(boxas1, &w, &h, NULL);
559  boxaGetExtent(boxas2, &w2, &h2, NULL);
560  w = L_MAX(w, w2);
561  h = L_MAX(h, w2);
562  }
563 
564  /* Let the boxa with the largest area have first crack at the other */
565  boxaGetArea(boxas1, &area1);
566  boxaGetArea(boxas2, &area2);
567  if (area1 >= area2) {
568  boxac1 = boxaCopy(boxas1, L_COPY);
569  boxac2 = boxaCopy(boxas2, L_COPY);
570  } else {
571  boxac1 = boxaCopy(boxas2, L_COPY);
572  boxac2 = boxaCopy(boxas1, L_COPY);
573  }
574 
575  n1i = boxaGetCount(boxac1);
576  n2i = boxaGetCount(boxac2);
577  niters = 0;
578  while (1) {
579  niters++;
580  if (pixadb) {
581  pix1 = pixCreate(w + 5, h + 5, 32);
582  pixSetAll(pix1);
583  pixRenderBoxaArb(pix1, boxac1, 2, 255, 0, 0);
584  pixRenderBoxaArb(pix1, boxac2, 2, 0, 255, 0);
585  pixaAddPix(pixadb, pix1, L_INSERT);
586  }
587 
588  /* First combine boxes in each set */
589  boxa1 = boxaCombineOverlaps(boxac1, NULL);
590  boxa2 = boxaCombineOverlaps(boxac2, NULL);
591 
592  /* Now combine boxes between sets */
593  n1 = boxaGetCount(boxa1);
594  n2 = boxaGetCount(boxa2);
595  for (i = 0; i < n1; i++) { /* 1 eats 2 */
596  if ((box1 = boxaGetValidBox(boxa1, i, L_COPY)) == NULL)
597  continue;
598  for (j = 0; j < n2; j++) {
599  if ((box2 = boxaGetValidBox(boxa2, j, L_COPY)) == NULL)
600  continue;
601  boxIntersects(box1, box2, &overlap);
602  boxCompareSize(box1, box2, L_SORT_BY_AREA, &bigger);
603  if (overlap && (bigger == 1)) {
604  box3 = boxBoundingRegion(box1, box2);
605  boxaReplaceBox(boxa1, i, box3);
606  boxaReplaceBox(boxa2, j, boxCreate(0, 0, 0, 0));
607  boxDestroy(&box1);
608  box1 = boxCopy(box3);
609  }
610  boxDestroy(&box2);
611  }
612  boxDestroy(&box1);
613  }
614  for (i = 0; i < n2; i++) { /* 2 eats 1 */
615  if ((box2 = boxaGetValidBox(boxa2, i, L_COPY)) == NULL)
616  continue;
617  for (j = 0; j < n1; j++) {
618  if ((box1 = boxaGetValidBox(boxa1, j, L_COPY)) == NULL)
619  continue;
620  boxIntersects(box1, box2, &overlap);
621  boxCompareSize(box2, box1, L_SORT_BY_AREA, &bigger);
622  if (overlap && (bigger == 1)) {
623  box3 = boxBoundingRegion(box1, box2);
624  boxaReplaceBox(boxa2, i, box3);
625  boxaReplaceBox(boxa1, j, boxCreate(0, 0, 0, 0));
626  boxDestroy(&box2);
627  box2 = boxCopy(box3);
628  }
629  boxDestroy(&box1);
630  }
631  boxDestroy(&box2);
632  }
633  boxaDestroy(&boxac1);
634  boxaDestroy(&boxac2);
635  boxac1 = boxaSaveValid(boxa1, L_COPY); /* remove invalid boxes */
636  boxac2 = boxaSaveValid(boxa2, L_COPY);
637  boxaDestroy(&boxa1);
638  boxaDestroy(&boxa2);
639  n1 = boxaGetCount(boxac1);
640  n2 = boxaGetCount(boxac2);
641  if (n1 == n1i && n2 == n2i) break;
642  n1i = n1;
643  n2i = n2;
644  if (pixadb) {
645  pix1 = pixCreate(w + 5, h + 5, 32);
646  pixSetAll(pix1);
647  pixRenderBoxaArb(pix1, boxac1, 2, 255, 0, 0);
648  pixRenderBoxaArb(pix1, boxac2, 2, 0, 255, 0);
649  pixaAddPix(pixadb, pix1, L_INSERT);
650  }
651  }
652 
653  if (pixadb)
654  L_INFO("number of iterations: %d\n", procName, niters);
655  *pboxad1 = boxac1;
656  *pboxad2 = boxac2;
657  return 0;
658 }
659 
660 
673 BOX *
675  BOX *box2)
676 {
677 l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2, ld, td, rd, bd;
678 
679  PROCNAME("boxOverlapRegion");
680 
681  if (!box1)
682  return (BOX *)ERROR_PTR("box1 not defined", procName, NULL);
683  if (!box2)
684  return (BOX *)ERROR_PTR("box2 not defined", procName, NULL);
685 
686  boxGetGeometry(box1, &l1, &t1, &w1, &h1);
687  boxGetGeometry(box2, &l2, &t2, &w2, &h2);
688  r1 = l1 + w1 - 1;
689  r2 = l2 + w2 - 1;
690  b1 = t1 + h1 - 1;
691  b2 = t2 + h2 - 1;
692  if (b2 < t1 || b1 < t2 || r1 < l2 || r2 < l1)
693  return NULL;
694 
695  ld = L_MAX(l1, l2);
696  td = L_MAX(t1, t2);
697  rd = L_MIN(r1, r2);
698  bd = L_MIN(b1, b2);
699  return boxCreate(ld, td, rd - ld + 1, bd - td + 1);
700 }
701 
702 
715 BOX *
717  BOX *box2)
718 {
719 l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2, ld, td, rd, bd;
720 
721  PROCNAME("boxBoundingRegion");
722 
723  if (!box1)
724  return (BOX *)ERROR_PTR("box1 not defined", procName, NULL);
725  if (!box2)
726  return (BOX *)ERROR_PTR("box2 not defined", procName, NULL);
727 
728  boxGetGeometry(box1, &l1, &t1, &w1, &h1);
729  boxGetGeometry(box2, &l2, &t2, &w2, &h2);
730  r1 = l1 + w1 - 1;
731  r2 = l2 + w2 - 1;
732  b1 = t1 + h1 - 1;
733  b2 = t2 + h2 - 1;
734  ld = L_MIN(l1, l2);
735  td = L_MIN(t1, t2);
736  rd = L_MAX(r1, r2);
737  bd = L_MAX(b1, b2);
738  return boxCreate(ld, td, rd - ld + 1, bd - td + 1);
739 }
740 
741 
755 l_int32
757  BOX *box2,
758  l_float32 *pfract)
759 {
760 l_int32 w2, h2, w, h;
761 BOX *boxo;
762 
763  PROCNAME("boxOverlapFraction");
764 
765  if (!pfract)
766  return ERROR_INT("&fract not defined", procName, 1);
767  *pfract = 0.0;
768  if (!box1)
769  return ERROR_INT("box1 not defined", procName, 1);
770  if (!box2)
771  return ERROR_INT("box2 not defined", procName, 1);
772 
773  if ((boxo = boxOverlapRegion(box1, box2)) == NULL) /* no overlap */
774  return 0;
775 
776  boxGetGeometry(box2, NULL, NULL, &w2, &h2);
777  boxGetGeometry(boxo, NULL, NULL, &w, &h);
778  *pfract = (l_float32)(w * h) / (l_float32)(w2 * h2);
779  boxDestroy(&boxo);
780  return 0;
781 }
782 
783 
791 l_int32
793  BOX *box2,
794  l_int32 *parea)
795 {
796 l_int32 w, h;
797 BOX *box;
798 
799  PROCNAME("boxOverlapArea");
800 
801  if (!parea)
802  return ERROR_INT("&area not defined", procName, 1);
803  *parea = 0;
804  if (!box1)
805  return ERROR_INT("box1 not defined", procName, 1);
806  if (!box2)
807  return ERROR_INT("box2 not defined", procName, 1);
808 
809  if ((box = boxOverlapRegion(box1, box2)) == NULL) /* no overlap */
810  return 0;
811 
812  boxGetGeometry(box, NULL, NULL, &w, &h);
813  *parea = w * h;
814  boxDestroy(&box);
815  return 0;
816 }
817 
818 
852 BOXA *
854  l_int32 op,
855  l_int32 range,
856  l_float32 min_overlap,
857  l_float32 max_ratio,
858  NUMA **pnamap)
859 {
860 l_int32 i, j, n, w, h, area1, area2, val;
861 l_int32 overlap_area;
862 l_float32 overlap_ratio, area_ratio;
863 BOX *box1, *box2, *box3;
864 BOXA *boxat, *boxad;
865 NUMA *namap;
866 
867  PROCNAME("boxaHandleOverlaps");
868 
869  if (pnamap) *pnamap = NULL;
870  if (!boxas)
871  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
872  if (op != L_COMBINE && op != L_REMOVE_SMALL)
873  return (BOXA *)ERROR_PTR("invalid op", procName, NULL);
874 
875  n = boxaGetCount(boxas);
876  if (n == 0)
877  return boxaCreate(1); /* empty */
878  if (range == 0) {
879  L_WARNING("range is 0\n", procName);
880  return boxaCopy(boxas, L_COPY);
881  }
882 
883  /* Identify smaller boxes in overlap pairs, and mark to eliminate. */
884  namap = numaMakeConstant(-1, n);
885  for (i = 0; i < n; i++) {
886  box1 = boxaGetBox(boxas, i, L_CLONE);
887  boxGetGeometry(box1, NULL, NULL, &w, &h);
888  area1 = w * h;
889  if (area1 == 0) {
890  boxDestroy(&box1);
891  continue;
892  }
893  for (j = i + 1; j < i + 1 + range && j < n; j++) {
894  box2 = boxaGetBox(boxas, j, L_CLONE);
895  boxOverlapArea(box1, box2, &overlap_area);
896  if (overlap_area > 0) {
897  boxGetGeometry(box2, NULL, NULL, &w, &h);
898  area2 = w * h;
899  if (area2 == 0) {
900  /* do nothing */
901  } else if (area1 >= area2) {
902  overlap_ratio = (l_float32)overlap_area / (l_float32)area2;
903  area_ratio = (l_float32)area2 / (l_float32)area1;
904  if (overlap_ratio >= min_overlap &&
905  area_ratio <= max_ratio) {
906  numaSetValue(namap, j, i);
907  }
908  } else {
909  overlap_ratio = (l_float32)overlap_area / (l_float32)area1;
910  area_ratio = (l_float32)area1 / (l_float32)area2;
911  if (overlap_ratio >= min_overlap &&
912  area_ratio <= max_ratio) {
913  numaSetValue(namap, i, j);
914  }
915  }
916  }
917  boxDestroy(&box2);
918  }
919  boxDestroy(&box1);
920  }
921 
922  boxat = boxaCopy(boxas, L_COPY);
923  if (op == L_COMBINE) {
924  /* Resize the larger of the pair to the bounding region */
925  for (i = 0; i < n; i++) {
926  numaGetIValue(namap, i, &val);
927  if (val >= 0) {
928  box1 = boxaGetBox(boxas, i, L_CLONE); /* smaller */
929  box2 = boxaGetBox(boxas, val, L_CLONE); /* larger */
930  box3 = boxBoundingRegion(box1, box2);
931  boxaReplaceBox(boxat, val, box3);
932  boxDestroy(&box1);
933  boxDestroy(&box2);
934  }
935  }
936  }
937 
938  /* Remove the smaller of the pairs */
939  boxad = boxaCreate(n);
940  for (i = 0; i < n; i++) {
941  numaGetIValue(namap, i, &val);
942  if (val == -1) {
943  box1 = boxaGetBox(boxat, i, L_COPY);
944  boxaAddBox(boxad, box1, L_INSERT);
945  }
946  }
947  boxaDestroy(&boxat);
948  if (pnamap)
949  *pnamap = namap;
950  else
951  numaDestroy(&namap);
952  return boxad;
953 }
954 
955 
972 l_int32
974  BOX *box2,
975  l_int32 *ph_sep,
976  l_int32 *pv_sep)
977 {
978 l_int32 l1, t1, w1, h1, r1, b1, l2, t2, w2, h2, r2, b2;
979 
980  PROCNAME("boxSeparationDistance");
981 
982  if (!ph_sep && !pv_sep)
983  return ERROR_INT("nothing to do", procName, 1);
984  if (ph_sep) *ph_sep = 0;
985  if (pv_sep) *pv_sep = 0;
986  if (!box1 || !box2)
987  return ERROR_INT("box1 and box2 not both defined", procName, 1);
988 
989  if (ph_sep) {
990  boxGetGeometry(box1, &l1, NULL, &w1, NULL);
991  boxGetGeometry(box2, &l2, NULL, &w2, NULL);
992  r1 = l1 + w1; /* 1 pixel to the right of box 1 */
993  r2 = l2 + w2;
994  if (l2 >= l1)
995  *ph_sep = l2 - r1;
996  else
997  *ph_sep = l1 - r2;
998  }
999  if (pv_sep) {
1000  boxGetGeometry(box1, NULL, &t1, NULL, &h1);
1001  boxGetGeometry(box2, NULL, &t2, NULL, &h2);
1002  b1 = t1 + h1; /* 1 pixel below box 1 */
1003  b2 = t2 + h2;
1004  if (t2 >= t1)
1005  *pv_sep = t2 - b1;
1006  else
1007  *pv_sep = t1 - b2;
1008  }
1009  return 0;
1010 }
1011 
1012 
1028 l_int32
1030  BOX *box2,
1031  l_int32 type,
1032  l_int32 *prel)
1033 {
1034 l_int32 w1, h1, w2, h2, size1, size2;
1035 
1036  PROCNAME("boxCompareSize");
1037 
1038  if (!prel)
1039  return ERROR_INT("&rel not defined", procName, 1);
1040  *prel = 0;
1041  if (!box1 || !box2)
1042  return ERROR_INT("box1 and box2 not both defined", procName, 1);
1043  if (type != L_SORT_BY_WIDTH && type != L_SORT_BY_HEIGHT &&
1044  type != L_SORT_BY_MAX_DIMENSION && type != L_SORT_BY_PERIMETER &&
1045  type != L_SORT_BY_AREA)
1046  return ERROR_INT("invalid compare type", procName, 1);
1047 
1048  boxGetGeometry(box1, NULL, NULL, &w1, &h1);
1049  boxGetGeometry(box2, NULL, NULL, &w2, &h2);
1050  if (type == L_SORT_BY_WIDTH) {
1051  *prel = (w1 > w2) ? 1 : ((w1 == w2) ? 0 : -1);
1052  } else if (type == L_SORT_BY_HEIGHT) {
1053  *prel = (h1 > h2) ? 1 : ((h1 == h2) ? 0 : -1);
1054  } else if (type == L_SORT_BY_MAX_DIMENSION) {
1055  size1 = L_MAX(w1, h1);
1056  size2 = L_MAX(w2, h2);
1057  *prel = (size1 > size2) ? 1 : ((size1 == size2) ? 0 : -1);
1058  } else if (type == L_SORT_BY_PERIMETER) {
1059  size1 = w1 + h1;
1060  size2 = w2 + h2;
1061  *prel = (size1 > size2) ? 1 : ((size1 == size2) ? 0 : -1);
1062  } else if (type == L_SORT_BY_AREA) {
1063  size1 = w1 * h1;
1064  size2 = w2 * h2;
1065  *prel = (size1 > size2) ? 1 : ((size1 == size2) ? 0 : -1);
1066  }
1067  return 0;
1068 }
1069 
1070 
1079 l_int32
1081  l_float32 x,
1082  l_float32 y,
1083  l_int32 *pcontains)
1084 {
1085 l_int32 bx, by, bw, bh;
1086 
1087  PROCNAME("boxContainsPt");
1088 
1089  if (!pcontains)
1090  return ERROR_INT("&contains not defined", procName, 1);
1091  *pcontains = 0;
1092  if (!box)
1093  return ERROR_INT("&box not defined", procName, 1);
1094  boxGetGeometry(box, &bx, &by, &bw, &bh);
1095  if (x >= bx && x < bx + bw && y >= by && y < by + bh)
1096  *pcontains = 1;
1097  return 0;
1098 }
1099 
1100 
1114 BOX *
1116  l_int32 x,
1117  l_int32 y)
1118 {
1119 l_int32 i, n, minindex;
1120 l_float32 delx, dely, dist, mindist, cx, cy;
1121 BOX *box;
1122 
1123  PROCNAME("boxaGetNearestToPt");
1124 
1125  if (!boxa)
1126  return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
1127  if ((n = boxaGetCount(boxa)) == 0)
1128  return (BOX *)ERROR_PTR("n = 0", procName, NULL);
1129 
1130  mindist = 1000000000.;
1131  minindex = 0;
1132  for (i = 0; i < n; i++) {
1133  box = boxaGetBox(boxa, i, L_CLONE);
1134  boxGetCenter(box, &cx, &cy);
1135  delx = (l_float32)(cx - x);
1136  dely = (l_float32)(cy - y);
1137  dist = delx * delx + dely * dely;
1138  if (dist < mindist) {
1139  minindex = i;
1140  mindist = dist;
1141  }
1142  boxDestroy(&box);
1143  }
1144 
1145  return boxaGetBox(boxa, minindex, L_COPY);
1146 }
1147 
1148 
1166 BOX *
1168  l_int32 x,
1169  l_int32 y)
1170 {
1171 l_int32 i, n, minindex;
1172 l_float32 dist, mindist, cx, cy;
1173 BOX *box;
1174 
1175  PROCNAME("boxaGetNearestToLine");
1176 
1177  if (!boxa)
1178  return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
1179  if ((n = boxaGetCount(boxa)) == 0)
1180  return (BOX *)ERROR_PTR("n = 0", procName, NULL);
1181  if (y >= 0 && x >= 0)
1182  return (BOX *)ERROR_PTR("either x or y must be < 0", procName, NULL);
1183  if (y < 0 && x < 0)
1184  return (BOX *)ERROR_PTR("either x or y must be >= 0", procName, NULL);
1185 
1186  mindist = 1000000000.;
1187  minindex = 0;
1188  for (i = 0; i < n; i++) {
1189  box = boxaGetBox(boxa, i, L_CLONE);
1190  boxGetCenter(box, &cx, &cy);
1191  if (x >= 0)
1192  dist = L_ABS(cx - (l_float32)x);
1193  else /* y >= 0 */
1194  dist = L_ABS(cy - (l_float32)y);
1195  if (dist < mindist) {
1196  minindex = i;
1197  mindist = dist;
1198  }
1199  boxDestroy(&box);
1200  }
1201 
1202  return boxaGetBox(boxa, minindex, L_COPY);
1203 }
1204 
1205 
1223 l_int32
1225  l_int32 dist_select,
1226  l_int32 range,
1227  NUMAA **pnaaindex,
1228  NUMAA **pnaadist)
1229 {
1230 l_int32 i, n, index, dist;
1231 NUMA *nai, *nad;
1232 NUMAA *naai, *naad;
1233 
1234  PROCNAME("boxaFindNearestBoxes");
1235 
1236  if (pnaaindex) *pnaaindex = NULL;
1237  if (pnaadist) *pnaadist = NULL;
1238  if (!pnaaindex)
1239  return ERROR_INT("&naaindex not defined", procName, 1);
1240  if (!pnaadist)
1241  return ERROR_INT("&naadist not defined", procName, 1);
1242  if (!boxa)
1243  return ERROR_INT("boxa not defined", procName, 1);
1244 
1245  n = boxaGetCount(boxa);
1246  naai = numaaCreate(n);
1247  naad = numaaCreate(n);
1248  *pnaaindex = naai;
1249  *pnaadist = naad;
1250  for (i = 0; i < n; i++) {
1251  nai = numaCreate(4);
1252  nad = numaCreate(4);
1253  boxaGetNearestByDirection(boxa, i, L_FROM_LEFT, dist_select,
1254  range, &index, &dist);
1255  numaAddNumber(nai, index);
1256  numaAddNumber(nad, dist);
1257  boxaGetNearestByDirection(boxa, i, L_FROM_RIGHT, dist_select,
1258  range, &index, &dist);
1259  numaAddNumber(nai, index);
1260  numaAddNumber(nad, dist);
1261  boxaGetNearestByDirection(boxa, i, L_FROM_TOP, dist_select,
1262  range, &index, &dist);
1263  numaAddNumber(nai, index);
1264  numaAddNumber(nad, dist);
1265  boxaGetNearestByDirection(boxa, i, L_FROM_BOT, dist_select,
1266  range, &index, &dist);
1267  numaAddNumber(nai, index);
1268  numaAddNumber(nad, dist);
1269  numaaAddNuma(naai, nai, L_INSERT);
1270  numaaAddNuma(naad, nad, L_INSERT);
1271  }
1272  return 0;
1273 }
1274 
1275 
1304 l_int32
1306  l_int32 i,
1307  l_int32 dir,
1308  l_int32 dist_select,
1309  l_int32 range,
1310  l_int32 *pindex,
1311  l_int32 *pdist)
1312 {
1313 l_int32 j, jmin, jmax, n, mindist, dist, index;
1314 l_int32 x, y, w, h, bx, by, bw, bh;
1315 
1316  PROCNAME("boxaGetNearestByDirection");
1317 
1318  if (pindex) *pindex = -1;
1319  if (pdist) *pdist = 100000;
1320  if (!pindex)
1321  return ERROR_INT("&index not defined", procName, 1);
1322  if (!pdist)
1323  return ERROR_INT("&dist not defined", procName, 1);
1324  if (!boxa)
1325  return ERROR_INT("boxa not defined", procName, 1);
1326  if (dir != L_FROM_LEFT && dir != L_FROM_RIGHT &&
1327  dir != L_FROM_TOP && dir != L_FROM_BOT)
1328  return ERROR_INT("invalid dir", procName, 1);
1329  if (dist_select != L_NON_NEGATIVE && dist_select != L_ALL)
1330  return ERROR_INT("invalid dist_select", procName, 1);
1331  n = boxaGetCount(boxa);
1332  if (i < 0 || i >= n)
1333  return ERROR_INT("invalid box index", procName, 1);
1334 
1335  jmin = (range <= 0) ? 0 : L_MAX(0, i - range);
1336  jmax = (range <= 0) ? n - 1 : L_MIN(n -1, i + range);
1337  boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
1338  mindist = 100000;
1339  index = -1;
1340  if (dir == L_FROM_LEFT || dir == L_FROM_RIGHT) {
1341  for (j = jmin; j <= jmax; j++) {
1342  if (j == i) continue;
1343  boxaGetBoxGeometry(boxa, j, &bx, &by, &bw, &bh);
1344  if ((bx >= x && dir == L_FROM_LEFT) || /* not to the left */
1345  (x >= bx && dir == L_FROM_RIGHT)) /* not to the right */
1346  continue;
1347  if (boxHasOverlapInXorY(y, h, by, bh) == 1) {
1348  dist = boxGetDistanceInXorY(x, w, bx, bw);
1349  if (dist_select == L_NON_NEGATIVE && dist < 0) continue;
1350  if (dist < mindist) {
1351  mindist = dist;
1352  index = j;
1353  }
1354  }
1355  }
1356  } else if (dir == L_FROM_TOP || dir == L_FROM_BOT) {
1357  for (j = jmin; j <= jmax; j++) {
1358  if (j == i) continue;
1359  boxaGetBoxGeometry(boxa, j, &bx, &by, &bw, &bh);
1360  if ((by >= y && dir == L_FROM_TOP) || /* not above */
1361  (y >= by && dir == L_FROM_BOT)) /* not below */
1362  continue;
1363  if (boxHasOverlapInXorY(x, w, bx, bw) == 1) {
1364  dist = boxGetDistanceInXorY(y, h, by, bh);
1365  if (dist_select == L_NON_NEGATIVE && dist < 0) continue;
1366  if (dist < mindist) {
1367  mindist = dist;
1368  index = j;
1369  }
1370  }
1371  }
1372  }
1373  *pindex = index;
1374  *pdist = mindist;
1375  return 0;
1376 }
1377 
1378 
1394 static l_int32
1396  l_int32 s1,
1397  l_int32 c2,
1398  l_int32 s2)
1399 {
1400 l_int32 ovlp;
1401 
1402  if (c1 > c2)
1403  ovlp = c2 + s2 - 1 - c1;
1404  else
1405  ovlp = c1 + s1 - 1 - c2;
1406  return (ovlp < 0) ? 0 : 1;
1407 }
1408 
1409 
1420 static l_int32
1422  l_int32 s1,
1423  l_int32 c2,
1424  l_int32 s2)
1425 {
1426 l_int32 dist;
1427 
1428  if (c1 > c2)
1429  dist = c1 - (c2 + s2 - 1);
1430  else
1431  dist = c2 - (c1 + s1 - 1);
1432  return dist;
1433 }
1434 
1435 
1443 l_int32
1445  l_float32 *pcx,
1446  l_float32 *pcy)
1447 {
1448 l_int32 x, y, w, h;
1449 
1450  PROCNAME("boxGetCenter");
1451 
1452  if (pcx) *pcx = 0;
1453  if (pcy) *pcy = 0;
1454  if (!pcx || !pcy)
1455  return ERROR_INT("&cx, &cy not both defined", procName, 1);
1456  if (!box)
1457  return ERROR_INT("box not defined", procName, 1);
1458  boxGetGeometry(box, &x, &y, &w, &h);
1459  *pcx = (l_float32)(x + 0.5 * w);
1460  *pcy = (l_float32)(y + 0.5 * h);
1461 
1462  return 0;
1463 }
1464 
1465 
1484 l_int32
1486  l_int32 x,
1487  l_int32 y,
1488  l_float32 slope,
1489  l_int32 *px1,
1490  l_int32 *py1,
1491  l_int32 *px2,
1492  l_int32 *py2,
1493  l_int32 *pn)
1494 {
1495 l_int32 bx, by, bw, bh, xp, yp, xt, yt, i, n;
1496 l_float32 invslope;
1497 PTA *pta;
1498 
1499  PROCNAME("boxIntersectByLine");
1500 
1501  if (px1) *px1 = 0;
1502  if (px2) *px2 = 0;
1503  if (py1) *py1 = 0;
1504  if (py2) *py2 = 0;
1505  if (pn) *pn = 0;
1506  if (!px1 || !py1 || !px2 || !py2)
1507  return ERROR_INT("&x1, &y1, &x2, &y2 not all defined", procName, 1);
1508  if (!pn)
1509  return ERROR_INT("&n not defined", procName, 1);
1510  if (!box)
1511  return ERROR_INT("box not defined", procName, 1);
1512  boxGetGeometry(box, &bx, &by, &bw, &bh);
1513 
1514  if (slope == 0.0) {
1515  if (y >= by && y < by + bh) {
1516  *py1 = *py2 = y;
1517  *px1 = bx;
1518  *px2 = bx + bw - 1;
1519  }
1520  return 0;
1521  }
1522 
1523  if (slope > 1000000.0) {
1524  if (x >= bx && x < bx + bw) {
1525  *px1 = *px2 = x;
1526  *py1 = by;
1527  *py2 = by + bh - 1;
1528  }
1529  return 0;
1530  }
1531 
1532  /* Intersection with top and bottom lines of box */
1533  pta = ptaCreate(2);
1534  invslope = 1.0 / slope;
1535  xp = (l_int32)(x + invslope * (y - by));
1536  if (xp >= bx && xp < bx + bw)
1537  ptaAddPt(pta, xp, by);
1538  xp = (l_int32)(x + invslope * (y - by - bh + 1));
1539  if (xp >= bx && xp < bx + bw)
1540  ptaAddPt(pta, xp, by + bh - 1);
1541 
1542  /* Intersection with left and right lines of box */
1543  yp = (l_int32)(y + slope * (x - bx));
1544  if (yp >= by && yp < by + bh)
1545  ptaAddPt(pta, bx, yp);
1546  yp = (l_int32)(y + slope * (x - bx - bw + 1));
1547  if (yp >= by && yp < by + bh)
1548  ptaAddPt(pta, bx + bw - 1, yp);
1549 
1550  /* There is a maximum of 2 unique points; remove duplicates. */
1551  n = ptaGetCount(pta);
1552  if (n > 0) {
1553  ptaGetIPt(pta, 0, px1, py1); /* accept the first one */
1554  *pn = 1;
1555  }
1556  for (i = 1; i < n; i++) {
1557  ptaGetIPt(pta, i, &xt, &yt);
1558  if ((*px1 != xt) || (*py1 != yt)) {
1559  *px2 = xt;
1560  *py2 = yt;
1561  *pn = 2;
1562  break;
1563  }
1564  }
1565 
1566  ptaDestroy(&pta);
1567  return 0;
1568 }
1569 
1570 
1586 BOX *
1588  l_int32 wi,
1589  l_int32 hi)
1590 {
1591 BOX *boxd;
1592 
1593  PROCNAME("boxClipToRectangle");
1594 
1595  if (!box)
1596  return (BOX *)ERROR_PTR("box not defined", procName, NULL);
1597  if (box->x >= wi || box->y >= hi ||
1598  box->x + box->w <= 0 || box->y + box->h <= 0)
1599  return (BOX *)ERROR_PTR("box outside rectangle", procName, NULL);
1600 
1601  boxd = boxCopy(box);
1602  if (boxd->x < 0) {
1603  boxd->w += boxd->x;
1604  boxd->x = 0;
1605  }
1606  if (boxd->y < 0) {
1607  boxd->h += boxd->y;
1608  boxd->y = 0;
1609  }
1610  if (boxd->x + boxd->w > wi)
1611  boxd->w = wi - boxd->x;
1612  if (boxd->y + boxd->h > hi)
1613  boxd->h = hi - boxd->y;
1614  return boxd;
1615 }
1616 
1617 
1643 l_int32
1645  l_int32 w,
1646  l_int32 h,
1647  l_int32 *pxstart,
1648  l_int32 *pystart,
1649  l_int32 *pxend,
1650  l_int32 *pyend,
1651  l_int32 *pbw,
1652  l_int32 *pbh)
1653 {
1654 l_int32 bw, bh;
1655 BOX *boxc;
1656 
1657  PROCNAME("boxClipToRectangleParams");
1658 
1659  if (pxstart) *pxstart = 0;
1660  if (pystart) *pystart = 0;
1661  if (pxend) *pxend = w;
1662  if (pyend) *pyend = h;
1663  if (pbw) *pbw = w;
1664  if (pbh) *pbh = h;
1665  if (!pxstart || !pystart || !pxend || !pyend)
1666  return ERROR_INT("invalid ptr input", procName, 1);
1667  if (!box) return 0;
1668 
1669  if ((boxc = boxClipToRectangle(box, w, h)) == NULL)
1670  return ERROR_INT("box outside image", procName, 1);
1671  boxGetGeometry(boxc, pxstart, pystart, &bw, &bh);
1672  boxDestroy(&boxc);
1673 
1674  if (pbw) *pbw = bw;
1675  if (pbh) *pbh = bh;
1676  if (bw == 0 || bh == 0)
1677  return ERROR_INT("invalid clipping box", procName, 1);
1678  *pxend = *pxstart + bw; /* 1 past the end */
1679  *pyend = *pystart + bh; /* 1 past the end */
1680  return 0;
1681 }
1682 
1683 
1705 BOX *
1707  BOX *boxs,
1708  l_int32 loc,
1709  l_int32 sideflag)
1710 {
1711 l_int32 x, y, w, h;
1712 
1713  PROCNAME("boxRelocateOneSide");
1714 
1715  if (!boxs)
1716  return (BOX *)ERROR_PTR("boxs not defined", procName, NULL);
1717  if (!boxd)
1718  boxd = boxCopy(boxs);
1719 
1720  boxGetGeometry(boxs, &x, &y, &w, &h);
1721  if (sideflag == L_FROM_LEFT)
1722  boxSetGeometry(boxd, loc, -1, w + x - loc, -1);
1723  else if (sideflag == L_FROM_RIGHT)
1724  boxSetGeometry(boxd, -1, -1, loc - x + 1, -1);
1725  else if (sideflag == L_FROM_TOP)
1726  boxSetGeometry(boxd, -1, loc, -1, h + y - loc);
1727  else if (sideflag == L_FROM_BOT)
1728  boxSetGeometry(boxd, -1, -1, -1, loc - y + 1);
1729  return boxd;
1730 }
1731 
1732 
1749 BOXA *
1751  l_int32 delleft,
1752  l_int32 delright,
1753  l_int32 deltop,
1754  l_int32 delbot)
1755 {
1756 l_int32 n, i, x, y;
1757 BOX *box1, *box2;
1758 BOXA *boxad;
1759 
1760  PROCNAME("boxaAdjustSides");
1761 
1762  if (!boxas)
1763  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
1764 
1765  n = boxaGetCount(boxas);
1766  boxad = boxaCreate(n);
1767  for (i = 0; i < n; i++) {
1768  box1 = boxaGetBox(boxas, i, L_COPY);
1769  box2 = boxAdjustSides(NULL, box1, delleft, delright, deltop, delbot);
1770  if (!box2) {
1771  boxGetGeometry(box1, &x, &y, NULL, NULL);
1772  box2 = boxCreate(x, y, 1, 1);
1773  }
1774  boxaAddBox(boxad, box2, L_INSERT);
1775  boxDestroy(&box1);
1776  }
1777 
1778  return boxad;
1779 }
1780 
1781 
1806 BOX *
1808  BOX *boxs,
1809  l_int32 delleft,
1810  l_int32 delright,
1811  l_int32 deltop,
1812  l_int32 delbot)
1813 {
1814 l_int32 x, y, w, h, xl, xr, yt, yb, wnew, hnew;
1815 
1816  PROCNAME("boxAdjustSides");
1817 
1818  if (!boxs)
1819  return (BOX *)ERROR_PTR("boxs not defined", procName, NULL);
1820 
1821  boxGetGeometry(boxs, &x, &y, &w, &h);
1822  xl = L_MAX(0, x + delleft);
1823  yt = L_MAX(0, y + deltop);
1824  xr = x + w + delright; /* one pixel beyond right edge */
1825  yb = y + h + delbot; /* one pixel below bottom edge */
1826  wnew = xr - xl;
1827  hnew = yb - yt;
1828 
1829  if (wnew < 1 || hnew < 1)
1830  return (BOX *)ERROR_PTR("boxd has 0 area", procName, NULL);
1831  if (!boxd)
1832  return boxCreate(xl, yt, wnew, hnew);
1833 
1834  boxSetGeometry(boxd, xl, yt, wnew, hnew);
1835  return boxd;
1836 }
1837 
1838 
1858 BOXA *
1860  BOXA *boxas,
1861  l_int32 side,
1862  l_int32 val,
1863  l_int32 thresh)
1864 {
1865 l_int32 x, y, w, h, n, i, diff;
1866 BOX *box;
1867 
1868  PROCNAME("boxaSetSide");
1869 
1870  if (!boxas)
1871  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
1872  if (boxad && (boxas != boxad))
1873  return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
1874  if (side != L_SET_LEFT && side != L_SET_RIGHT &&
1875  side != L_SET_TOP && side != L_SET_BOT)
1876  return (BOXA *)ERROR_PTR("invalid side", procName, NULL);
1877  if (val < 0)
1878  return (BOXA *)ERROR_PTR("val < 0", procName, NULL);
1879 
1880  if (!boxad)
1881  boxad = boxaCopy(boxas, L_COPY);
1882  n = boxaGetCount(boxad);
1883  for (i = 0; i < n; i++) {
1884  box = boxaGetBox(boxad, i, L_CLONE);
1885  boxGetGeometry(box, &x, &y, &w, &h);
1886  if (side == L_SET_LEFT) {
1887  diff = x - val;
1888  if (L_ABS(diff) >= thresh)
1889  boxSetGeometry(box, val, y, w + diff, h);
1890  } else if (side == L_SET_RIGHT) {
1891  diff = x + w -1 - val;
1892  if (L_ABS(diff) >= thresh)
1893  boxSetGeometry(box, x, y, val - x + 1, h);
1894  } else if (side == L_SET_TOP) {
1895  diff = y - val;
1896  if (L_ABS(diff) >= thresh)
1897  boxSetGeometry(box, x, val, w, h + diff);
1898  } else { /* side == L_SET_BOT */
1899  diff = y + h - 1 - val;
1900  if (L_ABS(diff) >= thresh)
1901  boxSetGeometry(box, x, y, w, val - y + 1);
1902  }
1903  boxDestroy(&box);
1904  }
1905 
1906  return boxad;
1907 }
1908 
1909 
1931 BOXA *
1933  BOXA *boxas,
1934  l_int32 sides,
1935  l_int32 target,
1936  l_int32 thresh)
1937 {
1938 l_int32 x, y, w, h, n, i, diff;
1939 BOX *box;
1940 
1941  PROCNAME("boxaAdjustWidthToTarget");
1942 
1943  if (!boxas)
1944  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
1945  if (boxad && (boxas != boxad))
1946  return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
1947  if (sides != L_ADJUST_LEFT && sides != L_ADJUST_RIGHT &&
1948  sides != L_ADJUST_LEFT_AND_RIGHT)
1949  return (BOXA *)ERROR_PTR("invalid sides", procName, NULL);
1950  if (target < 1)
1951  return (BOXA *)ERROR_PTR("target < 1", procName, NULL);
1952 
1953  if (!boxad)
1954  boxad = boxaCopy(boxas, L_COPY);
1955  n = boxaGetCount(boxad);
1956  for (i = 0; i < n; i++) {
1957  box = boxaGetBox(boxad, i, L_CLONE);
1958  boxGetGeometry(box, &x, &y, &w, &h);
1959  diff = w - target;
1960  if (sides == L_ADJUST_LEFT) {
1961  if (L_ABS(diff) >= thresh)
1962  boxSetGeometry(box, L_MAX(0, x + diff), y, target, h);
1963  } else if (sides == L_ADJUST_RIGHT) {
1964  if (L_ABS(diff) >= thresh)
1965  boxSetGeometry(box, x, y, target, h);
1966  } else { /* sides == L_ADJUST_LEFT_AND_RIGHT */
1967  if (L_ABS(diff) >= thresh)
1968  boxSetGeometry(box, L_MAX(0, x + diff/2), y, target, h);
1969  }
1970  boxDestroy(&box);
1971  }
1972 
1973  return boxad;
1974 }
1975 
1976 
1998 BOXA *
2000  BOXA *boxas,
2001  l_int32 sides,
2002  l_int32 target,
2003  l_int32 thresh)
2004 {
2005 l_int32 x, y, w, h, n, i, diff;
2006 BOX *box;
2007 
2008  PROCNAME("boxaAdjustHeightToTarget");
2009 
2010  if (!boxas)
2011  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
2012  if (boxad && (boxas != boxad))
2013  return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
2014  if (sides != L_ADJUST_TOP && sides != L_ADJUST_BOT &&
2015  sides != L_ADJUST_TOP_AND_BOT)
2016  return (BOXA *)ERROR_PTR("invalid sides", procName, NULL);
2017  if (target < 1)
2018  return (BOXA *)ERROR_PTR("target < 1", procName, NULL);
2019 
2020  if (!boxad)
2021  boxad = boxaCopy(boxas, L_COPY);
2022  n = boxaGetCount(boxad);
2023  for (i = 0; i < n; i++) {
2024  box = boxaGetBox(boxad, i, L_CLONE);
2025  boxGetGeometry(box, &x, &y, &w, &h);
2026  if (w == 0 || h == 0) { /* invalid; do not alter */
2027  boxDestroy(&box);
2028  continue;
2029  }
2030  diff = h - target;
2031  if (sides == L_ADJUST_TOP) {
2032  if (L_ABS(diff) >= thresh)
2033  boxSetGeometry(box, x, L_MAX(0, y + diff), w, target);
2034  } else if (sides == L_ADJUST_BOT) {
2035  if (L_ABS(diff) >= thresh)
2036  boxSetGeometry(box, x, y, w, target);
2037  } else { /* sides == L_ADJUST_TOP_AND_BOT */
2038  if (L_ABS(diff) >= thresh)
2039  boxSetGeometry(box, x, L_MAX(0, y + diff/2), w, target);
2040  }
2041  boxDestroy(&box);
2042  }
2043 
2044  return boxad;
2045 }
2046 
2047 
2056 l_int32
2058  BOX *box2,
2059  l_int32 *psame)
2060 {
2061  PROCNAME("boxEqual");
2062 
2063  if (!psame)
2064  return ERROR_INT("&same not defined", procName, 1);
2065  *psame = 0;
2066  if (!box1 || !box2)
2067  return ERROR_INT("box1 and box2 not both defined", procName, 1);
2068  if (box1->x == box2->x && box1->y == box2->y &&
2069  box1->w == box2->w && box1->h == box2->h)
2070  *psame = 1;
2071  return 0;
2072 }
2073 
2074 
2103 l_int32
2105  BOXA *boxa2,
2106  l_int32 maxdist,
2107  NUMA **pnaindex,
2108  l_int32 *psame)
2109 {
2110 l_int32 i, j, n, jstart, jend, found, samebox;
2111 l_int32 *countarray;
2112 BOX *box1, *box2;
2113 NUMA *na;
2114 
2115  PROCNAME("boxaEqual");
2116 
2117  if (pnaindex) *pnaindex = NULL;
2118  if (!psame)
2119  return ERROR_INT("&same not defined", procName, 1);
2120  *psame = 0;
2121  if (!boxa1 || !boxa2)
2122  return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
2123  n = boxaGetCount(boxa1);
2124  if (n != boxaGetCount(boxa2))
2125  return 0;
2126 
2127  if ((countarray = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32))) == NULL)
2128  return ERROR_INT("calloc fail for countarray", procName, 1);
2129  na = numaMakeConstant(0.0, n);
2130 
2131  for (i = 0; i < n; i++) {
2132  box1 = boxaGetBox(boxa1, i, L_CLONE);
2133  jstart = L_MAX(0, i - maxdist);
2134  jend = L_MIN(n-1, i + maxdist);
2135  found = FALSE;
2136  for (j = jstart; j <= jend; j++) {
2137  box2 = boxaGetBox(boxa2, j, L_CLONE);
2138  boxEqual(box1, box2, &samebox);
2139  if (samebox && countarray[j] == 0) {
2140  countarray[j] = 1;
2141  numaReplaceNumber(na, i, j);
2142  found = TRUE;
2143  boxDestroy(&box2);
2144  break;
2145  }
2146  boxDestroy(&box2);
2147  }
2148  boxDestroy(&box1);
2149  if (!found) {
2150  numaDestroy(&na);
2151  LEPT_FREE(countarray);
2152  return 0;
2153  }
2154  }
2155 
2156  *psame = 1;
2157  if (pnaindex)
2158  *pnaindex = na;
2159  else
2160  numaDestroy(&na);
2161  LEPT_FREE(countarray);
2162  return 0;
2163 }
2164 
2165 
2182 l_int32
2184  BOX *box2,
2185  l_int32 leftdiff,
2186  l_int32 rightdiff,
2187  l_int32 topdiff,
2188  l_int32 botdiff,
2189  l_int32 *psimilar)
2190 {
2191 l_int32 l1, l2, r1, r2, t1, t2, b1, b2;
2192 
2193  PROCNAME("boxSimilar");
2194 
2195  if (!psimilar)
2196  return ERROR_INT("&similar not defined", procName, 1);
2197  *psimilar = 0;
2198  if (!box1 || !box2)
2199  return ERROR_INT("box1 and box2 not both defined", procName, 1);
2200 
2201  boxGetSideLocations(box1, &l1, &r1, &t1, &b1);
2202  boxGetSideLocations(box2, &l2, &r2, &t2, &b2);
2203  if (L_ABS(l1 - l2) > leftdiff)
2204  return 0;
2205  if (L_ABS(r1 - r2) > rightdiff)
2206  return 0;
2207  if (L_ABS(t1 - t2) > topdiff)
2208  return 0;
2209  if (L_ABS(b1 - b2) > botdiff)
2210  return 0;
2211 
2212  *psimilar = 1;
2213  return 0;
2214 }
2215 
2216 
2237 l_int32
2239  BOXA *boxa2,
2240  l_int32 leftdiff,
2241  l_int32 rightdiff,
2242  l_int32 topdiff,
2243  l_int32 botdiff,
2244  l_int32 debug,
2245  l_int32 *psimilar,
2246  NUMA **pnasim)
2247 {
2248 l_int32 i, n1, n2, match, mismatch;
2249 BOX *box1, *box2;
2250 
2251  PROCNAME("boxaSimilar");
2252 
2253  if (psimilar) *psimilar = 0;
2254  if (pnasim) *pnasim = NULL;
2255  if (!boxa1 || !boxa2)
2256  return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
2257  if (!psimilar)
2258  return ERROR_INT("&similar not defined", procName, 1);
2259  n1 = boxaGetCount(boxa1);
2260  n2 = boxaGetCount(boxa2);
2261  if (n1 != n2) {
2262  L_ERROR("boxa counts differ: %d vs %d\n", procName, n1, n2);
2263  return 1;
2264  }
2265  if (pnasim) *pnasim = numaCreate(n1);
2266 
2267  mismatch = FALSE;
2268  for (i = 0; i < n1; i++) {
2269  box1 = boxaGetBox(boxa1, i, L_CLONE);
2270  box2 = boxaGetBox(boxa2, i, L_CLONE);
2271  boxSimilar(box1, box2, leftdiff, rightdiff, topdiff, botdiff,
2272  &match);
2273  boxDestroy(&box1);
2274  boxDestroy(&box2);
2275  if (pnasim)
2276  numaAddNumber(*pnasim, match);
2277  if (!match) {
2278  mismatch = TRUE;
2279  if (!debug && pnasim == NULL)
2280  return 0;
2281  else if (debug)
2282  L_INFO("box %d not similar\n", procName, i);
2283  }
2284  }
2285 
2286  if (!mismatch) *psimilar = 1;
2287  return 0;
2288 }
2289 
2290 
2291 /*----------------------------------------------------------------------*
2292  * Boxa combine and split *
2293  *----------------------------------------------------------------------*/
2311 l_int32
2313  BOXA *boxas,
2314  l_int32 istart,
2315  l_int32 iend)
2316 {
2317 l_int32 n, i;
2318 BOX *box;
2319 
2320  PROCNAME("boxaJoin");
2321 
2322  if (!boxad)
2323  return ERROR_INT("boxad not defined", procName, 1);
2324  if (!boxas || ((n = boxaGetCount(boxas)) == 0))
2325  return 0;
2326 
2327  if (istart < 0)
2328  istart = 0;
2329  if (iend < 0 || iend >= n)
2330  iend = n - 1;
2331  if (istart > iend)
2332  return ERROR_INT("istart > iend; nothing to add", procName, 1);
2333 
2334  for (i = istart; i <= iend; i++) {
2335  box = boxaGetBox(boxas, i, L_CLONE);
2336  boxaAddBox(boxad, box, L_INSERT);
2337  }
2338 
2339  return 0;
2340 }
2341 
2342 
2360 l_int32
2362  BOXAA *baas,
2363  l_int32 istart,
2364  l_int32 iend)
2365 {
2366 l_int32 n, i;
2367 BOXA *boxa;
2368 
2369  PROCNAME("boxaaJoin");
2370 
2371  if (!baad)
2372  return ERROR_INT("baad not defined", procName, 1);
2373  if (!baas)
2374  return 0;
2375 
2376  if (istart < 0)
2377  istart = 0;
2378  n = boxaaGetCount(baas);
2379  if (iend < 0 || iend >= n)
2380  iend = n - 1;
2381  if (istart > iend)
2382  return ERROR_INT("istart > iend; nothing to add", procName, 1);
2383 
2384  for (i = istart; i <= iend; i++) {
2385  boxa = boxaaGetBoxa(baas, i, L_CLONE);
2386  boxaaAddBoxa(baad, boxa, L_INSERT);
2387  }
2388 
2389  return 0;
2390 }
2391 
2392 
2410 l_int32
2412  l_int32 fillflag,
2413  BOXA **pboxae,
2414  BOXA **pboxao)
2415 {
2416 l_int32 i, n;
2417 BOX *box, *boxt;
2418 
2419  PROCNAME("boxaSplitEvenOdd");
2420 
2421  if (pboxae) *pboxae = NULL;
2422  if (pboxao) *pboxao = NULL;
2423  if (!pboxae || !pboxao)
2424  return ERROR_INT("&boxae and &boxao not both defined", procName, 1);
2425  if (!boxa)
2426  return ERROR_INT("boxa not defined", procName, 1);
2427 
2428  n = boxaGetCount(boxa);
2429  *pboxae = boxaCreate(n);
2430  *pboxao = boxaCreate(n);
2431  if (fillflag == 0) {
2432  /* don't fill with invalid boxes; end up with half-size boxa */
2433  for (i = 0; i < n; i++) {
2434  box = boxaGetBox(boxa, i, L_COPY);
2435  if ((i & 1) == 0)
2436  boxaAddBox(*pboxae, box, L_INSERT);
2437  else
2438  boxaAddBox(*pboxao, box, L_INSERT);
2439  }
2440  } else {
2441  for (i = 0; i < n; i++) {
2442  box = boxaGetBox(boxa, i, L_COPY);
2443  boxt = boxCreate(0, 0, 0, 0); /* empty placeholder */
2444  if ((i & 1) == 0) {
2445  boxaAddBox(*pboxae, box, L_INSERT);
2446  boxaAddBox(*pboxao, boxt, L_INSERT);
2447  } else {
2448  boxaAddBox(*pboxae, boxt, L_INSERT);
2449  boxaAddBox(*pboxao, box, L_INSERT);
2450  }
2451  }
2452  }
2453  return 0;
2454 }
2455 
2456 
2474 BOXA *
2476  BOXA *boxao,
2477  l_int32 fillflag)
2478 {
2479 l_int32 i, n, ne, no;
2480 BOX *box;
2481 BOXA *boxad;
2482 
2483  PROCNAME("boxaMergeEvenOdd");
2484 
2485  if (!boxae || !boxao)
2486  return (BOXA *)ERROR_PTR("boxae and boxao not defined", procName, NULL);
2487  ne = boxaGetCount(boxae);
2488  no = boxaGetCount(boxao);
2489  if (ne < no || ne > no + 1)
2490  return (BOXA *)ERROR_PTR("boxa sizes invalid", procName, NULL);
2491 
2492  boxad = boxaCreate(ne);
2493  if (fillflag == 0) { /* both are approx. half-sized; all valid boxes */
2494  n = ne + no;
2495  for (i = 0; i < n; i++) {
2496  if ((i & 1) == 0)
2497  box = boxaGetBox(boxae, i / 2, L_COPY);
2498  else
2499  box = boxaGetBox(boxao, i / 2, L_COPY);
2500  boxaAddBox(boxad, box, L_INSERT);
2501  }
2502  } else { /* both are full size and have invalid placeholders */
2503  for (i = 0; i < ne; i++) {
2504  if ((i & 1) == 0)
2505  box = boxaGetBox(boxae, i, L_COPY);
2506  else
2507  box = boxaGetBox(boxao, i, L_COPY);
2508  boxaAddBox(boxad, box, L_INSERT);
2509  }
2510  }
2511  return boxad;
2512 }
BOXA * boxaIntersectsBox(BOXA *boxas, BOX *box)
boxaIntersectsBox()
Definition: boxfunc1.c:302
BOX * boxaGetNearestToPt(BOXA *boxa, l_int32 x, l_int32 y)
boxaGetNearestToPt()
Definition: boxfunc1.c:1115
BOX * boxaGetValidBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetValidBox()
Definition: boxbasic.c:799
l_int32 boxSeparationDistance(BOX *box1, BOX *box2, l_int32 *ph_sep, l_int32 *pv_sep)
boxSeparationDistance()
Definition: boxfunc1.c:973
l_int32 numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:472
l_int32 boxContains(BOX *box1, BOX *box2, l_int32 *presult)
boxContains()
Definition: boxfunc1.c:99
BOXA * boxaMergeEvenOdd(BOXA *boxae, BOXA *boxao, l_int32 fillflag)
boxaMergeEvenOdd()
Definition: boxfunc1.c:2475
l_int32 ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:341
l_int32 boxaaGetCount(BOXAA *baa)
boxaaGetCount()
Definition: boxbasic.c:1438
l_int32 boxSimilar(BOX *box1, BOX *box2, l_int32 leftdiff, l_int32 rightdiff, l_int32 topdiff, l_int32 botdiff, l_int32 *psimilar)
boxSimilar()
Definition: boxfunc1.c:2183
l_int32 boxaEqual(BOXA *boxa1, BOXA *boxa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame)
boxaEqual()
Definition: boxfunc1.c:2104
Definition: pix.h:955
static l_int32 boxGetDistanceInXorY(l_int32 c1, l_int32 s1, l_int32 c2, l_int32 s2)
boxGetDistanceInXorY()
Definition: boxfunc1.c:1421
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:115
l_int32 boxCompareSize(BOX *box1, BOX *box2, l_int32 type, l_int32 *prel)
boxCompareSize()
Definition: boxfunc1.c:1029
l_int32 y
Definition: pix.h:483
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:768
l_int32 boxSetGeometry(BOX *box, l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxSetGeometry()
Definition: boxbasic.c:339
l_int32 boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:615
BOXA * boxaContainedInBox(BOXA *boxas, BOX *box)
boxaContainedInBox()
Definition: boxfunc1.c:172
l_int32 boxContainsPt(BOX *box, l_float32 x, l_float32 y, l_int32 *pcontains)
boxContainsPt()
Definition: boxfunc1.c:1080
l_int32 boxOverlapFraction(BOX *box1, BOX *box2, l_float32 *pfract)
boxOverlapFraction()
Definition: boxfunc1.c:756
BOX * boxClipToRectangle(BOX *box, l_int32 wi, l_int32 hi)
boxClipToRectangle()
Definition: boxfunc1.c:1587
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
BOXA * boxaCopy(BOXA *boxa, l_int32 copyflag)
boxaCopy()
Definition: boxbasic.c:531
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:186
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:503
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:577
BOXA * boxaAdjustHeightToTarget(BOXA *boxad, BOXA *boxas, l_int32 sides, l_int32 target, l_int32 thresh)
boxaAdjustHeightToTarget()
Definition: boxfunc1.c:1999
l_int32 pixRenderBoxaArb(PIX *pix, BOXA *boxa, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderBoxaArb()
Definition: graphics.c:1758
l_int32 boxaJoin(BOXA *boxad, BOXA *boxas, l_int32 istart, l_int32 iend)
boxaJoin()
Definition: boxfunc1.c:2312
l_int32 boxaContainedInBoxa(BOXA *boxa1, BOXA *boxa2, l_int32 *pcontained)
boxaContainedInBoxa()
Definition: boxfunc1.c:249
l_int32 boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:860
BOXA * boxaHandleOverlaps(BOXA *boxas, l_int32 op, l_int32 range, l_float32 min_overlap, l_float32 max_ratio, NUMA **pnamap)
boxaHandleOverlaps()
Definition: boxfunc1.c:853
NUMAA * numaaCreate(l_int32 n)
numaaCreate()
Definition: numabasic.c:1307
Definition: pix.h:492
BOX * boxBoundingRegion(BOX *box1, BOX *box2)
boxBoundingRegion()
Definition: boxfunc1.c:716
BOXA * boxaClipToBox(BOXA *boxas, BOX *box)
boxaClipToBox()
Definition: boxfunc1.c:385
l_int32 numaaAddNuma(NUMAA *naa, NUMA *na, l_int32 copyflag)
numaaAddNuma()
Definition: numabasic.c:1448
Definition: pix.h:502
static l_int32 boxHasOverlapInXorY(l_int32 c1, l_int32 s1, l_int32 c2, l_int32 s2)
boxHasOverlapInXorY()
Definition: boxfunc1.c:1395
l_int32 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:2238
l_int32 boxEqual(BOX *box1, BOX *box2, l_int32 *psame)
boxEqual()
Definition: boxfunc1.c:2057
Definition: array.h:59
static const l_int32 L_INSERT
Definition: pix.h:710
l_int32 boxGetCenter(BOX *box, l_float32 *pcx, l_float32 *pcy)
boxGetCenter()
Definition: boxfunc1.c:1444
l_int32 boxaIntersectsBoxCount(BOXA *boxa, BOX *box, l_int32 *pcount)
boxaIntersectsBoxCount()
Definition: boxfunc1.c:340
l_int32 boxaGetArea(BOXA *boxa, l_int32 *parea)
boxaGetArea()
Definition: boxfunc4.c:2648
l_int32 pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:493
l_int32 w
Definition: pix.h:484
BOXA * boxaSaveValid(BOXA *boxas, l_int32 copyflag)
boxaSaveValid()
Definition: boxbasic.c:1109
l_int32 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:1644
l_int32 boxGetSideLocations(BOX *box, l_int32 *pl, l_int32 *pr, l_int32 *pt, l_int32 *pb)
boxGetSideLocations()
Definition: boxbasic.c:370
l_int32 boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:309
BOX * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1807
l_int32 boxaCombineOverlapsInPair(BOXA *boxas1, BOXA *boxas2, BOXA **pboxad1, BOXA **pboxad2, PIXA *pixadb)
boxaCombineOverlapsInPair()
Definition: boxfunc1.c:536
l_int32 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:1305
BOXA * boxaSetSide(BOXA *boxad, BOXA *boxas, l_int32 side, l_int32 val, l_int32 thresh)
boxaSetSide()
Definition: boxfunc1.c:1859
Definition: array.h:71
BOX * boxOverlapRegion(BOX *box1, BOX *box2)
boxOverlapRegion()
Definition: boxfunc1.c:674
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:545
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:760
l_int32 boxaaJoin(BOXAA *baad, BOXAA *baas, l_int32 istart, l_int32 iend)
boxaaJoin()
Definition: boxfunc1.c:2361
l_int32 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:1485
l_int32 x
Definition: pix.h:482
Definition: pix.h:454
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:359
BOX * boxRelocateOneSide(BOX *boxd, BOX *boxs, l_int32 loc, l_int32 sideflag)
boxRelocateOneSide()
Definition: boxfunc1.c:1706
l_int32 ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:554
BOXA * boxaAdjustSides(BOXA *boxas, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxaAdjustSides()
Definition: boxfunc1.c:1750
l_int32 boxIntersects(BOX *box1, BOX *box2, l_int32 *presult)
boxIntersects()
Definition: boxfunc1.c:130
l_int32 numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:601
l_int32 boxaaAddBoxa(BOXAA *baa, BOXA *ba, l_int32 copyflag)
boxaaAddBoxa()
Definition: boxbasic.c:1341
BOX * boxaGetNearestToLine(BOXA *boxa, l_int32 x, l_int32 y)
boxaGetNearestToLine()
Definition: boxfunc1.c:1167
BOXA * boxaAdjustWidthToTarget(BOXA *boxad, BOXA *boxas, l_int32 sides, l_int32 target, l_int32 thresh)
boxaAdjustWidthToTarget()
Definition: boxfunc1.c:1932
Definition: pix.h:705
BOXA * boxaCombineOverlaps(BOXA *boxas, PIXA *pixadb)
boxaCombineOverlaps()
Definition: boxfunc1.c:442
l_int32 h
Definition: pix.h:485
BOX * boxCopy(BOX *box)
boxCopy()
Definition: boxbasic.c:229
Definition: pix.h:134
l_int32 numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
Definition: numabasic.c:758
Definition: pix.h:706
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:191
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:496
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:277
l_int32 boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition: boxfunc4.c:2321
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:715
l_int32 numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:726
l_int32 pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:729
Definition: pix.h:480
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:164
l_int32 boxaFindNearestBoxes(BOXA *boxa, l_int32 dist_select, l_int32 range, NUMAA **pnaaindex, NUMAA **pnaadist)
boxaFindNearestBoxes()
Definition: boxfunc1.c:1224
l_int32 boxOverlapArea(BOX *box1, BOX *box2, l_int32 *parea)
boxOverlapArea()
Definition: boxfunc1.c:792
Definition: pix.h:517
l_int32 boxaReplaceBox(BOXA *boxa, l_int32 index, BOX *box)
boxaReplaceBox()
Definition: boxbasic.c:942
BOXA * boxaaGetBoxa(BOXAA *baa, l_int32 index, l_int32 accessflag)
boxaaGetBoxa()
Definition: boxbasic.c:1485
l_int32 boxaSplitEvenOdd(BOXA *boxa, l_int32 fillflag, BOXA **pboxae, BOXA **pboxao)
boxaSplitEvenOdd()
Definition: boxfunc1.c:2411
l_int32 boxaContainedInBoxCount(BOXA *boxa, BOX *box, l_int32 *pcount)
boxaContainedInBoxCount()
Definition: boxfunc1.c:210