mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-29 09:30:46 +02:00
label text) vs. non-extended bounding box of a cell when doing "getcell" (and probably a number of other commands/functions, as well). A function was always computing the extended bounding box and then setting both the normal and extended bounding boxes of the cell to this value, resulting in incorrect cell selections.
259 lines
6.9 KiB
C
259 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;
|
|
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);
|
|
}
|