⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 efst.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Merge two disjoint ordered lists of terminal numbers.  The result * is of course also ordered. */	static	eterm_t *merge_terminal_lists (struct einfo * eip,  /* IN/OUT - global EFST info */struct eqp_t * eqpi, /* IN - first eq-point */struct eqp_t * eqpj, /* IN - second eq-point */struct eqp_t * eqpk  /* IN - new eq-point */){	eterm_t *p1, *endp1, *p2, *endp2, *Zp, *eqpZ_old;	int t1, t2;	struct eqp_t *eqpt;	/* Set new eq-point terminal list pointer */	eqpk -> Z = eip -> eqpZ_curr;	if (eip -> eqpZ_curr + eqpi -> S + eqpj -> S		>  eip -> eqpZ + eip -> eqpZ_size)  {		/* Terminal list space exhausted - double array */		if (Print_Detailed_Timings)			fprintf(stderr, "- doubling terminal list array\n");		eqpZ_old = eip -> eqpZ;		eip -> eqpZ = NEWA ( eip -> eqpZ_size * 2, eterm_t );		memcpy ( eip -> eqpZ, eqpZ_old, eip -> eqpZ_size * sizeof(eterm_t) );		eip -> eqpZ_size = 2 * eip -> eqpZ_size;		eip -> eqpZ_curr = UPDATE_PTR( eip -> eqpZ_curr, eqpZ_old, eip -> eqpZ );		/* Update pointers from eq-point array */		for (eqpt = eip -> eqp; eqpt <= eqpk; eqpt++)			eqpt -> Z = UPDATE_PTR( eqpt -> Z, eqpZ_old, eip -> eqpZ );		free( eqpZ_old );	}	p1 = eqpi -> Z;	p2 = eqpj -> Z;	endp1 = p1 + eqpi -> S;	endp2 = p2 + eqpj -> S;	/* We know each list contains at least one item! */	t1 = *p1++;	t2 = *p2++;	/* I tried it lots of different ways and discovered that	   these goto's actually produce the MOST readable form! */	Zp = eip -> eqpZ_curr;	for (;;) {		if (t1 < t2) {			*Zp++ = t1;			if (p1 >= endp1) goto finish2;			t1 = *p1++;		}		else {			/* Disjoint implies t2 < t1 right here. */			*Zp++ = t2;			if (p2 >= endp2) goto finish1;			t2 = *p2++;		}	}finish1:	for (;;) {		*Zp++ = t1;		if (p1 >= endp1) break;		t1 = *p1++;	}	return (Zp);finish2:	for (;;) {		*Zp++ = t2;		if (p2 >= endp2) break;		t2 = *p2++;	}	return (Zp);}/* * Test if terminals involved in eq-point j are disjoint from those * already flagged. */	static	booldisjoint (struct einfo * eip, /* IN - global EFST info */struct eqp_t * eqp  /* IN - eq-point */){	eterm_t *p = eqp -> Z;	eterm_t *endp = p + eqp -> S;	while (p < endp) {		int t = *p++;		if (eip -> MEMB [t]) return FALSE;	}	return TRUE;}/* * Return terminal with highest index involved in eq-point k */	static	inthighest_terminal (struct eqp_t * eqp  /* IN - eq-point */){	return ( (eqp -> Z) [eqp -> S  -  1]);}/* * Return the closest terminal to Q involved in the construction of * equilateral point number k */	static	dist_tclosest_terminal (struct einfo * eip,  /* IN - global EFST info */struct point * Q,    /* IN - query point */struct eqp_t * eqpk  /* IN - eq-point */){	eterm_t *p, *endp;	int t;	dist_t min_dist2, dist2;	int min_t;	p = eqpk -> Z;	endp = p + eqpk -> S;	min_t = *p++;	min_dist2 = sqr_dist(Q, &(eip -> eqp[min_t].E));	while (p < endp) {		t = *p++;		dist2 = sqr_dist(Q, &(eip -> eqp[t].E));		if (dist2 < min_dist2) {			min_dist2 = dist2;			min_t = t;		}	}	return (sqrt (min_dist2));}/* * Get bottleneck Steiner distance between equilateral points i and j */	static	doublegetBSD (struct einfo * eip,  /* IN - global EFST info */struct eqp_t * eqpi, /* IN - first eq-point */struct eqp_t * eqpj  /* IN - second eq-point */){	dist_t rbsd, lbsd;	if (eqpi -> R EQ NULL) {		if (eqpj -> R EQ NULL) return bsd(eip -> bsd, eqpi -> E.pnum, eqpj -> E.pnum);		rbsd = getBSD(eip, eqpi, eqpj -> R);		lbsd = getBSD(eip, eqpi, eqpj -> L);	}	else {		rbsd = getBSD(eip, eqpi -> R, eqpj);		lbsd = getBSD(eip, eqpi -> L, eqpj);	}	if (rbsd < lbsd) return rbsd;	return lbsd;}/* * Computation of eq-point displacement vector */	static	voideq_point_disp_vector (struct einfo * eip,   /* IN - global EFST info */struct eqp_t * eqpi,  /* IN - first eq-point */struct eqp_t * eqpj,  /* IN - second eq-point */struct eqp_t * eqpk   /* IN - new eq-point */){pnum_t		ti, tj;double		dx, dy, rdx, rdy;	/* First compute vector between old eq-points terminal references */	ti = eqpi -> DV.pnum;	tj = eqpj -> DV.pnum;	dx = eip -> eqp [tj].E.x - eip -> eqp [ti].E.x;	dy = eip -> eqp [tj].E.y - eip -> eqp [ti].E.y;	/* Add displacements */	dx -= eqpi -> DV.x;	dy -= eqpi -> DV.y;	dx += eqpj -> DV.x;	dy += eqpj -> DV.y;	/* Rotate 60 degrees and save */	rotate60(dx, dy, &rdx, &rdy);	eqpk -> DV.x	= rdx + eqpi -> DV.x;	eqpk -> DV.y	= rdy + eqpi -> DV.y;	eqpk -> DV.pnum = eqpi -> DV.pnum;}/* * Computation of distance between eq-points. * We do this in a numerically careful way by computing displacements * and not absolute coordinates. */	static	dist_teq_point_dist (struct einfo * eip,   /* IN - global EFST info */struct eqp_t * eqpi,  /* IN - first eq-point */struct eqp_t * eqpj   /* IN - second eq-point */){pnum_t		ti, tj;double		dx, dy, rdx, rdy;	/* First compute vector between eq-points terminal references */	ti = eqpi -> DV.pnum;	tj = eqpj -> DV.pnum;	dx = eip -> eqp [tj].E.x - eip -> eqp [ti].E.x;	dy = eip -> eqp [tj].E.y - eip -> eqp [ti].E.y;	/* Add displacements */	dx -= eqpi -> DV.x;	dy -= eqpi -> DV.y;	dx += eqpj -> DV.x;	dy += eqpj -> DV.y;	/* Finally return length of vector */	return hypot (dx, dy);}/* * List of terminals involved in the construction of eq-point */	static	voideqpoint_terminals (struct einfo * eip,  /* IN - global EFST info */struct eqp_t * eqpk, /* IN - eq-point */struct pset  * pts,  /* OUT - list of point */bool   append	     /* IN - append to list? */){	eterm_t *p = eqpk -> Z;	eterm_t *endp = p + eqpk -> S;	struct point *pt;	if (NOT append) pts -> n = 0;	pt = pts -> a + pts -> n;	while (p < endp)		*(pt++) = eip -> eqp[ *p++ ].E;	pts -> n += eqpk -> S;}/* * Initialize data structure for eq-point rectangles. * We use a hashing like data structure; the rectangle enclosing all * the terminals is divided into squares with side length of the * longest MST edge. For each such square the list of eq-point * rectangles overlapping with that square are stored in an array. * The idea of using eq-point rectangles was proposed by Ernst Althaus, * Max-Planck-Institut fur Informatik, Germany. * He used a 2D-search trees to store the rectangles; we apply * a simpler alternative here. */	static	voidinitialize_eqp_rectangles (struct einfo * eip /* IN/OUT - global EFST info */){	int i;	struct point * p;	/* Allocate square data structure */	eip -> eqp_squares = NEWA(eip -> pts -> n, struct eqp_square_t *);	/* Find range of terminal coordinates */	eip -> minx =  INF_DISTANCE;	eip -> maxx = -INF_DISTANCE;	eip -> miny =  INF_DISTANCE;	eip -> maxy = -INF_DISTANCE;	for (i = 0; i < eip -> pts -> n; i++) {		p = &(eip -> pts -> a[i]);		eip -> minx = MIN( eip -> minx, p -> x - eip -> mean.x);		eip -> maxx = MAX( eip -> maxx, p -> x - eip -> mean.x);		eip -> miny = MIN( eip -> miny, p -> y - eip -> mean.y);		eip -> maxy = MAX( eip -> maxy, p -> y - eip -> mean.y);		eip -> eqp_squares[i] = NULL;	}	/* Set up basic paramaters */	eip -> eqp_square_size = eip -> max_mst_edge;	eip -> srangex = floor( (eip -> maxx - eip -> minx) / eip -> eqp_square_size) + 1;	eip -> srangey = floor( (eip -> maxy - eip -> miny) / eip -> eqp_square_size) + 1;}/* * Free memory used by eq-point rectangle data structure. */	static	voiddestroy_eqp_rectangles (struct einfo * eip /* IN/OUT - global EFST info */){	int i;	for (i = 0; i < eip -> pts -> n; i++)	if (eip -> eqp_squares[i] NE NULL) {		free( eip -> eqp_squares[i][0].eqp ); /* eq-point lists */		free( eip -> eqp_squares[i]	   ); /* pointers to eq-point lists */	}	free( eip -> eqp_squares );}/* * Compute boundary of rectangle in which the Steiner point joining * the current eq-point to another eq-point can be placed */	static	voidcompute_eqp_rectangle (struct einfo * eip,  /* IN - global EFST info */struct eqp_t * eqpk, /* IN - eq-point */dist_t * minx,	     /* OUT - minimum x-coordinate of boundary */dist_t * maxx,	     /* OUT - maximum x-coordinate of boundary */dist_t * miny,	     /* OUT - minimum y-coordinate of boundary */dist_t * maxy	     /* OUT - maximum x-coordinate of boundary */){	struct point p;	dist_t alpha;	if (eqpk -> S EQ 1) {		/* This is a terminal */		*minx = eqpk -> E.x - eip -> max_mst_edge;		*maxx = eqpk -> E.x + eip -> max_mst_edge;		*miny = eqpk -> E.y - eip -> max_mst_edge;		*maxy = eqpk -> E.y + eip -> max_mst_edge;	}	else {		/* This is a "normal" eq-point */		*minx = eqpk -> LP.x; *maxx = eqpk -> LP.x;		*miny = eqpk -> LP.y; *maxy = eqpk -> LP.y;		UPDATE_RECTANGLE_BOUNDS(eqpk -> RP);		/* Projection of eqpk -> LP (from eqpk -> E) to a point		   at distance max_mst_edge away. */		alpha = 1.0 + eip -> max_mst_edge / EDIST(&(eqpk -> E), &(eqpk -> LP));		p.x   = eqpk -> E.x + alpha * (eqpk -> LP.x - eqpk -> E.x);		p.y   = eqpk -> E.y + alpha * (eqpk -> LP.y - eqpk -> E.y);		UPDATE_RECTANGLE_BOUNDS(p);		/* Projection of eqpk -> RP (from eqpk -> E) to a point		   at distance max_mst_edge away. */		alpha = 1.0 + eip -> max_mst_edge / EDIST(&(eqpk -> E), &(eqpk -> RP));		p.x   = eqpk -> E.x + alpha * (eqpk -> RP.x - eqpk -> E.x);		p.y   = eqpk -> E.y + alpha * (eqpk -> RP.y - eqpk -> E.y);		UPDATE_RECTANGLE_BOUNDS(p);		/* Now check all intersections with axis parallel lines		   through  eqpk -> DC */		p.x = eqpk -> DC.x + eqpk -> DR + eip -> max_mst_edge;		p.y = eqpk -> DC.y;		if (right_turn(&(eqpk -> E), &(eqpk -> LP), &p) AND		    left_turn(&(eqpk -> E), &(eqpk -> RP), &p))			UPDATE_RECTANGLE_BOUNDS(p);		p.x = eqpk -> DC.x - eqpk -> DR - eip -> max_mst_edge;		p.y = eqpk -> DC.y;		if (right_turn(&(eqpk -> E), &(eqpk -> LP), &p) AND		    left_turn(&(eqpk -> E), &(eqpk -> RP), &p))			UPDATE_RECTANGLE_BOUNDS(p);		p.x = eqpk -> DC.x;		p.y = eqpk -> DC.y + eqpk -> DR + eip -> max_mst_edge;		if (right_turn(&(eqpk -> E), &(eqpk -> LP), &p) AND		    left_turn(&(eqpk -> E), &(eqpk -> RP), &p))			UPDATE_RECTANGLE_BOUNDS(p);		p.x = eqpk -> DC.x;		p.y = eqpk -> DC.y - eqpk -> DR - eip -> max_mst_edge;		if (right_turn(&(eqpk -> E), &(eqpk -> LP), &p) AND		    left_turn(&(eqpk -> E), &(eqpk -> RP), &p))			UPDATE_RECTANGLE_BOUNDS(p);	}	*minx -= (fabs(*minx) * eip -> eps * ((double) eqpk -> S));	*miny -= (fabs(*miny) * eip -> eps * ((double) eqpk -> S));	*maxx += (fabs(*maxx) * eip -> eps * ((double) eqpk -> S));	*maxy += (fabs(*maxy) * eip -> eps * ((double) eqpk -> S));}/* * Save all eq-point rectangles for a given eq-point size */	static	voidsave_eqp_rectangles (struct einfo * eip,  /* IN/OUT - global EFST info */int first_eqp,	     /* IN - index of first eq-point to be saved */int last_eqp	     /* IN - index of last eq-point to be saved */){	int i, j, k, si, size;	struct eqp_t * eqpk;	dist_t minx, maxx, miny, maxy;	int total_squares;	int * curr_count;	struct eqp_square_t* sqr;	struct eqp_t ** eqp_alloc;	if (first_eqp > last_eqp) return; /* no eq-points to save */	/* Go through all equilateral points.	 * Find min/max square indices in each dimension and count the total	 * number of squares that are overlapped by these eq-points.	 */	size = eip -> eqp[first_eqp].S;	total_squares = 0;	for (k = first_eqp; k <= last_eqp; k++) {		eqpk = &(eip -> eqp[k]);		/* Compute geometric range of rectangle for this eq-point */		compute_eqp_rectangle(eip, eqpk, &minx, &maxx, &miny, &maxy);		/* Compute square index range for this eq-point */		eqpk -> SMINX = MAX(0,		      floor( (minx - eip -> minx) /						       eip -> eqp_square_size));		eqpk -> SMAXX = MIN(eip -> srangex-1, floor( (maxx - eip -> minx) /						       eip -> eqp_square_size));		eqpk -> SMINY = MAX(0,		      floor( (miny - eip -> miny) /						       eip -> eqp_square_size));		eqpk -> SMAXY = MIN(eip -> srangey-1, floor( (maxy - eip -> miny) /						       eip -> eqp_square_size));		total_squares += (eqpk -> SMAXX - eqpk -> SMINX + 1) *				 (eqpk -> SMAXY - eqpk -> SMINY + 1);	}	/* Allocate space for these rectangles */	eip -> eqp_squares[size] = NEWA(eip -> srangex * eip -> srangey,						struct eqp_square_t);	sqr = eip -> eqp_squares[size];	/* Initialize eq-point counts */	curr_count = NEWA(eip -> srangex * eip -> srangey, int);	for (i = 0; i < eip -> srangex; i++)		for (j = 0; j < eip -> srangey; j++) {			si = i * eip -> srangey + j;			sqr[si].n = 0; curr_count[si] = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -