262 lines
6.9 KiB
C
262 lines
6.9 KiB
C
/*
|
||
* 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 <stdio.h>
|
||
#include "utils/magic.h"
|
||
#include "utils/geometry.h"
|
||
#include "database/database.h"
|
||
#include "tiles/tile.h"
|
||
|
||
|
||
typedef struct dbcellboundstruct
|
||
{
|
||
Rect *area;
|
||
bool extended;
|
||
bool found;
|
||
} DBCellBoundStruct;
|
||
|
||
/*
|
||
* --------------------------------------------------------------------
|
||
* --------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
DBBoundCellPlane(def, extended, rect)
|
||
CellDef *def;
|
||
bool 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 (TiSrArea((Tile *)NULL, def->cd_planes[PL_CELL],
|
||
&TiPlaneRect, dbCellBoundFunc, (ClientData) &filter) == 0)
|
||
return cbs.found;
|
||
else
|
||
return -1;
|
||
}
|
||
|
||
int
|
||
dbCellBoundFunc(tile, fp)
|
||
Tile *tile;
|
||
TreeFilter *fp;
|
||
{
|
||
CellUse *use;
|
||
CellTileBody *body;
|
||
Rect *bbox;
|
||
DBCellBoundStruct *cbs;
|
||
|
||
cbs = (DBCellBoundStruct *)fp->tf_arg;
|
||
|
||
for (body = (CellTileBody *) TiGetBody(tile); body != NULL;
|
||
body = body->ctb_next)
|
||
{
|
||
use = body->ctb_use;
|
||
bbox = &use->cu_bbox;
|
||
if ((BOTTOM(tile) <= bbox->r_ybot) && (RIGHT(tile) >= bbox->r_xtop))
|
||
{
|
||
if (cbs->found)
|
||
{
|
||
if (cbs->extended)
|
||
GeoInclude(&use->cu_extended, cbs->area);
|
||
else
|
||
GeoInclude(&use->cu_bbox, cbs->area);
|
||
}
|
||
else
|
||
{
|
||
if (cbs->extended)
|
||
*cbs->area = use->cu_extended;
|
||
else
|
||
*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);
|
||
}
|