/********************************/ /* asmble valdes 8 30 82 */ /* */ /* Collate horizontal runs */ /* into areas */ /********************************/ #include "focas1.h" struct objrec ob[ARMAX]; struct areas area[ARMAX]; int yp; /* y value of line being processed */ int nent, nsb; static struct smblk *head[2], /* start of area block chains */ *sfree; /* free pool of smblks */ add (rlc, type) int *rlc; int type; { struct smblk *ap, *dp, *lp, *np, *getblk (); lp = 0; for (ap = head[type];; ap = ap -> smb1.a) { if (ap == 0) { /* start new area at end of chain */ newarea (lp, rlc, type); return; } if (rlc[1] < ap -> smb2.lnp -> smb2.xmin) { newarea (lp, rlc, type); return; } if (ap -> smb2.lnp -> smb3.xmax >= rlc[0]) { for (dp = ap -> smb2.lnp -> smb1.b; (dp != 0) && (dp -> smb4.y == rlc[2]); dp = dp -> smb1.b); for (; (dp != 0) && (dp -> smb4.y == (rlc[2] - 1)); dp = dp -> smb1.b) { if ((dp -> smb2.xl <= rlc[1]) && (dp -> smb3.xr >= rlc[0])) { np = getblk ();/* create a rlc block */ np -> smb2.xl = rlc[0]; np -> smb3.xr = rlc[1]; np -> smb4.y = rlc[2]; np -> smb1.b = ap -> smb2.lnp -> smb1.b; if (rlc[0] < ap -> smb2.lnp -> smb2.xmin) ap -> smb2.lnp -> smb2.xmin = rlc[0]; if (rlc[1] > ap -> smb2.lnp -> smb3.xmax) ap -> smb2.lnp -> smb3.xmax = rlc[1]; ap -> smb2.lnp -> smb4.ytop = rlc[2]; ap -> smb2.lnp -> smb1.b = np; return; } } } lp = ap; } } newarea (lp, rlc, type) struct smblk *lp; int *rlc; int type; { struct smblk *np, *dp, *getblk (); dp = getblk (); dp -> smb2.xl = rlc[0]; dp -> smb3.xr = rlc[1]; dp -> smb4.y = rlc[2]; dp -> smb1.b = 0; np = getblk (); np -> smb2.xmin = rlc[0]; np -> smb3.xmax = rlc[1]; np -> smb4.ytop = rlc[2]; np -> smb1.b = dp; dp = getblk (); dp -> smb2.lnp = np; if (lp == 0) { dp -> smb1.a = head[type]; head[type] = dp; } else { dp -> smb1.a = lp -> smb1.a; lp -> smb1.a = dp; } } struct smblk *getblk () { char *fvalloc (); struct smblk *ap, *ip; static unsigned nget = 4000; int i; if (sfree == 0) { ip = sfree = (struct smblk *) fvalloc (nget, sizeof (struct smblk)); if (ip == 0) focaserr (1, "asmble: getblk out of space", ""); for (i = 0; i < nget - 1; i++) { ip -> smb1.a = ip + 1; ip++; } ip -> smb1.a = 0; } ap = sfree; sfree = ap -> smb1.a; ap -> smb1.a = 0; return (ap); } rtnblk (rp) struct smblk *rp; { struct smblk *ap, *lp; rp -> smb1.b = rp -> smb2.lnp; for (ap = rp; ap != 0; ap = ap -> smb1.b) lp = ap; lp -> smb1.b = sfree; sfree = rp; } /*dispose of all areas not added to during last line*/ linend () { int type; struct smblk *ap, *np, *lp, *pa; for (type = 0; type < 2; type++) { lp = 0; for (ap = head[type]; ap != 0; ap = np) { np = ap -> smb1.a; if (ap -> smb2.lnp -> smb4.ytop == yp) { lp = ap; continue; } if (lp == 0) head[type] = np;/* unlink ap as it is complete */ else lp -> smb1.a = np; ap -> smb1.a = 0; for (pa = head[type]; pa != 0; pa = pa -> smb1.a) if (as_match (pa, ap) == 0) { as_merge (pa, ap); break; } if (pa == 0) { mkarea (ap, type); } rtnblk (ap); } } } /*determine if chains have overlapping lines*/ as_match (lp, ap) struct smblk *lp, *ap; { struct smblk *ta, *tb; int ya, yb; if (lp == 0) return (1); /* no preceeding area description */ if ((ap -> smb2.lnp -> smb3.xmax < lp -> smb2.lnp -> smb2.xmin) || (ap -> smb2.lnp -> smb2.xmin > lp -> smb2.lnp -> smb3.xmax)) return (1); for (tb = ap -> smb2.lnp -> smb1.b; tb != 0; tb = tb -> smb1.b) { yb = tb -> smb4.y; for (ta = lp -> smb2.lnp -> smb1.b; (ta != 0) && (yb - (ya = ta -> smb4.y) < 2); ta = ta -> smb1.b) { if ((ya - yb == 1) || (yb - ya == 1)) if ((tb -> smb2.xl <= ta -> smb3.xr) && (tb -> smb3.xr >= ta -> smb2.xl)) return (0); } } return (1); /* no overlap */ } /*merge data in area ap into area lp*/ as_merge (lp, ap) struct smblk *lp, *ap; { struct smblk *la, *ta, *lb, *tb; lp -> smb2.lnp -> smb2.xmin = min (lp -> smb2.lnp -> smb2.xmin, ap -> smb2.lnp -> smb2.xmin); lp -> smb2.lnp -> smb3.xmax = max (lp -> smb2.lnp -> smb3.xmax, ap -> smb2.lnp -> smb3.xmax); la = lp -> smb2.lnp -> smb1.b; ta = la -> smb1.b; lb = ap -> smb2.lnp -> smb1.b; for (; lb != 0;) { if (ta == 0) { la -> smb1.b = lb; ap -> smb2.lnp -> smb1.b = 0; break; } if ((lb -> smb4.y > ta -> smb4.y) || ((lb -> smb4.y == ta -> smb4.y) && (lb -> smb2.xl > ta -> smb2.xl))) { tb = lb -> smb1.b; lb -> smb1.b = ta; la -> smb1.b = lb; la = la -> smb1.b; lb = tb; ap -> smb2.lnp -> smb1.b = tb; } else { la = ta; ta = la -> smb1.b; } } } mkarea (ap, type) struct smblk *ap; int type; { long ar, detect (); int m, x, y, dx, dy; int i; short rct[4]; if (nsb == 0) { if (type == 1) area[nsb].aflgs = DARK; else area[nsb].aflgs = 0; rct[0] = rct[1] = 0; rct[2] = sp.kpts - 1; rct[3] = sp.kscan - 1; ar = detect (ap, rct, &area[nsb]); if (ar == 0) return; /* tests on maximum size */ m = 0; dx = area[nsb].rct[2] - area[nsb].rct[0] + 1; dy = area[nsb].rct[3] - area[nsb].rct[1] + 1; x = (area[nsb].rct[0] + area[nsb].rct[2]) / 2; y = (area[nsb].rct[1] + area[nsb].rct[3]) / 2; if (dy > MXLN) { /* y extent too large */ printf ("mkarea: y extent too large y = %d %d\n", area[nsb].rct[1], area[nsb].rct[3]); m |= 01; rct[3] = y + MXLN / 2 - 1; rct[1] = y - MXLN / 2; dy = MXLN; } if (dx > MXLN) { /* X extent too large */ printf ("mkarea: x extent too large x = %d %d\n", area[nsb].rct[0], area[nsb].rct[2]); m |= 02; rct[0] = x - MXLN / 2; rct[2] = x + MXLN / 2 - 1; dx = MXLN; } if ((dx + 3) * (dy + 3) > MXSZ) {/* image area too large */ printf ("mkarea: image area too large x = %d %d dy = %d %d\n", area[nsb].rct[0], area[nsb].rct[2], area[nsb].rct[1], area[nsb].rct[3]); m |= 04; i = sqrt ((float) dx / dy * MXSZ) - 3; dy = sqrt ((float) dy / dx * MXSZ) - 3; dx = i; if ((dx + 3) * (dy + 3) > MXSZ) dx = dy = 300; rct[0] = x - dx / 2; rct[1] = y - dy / 2; rct[2] = x + dx / 2; rct[3] = y + dy / 2; printf ("mkarea: new area x = %d %d dy = %d %d\n", rct[0], rct[2], rct[1], rct[3]); } if (m) { /* constrain segmentation to bounding rectangle */ ar = detect (ap, rct, &area[nsb]); area[nsb].aflgs |= SIZE; if (ar > 0) { dx = area[nsb].rct[2] - area[nsb].rct[0]; dy = area[nsb].rct[3] - area[nsb].rct[1]; if ((dx + 3) * (dy + 3) >= MXSZ) { printf ("mkarea: image still too large x = %d %d dy = %d %d\n", area[nsb].rct[0], area[nsb].rct[2], area[nsb].rct[1], area[nsb].rct[3]); return; } } else printf ("mkarea: area = 0\n"); } if (ar >= sp.minarea) { ob[nsb].entnum = nent; ob[nsb].subent = 0; ob[nsb].sbr = 0.; ob[nsb].eflgs = area[nsb].aflgs; ob[nsb].xc = lpcoords ((area[nsb].xmax + area[nsb].xmin)/2., 1, 1); ob[nsb].yc = lpcoords (area[nsb].d.ychst-area[nsb].d.nlines/2.,2,1); ob[nsb].area = ar; ob[nsb].tarea = totarea (&area[nsb], sp.grow); if (ob[nsb].tarea == 0) ob[nsb].tarea = ob[nsb].area; strcpy (ob[nsb].class, "u"); ob[nsb].arpos = wrarea (afd, &ob[nsb], &area[nsb]); wtcat (&ob[nsb], cfd); nent++; } } /* For split objects */ else if (nsb < ARMAX) { area[nsb].aflgs = area[0].aflgs; ar = detect (ap, area[0].rct, &area[nsb]); ob[nsb].area = ar; ob[nsb].sbr = ob[0].sbr; ob[nsb].ssbr = ob[0].ssbr; ob[nsb].nsbr = ob[0].nsbr; ob[nsb].eflgs = area[nsb].aflgs; ob[nsb].tarea = totarea (&area[nsb], sp.grow); if (ob[nsb].tarea == 0) ob[i].tarea = ob[nsb].area; if (sptevl (0) == 0) nsb++; } else printf ("mkarea: Too many fragments\n"); } dmpards (ap) struct smblk *ap; { struct smblk *pp; for (pp = ap -> smb2.lnp; pp != 0; pp = pp -> smb1.b) printf ("y = %4d xl = %4d xr = %4d\n", pp -> smb4.y, pp -> smb2.xl, pp -> smb3.xr); fflush (stdout); }