Moved new work on magic-8.4 (experimental merging of micromagic bplane structure

into magic-8.2) into the newly-reorganized git repo as branch "bplane".
This commit is contained in:
Tim Edwards 2019-03-22 19:58:47 -04:00
parent 465a46c1c6
commit 1d04f20f5d
59 changed files with 4507 additions and 1790 deletions

View File

@ -6,9 +6,9 @@ MAGICDIR = .
PROGRAMS = magic
TECH = scmos
LIBRARIES = database utils extflat
MODULES = cmwind commands database dbwind debug drc extflat extract \
graphics netmenu plow resis select sim textio tiles utils \
windows wiring
MODULES = bplane cmwind commands database dbwind debug drc extflat \
extract graphics netmenu plow resis select sim textio tiles \
utils windows wiring
MAKEFLAGS =
INSTALL_CAD_DIRS = windows doc ${TECH}

View File

@ -1 +1 @@
8.2.101
8.4.0

10
bplane/Makefile Normal file
View File

@ -0,0 +1,10 @@
#
# rcsid "$Header: /usr/cvsroot/magic-8.0/drc/Makefile,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"
#
MODULE = bplane
MAGICDIR = ..
SRCS = bpDump.c bpUtils.c bpBins.c bpEnum.c bpMain.c bpStat.c
include ${MAGICDIR}/defs.mak
include ${MAGICDIR}/rules.mak

38
bplane/README Normal file
View File

@ -0,0 +1,38 @@
TODO
----
NOTE: nested enums are broken do to dynamic binning.
Don't rebuild entire bplane when bbox grows.
unsubbing sometimes.
Some (remaining) bplane design issues:
groups?
idea: support small number of groups by having
separate bplane for each group. Do selection this
way. Logically layered on top of bplanes - but may
want to integrate.
DECISION: defer for now.
pack/unpack?
Seems incompatible with user alloc/dealloc.
Complicated.
DECISION: Forget it.
coarse/fine with cache.
can be added later. should fit in nicely.
no special support needed.
integrated find/add?
can add later.
don't worry about it now.
May want to add attributes, via external hash.

716
bplane/bpBins.c Normal file
View File

@ -0,0 +1,716 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
/* bpBins.c
*
* Routines for creating and manipulating bin arrays.
*
*/
#include <stdio.h>
#include <math.h>
#include "utils/utils.h"
#include "utils/malloc.h"
#include "database/database.h"
#include "utils/geometry.h"
#include "bplane/bplaneInt.h"
/* debug */
#define BPD 0
/* Tcl linked Parameters */
int bpMinBAPop = 10; /* don't sub(bin) when count less than this */
double bpMinAvgBinPop = 1.0; /* try to keep average bin pop at or
* below this
*/
/*
* ----------------------------------------------------------------------------
*
* roundUp -- Round up a number to a grid.
*
* ----------------------------------------------------------------------------
*/
static __inline__ int roundUp(int i, int res)
{
int r = (i % res);
/* Subtract negative number */
if (r > 0) r = r - res;
return i - r;
}
/*
* ----------------------------------------------------------------------------
*
* bpBinArrayNew -- allocate new bin array.
*
* ----------------------------------------------------------------------------
*/
static BinArray *bpBinArrayNew(int dx, /* x diameter of bins */
int dy, /* y diameter of bins */
Rect *bbox) /* area covered */
{
BinArray *new;
Rect abbox;
int w, h, dimX, dimY, numBins;
int size;
/* compute array dimensions */
w = roundUp(GEO_WIDTH(bbox),dx);
h = roundUp(GEO_HEIGHT(bbox),dy);
dimX = w/dx;
dimY = h/dy;
numBins = dimX*dimY;
/* allocate array */
size = sizeof(BinArray) + numBins*(sizeof(void *));
new = (BinArray *)callocMagic(size);
/* initial */
new->ba_bbox = *bbox;
new->ba_dx = dx;
new->ba_dy = dy;
new->ba_dimX = dimX;
new->ba_numBins = numBins;
/* pull bbox back one from top-edge, right-edge, to simplify index
* computation in bpEnumPush
*/
new->ba_bbox.r_xtop --;
new->ba_bbox.r_ytop --;
return new;
}
/*
* ----------------------------------------------------------------------------
*
* bpBinAdd -- add element to bin array
*
* ----------------------------------------------------------------------------
*/
void bpBinAdd(BinArray *ba,
Element *e)
{
int i; /* bin index */
/* compute bin index */
if(GEO_WIDTH(&e->e_rect) >= ba->ba_dx ||
GEO_HEIGHT(&e->e_rect) >= ba->ba_dy)
{
/* oversized */
i = ba->ba_numBins;
}
else
{
/* x and y indices */
int xi = (e->e_rect.r_xbot - ba->ba_bbox.r_xbot) / ba->ba_dx;
int yi = (e->e_rect.r_ybot - ba->ba_bbox.r_ybot) / ba->ba_dy;
i = xi + yi*ba->ba_dimX ;
}
/* add element */
if(bpBinType(ba,i) == BT_ARRAY)
{
/* sub-binned */
bpBinAdd(bpSubArray(ba,i), e);
}
else
{
/* simple list */
Element *next = bpBinList(ba,i);
/* link with next */
e->e_link = next;
if(next) next->e_linkp = &e->e_link;
/* link to head */
ba->ba_bins[i] = e;
e->e_linkp = (Element **) &ba->ba_bins[i];
}
}
/*
* ----------------------------------------------------------------------------
*
* bpBinArrayUnbuild - remove elements from bin array and Free the array
*
* Returns: (singly linked) list of elements formerly in the array
*
* ----------------------------------------------------------------------------
*/
static Element *bpBinArrayUnbuild(BinArray *ba)
{
Element *elements = NULL;
int numBins = ba->ba_numBins;
int i;
/* empty the bins */
for(i=0;i<=numBins;i++)
{
Element *l;
if(bpBinType(ba,i) == BT_ARRAY)
{
/* sub-array, unbuild recursively */
l = bpBinArrayUnbuild(bpSubArray(ba,i));
}
else
{
/* Simple list */
l = bpBinList(ba,i);
}
/* collect elements */
while(l)
{
Element *e = l;
l = e->e_link;
e->e_link = elements;
elements = e;
}
}
/* free the array */
freeMagic((char *)ba);
return elements;
}
/*
* ----------------------------------------------------------------------------
* bpListExceedsQ --
*
* check if element list exceeds given length
*
* Returns size of list.
*
* ----------------------------------------------------------------------------
*/
static __inline__ int
bpListExceedsQ(Element *e, /* list */
int n) /* length to check against */
{
n++;
while(e && n)
{
n--;
e = e->e_link;
}
return n==0;
}
/*
* ----------------------------------------------------------------------------
*
* bpBinArraySizeIt -- choose bin sizes for new bin array.
*
* RESULT:
*
* normally returns TRUE,
* returns FALSE on failure: could not come up with binning that
* makes progress.
*
* NOTE: the various 'return' parameters are not set on failure.
*
* ----------------------------------------------------------------------------
*/
static __inline__ bool
bpBinArraySizeIt(Rect *bbox, /* bin array bbox */
Element *elements, /* initial elements */
int *dxp, /* return bin x-diameter here */
int *dyp, /* return bin y-diameter here */
int *maxDXp,
int *maxDYp,
int *numBinsp, /* return number of bins here */
int *countp) /* return number of elements here */
{
BinArray *ba;
int count;
double numBins; /* need double to avoid overflow on tentative calc. */
int h = GEO_HEIGHT(bbox);
int w = GEO_WIDTH(bbox);
int dx,dy; /* individual bin diameter */
int maxEX, maxEY; /* max element dimensions */
int maxDX, maxDY; /* max bin diameter allowed */
int xDim, yDim; /* array dimensions */
int maxBins; /* max number of bins
* (due to bpMinAvgBinPop)
*/
/* compute max element dimensions
* (would like bins coarser than max dimensisons)
*/
{
Element *e;
maxEX = 0;
maxEY = 0;
count = 0;
for(e=elements; e; e=e->e_link)
{
int ew = GEO_WIDTH(&e->e_rect);
int eh = GEO_HEIGHT(&e->e_rect);
maxEX = MAX(maxEX,ew);
maxEY = MAX(maxEY,eh);
count++;
}
}
/* if too few elements, don't bother with binning */
if(count < bpMinBAPop) return FALSE;
/* if too tiny don't subbin,
* avoid nasty corner-cases in code below
*/
if(h<2 || w<2) return FALSE;
/* tentatively choose bin size to fit all elements */
dx = maxEX+1;
dy = maxEY+1;
/* ensure we get at least two bins, so that
* subbining of sparse designs will work.
*/
maxDX = (w+1)/2;
maxDY = (h+1)/2;
/*
fprintf(stderr,"bpBinArraySizeIt, initial "
"maxEX=%d maxEY=%d maxDX=%d maxDY=%d dx=%d dy=%d\n",
maxEX,maxEY,maxDX,maxDY,dx,dy);
*/
if(dx <= maxDX)
{
/* x is cool */
if(dy <= maxDY)
{
/* totally cool */
;
}
else
{
/* y-dim too big for two bins, but x-dim cool,
* just reduce in x this time.
*/
dy = h+1;
}
}
else
{
/* x-dim too big for two bins */
if(dy <= maxDY)
{
/* x-dim too big for two bins but y=dim cool,
* just reduce in y this time
*/
dx = w+1;
}
else
{
/* BOTH x-dim and y-dim too big for two bins.
* We are screwed: will have some oversized.
*
* Choose betwen splitting in two horizontally or
* vertically, by which ever method results in the minimum
* number of oversized elements.
*/
int xOver=0; /* number of oversized if we reduce x-dim. */
int yOver=0; /* number of oversized if we reduce y-dim. */
Element *e;
/* count potential oversized */
for(e=elements; e; e=e->e_link)
{
int ew = GEO_WIDTH(&e->e_rect);
int eh = GEO_HEIGHT(&e->e_rect);
if(ew >= maxDX) xOver++;
if(eh >= maxDY) yOver++;
}
if(xOver<yOver)
{
/* reduce x-dim to minimize oversized */
dx = maxDX;
dy = h+1;
}
else
{
/* are we making progress? */
if(yOver == count) return FALSE;
/* reduce y-dim to minimize oversized */
dx = w+1;
dy = maxDY;
}
}
}
/* tentative number of bins */
xDim = roundUp(w,dx)/dx;
yDim = roundUp(h,dy)/dy;
numBins = xDim*((double)yDim);
/* if too many bins, need to increase at least one dimension */
/* (note this step will NOT reduce dimensions) */
maxBins = MAX(count / bpMinAvgBinPop,1);
/*
fprintf(stderr,"DEBUG numBins = %g count= %d bpMinAvgBinPop=%f maxBins= %d\n",
numBins,count,bpMinAvgBinPop,maxBins);
*/
if(numBins>maxBins)
{
if(dx == w+1)
{
/* can't increase x-dim, so try increasing y-dim */
int yDimTarget = maxBins/xDim;
dy = (h+1) / MAX(yDimTarget,1);
dy = MIN(dy,maxDY);
}
else if (dy == h+1)
{
/* can't increase y-dim, so try increasing x-dim */
int xDimTarget = maxBins/yDim;
dx = (w+1) / MAX(xDimTarget,1);
dx = MIN(dx,maxDX);
}
else
{
/* try for square bins */
double area = h * (w + 0.0);
int d = MAX(sqrt(area/maxBins),1);
if(d<dx)
{
/* target d too small in x-dim
* leave xdim fixed and just increase y-dim
*/
int yDimTarget = maxBins/xDim;
dy = (h+1) / MAX(yDimTarget,1);
dy = MIN(dy,maxDY);
}
else if (d<dy)
{
/* target d too small in y-dim
* leave xdim fixed and just increase y-dim
*/
int xDimTarget = maxBins/yDim;
dx = (w+1) / MAX(xDimTarget,1);
dx = MIN(dx,maxDX);
}
else if(d>maxDX)
{
/* d too big for x-dim
* (this can happen for tall skinny bins)
*
* make x-dim maximal, and adjust y accordingly
*/
dx = w+1;
dy = MAX((h+1)/maxBins,dy);
dy = MIN(dy,maxDY);
}
else if(d>maxDY)
{
/* d too big for y-dim
* (this can happen for long squat bins)
*
* make y-dim maximal, and adjust x-dim accordingly
*/
dy = h+1;
dx = MAX((w+1)/maxBins,dx);
dx = MIN(dx,maxDX);
}
else
{
/* we're cool, create square bins */
dx = d;
dy = d;
}
}
/* update numBins */
xDim = roundUp(w,dx)/dx;
yDim = roundUp(h,dy)/dy;
numBins = xDim*yDim;
}
/* DEBUG */
if(BPD)
{
fprintf(stderr,"\nDEBUG bpBinArraySizeIt DONE, count=%d h=%d w=%d\n"
"\tmaxDX=%d maxDY=%d maxBins=%d\n"
"\tnumBins=%g dx=%d dy=%d\n",
count,h,w,
maxDX,maxDY,maxBins,
numBins,dx,dy);
}
/* set results */
if(dxp) *dxp = dx;
if(dyp) *dyp = dy;
if(maxDXp) *maxDXp = maxDX;
if(maxDYp) *maxDYp = maxDY;
if(numBinsp) *numBinsp = numBins;
if(countp) *countp = count;
/* success */
return TRUE;
}
/*
* ----------------------------------------------------------------------------
*
* bpBinArrayBuild1 -- build and populate bin array of given area and
* bin size.
*
* Returns: pointer to new bin array.
*
* ----------------------------------------------------------------------------
*/
static BinArray *bpBinArrayBuild1(Rect *bbox,
Element *elements, /* initial elements */
int dx, /* bin diameter */
int dy)
{
BinArray *ba;
/* build bin array */
ba = bpBinArrayNew(dx, dy, bbox);
/* transfer elements to bin array */
while(elements)
{
Element *e;
/* pop list */
e = elements;
elements = e->e_link;
bpBinAdd(ba, e);
}
return ba;
}
/*
* ----------------------------------------------------------------------------
*
* bpBinArrayBuild -- build and populate bin array of given area,
*
* NOTE: optimal bin size determined by trial and error.
* oversized subbinned, as indicated.
*
* Returns: pointer to new bin array, NULL on failure.
*
* ----------------------------------------------------------------------------
*/
BinArray *bpBinArrayBuild(Rect bbox,
Element *elements, /* initial elements */
bool subbin) /* subbin as needed */
{
BinArray *ba;
int dx,dy; /* individual bin diameter */
int maxDX, maxDY;
int numBins;
int count;
if(BPD) DumpRect("#### bpBinArrayBuild, TOP bbox= ", &bbox);
/* figure out good bin dimensions */
if(!bpBinArraySizeIt(&bbox,
elements,
&dx,
&dy,
&maxDX,
&maxDY,
&numBins,
&count)) return NULL;
/* build the bin array */
ba = bpBinArrayBuild1(&bbox, elements, dx, dy);
if(!subbin) return ba;
/* sub-bin normal bins */
{
int dimX = ba->ba_dimX;
int i;
for(i=0;i<numBins;i++)
{
BinArray *sub;
sub = bpBinArrayBuild(bpBinArea(ba,i),
bpBinList(ba, i),
TRUE);
if(sub)
{
ba->ba_bins[i] =
(void *) ((pointertype) sub | BT_ARRAY);
}
}
}
/* sub-bin oversized */
{
BinArray *sub;
sub = bpBinArrayBuild(bbox,
bpBinList(ba, numBins),
TRUE);
if(sub)
{
ba->ba_bins[numBins] =
(void *) ((pointertype) sub | BT_ARRAY);
}
}
if(BPD)
{
DumpRect("\n#### bpBinArrayBuild, DONE bbox= ", &bbox);
fprintf(stderr,"\n");
}
return ba;
}
/*
* ----------------------------------------------------------------------------
*
* bpBinsUpdate -- update bplane bins
*
* Called prior to enumerations.
*
* ----------------------------------------------------------------------------
*/
int bpBinLife = 0;
void bpBinsUpdate(BPlane *bp)
{
Rect bbox;
bool oldBins;
/* rebuild whenever inbox gets big */
if(!bpListExceedsQ(bp->bp_inBox, bpMinBAPop-1)) return;
/* fprintf(stderr,"DEBUG bpBinsUpdate - rebuilding bins.\n"); */
/* do bins already exist ? */
oldBins = (bp->bp_rootNode != 0);
/* if bins exist, dissolve them */
if(oldBins)
{
Element *elist = bpBinArrayUnbuild(bp->bp_rootNode);
/* add inbox to list */
while(bp->bp_inBox)
{
/* pop from inbox */
Element *e = bp->bp_inBox;
bp->bp_inBox = e->e_link;
/* add to elist */
e->e_link = elist;
elist = e;
}
bp->bp_inBox = elist;
}
/* compute accurate bbox */
{
Element *e = bp->bp_inBox;
bbox = e->e_rect;
for(e=bp->bp_inBox; e; e=e->e_link)
{
GeoIncludeRectInBBox(&e->e_rect, &bbox);
}
}
/* if rebuild, double bounding box, to avoid too many rebuilds */
if(oldBins)
{
int dx = GEO_WIDTH(&bbox)/2;
int dy = GEO_HEIGHT(&bbox)/2;
bbox.r_xbot -= dx;
bbox.r_ybot -= dy;
bbox.r_xtop += dx;
bbox.r_ytop += dy;
}
/* build and populate bin array */
bp->bp_rootNode = bpBinArrayBuild(bbox, bp->bp_inBox, TRUE);
if(bp->bp_rootNode) bp->bp_inBox = NULL;
bp->bp_binArea = bbox;
bp->bp_binLife = bpBinLife;
bp->bp_inAdds = 0;
/* if(BPD) bpDump(bp, 0); */
}

316
bplane/bpDump.c Normal file
View File

@ -0,0 +1,316 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
/* bpDump.c
*
* routines to dump bin system (for debugging)
*
*/
#include <stdio.h>
#include "utils/utils.h"
#include "database/database.h"
#include "utils/geometry.h"
#include "bplane/bplaneInt.h"
static int bpDumpFlags; /* set by bpDump, used by subroutines */
/*
* ----------------------------------------------------------------------------
* bpIndent --
*
* tab over n spaces on stderr
*
* ----------------------------------------------------------------------------
*/
static void bpIndent(int n)
{
int i;
for(i=0;i<n;i++) fprintf(stderr," ");
}
/*
* ----------------------------------------------------------------------------
* bpDumpRect --
*
* list rects.
*
* ----------------------------------------------------------------------------
*/
void bpDumpRect(Rect *r)
{
if(bpDumpFlags & BPD_INTERNAL_UNITS)
{
fprintf(stderr,"%d ",
r->r_xbot);
fprintf(stderr,"%d ",
r->r_ybot);
fprintf(stderr,"%d ",
r->r_xtop);
fprintf(stderr,"%d",
r->r_ytop);
}
else
{
fprintf(stderr,"%s ",
UnitsI2S(r->r_xbot));
fprintf(stderr,"%s ",
UnitsI2S(r->r_ybot));
fprintf(stderr,"%s ",
UnitsI2S(r->r_xtop));
fprintf(stderr,"%s",
UnitsI2S(r->r_ytop));
}
}
/*
* ----------------------------------------------------------------------------
* bpDumpElements --
*
* list rects.
*
* ----------------------------------------------------------------------------
*/
void bpDumpElements(Element *list, int indent)
{
Element *e;
for(e = list; e; e=e->e_link)
{
bpIndent(indent);
fprintf(stderr,"{element ");
if(bpDumpFlags & BPD_LABELED)
{
LabeledElement *le = (LabeledElement *) e;
fprintf(stderr,"%s ", le->le_text);
}
bpDumpRect(&e->e_rect);
fprintf(stderr,"}\n");
}
}
/*
* ----------------------------------------------------------------------------
* bpDumpEnums --
*
* list active enumerations
*
* ----------------------------------------------------------------------------
*/
void bpDumpEnums(BPEnum *bpe, int indent)
{
for(; bpe; bpe=bpe->bpe_next)
{
bpIndent(indent);
fprintf(stderr,"{enum \"%s\"}",
bpe->bpe_id);
}
}
/*
* ----------------------------------------------------------------------------
* bpBinArrayDump --
*
* recursively dump hierarchical bin system
*
* ----------------------------------------------------------------------------
*/
static void bpBinArrayDump(BinArray *ba, int indent)
{
int numBins = ba->ba_numBins;
int dx = ba->ba_dx;
int dy = ba->ba_dy;
int dimX = ba->ba_dimX;
int dimY = numBins/dimX;
Rect *bbox = &ba->ba_bbox;
int xi,yi;
/* open */
bpIndent(indent);
fprintf(stderr,"{bin-array ");
if(bpDumpFlags & BPD_INTERNAL_UNITS)
{
fprintf(stderr,"{dx %d} {dy %d} ",
dx,dy);
}
else
{
fprintf(stderr,"{dx %s} ",
UnitsI2S(dx));
fprintf(stderr,"{dy %s} ",
UnitsI2S(dy));
}
fprintf(stderr,"{dimX %d} {dimY %d} { bbox ",
dimX,
dimY);
bpDumpRect(bbox);
fprintf(stderr," }\n");
/* bins */
for(yi=0; yi<dimY; yi++)
{
for(xi=0; xi<dimX; xi++)
{
Rect area;
int i = xi + yi*dimX;
area.r_xbot = bbox->r_xbot + xi*dx;
area.r_ybot = bbox->r_ybot + yi*dy;
area.r_xtop = area.r_xbot + dx;
area.r_ytop = area.r_ybot + dy;
/* skip empty bins */
if(bpBinEmpty(ba,i)) continue;
/* open bin */
bpIndent(indent+2);
fprintf(stderr,"{bin {number %d} { bbox ",
i);
bpDumpRect(&area);
fprintf(stderr," }\n");
/* list bin contents */
if(bpBinType(ba,i) == BT_ARRAY)
{
/* dump sub array */
bpBinArrayDump( bpSubArray(ba,i),
indent+4);
}
else
{
/* list elements */
bpDumpElements(bpBinList(ba,i),indent+4);
}
/* close bin */
bpIndent(indent+2);
fprintf(stderr,"}\n");
}
}
/* oversized */
if(!bpBinEmpty(ba,numBins))
{
/* open oversized */
bpIndent(indent+2);
fprintf(stderr,"{oversized {bbox ");
bpDumpRect(bbox);
fprintf(stderr,"}\n");
/* list bin contents */
if(bpBinType(ba,numBins) == BT_ARRAY)
{
/* dump sub array */
bpBinArrayDump( bpSubArray(ba,numBins),
indent+4);
}
else
{
/* list elements */
bpDumpElements(bpBinList(ba,numBins),indent+4);
}
/* close oversized */
bpIndent(indent+2);
fprintf(stderr,"}\n");
}
/* close bin array */
bpIndent(indent);
fprintf(stderr,"}\n");
}
/*
* ----------------------------------------------------------------------------
* bpDump --
*
* dump bplane (for debugging)
*
* ----------------------------------------------------------------------------
*/
void bpDump(BPlane *bp, int flags)
{
fprintf(stderr, "======= BPLANE DUMP ======\n");
bpDumpFlags = flags;
/* open bplane */
fprintf(stderr,"{bplane {count %d} {bbox ",
bp->bp_count);
bpDumpRect(&bp->bp_bbox);
fprintf(stderr,"}\n");
/* list in box rects */
bpIndent(2);
fprintf(stderr,"{in_box\n");
bpDumpElements(bp->bp_inBox,4);
bpIndent(2);
fprintf(stderr,"}\n");
/*** bins ***/
bpIndent(2);
fprintf(stderr,"{binned {area ");
bpDumpRect(&bp->bp_binArea);
fprintf(stderr,"}\n");
if(bp->bp_rootNode) bpBinArrayDump(bp->bp_rootNode, 4);
bpIndent(2);
fprintf(stderr,"}\n");
/*** enums ***/
bpIndent(2);
fprintf(stderr,"{enums\n");
bpDumpEnums(bp->bp_enums,4);
bpIndent(2);
fprintf(stderr,"}\n");
/* close bplane */
fprintf(stderr,"}\n");
}

166
bplane/bpEnum.c Normal file
View File

@ -0,0 +1,166 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
/* bpEnum.c -
*
* Search routines for bplanes
*
*/
#include <stdio.h>
#include "utils/utils.h"
#include "database/database.h"
#include "utils/geometry.h"
#include "bplane/bplaneInt.h"
/*
* ----------------------------------------------------------------------------
* BPEnumInit --
*
* set up search.
*
* ----------------------------------------------------------------------------
*/
void BPEnumInit(BPEnum *bpe, /* enum to initialize */
BPlane *bp,
Rect *area, /* search area */
int match,
char *id) /* for debugging */
{
bool inside = FALSE;
bpe->bpe_plane = bp;
bpe->bpe_id = id;
bpe->bpe_match = match;
bpe->bpe_top = bpe->bpe_stack;
/*
fprintf(stderr,"DEBUG bpEnumInit, match=%d id=%s\n",
match, id);
*/
/* link enum to bplane */
bpe->bpe_next = bp->bp_enums;
bp->bp_enums = bpe;
switch (match)
{
case BPE_EQUAL:
GeoCanonicalRect(area, &bpe->bpe_srchArea);
bpe->bpe_nextElement = IHashLookUp(bp->bp_hashTable, &bpe->bpe_srchArea);
bpe->bpe_top->bps_state = BPS_HASH;
/* don't need to setup stack, just return */
return;
case BPE_ALL:
/* If we start 'INSIDE', no match checks will be done */
bpe->bpe_top->bps_state = BPS_BINS_INSIDE;
inside = TRUE;
break;
case BPE_TOUCH:
GeoCanonicalRect(area, &bpe->bpe_srchArea);
inside = GEO_SURROUND(&bpe->bpe_srchArea, &bp->bp_bbox);
if(inside)
{
bpe->bpe_top->bps_state = BPS_BINS_INSIDE;
}
else
{
bpe->bpe_top->bps_state = BPS_BINS;
bpe->bpe_subBinMinX = GEO_WIDTH(&bpe->bpe_srchArea)/2;
bpe->bpe_subBinMinY = GEO_HEIGHT(&bpe->bpe_srchArea)/2;
bpBinsUpdate(bp);
}
break;
case BPE_OVERLAP:
GeoCanonicalRect(area, &bpe->bpe_srchArea);
GEO_EXPAND(&bpe->bpe_srchArea, -1, &bpe->bpe_srchArea);
inside = GEO_SURROUND(&bpe->bpe_srchArea, &bp->bp_bbox);
if(inside)
{
bpe->bpe_top->bps_state = BPS_BINS_INSIDE;
}
else
{
bpe->bpe_top->bps_state = BPS_BINS;
bpe->bpe_subBinMinX = GEO_WIDTH(&bpe->bpe_srchArea)/2;
bpe->bpe_subBinMinY = GEO_HEIGHT(&bpe->bpe_srchArea)/2;
bpBinsUpdate(bp);
}
break;
default:
ASSERT(FALSE,"BPEnumInit, bad match value");
}
/* push rootnode */
if(bp->bp_rootNode)
{
bpEnumPush(bpe, bp->bp_rootNode, inside);
bpe->bpe_nextElement = NULL;
}
else
{
/* no bins, go straight to inbox */
bpe->bpe_top->bps_state = BPS_INBOX | inside;
bpe->bpe_nextElement = bp->bp_inBox;
}
}
/*
* ----------------------------------------------------------------------------
* BPEnumTerm --
*
* terminate enumeration
*
* ----------------------------------------------------------------------------
*/
void BPEnumTerm(BPEnum *bpe)
{
BPEnum **linkp;
/*
fprintf(stderr,"DEBUG bpEnumTerm, id=%s\n",
bpe->bpe_id);
*/
/* unlink */
linkp = &bpe->bpe_plane->bp_enums;
while(*linkp && *linkp != bpe) linkp = &(*linkp)->bpe_next;
ASSERT(*linkp==bpe,"BPEnumTerm");
*linkp = bpe->bpe_next;
}

537
bplane/bpEnum.h Normal file
View File

@ -0,0 +1,537 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
#ifndef _BPENUM_H
#define _BPENUM_H
/* bpEnum.h --
*
* inlined Search routines for bplanes (see also bpEnum.c)
*
*/
#include <stdio.h>
#include "utils/utils.h"
#include "utils/geometry.h"
#include "utils/geofast.h"
#include "bplane/bplane.h"
#include "bplane/bplaneInt.h"
extern void DumpRect(char *msg, Rect *r);
/* state machine states */
#define BPS_BINS 0
#define BPS_BINS_INSIDE 1
#define BPS_INBOX 2
#define BPS_INBOX_INSIDE 3
#define BPS_HASH 4
#define BPS_DONE 5
/* range code */
#define R_LEFT 1
#define R_RIGHT 2
#define R_BOT 4
#define R_TOP 8
/*
* ----------------------------------------------------------------------------
*
* bpBinArea -- compute area covered by given bin.
*
* Returns: bin area.
*
* ----------------------------------------------------------------------------
*/
static __inline__ Rect bpBinArea(BinArray *ba, int i)
{
int dimX = ba->ba_dimX;
int dx = ba->ba_dx;
int dy = ba->ba_dy;
int xi = i % dimX;
int yi = i / dimX;
Rect area;
area.r_xbot = ba->ba_bbox.r_xbot + dx*xi;
area.r_ybot = ba->ba_bbox.r_ybot + dy*yi;
area.r_xtop = area.r_xbot + dx;
area.r_ytop = area.r_ybot + dy;
return area;
}
/*
* ----------------------------------------------------------------------------
* bpEnumRange --
*
* Determine which edges of search area bin overlaps.
*
* (Used to make match checks as efficient as possible, for example if bin
* does not extend past srch area in any direction, no match checking is
* required)
*
* Returns: int encoding 'range'.
*
* ----------------------------------------------------------------------------
*/
static __inline__ int
bpEnumRange(Rect *bin, Rect *srch)
{
int range = 0;
if (bin->r_xbot < srch->r_xbot) range |= R_LEFT;
if (bin->r_xtop > srch->r_xtop) range |= R_RIGHT;
if (bin->r_ybot < srch->r_ybot) range |= R_BOT;
if (bin->r_ytop > srch->r_ytop) range |= R_TOP;
return range;
}
/*
* ----------------------------------------------------------------------------
* bpEnumMatchQ -
*
* Check if element intersects search area
*
* range specifies which search area boundaries the element
* can potentially extend beyond.
*
* We rely on the optimizing compiler to remove unnecessary checks
* based on compile time knowledge of range value.
*
* Returns: TRUE on match, FALSE otherwise.
*
* ----------------------------------------------------------------------------
*/
static __inline__ bool
bpEnumMatchQ(BPEnum *bpe, Element *e)
{
Rect *area = &bpe->bpe_srchArea;
Rect *r = &e->e_rect;
if(r->r_xtop < area->r_xbot) return FALSE;
if(r->r_xbot > area->r_xtop) return FALSE;
if(r->r_ytop < area->r_ybot) return FALSE;
if(r->r_ybot > area->r_ytop) return FALSE;
return TRUE;
}
/*
* ----------------------------------------------------------------------------
* bpEnumPushInside --
*
* called by bpEnumPush when the binarray is entirely inside the search area
*
* push a bin array onto an enum stack.
*
* ----------------------------------------------------------------------------
*/
static __inline__ bool bpEnumPushInside(BPEnum *bpe,
BinArray *ba)
{
BPStack *bps;
/* push stack */
++bpe->bpe_top;
bps = bpe->bpe_top;
bps->bps_node = ba;
bps->bps_state = BPS_BINS_INSIDE;
/* set up indices to scan entire bin array */
bps->bps_i = -1;
bps->bps_max = ba->ba_numBins;
return TRUE;
}
/*
* ----------------------------------------------------------------------------
* bpEnumPush --
*
* push a bin array onto an enum stack.
*
* normally returns TRUE, returns FALSE on (possible) state change.
*
* ----------------------------------------------------------------------------
*/
static __inline__ bool bpEnumPush(BPEnum *bpe,
BinArray *ba,
bool inside)
{
Rect area;
Rect *bbox;
int dx;
int dy;
BPStack *bps;
/*
fprintf(stderr,"DEBUG bpEnumPush, inside=%d\n", inside);
*/
/* special case inside */
if(inside) return bpEnumPushInside(bpe,ba);
bbox = &ba->ba_bbox;
if(GEO_SURROUND(&bpe->bpe_srchArea,bbox))
{
bpEnumPushInside(bpe,ba);
return FALSE; /* state change */
}
/* push stack */
++bpe->bpe_top;
bps = bpe->bpe_top;
bps->bps_node = ba;
bps->bps_state = BPS_BINS;
bps->bps_subbin = FALSE;
bps->bps_rejects = 0;
/* compute search area for this bin array */
dx = ba->ba_dx;
dy = ba->ba_dy;
area.r_xbot = bpe->bpe_srchArea.r_xbot - dx;
area.r_xtop = bpe->bpe_srchArea.r_xtop + 1;
area.r_ybot = bpe->bpe_srchArea.r_ybot - dy;
area.r_ytop = bpe->bpe_srchArea.r_ytop + 1;
GEOCLIP(&area,bbox);
if(GEO_RECTNULL(&area))
{
/* only need to check oversized */
bps->bps_i = 0;
bps->bps_rowMax = 0;
bps->bps_max = 0;
}
else
{
/* setup indices for this array and search area */
int dimX = ba->ba_dimX;
int i;
/* make area relative to bin bbox */
area.r_xbot -= bbox->r_xbot;
area.r_xtop -= bbox->r_xbot;
area.r_ybot -= bbox->r_ybot;
area.r_ytop -= bbox->r_ybot;
/* DumpRect("area relative to bin bbox = ",&area); */
area.r_xbot /= ba->ba_dx;
area.r_xtop /= ba->ba_dx;
area.r_ybot /= ba->ba_dy;
area.r_ytop /= ba->ba_dy;
i = area.r_ybot*dimX + area.r_xbot; /* next index */
bps->bps_i = i-1;
bps->bps_rowMax = i + area.r_xtop - area.r_xbot;
bps->bps_max = area.r_ytop*dimX + area.r_xtop;
bps->bps_rowDelta = dimX + area.r_xbot - area.r_xtop;
bps->bps_dimX = dimX;
/* consider subbinning? */
if(dx >= bpe->bpe_subBinMinX || dy >= bpe->bpe_subBinMinY)
{
bps->bps_subbin = TRUE;
}
}
return TRUE;
}
/*
* ----------------------------------------------------------------------------
* bpEnumNextBin1 --
*
* called by bpEnumNextBin() after indexes for new bin are setup
*
* returns: normally returns TRUE, returns FALSE on state change.
*
* ----------------------------------------------------------------------------
*/
static __inline__ bool
bpEnumNextBin1(BPEnum *bpe, BPStack *bps, bool inside)
{
if(bpBinType(bps->bps_node,bps->bps_i) != BT_ARRAY)
{
bpe->bpe_nextElement = bpBinList(bps->bps_node,bps->bps_i);
return TRUE;
}
/* array, push into it */
return bpEnumPush(bpe, bpSubArray(bps->bps_node,bps->bps_i), inside);
}
/*
* ----------------------------------------------------------------------------
* bpEnumNextBin --
*
* called by bpEnumNextBINS to advance to next bin (bucket).
*
* cycles through normal bins first, then oversized,
* finally, for toplevel, sets INBOX state.
*
* sets bpe->bpe_nextElement to first element in next bin.
*
* returns: normally returns TRUE, returns FALSE on state change.
*
* ----------------------------------------------------------------------------
*/
static __inline__ bool
bpEnumNextBin(BPEnum *bpe, bool inside)
{
BPStack *bps = bpe->bpe_top;
#ifdef PARANOID
ASSERT(bps,"bpEnumNextBin");
ASSERT(!bpe->bpe_nextElement,"bpEnumNextBin");
#endif
/*
fprintf(stderr,"DEBUG bpEnumNextBin TOP inside=%d nextElement=%x\n",
inside, bpe->bpe_nextElement);
*/
/* consider subbining this bin before advancing to next */
if(!inside)
{
if(bps->bps_rejects >= bpMinBAPop
&& (bps->bps_subbin || bps->bps_i == bps->bps_node->ba_numBins))
{
int i = bps->bps_i;
BinArray *ba = bps->bps_node;
BinArray *sub;
/* fprintf(stderr,"DEBUG, subbining!\n"); */
sub = bpBinArrayBuild(bpBinArea(ba,i),
bpBinList(ba,i),
FALSE); /* don't recursively subbin! */
if(sub)
{
ba->ba_bins[i] =
(void *) ((pointertype) sub | BT_ARRAY);
}
}
bps->bps_rejects = 0;
}
/* handle inside case first */
if(inside)
{
/* Inside case, cycle through all bins */
/* next bin */
if(bps->bps_i<bps->bps_max)
{
bps->bps_i += 1;
return bpEnumNextBin1(bpe,bps,inside);
}
}
else
{
/* cycle only through relevant bins */
/* next in row */
if(bps->bps_i<bps->bps_rowMax)
{
bps->bps_i += 1;
goto bin;
}
/* next row */
if(bps->bps_i<bps->bps_max)
{
bps->bps_i += bps->bps_rowDelta;
bps->bps_rowMax += bps->bps_dimX;
goto bin;
}
/* oversized */
if(bps->bps_i == bps->bps_max)
{
bps->bps_i = bps->bps_node->ba_numBins;
goto bin;
}
}
/* pop stack */
/* fprintf(stderr,"DEBUG BPEnumNextBin Pop.\n"); */
bpe->bpe_top--;
if(bpe->bpe_top>bpe->bpe_stack) return FALSE; /* state may have changed */
/* inbox */
/* fprintf(stderr,"DEBUG BPEnumNextBin INBOX.\n"); */
bpe->bpe_nextElement = bpe->bpe_plane->bp_inBox;
bpe->bpe_top->bps_state = BPS_INBOX | inside;
return FALSE; /* state change */
/* dive into indexed bin */
bin:
return bpEnumNextBin1(bpe,bps,inside);
}
/*
* ----------------------------------------------------------------------------
* bpEnumNextBINS --
*
* Handle BINS state for BPEnumNext()
*
* (bin enumeration.)
*
* ----------------------------------------------------------------------------
*/
static __inline__ Element* bpEnumNextBINS(BPEnum *bpe, bool inside)
{
/* bin by bin */
do
{
/* search this bin */
Element *e = bpe->bpe_nextElement;
while(e && !inside && !bpEnumMatchQ(bpe,e))
{
bpe->bpe_top->bps_rejects++;
e = e->e_link;
}
if(e)
{
bpe->bpe_nextElement = e->e_link;
/* DumpRect("DEBUG e_rect= ",&e->e_rect); */
return e;
}
bpe->bpe_nextElement = NULL;
}
while(bpEnumNextBin(bpe,inside));
/* next state */
return NULL;
}
/*
* ----------------------------------------------------------------------------
* bpEnumNextINBOX --
*
* Handle INBOX states for BPEnumNext()
*
* unbinned enumeration.
*
* ----------------------------------------------------------------------------
*/
static __inline__ Element *bpEnumNextINBOX(BPEnum *bpe,
bool inside)
{
Element *e = bpe->bpe_nextElement;
while(e && !inside && !bpEnumMatchQ(bpe,e)) e = e->e_link;
if(e)
{
bpe->bpe_nextElement = e->e_link;
return e;
}
/* done */
bpe->bpe_top->bps_state = BPS_DONE;
return NULL;
}
/*
* ----------------------------------------------------------------------------
* bpEnumNextHASH --
*
* Handle HASH state for BPEnumNext()
*
* (hash based (EQUALS) enumerations.)
*
* ----------------------------------------------------------------------------
*/
static __inline__ Element *bpEnumNextHASH(BPEnum *bpe)
{
Element *e = bpe->bpe_nextElement;
if(e)
{
bpe->bpe_nextElement =
IHashLookUpNext(bpe->bpe_plane->bp_hashTable, e);
}
else
{
bpe->bpe_top->bps_state = BPS_DONE;
}
return e;
}
/*
* ----------------------------------------------------------------------------
* BPEnumNext --
*
* get next element in enumeration.
*
* ----------------------------------------------------------------------------
*/
static __inline__ void *BPEnumNext(BPEnum *bpe)
{
Element *e;
while(TRUE)
{
/*
fprintf(stderr,"DEBUG state=%d\n",bpe->bpe_top->bps_state);
*/
switch (bpe->bpe_top->bps_state)
{
case BPS_BINS:
if(e=bpEnumNextBINS(bpe, 0)) return e;
break;
case BPS_BINS_INSIDE:
if(e=bpEnumNextBINS(bpe, 1)) return e;
break;
case BPS_INBOX:
if(e=bpEnumNextINBOX(bpe, 0)) return e;
break;
case BPS_INBOX_INSIDE:
if(e=bpEnumNextINBOX(bpe, 1)) return e;
break;
case BPS_HASH:
if(e=bpEnumNextHASH(bpe)) return e;
break;
case BPS_DONE:
return NULL;
default:
ASSERT(FALSE,"BPEnumNext, bad state");
}
}
}
#endif /* _BPENUM_H */

273
bplane/bpMain.c Normal file
View File

@ -0,0 +1,273 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
/* bpMain.c
*
* Top-level routines for BPlanes
* (interface to other modules)
*
* See bpEnum.c for enum routines.
* See bpTcl.c for tcl-level interface.
*/
#include <stdio.h>
#include "utils/utils.h"
#include "utils/malloc.h"
#include "database/database.h"
#include "utils/geometry.h"
#include "bplane/bplaneInt.h"
/*
* ----------------------------------------------------------------------------
* BPNew --
*
* Return newly created BPlane.
*
* ----------------------------------------------------------------------------
*/
BPlane *BPNew(void)
{
BPlane *new;
new = (BPlane *)mallocMagic(sizeof(BPlane));
new->bp_bbox = GeoNullRect;
new->bp_bbox_exact = TRUE;
new->bp_count = 0;
/* ENUMS */
new->bp_enums = NULL;
/* HASH TABLE */
new->bp_hashTable = IHashInit(4, /* initial buckets */
OFFSET(Element, e_rect), /* key */
OFFSET(Element, e_hashLink),
IHash4WordKeyHash,
IHash4WordKeyEq);
/* IN BOX */
new->bp_inBox = NULL;
/* BINS */
new->bp_binLife = 0;
new->bp_inAdds = 0;
new->bp_binArea = GeoNullRect;
new->bp_rootNode = NULL;
return new;
}
/*
* ----------------------------------------------------------------------------
* BPFree --
*
* free (empty) BPlane
*
* ----------------------------------------------------------------------------
*/
void BPFree(BPlane *bp)
{
ASSERT(bp->bp_count == 0,"BPFree");
IHashFree(bp->bp_hashTable);
freeMagic((char *)bp);
}
/*
* ----------------------------------------------------------------------------
* BPAdd --
*
* Add element to the given bplane
*
* NOTE: e_rect better be canonical!
*
* ----------------------------------------------------------------------------
*/
void BPAdd(BPlane *bp, void *element)
{
int size;
int binDim;
Element * e = element;
Rect *r = &e->e_rect;
/* Don't allow adds during active enumerations.
* This is confusing, since newly added elements may or may not
* be enumerated in on going enumerations, is not particularly
* useful, since elements to add can just be stored up on a local
* list and added after the enumeration completes.
*/
ASSERT(!bp->bp_enums,
"BPAdd, attempted during active enumerations");
/* element rect must be canonical! */
#ifdef PARANOID
ASSERT(GeoIsCanonicalRect(r),"BPAdd, rect must be canonical.");
#endif
bp->bp_count++;
/* update hash table */
IHashAdd(bp->bp_hashTable, element);
/* update bbox */
if(bp->bp_count == 1)
{
bp->bp_bbox = *r;
}
else
{
GeoIncludeRectInBBox(r,&bp->bp_bbox);
}
/* no bins? */
if(!bp->bp_rootNode) goto inBox;
/* doesn't fit inside bins ? */
if(!GEO_SURROUND(&bp->bp_binArea,r)) goto inBox;
/* bin element */
bpBinAdd(bp->bp_rootNode, e);
return;
/* add to in box */
inBox:
bp->bp_inAdds++;
e->e_link = bp->bp_inBox;
bp->bp_inBox = e;
/* maintain back pointers */
e->e_linkp = &bp->bp_inBox;
if(e->e_link) e->e_link->e_linkp = &e->e_link;
}
/*
* ----------------------------------------------------------------------------
* BPDelete --
*
* remove element from bplane
*
* ----------------------------------------------------------------------------
*/
void BPDelete(BPlane *bp, void *element)
{
Element *e = element;
ASSERT(e,"BPDelete");
bp->bp_count--;
/* if element was on edge of bbox, bbox may no longer
* be exact.
*/
if(bp->bp_bbox_exact &&
(bp->bp_bbox.r_xbot == e->e_rect.r_xbot ||
bp->bp_bbox.r_xtop == e->e_rect.r_xtop ||
bp->bp_bbox.r_ybot == e->e_rect.r_ybot ||
bp->bp_bbox.r_ytop == e->e_rect.r_ytop))
{
bp->bp_bbox_exact = FALSE;
}
/* advance any nextElement pointers at e */
{
BPEnum *bpe;
for(bpe=bp->bp_enums; bpe; bpe=bpe->bpe_next)
{
if(bpe->bpe_nextElement != e) continue;
if(bpe->bpe_match == BPE_EQUAL)
{
bpe->bpe_nextElement = IHashLookUpNext(bp->bp_hashTable, e);
}
else
{
bpe->bpe_nextElement = e->e_link;
}
}
}
IHashDelete(bp->bp_hashTable, e);
/* next pointer of prev element */
*e->e_linkp = e->e_link;
/* back pointer of next element */
if(e->e_link) e->e_link->e_linkp = e->e_linkp;
}
/*
* ----------------------------------------------------------------------------
* BPBBox --
*
* Get current bplane bbox.
*
* returns: current bplane bbox
* (returns an inverted rect, if bplane is empty)
*
* ----------------------------------------------------------------------------
*/
Rect BPBBox(BPlane *bp)
{
if(bp->bp_count == 0) return GeoInvertedRect;
/* if bbox is not up-to-date, recompute */
if(!bp->bp_bbox_exact)
{
BPEnum bpe;
Element *e;
bp->bp_bbox_exact = TRUE;
BPEnumInit(&bpe,
bp,
NULL,
BPE_ALL,
"BPBBox");
e = BPEnumNext(&bpe);
bp->bp_bbox = e->e_rect;
while(e = BPEnumNext(&bpe))
{
GeoIncludeRectInBBox(&e->e_rect, &bp->bp_bbox);
}
}
return bp->bp_bbox;
}

195
bplane/bpOpaque.h Normal file
View File

@ -0,0 +1,195 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
#ifndef _BPOPAQUE_H
#define _BPOPAQUE_H
#ifndef _IHASH_H
#include "utils/ihash.h"
#endif /* _IHASH_H */
/*
* bpOpaque.h --
*
* This file contains strucs directly or indirectly referenced by
* clients of bplane module, whose internals should be treated
* as opaque by clients.
*
* It is included by bplane.h
*
*/
/* data element, stored in BPlane
*
* Storage managed by caller.
* Inital part must correspond to below.
*/
typedef struct element
{
struct element *e_hashLink;
struct element *e_link;
struct element **e_linkp; /* back pointer for quick deletes */
Rect e_rect;
/* client data goes here */
} Element;
/* number of link fields in element
*
* user code should not depend on more than 1 link.
* (and should only use/ref that link when element is not in a bplane)
*/
#define BP_NUM_LINKS 3
/* bin array */
typedef struct binarray
{
Rect ba_bbox; /* area covered by array */
int ba_dx; /* dimensions of a single bin */
int ba_dy;
int ba_dimX; /* number of bins in a row */
int ba_numBins; /* number of regular bins (size of array - 1) */
void *ba_bins[1]; /* low order bit(s) used to encode type info.
* DON'T ACCESS DIRECTLY, USE MACROS BELOW
*
* (last bin is for oversized)
*/
} BinArray;
/* bin types
*
* NOTE: its important that simple lists have type 0, i.e. are
* just standard pointers. This is so that the list head
* 'link' can be treated just as any other link, during
* deletion etc.
*/
#define BT_TYPE_MASK 1
#define BT_LIST 0
#define BT_ARRAY 1
static __inline__ bool bpBinEmpty(BinArray *ba, int i)
{
return ba->ba_bins[i] == NULL;
}
static __inline__ bool bpBinType(BinArray *ba, int i)
{
return (bool) (((pointertype) ba->ba_bins[i]) & BT_TYPE_MASK);
}
static __inline__ Element *bpBinList(BinArray *ba, int i)
{
#ifdef PARANOID
ASSERT(bpBinType(ba,i)==BT_LIST,"bpBinList");
#endif
return (Element *) ba->ba_bins[i];
}
static __inline__ Element **bpBinListHead(BinArray *ba, int i)
{
#ifdef PARANOID
ASSERT(bpBinType(ba,i)==BT_LIST,"bpBinList");
#endif
return (Element **) &ba->ba_bins[i];
}
static __inline__ BinArray *bpSubArray(BinArray *ba, int i)
{
#ifdef PARANOID
ASSERT(bpBinType(ba,i)==BT_ARRAY,"bpSubArray");
#endif
return (BinArray *) ((pointertype) ba->ba_bins[i] & ~BT_TYPE_MASK);
}
/* BPlane - toplevel struc */
typedef struct bplane
{
Rect bp_bbox; /* bbox (bin + in) */
bool bp_bbox_exact; /* if set bp_bbox, is exact,
* if reset bp_bbox may be over-sized.
*/
int bp_count; /* total number of elements in bplane */
struct bpenum *bp_enums; /* list of active enums */
/* HASH TABLE */
IHashTable *bp_hashTable; /* hash table
* (for expediting BP_EQUAL searches) */
/* IN BOX */
Element *bp_inBox; /* elements not yet added to bin system */
/* BINS */
int bp_binLife; /* set to binCount when bin system
* built, decremented on add/delete ops.
* bin system rebuilt when zero reached.
*/
int bp_inAdds; /* additions to inBox since last rebuild */
Rect bp_binArea; /* area covered by bin arrays */
BinArray *bp_rootNode; /* top bin node */
} BPlane;
/* context for BPlane enumeration */
typedef struct bpStack
{
int bps_state; /* where we are at rolled in one convenient
* number (see BPS_* defs in bpEnum.h)
*/
BinArray *bps_node; /* current bin array */
int bps_i; /* current index */
int bps_rowMax; /* max index for this row */
int bps_rowDelta; /* increment from end of one row to beginning
* of next.
*/
int bps_max; /* max index */
int bps_dimX; /* row length */
bool bps_subbin; /* if set consider subbinning */
int bps_rejects; /* number of unmatching elements in current
* bin, used to decide when to subbin.
*/
} BPStack;
/* enumeration 'handle' */
typedef struct bpenum
{
struct bpenum *bpe_next; /* all enums for bplane linked together */
BPlane *bpe_plane; /* plane being searched */
Rect bpe_srchArea; /* area being searched */
int bpe_match; /* match criteria */
char *bpe_id; /* for debug */
int bpe_subBinMinX;
int bpe_subBinMinY; /* consider subbinning
* for bins bigger than this.
*/
Element *bpe_nextElement; /* next element in current list */
BPStack *bpe_top; /* top of stack */
BPStack bpe_stack[10000]; /* stack for tree traversal during enum */
} BPEnum;
#endif /* _BPOPAQUE_H */

304
bplane/bpStat.c Normal file
View File

@ -0,0 +1,304 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
/* bpStat.c
*
* routines to get bplane statistics.
*
*/
#include <stdio.h>
#include <limits.h>
#include "utils/utils.h"
#include "database/database.h"
#include "utils/geometry.h"
#include "bplane/bplaneInt.h"
/*
* ----------------------------------------------------------------------------
* bpCount --
*
* count list of elements.
*
* Returns size of list.
*
* ----------------------------------------------------------------------------
*/
int bpCount(Element *e)
{
int i = 0;
while(e)
{
i++;
e = e->e_link;
}
return i;
}
/*
* ----------------------------------------------------------------------------
* bpStatBA --
*
* compute bin array statistics.
* (includes sub-arrays)
*
*
* Returns memory used by bplane (excluding elements)
*
* ----------------------------------------------------------------------------
*/
unsigned int bpStatBA(BinArray *ba,
int *totCount, /* total number of elements */
int *totBins, /* ret tot num of bins */
int *emptyBins, /* ret num of empty bins */
int *binArraysp, /* ret num of bin arrays */
int *maxEffp, /* ret max effective list length */
int *maxBinCount, /* ret max count for regular bin */
int *totUnbinned, /* ret tot num of e's not binned */
int *maxDepth) /* ret max bin array depth */
{
Rect *bbox = &ba->ba_bbox;
int dx = ba->ba_dx;
int dy = ba->ba_dy;
int numBins = ba->ba_numBins;
int dimX = ba->ba_dimX;
int dimY = numBins/dimX;
int w = GEO_WIDTH(bbox);
int h = GEO_HEIGHT(bbox);
/* initial statistics */
unsigned int mem = 0;
int tot = 0;
int bins = 0;
int emptys = 0;
int binArrays = 1;
int maxCount = 0;
int maxEff = 0;
int maxEffSub = 0;
int maxSubCount = 0;
int unbinned = 0;
int depth = 1;
int maxDepthSub = 0;
int i;
/* add bins in this array */
bins += numBins;
/* add memory usage for this array (sub arrays already tabulated) */
if(ba) mem += sizeof(BinArray) + numBins*sizeof(void*);
/* gather stats bin by bin */
for(i=0;i<numBins;i++)
{
if(bpBinType(ba,i) != BT_ARRAY)
{
/* simple bin */
int count = bpCount(bpBinList(ba,i));
tot += count;
if(count>maxCount) maxCount = count;
if(count==0) emptys++;
}
else
{
/* arrayed, recurse */
int sMem, sTot, sBins, sEmptys, sBinArrays;
int sMaxEff, sMaxCount, sUnbinned, sDepth;
sMem = bpStatBA(bpSubArray(ba,i),
&sTot, /* total number of elements */
&sBins, /* ret tot num of bins */
&sEmptys, /* ret num of empty bins */
&sBinArrays, /* ret num bin arrays */
&sMaxEff, /* ret max effective list length */
&sMaxCount, /* ret max count for regular bin */
&sUnbinned, /* ret tot num of e's not binned */
&sDepth); /* ret max bin array depth */
mem += sMem;
tot += sTot;
bins += sBins;
emptys += sEmptys;
binArrays += sBinArrays;
if(sMaxEff > maxEffSub) maxEffSub = sMaxEff;
if(sMaxCount > maxCount) maxCount = sMaxCount;
if(sUnbinned > maxCount) maxCount = sUnbinned;
if(sDepth > maxDepthSub) maxDepthSub = sDepth;
}
}
maxEff += MAX(maxCount,maxEffSub);
depth += maxDepthSub;
/* oversized */
if(bpBinType(ba,numBins) != BT_ARRAY)
{
/* oversized unbinned */
int over = bpCount(bpBinList(ba,numBins));
tot += over;
unbinned += over;
maxEff += over;
}
else
{
/* oversized is arrayed, recurse */
int sMem, sTot, sBins, sEmptys, sBinArrays;
int sMaxEff, sMaxCount, sUnbinned, sDepth;
sMem = bpStatBA(bpSubArray(ba,numBins),
&sTot, /* total number of elements */
&sBins, /* ret tot num of bins */
&sEmptys, /* ret num of empty bins */
&sBinArrays, /* ret num bin arrays */
&sMaxEff, /* ret max effective list length */
&sMaxCount, /* ret max count for regular bin */
&sUnbinned, /* ret tot num of e's not binned */
&sDepth); /* ret max bin array depth */
mem += sMem;
tot += sTot;
bins += sBins;
emptys += sEmptys;
binArrays += sBinArrays;
maxEff += sMaxEff;
if(sMaxCount > maxCount) maxCount = sMaxCount;
unbinned += sUnbinned;
depth += sDepth;
}
/* set results */
if(totCount) *totCount = tot;
if(totBins) *totBins = bins;
if(emptyBins) *emptyBins = emptys;
if(binArraysp) *binArraysp = binArrays;
if(maxEffp) *maxEffp = maxEff;
if(maxBinCount) *maxBinCount = maxCount;
if(totUnbinned) *totUnbinned = unbinned;
if(maxDepth) *maxDepth = depth;
return mem;
}
/*
* ----------------------------------------------------------------------------
* BPStat --
*
* compute bplane statistics.
*
* Returns memory used by bplane (excluding elements)
*
* ----------------------------------------------------------------------------
*/
unsigned int BPStat(BPlane *bp,
int *totCount, /* total number of elements */
int *inBox, /* ret num of elements in inBox */
int *totBins, /* ret tot num of bins */
int *emptyBins, /* ret num of empty bins */
int *binArraysp, /* ret tot num of bin arrays */
int *maxEffp, /* ret max effective list length */
int *maxBinCount, /* ret max count for regular bin */
int *totUnbinned, /* ret tot num of e's not binned */
int *maxDepth) /* ret max bin array depth */
{
BinArray *ba = bp->bp_rootNode;
int numBins;
unsigned int mem = 0;
int tot = 0;
int bins = 0;
int emptys = 0;
int binArrays = 0;
int maxEff = 0;
int maxCount = 0;
int unbinned = 0;
int depth = 0;
int in;
/* bin arrays */
if(ba)
{
mem += bpStatBA(bp->bp_rootNode,
&tot, /* total number of elements */
&bins, /* ret tot num of bins */
&emptys, /* ret tot num of empty bins */
&binArrays, /* ret tot num of bin arrays */
&maxEff, /* ret max effective list length */
&maxCount, /* ret max count for regular bin */
&unbinned, /* ret tot num of e's not binned */
&depth); /* ret max bin array depth */
}
/* inbox */
in = bpCount(bp->bp_inBox);
tot += in;
maxEff += in;
unbinned += in;
/* add in memory usage for bplane */
mem += sizeof(BPlane);
mem += IHashStats2(bp->bp_hashTable,NULL,NULL);
/* set results */
if(totCount) *totCount = tot;
if(inBox) *inBox = in;
if(totBins) *totBins = bins;
if(emptyBins) *emptyBins = emptys;
if(binArraysp) *binArraysp = binArrays;
if(maxEffp) *maxEffp = maxEff;
if(maxBinCount) *maxBinCount = maxCount;
if(totUnbinned) *totUnbinned = unbinned;
if(maxDepth) *maxDepth = depth;
return mem;
}
/*
* ----------------------------------------------------------------------------
* BPStatMemory --
*
* returns memory usage of BPlane in bytes
* (exclusive of elements contained by the BPlane)
*
* ----------------------------------------------------------------------------
*/
unsigned int BPStatMemory(BPlane *bp)
{
return BPStat(bp,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
}

361
bplane/bpTest.c Normal file
View File

@ -0,0 +1,361 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
/* bpTest.c
*
* (regression) tests of bplane code
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "utils.h"
#include "message.h"
#include "database.h"
#include "geometry.h"
#include "bplane.h"
#include "bplaneInt.h"
#include "debug.h"
#include "cifInt.h"
/*
* elements used by test code.
*/
typedef struct rectc
{
struct rectc *rc_links[BP_NUM_LINKS];
Rect rc_rect;
} RectC;
/*
* ----------------------------------------------------------------------------
* bpRand --
* generate a random int in given range.
*
* side effects: sets coords of input rect.
* ----------------------------------------------------------------------------
*/
int bpRand(int min, int max)
{
double f = rand()/ (double) RAND_MAX; /* random number in unit interval */
return min + (int) ((max-min+1)*f);
}
/*
* ----------------------------------------------------------------------------
* bpTestRandRect --
* generate a random unit rectangle inside bbox
*
* side effects: sets coords of input rect.
* ----------------------------------------------------------------------------
*/
static void bpTestRandRect(Rect *r, Rect *bbox)
{
r->r_xbot = bpRand(bbox->r_xbot,bbox->r_xtop-1);
r->r_ybot = bpRand(bbox->r_ybot,bbox->r_ytop-1);
r->r_xtop = r->r_xbot+1;
r->r_ytop = r->r_ybot+1;
}
/* ====== GOLD snow test.
* ====== linked list implementation (to determine 'right' answer)
*/
/*
* ----------------------------------------------------------------------------
* bpTestIntersectGold --
*
* check whether rc intersects list
* ----------------------------------------------------------------------------
*/
static bool bpTestIntersectGold(RectC *rc, RectC *list)
{
while(list)
{
if(GEO_TOUCH(&rc->rc_rect,&list->rc_rect)) return TRUE;
list=list->rc_links[0];
}
return FALSE;
}
/*
* ----------------------------------------------------------------------------
* bpTestSnowGold --
* populate square of dimension 'size' with non-overlapping random unit
* rectangles. Keep adding rectangles until failures exceed successes.
* (stop when maxFailures reached.)
*
* coded with simple linked list.
*
* ---------------------------------------------------------------------------- */
void bpTestSnowGold(int size, bool trace)
{
int failures = 0;
int successes = 0;
int i = 0;
int crc = 0;
RectC *result = NULL;
RectC *rc = NULL;
Rect area;
fprintf(stderr,"BEGIN Snow GOLD, size=%d\n", size);
/* set up area */
area.r_xbot = 0;
area.r_ybot = 0;
area.r_xtop = size;
area.r_ytop = size;
while(failures<=successes)
{
i++;
if(!rc) rc = MALLOC_TAG(RectC *,rc, sizeof(RectC), "RectC");
bpTestRandRect(&rc->rc_rect, &area);
if(!bpTestIntersectGold(rc,result))
{
if(trace) DumpRect("success ",&rc->rc_rect);
crc ^= i+ 3*rc->rc_rect.r_xbot+ 5*rc->rc_rect.r_ybot;
rc->rc_links[0] = result;
result = rc;
rc = NULL;
successes++;
}
else
{
if(trace) DumpRect("failure ",&rc->rc_rect);
failures++;
}
}
/* clean up */
while(result)
{
/* pop */
rc=result;
result=rc->rc_links[0];
/* free */
FREE(rc);
}
fprintf(stderr,"END Snow GOLD, size=%d failures=%d successes=%d crc=%d\n",
size,
failures,
successes,
crc);
}
/* ====== bplane snow test.
*/
/*
* ----------------------------------------------------------------------------
* bpTestIntersect --
*
* check whether rc intersects list
* ----------------------------------------------------------------------------
*/
static bool bpTestIntersect(RectC *rc, BPlane *bp)
{
BPEnum bpe;
int result;
BPEnumInit(&bpe,bp, &rc->rc_rect, BPE_TOUCH,"bpTestIntersect");
result = (BPEnumNext(&bpe)!=NULL);
BPEnumTerm(&bpe);
return result;
}
/*
* ----------------------------------------------------------------------------
* bpTestSnow --
* populate area with non-overlapping random unit rectangles.
*
* using bplane.
*
* ----------------------------------------------------------------------------
*/
BPlane *bpTestSnow(int size, bool trace)
{
int failures = 0;
int successes = 0;
int i = 0;
int crc = 0;
RectC *result = NULL;
RectC *rc = NULL;
BPlane *bp = BPNew();
Rect area;
fprintf(stderr,"BEGIN Snow, size=%d\n", size);
/* set up area */
area.r_xbot = 0;
area.r_ybot = 0;
area.r_xtop = size;
area.r_ytop = size;
while(failures<=successes)
{
i++;
if(!rc) rc = MALLOC_TAG(RectC *,rc, sizeof(RectC), "RectC");
bpTestRandRect(&rc->rc_rect, &area);
if(!bpTestIntersect(rc,bp))
{
if(trace) DumpRect("success ",&rc->rc_rect);
crc ^= i+ 3*rc->rc_rect.r_xbot+ 5*rc->rc_rect.r_ybot;
BPAdd(bp,rc);
rc = NULL;
successes++;
}
else
{
if(trace) DumpRect("failure ",&rc->rc_rect);
failures++;
}
}
fprintf(stderr,"END Snow, size=%d failures=%d success=%d crc=%d\n",
size,
failures,
successes,
crc);
return bp;
}
/* ====== Tile Plane based snow test.
*/
/*
* ----------------------------------------------------------------------------
* bpTestIntersectTile --
*
* check whether r intersects existing tiles
*
* ----------------------------------------------------------------------------
*/
int bpTestIntersectTileFunc(Tile *tile, ClientData cd)
{
return 1;
}
static bool bpTestIntersectTile(Rect *r, Plane *plane)
{
Rect area;
/* catch touching tiles */
area = *r;
area.r_xbot -= 1;
area.r_ybot -= 1;
area.r_xtop += 1;
area.r_ytop += 1;
return DBPlaneEnumAreaPaint((Tile *) NULL,
plane,
&area,
&DBAllButSpaceBits,
bpTestIntersectTileFunc,
NULL);
}
/*
* ----------------------------------------------------------------------------
* bpTestSnowTile --
* populate area with non-overlapping random unit rectangles.
*
* using tile plane
*
* ----------------------------------------------------------------------------
*/
Plane *bpTestSnowTile(int size, bool trace)
{
int failures = 0;
int successes = 0;
int i = 0;
int crc = 0;
RectC *result = NULL;
RectC *rc = NULL;
Plane *plane = DBPlaneNew((ClientData) TT_SPACE);
Rect area;
fprintf(stderr,"BEGIN Snow Tile, size=%d\n", size);
/* set up area */
area.r_xbot = 0;
area.r_ybot = 0;
area.r_xtop = size;
area.r_ytop = size;
while(failures<=successes)
{
Rect r;
i++;
bpTestRandRect(&r, &area);
if(!bpTestIntersectTile(&r,plane))
{
if(trace) DumpRect("success ",&r);
crc ^= i+ 3*r.r_xbot + 5*r.r_ybot;
DBPaintPlane(plane, &r, CIFPaintTable, (PaintUndoInfo *) NULL);
rc = NULL;
successes++;
}
else
{
if(trace) DumpRect("failure ",&r);
failures++;
}
}
fprintf(stderr,"END Snow Tile, size=%d failures=%d success=%d crc=%d\n",
size,
failures,
successes,
crc);
return plane;
}

77
bplane/bpUtils.c Normal file
View File

@ -0,0 +1,77 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
/* bpUtils.c --
*
* shared low-level routines for this module.
*
*/
#include <stdio.h>
#include "utils/utils.h"
#include "database/database.h"
#include "utils/geometry.h"
#include "bplane/bplaneInt.h"
/*
* ----------------------------------------------------------------------------
* bpRectDim --
*
* return dimension of rectangle in xDir
*
* ----------------------------------------------------------------------------
*/
int bpRectDim(Rect *r, bool xDir)
{
return xDir ? r->r_xtop - r->r_xbot : r->r_ytop - r->r_ybot;
}
/*
* ----------------------------------------------------------------------------
* bpBinIndices --
*
* compute bin indices corresponding to area.
*
* ----------------------------------------------------------------------------
*/
static __inline__ void
bpBinIndices(Rect area, /* area */
Rect binArea, /* lower left corner of bin system */
int indexBits,
int dim,
bool xDir, /* TRUE for x bin, FALSE for y bin */
int *min, /* results go here */
int *max)
{
int ref, coord;
int index;
}

246
bplane/bplane.h Normal file
View File

@ -0,0 +1,246 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
#ifndef _BPLANE_H
#define _BPLANE_H
/*
* bplane.h --
*
* This file defines the interface between the bplane
* module and the rest of max.
*
* BUGS
* ====
*
* NOTE nested enums are currently broken do to dynamic binning.
*
* OVERVIEW OF BPLANES
* ===================
*
* BPlanes ('Binned' Planes) are a data-structure for storing, sorting,
* and accessing two dimensional geometric objects.
*
* BPlanes are an alternative to Planes, i.e. corner-stitched tile planes,
* defined in the tile module.
*
* Differences between Planes and BPlanes:
* --------------------------------------
*
* 1. BPlanes are more memory efficient.
* Three pointers (+ a modest amount of binning overhead)
* replaces approximately 8 pointers (4/tile, approx. 1 space
* tile for each data tile).
*
* 2. BPlanes use a 'next' procedure for enumeration, instead of
* function call-backs. This allows client code to be simpler
* and more readable, partcularly with regard to passing state info.
* In addition gprof results are easier to interpet, since
* there is not confusion about which client procedures belong to
* a given "loop".
*
* 3. Planes fundamentally assume objects don't overlap, while BPlanes
* make no such assumption. This makes BPlanes more generally useful.
* In particular they are a natural choice for instance uses,
* labels, and non-manhattan polygons (sorted on bounding boxes).
*
* 4. Planes are optimized for merging (merging recangles
* into maximal horizontal strips) and neighbor access
* (finding nearest elements to current element). BPlanes are less
* efficient for these operations.
*
* 5. Planes generally cannot be safely modified during an enumeration,
* but BPlanes can. This makes operations such as delete, copy, and
* move simpler in BPlanes.
*
* Interface
* ---------
*
* 1. The structure of elements to be stored in BPlanes must be as
* follows:
*
* typedef struct foo
* {
* struct void *foo_bpLinks[BP_NUM_LINKS];
* Rect foo_rect;
* <client fields go here>
* } Foo
*
* 2. It is the clients responsiblity to alloc/free elements.
*
* 3. The client must set foo_rect before adding the element
* to a BPlane. foo_rect must be canonical: not inverted.
*
* 4. The BPlane module does not access or modify any client fields.
*
* 5. The client may access/modify client fields at any time.
*
* 6. As long as an element belongs to a BPlane (i.e. has been
* added via BPAdd() and not removed via BPDelete()):
*
* a. The client should not reference/modify the foo_bpLinks[] fields.
* b. The client may reference but should not modify the foo_rect
* field.
* c. The client should not call BPAdd() for the element
* (an element can only belong to one BPlane at at time).
* d. The client should not free the element!
*
* 7. The client may assume tht BP_NUM_LINKS is at least one, and
* may use foo_bpLinks[0], for his own purposes as long as an
* element does not belong to a bplane.
*
* 8. Concurrent (nested) enumerations of a bplane are permitted.
*
* 9. Elements may not be added to a bplane during active enumeration(s)
* on that bplane.
*
* 10. An element may be deleted from a bplane at any time, including
* during active enumeration(s) of that bplane. After an element
* has been deleted from a bplane, it will not be enumerated
* (i.e. returned by BPEnumNext() on that bplane).
*
* Example
* -------
*
* Here is a procedure that takes an array of id'ed rectangles and an
* area as input, and prints the ids of all rectangles impinging on the
* area.
*
* typedef struct rid
* {
* struct rid *rid_bpLinks[BP_NUM_LINKS];
* Rect rid_rect;
* char *rid_id;
* } RId;
*
* void findRects(RId data[], // ided rects
* int n, // number of rects in data
* Rect *area) // area to search
* {
* int i;
* BPEnum bpe;
* BPlane *bp;
* RId *rid;
*
* bp = BPNew();
* for(i=0;i<n;i++) BPAdd(bp,&data[i]);
*
* BPEnumInit(&bpe,bp,area,BPE_OVERLAP,"findRects");
* while(rid = BPEnumNext(&bpe))
* {
* printf("%s\n", rid->rid_id);
* }
* BPEnumTerm(&bpe);
*
*/
/* offset of a structure member (used to gen offsets for ihash stuff) */
#if _MSC_VER
/* Microsoft compile complains about size of (void*), so must use (char*) */
/* Could use (char*) in UNIX version too. */
#define OFFSET(structure,member) \
( ((char *) &(((structure *) 0))->member) - ((char *) 0) )
#else
#define OFFSET(structure,member) \
( ((void *) &(((structure *) 0))->member) - ((void *) 0) )
#endif
/* data-structures opaque to clients */
#include "bplane/bpOpaque.h"
/* create a new BPlane */
extern BPlane *BPNew(void);
/* free storate assoicated with a BPlane
* (The BPlane must be empty.)
*/
extern void BPFree(BPlane *bp);
/* add an element to a BPlane */
extern void BPAdd(BPlane *bp,
void *element);
/* remove an element from a BPlane */
extern void BPDelete(BPlane *bp,
void *element);
/* begin an enumeration */
extern void BPEnumInit(BPEnum *bpe, /* this procedure initializes this
* client supplied 'handle' for the
* enumeration.
*/
BPlane *bp, /* bplane to search */
Rect *area, /* area to search */
int match, /* see below */
char *id); /* for debugging */
/* match values */
/* enum all elements in the bplane (area arg must be null) */
#define BPE_ALL 0
/* element need only touch area */
#define BPE_TOUCH 1
/* some part of element must be inside (not just on boundary of) area */
#define BPE_OVERLAP 2
/* elements rect must be identical to area */
#define BPE_EQUAL 3
/* return next element in enumeration (returns NULL if none) */
#include "bplane/bpEnum.h"
/* inlined extern void *BPEnumNext(BPEnum *bpe); */
/* terminate enumeration
*
* (unterminated enumerations can cause great inefficiency since
* all active enumerations for a bplane must be considered whenever
* an element is added or deleted.)
*/
extern void BPEnumTerm(BPEnum *bpe);
/* get current bounding box of BPlane */
extern Rect BPBBox(BPlane *bp);
/* compute number of bytes used by BPlane
* (does not count memory of the elements themselves)
*/
extern unsigned int BPStatMemory(BPlane *bp);
/* tabulate statistics on a bplane */
extern unsigned int
BPStat(BPlane *bp,
int *totCount, /* ret total number of elements */
int *inBox, /* ret num of elements in inBox */
int *totBins, /* ret tot num of bins */
int *emptyBins, /* ret num of empty bins */
int *binArraysp, /* ret num of bin arrays */
int *maxEffp, /* ret max effective list length */
int *maxBinCount, /* ret max count for regular bin */
int *totUnbinned, /* ret tot num of e's not binned */
int *maxDepth); /* ret max bin array depth */
#endif /* _BPLANE_H */

82
bplane/bplaneInt.h Normal file
View File

@ -0,0 +1,82 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
/*
* bplaneInt.h --
*
* This file defines constants and datastructures used internally by the
* bplane module, but not exported to the rest of the world.
*/
#ifndef _BPLANEINT_H
#define _BPLANEINT_H
/* Tcl linked Parameters */
extern int bpMinBAPop; /* don't sub(bin) when count less than this
*/
extern double bpMinAvgBinPop; /* try to keep average bin pop at or
* below this
*/
/* LabeledElement
*
* Used in this module as elements for test bplanes.
*/
typedef struct labeledelement
{
struct element *le_links[BP_NUM_LINKS];
Rect le_rect;
/* client data goes here */
char * le_text;
} LabeledElement;
/* bins */
extern void bpBinsUpdate(BPlane *bp);
extern void bpBinAdd(BinArray *ba, Element *e);
extern BinArray *bpBinArrayBuild(Rect bbox,
Element *elements, /* initial elements */
bool subbin); /* subbin as needed */
/* dump (for debug) */
extern void bpDumpRect(Rect *r);
extern void bpDump(BPlane *bp, int flags);
/* bpDump flags */
/* labeled elements */
# define BPD_LABELED 1
# define BPD_INTERNAL_UNITS 2
/* test */
void bpTestSnowGold(int size, bool trace);
extern BPlane *bpTestSnow(int size, bool trace);
extern Plane *bpTestSnowTile(int size, bool trace);
extern int bpRand(int min, int max);
#endif /* _BPLANEINT_H */

View File

@ -3678,7 +3678,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
Point childPoint, editPoint, rootPoint;
CellDef *def, *rootDef, *editDef;
bool hasChild, hasRoot, hasTrans;
Rect rootBox;
Rect rootBox, bbox;
Transform *tx_cell, trans_cell;
char **av;
char *cellnameptr, *fullpathname;
@ -3792,6 +3792,25 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
return FALSE;
}
/*
* Get def's bounding box. If def is an abstract view with CDFIXEDBBOX
* set, then used the property FIXED_BBOX to set the bounding box.
*/
bbox = def->cd_bbox;
if (def->cd_flags & CDFIXEDBBOX)
{
char *propvalue;
bool found;
propvalue = DBPropGet(def, "FIXED_BBOX", &found);
if (found)
{
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
&bbox.r_xtop, &bbox.r_ytop) != 4)
bbox = def->cd_bbox;
}
}
/*
* Parse the remainder of the arguments to find out the reference
* points in the child cell and the edit cell. Use the defaults
@ -3843,23 +3862,23 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
p = Lookup(av[1], refPointNames);
if (p == 0) /* lower left */
{
childPoint.p_x = def->cd_bbox.r_ll.p_x;
childPoint.p_y = def->cd_bbox.r_ll.p_y;
childPoint.p_x = bbox.r_ll.p_x;
childPoint.p_y = bbox.r_ll.p_y;
}
else if (p == 1) /* lower right */
{
childPoint.p_x = def->cd_bbox.r_ur.p_x;
childPoint.p_y = def->cd_bbox.r_ll.p_y;
childPoint.p_x = bbox.r_ur.p_x;
childPoint.p_y = bbox.r_ll.p_y;
}
else if (p == 2) /* upper left */
{
childPoint.p_x = def->cd_bbox.r_ll.p_x;
childPoint.p_y = def->cd_bbox.r_ur.p_y;
childPoint.p_x = bbox.r_ll.p_x;
childPoint.p_y = bbox.r_ur.p_y;
}
else if (p == 3) /* upper right */
{
childPoint.p_x = def->cd_bbox.r_ur.p_x;
childPoint.p_y = def->cd_bbox.r_ur.p_y;
childPoint.p_x = bbox.r_ur.p_x;
childPoint.p_y = bbox.r_ur.p_y;
}
else
{
@ -3960,9 +3979,9 @@ default_action:
{
Rect r;
GeoTransRect(tx_cell, &def->cd_bbox, &r);
GeoTranslateTrans(tx_cell, def->cd_bbox.r_xbot - r.r_xbot,
def->cd_bbox.r_ybot - r.r_ybot,
GeoTransRect(tx_cell, &bbox, &r);
GeoTranslateTrans(tx_cell, bbox.r_xbot - r.r_xbot,
bbox.r_ybot - r.r_ybot,
&trans_cell);
}
av += 1;
@ -3991,23 +4010,23 @@ default_action:
p = Lookup(av[1], refPointNames);
if (p == 0) /* lower left */
{
editPoint.p_x = def->cd_bbox.r_ll.p_x;
editPoint.p_y = def->cd_bbox.r_ll.p_y;
editPoint.p_x = bbox.r_ll.p_x;
editPoint.p_y = bbox.r_ll.p_y;
}
else if (p == 1) /* lower right */
{
editPoint.p_x = def->cd_bbox.r_ur.p_x;
editPoint.p_y = def->cd_bbox.r_ll.p_y;
editPoint.p_x = bbox.r_ur.p_x;
editPoint.p_y = bbox.r_ll.p_y;
}
else if (p == 2) /* upper left */
{
editPoint.p_x = def->cd_bbox.r_ll.p_x;
editPoint.p_y = def->cd_bbox.r_ur.p_y;
editPoint.p_x = bbox.r_ll.p_x;
editPoint.p_y = bbox.r_ur.p_y;
}
else if (p == 3) /* upper right */
{
editPoint.p_x = def->cd_bbox.r_ur.p_x;
editPoint.p_y = def->cd_bbox.r_ur.p_y;
editPoint.p_x = bbox.r_ur.p_x;
editPoint.p_y = bbox.r_ur.p_y;
}
else
{
@ -4073,7 +4092,7 @@ default_action:
* provided.
*/
if (!hasChild)
childPoint = def->cd_bbox.r_ll;
childPoint = bbox.r_ll;
if (!hasRoot)
{
if (!ToolGetBox(&rootDef, &rootBox))
@ -4102,7 +4121,7 @@ box_error:
GeoTranslateTrans(&trans_cell, rootPoint.p_x - childPoint.p_x,
rootPoint.p_y - childPoint.p_y,
&scx->scx_trans);
scx->scx_area = def->cd_bbox;
scx->scx_area = bbox;
return TRUE;
usage:

View File

@ -1635,7 +1635,8 @@ CmdFindNetProc(nodename, use, rect, warn_not_found)
/* Find the tile type of the tile at the specified point which */
/* exists on the plane pnum. */
(void) TiSrArea(NULL, plane, &localrect, findTile, (ClientData) &ttype);
DBSrPaintArea(NULL, plane, &localrect, &DBAllTypeBits, findTile,
(ClientData) &ttype);
}
else
{

View File

@ -832,7 +832,7 @@ cmdPsearchStats(str, tl, td, count)
*
* CmdTsearch --
*
* Call TiSrArea() a number of times over an area the size and shape of
* Call DBSrPaintArea() a number of times over an area the size and shape of
* that specified by the box, each time over a different area in the
* edit cell.
*
@ -943,18 +943,12 @@ CmdTsearch(w, cmd)
if (cmd->tx_argc < 5)
{
(void) TiSrArea((Tile *) NULL, plane, &rsearch,
(void) DBSrPaintArea((Tile *) NULL, plane, &rsearch, &DBAllTypeBits,
cmdTsrFunc, (ClientData) 0);
}
else
{
/****
if (strcmp(cmd->tx_argv[4], "mayo") == 0)
(void) TiSrAreaNR2((Tile *) NULL, plane, &rsearch, &mask,
cmdTsrFunc, (ClientData) 0);
else
****/
(void) DBSrPaintArea((Tile *) NULL, plane, &rsearch, &mask,
(void) DBSrPaintArea((Tile *) NULL, plane, &rsearch, &mask,
cmdTsrFunc, (ClientData) 0);
}
}

View File

@ -58,48 +58,38 @@ DBBoundCellPlane(def, extended, rect)
cbs.found = FALSE;
*rect = GeoNullRect;
if (TiSrArea((Tile *)NULL, def->cd_planes[PL_CELL],
&TiPlaneRect, dbCellBoundFunc, (ClientData) &filter) == 0)
if (DBSrCellPlaneArea(def->cd_cellPlane, &TiPlaneRect,
dbCellBoundFunc, (ClientData) &filter) == 0)
return cbs.found;
else
return -1;
}
int
dbCellBoundFunc(tile, fp)
Tile *tile;
dbCellBoundFunc(use, fp)
CellUse *use;
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)
bbox = &use->cu_bbox;
if (cbs->found)
{
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;
}
}
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;
}

View File

@ -45,7 +45,7 @@ struct searchArg
{
CellUse * celluse;
Rect * rect;
Plane * plane;
BPlane * bplane;
};
#define TOPLEFT 10
@ -55,6 +55,25 @@ struct searchArg
#define TOPBOTTOMLEFTRIGHT 15
int dbCellDebug = 0;
void
dbInstanceUnplace(CellUse *use)
{
ASSERT(use != (CellUse *) NULL, "dbInstanceUnplace");
/* It's important that this code run with interrupts disabled,
* or else we could leave the subcell tile plane in a weird
* state.
*/
SigDisableInterrupts();
BPDelete(use->cu_parent->cd_cellPlane, use);
DBUndoCellUse(use, UNDO_CELL_DELETE);
SigEnableInterrupts();
}
/*
* ----------------------------------------------------------------------------
@ -86,28 +105,18 @@ DBCellFindDup(use, parent)
* something identical to use?
*/
{
Tile *tile;
CellTileBody *body;
CellUse *checkUse;
BPEnum bpe;
CellUse *dupUse;
tile = TiSrPoint((Tile *) NULL, parent->cd_planes[PL_CELL],
&use->cu_bbox.r_ll);
for (body = (CellTileBody *) TiGetBody(tile);
body != NULL;
body = body->ctb_next)
{
checkUse = body->ctb_use;
if (use->cu_def != checkUse->cu_def) continue;
if ((use->cu_bbox.r_xbot != checkUse->cu_bbox.r_xbot)
|| (use->cu_bbox.r_xtop != checkUse->cu_bbox.r_xtop)
|| (use->cu_bbox.r_ybot != checkUse->cu_bbox.r_ybot)
|| (use->cu_bbox.r_ytop != checkUse->cu_bbox.r_ytop))
continue;
return checkUse;
}
return (CellUse *) NULL;
BPEnumInit(&bpe, parent->cd_cellPlane, &use->cu_bbox, BPE_EQUAL,
"DBCellFindDup");
while (dupUse = BPEnumNext(&bpe))
if (dupUse->cu_def == use->cu_def) break;
BPEnumTerm(&bpe);
return dupUse;
}
/*
* ----------------------------------------------------------------------------
@ -130,33 +139,30 @@ DBCellFindDup(use, parent)
*/
void
DBPlaceCell (celluse, targetcell)
CellUse * celluse; /* new celluse to add to subcell tile plane */
CellDef * targetcell; /* parent cell's definition */
DBPlaceCell (use, def)
CellUse * use; /* new celluse to add to subcell tile plane */
CellDef * def; /* parent cell's definition */
{
Rect rect; /* argument to TiSrArea(), placeCellFunc() */
Plane * plane; /* argument to TiSrArea(), placeCellFunc() */
struct searchArg arg; /* argument to placeCellFunc() */
Rect rect; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
BPlane *bplane; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
struct searchArg arg; /* argument to placeCellFunc() */
ASSERT(celluse != (CellUse *) NULL, "DBPlaceCell");
celluse->cu_parent = targetcell;
plane = targetcell->cd_planes[PL_CELL]; /* assign plane */
rect = celluse->cu_bbox;
/* rect = celluse->cu_extended; */
arg.rect = &rect;
arg.celluse = celluse;
arg.plane = plane;
ASSERT(use != (CellUse *) NULL, "DBPlaceCell");
ASSERT(def, "DBPlaceCell");
/* To do: Check non-duplicate placement, check non-duplicate ID */
use->cu_parent = def;
/* Be careful not to permit interrupts during this, or the
* database could be left in a trashed state.
*/
SigDisableInterrupts();
(void) TiSrArea((Tile *) NULL, plane, &rect, placeCellFunc,
(ClientData) &arg);
targetcell->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
BPAdd(def->cd_cellPlane, use);
def->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
if (UndoIsEnabled())
DBUndoCellUse(celluse, UNDO_CELL_PLACE);
DBUndoCellUse(use, UNDO_CELL_PLACE);
SigEnableInterrupts();
}
@ -176,19 +182,12 @@ DBPlaceCell (celluse, targetcell)
*/
void
DBDeleteCell (celluse)
CellUse * celluse;
DBDeleteCell (use)
CellUse * use;
{
Rect rect; /* argument to TiSrArea(), deleteCellFunc() */
Plane * plane; /* argument to TiSrArea(), deleteCellFunc() */
struct searchArg arg; /* argument to deleteCellFunc() */
ASSERT(use != (CellUse *) NULL, "DBDeleteCell");
ASSERT(celluse != (CellUse *) NULL, "DBDeleteCell");
plane = celluse->cu_parent->cd_planes[PL_CELL]; /* assign plane */
rect = celluse->cu_bbox;
arg.rect = &rect;
arg.plane = plane;
arg.celluse = celluse;
dbInstanceUnplace(use);
/* It's important that this code run with interrupts disabled,
* or else we could leave the subcell tile plane in a weird
@ -196,511 +195,10 @@ DBDeleteCell (celluse)
*/
SigDisableInterrupts();
(void) TiSrArea((Tile *) NULL, plane, &rect, deleteCellFunc,
(ClientData) &arg);
celluse->cu_parent->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
use->cu_parent->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
if (UndoIsEnabled())
DBUndoCellUse(celluse, UNDO_CELL_DELETE);
celluse->cu_parent = (CellDef *) NULL;
DBUndoCellUse(use, UNDO_CELL_DELETE);
use->cu_parent = (CellDef *) NULL;
SigEnableInterrupts();
}
/*
* ----------------------------------------------------------------------------
* placeCellFunc --
*
* Add a new subcell to a tile.
* Clip the tile with respect to the subcell's bounding box.
* Insert the new CellTileBody into the linked list in ascending order
* based on the celluse pointer.
* This function is passed to TiSrArea.
*
* Results:
* 0 is always returned.
*
* Side effects:
* Modifies the subcell tile plane of the appropriate CellDef.
* Allocates a new CellTileBody.
* ----------------------------------------------------------------------------
*/
int
placeCellFunc (tile, arg)
Tile * tile; /* target tile */
struct searchArg * arg; /* celluse, rect, plane */
{
Tile * tp;
CellTileBody * body, * ctp, * ctplast;
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("placeCellFunc called %x\n",tile);
#endif /* CELLDEBUG */
tp = clipCellTile (tile, arg->plane, arg->rect);
body = (CellTileBody *) mallocMagic((unsigned) (sizeof (CellTileBody)));
body->ctb_use = arg->celluse;
ctp = (CellTileBody *) tp->ti_body;
ctplast = ctp;
while ((ctp != (CellTileBody *) NULL) && (ctp->ctb_use > body->ctb_use))
{
ctplast = ctp;
ctp = ctp->ctb_next;
}
body->ctb_next = ctp;
if (ctp == (CellTileBody *) tp->ti_body) /* empty list or front of list */
TiSetBody(tp, body);
else /* after at least one CellTileBody */
ctplast->ctb_next = body;
/* merge tiles back into the the plane */
/* requires that TiSrArea visit tiles in NW to SE wavefront */
if ( RIGHT(tp) == arg->rect->r_xtop)
{
if (BOTTOM(tp) == arg->rect->r_ybot)
cellTileMerge (tp, arg->plane, TOPBOTTOMLEFTRIGHT);
else
cellTileMerge (tp, arg->plane, TOPLEFTRIGHT);
}
else if (BOTTOM(tp) == arg->rect->r_ybot)
cellTileMerge (tp, arg->plane, TOPBOTTOMLEFT);
else
cellTileMerge (tp, arg->plane, TOPLEFT);
return 0;
}
/*
* ----------------------------------------------------------------------------
* deleteCellFunc --
*
* Remove a subcell from a tile.
* This function is passed to TiSrArea.
*
* Results:
* Always returns 0.
*
* Side effects:
* Modifies the subcell tile plane of the appropriate CellDef.
* Deallocates a CellTileBody.
* ----------------------------------------------------------------------------
*/
int
deleteCellFunc (tile, arg)
Tile * tile;
struct searchArg * arg; /* plane, rect */
{
CellTileBody * ctp; /* CellTileBody to be freed */
CellTileBody * ctplast; /* follows one behind ctp */
CellUse * celluse;
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("deleteCellFunc called %x\n",tile);
#endif /* CELLDEBUG */
celluse = arg->celluse;
/* find the appropriate CellTileBody in the linked list */
ctp = (CellTileBody *) tile->ti_body;
ctplast = ctp;
while ((ctp != (CellTileBody *) NULL) && (ctp->ctb_use != celluse))
{
ctplast = ctp;
ctp = ctp->ctb_next;
}
/* there should have been a match */
if (ctp == (CellTileBody *) NULL)
{
ASSERT (ctp != (CellTileBody *) NULL, "deleteCellFunc");
return 0;
}
/* relink the list with one CellTileBody deleted */
if (ctp == ctplast) /* front of list */
TiSetBody(tile, ctp->ctb_next);
else /* beyond front of list */
ctplast->ctb_next = ctp->ctb_next;
freeMagic((char *) ctp);
/* merge tiles back into the the plane */
/* requires that TiSrArea visit tiles in NW to SE wavefront */
if ( RIGHT(tile) == arg->rect->r_xtop)
{
if (BOTTOM(tile) == arg->rect->r_ybot)
cellTileMerge (tile, arg->plane, TOPBOTTOMLEFTRIGHT);
else
cellTileMerge (tile, arg->plane, TOPLEFTRIGHT);
}
else if (BOTTOM(tile) == arg->rect->r_ybot)
cellTileMerge (tile, arg->plane, TOPBOTTOMLEFT);
else
cellTileMerge (tile, arg->plane, TOPLEFT);
return (0);
}
/*
* ----------------------------------------------------------------------------
* clipCellTile --
*
* Clip the given tile against the given rectangle.
*
* Results:
* Returns a pointer to the clipped tile.
*
* Side effects:
* Modifies the database plane that contains the given tile.
* ----------------------------------------------------------------------------
*/
Tile *
clipCellTile (tile, plane, rect)
Tile * tile;
Plane * plane;
Rect * rect;
{
Tile * newtile;
if (TOP(tile) > rect->r_ytop)
{
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("clipCellTile calls TiSplitY TOP\n");
#endif /* CELLDEBUG */
newtile = TiSplitY (tile, rect->r_ytop); /* no merge */
dupTileBody (tile, newtile);
}
if (BOTTOM(tile) < rect->r_ybot)
{
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("clipCellTile calls TiSplitY BOTTOM\n");
#endif /* CELLDEBUG */
newtile = tile;
tile = TiSplitY (tile, rect->r_ybot); /* no merge */
dupTileBody (newtile, tile);
}
if (RIGHT(tile) > rect->r_xtop)
{
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("clipCellTile calls TiSplitX RIGHT\n");
#endif /* CELLDEBUG */
newtile = TiSplitX (tile, rect->r_xtop);
dupTileBody (tile, newtile);
cellTileMerge (newtile, plane, TOPBOTTOM);
}
if (LEFT(tile) < rect->r_xbot)
{
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("clipCellTile calls TiSplitX LEFT\n");
#endif /* CELLDEBUG */
newtile = tile;
tile = TiSplitX (tile, rect->r_xbot);
dupTileBody (newtile, tile);
cellTileMerge (newtile, plane, TOPBOTTOM);
}
return (tile);
} /* clipCellTile */
/*
* ----------------------------------------------------------------------------
* dupTileBody --
*
* Duplicate the body of an old tile as the body for a new tile.
*
* Results:
* None.
*
* Side effects:
* Allocates new CellTileBodies unless the old tile was a space tile.
* ----------------------------------------------------------------------------
*/
void
dupTileBody (oldtp, newtp)
Tile * oldtp;
Tile * newtp;
{
CellTileBody * oldctb, * newctb, * newctblast;
oldctb = (CellTileBody *) oldtp->ti_body;
if (oldctb != (CellTileBody *) NULL)
{
newctb = (CellTileBody *) mallocMagic((unsigned) (sizeof (CellTileBody)));
TiSetBody(newtp, newctb);
newctb->ctb_use = oldctb->ctb_use;
oldctb = oldctb->ctb_next;
newctblast = newctb;
while (oldctb != (CellTileBody *) NULL)
{
newctb = (CellTileBody *) mallocMagic((unsigned) (sizeof (CellTileBody)));
newctblast->ctb_next = newctb;
newctb->ctb_use = oldctb->ctb_use;
oldctb = oldctb->ctb_next;
newctblast = newctb;
}
newctblast->ctb_next = (CellTileBody *) NULL;
}
else TiSetBody(newtp, NULL);
} /* dupTileBody */
/*
* ----------------------------------------------------------------------------
* cellTileMerge --
*
* Merge the given tile with its plane in the directions specified.
*
* Results:
* None.
*
* Side effects:
* Modifies the database plane that contains the given tile.
* ----------------------------------------------------------------------------
*/
void
cellTileMerge (tile, plane, direction)
Tile * tile;
Plane * plane;
int direction; /* TOP = 8, BOTTOM = 4, LEFT = 2, RIGHT = 1 */
{
Point topleft, bottomright;
Tile * dummy, * tpleft, * tpright, * tp1, * tp2;
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("cellTileMerge %x\n",tile);
#endif /* CELLDEBUG */
topleft.p_x = LEFT(tile);
topleft.p_y = TOP(tile);
bottomright.p_x = RIGHT(tile);
bottomright.p_y = BOTTOM(tile);
if ((direction >> 1) % 2) /* LEFT */
{
tpright = tile;
tpleft = BL(tpright);
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("LEFT %x %x\n",tpleft,tpright);
#endif /* CELLDEBUG */
while (BOTTOM(tpleft) < topleft.p_y) /* go up left edge */
{
if (ctbListMatch (tpleft, tpright))
{
if (BOTTOM(tpleft) < BOTTOM(tpright))
{
dummy = tpleft;
tpleft = TiSplitY (tpleft, BOTTOM (tpright));
dupTileBody (dummy, tpleft);
}
else if (BOTTOM(tpleft) > BOTTOM(tpright))
{
dummy = tpright;
tpright = TiSplitY (tpright, BOTTOM (tpleft));
dupTileBody (dummy, tpright);
}
if (TOP(tpleft) > TOP(tpright))
{
dummy = TiSplitY (tpleft, TOP(tpright));
dupTileBody (tpleft, dummy);
}
else if (TOP(tpright) > TOP(tpleft))
{
dummy = TiSplitY (tpright, TOP(tpleft));
dupTileBody (tpright, dummy);
}
freeCTBList (tpright);
TiJoinX (tpleft, tpright, plane); /* tpright disappears */
tpright = RT(tpleft);
if (BOTTOM(tpright) < topleft.p_y) tpleft = BL(tpright);
else tpleft = tpright; /* we're off the top of the tile */
/* this will break the while loop */
} /* if (ctbListMatch (tpleft, tpright)) */
else tpleft = RT(tpleft);
} /* while */
tile = tpleft; /* for TiSrPoint in next IF statement */
}
if (direction % 2) /* RIGHT */
{
tpright = TiSrPoint (tile, plane, &bottomright);
--(bottomright.p_x);
tpleft = TiSrPoint (tpright, plane, &bottomright);
++(bottomright.p_x);
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("RIGHT %x %x\n",tpleft,tpright);
#endif /* CELLDEBUG */
while (BOTTOM(tpright) < topleft.p_y) /* go up right edge */
{
if (ctbListMatch (tpleft, tpright))
{
if (BOTTOM(tpright) < BOTTOM(tpleft))
{
dummy = tpright;
tpright = TiSplitY (tpright, BOTTOM(tpleft));
dupTileBody (dummy, tpright);
}
else if (BOTTOM(tpleft) < BOTTOM(tpright))
{
dummy = tpleft;
tpleft = TiSplitY (tpleft, BOTTOM(tpright));
dupTileBody (dummy, tpleft);
}
if (TOP(tpright) > TOP(tpleft))
{
dummy = TiSplitY (tpright, TOP(tpleft));
dupTileBody (tpright, dummy);
}
else if (TOP(tpleft) > TOP(tpright))
{
dummy = TiSplitY (tpleft, TOP(tpright));
dupTileBody (tpleft, dummy);
}
freeCTBList (tpright);
TiJoinX (tpleft, tpright, plane); /* tpright disappears */
tpright = RT(tpleft);
while (LEFT(tpright) > bottomright.p_x) tpright = BL(tpright);
/* tpleft can be garbage if we're off the top of the loop, */
/* but it doesn't matter since the expression tests tpright */
tpleft = BL(tpright);
} /* if (ctbListMatch (tpleft, tpright)) */
else
{
tpright = RT(tpright);
while (LEFT(tpright) > bottomright.p_x) tpright = BL(tpright);
tpleft = BL(tpright); /* left side merges may have */
/* created more tiles */
}
} /* while */
tile = tpright; /* for TiSrPoint in next IF statement */
}
if ((direction >> 3) % 2) /* TOP */
{
tp1 = TiSrPoint (tile, plane, &topleft); /* merge across top */
--(topleft.p_y);
tp2 = TiSrPoint (tile, plane, &topleft);/* top slice of original tile */
++(topleft.p_y);
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("TOP %x %x\n",tp1,tp2);
#endif /* CELLDEBUG */
if ((LEFT(tp1) == LEFT(tp2) ) &&
(RIGHT(tp1) == RIGHT(tp2)) &&
(ctbListMatch (tp1, tp2) ))
{
freeCTBList (tp2);
TiJoinY (tp1, tp2, plane);
}
tile = tp1; /* for TiSrPoint in next IF statement */
}
if ((direction >> 2) % 2) /* BOTTOM */
{
--(bottomright.p_x);
/* bottom slice of orig tile */
tp1 = TiSrPoint (tile, plane, &bottomright);
--(bottomright.p_y);
tp2 = TiSrPoint (tile, plane, &bottomright); /* merge across bottom */
#ifdef CELLDEBUG
if (dbCellDebug) TxPrintf("BOTTOM %x %x\n",tp1,tp2);
#endif /* CELLDEBUG */
if ((LEFT(tp1) == LEFT(tp2) ) &&
(RIGHT(tp1) == RIGHT(tp2)) &&
(ctbListMatch (tp1, tp2) ))
{
freeCTBList (tp2);
TiJoinY (tp1, tp2, plane);
}
}
}
/*
* ----------------------------------------------------------------------------
* freeCTBList --
*
* Free all CellTileBodies attached to the give tile.
*
* Results:
* None.
*
* Side effects:
* Frees CellTileBodies.
* ----------------------------------------------------------------------------
*/
void
freeCTBList (tile)
Tile * tile;
{
CellTileBody * ctp, * ctplast;
ctp = (CellTileBody *) tile->ti_body;
while (ctp != (CellTileBody *) NULL)
{
ctplast = ctp;
ctp = ctp->ctb_next;
freeMagic((char *) ctplast);
}
TiSetBody(tile, NULL);
}
/*
* ----------------------------------------------------------------------------
* ctbListMatch --
*
* Compare two linked lists of CellTileBodies, assuming that they are
* sorted in ascending order by celluse pointers.
*
* Results:
* True if the tiles have identical lists of CellTileBodies.
*
* Side effects:
* None.
* ----------------------------------------------------------------------------
*/
bool
ctbListMatch (tp1, tp2)
Tile * tp1, * tp2;
{
CellTileBody * ctp1, * ctp2;
ctp1 = (CellTileBody *) tp1->ti_body;
ctp2 = (CellTileBody *) tp2->ti_body;
while (ctp1 && ctp2 && (ctp1->ctb_use == ctp2->ctb_use))
ctp1 = ctp1->ctb_next, ctp2 = ctp2->ctb_next;
return ((ctp1 == (CellTileBody *) NULL) && (ctp2 == (CellTileBody *) NULL));
}

View File

@ -616,11 +616,6 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
bool foundAny;
int pNum;
/* Cells which declare their bounding box to be fixed */
/* must return immediately. */
if (cellDef->cd_flags & CDFIXEDBBOX) return;
/*
* Include area of subcells separately
*/

View File

@ -1318,7 +1318,8 @@ DBCellDefAlloc()
TTMaskZero(&cellDef->cd_types);
HashInit(&cellDef->cd_idHash, 16, HT_STRINGKEYS);
cellDef->cd_planes[PL_CELL] = DBNewPlane((ClientData) NULL);
cellDef->cd_cellPlane = BPNew();
cellDef->cd_planes[PL_ROUTER] = DBNewPlane((ClientData) NULL);
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
cellDef->cd_planes[pNum] = DBNewPlane((ClientData) TT_SPACE);
@ -1512,9 +1513,10 @@ DBCellDefFree(cellDef)
*/
SigDisableInterrupts();
DBFreeCellPlane(cellDef->cd_planes[PL_CELL]);
TiFreePlane(cellDef->cd_planes[PL_CELL]);
DBClearCellPlane(cellDef); /* Remove instances only */
BPFree(cellDef->cd_cellPlane); /* Remove the cell plane itself */
TiFreePlane(cellDef->cd_planes[PL_ROUTER]);
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
{
DBFreePaintPlane(cellDef->cd_planes[pNum]);

View File

@ -51,7 +51,53 @@ struct seeTypesArg
TileTypeBitMask *saa_mask; /* Mask of tile types seen in search */
Rect *saa_rect; /* Search area in root coordinates */
};
/*
*-----------------------------------------------------------------------------
*
* DBSrCellPlaneArea --
*
* Searches a CellDef's cell plane and calls function func() for each
* cell use found.
*
* func() must be in the form:
*
* int func(CellUse *use, ClientData cdata)
*
* and must return 0 to keep the search running, or 1 to end the search.
*
* Replaces the original TiSrArea() routine, but with the function's
* first argument as a CellUse pointer rather than a Tile pointer,
* since the tile plane has been replaced with the BPlane method.
*
* Returns 1 if the func() returns 1; otherwise returns 0 to keep the
* search alive.
*
*-----------------------------------------------------------------------------
*/
int
DBSrCellPlaneArea(BPlane *plane, Rect *rect, int (*func)(), ClientData arg)
{
BPEnum bpe;
CellUse *use;
int rval = 0;
BPEnumInit(&bpe, plane, rect, BPE_OVERLAP, "DBSrCellPlaneArea");
while (use = BPEnumNext(&bpe))
{
if ((*func)(use, arg))
{
rval = 1;
break;
}
}
BPEnumTerm(&bpe);
return rval;
}
/*
*-----------------------------------------------------------------------------
*
@ -81,7 +127,7 @@ struct seeTypesArg
*
* The client procedure should not modify any of the paint planes in
* the cells visited by DBTreeSrTiles, because we use DBSrPaintArea
* instead of TiSrArea as our paint-tile enumeration function.
* as our paint-tile enumeration function.
*
* Results:
* 0 is returned if the search finished normally. 1 is returned
@ -112,7 +158,7 @@ DBTreeSrTiles(scx, mask, xMask, func, cdarg)
int (*func)(); /* Function to apply at each qualifying tile */
ClientData cdarg; /* Client data for above function */
{
int dbCellTileSrFunc();
int dbCellPlaneSrFunc();
TreeFilter filter;
/* Set up the filter and call the recursive filter function */
@ -124,7 +170,7 @@ DBTreeSrTiles(scx, mask, xMask, func, cdarg)
filter.tf_dinfo = 0;
filter.tf_planes = DBTechTypesToPlanes(mask);
return dbCellTileSrFunc(scx, &filter);
return dbCellPlaneSrFunc(scx, &filter);
}
/*
@ -154,7 +200,7 @@ DBTreeSrNMTiles(scx, dinfo, mask, xMask, func, cdarg)
int (*func)(); /* Function to apply at each qualifying tile */
ClientData cdarg; /* Client data for above function */
{
int dbCellTileSrFunc();
int dbCellPlaneSrFunc();
TreeFilter filter;
/* Set up the filter and call the recursive filter function */
@ -166,17 +212,17 @@ DBTreeSrNMTiles(scx, dinfo, mask, xMask, func, cdarg)
filter.tf_dinfo = dinfo;
filter.tf_planes = DBTechTypesToPlanes(mask);
return dbCellTileSrFunc(scx, &filter);
return dbCellPlaneSrFunc(scx, &filter);
}
/*
* dbCellTileSrFunc --
* dbCellPlaneSrFunc --
*
* Recursive filter procedure applied to the cell by DBTreeSrTiles().
*/
int
dbCellTileSrFunc(scx, fp)
dbCellPlaneSrFunc(scx, fp)
SearchContext *scx;
TreeFilter *fp;
{
@ -184,7 +230,7 @@ dbCellTileSrFunc(scx, fp)
CellDef *def = scx->scx_use->cu_def;
int pNum;
ASSERT(def != (CellDef *) NULL, "dbCellTileSrFunc");
ASSERT(def != (CellDef *) NULL, "dbCellPlaneSrFunc");
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
@ -219,10 +265,10 @@ dbCellTileSrFunc(scx, fp)
/*
* Now apply ourselves recursively to each of the CellUses
* in our tile plane.
* in our cell plane.
*/
if (DBCellSrArea(scx, dbCellTileSrFunc, (ClientData) fp))
if (DBCellSrArea(scx, dbCellPlaneSrFunc, (ClientData) fp))
return 1;
else return 0;
}
@ -270,7 +316,7 @@ DBTreeSrUniqueTiles(scx, mask, xMask, func, cdarg)
int (*func)(); /* Function to apply at each qualifying tile */
ClientData cdarg; /* Client data for above function */
{
int dbCellTileSrFunc();
int dbCellPlaneSrFunc();
TreeFilter filter;
/* Set up the filter and call the recursive filter function */
@ -288,7 +334,7 @@ DBTreeSrUniqueTiles(scx, mask, xMask, func, cdarg)
* dbCellUniqueTileSrFunc --
*
* Recursive filter procedure applied to the cell by DBTreeSrUniqueTiles().
* This is similar to dbCellTileSrFunc, except that for each plane searched,
* This is similar to dbCellPlaneSrFunc, except that for each plane searched,
* only the tile types having that plane as their home plane will be passed
* to the filter function. Contacts will therefore be processed only once.
*/
@ -348,8 +394,6 @@ dbCellUniqueTileSrFunc(scx, fp)
*
* DBNoTreeSrTiles --
*
* (*** Move to database module after tested)
*
* NOTE: THIS PROCEDURE IS EXACTLY LIKE DBTreeSrTiles EXCEPT THAT IT DOES
* NOT SEARCH SUBCELLS.
*
@ -377,7 +421,7 @@ dbCellUniqueTileSrFunc(scx, fp)
*
* The client procedure should not modify any of the paint planes in
* the cells visited by DBTreeSrTiles, because we use DBSrPaintArea
* instead of TiSrArea as our paint-tile enumeration function.
* as our paint-tile enumeration function.
*
* Results:
* 0 is returned if the search finished normally. 1 is returned
@ -1030,7 +1074,6 @@ DBCellSrArea(scx, func, cdarg)
{
TreeFilter filter;
TreeContext context;
Rect expanded;
int dbCellSrFunc();
filter.tf_func = func;
@ -1042,22 +1085,10 @@ DBCellSrArea(scx, func, cdarg)
if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, NULL))
return 0;
/* In order to make this work with zero-size areas, we first expand
* the area by before searching the tile plane. DbCellSrFunc will
* check carefully to throw out things that don't overlap the original
* area. The expansion is tricky because we mustn't expand infinities.
*/
expanded = scx->scx_area;
if (expanded.r_xbot > TiPlaneRect.r_xbot) expanded.r_xbot -= 1;
if (expanded.r_ybot > TiPlaneRect.r_ybot) expanded.r_ybot -= 1;
if (expanded.r_xtop < TiPlaneRect.r_xtop) expanded.r_xtop += 1;
if (expanded.r_ytop < TiPlaneRect.r_ytop) expanded.r_ytop += 1;
if (TiSrArea((Tile *) NULL, scx->scx_use->cu_def->cd_planes[PL_CELL],
&expanded, dbCellSrFunc, (ClientData) &context))
if (DBSrCellPlaneArea(scx->scx_use->cu_def->cd_cellPlane,
&scx->scx_area, dbCellSrFunc, (ClientData) &context))
return 1;
else return 0;
return 0;
}
/*
@ -1066,17 +1097,7 @@ DBCellSrArea(scx, func, cdarg)
* dbCellSrFunc --
*
* Filter procedure for DBCellSrArea. Applies the procedure given
* to DBCellSrArea to any of the CellUses in the tile that are
* enumerable.
*
* Since subcells are allowed to overlap, a single tile body may
* refer to many subcells and a single subcell may be referred to
* by many tile bodies. To insure that each CellUse is enumerated
* exactly once, the procedure given to DBCellSrArea is only applied
* to a CellUse when its lower right corner is contained in the
* tile to dbCellSrFunc (or otherwise at the last tile encountered
* in the event the lower right corner of the CellUse is outside the
* search rectangle).
* to DBCellSrArea to any of the CellUses in the given area.
*
* Results:
* 0 is normally returned, and 1 is returned if an abort occurred.
@ -1089,88 +1110,56 @@ DBCellSrArea(scx, func, cdarg)
*/
int
dbCellSrFunc(tile, cxp)
Tile *tile;
dbCellSrFunc(use, cxp)
CellUse *use;
TreeContext *cxp;
{
TreeFilter *fp = cxp->tc_filter;
SearchContext *scx = cxp->tc_scx;
CellUse *use;
Rect *bbox;
CellTileBody *body;
SearchContext newScx;
Transform t, tinv;
Rect tileArea;
int srchBot, srchRight;
int xlo, xhi, ylo, yhi, xbase, ybase, xsep, ysep, clientResult;
srchBot = scx->scx_area.r_ybot;
srchRight = scx->scx_area.r_xtop;
TITORECT(tile, &tileArea);
bbox = &use->cu_bbox;
newScx.scx_use = use;
/* Make sure that this tile really does overlap the search area
* (it could be just touching because of the expand-by-one in
* DBCellSrArea).
*/
if (!GEO_OVERLAP(&tileArea, &scx->scx_area)) return 0;
for (body = (CellTileBody *) TiGetBody(tile);
body != NULL;
body = body->ctb_next)
/* If not an array element, life is much simpler */
if (use->cu_xlo == use->cu_xhi && use->cu_ylo == use->cu_yhi)
{
use = newScx.scx_use = body->ctb_use;
ASSERT(use != (CellUse *) NULL, "dbCellSrFunc");
/* The check below is to ensure that we only enumerate each
* cell once, even though it appears in many different tiles
* in the subcell plane.
*/
bbox = &use->cu_bbox;
if ( (tileArea.r_ybot <= bbox->r_ybot ||
(tileArea.r_ybot <= srchBot && bbox->r_ybot < srchBot))
&& (tileArea.r_xtop >= bbox->r_xtop ||
(tileArea.r_xtop >= srchRight && bbox->r_xtop >= srchRight)))
{
/* If not an array element, life is much simpler */
if (use->cu_xlo == use->cu_xhi && use->cu_ylo == use->cu_yhi)
{
newScx.scx_x = use->cu_xlo, newScx.scx_y = use->cu_yhi;
if (SigInterruptPending) return 1;
GEOINVERTTRANS(&use->cu_transform, &tinv);
GeoTransTrans(&use->cu_transform, &scx->scx_trans,
newScx.scx_x = use->cu_xlo, newScx.scx_y = use->cu_yhi;
if (SigInterruptPending) return 1;
GEOINVERTTRANS(&use->cu_transform, &tinv);
GeoTransTrans(&use->cu_transform, &scx->scx_trans,
&newScx.scx_trans);
GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area);
if ((*fp->tf_func)(&newScx, fp->tf_arg) == 1)
return 1;
continue;
}
/*
* More than a single array element;
* check to see which ones overlap our search area.
*/
DBArrayOverlap(use, &scx->scx_area, &xlo, &xhi, &ylo, &yhi);
xsep = (use->cu_xlo > use->cu_xhi) ? -use->cu_xsep : use->cu_xsep;
ysep = (use->cu_ylo > use->cu_yhi) ? -use->cu_ysep : use->cu_ysep;
for (newScx.scx_y = ylo; newScx.scx_y <= yhi; newScx.scx_y++)
for (newScx.scx_x = xlo; newScx.scx_x <= xhi; newScx.scx_x++)
{
if (SigInterruptPending) return 1;
xbase = xsep * (newScx.scx_x - use->cu_xlo);
ybase = ysep * (newScx.scx_y - use->cu_ylo);
GeoTransTranslate(xbase, ybase, &use->cu_transform, &t);
GEOINVERTTRANS(&t, &tinv);
GeoTransTrans(&t, &scx->scx_trans, &newScx.scx_trans);
GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area);
clientResult = (*fp->tf_func)(&newScx, fp->tf_arg);
if (clientResult == 2) goto skipArray;
else if (clientResult == 1) return 1;
}
}
skipArray: continue;
GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area);
if ((*fp->tf_func)(&newScx, fp->tf_arg) == 1)
return 1;
return 0;
}
/*
* More than a single array element;
* check to see which ones overlap our search area.
*/
DBArrayOverlap(use, &scx->scx_area, &xlo, &xhi, &ylo, &yhi);
xsep = (use->cu_xlo > use->cu_xhi) ? -use->cu_xsep : use->cu_xsep;
ysep = (use->cu_ylo > use->cu_yhi) ? -use->cu_ysep : use->cu_ysep;
for (newScx.scx_y = ylo; newScx.scx_y <= yhi; newScx.scx_y++)
for (newScx.scx_x = xlo; newScx.scx_x <= xhi; newScx.scx_x++)
{
if (SigInterruptPending) return 1;
xbase = xsep * (newScx.scx_x - use->cu_xlo);
ybase = ysep * (newScx.scx_y - use->cu_ylo);
GeoTransTranslate(xbase, ybase, &use->cu_transform, &t);
GEOINVERTTRANS(&t, &tinv);
GeoTransTrans(&t, &scx->scx_trans, &newScx.scx_trans);
GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area);
clientResult = (*fp->tf_func)(&newScx, fp->tf_arg);
if (clientResult == 2) return 0;
else if (clientResult == 1) return 1;
}
return 0;
}
@ -1179,9 +1168,10 @@ dbCellSrFunc(tile, cxp)
*
* DBCellEnum --
*
* Apply the supplied procedure once to each CellUse in the subcell tile
* Apply the supplied procedure once to each CellUse in the subcell
* plane of the supplied CellDef. This procedure is not a geometric
* search, but rather a hierarchical enumeration.
* search, but rather a hierarchical enumeration. Use DBSrCellPlaneArea()
* for geometric searches over an area.
*
* The procedure should be of the following form:
* int
@ -1216,7 +1206,7 @@ DBCellEnum(cellDef, func, cdarg)
filter.tf_arg = cdarg;
if ((cellDef->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(cellDef, (char *) NULL, TRUE, NULL)) return 0;
if (TiSrArea((Tile *) NULL, cellDef->cd_planes[PL_CELL],
if (DBSrCellPlaneArea(cellDef->cd_cellPlane,
&TiPlaneRect, dbEnumFunc, (ClientData) &filter))
return 1;
else return 0;
@ -1228,11 +1218,7 @@ DBCellEnum(cellDef, func, cdarg)
* dbEnumFunc --
*
* Filter procedure for DBCellEnum. Applies the procedure given
* to DBCellEnum to any of the CellUses in the tile that are
* enumerable.
*
* The scheme used for handling overlapping subcells is the same
* as used in DBCellSrArea above.
* to DBCellEnum to the visited CellUse.
*
* Results:
* 0 normally, 1 if abort occurred.
@ -1245,28 +1231,17 @@ DBCellEnum(cellDef, func, cdarg)
*/
int
dbEnumFunc(tile, fp)
Tile *tile;
dbEnumFunc(use, fp)
CellUse *use;
TreeFilter *fp;
{
CellUse *use;
CellTileBody *body;
Rect *bbox;
for (body = (CellTileBody *) TiGetBody(tile);
body != NULL;
body = body->ctb_next)
{
use = body->ctb_use;
ASSERT(use != (CellUse *) NULL, "dbCellSrFunc");
bbox = &use->cu_bbox;
if ((BOTTOM(tile) <= bbox->r_ybot) && (RIGHT(tile) >= bbox->r_xtop))
if ((*fp->tf_func)(use, fp->tf_arg)) return 1;
}
bbox = &use->cu_bbox;
if ((*fp->tf_func)(use, fp->tf_arg)) return 1;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -1594,10 +1569,10 @@ dbTileScaleFunc(tile, scvals)
* DBSrCellUses --
*
* Do function "func" for each cell use in cellDef, passing "arg" as
* client data. Unlike DBEnumCell, this routine first collects a linked
* list of cell uses, then performs the function on the list, so that
* the search cannot be corrupted by, removing or reallocating the use
* structure from the cell def. Function "func" takes 2 arguments:
* client data. This routine first collects a linked list of cell uses,
* then performs the function on the list, so that the search cannot be
* corrupted by (specifically) removing the use structure from the cell
* def's bplane. Function "func" takes 2 arguments:
*
* int func(Celluse *use, ClientData arg) {}
*
@ -1671,7 +1646,7 @@ dbScaleCell(cellDef, scalen, scaled)
*/
int scalen, scaled; /* scale numerator and denominator. */
{
int dbCellTileEnumFunc(), dbCellUseEnumFunc();
int dbCellScaleFunc(), dbCellUseEnumFunc();
Label *lab;
int pNum;
LinkedTile *lhead, *lt;
@ -1731,31 +1706,13 @@ dbScaleCell(cellDef, scalen, scaled)
lu = lu->cu_next;
}
/* Scale the position of all subcell uses. Count all of the tiles in the */
/* Scale the position of all subcell uses. Count all of the cells in the */
/* subcell plane, and scale those without reference to the actual cells (so */
/* we don't count the cells multiple times). */
lhead = NULL;
(void) TiSrArea((Tile *)NULL, cellDef->cd_planes[PL_CELL], &TiPlaneRect,
dbCellTileEnumFunc, (ClientData) &lhead);
/* Scale each of the tiles in the linked list by (n / d) */
/* Don't scale (M)INFINITY on boundary tiles! */
lt = lhead;
while (lt != NULL)
{
DBScalePoint(&lt->tile->ti_ll, scalen, scaled);
lt = lt->t_next;
}
/* Free this linked tile structure */
lt = lhead;
while (lt != NULL)
{
freeMagic((char *)lt);
lt = lt->t_next;
}
(void) DBSrCellPlaneArea(cellDef->cd_cellPlane, &TiPlaneRect,
dbCellUseEnumFunc, (ClientData) &lhead);
/* Scale all of the paint tiles in this cell by creating a new plane */
/* and copying all tiles into the new plane at scaled dimensions. */
@ -1810,33 +1767,33 @@ donecell:
DBScalePoint(&cellDef->cd_extended.r_ll, scalen, scaled);
DBScalePoint(&cellDef->cd_extended.r_ur, scalen, scaled);
return 0;
}
/* If the cell is an abstract view with a fixed bounding box, then */
/* adjust the bounding box property to match the new scale. */
/*
* ----------------------------------------------------------------------------
*
* dbCellTileEnumFunc --
*
* Enumeration procedure called on each tile encountered in the search of
* the cell plane. Adds the tile to a linked list of tiles.
*
* ----------------------------------------------------------------------------
*/
if ((cellDef->cd_flags & CDFIXEDBBOX) != 0)
{
Rect r;
bool found;
char *propval;
int
dbCellTileEnumFunc(tile, arg)
Tile *tile;
LinkedTile **arg;
{
LinkedTile *lt;
propval = (char *)DBPropGet(cellDef, "FIXED_BBOX", &found);
if (found)
{
if (sscanf(propval, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
{
DBScalePoint(&r.r_ll, scalen, scaled);
DBScalePoint(&r.r_ur, scalen, scaled);
lt = (LinkedTile *) mallocMagic(sizeof(LinkedTile));
propval = (char *)mallocMagic(40);
sprintf(propval, "%d %d %d %d", r.r_xbot, r.r_ybot,
r.r_xtop, r.r_ytop);
DBPropPut(cellDef, "FIXED_BBOX", propval);
}
}
}
lt->tile = tile;
lt->t_next = (*arg);
(*arg) = lt;
return 0;
}

View File

@ -131,25 +131,20 @@ DBCellCopyDefBody(sourceDef, destDef)
*/
SigDisableInterrupts();
(void) TiSrArea((Tile *) NULL, destDef->cd_planes[PL_CELL],
&TiPlaneRect, dbCopyDefFunc, (ClientData) destDef);
(void) DBSrCellPlaneArea(destDef->cd_cellPlane,
&TiPlaneRect, dbCopyDefFunc, (ClientData) destDef);
SigEnableInterrupts();
}
int
dbCopyDefFunc(tile, def)
Tile *tile; /* Tile to search for subcell uses. */
dbCopyDefFunc(use, def)
CellUse *use; /* Subcell use. */
CellDef *def; /* Set parent pointer in each use to this. */
{
CellTileBody *ctb;
for (ctb = (CellTileBody *) tile->ti_body; ctb != NULL;
ctb = ctb->ctb_next)
{
ctb->ctb_use->cu_parent = def;
}
use->cu_parent = def;
return 0;
}
/*
* ----------------------------------------------------------------------------
@ -185,19 +180,8 @@ DBCellClearDef(cellDef)
SigDisableInterrupts();
/*
* We use a simple optimization to avoid trying
* to clear an already empty plane.
*/
plane = cellDef->cd_planes[PL_CELL];
tile = TR(plane->pl_left);
if (TiGetBody(tile) != (ClientData) NULL
|| LB(tile) != plane->pl_bottom
|| TR(tile) != plane->pl_right
|| RT(tile) != plane->pl_top)
{
DBClearCellPlane(plane);
}
/* Remove all instances from the cell plane */
DBClearCellPlane(cellDef);
/* Reduce clutter by reinitializing the id hash table */
HashKill(&cellDef->cd_idHash);
@ -224,41 +208,7 @@ DBCellClearDef(cellDef)
SigEnableInterrupts();
}
/*
* ----------------------------------------------------------------------------
*
* DBClearCellPlane --
*
* Remove all cell uses contained in the given cell tile plane.
* Deallocates the Tiles and CellTileBodies contained in the plane,
* and constructs a new plane containing a single tile with a null
* tile body.
*
* Results:
* None.
*
* Side effects:
* Modifies the database plane given.
*
* ----------------------------------------------------------------------------
*/
void
DBClearCellPlane(plane)
Plane *plane;
{
Tile *newCenterTile;
/* Free all tiles from plane, and delete all uses */
DBFreeCellPlane(plane);
/* Allocate a new central space tile with a NULL body */
newCenterTile = TiAlloc();
plane->pl_hint = newCenterTile;
TiSetBody(newCenterTile, NULL);
dbSetPlaneTile(plane, newCenterTile);
}
/*
* ----------------------------------------------------------------------------
*

View File

@ -647,6 +647,11 @@ dbcUnconnectFunc(tile, clientData)
* when a label is found which is connected to paint belonging to the
* network, it adds it to the destination definition.
*
* In addition to simply adding a label to the destination, this
* routine also checks port connections on abstract cells. Abstract
* cells can have multiple ports of the same name with implied
* connectivity between them.
*
* Results:
* Always 0.
*
@ -674,10 +679,11 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
GeoTransPointDelta(&scx->scx_trans, &lab->lab_offset, &offset);
rotate = GeoTransAngle(&scx->scx_trans, lab->lab_rotate);
/* Only add labels if they are on the search top level */
/* (NOTE: Could add hierachical labels using tpath) */
/* Do not add any labels to the destination unless they are on */
/* the top level (Note: Could alter label to be placed with */
/* tpath). */
if (scx->scx_use == csa2->csa2_topscx->scx_use)
if (csa2->csa2_topscx->scx_use == scx->scx_use)
{
DBEraseLabelsByContent(def, &r, -1, lab->lab_text);
DBPutFontLabel(def, &r, lab->lab_font, lab->lab_size, rotate, &offset,
@ -689,30 +695,72 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
CellDef *orig_def = scx->scx_use->cu_def;
Label *slab;
int lidx = lab->lab_flags & PORT_NUM_MASK;
TileTypeBitMask *connectMask;
/* Check for equivalent ports. For any found, call */
/* DBTreeSrTiles recursively on the type and area */
/* of the label. */
/* Don't recurse, just add area to the csa2_list. */
/* To avoid infinite recursion, only look at labels */
/* forward of the currently searched label, and only */
/* add the next one to the list. If there are more */
/* equivalent ports, they will be found when processing */
/* this label's area. */
for (slab = orig_def->cd_labels; slab != NULL; slab = slab->lab_next)
if ((slab->lab_flags & PORT_DIR_MASK) && (slab != lab))
for (slab = lab->lab_next; slab != NULL; slab = slab->lab_next)
if (slab->lab_flags & PORT_DIR_MASK)
if ((slab->lab_flags & PORT_NUM_MASK) == lidx)
{
SearchContext scx2 = *csa2->csa2_topscx;
TileTypeBitMask mask;
Rect newarea;
int pNum;
// Do NOT go searching on labels connected to space!
if (slab->lab_type == TT_SPACE) continue;
TTMaskSetOnlyType(&mask, slab->lab_type);
GeoTransRect(&scx->scx_trans, &slab->lab_rect, &scx2.scx_area);
// Expand search area by 1 to capture edge and point labels.
scx2.scx_area.r_xbot--;
scx2.scx_area.r_xtop++;
scx2.scx_area.r_ybot--;
scx2.scx_area.r_ytop++;
DBTreeSrTiles(&scx2, &mask, csa2->csa2_xMask,
dbcConnectFunc, (ClientData) csa2);
GeoTransRect(&scx->scx_trans, &slab->lab_rect, &newarea);
// Avoid infinite looping. If material under the label
// has already been added to the destination, then ignore.
connectMask = &csa2->csa2_connect[slab->lab_type];
pNum = DBPlane(slab->lab_type);
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
&newarea, connectMask, dbcUnconnectFunc,
(ClientData) NULL) == 1)
continue;
newarea.r_xbot--;
newarea.r_xtop++;
newarea.r_ybot--;
newarea.r_ytop++;
/* Register the area and connection mask as needing to be processed */
if (++csa2->csa2_top == csa2->csa2_size)
{
/* Reached list size limit---need to enlarge the list */
/* Double the size of the list every time we hit the limit */
conSrArea *newlist;
int i, lastsize = csa2->csa2_size;
csa2->csa2_size *= 2;
newlist = (conSrArea *)mallocMagic(csa2->csa2_size
* sizeof(conSrArea));
memcpy((void *)newlist, (void *)csa2->csa2_list,
(size_t)lastsize * sizeof(conSrArea));
freeMagic((char *)csa2->csa2_list);
csa2->csa2_list = newlist;
}
csa2->csa2_list[csa2->csa2_top].area = newarea;
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
csa2->csa2_list[csa2->csa2_top].dinfo = 0;
/* See above: Process only one equivalent port at a time */
break;
}
}
return 0;
@ -760,7 +808,6 @@ dbcConnectFunc(tile, cx)
TileType loctype = TiGetTypeExact(tile);
TileType dinfo = 0;
int pNum = cx->tc_plane;
unsigned char searchtype;
CellDef *def;
TiToRect(tile, &tileArea);
@ -809,34 +856,12 @@ dbcConnectFunc(tile, cx)
if (DBIsContact(loctype))
{
// TileType ctype;
// TileTypeBitMask *cMask, *rMask = DBResidueMask(loctype);
// TTMaskSetOnlyType(&notConnectMask, loctype);
/* Different contact types may share residues (6/18/04) */
/* Use TTMaskIntersect(), not TTMaskEqual()---types */
/* which otherwise stack may be in separate cells */
/* (12/1/05) */
// for (ctype = TT_TECHDEPBASE; ctype < DBNumUserLayers; ctype++)
// {
// if (DBIsContact(ctype))
// {
// cMask = DBResidueMask(ctype);
// if (TTMaskIntersect(rMask, cMask))
// TTMaskSetType(&notConnectMask, ctype);
// }
// }
/* The mask of contact types must include all stacked contacts */
// for (ctype = DBNumUserLayers; ctype < DBNumTypes; ctype++)
// {
// cMask = DBResidueMask(ctype);
// if (TTMaskHasType(cMask, loctype))
// TTMaskSetType(&notConnectMask, ctype);
// }
// TTMaskCom(&notConnectMask);
TTMaskZero(&notConnectMask);
TTMaskSetMask(&notConnectMask, &DBNotConnectTbl[loctype]);
@ -864,43 +889,6 @@ dbcConnectFunc(tile, cx)
&newarea, DBStdPaintTbl(loctype, pNum),
(PaintUndoInfo *) NULL);
/* Check the source def for any labels belonging to this */
/* tile area and plane, and add them to the destination. */
searchtype = TF_LABEL_ATTACH;
if (IsSplit(tile))
{
/* If the tile is split, then labels attached to the */
/* opposite point of the triangle are NOT connected. */
if (SplitSide(tile))
{
if (SplitDirection(tile))
searchtype |= TF_LABEL_ATTACH_NOT_SW;
else
searchtype |= TF_LABEL_ATTACH_NOT_NW;
}
else
{
if (SplitDirection(tile))
searchtype |= TF_LABEL_ATTACH_NOT_NE;
else
searchtype |= TF_LABEL_ATTACH_NOT_SE;
}
}
/* Note that the search must be done from the top since zero-size */
/* port labels can be on any part of the hierarchy with no paint */
/* underneath in its own cell to trigger the callback function. */
/* Copy information from top search context into new search context */
scx2 = *csa2->csa2_topscx;
scx2.scx_area = newarea;
DBTreeSrLabels(&scx2, connectMask, csa2->csa2_xMask, NULL,
searchtype, dbcConnectLabelFunc,
(ClientData) csa2);
/* Since the whole area of this tile hasn't been recorded,
* we must process its area to find any other tiles that
* connect to it. Add each of them to the list of things
@ -947,12 +935,6 @@ dbcConnectFunc(tile, cx)
newlist = (conSrArea *)mallocMagic(csa2->csa2_size * sizeof(conSrArea));
memcpy((void *)newlist, (void *)csa2->csa2_list,
(size_t)lastsize * sizeof(conSrArea));
// for (i = 0; i < lastsize; i++)
// {
// newlist[i].area = csa2->csa2_list[i].area;
// newlist[i].connectMask = csa2->csa2_list[i].connectMask;
// newlist[i].dinfo = csa2->csa2_list[i].dinfo;
// }
freeMagic((char *)csa2->csa2_list);
csa2->csa2_list = newlist;
}
@ -1023,6 +1005,7 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, destUse)
struct conSrArg2 csa2;
TileTypeBitMask *newmask;
TileType newtype;
unsigned char searchtype;
csa2.csa2_use = destUse;
csa2.csa2_xMask = xMask;
@ -1052,6 +1035,37 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, destUse)
(ClientData) &csa2);
else
DBTreeSrTiles(scx, newmask, xMask, dbcConnectFunc, (ClientData) &csa2);
/* Check the source def for any labels belonging to this */
/* tile area and plane, and add them to the destination. */
/* (This code previously in dbcConnectFunc, but the change to */
/* BPlane for cells means that the cell search cannot be run */
/* from the top within another cell search.) */
searchtype = TF_LABEL_ATTACH;
if (newtype & TT_DIAGONAL)
{
/* If the tile is split, then labels attached to the */
/* opposite point of the triangle are NOT connected. */
if (newtype & TT_SIDE)
{
if (newtype & TT_DIRECTION)
searchtype |= TF_LABEL_ATTACH_NOT_SW;
else
searchtype |= TF_LABEL_ATTACH_NOT_NW;
}
else
{
if (newtype & TT_DIRECTION)
searchtype |= TF_LABEL_ATTACH_NOT_NE;
else
searchtype |= TF_LABEL_ATTACH_NOT_SE;
}
}
DBTreeSrLabels(scx, newmask, xMask, NULL, searchtype,
dbcConnectLabelFunc, (ClientData) &csa2);
}
freeMagic((char *)csa2.csa2_list);

View File

@ -1584,17 +1584,17 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
if (!strcmp(propertyname, "GDS_FILE"))
cellDef->cd_flags |= CDVENDORGDS;
/* Also process FIXED_BBOX property, but do not keep */
/* the property, as it should be regenerated on cell */
/* output from the current scale. */
/* Also process FIXED_BBOX property, as units must match */
if (!strcmp(propertyname, "FIXED_BBOX"))
{
Rect locbbox;
if (sscanf(propertyvalue, "%d %d %d %d",
&(cellDef->cd_bbox.r_xbot),
&(cellDef->cd_bbox.r_ybot),
&(cellDef->cd_bbox.r_xtop),
&(cellDef->cd_bbox.r_ytop)) != 4)
&(locbbox.r_xbot),
&(locbbox.r_ybot),
&(locbbox.r_xtop),
&(locbbox.r_ytop)) != 4)
{
TxError("Cannot read bounding box values in %s property",
propertyname);
@ -1605,20 +1605,24 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
{
if (scalen > 1)
{
cellDef->cd_bbox.r_xbot *= scalen;
cellDef->cd_bbox.r_ybot *= scalen;
cellDef->cd_bbox.r_xtop *= scalen;
cellDef->cd_bbox.r_ytop *= scalen;
locbbox.r_xbot *= scalen;
locbbox.r_ybot *= scalen;
locbbox.r_xtop *= scalen;
locbbox.r_ytop *= scalen;
}
if (scaled > 1)
{
cellDef->cd_bbox.r_xbot /= scaled;
cellDef->cd_bbox.r_ybot /= scaled;
cellDef->cd_bbox.r_xtop /= scaled;
cellDef->cd_bbox.r_ytop /= scaled;
locbbox.r_xbot /= scaled;
locbbox.r_ybot /= scaled;
locbbox.r_xtop /= scaled;
locbbox.r_ytop /= scaled;
}
cellDef->cd_extended = cellDef->cd_bbox;
cellDef->cd_flags |= CDFIXEDBBOX;
storedvalue = (char *)mallocMagic(40);
sprintf(storedvalue, "%d %d %d %d",
locbbox.r_xbot, locbbox.r_ybot,
locbbox.r_xtop, locbbox.r_ytop);
(void) DBPropPut(cellDef, propertyname, storedvalue);
}
}
else
@ -2538,27 +2542,6 @@ DBCellWriteFile(cellDef, f)
DBPropEnum(cellDef, dbWritePropFunc, (ClientData)f);
}
/* Fixed bounding box goes into a special property in output file */
/* This is not kept internally as a property, so that it can be */
/* read and written in the correct units without regard to internal */
/* changes in scaling. */
if (cellDef->cd_flags & CDFIXEDBBOX)
{
// If there were no explicit properties, then we need to
// write the header
if (cellDef->cd_props == (ClientData)NULL)
FPRINTF(f, "<< properties >>\n");
sprintf(lstring, "string FIXED_BBOX %d %d %d %d\n",
cellDef->cd_bbox.r_xbot / reducer,
cellDef->cd_bbox.r_ybot / reducer,
cellDef->cd_bbox.r_xtop / reducer,
cellDef->cd_bbox.r_ytop / reducer);
FPRINTF(f, lstring);
}
FPRINTF(f, "<< end >>\n");
if (fflush(f) == EOF || ferror(f))

View File

@ -765,13 +765,13 @@ DBTechFinalContact()
/*
* Initialize the masks of planes on which each type appears.
* It will contain all planes (except subcell) for space,
* It will contain all planes (except router) for space,
* the home plane for each type up to DBNumTypes, and no
* planes for undefined types. Also update the mask of
* types visible on each plane.
*/
DBTypePlaneMaskTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_CELL));
DBTypePlaneMaskTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_ROUTER));
for (primaryType = 0; primaryType < DBNumTypes; primaryType++)
{
pNum = DBPlane(primaryType);

View File

@ -393,8 +393,8 @@ DBTechTypesToPlanes(mask)
TileType t;
PlaneMask planeMask, noCellMask, retMask;
/* Space tiles are present in all planes but the cell plane */
noCellMask = ~(PlaneNumToMaskBit(PL_CELL));
/* Space tiles are present in all planes but the router plane */
noCellMask = ~(PlaneNumToMaskBit(PL_ROUTER));
if (TTMaskHasType(mask, TT_SPACE)) {
retMask = PlaneNumToMaskBit(DBNumPlanes) - 1;
retMask &= noCellMask;

View File

@ -70,7 +70,7 @@ TileTypeBitMask DBTechActiveLayerBits; /* Layers marked locked in the techfile *
/* Table of default, builtin planes */
DefaultPlane dbTechDefaultPlanes[] =
{
PL_CELL, "subcell",
PL_ROUTER, "router",
PL_DRC_ERROR, "designRuleError",
PL_DRC_CHECK, "designRuleCheck",
PL_M_HINT, "mhint",
@ -584,8 +584,8 @@ DBTechFinalType()
TTMaskZero(&DBTechActiveLayerBits);
TTMaskSetMask(&DBTechActiveLayerBits, &DBActiveLayerBits);
/* Space is visible on all planes but the subcell plane */
TTMaskZero(&DBPlaneTypes[PL_CELL]);
/* Space is visible on all planes except the router */
TTMaskZero(&DBPlaneTypes[PL_ROUTER]);
for (pNum = PL_PAINTBASE; pNum < PL_MAXTYPES; pNum++)
TTMaskSetOnlyType(&DBPlaneTypes[pNum], TT_SPACE);
}

View File

@ -334,9 +334,6 @@ enum_next:
*
* NOTE:
*
* THIS IS THE PREFERRED WAY TO FIND ALL TILES IN A GIVEN AREA;
* TiSrArea IS OBSOLETE FOR ALL BUT THE SUBCELL PLANE.
*
* Results:
* 0 is returned if the search completed normally. 1 is returned
* if it aborted.
@ -786,15 +783,10 @@ enumerate:
/*
* --------------------------------------------------------------------
*
* DBFreeCellPlane --
* DBClearCellPlane --
*
* Deallocate all tiles in the cell tile plane of a given CellDef.
* Also deallocates the lists of CellTileBodies and their associated
* CellUses, but not their associated CellDefs.
* Don't free the cell tile plane itself or the four boundary tiles.
*
* Since cell tile planes contain less stuff than paint tile planes
* usually, we don't have to be as performance-conscious here.
* Removes all CellUses from a def's cell plane. Does not remove the
* cell plane itself.
*
* Results:
* None.
@ -806,54 +798,40 @@ enumerate:
*/
void
DBFreeCellPlane(plane)
Plane *plane; /* Plane whose storage is to be freed */
DBClearCellPlane(def)
CellDef *def;
{
int dbFreeCellFunc();
int dbDeleteCellUse(); /* Forward reference */
/* Don't let this search be interrupted. */
SigDisableInterrupts();
(void) TiSrArea((Tile *) NULL, plane, &TiPlaneRect,
dbFreeCellFunc, (ClientData) NULL);
/* Remove everything from the BPlane */
/* Do not use BPDelete() inside a BPEnum loop. Use DBSrCellUses */
/* to get a linked list of cell instances, then remove each one. */
DBSrCellUses(def, dbDeleteCellUse, (ClientData)NULL);
SigEnableInterrupts();
}
/*
* Filter function called via TiSrArea on behalf of DBFreeCellPlane()
* above. Deallocates each tile it is passed. If the tile has a vanilla
* body, only the tile is deallocated; otherwise, the tile body and its
* label list are both deallocated along with the tile itself.
* --------------------------------------------------------------------
*
* dbDeleteCellUse ---
*
* Callback function from DBSrCellUses, calls BPDelete to remove a
* cell use from the cell plane
*
* --------------------------------------------------------------------
*/
int
dbFreeCellFunc(tile)
Tile *tile;
int dbDeleteCellUse(CellUse *use, ClientData arg)
{
CellTileBody *body;
CellUse *use;
Rect *bbox;
for (body = (CellTileBody *) TiGetBody(tile);
body != NULL;
body = body->ctb_next)
{
use = body->ctb_use;
ASSERT(use != (CellUse *) NULL, "dbCellSrFunc");
bbox = &use->cu_bbox;
if ((BOTTOM(tile) <= bbox->r_ybot) && (RIGHT(tile) >= bbox->r_xtop))
{
/* The parent must be null before DBCellDeleteUse will work */
use->cu_parent = (CellDef *) NULL;
DBCellDeleteUse(use);
}
freeMagic((char *)body);
}
TiFree(tile);
dbInstanceUnplace(use);
return 0;
}
/*
* --------------------------------------------------------------------

View File

@ -147,12 +147,9 @@ DBFixMismatch()
* the uses.
*/
if (!(cellDef->cd_flags & CDFIXEDBBOX))
{
cellDef->cd_bbox.r_xtop = cellDef->cd_bbox.r_xbot - 1;
cellDef->cd_extended.r_xtop = cellDef->cd_extended.r_xbot - 1;
DBReComputeBbox(cellDef);
}
cellDef->cd_bbox.r_xtop = cellDef->cd_bbox.r_xbot - 1;
cellDef->cd_extended.r_xtop = cellDef->cd_extended.r_xbot - 1;
DBReComputeBbox(cellDef);
/* Now, for each parent, recheck the parent in both the
* old area of the child and the new area.

View File

@ -149,9 +149,9 @@ dbTechPaintErasePlanes()
TileType t, s;
int pNum;
/* Space tiles are special: they may appear on any plane */
DBTypePaintPlanesTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_CELL));
DBTypeErasePlanesTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_CELL));
/* Space tiles are special: they may appear on any plane except router */
DBTypePaintPlanesTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_ROUTER));
DBTypeErasePlanesTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_ROUTER));
/* Skip TT_SPACE */
for (t = 1; t < DBNumTypes; t++)

View File

@ -33,6 +33,10 @@
#include "utils/hash.h"
#endif /* _HASH_H */
#ifndef _BPLANE_H
#include "bplane/bplane.h"
#endif /* _BPLANE_H */
/* ----------------------- Tunable constants -------------------------- */
#define MAXPLANES 64 /* Maximum number of planes per cell */
@ -185,7 +189,7 @@ typedef unsigned char PaintResultType;
#define PL_MAXTYPES MAXPLANES /* Maximum number of planes per cell */
#define PL_CELL 0 /* Cell plane */
#define PL_ROUTER 0 /* Used by the router and plow modules */
#define PL_DRC_CHECK 1 /* DRC plane for CHECK tiles */
#define PL_DRC_ERROR 2 /* DRC plane for ERROR tiles */
#define PL_M_HINT 3 /* magnet hints for irouter */
@ -325,6 +329,7 @@ typedef struct celldef
#endif
char *cd_name; /* Name of cell */
struct celluse *cd_parents; /* NULL-terminated list of all uses */
BPlane *cd_cellPlane; /* Instance locations */
Plane *cd_planes[MAXPLANES]; /* Tiles */
ClientData cd_client; /* This space for rent */
int cd_timestamp; /* Unique integer identifying last
@ -461,6 +466,17 @@ typedef struct
typedef struct celluse
{
/* Binning plane element struct header---must go first! */
void *cu_bpLinks[BP_NUM_LINKS]; /* link fields */
Rect cu_bbox; /* Bounding box of this use, with
* arraying taken into account, in
* coordinates of the parent def.
*/
/* End of BPlane header */
Rect cu_extended; /* Bounding box of this use, including
* the area of rendered text labels.
*/
unsigned int cu_expandMask; /* Mask of windows in which this use
* is expanded.
*/
@ -473,13 +489,6 @@ typedef struct celluse
* or NULL for end of list.
*/
CellDef *cu_parent; /* Cell def containing this use */
Rect cu_bbox; /* Bounding box of this use, with
* arraying taken into account, in
* coordinates of the parent def.
*/
Rect cu_extended; /* Bounding box of this use, including
* the area of rendered text labels.
*/
ClientData cu_client; /* This space for rent */
} CellUse;
@ -521,20 +530,6 @@ typedef struct celluse
#define CU_DESCEND_NO_LOCK 0x0007 /* Descend unlocked subcells only */
#define CU_DESCEND_NONE 0x0009 /* Descend no subcells */
/*
* All subcells used by a cell are part of another tile plane,
* called the `cell plane'. To handle overlap, each tile in
* this plane points to a list of cell uses that appear in the
* area covered by the tile. Where there is overlap, this list
* will contain more than one tile.
*/
typedef struct celltilebody
{
CellUse *ctb_use; /* Cell used */
struct celltilebody *ctb_next; /* Next tile body on list */
} CellTileBody;
/*
* Declare tile type structure for non-manhattan geometry
*/

View File

@ -183,7 +183,7 @@ DBWredisplay(w, rootArea, clipArea)
GrLock(w, TRUE);
/* Round up the redisplay area by 1 pixel on all sides. This
* is needed because TiSrArea won't return tiles that touch
* is needed because DBSrPaintArea won't return tiles that touch
* the area without overlapping it. Without the round-up, there
* will be occasional (in fact, frequent), one-pixel wide slivers.
*/
@ -516,9 +516,9 @@ DBWredisplay(w, rootArea, clipArea)
dbwWatchTrans = crec->dbw_watchTrans;
dbwWatchDemo = ((crec->dbw_flags & DBW_WATCHDEMO) != 0);
dbwSeeTypes = ((crec->dbw_flags & DBW_SEETYPES) != 0);
(void) TiSrArea((Tile *) NULL,
(void) DBSrPaintArea((Tile *) NULL,
crec->dbw_watchDef->cd_planes[crec->dbw_watchPlane],
&dbwWatchArea, dbwTileFunc, (ClientData) NULL);
&dbwWatchArea, &DBAllTypeBits, dbwTileFunc, (ClientData) NULL);
}
/* Record information so that the highlight manager will redisplay
@ -1114,7 +1114,7 @@ dbwTileFunc(tile)
GrPutText(string, STYLE_DRAWTILE, &p, GEO_CENTER,
GR_TEXT_LARGE, FALSE, &r2, (Rect *) NULL);
#define OFFSET 12
#define XYOFFSET 12
for (i=0; i<4; i++)
{
@ -1125,25 +1125,25 @@ dbwTileFunc(tile)
case 0:
stitch = BL(tile);
p = pLL;
yoffset = OFFSET;
yoffset = XYOFFSET;
pos = GEO_NORTHEAST;
break;
case 1:
stitch = LB(tile);
p = pLL;
xoffset = OFFSET;
xoffset = XYOFFSET;
pos = GEO_NORTHEAST;
break;
case 2:
stitch = RT(tile);
p = pUR;
xoffset = -OFFSET;
xoffset = -XYOFFSET;
pos = GEO_SOUTHWEST;
break;
case 3:
stitch = TR(tile);
p = pUR;
yoffset = -OFFSET;
yoffset = -XYOFFSET;
pos = GEO_SOUTHWEST;
break;
}

View File

@ -43,9 +43,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
static Rect drcSubIntArea; /* Accumulates area of interactions. */
static CellDef *drcSubDef; /* Cell definition we're checking. */
static int drcSubRadius; /* Interaction radius. */
static CellTileBody *drcCurSub; /* Holds current tile when checking to see
* if more than one use in an area.
*/
static Rect drcSubLookArea; /* Area where we're looking for interactions */
static void (*drcSubFunc)(); /* Error function. */
static ClientData drcSubClientData;
@ -69,52 +66,10 @@ extern int DRCErrorType;
/*
* ----------------------------------------------------------------------------
*
* drcFindOtherCells --
* drcSubcellFunc --
*
* This is a search function invoked when looking around a given
* cell for interactions. If a tile is found other than drcCurSub,
* then it constitutes an interaction, and its area is included
* into the area parameter.
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* The area parameter may be modified by including the area
* of the current tile.
*
* ----------------------------------------------------------------------------
*/
int
drcFindOtherCells(tile, area)
Tile *tile; /* Tile in subcell plane. */
Rect *area; /* Area in which to include interactions. */
{
CellUse *use;
CellTileBody *ctbptr = (CellTileBody *) tile->ti_body;
/* XXX */
/* if (ctbptr == NULL) return 0; */
if (ctbptr == drcCurSub) return 0;
for (ctbptr = (CellTileBody *) TiGetBody(tile); ctbptr != NULL;
ctbptr = ctbptr->ctb_next)
{
use = ctbptr->ctb_use;
GeoInclude(&use->cu_bbox, area);
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* drcSubcellTileFunc --
*
* Called by TiSrArea when looking for interactions in
* a given area. It sees if this subcell tile participates
* Called by DBSrCellPlaneArea when looking for interactions in
* a given area. It sees if this subcell participates
* in any interactions in the area we're rechecking.
*
* Results:
@ -128,36 +83,23 @@ drcFindOtherCells(tile, area)
*/
int
drcSubcellTileFunc(tile, propagate)
Tile *tile; /* Subcell tile. */
drcSubcellFunc(subUse, propagate)
CellUse *subUse; /* Subcell instance. */
bool *propagate; /* Errors to propagate up */
{
Rect area, haloArea, intArea, subIntArea, locIntArea;
int i;
CellTileBody *ctbptr = (CellTileBody *) tile->ti_body;
CellUse *subUse;
if (ctbptr == NULL) return 0;
/* To determine interactions, find the bounding box of
* all paint and other subcells within one halo of this
* subcell tile (and also within the original area where
* subcell (and also within the original area where
* we're recomputing errors).
*/
/* XXX This is not right---the area of the cell plane tile is not */
/* the area of the subcell. */
/* TiToRect(tile, &area); */
area = subUse->cu_bbox;
for (ctbptr = (CellTileBody *) TiGetBody(tile); ctbptr != NULL;
ctbptr = ctbptr->ctb_next)
{
subUse = ctbptr->ctb_use;
area = subUse->cu_bbox;
GEO_EXPAND(&area, drcSubRadius, &haloArea);
GeoClip(&haloArea, &drcSubLookArea);
}
GEO_EXPAND(&area, drcSubRadius, &haloArea);
GeoClip(&haloArea, &drcSubLookArea);
intArea = GeoNullRect;
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
@ -171,28 +113,14 @@ drcSubcellTileFunc(tile, propagate)
/* interaction area of the parent. Ultimately this is recursive as */
/* all cells are checked and errors propagate to the top level. */
/* XXX */
for (ctbptr = (CellTileBody *) TiGetBody(tile); ctbptr != NULL;
ctbptr = ctbptr->ctb_next)
{
subUse = ctbptr->ctb_use;
subIntArea = GeoNullRect;
DBSrPaintArea((Tile *) NULL, subUse->cu_def->cd_planes[PL_DRC_ERROR],
subIntArea = GeoNullRect;
DBSrPaintArea((Tile *) NULL, subUse->cu_def->cd_planes[PL_DRC_ERROR],
&TiPlaneRect, &DBAllButSpaceBits, drcIncludeArea,
(ClientData) &subIntArea);
GeoTransRect(&(subUse->cu_transform), &subIntArea, &locIntArea);
GeoInclude(&locIntArea, &intArea);
if (!GEO_RECTNULL(&subIntArea)) *propagate = TRUE;
}
drcCurSub = ctbptr;
(void) TiSrArea((Tile *) NULL, drcSubDef->cd_planes[PL_CELL],
&haloArea, drcFindOtherCells, (ClientData) &intArea);
if (GEO_RECTNULL(&intArea)) return 0;
GEO_EXPAND(&intArea, drcSubRadius, &intArea);
GeoClip(&intArea, &haloArea);
(void) GeoInclude(&intArea, &drcSubIntArea);
GeoTransRect(&(subUse->cu_transform), &subIntArea, &locIntArea);
GeoInclude(&locIntArea, &intArea);
if (!GEO_RECTNULL(&subIntArea)) *propagate = TRUE;
return 0;
}
@ -330,8 +258,8 @@ DRCFindInteractions(def, area, radius, interaction)
drcSubIntArea = GeoNullRect;
GEO_EXPAND(area, radius, &drcSubLookArea);
propagate = FALSE;
(void) TiSrArea((Tile *) NULL, def->cd_planes[PL_CELL],
&drcSubLookArea, drcSubcellTileFunc, (ClientData)(&propagate));
(void) DBSrCellPlaneArea(def->cd_cellPlane, &drcSubLookArea,
drcSubcellFunc, (ClientData)(&propagate));
/* If there seems to be an interaction area, make a second pass
* to make sure there's more than one cell with paint in the

View File

@ -1552,8 +1552,7 @@ esMakePorts(hc, cdata)
char *name, *portname, *tptr, *aptr, *locname;
int j;
/* Done when the bottom of the hierarchy is reached */
if (HashGetNumEntries(&def->def_uses) == 0) return 0;
if (def->def_uses == NULL) return 0; /* Bottom of hierarchy */
for (conn = (Connection *)def->def_conns; conn; conn = conn->conn_next)
{
@ -1580,11 +1579,13 @@ esMakePorts(hc, cdata)
// Find the cell for the instance
portdef = NULL;
he = HashFind(&updef->def_uses, portname);
if (he != NULL)
for (use = updef->def_uses; use; use = use->use_next)
{
use = (Use *)HashGetValue(he);
portdef = use->use_def;
if (!strcmp(use->use_id, portname))
{
portdef = use->use_def;
break;
}
}
if ((aptr == NULL) || (aptr > tptr))
*tptr = '/';
@ -1659,11 +1660,13 @@ esMakePorts(hc, cdata)
// Find the cell for the instance
portdef = NULL;
he = HashFind(&updef->def_uses, portname);
if (he != NULL)
for (use = updef->def_uses; use; use = use->use_next)
{
use = (Use *)HashGetValue(he);
portdef = use->use_def;
if (!strcmp(use->use_id, portname))
{
portdef = use->use_def;
break;
}
}
if ((aptr == NULL) || (aptr > tptr))
*tptr = '/';
@ -1744,7 +1747,7 @@ esHierVisit(hc, cdata)
if (def != topdef)
{
if ((def->def_devs == NULL) && (HashGetNumEntries(&def->def_uses) == 0))
if (def->def_devs == NULL && def->def_uses == NULL)
{
if (locDoSubckt == AUTO)
{

View File

@ -2061,7 +2061,7 @@ extOutputDevices(def, transList, outFile)
if (ExtCurStyle->exts_deviceClass[t] == DEV_RSUBCKT)
{
/* nothing */
/* (Nothing) */
}
else if (hasModel) /* SPICE semiconductor resistor */
{
@ -2079,7 +2079,6 @@ extOutputDevices(def, transList, outFile)
fprintf(outFile, " \"%s\"", (subsName == NULL) ?
"None" : subsName);
}
break;
case DEV_CAP:
@ -2145,7 +2144,7 @@ extOutputDevices(def, transList, outFile)
if (ExtCurStyle->exts_deviceClass[t] == DEV_CSUBCKT)
{
/* (Nothing) */
/* (Nothing) */
}
else /* SPICE semiconductor resistor */
{

View File

@ -113,7 +113,7 @@ ExtFindInteractions(def, halo, bloatby, resultPlane)
* not including, the subtree under consideration.
*/
extInterUse = (CellUse *) NULL;
(void) extCellSrArea(&scx, extInterSubtree, (ClientData) NULL);
(void) DBCellSrArea(&scx, extInterSubtree, (ClientData) NULL);
/*
* Process parent paint if there were any subcells.
@ -123,7 +123,7 @@ ExtFindInteractions(def, halo, bloatby, resultPlane)
if (extInterUse)
{
extInterUse = (CellUse *) NULL;
(void) extCellSrArea(&scx, extInterSubtreePaint, (ClientData) def);
(void) DBCellSrArea(&scx, extInterSubtreePaint, (ClientData) def);
}
UndoEnable();
}
@ -179,7 +179,7 @@ extInterSubtree(scx)
BLOATBY(&parentScx.scx_area, extInterHalo);
parentScx.scx_trans = GeoIdentityTransform;
parentScx.scx_use = extParentUse;
(void) extCellSrArea(&parentScx, extInterSubtreeClip, (ClientData) scx);
(void) DBCellSrArea(&parentScx, extInterSubtreeClip, (ClientData) scx);
}
return (2);
}
@ -286,7 +286,7 @@ extInterSubtreeTile(tile, cxp)
else newscx.scx_area = r;
newscx.scx_trans = GeoIdentityTransform;
newscx.scx_use = extParentUse;
(void) extCellSrArea(&newscx, extInterOverlapSubtree, (ClientData) NULL);
(void) DBCellSrArea(&newscx, extInterOverlapSubtree, (ClientData) NULL);
return (0);
}
@ -394,7 +394,7 @@ extInterOverlapTile(tile, cxp)
*
* The client procedure should not modify any of the paint planes in
* the cells visited by extTreeSrTiles, because we use DBSrPaintArea
* instead of TiSrArea as our paint-tile enumeration function.
* as our paint-tile enumeration function.
*
* Results:
* 0 is returned if the search finished normally. 1 is returned
@ -442,7 +442,7 @@ extTreeSrPaintArea(scx, func, cdarg)
return (1);
/* Visit our children recursively */
return (extCellSrArea(scx, extTreeSrFunc, (ClientData) &filter));
return (DBCellSrArea(scx, extTreeSrFunc, (ClientData) &filter));
}
/*
@ -477,215 +477,6 @@ extTreeSrFunc(scx, fp)
return (1);
/* Visit our children recursively */
return (extCellSrArea(scx, extTreeSrFunc, (ClientData) fp));
return (DBCellSrArea(scx, extTreeSrFunc, (ClientData) fp));
}
/*
*-----------------------------------------------------------------------------
*
* extCellSrArea --
*
* Apply the supplied procedure to each of the cellUses found in the
* given area in the subcell plane of the child def of the supplied
* search context.
*
* The procedure is applied to each array element in each cell use that
* overlaps the clipping rectangle. The scx_x and scx_y parts of
* the SearchContext passed to the filter function correspond to the
* array element being visited. The same CellUse is, of course, passed
* as scx_use for all elements of the array.
*
* The array elements are visited by varying the X coordinate fastest.
*
* The procedure should be of the following form:
* int
* func(scx, cdarg)
* SearchContext *scx;
* ClientData cdarg;
* {
* }
*
* Func normally returns 0. If it returns 1 then the search is
* aborted. If it returns 2, then any remaining elements in the
* current array are skipped.
*
* Results:
* 0 is returned if the search terminated normally. 1 is
* returned if it was aborted.
*
* Side effects:
* Whatever side effects are brought about by applying the
* procedure supplied.
*
*-----------------------------------------------------------------------------
*/
int
extCellSrArea(scx, func, cdarg)
SearchContext *scx;
/* Pointer to search context specifying a cell use to
* search, an area in the coordinates of the cell's
* def, and a transform back to "root" coordinates.
* The area may have zero size.
*/
int (*func)(); /* Function to apply at every tile found */
ClientData cdarg; /* Argument to pass to function */
{
int xlo, xhi, ylo, yhi, xbase, ybase, xsep, ysep, clientResult;
int srchBot, srchRight;
Plane *plane = scx->scx_use->cu_def->cd_planes[PL_CELL];
Tile *tp, *tpnew;
Rect *rect, *bbox;
CellUse *use;
SearchContext newScx;
CellTileBody *body;
Transform t, tinv;
TreeFilter filter;
Rect expanded;
Point start;
filter.tf_func = func;
filter.tf_arg = cdarg;
if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, NULL))
return 0;
/*
* In order to make this work with zero-size areas, we first expand
* the area by before searching the tile plane. extCellSrFunc will
* check carefully to throw out things that don't overlap the original
* area. The expansion is tricky because we mustn't expand infinities.
*/
expanded = scx->scx_area;
if (expanded.r_xbot > TiPlaneRect.r_xbot) expanded.r_xbot -= 1;
if (expanded.r_ybot > TiPlaneRect.r_ybot) expanded.r_ybot -= 1;
if (expanded.r_xtop < TiPlaneRect.r_xtop) expanded.r_xtop += 1;
if (expanded.r_ytop < TiPlaneRect.r_ytop) expanded.r_ytop += 1;
rect = &expanded;
/* Start along the top of the LHS of the search area */
start.p_x = rect->r_xbot;
start.p_y = rect->r_ytop - 1;
tp = plane->pl_hint;
GOTOPOINT(tp, &start);
/* Each iteration visits another tile on the LHS of the search area */
while (TOP(tp) > rect->r_ybot)
{
/* Each iteration enumerates another tile */
enumerate:
plane->pl_hint = tp;
if (SigInterruptPending)
return (1);
/*
* Since subcells are allowed to overlap, a single tile body may
* refer to many subcells and a single subcell may be referred to
* by many tile bodies. To insure that each CellUse is enumerated
* exactly once, the procedure given to DBCellSrArea is only applied
* to a CellUse when its lower right corner is contained in the
* tile to dbCellSrFunc (or otherwise at the last tile encountered
* in the event the lower right corner of the CellUse is outside the
* search rectangle).
*/
srchBot = scx->scx_area.r_ybot;
srchRight = scx->scx_area.r_xtop;
for (body = (CellTileBody *) TiGetBody(tp);
body != NULL;
body = body->ctb_next)
{
use = newScx.scx_use = body->ctb_use;
ASSERT(use != (CellUse *) NULL, "dbCellSrFunc");
/*
* The check below is to ensure that we only enumerate each
* cell once, even though it appears in many different tiles
* in the subcell plane.
*/
bbox = &use->cu_bbox;
if ( (BOTTOM(tp) <= bbox->r_ybot ||
(BOTTOM(tp) <= srchBot && bbox->r_ybot < srchBot))
&& (RIGHT(tp) >= bbox->r_xtop ||
(RIGHT(tp) >= srchRight && bbox->r_xtop >= srchRight)))
{
/*
* Make sure that this cell really does overlap the
* search area (it could be just touching because of
* the expand-by-one in DBCellSrArea).
*/
if (!GEO_OVERLAP(&scx->scx_area, bbox)) continue;
/* If not an array element, it's much simpler */
if (use->cu_xlo == use->cu_xhi && use->cu_ylo == use->cu_yhi)
{
newScx.scx_x = use->cu_xlo, newScx.scx_y = use->cu_yhi;
if (SigInterruptPending) return 1;
GEOINVERTTRANS(&use->cu_transform, &tinv);
GEOTRANSTRANS(&use->cu_transform, &scx->scx_trans,
&newScx.scx_trans);
GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area);
if ((*func)(&newScx, filter.tf_arg) == 1)
return 1;
continue;
}
/*
* More than a single array element;
* check to see which ones overlap our search area.
*/
DBArrayOverlap(use, &scx->scx_area, &xlo, &xhi, &ylo, &yhi);
xsep = (use->cu_xlo > use->cu_xhi)
? -use->cu_xsep : use->cu_xsep;
ysep = (use->cu_ylo > use->cu_yhi)
? -use->cu_ysep : use->cu_ysep;
for (newScx.scx_y = ylo; newScx.scx_y<=yhi; newScx.scx_y++)
for (newScx.scx_x = xlo; newScx.scx_x<=xhi; newScx.scx_x++)
{
if (SigInterruptPending) return 1;
xbase = xsep * (newScx.scx_x - use->cu_xlo);
ybase = ysep * (newScx.scx_y - use->cu_ylo);
GEOTRANSTRANSLATE(xbase, ybase, &use->cu_transform, &t);
GEOINVERTTRANS(&t, &tinv);
GEOTRANSTRANS(&t, &scx->scx_trans, &newScx.scx_trans);
GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area);
clientResult = (*func)(&newScx, filter.tf_arg);
if (clientResult == 2) goto skipArray;
else if (clientResult == 1) return 1;
}
}
skipArray: continue;
}
tpnew = TR(tp);
if (LEFT(tpnew) < rect->r_xtop)
{
while (BOTTOM(tpnew) >= rect->r_ytop) tpnew = LB(tpnew);
if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot)
{
tp = tpnew;
goto enumerate;
}
}
/* Each iteration returns one tile further to the left */
while (LEFT(tp) > rect->r_xbot)
{
if (BOTTOM(tp) <= rect->r_ybot)
return (0);
tpnew = LB(tp);
tp = BL(tp);
if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot)
{
tp = tpnew;
goto enumerate;
}
}
/* At left edge -- walk down to next tile along the left edge */
for (tp = LB(tp); RIGHT(tp) <= rect->r_xbot; tp = TR(tp))
/* Nothing */;
}
return (0);
}

View File

@ -475,7 +475,7 @@ extContainsGeometry(def, allButUse, area)
bool extContainsCellFunc();
int pNum;
if (TiSrArea((Tile *) NULL, def->cd_planes[PL_CELL], area,
if (DBSrCellPlaneArea(def->cd_cellPlane, area,
extContainsCellFunc, (ClientData) allButUse))
return (TRUE);
@ -489,17 +489,11 @@ extContainsGeometry(def, allButUse, area)
}
bool
extContainsCellFunc(tile, allButUse)
Tile *tile;
extContainsCellFunc(use, allButUse)
CellUse *use;
CellUse *allButUse;
{
CellTileBody *ctb;
for (ctb = (CellTileBody *) TiGetBody(tile); ctb; ctb = ctb->ctb_next)
if (ctb->ctb_use != allButUse)
return (TRUE);
return (FALSE);
return (use != allButUse) ? TRUE : FALSE;
}
int

View File

@ -31,6 +31,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "tcltk/tclmagic.h"
#include "utils/geometry.h"
#include "utils/geofast.h"
#include "tiles/tile.h"
@ -175,10 +176,10 @@ extSubtree(parentUse, reg, f)
* halo has been set above to reflect the maximum distance for
* sidewall coupling capacitance).
*/
b = &def->cd_bbox;
/* Monitor progress, for large designs */
/* Monitor progress, for large designs, and allow display refresh at intervals */
totcuts = (b->r_ytop - b->r_ybot + ExtCurStyle->exts_stepSize - 1)
/ ExtCurStyle->exts_stepSize;
totcuts *= ((b->r_xtop - b->r_xbot + ExtCurStyle->exts_stepSize - 1)
@ -233,7 +234,6 @@ extSubtree(parentUse, reg, f)
/* even if there were no other interactions found. */
SearchContext scx;
GEOCLIP(&ha.ha_clipArea, &r);
scx.scx_trans = GeoIdentityTransform;
scx.scx_area = r;
scx.scx_use = ha.ha_parentUse;
@ -243,8 +243,8 @@ extSubtree(parentUse, reg, f)
cuts++;
pdone = 100.0 * ((float)cuts / (float)totcuts);
if ((((pdone - plast) > 5.0) || (cuts == totcuts)) && (cuts > 1)) {
TxPrintf("Completed %d%%\n", (int)(pdone + 0.5));
plast = pdone;
TxPrintf("Completed %d%%\n", (int)(pdone + 0.5));
plast = pdone;
TxFlushOut();
#ifdef MAGIC_WRAPPER

View File

@ -2854,14 +2854,14 @@ zinit:
}
/* If global variable "doConvert" is TRUE, then we convert from */
/* microns to lambda and microns^2 to lambda^2, based on the */
/* current value of DBLambda and output scale. */
/* microns to lambda and microns^2 to lambda^2. */
if (doConvert)
{
/* Convert from micron units in the file to the current */
/* physical scalefactor as determined by the default CIF */
/* output scale. */
/* Use current CIF output scale for determining the scale */
/* factor between micron units in the extract section and */
/* lambda units of the database (conversion from lambda to */
/* internal units is done separately). */
float dscale = CIFGetOutputScale(1000);

View File

@ -577,7 +577,7 @@ DefReadLocation(use, f, oscale, tptr)
float oscale;
Transform *tptr;
{
Rect *r, tr;
Rect *r, tr, rect;
int keyword;
char *token;
float x, y;
@ -611,7 +611,25 @@ DefReadLocation(use, f, oscale, tptr)
/* restore the lower-left corner position. */
if (use)
{
r = &use->cu_def->cd_bbox;
/* Abstract views with fixed bounding boxes use the FIXED_BBOX property */
if (use->cu_def->cd_flags & CDFIXEDBBOX)
{
char *propval;
bool found;
propval = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
if (found)
{
if (sscanf(propval, "%d %d %d %d", &rect.r_xbot, &rect.r_ybot,
&rect.r_xtop, &rect.r_ytop) == 4)
r = &rect;
}
}
}
else
r = &GeoNullRect;
@ -805,9 +823,9 @@ DefReadPins(f, rootDef, sname, oscale, total)
currect = LefReadRect(f, curlayer, oscale);
if (pending)
{
flags = PORT_DIR_MASK;
/* If layer was unknown, set to space and force */
/* non-sticky. */
flags = PORT_DIR_MASK;
if (curlayer < 0)
curlayer = TT_SPACE;
else
@ -828,9 +846,9 @@ DefReadPins(f, rootDef, sname, oscale, total)
pending = TRUE;
else
{
flags = PORT_DIR_MASK;
/* If layer was unknown, set to space and force */
/* non-sticky. */
flags = PORT_DIR_MASK;
if (curlayer < 0)
curlayer = TT_SPACE;
else

View File

@ -1350,7 +1350,7 @@ LefReadMacro(f, mname, oscale, importForeign)
CellDef *lefMacro;
HashEntry *he;
char *token, tsave[128];
char *token, tsave[128], *propval;
int keyword, pinNum;
float x, y;
bool has_size, is_imported = FALSE;
@ -1544,13 +1544,16 @@ origin_error:
if (is_imported)
{
/* Redefine cell bounding box to match the LEF macro */
/* Leave "extended" to mark the original bounding box */
/* Define the FIXED_BBOX property to match the LEF macro */
if (has_size)
{
lefMacro->cd_bbox = lefBBox;
lefMacro->cd_flags |= CDFIXEDBBOX;
propval = (char *)mallocMagic(40);
sprintf(propval, "%d %d %d %d",
lefBBox.r_xbot, lefBBox.r_ybot,
lefBBox.r_xtop, lefBBox.r_ytop);
DBPropPut(lefMacro, "FIXED_BBOX", propval);
}
}
else
@ -1564,15 +1567,21 @@ origin_error:
}
else
{
char *propstr = (char *)mallocMagic(64);
int reducer = DBCellFindScale(lefMacro);
lefMacro->cd_bbox = lefBBox;
lefMacro->cd_extended = lefBBox;
}
/* Fix the bounding box and do not allow edits */
lefMacro->cd_flags |= /* CDNOEDIT | */ CDFIXEDBBOX;
/* Set the placement bounding box property to the current bounding box */
lefMacro->cd_flags |= CDFIXEDBBOX;
propval = (char *)mallocMagic(40);
sprintf(propval, "%d %d %d %d",
lefMacro->cd_bbox.r_xbot,
lefMacro->cd_bbox.r_ybot,
lefMacro->cd_bbox.r_xtop,
lefMacro->cd_bbox.r_ytop);
DBPropPut(lefMacro, "FIXED_BBOX", propval);
DRCCheckThis(lefMacro, TT_CHECKPAINT, &lefMacro->cd_bbox);
}

View File

@ -8,15 +8,25 @@ SRCS = magicTop.c
include ${MAGICDIR}/defs.mak
EXTRA_LIBS = ${MAGICDIR}/cmwind/libcmwind.o ${MAGICDIR}/commands/libcommands.o \
${MAGICDIR}/database/libdatabase.o ${MAGICDIR}/dbwind/libdbwind.o \
${MAGICDIR}/drc/libdrc.o ${MAGICDIR}/debug/libdebug.o \
${MAGICDIR}/extract/libextract.o ${MAGICDIR}/graphics/libgraphics.o \
${MAGICDIR}/select/libselect.o ${MAGICDIR}/textio/libtextio.o \
${MAGICDIR}/tiles/libtiles.o ${MAGICDIR}/windows/libwindows.o \
${MAGICDIR}/wiring/libwiring.o ${MAGICDIR}/resis/libresis.o \
${MAGICDIR}/sim/libsim.o ${MAGICDIR}/netmenu/libnetmenu.o \
${MAGICDIR}/plow/libplow.o ${MAGICDIR}/utils/libutils.o \
EXTRA_LIBS = ${MAGICDIR}/bplane/libbplane.o \
${MAGICDIR}/cmwind/libcmwind.o \
${MAGICDIR}/commands/libcommands.o \
${MAGICDIR}/database/libdatabase.o \
${MAGICDIR}/dbwind/libdbwind.o \
${MAGICDIR}/drc/libdrc.o \
${MAGICDIR}/debug/libdebug.o \
${MAGICDIR}/extract/libextract.o \
${MAGICDIR}/graphics/libgraphics.o \
${MAGICDIR}/select/libselect.o \
${MAGICDIR}/textio/libtextio.o \
${MAGICDIR}/tiles/libtiles.o \
${MAGICDIR}/windows/libwindows.o \
${MAGICDIR}/wiring/libwiring.o \
${MAGICDIR}/resis/libresis.o \
${MAGICDIR}/sim/libsim.o \
${MAGICDIR}/netmenu/libnetmenu.o \
${MAGICDIR}/plow/libplow.o \
${MAGICDIR}/utils/libutils.o \
${MAIN_EXTRA_LIBS}
BITMAPS = up.xbm down.xbm left.xbm right.xbm zoom.xbm lock.xbm

View File

@ -739,7 +739,7 @@ plowPropagateRect(def, userRect, lc, changedArea)
lc, plowInitialPaint, (ClientData) plowRect.r_xtop);
/* Find any subcells crossed by the plow */
(void) TiSrArea((Tile *) NULL, plowYankDef->cd_planes[PL_CELL],
(void) DBSrCellPlaneArea(plowYankDef->cd_cellPlane,
&cellPlowRect, plowInitialCell, (ClientData) &cellPlowRect);
/* While edges remain, process them */
@ -1120,7 +1120,7 @@ plowFindSelCell(yankUse, editUse)
return (0);
edge.e_flags = 0;
edge.e_pNum = PL_CELL;
edge.e_pNum = PL_ROUTER;
edge.e_use = yankUse;
edge.e_ytop = yankUse->cu_bbox.r_ytop;
edge.e_ybot = yankUse->cu_bbox.r_ybot;
@ -1443,45 +1443,39 @@ plowInitialPaint(edge, xnew)
*/
int
plowInitialCell(cellTile, plowRect)
Tile *cellTile;
plowInitialCell(use, plowRect)
CellUse *use;
Rect *plowRect;
{
CellTileBody *ctb;
CellUse *use;
int xmove;
Edge edge;
edge.e_pNum = PL_CELL;
for (ctb = (CellTileBody *) TiGetBody(cellTile); ctb; ctb = ctb->ctb_next)
if (use->cu_bbox.r_xbot < plowRect->r_xbot)
{
use = ctb->ctb_use;
if (use->cu_bbox.r_xbot < plowRect->r_xbot)
{
if (use->cu_bbox.r_xtop >= plowRect->r_xtop)
continue;
if (use->cu_bbox.r_xtop >= plowRect->r_xtop)
return 0;
/* Dragging this cell by its front edge */
xmove = plowRect->r_xtop - use->cu_bbox.r_xtop;
}
else
{
/* Pushing this cell by its back edge */
xmove = plowRect->r_xtop - use->cu_bbox.r_xbot;
}
edge.e_use = use;
edge.e_flags = E_ISINITIAL;
edge.e_ytop = use->cu_bbox.r_ytop;
edge.e_ybot = use->cu_bbox.r_ybot;
edge.e_x = use->cu_bbox.r_xtop;
edge.e_newx = use->cu_bbox.r_xtop + xmove;
edge.e_ltype = PLOWTYPE_CELL;
edge.e_rtype = PLOWTYPE_CELL;
(void) plowQueueAdd(&edge);
/* Dragging this cell by its front edge */
xmove = plowRect->r_xtop - use->cu_bbox.r_xtop;
}
else
{
/* Pushing this cell by its back edge */
xmove = plowRect->r_xtop - use->cu_bbox.r_xbot;
}
return (0);
edge.e_pNum = PL_ROUTER;
edge.e_use = use;
edge.e_flags = E_ISINITIAL;
edge.e_ytop = use->cu_bbox.r_ytop;
edge.e_ybot = use->cu_bbox.r_ybot;
edge.e_x = use->cu_bbox.r_xtop;
edge.e_newx = use->cu_bbox.r_xtop + xmove;
edge.e_ltype = PLOWTYPE_CELL;
edge.e_rtype = PLOWTYPE_CELL;
(void) plowQueueAdd(&edge);
return 0;
}
/*

View File

@ -856,8 +856,7 @@ void
prFindCells(edge)
Edge *edge; /* Edge being moved */
{
Plane *cellPlane = plowYankDef->cd_planes[PL_CELL];
Tile *cellTile = cellPlane->pl_hint;
BPlane *cellPlane = plowYankDef->cd_cellPlane;
struct applyRule ar;
Rect searchArea;
@ -867,18 +866,7 @@ prFindCells(edge)
searchArea.r_xtop = edge->e_newx + DRCTechHalo;
ar.ar_moving = edge;
/*
* Don't bother doing anything if there is a single space tile
* beneath the plow.
*/
if (TiGetBody(cellTile) == (ClientData) NULL
&& LEFT(cellTile) <= searchArea.r_xbot
&& BOTTOM(cellTile) <= searchArea.r_ybot
&& RIGHT(cellTile) >= searchArea.r_xtop
&& TOP(cellTile) >= searchArea.r_ytop)
return;
(void) TiSrArea(cellTile, cellPlane, &searchArea, plowFoundCell,
(void) DBSrCellPlaneArea(cellPlane, &searchArea, plowFoundCell,
(ClientData) &ar);
}
@ -947,7 +935,7 @@ prCell(edge)
cellArea.r_xtop = edge->e_newx + DRCTechHalo;
cellArea.r_ybot = edge->e_ybot - DRCTechHalo;
cellArea.r_ytop = edge->e_ytop + DRCTechHalo;
(void) TiSrArea((Tile *) NULL, plowYankDef->cd_planes[edge->e_pNum],
(void) DBSrCellPlaneArea(plowYankDef->cd_cellPlane,
&cellArea, plowFoundCell,
(ClientData) &ar);
}
@ -1068,52 +1056,47 @@ plowCellPushPaint(impactedEdge, ar)
*/
int
plowFoundCell(cellTile, ar)
Tile *cellTile;
plowFoundCell(use, ar)
CellUse *use;
struct applyRule *ar;
{
Edge *movingEdge = ar->ar_moving;
CellTileBody *ctb;
int xmove, xsep;
CellUse *use;
Edge edge;
edge.e_pNum = PL_CELL;
for (ctb = (CellTileBody *) TiGetBody(cellTile); ctb; ctb = ctb->ctb_next)
{
use = ctb->ctb_use;
if (use->cu_bbox.r_xbot <= movingEdge->e_x)
{
/*
* If dragging the cell, move it by as much as this edge.
*/
xmove = movingEdge->e_newx - movingEdge->e_x;
}
else
{
/*
* If pushing the cell, keep it DRCTechHalo in front of the edge
* unless it was already closer.
*/
xsep = use->cu_bbox.r_xbot - movingEdge->e_x;
if (xsep > DRCTechHalo) xsep = DRCTechHalo;
xmove = movingEdge->e_newx + xsep - use->cu_bbox.r_xbot;
}
edge.e_pNum = PL_ROUTER;
/* Only queue the edge if the cell has not moved far enough */
if ((use->cu_client != (ClientData)CLIENTDEFAULT) &&
if (use->cu_bbox.r_xbot <= movingEdge->e_x)
{
/*
* If dragging the cell, move it by as much as this edge.
*/
xmove = movingEdge->e_newx - movingEdge->e_x;
}
else
{
/*
* If pushing the cell, keep it DRCTechHalo in front of the edge
* unless it was already closer.
*/
xsep = use->cu_bbox.r_xbot - movingEdge->e_x;
if (xsep > DRCTechHalo) xsep = DRCTechHalo;
xmove = movingEdge->e_newx + xsep - use->cu_bbox.r_xbot;
}
/* Only queue the edge if the cell has not moved far enough */
if ((use->cu_client != (ClientData)CLIENTDEFAULT) &&
((int)(use->cu_client) < xmove))
{
edge.e_use = use;
edge.e_flags = 0;
edge.e_ytop = use->cu_bbox.r_ytop;
edge.e_ybot = use->cu_bbox.r_ybot;
edge.e_x = use->cu_bbox.r_xtop;
edge.e_newx = use->cu_bbox.r_xtop + xmove;
edge.e_ltype = PLOWTYPE_CELL;
edge.e_rtype = PLOWTYPE_CELL;
(void) (*plowPropagateProcPtr)(&edge);
}
{
edge.e_use = use;
edge.e_flags = 0;
edge.e_ytop = use->cu_bbox.r_ytop;
edge.e_ybot = use->cu_bbox.r_ybot;
edge.e_x = use->cu_bbox.r_xtop;
edge.e_newx = use->cu_bbox.r_xtop + xmove;
edge.e_ltype = PLOWTYPE_CELL;
edge.e_rtype = PLOWTYPE_CELL;
(void) (*plowPropagateProcPtr)(&edge);
}
return (0);

View File

@ -249,7 +249,7 @@ plowYankUpdateCell(yankChildUse)
/* Restore the delta since DBPlaceCell re-initializes it to 0 */
yankChildUse->cu_client = savedelta;
/* Return 1 so TiSrArea doesn't bomb */
/* Return 1 so DBSrCellPlaneArea doesn't bomb */
return (1);
}
}

View File

@ -226,16 +226,18 @@ RtrDecompose(routeUse, area, netList)
* Clear the valid flags for horizontal edges for all space tiles in
* the error plane of the result cell.
*/
(void) TiSrArea((Tile *) NULL, cdTo->cd_planes[PL_DRC_ERROR], &RouteArea,
rtrSrClear, (ClientData) &RouteArea);
(void) DBSrPaintArea((Tile *) NULL, cdTo->cd_planes[PL_DRC_ERROR],
&RouteArea, &DBAllTypeBits, rtrSrClear,
(ClientData) &RouteArea);
/*
* Enumerate all tiles in the given area.
* If a tile is not a space tile, then perform the corner
* extension algorithm.
*/
(void) TiSrArea((Tile *) NULL, cdTo->cd_planes[PL_DRC_CHECK], &RouteArea,
rtrSrFunc, (ClientData) (cdTo->cd_planes[PL_DRC_ERROR]));
(void) DBSrPaintArea((Tile *) NULL, cdTo->cd_planes[PL_DRC_CHECK],
&RouteArea, &DBAllTypeBits, rtrSrFunc,
(ClientData) (cdTo->cd_planes[PL_DRC_ERROR]));
/* Allow the modified area to be redisplayed if the cell is visible */
DBReComputeBbox(cdTo);
@ -344,8 +346,8 @@ rtrSrCells(scx, targetDef)
*
* Round a rectangle out to the nearest grid line, and
* extend to a point halfway to the next grid point (if
* roundUp is TRUE) or back half a grid from the nearest
* grid line (if roundUp is FALSE).
* doRoundUp is TRUE) or back half a grid from the nearest
* grid line (if doRoundUp is FALSE).
*
* The halfway points are chosen to be RtrGridSpacing/2
* down or to the left from grid lines. Before rounding,
@ -362,16 +364,16 @@ rtrSrCells(scx, targetDef)
*/
void
rtrRoundRect(r, sepUp, sepDown, roundUp)
rtrRoundRect(r, sepUp, sepDown, doRoundUp)
Rect *r;
int sepUp, sepDown;
bool roundUp;
bool doRoundUp;
{
int halfGrid = RtrGridSpacing / 2;
r->r_xbot = RTR_GRIDDOWN(r->r_xbot - sepDown, RtrOrigin.p_x);
r->r_ybot = RTR_GRIDDOWN(r->r_ybot - sepDown, RtrOrigin.p_y);
if (roundUp)
if (doRoundUp)
{
r->r_xbot -= halfGrid;
r->r_ybot -= halfGrid;
@ -390,7 +392,7 @@ rtrRoundRect(r, sepUp, sepDown, roundUp)
*/
r->r_xtop = RTR_GRIDUP(r->r_xtop + sepUp, RtrOrigin.p_x);
r->r_ytop = RTR_GRIDUP(r->r_ytop + sepUp, RtrOrigin.p_y);
if (roundUp)
if (doRoundUp)
{
r->r_xtop += RtrGridSpacing - halfGrid;
r->r_ytop += RtrGridSpacing - halfGrid;
@ -503,7 +505,7 @@ rtrSplitToArea(area, def)
*
* rtrSrClear --
*
* TiSrArea function for each tile in the error plane of the __CHANNEL__
* DBSrPaintArea function for each tile in the error plane of the __CHANNEL__
* def. Sets the flags to 0 in internal space tiles, marking horizontal
* invalid. Mark edges at the boundary of the routing region as valid.
*
@ -561,12 +563,12 @@ rtrSrClear(tile, area)
*
* rtrSrFunc --
*
* Search function called from TiSrArea for each tile in the cell tile
* Search function called from DBSrPaintArea for each tile in the
* plane. Do this search in the OLD TILE PLANE. Process corners
* bordering space tiles.
*
* Results:
* Returns a 0 to TiSrArea so it won't abort the search.
* Returns a 0 to DBSrPaintArea so it won't abort the search.
*
* Side effects:
* Modifies the result plane to reflect the channel structure.

View File

@ -127,8 +127,8 @@ Route(routeUse, routeArea)
* but don't do anything else.
*/
RtrChannelList = (GCRChannel *) NULL;
(void) TiSrArea((Tile *) NULL, RtrChannelPlane, &RouteArea,
rtrMakeChannel, (ClientData) &RouteArea);
(void) DBSrPaintArea((Tile *) NULL, RtrChannelPlane, &RouteArea,
&DBAllTypeBits, rtrMakeChannel, (ClientData) &RouteArea);
if (!SigInterruptPending)
{
errs = GARoute(RtrChannelList, routeUse, &netList);
@ -149,7 +149,7 @@ done:
*
* rtrMakeChannel --
*
* Function passed to TiSrArea to enumerate space tiles and convert them
* Function passed to DBSrPaintArea to enumerate space tiles and convert them
* to channels. Clip all tiles against the box 'clipBox'. Don't set
* hazards for this channel; that has to happen after stem assignment.
*

View File

@ -228,14 +228,14 @@ rtrSideProcess(use, side, area, trans)
{
/* EAST (easy case since we don't have to transform) */
case GEO_EAST:
rtrSideTransPlane = use->cu_def->cd_planes[PL_CELL];
rtrSideTransPlane = use->cu_def->cd_planes[PL_ROUTER];
break;
/* Other cases use the transformed plane */
case GEO_SOUTH:
case GEO_NORTH:
case GEO_WEST:
rtrSideTransPlane = rtrSideTransDef->cd_planes[PL_CELL];
rtrSideTransPlane = rtrSideTransDef->cd_planes[PL_ROUTER];
scx.scx_area = *area;
scx.scx_use = use;
scx.scx_trans = *trans;
@ -245,19 +245,19 @@ rtrSideProcess(use, side, area, trans)
}
/* Initialize all client fields to NULL in the cell tile plane */
(void) TiSrArea((Tile *) NULL, rtrSideTransPlane, &rtrSideArea,
rtrSideInitClient, (ClientData) INFINITY);
(void) DBSrPaintArea((Tile *) NULL, rtrSideTransPlane, &rtrSideArea,
&DBAllTypeBits, rtrSideInitClient, (ClientData) INFINITY);
/* Process all Sides for this direction */
retval = TiSrArea((Tile *) NULL, rtrSideTransPlane, &rtrSideArea,
rtrEnumSidesFunc, (ClientData) NULL);
retval = DBSrPaintArea((Tile *) NULL, rtrSideTransPlane, &rtrSideArea,
&DBAllTypeBits, rtrEnumSidesFunc, (ClientData) NULL);
/* Clean up; be absolutely sure to reset client info */
if (side == GEO_EAST)
{
SigDisableInterrupts();
(void) TiSrArea((Tile *) NULL, rtrSideTransPlane, area,
rtrSideInitClient, (ClientData) CLIENTDEFAULT);
(void) DBSrPaintArea((Tile *) NULL, rtrSideTransPlane, area,
&DBAllTypeBits, rtrSideInitClient, (ClientData) CLIENTDEFAULT);
SigEnableInterrupts();
}

View File

@ -307,11 +307,34 @@ selRedisplayCellFunc(scx, window)
SearchContext *scx; /* Describes cell found. */
MagWindow *window; /* Window in which to redisplay. */
{
Rect tmp, screen;
Rect tmp, screen, bbox;
Point p;
char idName[100];
GeoTransRect(&scx->scx_trans, &scx->scx_use->cu_def->cd_bbox, &tmp);
/* Selections of cells with a fixed bounding box flag show the outline */
/* of the fixed bounding box, not the actual bounding box. */
if (scx->scx_use->cu_def->cd_flags & CDFIXEDBBOX)
{
bool found;
char *propval;
propval = (char *)DBPropGet(scx->scx_use->cu_def, "FIXED_BBOX", &found);
if (found)
{
if (sscanf(propval, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
&bbox.r_xtop, &bbox.r_ytop) == 4)
GeoTransRect(&scx->scx_trans, &bbox, &tmp);
else
found = FALSE;
}
if (!found)
GeoTransRect(&scx->scx_trans, &scx->scx_use->cu_def->cd_bbox, &tmp);
}
else
{
GeoTransRect(&scx->scx_trans, &scx->scx_use->cu_def->cd_bbox, &tmp);
}
if (!DBSrPaintArea((Tile *) NULL, selRedisplayPlane, &tmp,
&DBAllButSpaceBits, selAlways1, (ClientData) NULL))
return 0;

View File

@ -676,7 +676,7 @@ SimSrConnect(def, startArea, mask, connect, bounds, func, clientData)
*
* The client procedure should not modify any of the paint planes in
* the cells visited by SimTreeSrTiles, because we use DBSrPaintArea
* instead of TiSrArea as our paint-tile enumeration function.
* as our paint-tile enumeration function.
*
* Results:
* 0 is returned if the search finished normally. 1 is returned

View File

@ -4,7 +4,7 @@
MODULE = tiles
MAGICDIR = ..
SRCS = tile.c search.c search2.c
SRCS = tile.c search.c
include ${MAGICDIR}/defs.mak
include ${MAGICDIR}/rules.mak

View File

@ -1,234 +0,0 @@
/*
* search2.c --
*
* Area searching.
*
* *********************************************************************
* * 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/tiles/search2.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include "utils/magic.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
#include "utils/signals.h"
/* -------------------- Local function headers ------------------------ */
int tiSrAreaEnum();
/*
* --------------------------------------------------------------------
*
* TiSrArea --
*
* Find all tiles contained in or incident upon a given area.
* Applies the given procedure to all tiles found. The procedure
* should be of the following form:
*
* int
* func(tile, cdata)
* Tile *tile;
* ClientData cdata;
* {
* }
*
* Func normally should return 0. If it returns 1 then the search
* will be aborted.
*
* THIS PROCEDURE IS OBSOLETE EXCEPT FOR THE SUBCELL PLANE. USE
* DBSrPaintArea() IF YOU WANT TO SEARCH FOR PAINT TILES.
*
* Results:
* 0 is returned if the search completed normally. 1 is returned
* if it aborted.
*
* Side effects:
* Whatever side effects result from application of the
* supplied procedure.
*
* NOTE:
* The procedure called is free to do anything it wishes to tiles
* which have already been visited in the area search, but it must
* not affect anything about tiles not visited other than possibly
* corner stitches to tiles already visited.
*
* *************************************************************************
* *************************************************************************
* **** ****
* **** WARNING ****
* **** ****
* **** This code is INCREDIBLY sensitive to modification! ****
* **** Change it only with the utmost caution, or you'll ****
* **** be verrry sorry! ****
* **** ****
* *************************************************************************
* *************************************************************************
*
* --------------------------------------------------------------------
*/
int
TiSrArea(hintTile, plane, rect, func, arg)
Tile *hintTile; /* Tile at which to begin search, if not NULL.
* If this is NULL, use the hint tile supplied
* with plane.
*/
Plane *plane; /* Plane in which tiles lie. This is used to
* provide a hint tile in case hintTile == NULL.
* The hint tile in the plane is updated to be
* the last tile visited in the area enumeration.
*/
Rect *rect;/* Area to search */
int (*func)(); /* Function to apply at each tile */
ClientData arg; /* Additional argument to pass to (*func)() */
{
Point here;
Tile *tp, *enumTR, *enumTile;
int enumRight, enumBottom;
/*
* We will scan from top to bottom along the left hand edge
* of the search area, searching for tiles. Each tile we
* find in this search will be enumerated.
*/
here.p_x = rect->r_xbot;
here.p_y = rect->r_ytop - 1;
enumTile = hintTile ? hintTile : plane->pl_hint;
GOTOPOINT(enumTile, &here);
plane->pl_hint = enumTile;
while (here.p_y >= rect->r_ybot)
{
if (SigInterruptPending) return 1;
/*
* Find the tile (tp) immediately below the one to be
* enumerated (enumTile). This must be done before we enumerate
* the tile, as the filter function applied to enumerate
* it can result in its deallocation or modification in
* some other way.
*/
here.p_y = BOTTOM(enumTile) - 1;
tp = enumTile;
GOTOPOINT(tp, &here);
plane->pl_hint = tp;
enumRight = RIGHT(enumTile);
enumBottom = BOTTOM(enumTile);
enumTR = TR(enumTile);
if ((*func)(enumTile, arg)) return 1;
/*
* If the right boundary of the tile being enumerated is
* inside of the search area, recursively enumerate
* tiles to its right.
*/
if (enumRight < rect->r_xtop)
if (tiSrAreaEnum(enumTR, enumBottom, rect, func, arg))
return 1;
enumTile = tp;
}
return 0;
}
/*
* --------------------------------------------------------------------
*
* tiSrAreaEnum --
*
* Perform the recursive edge search of the tile which has just been
* enumerated in an area search. The arguments passed are the RT
* corner stitch and bottom coordinate of the tile just enumerated.
*
* Results:
* 0 is returned if the search completed normally, 1 if
* it was aborted.
*
* Side effects:
* Attempts to enumerate recursively each tile found in walking
* along the right edge of the tile just enumerated. Whatever
* side effects occur result from the application of the client's
* filter function.
*
* --------------------------------------------------------------------
*/
int
tiSrAreaEnum(enumRT, enumBottom, rect, func, arg)
Tile *enumRT; /* TR corner stitch of tile just enumerated */
int enumBottom; /* Bottom coordinate of tile just enumerated */
Rect *rect; /* Area to search */
int (*func)(); /* Function to apply at each tile */
ClientData arg; /* Additional argument to pass to (*func)() */
{
Tile *tp, *tpLB, *tpTR;
int tpRight, tpNextTop, tpBottom, srchBottom;
int atBottom = (enumBottom <= rect->r_ybot);
/*
* Begin examination of tiles along right edge.
* A tile to the right of the one being enumerated is enumerable if:
* - its bottom lies at or above that of the tile being enumerated, or,
* - the bottom of the tile being enumerated lies at or below the
* bottom of the search rectangle.
*/
if ((srchBottom = enumBottom) < rect->r_ybot)
srchBottom = rect->r_ybot;
for (tp = enumRT, tpNextTop = TOP(tp); tpNextTop > srchBottom; tp = tpLB)
{
if (SigInterruptPending) return 1;
/*
* Since the client's filter function may result in this tile
* being deallocated or otherwise modified, we must extract
* all the information we will need from the tile before we
* apply the filter function.
*/
tpLB = LB(tp);
tpNextTop = TOP(tpLB); /* Since TOP(tpLB) comes from tp */
if (BOTTOM(tp) < rect->r_ytop && (atBottom || BOTTOM(tp) >= enumBottom))
{
/*
* We extract more information from the tile, which we will use
* after applying the filter function.
*/
tpRight = RIGHT(tp);
tpBottom = BOTTOM(tp);
tpTR = TR(tp);
if ((*func)(tp, arg)) return 1;
/*
* If the right boundary of the tile being enumerated is
* inside of the search area, recursively enumerate
* tiles to its right.
*/
if (tpRight < rect->r_xtop)
if (tiSrAreaEnum(tpTR, tpBottom, rect, func, arg))
return 1;
}
}
return 0;
}

View File

@ -6,11 +6,11 @@ MODULE = utils
MAGICDIR = ..
LIB_SRCS = LIBdbio.c LIBmain.c LIBtextio.c
SRCS = args.c child.c dqueue.c finddisp.c flock.c flsbuf.c fraction.c \
geometry.c getrect.c hash.c heap.c list.c lookup.c lookupany.c \
lookupfull.c macros.c main.c malloc.c match.c maxrect.c netlist.c \
niceabort.c parser.c path.c pathvisit.c port.c printstuff.c \
signals.c stack.c strdup.c runstats.c set.c show.c tech.c \
touchtypes.c undo.c
geometry.c getrect.c hash.c heap.c ihash.c list.c lookup.c \
lookupany.c lookupfull.c macros.c main.c malloc.c match.c \
maxrect.c netlist.c niceabort.c parser.c path.c pathvisit.c \
port.c printstuff.c signals.c stack.c strdup.c runstats.c set.c \
show.c tech.c touchtypes.c undo.c
include ${MAGICDIR}/defs.mak

View File

@ -75,6 +75,7 @@ global int GeoOppositePos[] =
*/
global Rect GeoNullRect = { 0, 0, 0, 0 };
global Rect GeoInvertedRect = { 0, 0, -1, -1 };
global Point GeoOrigin = { 0, 0 };
@ -714,6 +715,24 @@ GeoIncludePoint(src, dst)
}
}
/*-------------------------------------------------------------------
* GeoIncludeRectInBBox() --
*
* Expand bounding box to include rectangle r
*
*-------------------------------------------------------------------
*/
void
GeoIncludeRectInBBox(r, bbox)
Rect *r;
Rect *bbox;
{
bbox->r_xbot = MIN(bbox->r_xbot,r->r_xbot);
bbox->r_ybot = MIN(bbox->r_ybot,r->r_ybot);
bbox->r_xtop = MAX(bbox->r_xtop,r->r_xtop);
bbox->r_ytop = MAX(bbox->r_ytop,r->r_ytop);
}
/*-------------------------------------------------------------------
* GeoClip --

View File

@ -190,6 +190,7 @@ extern int GeoRectPointSide(Rect *, Point *);
extern int GeoRectRectSide(Rect *, Rect *);
extern void GeoIncludePoint(Point *, Rect *);
extern void GeoDecomposeTransform(Transform *, bool *, int *);
extern void GeoIncludeRectInBBox(Rect *, Rect *bbox);
/*
*-------------------------------------------------------------------
@ -207,6 +208,7 @@ extern Transform GeoRef45Transform;
extern Transform GeoRef135Transform;
extern Rect GeoNullRect;
extern Rect GeoInvertedRect;
extern Point GeoOrigin;
extern int GeoOppositePos[];

360
utils/ihash.c Normal file
View File

@ -0,0 +1,360 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
/* ihash.c --
*
* Implements "internal" hash, i.e. hash on user supplied structures,
* without need for parallel hash entry structs.
*
* pointers involving users structs are cast to (void *)
* This should make the pointer arithmetic work out regardless
* of alignments within structs.
*
* See ihash.h
*
*/
#define DEREF(ptr,offset) ((ptr)+(offset))
static char rcsid[] = "$Header$";
#include <string.h>
#include <stdio.h>
#include "utils/magic.h"
#include "utils/malloc.h"
#include "utils/utils.h"
#include "utils/ihash.h"
/*
* The following defines the ratio of # entries to # buckets
* at which we rebuild the table to make it larger.
*/
static int iHashResizeRatio = 3;
/* forward reference */
static void iHashResize(IHashTable *table);
/* create a new hash table */
/* offsets should be generated by pointer subtraction of (void *) pointers */
extern IHashTable *IHashInit(
int nBuckets,
int keyOffset,
int nextOffset,
int (*hashFn)(void* key),
int (*sameKeyFn)(void* key1, void* key2)
)
{
IHashTable *table;
table = (IHashTable *)mallocMagic(sizeof(IHashTable));
table->iht_table = (void **)callocMagic(sizeof(void *)*nBuckets);
table->iht_nBucketsInit = nBuckets;
table->iht_nBuckets = nBuckets;
table->iht_nEntries = 0;
table->iht_keyOffset = keyOffset;
table->iht_nextOffset = nextOffset;
table->iht_hashFn = hashFn;
table->iht_sameKeyFn = sameKeyFn;
return table;
}
/* free hash table (does not free client structures) */
void IHashFree(IHashTable *table)
{
freeMagic((char *) table->iht_table); /* free buckets */
freeMagic((char *) table);
}
/* delete all entrys (and restore initial hash table size) */
void IHashClear(IHashTable *table)
{
/* reinitial bucket array */
freeMagic((char *) table->iht_table);
table->iht_table = (void **)callocMagic(sizeof(void *)*table->iht_nBucketsInit);
table->iht_nBuckets = table->iht_nBucketsInit;
table->iht_nEntries = 0;
}
/* lookup an entry in table */
void *IHashLookUp(IHashTable *table, void *key)
{
int hash;
int bucket;
void *entry;
hash = (table->iht_hashFn)(key);
bucket = ABS(hash) % table->iht_nBuckets;
for(entry=table->iht_table[bucket];
entry && !(table->iht_sameKeyFn)(key, DEREF(entry,(table->iht_keyOffset)));
entry = *((void **) DEREF(entry,table->iht_nextOffset))) /* empty body*/;
return entry;
}
/* return next matching entry */
void *IHashLookUpNext(IHashTable *table, void *prevEntry)
{
void *entry;
void *key = DEREF(prevEntry,table->iht_keyOffset);
int hash = (table->iht_hashFn)(key);
int bucket = ABS(hash) % table->iht_nBuckets;
for(entry = *((void **) DEREF(prevEntry,table->iht_nextOffset));
entry && !(table->iht_sameKeyFn)(key,DEREF(entry,table->iht_keyOffset));
entry = *((void **) DEREF(entry,table->iht_nextOffset))) /* empty body*/;
return entry;
}
/* add an entry in table */
void IHashAdd(IHashTable *table, void *entry)
{
int hash;
int bucket;
/* ASSERT(!IHashLookUp(IHashTable, entry+IHashTable->iht_keyOffset),"IHashAdd"); */
hash = (table->iht_hashFn)(DEREF(entry,table->iht_keyOffset));
bucket = ABS(hash) % table->iht_nBuckets;
*(void **)DEREF(entry,table->iht_nextOffset) = table->iht_table[bucket];
table->iht_table[bucket] = entry;
table->iht_nEntries++;
/* if table getting crowded, resize it */
if(table->iht_nEntries/table->iht_nBuckets >= iHashResizeRatio)
{
iHashResize(table);
}
}
/* deletes an entry from table */
/*
* NOTE: bplane code assumes IHashDelete() does not restructure table!
* (IHashLookUpNext() is called before IHashDelete(), and then the enum.
* is continued with further IHashLookUpNext() calls.
*/
void IHashDelete(IHashTable *table, void *entry)
{
int hash;
int bucket;
void **pp;
int nextOffset = table->iht_nextOffset;
hash = (table->iht_hashFn)DEREF(entry,table->iht_keyOffset);
bucket = ABS(hash) % table->iht_nBuckets;
for(pp = &table->iht_table[bucket];
(*pp) && (*pp) != entry;
pp = DEREF((*pp),nextOffset));
ASSERT(*pp,"IHashDelete");
(*pp) = * (void **) DEREF(entry,nextOffset);
table->iht_nEntries--;
}
/* return number of entries in table */
int IHashEntries(IHashTable *table)
{
return table->iht_nEntries;
}
/* call back client func on each entry in hashtable */
void IHashEnum(IHashTable *table, void (*clientFunc)(void *entry))
{
int bucket;
for(bucket=0; bucket<table->iht_nBuckets; bucket++)
{
void *entry;
for(entry=table->iht_table[bucket];
entry;
entry = *((void **) DEREF(entry,table->iht_nextOffset)))
{
(*clientFunc)(entry);
}
}
}
/* grow hash table */
static void iHashResize(IHashTable *table)
{
void **oldBuckets = table->iht_table;
int oldSize = table->iht_nBuckets;
int newSize = oldSize*4;
int bucket;
/* alloc a new table */
table->iht_table = (void **)callocMagic(sizeof(void *)*newSize);
table->iht_nBuckets = newSize;
table->iht_nEntries = 0;
/* add back all entries in old table */
for(bucket=0; bucket<oldSize; bucket++)
{
void *entry;
void *next;
for(entry=oldBuckets[bucket];
entry;
entry = next)
{
next = *((void **) DEREF(entry,table->iht_nextOffset));
IHashAdd(table,entry);
}
}
/* finally, free old table */
freeMagic((char *) oldBuckets);
}
/* print out statistics */
void IHashStats(IHashTable *table)
{
int bucket;
fprintf(stderr,"Internal Hash Statistics:\n");
fprintf(stderr,"\tinitial buckets = %d\n", table->iht_nBucketsInit);
fprintf(stderr,"\tbuckets = %d\n", table->iht_nBuckets);
fprintf(stderr,"\tentries = %d\n", table->iht_nEntries);
fprintf(stderr,"\tkey offset = %d\n", table->iht_keyOffset);
fprintf(stderr,"\tnext offset = %d\n", table->iht_nextOffset);
fprintf(stderr,"\ndistribution: ");
for(bucket=0; bucket<table->iht_nBuckets; bucket++)
{
void *entry;
int num = 0;
for(entry=table->iht_table[bucket];
entry;
entry = *((void **) DEREF(entry,table->iht_nextOffset)))
{
num++;
}
fprintf(stderr,"%d ",num);
}
}
/* return statistics on hash table (returns memory utilized by table) */
int IHashStats2(IHashTable *table,
int *nBuckets, /* if non-null return num buckets here */
int *nEntries) /* if non-null return num entries here */
{
if(nBuckets) *nBuckets = table->iht_nBuckets;
if(nEntries) *nEntries = table->iht_nEntries;
return
UtlsStatMallocMem(sizeof(IHashTable)) +
UtlsStatMallocMem(sizeof(void *)* table->iht_nBuckets);
}
/* hash for key fields that are pointers to strings */
int IHashStringPKeyHash(void *key)
{
char *s = * (char **) key;
int i=0;
/* Add up the characters as though this were a number */
while (*s != 0) i = (i*10) + (*s++ - '0');
if(i<0) i = -i;
return i;
}
/* compare string pointer keys */
int IHashStringPKeyEq(void *key1, void *key2)
{
return strcmp(* (char **) key1, * (char **) key2)==0;
}
/* hash for key fields that are strings */
int IHashStringKeyHash(void *key)
{
char *s = (char *) key;
int i=0;
/* Add up the characters as though this were a number */
while (*s != 0) i = (i*10) + (*s++ - '0');
if(i<0) i = -i;
return i;
}
/* compare string keys */
int IHashStringKeyEq(void *key1, void *key2)
{
return strcmp((char *) key1, (char *) key2)==0;
}
/* hash for key fields that are 32 bit words */
int IHashWordKeyHash(void *keyp)
{
/* just use the value of word itself! */
return * (int *) keyp;
}
/* compare struc for 32 bit word keys */
int IHashWordKeyEq(void *key1p, void *key2p)
{
return ( *(int *) key1p == * (int *) key2p);
}
/* hash for n-byte field */
static __inline__ int
iHash(void *key, int n)
{
char *s = (char *) key;
int hash=0;
int i;
/* Add up the characters as though this were a number */
for(i=0;i<n;i++) hash = (hash*10) + (s[i] - '0');
if(hash<0) hash = -hash;
return hash;
}
/* hash for key fields that are four words long */
int IHash4WordKeyHash(void *keyp)
{
return iHash(keyp,4*sizeof(int));
}
/* compare struc for 4 word keys */
int IHash4WordKeyEq(void *key1p, void *key2p)
{
return (memcmp(key1p,key2p,4*sizeof(int)) == 0);
}

122
utils/ihash.h Normal file
View File

@ -0,0 +1,122 @@
// ************************************************************************
//
// Copyright (c) 1995-2002 Juniper Networks, Inc. All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the
// above copyright notice and the following three paragraphs appear in
// all copies of this software.
//
// IN NO EVENT SHALL JUNIPER NETWORKS, INC. BE LIABLE TO ANY PARTY FOR
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// JUNIPER NETWORKS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// JUNIPER NETWORKS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
// NON-INFRINGEMENT.
//
// THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND JUNIPER
// NETWORKS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
// ************************************************************************
/* ihash.h --
*
* "Internal" hash routines.
* Allows hashing of existing structs without creating parallel structs
* to hold keys etc.
*
* The structs to be hashed must have "key" and "next" fields. The offsets
* of these fields are passed to HashInit.
*/
/* rcsid "$Header$" */
#ifndef _IHASH_H
#define _IHASH_H
/* The IHashTable struct should not be manipulated directly by clients */
typedef struct ihashtable
{
void **iht_table; /* Pointer to array of pointers. */
int iht_nBucketsInit; /* Initial size of array. */
int iht_nBuckets; /* Size of array. */
int iht_nEntries; /* Number of hashed items */
int iht_keyOffset; /* offset of keys in client strucs */
int iht_nextOffset; /* offset of next fields in client strucs */
int (*iht_hashFn)(void *key); /* Hash function */
int (*iht_sameKeyFn)(void *key1, void *key2); /* returns 1 if keys match */
} IHashTable;
/* create a new hash table */
extern IHashTable *IHashInit(
int nBuckets,
int keyOffset,
int nextOffset,
int (*hashFn)(void *key),
int (*sameKeyFn)(void *key1, void *key2)
);
/* lookup an entry in table (returns first match) */
extern void *IHashLookUp(IHashTable *table, void *key);
/* lookup NEXT matching entry in table */
extern void *IHashLookUpNext(IHashTable *table, void *prevEntry);
/* add an entry to the table */
extern void IHashAdd(IHashTable *table, void *entry);
/* delete an entry from the table */
extern void IHashDelete(IHashTable *table, void *entry);
/* delete all entrys (and restore initial hash table size) */
extern void IHashClear(IHashTable *table);
/* callback supplied func for each entry in table */
extern void IHashEnum(IHashTable *table, void (*clientFunc)(void *entry));
/* return number of entries in table */
extern int IHashEntries(IHashTable *table);
/* print hash table statistics */
extern void IHashStats(IHashTable *table);
/* return hashtable memory usage and stats */
extern int IHashStats2(IHashTable *table, int *nBuckets, int *nEntries);
/* free hash table (does not free client strucs!) */
extern void IHashFree(IHashTable *table);
/* A hash function suitable for hash key fields that are pointers to strings */
extern int IHashStringPKeyHash(void *key);
/* key comparison function for key fields that are pointers to strings */
extern int IHashStringPKeyEq(void *key1, void *key2);
/* A hash function suitable for hash key fields that are strings */
extern int IHashStringKeyHash(void *key);
/* key comparison function for key fields that are strings */
extern int IHashStringKeyEq(void *key1, void *key2);
/* A hash function suitable for keys that are pointers */
extern int IHashWordKeyHash(void *key);
/* key comparison function for key fields that are pointers */
extern int IHashWordKeyEq(void *key1, void *key2);
/* A hash function suitable for 4 word keys */
extern int IHash4WordKeyHash(void *key);
/* key comparison function for four word keys */
extern int IHash4WordKeyEq(void *key1, void *key2);
#endif /* _IHASH_H */