Leptonica  1.77.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 
80 #include "allheaders.h"
81 
82 static l_int32 boxHasOverlapInXorY(l_int32 c1, l_int32 s1, l_int32 c2,
83  l_int32 s2);
84 static l_int32 boxGetDistanceInXorY(l_int32 c1, l_int32 s1, l_int32 c2,
85  l_int32 s2);
86 
87 
88 /*---------------------------------------------------------------------*
89  * Box geometry *
90  *---------------------------------------------------------------------*/
99 l_ok
101  BOX *box2,
102  l_int32 *presult)
103 {
104 l_int32 x1, y1, w1, h1, x2, y2, w2, h2;
105 
106  PROCNAME("boxContains");
107 
108  if (!presult)
109  return ERROR_INT("&result not defined", procName, 1);
110  *presult = 0;
111  if (!box1 || !box2)
112  return ERROR_INT("box1 and box2 not both defined", procName, 1);
113 
114  boxGetGeometry(box1, &x1, &y1, &w1, &h1);
115  boxGetGeometry(box2, &x2, &y2, &w2, &h2);
116  if (x1 <= x2 && y1 <= y2 && (x1 + w1 >= x2 + w2) && (y1 + h1 >= y2 + h2))
117  *presult = 1;
118  return 0;
119 }
120 
121 
130 l_ok
132  BOX *box2,
133  l_int32 *presult)
134 {
135 l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2;
136 
137  PROCNAME("boxIntersects");
138 
139  if (!presult)
140  return ERROR_INT("&result not defined", procName, 1);
141  *presult = 0;
142  if (!box1 || !box2)
143  return ERROR_INT("box1 and box2 not both defined", procName, 1);
144 
145  boxGetGeometry(box1, &l1, &t1, &w1, &h1);
146  boxGetGeometry(box2, &l2, &t2, &w2, &h2);
147  r1 = l1 + w1 - 1;
148  r2 = l2 + w2 - 1;
149  b1 = t1 + h1 - 1;
150  b2 = t2 + h2 - 1;
151  if (b2 < t1 || b1 < t2 || r1 < l2 || r2 < l1)
152  *presult = 0;
153  else
154  *presult = 1;
155  return 0;
156 }
157 
158 
172 BOXA *
174  BOX *box)
175 {
176 l_int32 i, n, val;
177 BOX *boxt;
178 BOXA *boxad;
179 
180  PROCNAME("boxaContainedInBox");
181 
182  if (!boxas)
183  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
184  if (!box)
185  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
186  if ((n = boxaGetCount(boxas)) == 0)
187  return boxaCreate(1); /* empty */
188 
189  boxad = boxaCreate(0);
190  for (i = 0; i < n; i++) {
191  boxt = boxaGetBox(boxas, i, L_CLONE);
192  boxContains(box, boxt, &val);
193  if (val == 1)
194  boxaAddBox(boxad, boxt, L_COPY);
195  boxDestroy(&boxt); /* destroy the clone */
196  }
197 
198  return boxad;
199 }
200 
201 
210 l_ok
212  BOX *box,
213  l_int32 *pcount)
214 {
215 l_int32 i, n, val;
216 BOX *box1;
217 
218  PROCNAME("boxaContainedInBoxCount");
219 
220  if (!pcount)
221  return ERROR_INT("&count not defined", procName, 1);
222  *pcount = 0;
223  if (!boxa)
224  return ERROR_INT("boxa not defined", procName, 1);
225  if (!box)
226  return ERROR_INT("box not defined", procName, 1);
227  if ((n = boxaGetCount(boxa)) == 0)
228  return 0;
229 
230  for (i = 0; i < n; i++) {
231  box1 = boxaGetBox(boxa, i, L_CLONE);
232  boxContains(box, box1, &val);
233  if (val == 1)
234  (*pcount)++;
235  boxDestroy(&box1);
236  }
237  return 0;
238 }
239 
240 
249 l_ok
251  BOXA *boxa2,
252  l_int32 *pcontained)
253 {
254 l_int32 i, j, n1, n2, cont, result;
255 BOX *box1, *box2;
256 
257  PROCNAME("boxaContainedInBoxa");
258 
259  if (!pcontained)
260  return ERROR_INT("&contained not defined", procName, 1);
261  *pcontained = 0;
262  if (!boxa1 || !boxa2)
263  return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
264 
265  n1 = boxaGetCount(boxa1);
266  n2 = boxaGetCount(boxa2);
267  for (i = 0; i < n2; i++) {
268  box2 = boxaGetBox(boxa2, i, L_CLONE);
269  cont = 0;
270  for (j = 0; j < n1; j++) {
271  box1 = boxaGetBox(boxa1, j, L_CLONE);
272  boxContains(box1, box2, &result);
273  boxDestroy(&box1);
274  if (result) {
275  cont = 1;
276  break;
277  }
278  }
279  boxDestroy(&box2);
280  if (!cont) return 0;
281  }
282 
283  *pcontained = 1;
284  return 0;
285 }
286 
287 
302 BOXA *
304  BOX *box)
305 {
306 l_int32 i, n, val;
307 BOX *boxt;
308 BOXA *boxad;
309 
310  PROCNAME("boxaIntersectsBox");
311 
312  if (!boxas)
313  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
314  if (!box)
315  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
316  if ((n = boxaGetCount(boxas)) == 0)
317  return boxaCreate(1); /* empty */
318 
319  boxad = boxaCreate(0);
320  for (i = 0; i < n; i++) {
321  boxt = boxaGetBox(boxas, i, L_CLONE);
322  boxIntersects(box, boxt, &val);
323  if (val == 1)
324  boxaAddBox(boxad, boxt, L_COPY);
325  boxDestroy(&boxt); /* destroy the clone */
326  }
327 
328  return boxad;
329 }
330 
331 
340 l_ok
342  BOX *box,
343  l_int32 *pcount)
344 {
345 l_int32 i, n, val;
346 BOX *box1;
347 
348  PROCNAME("boxaIntersectsBoxCount");
349 
350  if (!pcount)
351  return ERROR_INT("&count not defined", procName, 1);
352  *pcount = 0;
353  if (!boxa)
354  return ERROR_INT("boxa not defined", procName, 1);
355  if (!box)
356  return ERROR_INT("box not defined", procName, 1);
357  if ((n = boxaGetCount(boxa)) == 0)
358  return 0;
359 
360  for (i = 0; i < n; i++) {
361  box1 = boxaGetBox(boxa, i, L_CLONE);
362  boxIntersects(box, box1, &val);
363  if (val == 1)
364  (*pcount)++;
365  boxDestroy(&box1);
366  }
367  return 0;
368 }
369 
370 
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 
440 BOXA *
442  PIXA *pixadb)
443 {
444 l_int32 i, j, w, h, n1, n2, overlap, niters;
445 BOX *box1, *box2, *box3;
446 BOXA *boxa1, *boxa2;
447 PIX *pix1;
448 
449  PROCNAME("boxaCombineOverlaps");
450 
451  if (!boxas)
452  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
453 
454  if (pixadb) boxaGetExtent(boxas, &w, &h, NULL);
455 
456  boxa1 = boxaCopy(boxas, L_COPY);
457  n1 = boxaGetCount(boxa1);
458  niters = 0;
459  while (1) { /* loop until no change from previous iteration */
460  niters++;
461  if (pixadb) {
462  pix1 = pixCreate(w + 5, h + 5, 32);
463  pixSetAll(pix1);
464  pixRenderBoxaArb(pix1, boxa1, 2, 255, 0, 0);
465  pixaAddPix(pixadb, pix1, L_COPY);
466  }
467 
468  /* Combine overlaps for this iteration */
469  for (i = 0; i < n1; i++) {
470  if ((box1 = boxaGetValidBox(boxa1, i, L_COPY)) == NULL)
471  continue;
472  for (j = i + 1; j < n1; j++) {
473  if ((box2 = boxaGetValidBox(boxa1, j, L_COPY)) == NULL)
474  continue;
475  boxIntersects(box1, box2, &overlap);
476  if (overlap) {
477  box3 = boxBoundingRegion(box1, box2);
478  boxaReplaceBox(boxa1, i, box3);
479  boxaReplaceBox(boxa1, j, boxCreate(0, 0, 0, 0));
480  boxDestroy(&box1);
481  box1 = boxCopy(box3);
482  }
483  boxDestroy(&box2);
484  }
485  boxDestroy(&box1);
486  }
487  boxa2 = boxaSaveValid(boxa1, L_COPY);
488  n2 = boxaGetCount(boxa2);
489  boxaDestroy(&boxa1);
490  boxa1 = boxa2;
491  if (n1 == n2) {
492  if (pixadb) pixDestroy(&pix1);
493  break;
494  }
495  n1 = n2;
496  if (pixadb) {
497  pixRenderBoxaArb(pix1, boxa1, 2, 0, 255, 0);
498  pixaAddPix(pixadb, pix1, L_INSERT);
499  }
500  }
501 
502  if (pixadb)
503  L_INFO("number of iterations: %d\n", procName, niters);
504  return boxa1;
505 }
506 
507 
534 l_ok
536  BOXA *boxas2,
537  BOXA **pboxad1,
538  BOXA **pboxad2,
539  PIXA *pixadb)
540 {
541 l_int32 i, j, w, h, w2, h2, n1, n2, n1i, n2i, niters;
542 l_int32 overlap, bigger, area1, area2;
543 BOX *box1, *box2, *box3;
544 BOXA *boxa1, *boxa2, *boxac1, *boxac2;
545 PIX *pix1;
546 
547  PROCNAME("boxaCombineOverlapsInPair");
548 
549  if (pboxad1) *pboxad1 = NULL;
550  if (pboxad2) *pboxad2 = NULL;
551  if (!boxas1 || !boxas2)
552  return ERROR_INT("boxas1 and boxas2 not both defined", procName, 1);
553  if (!pboxad1 || !pboxad2)
554  return ERROR_INT("&boxad1 and &boxad2 not both defined", procName, 1);
555 
556  if (pixadb) {
557  boxaGetExtent(boxas1, &w, &h, NULL);
558  boxaGetExtent(boxas2, &w2, &h2, NULL);
559  w = L_MAX(w, w2);
560  h = L_MAX(h, w2);
561  }
562 
563  /* Let the boxa with the largest area have first crack at the other */
564  boxaGetArea(boxas1, &area1);
565  boxaGetArea(boxas2, &area2);
566  if (area1 >= area2) {
567  boxac1 = boxaCopy(boxas1, L_COPY);
568  boxac2 = boxaCopy(boxas2, L_COPY);
569  } else {
570  boxac1 = boxaCopy(boxas2, L_COPY);
571  boxac2 = boxaCopy(boxas1, L_COPY);
572  }
573 
574  n1i = boxaGetCount(boxac1);
575  n2i = boxaGetCount(boxac2);
576  niters = 0;
577  while (1) {
578  niters++;
579  if (pixadb) {
580  pix1 = pixCreate(w + 5, h + 5, 32);
581  pixSetAll(pix1);
582  pixRenderBoxaArb(pix1, boxac1, 2, 255, 0, 0);
583  pixRenderBoxaArb(pix1, boxac2, 2, 0, 255, 0);
584  pixaAddPix(pixadb, pix1, L_INSERT);
585  }
586 
587  /* First combine boxes in each set */
588  boxa1 = boxaCombineOverlaps(boxac1, NULL);
589  boxa2 = boxaCombineOverlaps(boxac2, NULL);
590 
591  /* Now combine boxes between sets */
592  n1 = boxaGetCount(boxa1);
593  n2 = boxaGetCount(boxa2);
594  for (i = 0; i < n1; i++) { /* 1 eats 2 */
595  if ((box1 = boxaGetValidBox(boxa1, i, L_COPY)) == NULL)
596  continue;
597  for (j = 0; j < n2; j++) {
598  if ((box2 = boxaGetValidBox(boxa2, j, L_COPY)) == NULL)
599  continue;
600  boxIntersects(box1, box2, &overlap);
601  boxCompareSize(box1, box2, L_SORT_BY_AREA, &bigger);
602  if (overlap && (bigger == 1)) {
603  box3 = boxBoundingRegion(box1, box2);
604  boxaReplaceBox(boxa1, i, box3);
605  boxaReplaceBox(boxa2, j, boxCreate(0, 0, 0, 0));
606  boxDestroy(&box1);
607  box1 = boxCopy(box3);
608  }
609  boxDestroy(&box2);
610  }
611  boxDestroy(&box1);
612  }
613  for (i = 0; i < n2; i++) { /* 2 eats 1 */
614  if ((box2 = boxaGetValidBox(boxa2, i, L_COPY)) == NULL)
615  continue;
616  for (j = 0; j < n1; j++) {
617  if ((box1 = boxaGetValidBox(boxa1, j, L_COPY)) == NULL)
618  continue;
619  boxIntersects(box1, box2, &overlap);
620  boxCompareSize(box2, box1, L_SORT_BY_AREA, &bigger);
621  if (overlap && (bigger == 1)) {
622  box3 = boxBoundingRegion(box1, box2);
623  boxaReplaceBox(boxa2, i, box3);
624  boxaReplaceBox(boxa1, j, boxCreate(0, 0, 0, 0));
625  boxDestroy(&box2);
626  box2 = boxCopy(box3);
627  }
628  boxDestroy(&box1);
629  }
630  boxDestroy(&box2);
631  }
632  boxaDestroy(&boxac1);
633  boxaDestroy(&boxac2);
634  boxac1 = boxaSaveValid(boxa1, L_COPY); /* remove invalid boxes */
635  boxac2 = boxaSaveValid(boxa2, L_COPY);
636  boxaDestroy(&boxa1);
637  boxaDestroy(&boxa2);
638  n1 = boxaGetCount(boxac1);
639  n2 = boxaGetCount(boxac2);
640  if (n1 == n1i && n2 == n2i) break;
641  n1i = n1;
642  n2i = n2;
643  if (pixadb) {
644  pix1 = pixCreate(w + 5, h + 5, 32);
645  pixSetAll(pix1);
646  pixRenderBoxaArb(pix1, boxac1, 2, 255, 0, 0);
647  pixRenderBoxaArb(pix1, boxac2, 2, 0, 255, 0);
648  pixaAddPix(pixadb, pix1, L_INSERT);
649  }
650  }
651 
652  if (pixadb)
653  L_INFO("number of iterations: %d\n", procName, niters);
654  *pboxad1 = boxac1;
655  *pboxad2 = boxac2;
656  return 0;
657 }
658 
659 
672 BOX *
674  BOX *box2)
675 {
676 l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2, ld, td, rd, bd;
677 
678  PROCNAME("boxOverlapRegion");
679 
680  if (!box1)
681  return (BOX *)ERROR_PTR("box1 not defined", procName, NULL);
682  if (!box2)
683  return (BOX *)ERROR_PTR("box2 not defined", procName, NULL);
684 
685  boxGetGeometry(box1, &l1, &t1, &w1, &h1);
686  boxGetGeometry(box2, &l2, &t2, &w2, &h2);
687  r1 = l1 + w1 - 1;
688  r2 = l2 + w2 - 1;
689  b1 = t1 + h1 - 1;
690  b2 = t2 + h2 - 1;
691  if (b2 < t1 || b1 < t2 || r1 < l2 || r2 < l1)
692  return NULL;
693 
694  ld = L_MAX(l1, l2);
695  td = L_MAX(t1, t2);
696  rd = L_MIN(r1, r2);
697  bd = L_MIN(b1, b2);
698  return boxCreate(ld, td, rd - ld + 1, bd - td + 1);
699 }
700 
701 
714 BOX *
716  BOX *box2)
717 {
718 l_int32 l1, l2, r1, r2, t1, t2, b1, b2, w1, h1, w2, h2, ld, td, rd, bd;
719 
720  PROCNAME("boxBoundingRegion");
721 
722  if (!box1)
723  return (BOX *)ERROR_PTR("box1 not defined", procName, NULL);
724  if (!box2)
725  return (BOX *)ERROR_PTR("box2 not defined", procName, NULL);
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  ld = L_MIN(l1, l2);
734  td = L_MIN(t1, t2);
735  rd = L_MAX(r1, r2);
736  bd = L_MAX(b1, b2);
737  return boxCreate(ld, td, rd - ld + 1, bd - td + 1);
738 }
739 
740 
754 l_ok
756  BOX *box2,
757  l_float32 *pfract)
758 {
759 l_int32 w2, h2, w, h;
760 BOX *boxo;
761 
762  PROCNAME("boxOverlapFraction");
763 
764  if (!pfract)
765  return ERROR_INT("&fract not defined", procName, 1);
766  *pfract = 0.0;
767  if (!box1)
768  return ERROR_INT("box1 not defined", procName, 1);
769  if (!box2)
770  return ERROR_INT("box2 not defined", procName, 1);
771 
772  if ((boxo = boxOverlapRegion(box1, box2)) == NULL) /* no overlap */
773  return 0;
774 
775  boxGetGeometry(box2, NULL, NULL, &w2, &h2);
776  boxGetGeometry(boxo, NULL, NULL, &w, &h);
777  *pfract = (l_float32)(w * h) / (l_float32)(w2 * h2);
778  boxDestroy(&boxo);
779  return 0;
780 }
781 
782 
790 l_ok
792  BOX *box2,
793  l_int32 *parea)
794 {
795 l_int32 w, h;
796 BOX *box;
797 
798  PROCNAME("boxOverlapArea");
799 
800  if (!parea)
801  return ERROR_INT("&area not defined", procName, 1);
802  *parea = 0;
803  if (!box1)
804  return ERROR_INT("box1 not defined", procName, 1);
805  if (!box2)
806  return ERROR_INT("box2 not defined", procName, 1);
807 
808  if ((box = boxOverlapRegion(box1, box2)) == NULL) /* no overlap */
809  return 0;
810 
811  boxGetGeometry(box, NULL, NULL, &w, &h);
812  *parea = w * h;
813  boxDestroy(&box);
814  return 0;
815 }
816 
817 
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_ok
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_ok
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_ok
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_ok
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_ok
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_ok
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_ok
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_ok
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 n, i;
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  boxSetSide(box, side, val, thresh);
1886  boxDestroy(&box); /* the clone */
1887  }
1888 
1889  return boxad;
1890 }
1891 
1892 
1908 l_ok
1910  l_int32 side,
1911  l_int32 val,
1912  l_int32 thresh)
1913 {
1914 l_int32 x, y, w, h, diff;
1915 
1916  PROCNAME("boxSetSide");
1917 
1918  if (!boxs)
1919  return ERROR_INT("box not defined", procName, 1);
1920  if (side != L_SET_LEFT && side != L_SET_RIGHT &&
1921  side != L_SET_TOP && side != L_SET_BOT)
1922  return ERROR_INT("invalid side", procName, 1);
1923  if (val < 0)
1924  return ERROR_INT("val < 0", procName, 1);
1925 
1926  boxGetGeometry(boxs, &x, &y, &w, &h);
1927  if (side == L_SET_LEFT) {
1928  diff = x - val;
1929  if (L_ABS(diff) >= thresh)
1930  boxSetGeometry(boxs, val, y, w + diff, h);
1931  } else if (side == L_SET_RIGHT) {
1932  diff = x + w -1 - val;
1933  if (L_ABS(diff) >= thresh)
1934  boxSetGeometry(boxs, x, y, val - x + 1, h);
1935  } else if (side == L_SET_TOP) {
1936  diff = y - val;
1937  if (L_ABS(diff) >= thresh)
1938  boxSetGeometry(boxs, x, val, w, h + diff);
1939  } else { /* side == L_SET_BOT */
1940  diff = y + h - 1 - val;
1941  if (L_ABS(diff) >= thresh)
1942  boxSetGeometry(boxs, x, y, w, val - y + 1);
1943  }
1944 
1945  return 0;
1946 }
1947 
1948 
1970 BOXA *
1972  BOXA *boxas,
1973  l_int32 sides,
1974  l_int32 target,
1975  l_int32 thresh)
1976 {
1977 l_int32 x, y, w, h, n, i, diff;
1978 BOX *box;
1979 
1980  PROCNAME("boxaAdjustWidthToTarget");
1981 
1982  if (!boxas)
1983  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
1984  if (boxad && (boxas != boxad))
1985  return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
1986  if (sides != L_ADJUST_LEFT && sides != L_ADJUST_RIGHT &&
1987  sides != L_ADJUST_LEFT_AND_RIGHT)
1988  return (BOXA *)ERROR_PTR("invalid sides", procName, NULL);
1989  if (target < 1)
1990  return (BOXA *)ERROR_PTR("target < 1", procName, NULL);
1991 
1992  if (!boxad)
1993  boxad = boxaCopy(boxas, L_COPY);
1994  n = boxaGetCount(boxad);
1995  for (i = 0; i < n; i++) {
1996  box = boxaGetBox(boxad, i, L_CLONE);
1997  boxGetGeometry(box, &x, &y, &w, &h);
1998  diff = w - target;
1999  if (sides == L_ADJUST_LEFT) {
2000  if (L_ABS(diff) >= thresh)
2001  boxSetGeometry(box, L_MAX(0, x + diff), y, target, h);
2002  } else if (sides == L_ADJUST_RIGHT) {
2003  if (L_ABS(diff) >= thresh)
2004  boxSetGeometry(box, x, y, target, h);
2005  } else { /* sides == L_ADJUST_LEFT_AND_RIGHT */
2006  if (L_ABS(diff) >= thresh)
2007  boxSetGeometry(box, L_MAX(0, x + diff/2), y, target, h);
2008  }
2009  boxDestroy(&box);
2010  }
2011 
2012  return boxad;
2013 }
2014 
2015 
2037 BOXA *
2039  BOXA *boxas,
2040  l_int32 sides,
2041  l_int32 target,
2042  l_int32 thresh)
2043 {
2044 l_int32 x, y, w, h, n, i, diff;
2045 BOX *box;
2046 
2047  PROCNAME("boxaAdjustHeightToTarget");
2048 
2049  if (!boxas)
2050  return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL);
2051  if (boxad && (boxas != boxad))
2052  return (BOXA *)ERROR_PTR("not in-place", procName, NULL);
2053  if (sides != L_ADJUST_TOP && sides != L_ADJUST_BOT &&
2054  sides != L_ADJUST_TOP_AND_BOT)
2055  return (BOXA *)ERROR_PTR("invalid sides", procName, NULL);
2056  if (target < 1)
2057  return (BOXA *)ERROR_PTR("target < 1", procName, NULL);
2058 
2059  if (!boxad)
2060  boxad = boxaCopy(boxas, L_COPY);
2061  n = boxaGetCount(boxad);
2062  for (i = 0; i < n; i++) {
2063  box = boxaGetBox(boxad, i, L_CLONE);
2064  boxGetGeometry(box, &x, &y, &w, &h);
2065  if (w == 0 || h == 0) { /* invalid; do not alter */
2066  boxDestroy(&box);
2067  continue;
2068  }
2069  diff = h - target;
2070  if (sides == L_ADJUST_TOP) {
2071  if (L_ABS(diff) >= thresh)
2072  boxSetGeometry(box, x, L_MAX(0, y + diff), w, target);
2073  } else if (sides == L_ADJUST_BOT) {
2074  if (L_ABS(diff) >= thresh)
2075  boxSetGeometry(box, x, y, w, target);
2076  } else { /* sides == L_ADJUST_TOP_AND_BOT */
2077  if (L_ABS(diff) >= thresh)
2078  boxSetGeometry(box, x, L_MAX(0, y + diff/2), w, target);
2079  }
2080  boxDestroy(&box);
2081  }
2082 
2083  return boxad;
2084 }
2085 
2086 
2095 l_ok
2097  BOX *box2,
2098  l_int32 *psame)
2099 {
2100  PROCNAME("boxEqual");
2101 
2102  if (!psame)
2103  return ERROR_INT("&same not defined", procName, 1);
2104  *psame = 0;
2105  if (!box1 || !box2)
2106  return ERROR_INT("box1 and box2 not both defined", procName, 1);
2107  if (box1->x == box2->x && box1->y == box2->y &&
2108  box1->w == box2->w && box1->h == box2->h)
2109  *psame = 1;
2110  return 0;
2111 }
2112 
2113 
2142 l_ok
2144  BOXA *boxa2,
2145  l_int32 maxdist,
2146  NUMA **pnaindex,
2147  l_int32 *psame)
2148 {
2149 l_int32 i, j, n, jstart, jend, found, samebox;
2150 l_int32 *countarray;
2151 BOX *box1, *box2;
2152 NUMA *na;
2153 
2154  PROCNAME("boxaEqual");
2155 
2156  if (pnaindex) *pnaindex = NULL;
2157  if (!psame)
2158  return ERROR_INT("&same not defined", procName, 1);
2159  *psame = 0;
2160  if (!boxa1 || !boxa2)
2161  return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
2162  n = boxaGetCount(boxa1);
2163  if (n != boxaGetCount(boxa2))
2164  return 0;
2165 
2166  if ((countarray = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32))) == NULL)
2167  return ERROR_INT("calloc fail for countarray", procName, 1);
2168  na = numaMakeConstant(0.0, n);
2169 
2170  for (i = 0; i < n; i++) {
2171  box1 = boxaGetBox(boxa1, i, L_CLONE);
2172  jstart = L_MAX(0, i - maxdist);
2173  jend = L_MIN(n-1, i + maxdist);
2174  found = FALSE;
2175  for (j = jstart; j <= jend; j++) {
2176  box2 = boxaGetBox(boxa2, j, L_CLONE);
2177  boxEqual(box1, box2, &samebox);
2178  if (samebox && countarray[j] == 0) {
2179  countarray[j] = 1;
2180  numaReplaceNumber(na, i, j);
2181  found = TRUE;
2182  boxDestroy(&box2);
2183  break;
2184  }
2185  boxDestroy(&box2);
2186  }
2187  boxDestroy(&box1);
2188  if (!found) {
2189  numaDestroy(&na);
2190  LEPT_FREE(countarray);
2191  return 0;
2192  }
2193  }
2194 
2195  *psame = 1;
2196  if (pnaindex)
2197  *pnaindex = na;
2198  else
2199  numaDestroy(&na);
2200  LEPT_FREE(countarray);
2201  return 0;
2202 }
2203 
2204 
2221 l_ok
2223  BOX *box2,
2224  l_int32 leftdiff,
2225  l_int32 rightdiff,
2226  l_int32 topdiff,
2227  l_int32 botdiff,
2228  l_int32 *psimilar)
2229 {
2230 l_int32 l1, l2, r1, r2, t1, t2, b1, b2;
2231 
2232  PROCNAME("boxSimilar");
2233 
2234  if (!psimilar)
2235  return ERROR_INT("&similar not defined", procName, 1);
2236  *psimilar = 0;
2237  if (!box1 || !box2)
2238  return ERROR_INT("box1 and box2 not both defined", procName, 1);
2239 
2240  boxGetSideLocations(box1, &l1, &r1, &t1, &b1);
2241  boxGetSideLocations(box2, &l2, &r2, &t2, &b2);
2242  if (L_ABS(l1 - l2) > leftdiff)
2243  return 0;
2244  if (L_ABS(r1 - r2) > rightdiff)
2245  return 0;
2246  if (L_ABS(t1 - t2) > topdiff)
2247  return 0;
2248  if (L_ABS(b1 - b2) > botdiff)
2249  return 0;
2250 
2251  *psimilar = 1;
2252  return 0;
2253 }
2254 
2255 
2276 l_ok
2278  BOXA *boxa2,
2279  l_int32 leftdiff,
2280  l_int32 rightdiff,
2281  l_int32 topdiff,
2282  l_int32 botdiff,
2283  l_int32 debug,
2284  l_int32 *psimilar,
2285  NUMA **pnasim)
2286 {
2287 l_int32 i, n1, n2, match, mismatch;
2288 BOX *box1, *box2;
2289 
2290  PROCNAME("boxaSimilar");
2291 
2292  if (psimilar) *psimilar = 0;
2293  if (pnasim) *pnasim = NULL;
2294  if (!boxa1 || !boxa2)
2295  return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1);
2296  if (!psimilar)
2297  return ERROR_INT("&similar not defined", procName, 1);
2298  n1 = boxaGetCount(boxa1);
2299  n2 = boxaGetCount(boxa2);
2300  if (n1 != n2) {
2301  L_ERROR("boxa counts differ: %d vs %d\n", procName, n1, n2);
2302  return 1;
2303  }
2304  if (pnasim) *pnasim = numaCreate(n1);
2305 
2306  mismatch = FALSE;
2307  for (i = 0; i < n1; i++) {
2308  box1 = boxaGetBox(boxa1, i, L_CLONE);
2309  box2 = boxaGetBox(boxa2, i, L_CLONE);
2310  boxSimilar(box1, box2, leftdiff, rightdiff, topdiff, botdiff,
2311  &match);
2312  boxDestroy(&box1);
2313  boxDestroy(&box2);
2314  if (pnasim)
2315  numaAddNumber(*pnasim, match);
2316  if (!match) {
2317  mismatch = TRUE;
2318  if (!debug && pnasim == NULL)
2319  return 0;
2320  else if (debug)
2321  L_INFO("box %d not similar\n", procName, i);
2322  }
2323  }
2324 
2325  if (!mismatch) *psimilar = 1;
2326  return 0;
2327 }
2328 
2329 
2330 /*----------------------------------------------------------------------*
2331  * Boxa combine and split *
2332  *----------------------------------------------------------------------*/
2350 l_ok
2352  BOXA *boxas,
2353  l_int32 istart,
2354  l_int32 iend)
2355 {
2356 l_int32 n, i;
2357 BOX *box;
2358 
2359  PROCNAME("boxaJoin");
2360 
2361  if (!boxad)
2362  return ERROR_INT("boxad not defined", procName, 1);
2363  if (!boxas || ((n = boxaGetCount(boxas)) == 0))
2364  return 0;
2365 
2366  if (istart < 0)
2367  istart = 0;
2368  if (iend < 0 || iend >= n)
2369  iend = n - 1;
2370  if (istart > iend)
2371  return ERROR_INT("istart > iend; nothing to add", procName, 1);
2372 
2373  for (i = istart; i <= iend; i++) {
2374  box = boxaGetBox(boxas, i, L_CLONE);
2375  boxaAddBox(boxad, box, L_INSERT);
2376  }
2377 
2378  return 0;
2379 }
2380 
2381 
2399 l_ok
2401  BOXAA *baas,
2402  l_int32 istart,
2403  l_int32 iend)
2404 {
2405 l_int32 n, i;
2406 BOXA *boxa;
2407 
2408  PROCNAME("boxaaJoin");
2409 
2410  if (!baad)
2411  return ERROR_INT("baad not defined", procName, 1);
2412  if (!baas)
2413  return 0;
2414 
2415  if (istart < 0)
2416  istart = 0;
2417  n = boxaaGetCount(baas);
2418  if (iend < 0 || iend >= n)
2419  iend = n - 1;
2420  if (istart > iend)
2421  return ERROR_INT("istart > iend; nothing to add", procName, 1);
2422 
2423  for (i = istart; i <= iend; i++) {
2424  boxa = boxaaGetBoxa(baas, i, L_CLONE);
2425  boxaaAddBoxa(baad, boxa, L_INSERT);
2426  }
2427 
2428  return 0;
2429 }
2430 
2431 
2449 l_ok
2451  l_int32 fillflag,
2452  BOXA **pboxae,
2453  BOXA **pboxao)
2454 {
2455 l_int32 i, n;
2456 BOX *box, *boxt;
2457 
2458  PROCNAME("boxaSplitEvenOdd");
2459 
2460  if (pboxae) *pboxae = NULL;
2461  if (pboxao) *pboxao = NULL;
2462  if (!pboxae || !pboxao)
2463  return ERROR_INT("&boxae and &boxao not both defined", procName, 1);
2464  if (!boxa)
2465  return ERROR_INT("boxa not defined", procName, 1);
2466 
2467  n = boxaGetCount(boxa);
2468  *pboxae = boxaCreate(n);
2469  *pboxao = boxaCreate(n);
2470  if (fillflag == 0) {
2471  /* don't fill with invalid boxes; end up with half-size boxa */
2472  for (i = 0; i < n; i++) {
2473  box = boxaGetBox(boxa, i, L_COPY);
2474  if ((i & 1) == 0)
2475  boxaAddBox(*pboxae, box, L_INSERT);
2476  else
2477  boxaAddBox(*pboxao, box, L_INSERT);
2478  }
2479  } else {
2480  for (i = 0; i < n; i++) {
2481  box = boxaGetBox(boxa, i, L_COPY);
2482  boxt = boxCreate(0, 0, 0, 0); /* empty placeholder */
2483  if ((i & 1) == 0) {
2484  boxaAddBox(*pboxae, box, L_INSERT);
2485  boxaAddBox(*pboxao, boxt, L_INSERT);
2486  } else {
2487  boxaAddBox(*pboxae, boxt, L_INSERT);
2488  boxaAddBox(*pboxao, box, L_INSERT);
2489  }
2490  }
2491  }
2492  return 0;
2493 }
2494 
2495 
2513 BOXA *
2515  BOXA *boxao,
2516  l_int32 fillflag)
2517 {
2518 l_int32 i, n, ne, no;
2519 BOX *box;
2520 BOXA *boxad;
2521 
2522  PROCNAME("boxaMergeEvenOdd");
2523 
2524  if (!boxae || !boxao)
2525  return (BOXA *)ERROR_PTR("boxae and boxao not defined", procName, NULL);
2526  ne = boxaGetCount(boxae);
2527  no = boxaGetCount(boxao);
2528  if (ne < no || ne > no + 1)
2529  return (BOXA *)ERROR_PTR("boxa sizes invalid", procName, NULL);
2530 
2531  boxad = boxaCreate(ne);
2532  if (fillflag == 0) { /* both are approx. half-sized; all valid boxes */
2533  n = ne + no;
2534  for (i = 0; i < n; i++) {
2535  if ((i & 1) == 0)
2536  box = boxaGetBox(boxae, i / 2, L_COPY);
2537  else
2538  box = boxaGetBox(boxao, i / 2, L_COPY);
2539  boxaAddBox(boxad, box, L_INSERT);
2540  }
2541  } else { /* both are full size and have invalid placeholders */
2542  for (i = 0; i < ne; i++) {
2543  if ((i & 1) == 0)
2544  box = boxaGetBox(boxae, i, L_COPY);
2545  else
2546  box = boxaGetBox(boxao, i, L_COPY);
2547  boxaAddBox(boxad, box, L_INSERT);
2548  }
2549  }
2550  return boxad;
2551 }
BOXA * boxaIntersectsBox(BOXA *boxas, BOX *box)
boxaIntersectsBox()
Definition: boxfunc1.c:303
BOX * boxaGetNearestToPt(BOXA *boxa, l_int32 x, l_int32 y)
boxaGetNearestToPt()
Definition: boxfunc1.c:1115
l_ok boxaEqual(BOXA *boxa1, BOXA *boxa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame)
boxaEqual()
Definition: boxfunc1.c:2143
BOX * boxaGetValidBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetValidBox()
Definition: boxbasic.c:802
l_ok boxaJoin(BOXA *boxad, BOXA *boxas, l_int32 istart, l_int32 iend)
boxaJoin()
Definition: boxfunc1.c:2351
Definition: pix.h:717
l_ok boxaCombineOverlapsInPair(BOXA *boxas1, BOXA *boxas2, BOXA **pboxad1, BOXA **pboxad2, PIXA *pixadb)
boxaCombineOverlapsInPair()
Definition: boxfunc1.c:535
BOXA * boxaMergeEvenOdd(BOXA *boxae, BOXA *boxao, l_int32 fillflag)
boxaMergeEvenOdd()
Definition: boxfunc1.c:2514
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:342
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
l_ok boxContainsPt(BOX *box, l_float32 x, l_float32 y, l_int32 *pcontains)
boxContainsPt()
Definition: boxfunc1.c:1080
l_int32 boxaaGetCount(BOXAA *baa)
boxaaGetCount()
Definition: boxbasic.c:1424
l_ok boxaContainedInBoxCount(BOXA *boxa, BOX *box, l_int32 *pcount)
boxaContainedInBoxCount()
Definition: boxfunc1.c:211
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:116
l_ok boxGetSideLocations(BOX *box, l_int32 *pl, l_int32 *pr, l_int32 *pt, l_int32 *pb)
boxGetSideLocations()
Definition: boxbasic.c:371
l_ok boxaSplitEvenOdd(BOXA *boxa, l_int32 fillflag, BOXA **pboxae, BOXA **pboxao)
boxaSplitEvenOdd()
Definition: boxfunc1.c:2450
Definition: pix.h:983
l_int32 y
Definition: pix.h:483
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:781
BOXA * boxaContainedInBox(BOXA *boxas, BOX *box)
boxaContainedInBox()
Definition: boxfunc1.c:173
l_ok boxaReplaceBox(BOXA *boxa, l_int32 index, BOX *box)
boxaReplaceBox()
Definition: boxbasic.c:946
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
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:741
l_ok boxGetCenter(BOX *box, l_float32 *pcx, l_float32 *pcy)
boxGetCenter()
Definition: boxfunc1.c:1444
BOXA * boxaCopy(BOXA *boxa, l_int32 copyflag)
boxaCopy()
Definition: boxbasic.c:534
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:504
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:580
BOXA * boxaAdjustHeightToTarget(BOXA *boxad, BOXA *boxas, l_int32 sides, l_int32 target, l_int32 thresh)
boxaAdjustHeightToTarget()
Definition: boxfunc1.c:2038
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:1340
Definition: pix.h:492
BOX * boxBoundingRegion(BOX *box1, BOX *box2)
boxBoundingRegion()
Definition: boxfunc1.c:715
l_ok numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
Definition: numabasic.c:759
BOXA * boxaClipToBox(BOXA *boxas, BOX *box)
boxaClipToBox()
Definition: boxfunc1.c:385
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_ok boxSeparationDistance(BOX *box1, BOX *box2, l_int32 *ph_sep, l_int32 *pv_sep)
boxSeparationDistance()
Definition: boxfunc1.c:973
l_ok boxaaJoin(BOXAA *baad, BOXAA *baas, l_int32 istart, l_int32 iend)
boxaaJoin()
Definition: boxfunc1.c:2400
l_ok boxaaAddBoxa(BOXAA *baa, BOXA *ba, l_int32 copyflag)
boxaaAddBoxa()
Definition: boxbasic.c:1327
l_ok boxOverlapArea(BOX *box1, BOX *box2, l_int32 *parea)
boxOverlapArea()
Definition: boxfunc1.c:791
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
Definition: array.h:59
l_int32 w
Definition: pix.h:484
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:863
BOXA * boxaSaveValid(BOXA *boxas, l_int32 copyflag)
boxaSaveValid()
Definition: boxbasic.c:1095
l_ok boxaFindNearestBoxes(BOXA *boxa, l_int32 dist_select, l_int32 range, NUMAA **pnaaindex, NUMAA **pnaadist)
boxaFindNearestBoxes()
Definition: boxfunc1.c:1224
l_ok boxaGetArea(BOXA *boxa, l_int32 *parea)
boxaGetArea()
Definition: boxfunc4.c:1277
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:2222
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:618
l_ok boxContains(BOX *box1, BOX *box2, l_int32 *presult)
boxContains()
Definition: boxfunc1.c:100
BOX * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1807
l_ok boxSetSide(BOX *boxs, l_int32 side, l_int32 val, l_int32 thresh)
boxSetSide()
Definition: boxfunc1.c:1909
l_ok boxOverlapFraction(BOX *box1, BOX *box2, l_float32 *pfract)
boxOverlapFraction()
Definition: boxfunc1.c:755
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:673
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:763
l_ok boxaIntersectsBoxCount(BOXA *boxa, BOX *box, l_int32 *pcount)
boxaIntersectsBoxCount()
Definition: boxfunc1.c:341
l_int32 x
Definition: pix.h:482
l_ok boxCompareSize(BOX *box1, BOX *box2, l_int32 type, l_int32 *prel)
boxCompareSize()
Definition: boxfunc1.c:1029
Definition: pix.h:454
l_ok boxaGetExtent(BOXA *boxa, l_int32 *pw, l_int32 *ph, BOX **pbox)
boxaGetExtent()
Definition: boxfunc4.c:943
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
BOX * boxRelocateOneSide(BOX *boxd, BOX *boxs, l_int32 loc, l_int32 sideflag)
boxRelocateOneSide()
Definition: boxfunc1.c:1706
BOXA * boxaAdjustSides(BOXA *boxas, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxaAdjustSides()
Definition: boxfunc1.c:1750
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:1644
l_ok pixRenderBoxaArb(PIX *pix, BOXA *boxa, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderBoxaArb()
Definition: graphics.c:1759
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:1971
l_ok boxaContainedInBoxa(BOXA *boxa1, BOXA *boxa2, l_int32 *pcontained)
boxaContainedInBoxa()
Definition: boxfunc1.c:250
Definition: pix.h:718
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:1485
BOXA * boxaCombineOverlaps(BOXA *boxas, PIXA *pixadb)
boxaCombineOverlaps()
Definition: boxfunc1.c:441
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:2277
l_int32 h
Definition: pix.h:485
BOX * boxCopy(BOX *box)
boxCopy()
Definition: boxbasic.c:230
Definition: pix.h:134
Definition: pix.h:719
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:192
l_ok boxEqual(BOX *box1, BOX *box2, l_int32 *psame)
boxEqual()
Definition: boxfunc1.c:2096
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:1305
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:499
l_ok numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:602
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
l_ok boxIntersects(BOX *box1, BOX *box2, l_int32 *presult)
boxIntersects()
Definition: boxfunc1.c:131
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:718
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:555
l_ok boxSetGeometry(BOX *box, l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxSetGeometry()
Definition: boxbasic.c:340
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:310
Definition: pix.h:480
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:165
l_ok numaaAddNuma(NUMAA *naa, NUMA *na, l_int32 copyflag)
numaaAddNuma()
Definition: numabasic.c:1482
Definition: pix.h:517
BOXA * boxaaGetBoxa(BOXAA *baa, l_int32 index, l_int32 accessflag)
boxaaGetBoxa()
Definition: boxbasic.c:1471