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:
parent
465a46c1c6
commit
1d04f20f5d
6
Makefile
6
Makefile
|
|
@ -6,9 +6,9 @@ MAGICDIR = .
|
||||||
PROGRAMS = magic
|
PROGRAMS = magic
|
||||||
TECH = scmos
|
TECH = scmos
|
||||||
LIBRARIES = database utils extflat
|
LIBRARIES = database utils extflat
|
||||||
MODULES = cmwind commands database dbwind debug drc extflat extract \
|
MODULES = bplane cmwind commands database dbwind debug drc extflat \
|
||||||
graphics netmenu plow resis select sim textio tiles utils \
|
extract graphics netmenu plow resis select sim textio tiles \
|
||||||
windows wiring
|
utils windows wiring
|
||||||
|
|
||||||
MAKEFLAGS =
|
MAKEFLAGS =
|
||||||
INSTALL_CAD_DIRS = windows doc ${TECH}
|
INSTALL_CAD_DIRS = windows doc ${TECH}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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); */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -3678,7 +3678,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
||||||
Point childPoint, editPoint, rootPoint;
|
Point childPoint, editPoint, rootPoint;
|
||||||
CellDef *def, *rootDef, *editDef;
|
CellDef *def, *rootDef, *editDef;
|
||||||
bool hasChild, hasRoot, hasTrans;
|
bool hasChild, hasRoot, hasTrans;
|
||||||
Rect rootBox;
|
Rect rootBox, bbox;
|
||||||
Transform *tx_cell, trans_cell;
|
Transform *tx_cell, trans_cell;
|
||||||
char **av;
|
char **av;
|
||||||
char *cellnameptr, *fullpathname;
|
char *cellnameptr, *fullpathname;
|
||||||
|
|
@ -3792,6 +3792,25 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
||||||
return FALSE;
|
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
|
* Parse the remainder of the arguments to find out the reference
|
||||||
* points in the child cell and the edit cell. Use the defaults
|
* 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);
|
p = Lookup(av[1], refPointNames);
|
||||||
if (p == 0) /* lower left */
|
if (p == 0) /* lower left */
|
||||||
{
|
{
|
||||||
childPoint.p_x = def->cd_bbox.r_ll.p_x;
|
childPoint.p_x = bbox.r_ll.p_x;
|
||||||
childPoint.p_y = def->cd_bbox.r_ll.p_y;
|
childPoint.p_y = bbox.r_ll.p_y;
|
||||||
}
|
}
|
||||||
else if (p == 1) /* lower right */
|
else if (p == 1) /* lower right */
|
||||||
{
|
{
|
||||||
childPoint.p_x = def->cd_bbox.r_ur.p_x;
|
childPoint.p_x = bbox.r_ur.p_x;
|
||||||
childPoint.p_y = def->cd_bbox.r_ll.p_y;
|
childPoint.p_y = bbox.r_ll.p_y;
|
||||||
}
|
}
|
||||||
else if (p == 2) /* upper left */
|
else if (p == 2) /* upper left */
|
||||||
{
|
{
|
||||||
childPoint.p_x = def->cd_bbox.r_ll.p_x;
|
childPoint.p_x = bbox.r_ll.p_x;
|
||||||
childPoint.p_y = def->cd_bbox.r_ur.p_y;
|
childPoint.p_y = bbox.r_ur.p_y;
|
||||||
}
|
}
|
||||||
else if (p == 3) /* upper right */
|
else if (p == 3) /* upper right */
|
||||||
{
|
{
|
||||||
childPoint.p_x = def->cd_bbox.r_ur.p_x;
|
childPoint.p_x = bbox.r_ur.p_x;
|
||||||
childPoint.p_y = def->cd_bbox.r_ur.p_y;
|
childPoint.p_y = bbox.r_ur.p_y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -3960,9 +3979,9 @@ default_action:
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
||||||
GeoTransRect(tx_cell, &def->cd_bbox, &r);
|
GeoTransRect(tx_cell, &bbox, &r);
|
||||||
GeoTranslateTrans(tx_cell, def->cd_bbox.r_xbot - r.r_xbot,
|
GeoTranslateTrans(tx_cell, bbox.r_xbot - r.r_xbot,
|
||||||
def->cd_bbox.r_ybot - r.r_ybot,
|
bbox.r_ybot - r.r_ybot,
|
||||||
&trans_cell);
|
&trans_cell);
|
||||||
}
|
}
|
||||||
av += 1;
|
av += 1;
|
||||||
|
|
@ -3991,23 +4010,23 @@ default_action:
|
||||||
p = Lookup(av[1], refPointNames);
|
p = Lookup(av[1], refPointNames);
|
||||||
if (p == 0) /* lower left */
|
if (p == 0) /* lower left */
|
||||||
{
|
{
|
||||||
editPoint.p_x = def->cd_bbox.r_ll.p_x;
|
editPoint.p_x = bbox.r_ll.p_x;
|
||||||
editPoint.p_y = def->cd_bbox.r_ll.p_y;
|
editPoint.p_y = bbox.r_ll.p_y;
|
||||||
}
|
}
|
||||||
else if (p == 1) /* lower right */
|
else if (p == 1) /* lower right */
|
||||||
{
|
{
|
||||||
editPoint.p_x = def->cd_bbox.r_ur.p_x;
|
editPoint.p_x = bbox.r_ur.p_x;
|
||||||
editPoint.p_y = def->cd_bbox.r_ll.p_y;
|
editPoint.p_y = bbox.r_ll.p_y;
|
||||||
}
|
}
|
||||||
else if (p == 2) /* upper left */
|
else if (p == 2) /* upper left */
|
||||||
{
|
{
|
||||||
editPoint.p_x = def->cd_bbox.r_ll.p_x;
|
editPoint.p_x = bbox.r_ll.p_x;
|
||||||
editPoint.p_y = def->cd_bbox.r_ur.p_y;
|
editPoint.p_y = bbox.r_ur.p_y;
|
||||||
}
|
}
|
||||||
else if (p == 3) /* upper right */
|
else if (p == 3) /* upper right */
|
||||||
{
|
{
|
||||||
editPoint.p_x = def->cd_bbox.r_ur.p_x;
|
editPoint.p_x = bbox.r_ur.p_x;
|
||||||
editPoint.p_y = def->cd_bbox.r_ur.p_y;
|
editPoint.p_y = bbox.r_ur.p_y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -4073,7 +4092,7 @@ default_action:
|
||||||
* provided.
|
* provided.
|
||||||
*/
|
*/
|
||||||
if (!hasChild)
|
if (!hasChild)
|
||||||
childPoint = def->cd_bbox.r_ll;
|
childPoint = bbox.r_ll;
|
||||||
if (!hasRoot)
|
if (!hasRoot)
|
||||||
{
|
{
|
||||||
if (!ToolGetBox(&rootDef, &rootBox))
|
if (!ToolGetBox(&rootDef, &rootBox))
|
||||||
|
|
@ -4102,7 +4121,7 @@ box_error:
|
||||||
GeoTranslateTrans(&trans_cell, rootPoint.p_x - childPoint.p_x,
|
GeoTranslateTrans(&trans_cell, rootPoint.p_x - childPoint.p_x,
|
||||||
rootPoint.p_y - childPoint.p_y,
|
rootPoint.p_y - childPoint.p_y,
|
||||||
&scx->scx_trans);
|
&scx->scx_trans);
|
||||||
scx->scx_area = def->cd_bbox;
|
scx->scx_area = bbox;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
|
|
|
||||||
|
|
@ -1635,7 +1635,8 @@ CmdFindNetProc(nodename, use, rect, warn_not_found)
|
||||||
/* Find the tile type of the tile at the specified point which */
|
/* Find the tile type of the tile at the specified point which */
|
||||||
/* exists on the plane pnum. */
|
/* exists on the plane pnum. */
|
||||||
|
|
||||||
(void) TiSrArea(NULL, plane, &localrect, findTile, (ClientData) &ttype);
|
DBSrPaintArea(NULL, plane, &localrect, &DBAllTypeBits, findTile,
|
||||||
|
(ClientData) &ttype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -832,7 +832,7 @@ cmdPsearchStats(str, tl, td, count)
|
||||||
*
|
*
|
||||||
* CmdTsearch --
|
* 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
|
* that specified by the box, each time over a different area in the
|
||||||
* edit cell.
|
* edit cell.
|
||||||
*
|
*
|
||||||
|
|
@ -943,18 +943,12 @@ CmdTsearch(w, cmd)
|
||||||
|
|
||||||
if (cmd->tx_argc < 5)
|
if (cmd->tx_argc < 5)
|
||||||
{
|
{
|
||||||
(void) TiSrArea((Tile *) NULL, plane, &rsearch,
|
(void) DBSrPaintArea((Tile *) NULL, plane, &rsearch, &DBAllTypeBits,
|
||||||
cmdTsrFunc, (ClientData) 0);
|
cmdTsrFunc, (ClientData) 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/****
|
(void) DBSrPaintArea((Tile *) NULL, plane, &rsearch, &mask,
|
||||||
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,
|
|
||||||
cmdTsrFunc, (ClientData) 0);
|
cmdTsrFunc, (ClientData) 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,48 +58,38 @@ DBBoundCellPlane(def, extended, rect)
|
||||||
cbs.found = FALSE;
|
cbs.found = FALSE;
|
||||||
|
|
||||||
*rect = GeoNullRect;
|
*rect = GeoNullRect;
|
||||||
if (TiSrArea((Tile *)NULL, def->cd_planes[PL_CELL],
|
if (DBSrCellPlaneArea(def->cd_cellPlane, &TiPlaneRect,
|
||||||
&TiPlaneRect, dbCellBoundFunc, (ClientData) &filter) == 0)
|
dbCellBoundFunc, (ClientData) &filter) == 0)
|
||||||
return cbs.found;
|
return cbs.found;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCellBoundFunc(tile, fp)
|
dbCellBoundFunc(use, fp)
|
||||||
Tile *tile;
|
CellUse *use;
|
||||||
TreeFilter *fp;
|
TreeFilter *fp;
|
||||||
{
|
{
|
||||||
CellUse *use;
|
|
||||||
CellTileBody *body;
|
|
||||||
Rect *bbox;
|
Rect *bbox;
|
||||||
DBCellBoundStruct *cbs;
|
DBCellBoundStruct *cbs;
|
||||||
|
|
||||||
cbs = (DBCellBoundStruct *)fp->tf_arg;
|
cbs = (DBCellBoundStruct *)fp->tf_arg;
|
||||||
|
|
||||||
for (body = (CellTileBody *) TiGetBody(tile); body != NULL;
|
bbox = &use->cu_bbox;
|
||||||
body = body->ctb_next)
|
if (cbs->found)
|
||||||
{
|
{
|
||||||
use = body->ctb_use;
|
if (cbs->extended)
|
||||||
bbox = &use->cu_bbox;
|
GeoInclude(&use->cu_extended, cbs->area);
|
||||||
if ((BOTTOM(tile) <= bbox->r_ybot) && (RIGHT(tile) >= bbox->r_xtop))
|
else
|
||||||
{
|
GeoInclude(&use->cu_bbox, cbs->area);
|
||||||
if (cbs->found)
|
}
|
||||||
{
|
else
|
||||||
if (cbs->extended)
|
{
|
||||||
GeoInclude(&use->cu_extended, cbs->area);
|
if (cbs->extended)
|
||||||
else
|
*cbs->area = use->cu_extended;
|
||||||
GeoInclude(&use->cu_bbox, cbs->area);
|
else
|
||||||
}
|
*cbs->area = use->cu_bbox;
|
||||||
else
|
cbs->found = TRUE;
|
||||||
{
|
|
||||||
if (cbs->extended)
|
|
||||||
*cbs->area = use->cu_extended;
|
|
||||||
else
|
|
||||||
*cbs->area = use->cu_bbox;
|
|
||||||
cbs->found = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ struct searchArg
|
||||||
{
|
{
|
||||||
CellUse * celluse;
|
CellUse * celluse;
|
||||||
Rect * rect;
|
Rect * rect;
|
||||||
Plane * plane;
|
BPlane * bplane;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TOPLEFT 10
|
#define TOPLEFT 10
|
||||||
|
|
@ -55,6 +55,25 @@ struct searchArg
|
||||||
#define TOPBOTTOMLEFTRIGHT 15
|
#define TOPBOTTOMLEFTRIGHT 15
|
||||||
|
|
||||||
int dbCellDebug = 0;
|
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?
|
* something identical to use?
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
Tile *tile;
|
BPEnum bpe;
|
||||||
CellTileBody *body;
|
CellUse *dupUse;
|
||||||
CellUse *checkUse;
|
|
||||||
|
|
||||||
tile = TiSrPoint((Tile *) NULL, parent->cd_planes[PL_CELL],
|
BPEnumInit(&bpe, parent->cd_cellPlane, &use->cu_bbox, BPE_EQUAL,
|
||||||
&use->cu_bbox.r_ll);
|
"DBCellFindDup");
|
||||||
|
while (dupUse = BPEnumNext(&bpe))
|
||||||
|
if (dupUse->cu_def == use->cu_def) break;
|
||||||
|
|
||||||
for (body = (CellTileBody *) TiGetBody(tile);
|
BPEnumTerm(&bpe);
|
||||||
body != NULL;
|
return dupUse;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
|
|
@ -130,33 +139,30 @@ DBCellFindDup(use, parent)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
DBPlaceCell (celluse, targetcell)
|
DBPlaceCell (use, def)
|
||||||
CellUse * celluse; /* new celluse to add to subcell tile plane */
|
CellUse * use; /* new celluse to add to subcell tile plane */
|
||||||
CellDef * targetcell; /* parent cell's definition */
|
CellDef * def; /* parent cell's definition */
|
||||||
{
|
{
|
||||||
Rect rect; /* argument to TiSrArea(), placeCellFunc() */
|
Rect rect; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
|
||||||
Plane * plane; /* argument to TiSrArea(), placeCellFunc() */
|
BPlane *bplane; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
|
||||||
struct searchArg arg; /* argument to placeCellFunc() */
|
struct searchArg arg; /* argument to placeCellFunc() */
|
||||||
|
|
||||||
ASSERT(celluse != (CellUse *) NULL, "DBPlaceCell");
|
ASSERT(use != (CellUse *) NULL, "DBPlaceCell");
|
||||||
celluse->cu_parent = targetcell;
|
ASSERT(def, "DBPlaceCell");
|
||||||
plane = targetcell->cd_planes[PL_CELL]; /* assign plane */
|
|
||||||
rect = celluse->cu_bbox;
|
/* To do: Check non-duplicate placement, check non-duplicate ID */
|
||||||
/* rect = celluse->cu_extended; */
|
|
||||||
arg.rect = ▭
|
use->cu_parent = def;
|
||||||
arg.celluse = celluse;
|
|
||||||
arg.plane = plane;
|
|
||||||
|
|
||||||
/* Be careful not to permit interrupts during this, or the
|
/* Be careful not to permit interrupts during this, or the
|
||||||
* database could be left in a trashed state.
|
* database could be left in a trashed state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SigDisableInterrupts();
|
SigDisableInterrupts();
|
||||||
(void) TiSrArea((Tile *) NULL, plane, &rect, placeCellFunc,
|
BPAdd(def->cd_cellPlane, use);
|
||||||
(ClientData) &arg);
|
def->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
|
||||||
targetcell->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
|
|
||||||
if (UndoIsEnabled())
|
if (UndoIsEnabled())
|
||||||
DBUndoCellUse(celluse, UNDO_CELL_PLACE);
|
DBUndoCellUse(use, UNDO_CELL_PLACE);
|
||||||
SigEnableInterrupts();
|
SigEnableInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,19 +182,12 @@ DBPlaceCell (celluse, targetcell)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
DBDeleteCell (celluse)
|
DBDeleteCell (use)
|
||||||
CellUse * celluse;
|
CellUse * use;
|
||||||
{
|
{
|
||||||
Rect rect; /* argument to TiSrArea(), deleteCellFunc() */
|
ASSERT(use != (CellUse *) NULL, "DBDeleteCell");
|
||||||
Plane * plane; /* argument to TiSrArea(), deleteCellFunc() */
|
|
||||||
struct searchArg arg; /* argument to deleteCellFunc() */
|
|
||||||
|
|
||||||
ASSERT(celluse != (CellUse *) NULL, "DBDeleteCell");
|
dbInstanceUnplace(use);
|
||||||
plane = celluse->cu_parent->cd_planes[PL_CELL]; /* assign plane */
|
|
||||||
rect = celluse->cu_bbox;
|
|
||||||
arg.rect = ▭
|
|
||||||
arg.plane = plane;
|
|
||||||
arg.celluse = celluse;
|
|
||||||
|
|
||||||
/* It's important that this code run with interrupts disabled,
|
/* It's important that this code run with interrupts disabled,
|
||||||
* or else we could leave the subcell tile plane in a weird
|
* or else we could leave the subcell tile plane in a weird
|
||||||
|
|
@ -196,511 +195,10 @@ DBDeleteCell (celluse)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SigDisableInterrupts();
|
SigDisableInterrupts();
|
||||||
(void) TiSrArea((Tile *) NULL, plane, &rect, deleteCellFunc,
|
use->cu_parent->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
|
||||||
(ClientData) &arg);
|
|
||||||
celluse->cu_parent->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
|
|
||||||
if (UndoIsEnabled())
|
if (UndoIsEnabled())
|
||||||
DBUndoCellUse(celluse, UNDO_CELL_DELETE);
|
DBUndoCellUse(use, UNDO_CELL_DELETE);
|
||||||
celluse->cu_parent = (CellDef *) NULL;
|
use->cu_parent = (CellDef *) NULL;
|
||||||
SigEnableInterrupts();
|
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));
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -616,11 +616,6 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
|
||||||
bool foundAny;
|
bool foundAny;
|
||||||
int pNum;
|
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
|
* Include area of subcells separately
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1318,7 +1318,8 @@ DBCellDefAlloc()
|
||||||
TTMaskZero(&cellDef->cd_types);
|
TTMaskZero(&cellDef->cd_types);
|
||||||
HashInit(&cellDef->cd_idHash, 16, HT_STRINGKEYS);
|
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++)
|
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
||||||
cellDef->cd_planes[pNum] = DBNewPlane((ClientData) TT_SPACE);
|
cellDef->cd_planes[pNum] = DBNewPlane((ClientData) TT_SPACE);
|
||||||
|
|
||||||
|
|
@ -1512,9 +1513,10 @@ DBCellDefFree(cellDef)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SigDisableInterrupts();
|
SigDisableInterrupts();
|
||||||
DBFreeCellPlane(cellDef->cd_planes[PL_CELL]);
|
DBClearCellPlane(cellDef); /* Remove instances only */
|
||||||
TiFreePlane(cellDef->cd_planes[PL_CELL]);
|
BPFree(cellDef->cd_cellPlane); /* Remove the cell plane itself */
|
||||||
|
|
||||||
|
TiFreePlane(cellDef->cd_planes[PL_ROUTER]);
|
||||||
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
||||||
{
|
{
|
||||||
DBFreePaintPlane(cellDef->cd_planes[pNum]);
|
DBFreePaintPlane(cellDef->cd_planes[pNum]);
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,53 @@ struct seeTypesArg
|
||||||
TileTypeBitMask *saa_mask; /* Mask of tile types seen in search */
|
TileTypeBitMask *saa_mask; /* Mask of tile types seen in search */
|
||||||
Rect *saa_rect; /* Search area in root coordinates */
|
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 client procedure should not modify any of the paint planes in
|
||||||
* the cells visited by DBTreeSrTiles, because we use DBSrPaintArea
|
* 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:
|
* Results:
|
||||||
* 0 is returned if the search finished normally. 1 is returned
|
* 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 */
|
int (*func)(); /* Function to apply at each qualifying tile */
|
||||||
ClientData cdarg; /* Client data for above function */
|
ClientData cdarg; /* Client data for above function */
|
||||||
{
|
{
|
||||||
int dbCellTileSrFunc();
|
int dbCellPlaneSrFunc();
|
||||||
TreeFilter filter;
|
TreeFilter filter;
|
||||||
|
|
||||||
/* Set up the filter and call the recursive filter function */
|
/* 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_dinfo = 0;
|
||||||
filter.tf_planes = DBTechTypesToPlanes(mask);
|
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 */
|
int (*func)(); /* Function to apply at each qualifying tile */
|
||||||
ClientData cdarg; /* Client data for above function */
|
ClientData cdarg; /* Client data for above function */
|
||||||
{
|
{
|
||||||
int dbCellTileSrFunc();
|
int dbCellPlaneSrFunc();
|
||||||
TreeFilter filter;
|
TreeFilter filter;
|
||||||
|
|
||||||
/* Set up the filter and call the recursive filter function */
|
/* 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_dinfo = dinfo;
|
||||||
filter.tf_planes = DBTechTypesToPlanes(mask);
|
filter.tf_planes = DBTechTypesToPlanes(mask);
|
||||||
|
|
||||||
return dbCellTileSrFunc(scx, &filter);
|
return dbCellPlaneSrFunc(scx, &filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dbCellTileSrFunc --
|
* dbCellPlaneSrFunc --
|
||||||
*
|
*
|
||||||
* Recursive filter procedure applied to the cell by DBTreeSrTiles().
|
* Recursive filter procedure applied to the cell by DBTreeSrTiles().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCellTileSrFunc(scx, fp)
|
dbCellPlaneSrFunc(scx, fp)
|
||||||
SearchContext *scx;
|
SearchContext *scx;
|
||||||
TreeFilter *fp;
|
TreeFilter *fp;
|
||||||
{
|
{
|
||||||
|
|
@ -184,7 +230,7 @@ dbCellTileSrFunc(scx, fp)
|
||||||
CellDef *def = scx->scx_use->cu_def;
|
CellDef *def = scx->scx_use->cu_def;
|
||||||
int pNum;
|
int pNum;
|
||||||
|
|
||||||
ASSERT(def != (CellDef *) NULL, "dbCellTileSrFunc");
|
ASSERT(def != (CellDef *) NULL, "dbCellPlaneSrFunc");
|
||||||
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
|
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
|
||||||
return 0;
|
return 0;
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 0)
|
if ((def->cd_flags & CDAVAILABLE) == 0)
|
||||||
|
|
@ -219,10 +265,10 @@ dbCellTileSrFunc(scx, fp)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now apply ourselves recursively to each of the CellUses
|
* 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;
|
return 1;
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -270,7 +316,7 @@ DBTreeSrUniqueTiles(scx, mask, xMask, func, cdarg)
|
||||||
int (*func)(); /* Function to apply at each qualifying tile */
|
int (*func)(); /* Function to apply at each qualifying tile */
|
||||||
ClientData cdarg; /* Client data for above function */
|
ClientData cdarg; /* Client data for above function */
|
||||||
{
|
{
|
||||||
int dbCellTileSrFunc();
|
int dbCellPlaneSrFunc();
|
||||||
TreeFilter filter;
|
TreeFilter filter;
|
||||||
|
|
||||||
/* Set up the filter and call the recursive filter function */
|
/* Set up the filter and call the recursive filter function */
|
||||||
|
|
@ -288,7 +334,7 @@ DBTreeSrUniqueTiles(scx, mask, xMask, func, cdarg)
|
||||||
* dbCellUniqueTileSrFunc --
|
* dbCellUniqueTileSrFunc --
|
||||||
*
|
*
|
||||||
* Recursive filter procedure applied to the cell by DBTreeSrUniqueTiles().
|
* 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
|
* 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.
|
* to the filter function. Contacts will therefore be processed only once.
|
||||||
*/
|
*/
|
||||||
|
|
@ -348,8 +394,6 @@ dbCellUniqueTileSrFunc(scx, fp)
|
||||||
*
|
*
|
||||||
* DBNoTreeSrTiles --
|
* DBNoTreeSrTiles --
|
||||||
*
|
*
|
||||||
* (*** Move to database module after tested)
|
|
||||||
*
|
|
||||||
* NOTE: THIS PROCEDURE IS EXACTLY LIKE DBTreeSrTiles EXCEPT THAT IT DOES
|
* NOTE: THIS PROCEDURE IS EXACTLY LIKE DBTreeSrTiles EXCEPT THAT IT DOES
|
||||||
* NOT SEARCH SUBCELLS.
|
* NOT SEARCH SUBCELLS.
|
||||||
*
|
*
|
||||||
|
|
@ -377,7 +421,7 @@ dbCellUniqueTileSrFunc(scx, fp)
|
||||||
*
|
*
|
||||||
* The client procedure should not modify any of the paint planes in
|
* The client procedure should not modify any of the paint planes in
|
||||||
* the cells visited by DBTreeSrTiles, because we use DBSrPaintArea
|
* 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:
|
* Results:
|
||||||
* 0 is returned if the search finished normally. 1 is returned
|
* 0 is returned if the search finished normally. 1 is returned
|
||||||
|
|
@ -1030,7 +1074,6 @@ DBCellSrArea(scx, func, cdarg)
|
||||||
{
|
{
|
||||||
TreeFilter filter;
|
TreeFilter filter;
|
||||||
TreeContext context;
|
TreeContext context;
|
||||||
Rect expanded;
|
|
||||||
int dbCellSrFunc();
|
int dbCellSrFunc();
|
||||||
|
|
||||||
filter.tf_func = func;
|
filter.tf_func = func;
|
||||||
|
|
@ -1042,22 +1085,10 @@ DBCellSrArea(scx, func, cdarg)
|
||||||
if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, NULL))
|
if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* In order to make this work with zero-size areas, we first expand
|
if (DBSrCellPlaneArea(scx->scx_use->cu_def->cd_cellPlane,
|
||||||
* the area by before searching the tile plane. DbCellSrFunc will
|
&scx->scx_area, dbCellSrFunc, (ClientData) &context))
|
||||||
* 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))
|
|
||||||
return 1;
|
return 1;
|
||||||
else return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1066,17 +1097,7 @@ DBCellSrArea(scx, func, cdarg)
|
||||||
* dbCellSrFunc --
|
* dbCellSrFunc --
|
||||||
*
|
*
|
||||||
* Filter procedure for DBCellSrArea. Applies the procedure given
|
* Filter procedure for DBCellSrArea. Applies the procedure given
|
||||||
* to DBCellSrArea to any of the CellUses in the tile that are
|
* to DBCellSrArea to any of the CellUses in the given area.
|
||||||
* 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).
|
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* 0 is normally returned, and 1 is returned if an abort occurred.
|
* 0 is normally returned, and 1 is returned if an abort occurred.
|
||||||
|
|
@ -1089,88 +1110,56 @@ DBCellSrArea(scx, func, cdarg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCellSrFunc(tile, cxp)
|
dbCellSrFunc(use, cxp)
|
||||||
Tile *tile;
|
CellUse *use;
|
||||||
TreeContext *cxp;
|
TreeContext *cxp;
|
||||||
{
|
{
|
||||||
TreeFilter *fp = cxp->tc_filter;
|
TreeFilter *fp = cxp->tc_filter;
|
||||||
SearchContext *scx = cxp->tc_scx;
|
SearchContext *scx = cxp->tc_scx;
|
||||||
CellUse *use;
|
|
||||||
Rect *bbox;
|
Rect *bbox;
|
||||||
CellTileBody *body;
|
|
||||||
SearchContext newScx;
|
SearchContext newScx;
|
||||||
Transform t, tinv;
|
Transform t, tinv;
|
||||||
Rect tileArea;
|
|
||||||
int srchBot, srchRight;
|
|
||||||
int xlo, xhi, ylo, yhi, xbase, ybase, xsep, ysep, clientResult;
|
int xlo, xhi, ylo, yhi, xbase, ybase, xsep, ysep, clientResult;
|
||||||
|
|
||||||
srchBot = scx->scx_area.r_ybot;
|
bbox = &use->cu_bbox;
|
||||||
srchRight = scx->scx_area.r_xtop;
|
newScx.scx_use = use;
|
||||||
TITORECT(tile, &tileArea);
|
|
||||||
|
|
||||||
/* Make sure that this tile really does overlap the search area
|
/* If not an array element, life is much simpler */
|
||||||
* (it could be just touching because of the expand-by-one in
|
if (use->cu_xlo == use->cu_xhi && use->cu_ylo == use->cu_yhi)
|
||||||
* DBCellSrArea).
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!GEO_OVERLAP(&tileArea, &scx->scx_area)) return 0;
|
|
||||||
|
|
||||||
for (body = (CellTileBody *) TiGetBody(tile);
|
|
||||||
body != NULL;
|
|
||||||
body = body->ctb_next)
|
|
||||||
{
|
{
|
||||||
use = newScx.scx_use = body->ctb_use;
|
newScx.scx_x = use->cu_xlo, newScx.scx_y = use->cu_yhi;
|
||||||
ASSERT(use != (CellUse *) NULL, "dbCellSrFunc");
|
if (SigInterruptPending) return 1;
|
||||||
|
GEOINVERTTRANS(&use->cu_transform, &tinv);
|
||||||
/* The check below is to ensure that we only enumerate each
|
GeoTransTrans(&use->cu_transform, &scx->scx_trans,
|
||||||
* 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_trans);
|
&newScx.scx_trans);
|
||||||
GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area);
|
GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area);
|
||||||
if ((*fp->tf_func)(&newScx, fp->tf_arg) == 1)
|
if ((*fp->tf_func)(&newScx, fp->tf_arg) == 1)
|
||||||
return 1;
|
return 1;
|
||||||
continue;
|
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) goto skipArray;
|
|
||||||
else if (clientResult == 1) return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
skipArray: 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) return 0;
|
||||||
|
else if (clientResult == 1) return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1179,9 +1168,10 @@ dbCellSrFunc(tile, cxp)
|
||||||
*
|
*
|
||||||
* DBCellEnum --
|
* 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
|
* 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:
|
* The procedure should be of the following form:
|
||||||
* int
|
* int
|
||||||
|
|
@ -1216,7 +1206,7 @@ DBCellEnum(cellDef, func, cdarg)
|
||||||
filter.tf_arg = cdarg;
|
filter.tf_arg = cdarg;
|
||||||
if ((cellDef->cd_flags & CDAVAILABLE) == 0)
|
if ((cellDef->cd_flags & CDAVAILABLE) == 0)
|
||||||
if (!DBCellRead(cellDef, (char *) NULL, TRUE, NULL)) return 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))
|
&TiPlaneRect, dbEnumFunc, (ClientData) &filter))
|
||||||
return 1;
|
return 1;
|
||||||
else return 0;
|
else return 0;
|
||||||
|
|
@ -1228,11 +1218,7 @@ DBCellEnum(cellDef, func, cdarg)
|
||||||
* dbEnumFunc --
|
* dbEnumFunc --
|
||||||
*
|
*
|
||||||
* Filter procedure for DBCellEnum. Applies the procedure given
|
* Filter procedure for DBCellEnum. Applies the procedure given
|
||||||
* to DBCellEnum to any of the CellUses in the tile that are
|
* to DBCellEnum to the visited CellUse.
|
||||||
* enumerable.
|
|
||||||
*
|
|
||||||
* The scheme used for handling overlapping subcells is the same
|
|
||||||
* as used in DBCellSrArea above.
|
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* 0 normally, 1 if abort occurred.
|
* 0 normally, 1 if abort occurred.
|
||||||
|
|
@ -1245,28 +1231,17 @@ DBCellEnum(cellDef, func, cdarg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbEnumFunc(tile, fp)
|
dbEnumFunc(use, fp)
|
||||||
Tile *tile;
|
CellUse *use;
|
||||||
TreeFilter *fp;
|
TreeFilter *fp;
|
||||||
{
|
{
|
||||||
CellUse *use;
|
|
||||||
CellTileBody *body;
|
|
||||||
Rect *bbox;
|
Rect *bbox;
|
||||||
|
|
||||||
for (body = (CellTileBody *) TiGetBody(tile);
|
bbox = &use->cu_bbox;
|
||||||
body != NULL;
|
if ((*fp->tf_func)(use, fp->tf_arg)) return 1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -1594,10 +1569,10 @@ dbTileScaleFunc(tile, scvals)
|
||||||
* DBSrCellUses --
|
* DBSrCellUses --
|
||||||
*
|
*
|
||||||
* Do function "func" for each cell use in cellDef, passing "arg" as
|
* Do function "func" for each cell use in cellDef, passing "arg" as
|
||||||
* client data. Unlike DBEnumCell, this routine first collects a linked
|
* client data. This routine first collects a linked list of cell uses,
|
||||||
* list of cell uses, then performs the function on the list, so that
|
* then performs the function on the list, so that the search cannot be
|
||||||
* the search cannot be corrupted by, removing or reallocating the use
|
* corrupted by (specifically) removing the use structure from the cell
|
||||||
* structure from the cell def. Function "func" takes 2 arguments:
|
* def's bplane. Function "func" takes 2 arguments:
|
||||||
*
|
*
|
||||||
* int func(Celluse *use, ClientData arg) {}
|
* int func(Celluse *use, ClientData arg) {}
|
||||||
*
|
*
|
||||||
|
|
@ -1671,7 +1646,7 @@ dbScaleCell(cellDef, scalen, scaled)
|
||||||
*/
|
*/
|
||||||
int scalen, scaled; /* scale numerator and denominator. */
|
int scalen, scaled; /* scale numerator and denominator. */
|
||||||
{
|
{
|
||||||
int dbCellTileEnumFunc(), dbCellUseEnumFunc();
|
int dbCellScaleFunc(), dbCellUseEnumFunc();
|
||||||
Label *lab;
|
Label *lab;
|
||||||
int pNum;
|
int pNum;
|
||||||
LinkedTile *lhead, *lt;
|
LinkedTile *lhead, *lt;
|
||||||
|
|
@ -1731,31 +1706,13 @@ dbScaleCell(cellDef, scalen, scaled)
|
||||||
lu = lu->cu_next;
|
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 */
|
/* subcell plane, and scale those without reference to the actual cells (so */
|
||||||
/* we don't count the cells multiple times). */
|
/* we don't count the cells multiple times). */
|
||||||
|
|
||||||
lhead = NULL;
|
lhead = NULL;
|
||||||
(void) TiSrArea((Tile *)NULL, cellDef->cd_planes[PL_CELL], &TiPlaneRect,
|
(void) DBSrCellPlaneArea(cellDef->cd_cellPlane, &TiPlaneRect,
|
||||||
dbCellTileEnumFunc, (ClientData) &lhead);
|
dbCellUseEnumFunc, (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(<->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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scale all of the paint tiles in this cell by creating a new plane */
|
/* 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. */
|
/* and copying all tiles into the new plane at scaled dimensions. */
|
||||||
|
|
@ -1810,32 +1767,32 @@ donecell:
|
||||||
DBScalePoint(&cellDef->cd_extended.r_ll, scalen, scaled);
|
DBScalePoint(&cellDef->cd_extended.r_ll, scalen, scaled);
|
||||||
DBScalePoint(&cellDef->cd_extended.r_ur, 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. */
|
||||||
|
|
||||||
/*
|
if ((cellDef->cd_flags & CDFIXEDBBOX) != 0)
|
||||||
* ----------------------------------------------------------------------------
|
{
|
||||||
*
|
Rect r;
|
||||||
* dbCellTileEnumFunc --
|
bool found;
|
||||||
*
|
char *propval;
|
||||||
* Enumeration procedure called on each tile encountered in the search of
|
|
||||||
* the cell plane. Adds the tile to a linked list of tiles.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
propval = (char *)DBPropGet(cellDef, "FIXED_BBOX", &found);
|
||||||
dbCellTileEnumFunc(tile, arg)
|
if (found)
|
||||||
Tile *tile;
|
{
|
||||||
LinkedTile **arg;
|
if (sscanf(propval, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||||
{
|
&r.r_xtop, &r.r_ytop) == 4)
|
||||||
LinkedTile *lt;
|
{
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,25 +131,20 @@ DBCellCopyDefBody(sourceDef, destDef)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SigDisableInterrupts();
|
SigDisableInterrupts();
|
||||||
(void) TiSrArea((Tile *) NULL, destDef->cd_planes[PL_CELL],
|
(void) DBSrCellPlaneArea(destDef->cd_cellPlane,
|
||||||
&TiPlaneRect, dbCopyDefFunc, (ClientData) destDef);
|
&TiPlaneRect, dbCopyDefFunc, (ClientData) destDef);
|
||||||
SigEnableInterrupts();
|
SigEnableInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCopyDefFunc(tile, def)
|
dbCopyDefFunc(use, def)
|
||||||
Tile *tile; /* Tile to search for subcell uses. */
|
CellUse *use; /* Subcell use. */
|
||||||
CellDef *def; /* Set parent pointer in each use to this. */
|
CellDef *def; /* Set parent pointer in each use to this. */
|
||||||
{
|
{
|
||||||
CellTileBody *ctb;
|
use->cu_parent = def;
|
||||||
|
|
||||||
for (ctb = (CellTileBody *) tile->ti_body; ctb != NULL;
|
|
||||||
ctb = ctb->ctb_next)
|
|
||||||
{
|
|
||||||
ctb->ctb_use->cu_parent = def;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
|
|
@ -185,19 +180,8 @@ DBCellClearDef(cellDef)
|
||||||
|
|
||||||
SigDisableInterrupts();
|
SigDisableInterrupts();
|
||||||
|
|
||||||
/*
|
/* Remove all instances from the cell plane */
|
||||||
* We use a simple optimization to avoid trying
|
DBClearCellPlane(cellDef);
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reduce clutter by reinitializing the id hash table */
|
/* Reduce clutter by reinitializing the id hash table */
|
||||||
HashKill(&cellDef->cd_idHash);
|
HashKill(&cellDef->cd_idHash);
|
||||||
|
|
@ -224,41 +208,7 @@ DBCellClearDef(cellDef)
|
||||||
SigEnableInterrupts();
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -647,6 +647,11 @@ dbcUnconnectFunc(tile, clientData)
|
||||||
* when a label is found which is connected to paint belonging to the
|
* when a label is found which is connected to paint belonging to the
|
||||||
* network, it adds it to the destination definition.
|
* 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:
|
* Results:
|
||||||
* Always 0.
|
* Always 0.
|
||||||
*
|
*
|
||||||
|
|
@ -674,10 +679,11 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
|
||||||
GeoTransPointDelta(&scx->scx_trans, &lab->lab_offset, &offset);
|
GeoTransPointDelta(&scx->scx_trans, &lab->lab_offset, &offset);
|
||||||
rotate = GeoTransAngle(&scx->scx_trans, lab->lab_rotate);
|
rotate = GeoTransAngle(&scx->scx_trans, lab->lab_rotate);
|
||||||
|
|
||||||
/* Only add labels if they are on the search top level */
|
/* Do not add any labels to the destination unless they are on */
|
||||||
/* (NOTE: Could add hierachical labels using tpath) */
|
/* 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);
|
DBEraseLabelsByContent(def, &r, -1, lab->lab_text);
|
||||||
DBPutFontLabel(def, &r, lab->lab_font, lab->lab_size, rotate, &offset,
|
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;
|
CellDef *orig_def = scx->scx_use->cu_def;
|
||||||
Label *slab;
|
Label *slab;
|
||||||
int lidx = lab->lab_flags & PORT_NUM_MASK;
|
int lidx = lab->lab_flags & PORT_NUM_MASK;
|
||||||
|
TileTypeBitMask *connectMask;
|
||||||
|
|
||||||
/* Check for equivalent ports. For any found, call */
|
/* Check for equivalent ports. For any found, call */
|
||||||
/* DBTreeSrTiles recursively on the type and area */
|
/* DBTreeSrTiles recursively on the type and area */
|
||||||
/* of the label. */
|
/* 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)
|
for (slab = lab->lab_next; slab != NULL; slab = slab->lab_next)
|
||||||
if ((slab->lab_flags & PORT_DIR_MASK) && (slab != lab))
|
if (slab->lab_flags & PORT_DIR_MASK)
|
||||||
if ((slab->lab_flags & PORT_NUM_MASK) == lidx)
|
if ((slab->lab_flags & PORT_NUM_MASK) == lidx)
|
||||||
{
|
{
|
||||||
SearchContext scx2 = *csa2->csa2_topscx;
|
Rect newarea;
|
||||||
TileTypeBitMask mask;
|
int pNum;
|
||||||
|
|
||||||
// Do NOT go searching on labels connected to space!
|
// Do NOT go searching on labels connected to space!
|
||||||
if (slab->lab_type == TT_SPACE) continue;
|
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.
|
GeoTransRect(&scx->scx_trans, &slab->lab_rect, &newarea);
|
||||||
scx2.scx_area.r_xbot--;
|
|
||||||
scx2.scx_area.r_xtop++;
|
// Avoid infinite looping. If material under the label
|
||||||
scx2.scx_area.r_ybot--;
|
// has already been added to the destination, then ignore.
|
||||||
scx2.scx_area.r_ytop++;
|
|
||||||
DBTreeSrTiles(&scx2, &mask, csa2->csa2_xMask,
|
connectMask = &csa2->csa2_connect[slab->lab_type];
|
||||||
dbcConnectFunc, (ClientData) csa2);
|
|
||||||
|
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;
|
return 0;
|
||||||
|
|
@ -760,7 +808,6 @@ dbcConnectFunc(tile, cx)
|
||||||
TileType loctype = TiGetTypeExact(tile);
|
TileType loctype = TiGetTypeExact(tile);
|
||||||
TileType dinfo = 0;
|
TileType dinfo = 0;
|
||||||
int pNum = cx->tc_plane;
|
int pNum = cx->tc_plane;
|
||||||
unsigned char searchtype;
|
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
|
|
||||||
TiToRect(tile, &tileArea);
|
TiToRect(tile, &tileArea);
|
||||||
|
|
@ -809,34 +856,12 @@ dbcConnectFunc(tile, cx)
|
||||||
|
|
||||||
if (DBIsContact(loctype))
|
if (DBIsContact(loctype))
|
||||||
{
|
{
|
||||||
// TileType ctype;
|
|
||||||
// TileTypeBitMask *cMask, *rMask = DBResidueMask(loctype);
|
|
||||||
|
|
||||||
// TTMaskSetOnlyType(¬ConnectMask, loctype);
|
|
||||||
|
|
||||||
/* Different contact types may share residues (6/18/04) */
|
/* Different contact types may share residues (6/18/04) */
|
||||||
/* Use TTMaskIntersect(), not TTMaskEqual()---types */
|
/* Use TTMaskIntersect(), not TTMaskEqual()---types */
|
||||||
/* which otherwise stack may be in separate cells */
|
/* which otherwise stack may be in separate cells */
|
||||||
/* (12/1/05) */
|
/* (12/1/05) */
|
||||||
|
|
||||||
// for (ctype = TT_TECHDEPBASE; ctype < DBNumUserLayers; ctype++)
|
|
||||||
// {
|
|
||||||
// if (DBIsContact(ctype))
|
|
||||||
// {
|
|
||||||
// cMask = DBResidueMask(ctype);
|
|
||||||
// if (TTMaskIntersect(rMask, cMask))
|
|
||||||
// TTMaskSetType(¬ConnectMask, ctype);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/* The mask of contact types must include all stacked contacts */
|
/* The mask of contact types must include all stacked contacts */
|
||||||
// for (ctype = DBNumUserLayers; ctype < DBNumTypes; ctype++)
|
|
||||||
// {
|
|
||||||
// cMask = DBResidueMask(ctype);
|
|
||||||
// if (TTMaskHasType(cMask, loctype))
|
|
||||||
// TTMaskSetType(¬ConnectMask, ctype);
|
|
||||||
// }
|
|
||||||
// TTMaskCom(¬ConnectMask);
|
|
||||||
|
|
||||||
TTMaskZero(¬ConnectMask);
|
TTMaskZero(¬ConnectMask);
|
||||||
TTMaskSetMask(¬ConnectMask, &DBNotConnectTbl[loctype]);
|
TTMaskSetMask(¬ConnectMask, &DBNotConnectTbl[loctype]);
|
||||||
|
|
@ -864,43 +889,6 @@ dbcConnectFunc(tile, cx)
|
||||||
&newarea, DBStdPaintTbl(loctype, pNum),
|
&newarea, DBStdPaintTbl(loctype, pNum),
|
||||||
(PaintUndoInfo *) NULL);
|
(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,
|
/* Since the whole area of this tile hasn't been recorded,
|
||||||
* we must process its area to find any other tiles that
|
* we must process its area to find any other tiles that
|
||||||
* connect to it. Add each of them to the list of things
|
* 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));
|
newlist = (conSrArea *)mallocMagic(csa2->csa2_size * sizeof(conSrArea));
|
||||||
memcpy((void *)newlist, (void *)csa2->csa2_list,
|
memcpy((void *)newlist, (void *)csa2->csa2_list,
|
||||||
(size_t)lastsize * sizeof(conSrArea));
|
(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);
|
freeMagic((char *)csa2->csa2_list);
|
||||||
csa2->csa2_list = newlist;
|
csa2->csa2_list = newlist;
|
||||||
}
|
}
|
||||||
|
|
@ -1023,6 +1005,7 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, destUse)
|
||||||
struct conSrArg2 csa2;
|
struct conSrArg2 csa2;
|
||||||
TileTypeBitMask *newmask;
|
TileTypeBitMask *newmask;
|
||||||
TileType newtype;
|
TileType newtype;
|
||||||
|
unsigned char searchtype;
|
||||||
|
|
||||||
csa2.csa2_use = destUse;
|
csa2.csa2_use = destUse;
|
||||||
csa2.csa2_xMask = xMask;
|
csa2.csa2_xMask = xMask;
|
||||||
|
|
@ -1052,6 +1035,37 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, destUse)
|
||||||
(ClientData) &csa2);
|
(ClientData) &csa2);
|
||||||
else
|
else
|
||||||
DBTreeSrTiles(scx, newmask, xMask, dbcConnectFunc, (ClientData) &csa2);
|
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);
|
freeMagic((char *)csa2.csa2_list);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1584,17 +1584,17 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
|
||||||
if (!strcmp(propertyname, "GDS_FILE"))
|
if (!strcmp(propertyname, "GDS_FILE"))
|
||||||
cellDef->cd_flags |= CDVENDORGDS;
|
cellDef->cd_flags |= CDVENDORGDS;
|
||||||
|
|
||||||
/* Also process FIXED_BBOX property, but do not keep */
|
/* Also process FIXED_BBOX property, as units must match */
|
||||||
/* the property, as it should be regenerated on cell */
|
|
||||||
/* output from the current scale. */
|
|
||||||
|
|
||||||
if (!strcmp(propertyname, "FIXED_BBOX"))
|
if (!strcmp(propertyname, "FIXED_BBOX"))
|
||||||
{
|
{
|
||||||
|
Rect locbbox;
|
||||||
|
|
||||||
if (sscanf(propertyvalue, "%d %d %d %d",
|
if (sscanf(propertyvalue, "%d %d %d %d",
|
||||||
&(cellDef->cd_bbox.r_xbot),
|
&(locbbox.r_xbot),
|
||||||
&(cellDef->cd_bbox.r_ybot),
|
&(locbbox.r_ybot),
|
||||||
&(cellDef->cd_bbox.r_xtop),
|
&(locbbox.r_xtop),
|
||||||
&(cellDef->cd_bbox.r_ytop)) != 4)
|
&(locbbox.r_ytop)) != 4)
|
||||||
{
|
{
|
||||||
TxError("Cannot read bounding box values in %s property",
|
TxError("Cannot read bounding box values in %s property",
|
||||||
propertyname);
|
propertyname);
|
||||||
|
|
@ -1605,20 +1605,24 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled)
|
||||||
{
|
{
|
||||||
if (scalen > 1)
|
if (scalen > 1)
|
||||||
{
|
{
|
||||||
cellDef->cd_bbox.r_xbot *= scalen;
|
locbbox.r_xbot *= scalen;
|
||||||
cellDef->cd_bbox.r_ybot *= scalen;
|
locbbox.r_ybot *= scalen;
|
||||||
cellDef->cd_bbox.r_xtop *= scalen;
|
locbbox.r_xtop *= scalen;
|
||||||
cellDef->cd_bbox.r_ytop *= scalen;
|
locbbox.r_ytop *= scalen;
|
||||||
}
|
}
|
||||||
if (scaled > 1)
|
if (scaled > 1)
|
||||||
{
|
{
|
||||||
cellDef->cd_bbox.r_xbot /= scaled;
|
locbbox.r_xbot /= scaled;
|
||||||
cellDef->cd_bbox.r_ybot /= scaled;
|
locbbox.r_ybot /= scaled;
|
||||||
cellDef->cd_bbox.r_xtop /= scaled;
|
locbbox.r_xtop /= scaled;
|
||||||
cellDef->cd_bbox.r_ytop /= scaled;
|
locbbox.r_ytop /= scaled;
|
||||||
}
|
}
|
||||||
cellDef->cd_extended = cellDef->cd_bbox;
|
|
||||||
cellDef->cd_flags |= CDFIXEDBBOX;
|
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
|
else
|
||||||
|
|
@ -2538,27 +2542,6 @@ DBCellWriteFile(cellDef, f)
|
||||||
DBPropEnum(cellDef, dbWritePropFunc, (ClientData)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");
|
FPRINTF(f, "<< end >>\n");
|
||||||
|
|
||||||
if (fflush(f) == EOF || ferror(f))
|
if (fflush(f) == EOF || ferror(f))
|
||||||
|
|
|
||||||
|
|
@ -765,13 +765,13 @@ DBTechFinalContact()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the masks of planes on which each type appears.
|
* 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
|
* the home plane for each type up to DBNumTypes, and no
|
||||||
* planes for undefined types. Also update the mask of
|
* planes for undefined types. Also update the mask of
|
||||||
* types visible on each plane.
|
* types visible on each plane.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DBTypePlaneMaskTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_CELL));
|
DBTypePlaneMaskTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_ROUTER));
|
||||||
for (primaryType = 0; primaryType < DBNumTypes; primaryType++)
|
for (primaryType = 0; primaryType < DBNumTypes; primaryType++)
|
||||||
{
|
{
|
||||||
pNum = DBPlane(primaryType);
|
pNum = DBPlane(primaryType);
|
||||||
|
|
|
||||||
|
|
@ -393,8 +393,8 @@ DBTechTypesToPlanes(mask)
|
||||||
TileType t;
|
TileType t;
|
||||||
PlaneMask planeMask, noCellMask, retMask;
|
PlaneMask planeMask, noCellMask, retMask;
|
||||||
|
|
||||||
/* Space tiles are present in all planes but the cell plane */
|
/* Space tiles are present in all planes but the router plane */
|
||||||
noCellMask = ~(PlaneNumToMaskBit(PL_CELL));
|
noCellMask = ~(PlaneNumToMaskBit(PL_ROUTER));
|
||||||
if (TTMaskHasType(mask, TT_SPACE)) {
|
if (TTMaskHasType(mask, TT_SPACE)) {
|
||||||
retMask = PlaneNumToMaskBit(DBNumPlanes) - 1;
|
retMask = PlaneNumToMaskBit(DBNumPlanes) - 1;
|
||||||
retMask &= noCellMask;
|
retMask &= noCellMask;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ TileTypeBitMask DBTechActiveLayerBits; /* Layers marked locked in the techfile *
|
||||||
/* Table of default, builtin planes */
|
/* Table of default, builtin planes */
|
||||||
DefaultPlane dbTechDefaultPlanes[] =
|
DefaultPlane dbTechDefaultPlanes[] =
|
||||||
{
|
{
|
||||||
PL_CELL, "subcell",
|
PL_ROUTER, "router",
|
||||||
PL_DRC_ERROR, "designRuleError",
|
PL_DRC_ERROR, "designRuleError",
|
||||||
PL_DRC_CHECK, "designRuleCheck",
|
PL_DRC_CHECK, "designRuleCheck",
|
||||||
PL_M_HINT, "mhint",
|
PL_M_HINT, "mhint",
|
||||||
|
|
@ -584,8 +584,8 @@ DBTechFinalType()
|
||||||
TTMaskZero(&DBTechActiveLayerBits);
|
TTMaskZero(&DBTechActiveLayerBits);
|
||||||
TTMaskSetMask(&DBTechActiveLayerBits, &DBActiveLayerBits);
|
TTMaskSetMask(&DBTechActiveLayerBits, &DBActiveLayerBits);
|
||||||
|
|
||||||
/* Space is visible on all planes but the subcell plane */
|
/* Space is visible on all planes except the router */
|
||||||
TTMaskZero(&DBPlaneTypes[PL_CELL]);
|
TTMaskZero(&DBPlaneTypes[PL_ROUTER]);
|
||||||
for (pNum = PL_PAINTBASE; pNum < PL_MAXTYPES; pNum++)
|
for (pNum = PL_PAINTBASE; pNum < PL_MAXTYPES; pNum++)
|
||||||
TTMaskSetOnlyType(&DBPlaneTypes[pNum], TT_SPACE);
|
TTMaskSetOnlyType(&DBPlaneTypes[pNum], TT_SPACE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -334,9 +334,6 @@ enum_next:
|
||||||
*
|
*
|
||||||
* NOTE:
|
* NOTE:
|
||||||
*
|
*
|
||||||
* THIS IS THE PREFERRED WAY TO FIND ALL TILES IN A GIVEN AREA;
|
|
||||||
* TiSrArea IS OBSOLETE FOR ALL BUT THE SUBCELL PLANE.
|
|
||||||
*
|
|
||||||
* Results:
|
* Results:
|
||||||
* 0 is returned if the search completed normally. 1 is returned
|
* 0 is returned if the search completed normally. 1 is returned
|
||||||
* if it aborted.
|
* if it aborted.
|
||||||
|
|
@ -786,15 +783,10 @@ enumerate:
|
||||||
/*
|
/*
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* DBFreeCellPlane --
|
* DBClearCellPlane --
|
||||||
*
|
*
|
||||||
* Deallocate all tiles in the cell tile plane of a given CellDef.
|
* Removes all CellUses from a def's cell plane. Does not remove the
|
||||||
* Also deallocates the lists of CellTileBodies and their associated
|
* cell plane itself.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
|
|
@ -806,54 +798,40 @@ enumerate:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
DBFreeCellPlane(plane)
|
DBClearCellPlane(def)
|
||||||
Plane *plane; /* Plane whose storage is to be freed */
|
CellDef *def;
|
||||||
{
|
{
|
||||||
int dbFreeCellFunc();
|
int dbDeleteCellUse(); /* Forward reference */
|
||||||
|
|
||||||
/* Don't let this search be interrupted. */
|
/* Don't let this search be interrupted. */
|
||||||
|
|
||||||
SigDisableInterrupts();
|
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();
|
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
|
* dbDeleteCellUse ---
|
||||||
* label list are both deallocated along with the tile itself.
|
*
|
||||||
|
* Callback function from DBSrCellUses, calls BPDelete to remove a
|
||||||
|
* cell use from the cell plane
|
||||||
|
*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int dbDeleteCellUse(CellUse *use, ClientData arg)
|
||||||
dbFreeCellFunc(tile)
|
|
||||||
Tile *tile;
|
|
||||||
{
|
{
|
||||||
CellTileBody *body;
|
dbInstanceUnplace(use);
|
||||||
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);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -147,12 +147,9 @@ DBFixMismatch()
|
||||||
* the uses.
|
* 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;
|
||||||
cellDef->cd_bbox.r_xtop = cellDef->cd_bbox.r_xbot - 1;
|
DBReComputeBbox(cellDef);
|
||||||
cellDef->cd_extended.r_xtop = cellDef->cd_extended.r_xbot - 1;
|
|
||||||
DBReComputeBbox(cellDef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now, for each parent, recheck the parent in both the
|
/* Now, for each parent, recheck the parent in both the
|
||||||
* old area of the child and the new area.
|
* old area of the child and the new area.
|
||||||
|
|
|
||||||
|
|
@ -149,9 +149,9 @@ dbTechPaintErasePlanes()
|
||||||
TileType t, s;
|
TileType t, s;
|
||||||
int pNum;
|
int pNum;
|
||||||
|
|
||||||
/* Space tiles are special: they may appear on any plane */
|
/* Space tiles are special: they may appear on any plane except router */
|
||||||
DBTypePaintPlanesTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_CELL));
|
DBTypePaintPlanesTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_ROUTER));
|
||||||
DBTypeErasePlanesTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_CELL));
|
DBTypeErasePlanesTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_ROUTER));
|
||||||
|
|
||||||
/* Skip TT_SPACE */
|
/* Skip TT_SPACE */
|
||||||
for (t = 1; t < DBNumTypes; t++)
|
for (t = 1; t < DBNumTypes; t++)
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@
|
||||||
#include "utils/hash.h"
|
#include "utils/hash.h"
|
||||||
#endif /* _HASH_H */
|
#endif /* _HASH_H */
|
||||||
|
|
||||||
|
#ifndef _BPLANE_H
|
||||||
|
#include "bplane/bplane.h"
|
||||||
|
#endif /* _BPLANE_H */
|
||||||
|
|
||||||
/* ----------------------- Tunable constants -------------------------- */
|
/* ----------------------- Tunable constants -------------------------- */
|
||||||
|
|
||||||
#define MAXPLANES 64 /* Maximum number of planes per cell */
|
#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_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_CHECK 1 /* DRC plane for CHECK tiles */
|
||||||
#define PL_DRC_ERROR 2 /* DRC plane for ERROR tiles */
|
#define PL_DRC_ERROR 2 /* DRC plane for ERROR tiles */
|
||||||
#define PL_M_HINT 3 /* magnet hints for irouter */
|
#define PL_M_HINT 3 /* magnet hints for irouter */
|
||||||
|
|
@ -325,6 +329,7 @@ typedef struct celldef
|
||||||
#endif
|
#endif
|
||||||
char *cd_name; /* Name of cell */
|
char *cd_name; /* Name of cell */
|
||||||
struct celluse *cd_parents; /* NULL-terminated list of all uses */
|
struct celluse *cd_parents; /* NULL-terminated list of all uses */
|
||||||
|
BPlane *cd_cellPlane; /* Instance locations */
|
||||||
Plane *cd_planes[MAXPLANES]; /* Tiles */
|
Plane *cd_planes[MAXPLANES]; /* Tiles */
|
||||||
ClientData cd_client; /* This space for rent */
|
ClientData cd_client; /* This space for rent */
|
||||||
int cd_timestamp; /* Unique integer identifying last
|
int cd_timestamp; /* Unique integer identifying last
|
||||||
|
|
@ -461,6 +466,17 @@ typedef struct
|
||||||
|
|
||||||
typedef struct celluse
|
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
|
unsigned int cu_expandMask; /* Mask of windows in which this use
|
||||||
* is expanded.
|
* is expanded.
|
||||||
*/
|
*/
|
||||||
|
|
@ -473,13 +489,6 @@ typedef struct celluse
|
||||||
* or NULL for end of list.
|
* or NULL for end of list.
|
||||||
*/
|
*/
|
||||||
CellDef *cu_parent; /* Cell def containing this use */
|
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 */
|
ClientData cu_client; /* This space for rent */
|
||||||
} CellUse;
|
} CellUse;
|
||||||
|
|
||||||
|
|
@ -521,20 +530,6 @@ typedef struct celluse
|
||||||
#define CU_DESCEND_NO_LOCK 0x0007 /* Descend unlocked subcells only */
|
#define CU_DESCEND_NO_LOCK 0x0007 /* Descend unlocked subcells only */
|
||||||
#define CU_DESCEND_NONE 0x0009 /* Descend no subcells */
|
#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
|
* Declare tile type structure for non-manhattan geometry
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ DBWredisplay(w, rootArea, clipArea)
|
||||||
GrLock(w, TRUE);
|
GrLock(w, TRUE);
|
||||||
|
|
||||||
/* Round up the redisplay area by 1 pixel on all sides. This
|
/* 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
|
* the area without overlapping it. Without the round-up, there
|
||||||
* will be occasional (in fact, frequent), one-pixel wide slivers.
|
* will be occasional (in fact, frequent), one-pixel wide slivers.
|
||||||
*/
|
*/
|
||||||
|
|
@ -516,9 +516,9 @@ DBWredisplay(w, rootArea, clipArea)
|
||||||
dbwWatchTrans = crec->dbw_watchTrans;
|
dbwWatchTrans = crec->dbw_watchTrans;
|
||||||
dbwWatchDemo = ((crec->dbw_flags & DBW_WATCHDEMO) != 0);
|
dbwWatchDemo = ((crec->dbw_flags & DBW_WATCHDEMO) != 0);
|
||||||
dbwSeeTypes = ((crec->dbw_flags & DBW_SEETYPES) != 0);
|
dbwSeeTypes = ((crec->dbw_flags & DBW_SEETYPES) != 0);
|
||||||
(void) TiSrArea((Tile *) NULL,
|
(void) DBSrPaintArea((Tile *) NULL,
|
||||||
crec->dbw_watchDef->cd_planes[crec->dbw_watchPlane],
|
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
|
/* Record information so that the highlight manager will redisplay
|
||||||
|
|
@ -1114,7 +1114,7 @@ dbwTileFunc(tile)
|
||||||
GrPutText(string, STYLE_DRAWTILE, &p, GEO_CENTER,
|
GrPutText(string, STYLE_DRAWTILE, &p, GEO_CENTER,
|
||||||
GR_TEXT_LARGE, FALSE, &r2, (Rect *) NULL);
|
GR_TEXT_LARGE, FALSE, &r2, (Rect *) NULL);
|
||||||
|
|
||||||
#define OFFSET 12
|
#define XYOFFSET 12
|
||||||
|
|
||||||
for (i=0; i<4; i++)
|
for (i=0; i<4; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -1125,25 +1125,25 @@ dbwTileFunc(tile)
|
||||||
case 0:
|
case 0:
|
||||||
stitch = BL(tile);
|
stitch = BL(tile);
|
||||||
p = pLL;
|
p = pLL;
|
||||||
yoffset = OFFSET;
|
yoffset = XYOFFSET;
|
||||||
pos = GEO_NORTHEAST;
|
pos = GEO_NORTHEAST;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
stitch = LB(tile);
|
stitch = LB(tile);
|
||||||
p = pLL;
|
p = pLL;
|
||||||
xoffset = OFFSET;
|
xoffset = XYOFFSET;
|
||||||
pos = GEO_NORTHEAST;
|
pos = GEO_NORTHEAST;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
stitch = RT(tile);
|
stitch = RT(tile);
|
||||||
p = pUR;
|
p = pUR;
|
||||||
xoffset = -OFFSET;
|
xoffset = -XYOFFSET;
|
||||||
pos = GEO_SOUTHWEST;
|
pos = GEO_SOUTHWEST;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
stitch = TR(tile);
|
stitch = TR(tile);
|
||||||
p = pUR;
|
p = pUR;
|
||||||
yoffset = -OFFSET;
|
yoffset = -XYOFFSET;
|
||||||
pos = GEO_SOUTHWEST;
|
pos = GEO_SOUTHWEST;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
104
drc/DRCsubcell.c
104
drc/DRCsubcell.c
|
|
@ -43,9 +43,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
static Rect drcSubIntArea; /* Accumulates area of interactions. */
|
static Rect drcSubIntArea; /* Accumulates area of interactions. */
|
||||||
static CellDef *drcSubDef; /* Cell definition we're checking. */
|
static CellDef *drcSubDef; /* Cell definition we're checking. */
|
||||||
static int drcSubRadius; /* Interaction radius. */
|
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 Rect drcSubLookArea; /* Area where we're looking for interactions */
|
||||||
static void (*drcSubFunc)(); /* Error function. */
|
static void (*drcSubFunc)(); /* Error function. */
|
||||||
static ClientData drcSubClientData;
|
static ClientData drcSubClientData;
|
||||||
|
|
@ -69,52 +66,10 @@ extern int DRCErrorType;
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* drcFindOtherCells --
|
* drcSubcellFunc --
|
||||||
*
|
*
|
||||||
* This is a search function invoked when looking around a given
|
* Called by DBSrCellPlaneArea when looking for interactions in
|
||||||
* cell for interactions. If a tile is found other than drcCurSub,
|
* a given area. It sees if this subcell participates
|
||||||
* 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
|
|
||||||
* in any interactions in the area we're rechecking.
|
* in any interactions in the area we're rechecking.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
|
|
@ -128,36 +83,23 @@ drcFindOtherCells(tile, area)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcSubcellTileFunc(tile, propagate)
|
drcSubcellFunc(subUse, propagate)
|
||||||
Tile *tile; /* Subcell tile. */
|
CellUse *subUse; /* Subcell instance. */
|
||||||
bool *propagate; /* Errors to propagate up */
|
bool *propagate; /* Errors to propagate up */
|
||||||
{
|
{
|
||||||
Rect area, haloArea, intArea, subIntArea, locIntArea;
|
Rect area, haloArea, intArea, subIntArea, locIntArea;
|
||||||
int i;
|
int i;
|
||||||
CellTileBody *ctbptr = (CellTileBody *) tile->ti_body;
|
|
||||||
CellUse *subUse;
|
|
||||||
|
|
||||||
if (ctbptr == NULL) return 0;
|
|
||||||
|
|
||||||
/* To determine interactions, find the bounding box of
|
/* To determine interactions, find the bounding box of
|
||||||
* all paint and other subcells within one halo of this
|
* 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).
|
* we're recomputing errors).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* XXX This is not right---the area of the cell plane tile is not */
|
area = subUse->cu_bbox;
|
||||||
/* the area of the subcell. */
|
|
||||||
/* TiToRect(tile, &area); */
|
|
||||||
|
|
||||||
for (ctbptr = (CellTileBody *) TiGetBody(tile); ctbptr != NULL;
|
GEO_EXPAND(&area, drcSubRadius, &haloArea);
|
||||||
ctbptr = ctbptr->ctb_next)
|
GeoClip(&haloArea, &drcSubLookArea);
|
||||||
{
|
|
||||||
subUse = ctbptr->ctb_use;
|
|
||||||
area = subUse->cu_bbox;
|
|
||||||
|
|
||||||
GEO_EXPAND(&area, drcSubRadius, &haloArea);
|
|
||||||
GeoClip(&haloArea, &drcSubLookArea);
|
|
||||||
}
|
|
||||||
|
|
||||||
intArea = GeoNullRect;
|
intArea = GeoNullRect;
|
||||||
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
||||||
|
|
@ -171,28 +113,14 @@ drcSubcellTileFunc(tile, propagate)
|
||||||
/* interaction area of the parent. Ultimately this is recursive as */
|
/* interaction area of the parent. Ultimately this is recursive as */
|
||||||
/* all cells are checked and errors propagate to the top level. */
|
/* all cells are checked and errors propagate to the top level. */
|
||||||
|
|
||||||
/* XXX */
|
subIntArea = GeoNullRect;
|
||||||
for (ctbptr = (CellTileBody *) TiGetBody(tile); ctbptr != NULL;
|
DBSrPaintArea((Tile *) NULL, subUse->cu_def->cd_planes[PL_DRC_ERROR],
|
||||||
ctbptr = ctbptr->ctb_next)
|
|
||||||
{
|
|
||||||
subUse = ctbptr->ctb_use;
|
|
||||||
subIntArea = GeoNullRect;
|
|
||||||
DBSrPaintArea((Tile *) NULL, subUse->cu_def->cd_planes[PL_DRC_ERROR],
|
|
||||||
&TiPlaneRect, &DBAllButSpaceBits, drcIncludeArea,
|
&TiPlaneRect, &DBAllButSpaceBits, drcIncludeArea,
|
||||||
(ClientData) &subIntArea);
|
(ClientData) &subIntArea);
|
||||||
GeoTransRect(&(subUse->cu_transform), &subIntArea, &locIntArea);
|
|
||||||
GeoInclude(&locIntArea, &intArea);
|
|
||||||
if (!GEO_RECTNULL(&subIntArea)) *propagate = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
drcCurSub = ctbptr;
|
GeoTransRect(&(subUse->cu_transform), &subIntArea, &locIntArea);
|
||||||
(void) TiSrArea((Tile *) NULL, drcSubDef->cd_planes[PL_CELL],
|
GeoInclude(&locIntArea, &intArea);
|
||||||
&haloArea, drcFindOtherCells, (ClientData) &intArea);
|
if (!GEO_RECTNULL(&subIntArea)) *propagate = TRUE;
|
||||||
if (GEO_RECTNULL(&intArea)) return 0;
|
|
||||||
|
|
||||||
GEO_EXPAND(&intArea, drcSubRadius, &intArea);
|
|
||||||
GeoClip(&intArea, &haloArea);
|
|
||||||
(void) GeoInclude(&intArea, &drcSubIntArea);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -330,8 +258,8 @@ DRCFindInteractions(def, area, radius, interaction)
|
||||||
drcSubIntArea = GeoNullRect;
|
drcSubIntArea = GeoNullRect;
|
||||||
GEO_EXPAND(area, radius, &drcSubLookArea);
|
GEO_EXPAND(area, radius, &drcSubLookArea);
|
||||||
propagate = FALSE;
|
propagate = FALSE;
|
||||||
(void) TiSrArea((Tile *) NULL, def->cd_planes[PL_CELL],
|
(void) DBSrCellPlaneArea(def->cd_cellPlane, &drcSubLookArea,
|
||||||
&drcSubLookArea, drcSubcellTileFunc, (ClientData)(&propagate));
|
drcSubcellFunc, (ClientData)(&propagate));
|
||||||
|
|
||||||
/* If there seems to be an interaction area, make a second pass
|
/* 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
|
* to make sure there's more than one cell with paint in the
|
||||||
|
|
|
||||||
|
|
@ -1552,8 +1552,7 @@ esMakePorts(hc, cdata)
|
||||||
char *name, *portname, *tptr, *aptr, *locname;
|
char *name, *portname, *tptr, *aptr, *locname;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
/* Done when the bottom of the hierarchy is reached */
|
if (def->def_uses == NULL) return 0; /* Bottom of hierarchy */
|
||||||
if (HashGetNumEntries(&def->def_uses) == 0) return 0;
|
|
||||||
|
|
||||||
for (conn = (Connection *)def->def_conns; conn; conn = conn->conn_next)
|
for (conn = (Connection *)def->def_conns; conn; conn = conn->conn_next)
|
||||||
{
|
{
|
||||||
|
|
@ -1580,11 +1579,13 @@ esMakePorts(hc, cdata)
|
||||||
|
|
||||||
// Find the cell for the instance
|
// Find the cell for the instance
|
||||||
portdef = NULL;
|
portdef = NULL;
|
||||||
he = HashFind(&updef->def_uses, portname);
|
for (use = updef->def_uses; use; use = use->use_next)
|
||||||
if (he != NULL)
|
|
||||||
{
|
{
|
||||||
use = (Use *)HashGetValue(he);
|
if (!strcmp(use->use_id, portname))
|
||||||
portdef = use->use_def;
|
{
|
||||||
|
portdef = use->use_def;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((aptr == NULL) || (aptr > tptr))
|
if ((aptr == NULL) || (aptr > tptr))
|
||||||
*tptr = '/';
|
*tptr = '/';
|
||||||
|
|
@ -1659,11 +1660,13 @@ esMakePorts(hc, cdata)
|
||||||
|
|
||||||
// Find the cell for the instance
|
// Find the cell for the instance
|
||||||
portdef = NULL;
|
portdef = NULL;
|
||||||
he = HashFind(&updef->def_uses, portname);
|
for (use = updef->def_uses; use; use = use->use_next)
|
||||||
if (he != NULL)
|
|
||||||
{
|
{
|
||||||
use = (Use *)HashGetValue(he);
|
if (!strcmp(use->use_id, portname))
|
||||||
portdef = use->use_def;
|
{
|
||||||
|
portdef = use->use_def;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((aptr == NULL) || (aptr > tptr))
|
if ((aptr == NULL) || (aptr > tptr))
|
||||||
*tptr = '/';
|
*tptr = '/';
|
||||||
|
|
@ -1744,7 +1747,7 @@ esHierVisit(hc, cdata)
|
||||||
|
|
||||||
if (def != topdef)
|
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)
|
if (locDoSubckt == AUTO)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2061,7 +2061,7 @@ extOutputDevices(def, transList, outFile)
|
||||||
|
|
||||||
if (ExtCurStyle->exts_deviceClass[t] == DEV_RSUBCKT)
|
if (ExtCurStyle->exts_deviceClass[t] == DEV_RSUBCKT)
|
||||||
{
|
{
|
||||||
/* nothing */
|
/* (Nothing) */
|
||||||
}
|
}
|
||||||
else if (hasModel) /* SPICE semiconductor resistor */
|
else if (hasModel) /* SPICE semiconductor resistor */
|
||||||
{
|
{
|
||||||
|
|
@ -2079,7 +2079,6 @@ extOutputDevices(def, transList, outFile)
|
||||||
fprintf(outFile, " \"%s\"", (subsName == NULL) ?
|
fprintf(outFile, " \"%s\"", (subsName == NULL) ?
|
||||||
"None" : subsName);
|
"None" : subsName);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_CAP:
|
case DEV_CAP:
|
||||||
|
|
@ -2145,7 +2144,7 @@ extOutputDevices(def, transList, outFile)
|
||||||
|
|
||||||
if (ExtCurStyle->exts_deviceClass[t] == DEV_CSUBCKT)
|
if (ExtCurStyle->exts_deviceClass[t] == DEV_CSUBCKT)
|
||||||
{
|
{
|
||||||
/* (Nothing) */
|
/* (Nothing) */
|
||||||
}
|
}
|
||||||
else /* SPICE semiconductor resistor */
|
else /* SPICE semiconductor resistor */
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ ExtFindInteractions(def, halo, bloatby, resultPlane)
|
||||||
* not including, the subtree under consideration.
|
* not including, the subtree under consideration.
|
||||||
*/
|
*/
|
||||||
extInterUse = (CellUse *) NULL;
|
extInterUse = (CellUse *) NULL;
|
||||||
(void) extCellSrArea(&scx, extInterSubtree, (ClientData) NULL);
|
(void) DBCellSrArea(&scx, extInterSubtree, (ClientData) NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process parent paint if there were any subcells.
|
* Process parent paint if there were any subcells.
|
||||||
|
|
@ -123,7 +123,7 @@ ExtFindInteractions(def, halo, bloatby, resultPlane)
|
||||||
if (extInterUse)
|
if (extInterUse)
|
||||||
{
|
{
|
||||||
extInterUse = (CellUse *) NULL;
|
extInterUse = (CellUse *) NULL;
|
||||||
(void) extCellSrArea(&scx, extInterSubtreePaint, (ClientData) def);
|
(void) DBCellSrArea(&scx, extInterSubtreePaint, (ClientData) def);
|
||||||
}
|
}
|
||||||
UndoEnable();
|
UndoEnable();
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +179,7 @@ extInterSubtree(scx)
|
||||||
BLOATBY(&parentScx.scx_area, extInterHalo);
|
BLOATBY(&parentScx.scx_area, extInterHalo);
|
||||||
parentScx.scx_trans = GeoIdentityTransform;
|
parentScx.scx_trans = GeoIdentityTransform;
|
||||||
parentScx.scx_use = extParentUse;
|
parentScx.scx_use = extParentUse;
|
||||||
(void) extCellSrArea(&parentScx, extInterSubtreeClip, (ClientData) scx);
|
(void) DBCellSrArea(&parentScx, extInterSubtreeClip, (ClientData) scx);
|
||||||
}
|
}
|
||||||
return (2);
|
return (2);
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +286,7 @@ extInterSubtreeTile(tile, cxp)
|
||||||
else newscx.scx_area = r;
|
else newscx.scx_area = r;
|
||||||
newscx.scx_trans = GeoIdentityTransform;
|
newscx.scx_trans = GeoIdentityTransform;
|
||||||
newscx.scx_use = extParentUse;
|
newscx.scx_use = extParentUse;
|
||||||
(void) extCellSrArea(&newscx, extInterOverlapSubtree, (ClientData) NULL);
|
(void) DBCellSrArea(&newscx, extInterOverlapSubtree, (ClientData) NULL);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -394,7 +394,7 @@ extInterOverlapTile(tile, cxp)
|
||||||
*
|
*
|
||||||
* The client procedure should not modify any of the paint planes in
|
* The client procedure should not modify any of the paint planes in
|
||||||
* the cells visited by extTreeSrTiles, because we use DBSrPaintArea
|
* 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:
|
* Results:
|
||||||
* 0 is returned if the search finished normally. 1 is returned
|
* 0 is returned if the search finished normally. 1 is returned
|
||||||
|
|
@ -442,7 +442,7 @@ extTreeSrPaintArea(scx, func, cdarg)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
/* Visit our children recursively */
|
/* 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);
|
return (1);
|
||||||
|
|
||||||
/* Visit our children recursively */
|
/* 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);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -475,7 +475,7 @@ extContainsGeometry(def, allButUse, area)
|
||||||
bool extContainsCellFunc();
|
bool extContainsCellFunc();
|
||||||
int pNum;
|
int pNum;
|
||||||
|
|
||||||
if (TiSrArea((Tile *) NULL, def->cd_planes[PL_CELL], area,
|
if (DBSrCellPlaneArea(def->cd_cellPlane, area,
|
||||||
extContainsCellFunc, (ClientData) allButUse))
|
extContainsCellFunc, (ClientData) allButUse))
|
||||||
return (TRUE);
|
return (TRUE);
|
||||||
|
|
||||||
|
|
@ -489,17 +489,11 @@ extContainsGeometry(def, allButUse, area)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
extContainsCellFunc(tile, allButUse)
|
extContainsCellFunc(use, allButUse)
|
||||||
Tile *tile;
|
CellUse *use;
|
||||||
CellUse *allButUse;
|
CellUse *allButUse;
|
||||||
{
|
{
|
||||||
CellTileBody *ctb;
|
return (use != allButUse) ? TRUE : FALSE;
|
||||||
|
|
||||||
for (ctb = (CellTileBody *) TiGetBody(tile); ctb; ctb = ctb->ctb_next)
|
|
||||||
if (ctb->ctb_use != allButUse)
|
|
||||||
return (TRUE);
|
|
||||||
|
|
||||||
return (FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
|
|
||||||
#include "tcltk/tclmagic.h"
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "utils/geofast.h"
|
#include "utils/geofast.h"
|
||||||
#include "tiles/tile.h"
|
#include "tiles/tile.h"
|
||||||
|
|
@ -175,10 +176,10 @@ extSubtree(parentUse, reg, f)
|
||||||
* halo has been set above to reflect the maximum distance for
|
* halo has been set above to reflect the maximum distance for
|
||||||
* sidewall coupling capacitance).
|
* sidewall coupling capacitance).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
b = &def->cd_bbox;
|
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)
|
totcuts = (b->r_ytop - b->r_ybot + ExtCurStyle->exts_stepSize - 1)
|
||||||
/ ExtCurStyle->exts_stepSize;
|
/ ExtCurStyle->exts_stepSize;
|
||||||
totcuts *= ((b->r_xtop - b->r_xbot + ExtCurStyle->exts_stepSize - 1)
|
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. */
|
/* even if there were no other interactions found. */
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
|
|
||||||
GEOCLIP(&ha.ha_clipArea, &r);
|
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
scx.scx_area = r;
|
scx.scx_area = r;
|
||||||
scx.scx_use = ha.ha_parentUse;
|
scx.scx_use = ha.ha_parentUse;
|
||||||
|
|
@ -243,8 +243,8 @@ extSubtree(parentUse, reg, f)
|
||||||
cuts++;
|
cuts++;
|
||||||
pdone = 100.0 * ((float)cuts / (float)totcuts);
|
pdone = 100.0 * ((float)cuts / (float)totcuts);
|
||||||
if ((((pdone - plast) > 5.0) || (cuts == totcuts)) && (cuts > 1)) {
|
if ((((pdone - plast) > 5.0) || (cuts == totcuts)) && (cuts > 1)) {
|
||||||
TxPrintf("Completed %d%%\n", (int)(pdone + 0.5));
|
TxPrintf("Completed %d%%\n", (int)(pdone + 0.5));
|
||||||
plast = pdone;
|
plast = pdone;
|
||||||
TxFlushOut();
|
TxFlushOut();
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
|
|
|
||||||
|
|
@ -2854,14 +2854,14 @@ zinit:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If global variable "doConvert" is TRUE, then we convert from */
|
/* If global variable "doConvert" is TRUE, then we convert from */
|
||||||
/* microns to lambda and microns^2 to lambda^2, based on the */
|
/* microns to lambda and microns^2 to lambda^2. */
|
||||||
/* current value of DBLambda and output scale. */
|
|
||||||
|
|
||||||
if (doConvert)
|
if (doConvert)
|
||||||
{
|
{
|
||||||
/* Convert from micron units in the file to the current */
|
/* Use current CIF output scale for determining the scale */
|
||||||
/* physical scalefactor as determined by the default CIF */
|
/* factor between micron units in the extract section and */
|
||||||
/* output scale. */
|
/* lambda units of the database (conversion from lambda to */
|
||||||
|
/* internal units is done separately). */
|
||||||
|
|
||||||
float dscale = CIFGetOutputScale(1000);
|
float dscale = CIFGetOutputScale(1000);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -577,7 +577,7 @@ DefReadLocation(use, f, oscale, tptr)
|
||||||
float oscale;
|
float oscale;
|
||||||
Transform *tptr;
|
Transform *tptr;
|
||||||
{
|
{
|
||||||
Rect *r, tr;
|
Rect *r, tr, rect;
|
||||||
int keyword;
|
int keyword;
|
||||||
char *token;
|
char *token;
|
||||||
float x, y;
|
float x, y;
|
||||||
|
|
@ -611,7 +611,25 @@ DefReadLocation(use, f, oscale, tptr)
|
||||||
/* restore the lower-left corner position. */
|
/* restore the lower-left corner position. */
|
||||||
|
|
||||||
if (use)
|
if (use)
|
||||||
|
{
|
||||||
r = &use->cu_def->cd_bbox;
|
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 = ▭
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
r = &GeoNullRect;
|
r = &GeoNullRect;
|
||||||
|
|
||||||
|
|
@ -805,9 +823,9 @@ DefReadPins(f, rootDef, sname, oscale, total)
|
||||||
currect = LefReadRect(f, curlayer, oscale);
|
currect = LefReadRect(f, curlayer, oscale);
|
||||||
if (pending)
|
if (pending)
|
||||||
{
|
{
|
||||||
flags = PORT_DIR_MASK;
|
|
||||||
/* If layer was unknown, set to space and force */
|
/* If layer was unknown, set to space and force */
|
||||||
/* non-sticky. */
|
/* non-sticky. */
|
||||||
|
flags = PORT_DIR_MASK;
|
||||||
if (curlayer < 0)
|
if (curlayer < 0)
|
||||||
curlayer = TT_SPACE;
|
curlayer = TT_SPACE;
|
||||||
else
|
else
|
||||||
|
|
@ -828,9 +846,9 @@ DefReadPins(f, rootDef, sname, oscale, total)
|
||||||
pending = TRUE;
|
pending = TRUE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
flags = PORT_DIR_MASK;
|
|
||||||
/* If layer was unknown, set to space and force */
|
/* If layer was unknown, set to space and force */
|
||||||
/* non-sticky. */
|
/* non-sticky. */
|
||||||
|
flags = PORT_DIR_MASK;
|
||||||
if (curlayer < 0)
|
if (curlayer < 0)
|
||||||
curlayer = TT_SPACE;
|
curlayer = TT_SPACE;
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -1350,7 +1350,7 @@ LefReadMacro(f, mname, oscale, importForeign)
|
||||||
CellDef *lefMacro;
|
CellDef *lefMacro;
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
|
|
||||||
char *token, tsave[128];
|
char *token, tsave[128], *propval;
|
||||||
int keyword, pinNum;
|
int keyword, pinNum;
|
||||||
float x, y;
|
float x, y;
|
||||||
bool has_size, is_imported = FALSE;
|
bool has_size, is_imported = FALSE;
|
||||||
|
|
@ -1544,13 +1544,16 @@ origin_error:
|
||||||
|
|
||||||
if (is_imported)
|
if (is_imported)
|
||||||
{
|
{
|
||||||
/* Redefine cell bounding box to match the LEF macro */
|
/* Define the FIXED_BBOX property to match the LEF macro */
|
||||||
/* Leave "extended" to mark the original bounding box */
|
|
||||||
|
|
||||||
if (has_size)
|
if (has_size)
|
||||||
{
|
{
|
||||||
lefMacro->cd_bbox = lefBBox;
|
|
||||||
lefMacro->cd_flags |= CDFIXEDBBOX;
|
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
|
else
|
||||||
|
|
@ -1564,15 +1567,21 @@ origin_error:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *propstr = (char *)mallocMagic(64);
|
|
||||||
int reducer = DBCellFindScale(lefMacro);
|
int reducer = DBCellFindScale(lefMacro);
|
||||||
|
|
||||||
lefMacro->cd_bbox = lefBBox;
|
lefMacro->cd_bbox = lefBBox;
|
||||||
lefMacro->cd_extended = lefBBox;
|
lefMacro->cd_extended = lefBBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix the bounding box and do not allow edits */
|
/* Set the placement bounding box property to the current bounding box */
|
||||||
lefMacro->cd_flags |= /* CDNOEDIT | */ CDFIXEDBBOX;
|
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);
|
DRCCheckThis(lefMacro, TT_CHECKPAINT, &lefMacro->cd_bbox);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,25 @@ SRCS = magicTop.c
|
||||||
|
|
||||||
include ${MAGICDIR}/defs.mak
|
include ${MAGICDIR}/defs.mak
|
||||||
|
|
||||||
EXTRA_LIBS = ${MAGICDIR}/cmwind/libcmwind.o ${MAGICDIR}/commands/libcommands.o \
|
EXTRA_LIBS = ${MAGICDIR}/bplane/libbplane.o \
|
||||||
${MAGICDIR}/database/libdatabase.o ${MAGICDIR}/dbwind/libdbwind.o \
|
${MAGICDIR}/cmwind/libcmwind.o \
|
||||||
${MAGICDIR}/drc/libdrc.o ${MAGICDIR}/debug/libdebug.o \
|
${MAGICDIR}/commands/libcommands.o \
|
||||||
${MAGICDIR}/extract/libextract.o ${MAGICDIR}/graphics/libgraphics.o \
|
${MAGICDIR}/database/libdatabase.o \
|
||||||
${MAGICDIR}/select/libselect.o ${MAGICDIR}/textio/libtextio.o \
|
${MAGICDIR}/dbwind/libdbwind.o \
|
||||||
${MAGICDIR}/tiles/libtiles.o ${MAGICDIR}/windows/libwindows.o \
|
${MAGICDIR}/drc/libdrc.o \
|
||||||
${MAGICDIR}/wiring/libwiring.o ${MAGICDIR}/resis/libresis.o \
|
${MAGICDIR}/debug/libdebug.o \
|
||||||
${MAGICDIR}/sim/libsim.o ${MAGICDIR}/netmenu/libnetmenu.o \
|
${MAGICDIR}/extract/libextract.o \
|
||||||
${MAGICDIR}/plow/libplow.o ${MAGICDIR}/utils/libutils.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}
|
${MAIN_EXTRA_LIBS}
|
||||||
|
|
||||||
BITMAPS = up.xbm down.xbm left.xbm right.xbm zoom.xbm lock.xbm
|
BITMAPS = up.xbm down.xbm left.xbm right.xbm zoom.xbm lock.xbm
|
||||||
|
|
|
||||||
|
|
@ -739,7 +739,7 @@ plowPropagateRect(def, userRect, lc, changedArea)
|
||||||
lc, plowInitialPaint, (ClientData) plowRect.r_xtop);
|
lc, plowInitialPaint, (ClientData) plowRect.r_xtop);
|
||||||
|
|
||||||
/* Find any subcells crossed by the plow */
|
/* 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);
|
&cellPlowRect, plowInitialCell, (ClientData) &cellPlowRect);
|
||||||
|
|
||||||
/* While edges remain, process them */
|
/* While edges remain, process them */
|
||||||
|
|
@ -1120,7 +1120,7 @@ plowFindSelCell(yankUse, editUse)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
edge.e_flags = 0;
|
edge.e_flags = 0;
|
||||||
edge.e_pNum = PL_CELL;
|
edge.e_pNum = PL_ROUTER;
|
||||||
edge.e_use = yankUse;
|
edge.e_use = yankUse;
|
||||||
edge.e_ytop = yankUse->cu_bbox.r_ytop;
|
edge.e_ytop = yankUse->cu_bbox.r_ytop;
|
||||||
edge.e_ybot = yankUse->cu_bbox.r_ybot;
|
edge.e_ybot = yankUse->cu_bbox.r_ybot;
|
||||||
|
|
@ -1443,45 +1443,39 @@ plowInitialPaint(edge, xnew)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
plowInitialCell(cellTile, plowRect)
|
plowInitialCell(use, plowRect)
|
||||||
Tile *cellTile;
|
CellUse *use;
|
||||||
Rect *plowRect;
|
Rect *plowRect;
|
||||||
{
|
{
|
||||||
CellTileBody *ctb;
|
|
||||||
CellUse *use;
|
|
||||||
int xmove;
|
int xmove;
|
||||||
Edge edge;
|
Edge edge;
|
||||||
|
|
||||||
edge.e_pNum = PL_CELL;
|
if (use->cu_bbox.r_xbot < plowRect->r_xbot)
|
||||||
for (ctb = (CellTileBody *) TiGetBody(cellTile); ctb; ctb = ctb->ctb_next)
|
|
||||||
{
|
{
|
||||||
use = ctb->ctb_use;
|
if (use->cu_bbox.r_xtop >= plowRect->r_xtop)
|
||||||
if (use->cu_bbox.r_xbot < plowRect->r_xbot)
|
return 0;
|
||||||
{
|
|
||||||
if (use->cu_bbox.r_xtop >= plowRect->r_xtop)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Dragging this cell by its front edge */
|
/* Dragging this cell by its front edge */
|
||||||
xmove = plowRect->r_xtop - use->cu_bbox.r_xtop;
|
xmove = plowRect->r_xtop - use->cu_bbox.r_xtop;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Pushing this cell by its back edge */
|
/* Pushing this cell by its back edge */
|
||||||
xmove = plowRect->r_xtop - use->cu_bbox.r_xbot;
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -856,8 +856,7 @@ void
|
||||||
prFindCells(edge)
|
prFindCells(edge)
|
||||||
Edge *edge; /* Edge being moved */
|
Edge *edge; /* Edge being moved */
|
||||||
{
|
{
|
||||||
Plane *cellPlane = plowYankDef->cd_planes[PL_CELL];
|
BPlane *cellPlane = plowYankDef->cd_cellPlane;
|
||||||
Tile *cellTile = cellPlane->pl_hint;
|
|
||||||
struct applyRule ar;
|
struct applyRule ar;
|
||||||
Rect searchArea;
|
Rect searchArea;
|
||||||
|
|
||||||
|
|
@ -867,18 +866,7 @@ prFindCells(edge)
|
||||||
searchArea.r_xtop = edge->e_newx + DRCTechHalo;
|
searchArea.r_xtop = edge->e_newx + DRCTechHalo;
|
||||||
ar.ar_moving = edge;
|
ar.ar_moving = edge;
|
||||||
|
|
||||||
/*
|
(void) DBSrCellPlaneArea(cellPlane, &searchArea, plowFoundCell,
|
||||||
* 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,
|
|
||||||
(ClientData) &ar);
|
(ClientData) &ar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -947,7 +935,7 @@ prCell(edge)
|
||||||
cellArea.r_xtop = edge->e_newx + DRCTechHalo;
|
cellArea.r_xtop = edge->e_newx + DRCTechHalo;
|
||||||
cellArea.r_ybot = edge->e_ybot - DRCTechHalo;
|
cellArea.r_ybot = edge->e_ybot - DRCTechHalo;
|
||||||
cellArea.r_ytop = edge->e_ytop + 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,
|
&cellArea, plowFoundCell,
|
||||||
(ClientData) &ar);
|
(ClientData) &ar);
|
||||||
}
|
}
|
||||||
|
|
@ -1068,52 +1056,47 @@ plowCellPushPaint(impactedEdge, ar)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
plowFoundCell(cellTile, ar)
|
plowFoundCell(use, ar)
|
||||||
Tile *cellTile;
|
CellUse *use;
|
||||||
struct applyRule *ar;
|
struct applyRule *ar;
|
||||||
{
|
{
|
||||||
Edge *movingEdge = ar->ar_moving;
|
Edge *movingEdge = ar->ar_moving;
|
||||||
CellTileBody *ctb;
|
|
||||||
int xmove, xsep;
|
int xmove, xsep;
|
||||||
CellUse *use;
|
|
||||||
Edge edge;
|
Edge edge;
|
||||||
|
|
||||||
edge.e_pNum = PL_CELL;
|
edge.e_pNum = PL_ROUTER;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only queue the edge if the cell has not moved far enough */
|
if (use->cu_bbox.r_xbot <= movingEdge->e_x)
|
||||||
if ((use->cu_client != (ClientData)CLIENTDEFAULT) &&
|
{
|
||||||
|
/*
|
||||||
|
* 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))
|
((int)(use->cu_client) < xmove))
|
||||||
{
|
{
|
||||||
edge.e_use = use;
|
edge.e_use = use;
|
||||||
edge.e_flags = 0;
|
edge.e_flags = 0;
|
||||||
edge.e_ytop = use->cu_bbox.r_ytop;
|
edge.e_ytop = use->cu_bbox.r_ytop;
|
||||||
edge.e_ybot = use->cu_bbox.r_ybot;
|
edge.e_ybot = use->cu_bbox.r_ybot;
|
||||||
edge.e_x = use->cu_bbox.r_xtop;
|
edge.e_x = use->cu_bbox.r_xtop;
|
||||||
edge.e_newx = use->cu_bbox.r_xtop + xmove;
|
edge.e_newx = use->cu_bbox.r_xtop + xmove;
|
||||||
edge.e_ltype = PLOWTYPE_CELL;
|
edge.e_ltype = PLOWTYPE_CELL;
|
||||||
edge.e_rtype = PLOWTYPE_CELL;
|
edge.e_rtype = PLOWTYPE_CELL;
|
||||||
(void) (*plowPropagateProcPtr)(&edge);
|
(void) (*plowPropagateProcPtr)(&edge);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ plowYankUpdateCell(yankChildUse)
|
||||||
/* Restore the delta since DBPlaceCell re-initializes it to 0 */
|
/* Restore the delta since DBPlaceCell re-initializes it to 0 */
|
||||||
yankChildUse->cu_client = savedelta;
|
yankChildUse->cu_client = savedelta;
|
||||||
|
|
||||||
/* Return 1 so TiSrArea doesn't bomb */
|
/* Return 1 so DBSrCellPlaneArea doesn't bomb */
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -226,16 +226,18 @@ RtrDecompose(routeUse, area, netList)
|
||||||
* Clear the valid flags for horizontal edges for all space tiles in
|
* Clear the valid flags for horizontal edges for all space tiles in
|
||||||
* the error plane of the result cell.
|
* the error plane of the result cell.
|
||||||
*/
|
*/
|
||||||
(void) TiSrArea((Tile *) NULL, cdTo->cd_planes[PL_DRC_ERROR], &RouteArea,
|
(void) DBSrPaintArea((Tile *) NULL, cdTo->cd_planes[PL_DRC_ERROR],
|
||||||
rtrSrClear, (ClientData) &RouteArea);
|
&RouteArea, &DBAllTypeBits, rtrSrClear,
|
||||||
|
(ClientData) &RouteArea);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enumerate all tiles in the given area.
|
* Enumerate all tiles in the given area.
|
||||||
* If a tile is not a space tile, then perform the corner
|
* If a tile is not a space tile, then perform the corner
|
||||||
* extension algorithm.
|
* extension algorithm.
|
||||||
*/
|
*/
|
||||||
(void) TiSrArea((Tile *) NULL, cdTo->cd_planes[PL_DRC_CHECK], &RouteArea,
|
(void) DBSrPaintArea((Tile *) NULL, cdTo->cd_planes[PL_DRC_CHECK],
|
||||||
rtrSrFunc, (ClientData) (cdTo->cd_planes[PL_DRC_ERROR]));
|
&RouteArea, &DBAllTypeBits, rtrSrFunc,
|
||||||
|
(ClientData) (cdTo->cd_planes[PL_DRC_ERROR]));
|
||||||
|
|
||||||
/* Allow the modified area to be redisplayed if the cell is visible */
|
/* Allow the modified area to be redisplayed if the cell is visible */
|
||||||
DBReComputeBbox(cdTo);
|
DBReComputeBbox(cdTo);
|
||||||
|
|
@ -344,8 +346,8 @@ rtrSrCells(scx, targetDef)
|
||||||
*
|
*
|
||||||
* Round a rectangle out to the nearest grid line, and
|
* Round a rectangle out to the nearest grid line, and
|
||||||
* extend to a point halfway to the next grid point (if
|
* extend to a point halfway to the next grid point (if
|
||||||
* roundUp is TRUE) or back half a grid from the nearest
|
* doRoundUp is TRUE) or back half a grid from the nearest
|
||||||
* grid line (if roundUp is FALSE).
|
* grid line (if doRoundUp is FALSE).
|
||||||
*
|
*
|
||||||
* The halfway points are chosen to be RtrGridSpacing/2
|
* The halfway points are chosen to be RtrGridSpacing/2
|
||||||
* down or to the left from grid lines. Before rounding,
|
* down or to the left from grid lines. Before rounding,
|
||||||
|
|
@ -362,16 +364,16 @@ rtrSrCells(scx, targetDef)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
rtrRoundRect(r, sepUp, sepDown, roundUp)
|
rtrRoundRect(r, sepUp, sepDown, doRoundUp)
|
||||||
Rect *r;
|
Rect *r;
|
||||||
int sepUp, sepDown;
|
int sepUp, sepDown;
|
||||||
bool roundUp;
|
bool doRoundUp;
|
||||||
{
|
{
|
||||||
int halfGrid = RtrGridSpacing / 2;
|
int halfGrid = RtrGridSpacing / 2;
|
||||||
|
|
||||||
r->r_xbot = RTR_GRIDDOWN(r->r_xbot - sepDown, RtrOrigin.p_x);
|
r->r_xbot = RTR_GRIDDOWN(r->r_xbot - sepDown, RtrOrigin.p_x);
|
||||||
r->r_ybot = RTR_GRIDDOWN(r->r_ybot - sepDown, RtrOrigin.p_y);
|
r->r_ybot = RTR_GRIDDOWN(r->r_ybot - sepDown, RtrOrigin.p_y);
|
||||||
if (roundUp)
|
if (doRoundUp)
|
||||||
{
|
{
|
||||||
r->r_xbot -= halfGrid;
|
r->r_xbot -= halfGrid;
|
||||||
r->r_ybot -= 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_xtop = RTR_GRIDUP(r->r_xtop + sepUp, RtrOrigin.p_x);
|
||||||
r->r_ytop = RTR_GRIDUP(r->r_ytop + sepUp, RtrOrigin.p_y);
|
r->r_ytop = RTR_GRIDUP(r->r_ytop + sepUp, RtrOrigin.p_y);
|
||||||
if (roundUp)
|
if (doRoundUp)
|
||||||
{
|
{
|
||||||
r->r_xtop += RtrGridSpacing - halfGrid;
|
r->r_xtop += RtrGridSpacing - halfGrid;
|
||||||
r->r_ytop += RtrGridSpacing - halfGrid;
|
r->r_ytop += RtrGridSpacing - halfGrid;
|
||||||
|
|
@ -503,7 +505,7 @@ rtrSplitToArea(area, def)
|
||||||
*
|
*
|
||||||
* rtrSrClear --
|
* 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
|
* def. Sets the flags to 0 in internal space tiles, marking horizontal
|
||||||
* invalid. Mark edges at the boundary of the routing region as valid.
|
* invalid. Mark edges at the boundary of the routing region as valid.
|
||||||
*
|
*
|
||||||
|
|
@ -561,12 +563,12 @@ rtrSrClear(tile, area)
|
||||||
*
|
*
|
||||||
* rtrSrFunc --
|
* 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
|
* plane. Do this search in the OLD TILE PLANE. Process corners
|
||||||
* bordering space tiles.
|
* bordering space tiles.
|
||||||
*
|
*
|
||||||
* Results:
|
* 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:
|
* Side effects:
|
||||||
* Modifies the result plane to reflect the channel structure.
|
* Modifies the result plane to reflect the channel structure.
|
||||||
|
|
|
||||||
|
|
@ -127,8 +127,8 @@ Route(routeUse, routeArea)
|
||||||
* but don't do anything else.
|
* but don't do anything else.
|
||||||
*/
|
*/
|
||||||
RtrChannelList = (GCRChannel *) NULL;
|
RtrChannelList = (GCRChannel *) NULL;
|
||||||
(void) TiSrArea((Tile *) NULL, RtrChannelPlane, &RouteArea,
|
(void) DBSrPaintArea((Tile *) NULL, RtrChannelPlane, &RouteArea,
|
||||||
rtrMakeChannel, (ClientData) &RouteArea);
|
&DBAllTypeBits, rtrMakeChannel, (ClientData) &RouteArea);
|
||||||
if (!SigInterruptPending)
|
if (!SigInterruptPending)
|
||||||
{
|
{
|
||||||
errs = GARoute(RtrChannelList, routeUse, &netList);
|
errs = GARoute(RtrChannelList, routeUse, &netList);
|
||||||
|
|
@ -149,7 +149,7 @@ done:
|
||||||
*
|
*
|
||||||
* rtrMakeChannel --
|
* 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
|
* to channels. Clip all tiles against the box 'clipBox'. Don't set
|
||||||
* hazards for this channel; that has to happen after stem assignment.
|
* hazards for this channel; that has to happen after stem assignment.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -228,14 +228,14 @@ rtrSideProcess(use, side, area, trans)
|
||||||
{
|
{
|
||||||
/* EAST (easy case since we don't have to transform) */
|
/* EAST (easy case since we don't have to transform) */
|
||||||
case GEO_EAST:
|
case GEO_EAST:
|
||||||
rtrSideTransPlane = use->cu_def->cd_planes[PL_CELL];
|
rtrSideTransPlane = use->cu_def->cd_planes[PL_ROUTER];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Other cases use the transformed plane */
|
/* Other cases use the transformed plane */
|
||||||
case GEO_SOUTH:
|
case GEO_SOUTH:
|
||||||
case GEO_NORTH:
|
case GEO_NORTH:
|
||||||
case GEO_WEST:
|
case GEO_WEST:
|
||||||
rtrSideTransPlane = rtrSideTransDef->cd_planes[PL_CELL];
|
rtrSideTransPlane = rtrSideTransDef->cd_planes[PL_ROUTER];
|
||||||
scx.scx_area = *area;
|
scx.scx_area = *area;
|
||||||
scx.scx_use = use;
|
scx.scx_use = use;
|
||||||
scx.scx_trans = *trans;
|
scx.scx_trans = *trans;
|
||||||
|
|
@ -245,19 +245,19 @@ rtrSideProcess(use, side, area, trans)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize all client fields to NULL in the cell tile plane */
|
/* Initialize all client fields to NULL in the cell tile plane */
|
||||||
(void) TiSrArea((Tile *) NULL, rtrSideTransPlane, &rtrSideArea,
|
(void) DBSrPaintArea((Tile *) NULL, rtrSideTransPlane, &rtrSideArea,
|
||||||
rtrSideInitClient, (ClientData) INFINITY);
|
&DBAllTypeBits, rtrSideInitClient, (ClientData) INFINITY);
|
||||||
|
|
||||||
/* Process all Sides for this direction */
|
/* Process all Sides for this direction */
|
||||||
retval = TiSrArea((Tile *) NULL, rtrSideTransPlane, &rtrSideArea,
|
retval = DBSrPaintArea((Tile *) NULL, rtrSideTransPlane, &rtrSideArea,
|
||||||
rtrEnumSidesFunc, (ClientData) NULL);
|
&DBAllTypeBits, rtrEnumSidesFunc, (ClientData) NULL);
|
||||||
|
|
||||||
/* Clean up; be absolutely sure to reset client info */
|
/* Clean up; be absolutely sure to reset client info */
|
||||||
if (side == GEO_EAST)
|
if (side == GEO_EAST)
|
||||||
{
|
{
|
||||||
SigDisableInterrupts();
|
SigDisableInterrupts();
|
||||||
(void) TiSrArea((Tile *) NULL, rtrSideTransPlane, area,
|
(void) DBSrPaintArea((Tile *) NULL, rtrSideTransPlane, area,
|
||||||
rtrSideInitClient, (ClientData) CLIENTDEFAULT);
|
&DBAllTypeBits, rtrSideInitClient, (ClientData) CLIENTDEFAULT);
|
||||||
SigEnableInterrupts();
|
SigEnableInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -307,11 +307,34 @@ selRedisplayCellFunc(scx, window)
|
||||||
SearchContext *scx; /* Describes cell found. */
|
SearchContext *scx; /* Describes cell found. */
|
||||||
MagWindow *window; /* Window in which to redisplay. */
|
MagWindow *window; /* Window in which to redisplay. */
|
||||||
{
|
{
|
||||||
Rect tmp, screen;
|
Rect tmp, screen, bbox;
|
||||||
Point p;
|
Point p;
|
||||||
char idName[100];
|
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,
|
if (!DBSrPaintArea((Tile *) NULL, selRedisplayPlane, &tmp,
|
||||||
&DBAllButSpaceBits, selAlways1, (ClientData) NULL))
|
&DBAllButSpaceBits, selAlways1, (ClientData) NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -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 client procedure should not modify any of the paint planes in
|
||||||
* the cells visited by SimTreeSrTiles, because we use DBSrPaintArea
|
* 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:
|
* Results:
|
||||||
* 0 is returned if the search finished normally. 1 is returned
|
* 0 is returned if the search finished normally. 1 is returned
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
MODULE = tiles
|
MODULE = tiles
|
||||||
MAGICDIR = ..
|
MAGICDIR = ..
|
||||||
SRCS = tile.c search.c search2.c
|
SRCS = tile.c search.c
|
||||||
|
|
||||||
include ${MAGICDIR}/defs.mak
|
include ${MAGICDIR}/defs.mak
|
||||||
include ${MAGICDIR}/rules.mak
|
include ${MAGICDIR}/rules.mak
|
||||||
|
|
|
||||||
234
tiles/search2.c
234
tiles/search2.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -6,11 +6,11 @@ MODULE = utils
|
||||||
MAGICDIR = ..
|
MAGICDIR = ..
|
||||||
LIB_SRCS = LIBdbio.c LIBmain.c LIBtextio.c
|
LIB_SRCS = LIBdbio.c LIBmain.c LIBtextio.c
|
||||||
SRCS = args.c child.c dqueue.c finddisp.c flock.c flsbuf.c fraction.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 \
|
geometry.c getrect.c hash.c heap.c ihash.c list.c lookup.c \
|
||||||
lookupfull.c macros.c main.c malloc.c match.c maxrect.c netlist.c \
|
lookupany.c lookupfull.c macros.c main.c malloc.c match.c \
|
||||||
niceabort.c parser.c path.c pathvisit.c port.c printstuff.c \
|
maxrect.c netlist.c niceabort.c parser.c path.c pathvisit.c \
|
||||||
signals.c stack.c strdup.c runstats.c set.c show.c tech.c \
|
port.c printstuff.c signals.c stack.c strdup.c runstats.c set.c \
|
||||||
touchtypes.c undo.c
|
show.c tech.c touchtypes.c undo.c
|
||||||
|
|
||||||
include ${MAGICDIR}/defs.mak
|
include ${MAGICDIR}/defs.mak
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ global int GeoOppositePos[] =
|
||||||
*/
|
*/
|
||||||
|
|
||||||
global Rect GeoNullRect = { 0, 0, 0, 0 };
|
global Rect GeoNullRect = { 0, 0, 0, 0 };
|
||||||
|
global Rect GeoInvertedRect = { 0, 0, -1, -1 };
|
||||||
global Point GeoOrigin = { 0, 0 };
|
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 --
|
* GeoClip --
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,7 @@ extern int GeoRectPointSide(Rect *, Point *);
|
||||||
extern int GeoRectRectSide(Rect *, Rect *);
|
extern int GeoRectRectSide(Rect *, Rect *);
|
||||||
extern void GeoIncludePoint(Point *, Rect *);
|
extern void GeoIncludePoint(Point *, Rect *);
|
||||||
extern void GeoDecomposeTransform(Transform *, bool *, int *);
|
extern void GeoDecomposeTransform(Transform *, bool *, int *);
|
||||||
|
extern void GeoIncludeRectInBBox(Rect *, Rect *bbox);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------
|
*-------------------------------------------------------------------
|
||||||
|
|
@ -207,6 +208,7 @@ extern Transform GeoRef45Transform;
|
||||||
extern Transform GeoRef135Transform;
|
extern Transform GeoRef135Transform;
|
||||||
|
|
||||||
extern Rect GeoNullRect;
|
extern Rect GeoNullRect;
|
||||||
|
extern Rect GeoInvertedRect;
|
||||||
extern Point GeoOrigin;
|
extern Point GeoOrigin;
|
||||||
|
|
||||||
extern int GeoOppositePos[];
|
extern int GeoOppositePos[];
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -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 */
|
||||||
Loading…
Reference in New Issue