📄 emptyr.c
字号:
/*********************************************************************** File: emptyr.c Rev: b-1 Date: 01/31/2000 Copyright (c) 1998, 2001 by David M. Warme and Martin Zachariasen************************************************************************ Routines for efficiently determining whether or not two terminals define an empty rectangle. We precompute this information and store it compactly.************************************************************************ Modification Log: a-1: 09/28/98 warme : Created. Implemented Zachariasen's algorithm : using Warme's infrastructure. b-1: 01/31/2000 martinz : Successor array is computed within initialization : if given as a NULL pointer.************************************************************************/#include "emptyr.h"#include "steiner.h"/* * Global Routines */int count_empty_rectangles (bitmap_t *, int);bitmap_t * init_empty_rectangles (struct pset *, int *);bool is_empty_rectangle (bitmap_t *, int, int);void shutdown_empty_rectangles (bitmap_t *);/* * Local Macros */#define _POS(i,j) (((i * (i-1)) >> 1) + j)#define POS(i,j) ((i >= j) ? _POS(i,j) : _POS(j,i))/* * Local Routines */static void set_bit (bitmap_t *, int, int);static int * heapsort_x (struct pset *);/* * Pre-compute an N by N boolean matrix whose (i,j)-th element is * TRUE if-and-only-if the interior of the rectangle defined by * terminals i and j is devoid of terminals. * * Since this matrix is symmetric and the diagonal elements are * all TRUE, we store only the lower triangle in a compact bit-vector * form. * * The succ0 array may be given as the NULL pointer in which case it is * computed by the the procedure. */ bitmap_t *init_empty_rectangles (struct pset * pts, /* IN - point set to use */int * succ0 /* IN - next "dir 0" successor for each term */){int i;int j;int n;bitmap_t * bits;int nbits;int nwords;int * x_order;int * succ;struct point * p;struct point * q;double dx, dy;double x, y;double top_dist, bot_dist;double old_top_dist, old_bot_dist;double top_x, bot_x; n = pts -> n; /* Do we need to compute succ array? */ if (succ0 EQ NULL) { x_order = heapsort_x (pts); succ = NEWA (n, int); for (i = 1; i < n; i++) { succ [x_order [i - 1]] = x_order [i]; } succ [x_order [i - 1]] = -1; } else { succ = succ0; } /* Create the lower-triangular bit-vector and zero it. */ nbits = (n * (n - 1)) >> 1; nwords = BMAP_ELTS (nbits); bits = NEWA (nwords, bitmap_t); for (i = 0; i < nwords; i++) { bits [i] = 0; } p = &(pts -> a [0]); for (i = 0; i < n; i++, p++) { x = p -> x; y = p -> y; top_dist = INF_DISTANCE; bot_dist = INF_DISTANCE; old_top_dist = INF_DISTANCE; old_bot_dist = INF_DISTANCE; top_x = x; bot_x = x; for (j = succ [i]; j >= 0; j = succ [j]) { q = &(pts -> a [j]); dx = q -> x - x; if (dx EQ 0.0) { /* Q is exactly on vertical line through P. */ set_bit (bits, i, j); continue; } dy = q -> y - y; if (dy EQ 0.0) { /* Q is exactly on horiz line through Q. */ set_bit (bits, i, j); continue; } if (dy > 0.0) { /* Q is on top (above P). */ if (dy <= top_dist) { set_bit (bits, i, j); if (q -> x > top_x) { old_top_dist = top_dist; top_x = q -> x; } top_dist = dy; } else if ((q -> x EQ top_x) AND (dy <= old_top_dist)) { set_bit (bits, i, j); } } else { /* Q is on bottom (below P). */ dy = - dy; if (dy <= bot_dist) { set_bit (bits, i, j); if (q -> x > bot_x) { old_bot_dist = bot_dist; bot_x = q -> x; } bot_dist = dy; } else if ((q -> x EQ bot_x) AND (dy <= old_bot_dist)) { set_bit (bits, i, j); } } } } if (succ0 EQ NULL) { free ((char *) x_order); free ((char *) succ); } return (bits);}/* * Set bit (i,j) in the bit matrix. */ static voidset_bit (bitmap_t * bits, /* IN - bit vector for matrix */int i, /* IN - row number */int j /* IN - column number */){int pos; /* The diagonal is not stored! */ if (i EQ j) return; pos = POS (i, j); SETBIT (bits, pos);}/* * Clean up the empty rectangles data structure. */ voidshutdown_empty_rectangles (bitmap_t * bits /* IN - empty rectangle bit matrix */){ free ((char *) bits);}/* * Determine if the rectangle defined by terminals i and j is empty. */ boolis_empty_rectangle (bitmap_t * bits, /* IN - empty rectangle bit matrix */int i, /* IN - first terminal number */int j /* IN - second terminal number */){int pos; if (i EQ j) { /* The rectangle is zero by zero, and therefore has */ /* no interior. There cannot be any terminals inside! */ return (TRUE); } pos = POS (i, j); return (BITON (bits, pos));}/* * This routine counts the total number of 1 bits in the bit matrix. * This represents the number of pairs of terminals that define * rectangles whose INTERIORS are devoid of terminals. */ intcount_empty_rectangles (bitmap_t * bits, /* IN - empty rectangle bit matrix */int n /* IN - number of terminals */){int i;int nbits;int nwords;int count;bitmap_t mask1;bitmap_t mask2;bitmap_t limit; nbits = (n * (n - 1)) >> 1; nwords = nbits / BPW; nbits = nbits % BPW; count = 0; for (i = 0; i < nwords; i++) { mask1 = bits [i]; while (mask1 NE 0) { mask1 ^= (mask1 & -mask1); ++count; } } if (nbits > 0) { /* Count straggling bits in last word. */ mask1 = bits [nwords]; limit = 1 << nbits; /* first bit to EXCLUDE from count */ while (mask1 NE 0) { mask2 = (mask1 & -mask1); if (mask2 >= limit) break; mask1 ^= mask2; ++count; } } return (count);}/* * Use the heapsort algorithm to sort the given terminals in increasing * order by the following keys: * * 1. X coordinate * 2. Y coordinate * 3. index (i.e., position within input data) * * Of course, we do not move the points, but rather permute an array * of indexes into the points. */ static int *heapsort_x (struct pset * pts /* IN - the terminals to sort */){int i, i1, i2, j, k, n;struct point * p1;struct point * p2;int * index; n = pts -> n; index = NEWA (n, int); for (i = 0; i < n; i++) { index [i] = i; } /* Construct the heap via sift-downs, in O(n) time. */ for (k = n >> 1; k >= 0; k--) { j = k; for (;;) { i = (j << 1) + 1; if (i + 1 < n) { /* Increment i (to right subchild of j) */ /* if the right subchild is greater. */ i1 = index [i]; i2 = index [i + 1]; p1 = &(pts -> a [i1]); p2 = &(pts -> a [i2]); if ((p2 -> x > p1 -> x) OR ((p2 -> x EQ p1 -> x) AND ((p2 -> y > p1 -> y) OR ((p2 -> y EQ p1 -> y) AND (i2 > i1))))) { ++i; } } if (i >= n) { /* Hit bottom of heap, sift-down is done. */ break; } i1 = index [j]; i2 = index [i]; p1 = &(pts -> a [i1]); p2 = &(pts -> a [i2]); if ((p1 -> x > p2 -> x) OR ((p1 -> x EQ p2 -> x) AND ((p1 -> y > p2 -> y) OR ((p1 -> y EQ p2 -> y) AND (i1 > i2))))) { /* Greatest child is smaller. Sift- */ /* down is done. */ break; } /* Sift down and continue. */ index [j] = i2; index [i] = i1; j = i; } } /* Now do actual sorting. Exchange first/last and sift down. */ while (n > 1) { /* Largest is at index [0], swap with index [n-1], */ /* thereby putting it into final position. */ --n; i = index [0]; index [0] = index [n]; index [n] = i; /* Now restore the heap by sifting index [0] down. */ j = 0; for (;;) { i = (j << 1) + 1; if (i + 1 < n) { /* Increment i (to right subchild of j) */ /* if the right subchild is greater. */ i1 = index [i]; i2 = index [i + 1]; p1 = &(pts -> a [i1]); p2 = &(pts -> a [i2]); if ((p2 -> x > p1 -> x) OR ((p2 -> x EQ p1 -> x) AND ((p2 -> y > p1 -> y) OR ((p2 -> y EQ p1 -> y) AND (i2 > i1))))) { ++i; } } if (i >= n) { /* Hit bottom of heap, sift-down is done. */ break; } i1 = index [j]; i2 = index [i]; p1 = &(pts -> a [i1]); p2 = &(pts -> a [i2]); if ((p1 -> x > p2 -> x) OR ((p1 -> x EQ p2 -> x) AND ((p1 -> y > p2 -> y) OR ((p1 -> y EQ p2 -> y) AND (i1 > i2))))) { /* Greatest child is smaller. Sift- */ /* down is done. */ break; } /* Sift down and continue. */ index [j] = i2; index [i] = i1; j = i; } } return (index);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -