/* * DBbound.c -- * * Computation of boundaries of a database tile plane. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #ifndef lint static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/database/DBbound.c,v 1.2 2008/12/11 04:20:04 tim Exp $"; #endif /* not lint */ #include #include "utils/magic.h" #include "utils/geometry.h" #include "database/database.h" #include "tiles/tile.h" typedef struct dbcellboundstruct { Rect *area; Rect *extended; bool found; } DBCellBoundStruct; /* * -------------------------------------------------------------------- * DBBoundCellPlane --- * * Find the extents of all subcells of the cell "def", both the * extent of geometry (rect) and the extent of geometry plus any * labels extending outside the extent of geometry (extended). * * Results: * TRUE if subcells were found and measured; FALSE if no subcells * were found (in which case "extended" and "rect" may not be * valid). * * Side effects: * Values may be recorded in "extended" and "rect". * -------------------------------------------------------------------- */ int DBBoundCellPlane(def, extended, rect) CellDef *def; Rect *extended; Rect *rect; { TreeFilter filter; DBCellBoundStruct cbs; int dbCellBoundFunc(); Plane *plane; filter.tf_func = NULL; filter.tf_arg = (ClientData)&cbs; cbs.area = rect; cbs.extended = extended; cbs.found = FALSE; *rect = GeoNullRect; if (DBSrCellPlaneArea(def->cd_cellPlane, &TiPlaneRect, dbCellBoundFunc, (ClientData) &filter) == 0) return cbs.found; else return -1; } int dbCellBoundFunc(use, fp) CellUse *use; TreeFilter *fp; { DBCellBoundStruct *cbs; cbs = (DBCellBoundStruct *)fp->tf_arg; if (cbs->found) { GeoInclude(&use->cu_extended, cbs->extended); GeoInclude(&use->cu_bbox, cbs->area); } else { *cbs->extended = use->cu_extended; *cbs->area = use->cu_bbox; cbs->found = TRUE; } return 0; } /* * -------------------------------------------------------------------- * * DBBoundPlane -- * * Determine the bounding rectangle for the supplied tile plane. * The bounding rectangle is the smallest rectangle that completely * encloses all non-space tiles. * * If the tile plane is completely empty, we return a 0x0 bounding * box at the origin. * * Results: * TRUE if the tile plane contains any geometry, FALSE * if it is completely empty. * * Side effects: * Sets *rect to the bounding rectangle. * * -------------------------------------------------------------------- */ bool DBBoundPlane(plane, rect) Plane *plane; Rect *rect; { Tile *left, *right, *top, *bottom, *tp; left = plane->pl_left; right = plane->pl_right; top = plane->pl_top; bottom = plane->pl_bottom; rect->r_ur = TiPlaneRect.r_ll; rect->r_ll = TiPlaneRect.r_ur; /* * To find the rightmost and leftmost solid edges, we * scan along the respective edges. Our assumption is * that the only tiles along the edges are space tiles, * which, by the maximum horizontal strip property, must * have either solid tiles or the edge of the plane on * their other sides. */ for (tp = TR(left); tp != bottom; tp = LB(tp)) if (RIGHT(tp) < rect->r_xbot) rect->r_xbot = RIGHT(tp); for (tp = BL(right); tp != top; tp = RT(tp)) if (LEFT(tp) > rect->r_xtop) rect->r_xtop = LEFT(tp); /* * We assume that only space tiles extend all the way * from the left edge of the plane to the right. We * also assume that the topmost and bottommost tiles * are space tiles. */ rect->r_ytop = BOTTOM(LB(top)); rect->r_ybot = TOP(RT(bottom)); /* * If the bounding rectangle is degenerate (indicating no solid * tiles in the plane), we make it the 1x1 rectangle: (0,0)::(1,1). */ if (rect->r_xtop < rect->r_xbot || rect->r_ytop < rect->r_ybot) { rect->r_xbot = rect->r_xtop = 0; rect->r_ybot = rect->r_ytop = 0; return (FALSE); } return (TRUE); } /* * -------------------------------------------------------------------- * * DBBoundPlaneVert -- * * Determine the bounding rectangle for the supplied tile plane, * which is organized into maximal vertical strips instead of * maximal horizontal ones. * * The bounding rectangle is the smallest rectangle that completely * encloses all non-space tiles. * * If the tile plane is completely empty, we return a 0x0 bounding * box at the origin. * * Results: * TRUE if the tile plane contains any geometry, FALSE * if it is completely empty. * * Side effects: * Sets *rect to the bounding rectangle. * * -------------------------------------------------------------------- */ bool DBBoundPlaneVert(plane, rect) Plane *plane; Rect *rect; { Tile *left, *right, *top, *bottom, *tp; left = plane->pl_left; right = plane->pl_right; top = plane->pl_top; bottom = plane->pl_bottom; rect->r_ur = TiPlaneRect.r_ll; rect->r_ll = TiPlaneRect.r_ur; /* * To find the topmost and bottommost solid edges, we * scan along the respective edges. Our assumption is * that the only tiles along the edges are space tiles, * which, by the maximum vertical strip property, must * have either solid tiles or the edge of the plane on * their other sides. */ for (tp = RT(bottom); tp != left; tp = BL(tp)) if (TOP(tp) < rect->r_ybot) rect->r_ybot = TOP(tp); for (tp = LB(top); tp != right; tp = TR(tp)) if (BOTTOM(tp) > rect->r_ytop) rect->r_ytop = BOTTOM(tp); /* * We assume that only space tiles extend all the way * from the top edge of the plane to the bottom. We * also assume that the leftmost and rightmost tiles * are space tiles. */ rect->r_xtop = LEFT(BL(right)); rect->r_xbot = RIGHT(TR(left)); /* * If the bounding rectangle is degenerate (indicating no solid * tiles in the plane), we make it the 1x1 rectangle: (0,0)::(1,1). */ if (rect->r_xtop < rect->r_xbot || rect->r_ytop < rect->r_ybot) { rect->r_xbot = rect->r_xtop = 0; rect->r_ybot = rect->r_ytop = 0; return (FALSE); } return (TRUE); }