Exemplo n.º 1
0
/* getRotation:
 * The function determines how much the block should be rotated
 * for best positioning with parent, assuming its center is at x and y
 * relative to the parent.
 * angle gives the angle of the new position, i.e., tan(angle) = y/x.
 * If sn has 2 nodes, we arrange the line of the 2 normal to angle.
 * If sn has 1 node, parent_pos has already been set to the 
 * correct angle assuming no rotation.
 * Otherwise, we find the node in sn connected to the parent and rotate
 * the block so that it is closer or at least visible to its node in the
 * parent.
 *
 * For COALESCED blocks, if neighbor is in left half plane, 
 * use unCOALESCED case.
 * Else let theta be angle, R = LEN(x,y), pho the radius of actual 
 * child block, phi be angle of neighbor in actual child block,
 * and r the distance from center of coalesced block to center of 
 * actual block. Then, the angle to rotate the coalesced block to
 * that the edge from the parent is tangent to the neighbor on the
 * actual child block circle is
 *    alpha = theta + M_PI/2 - phi - arcsin((l/R)*(sin B))
 * where l = r - rho/(cos phi) and beta = M_PI/2 + phi.
 * Thus, 
 *    alpha = theta + M_PI/2 - phi - arcsin((l/R)*(cos phi))
 */
static double
getRotation(block_t * sn, Agraph_t * g, double x, double y, double theta)
{
    double mindist2;
    Agraph_t *subg;
    /* Agedge_t* e; */
    Agnode_t *n, *closest_node, *neighbor;
    nodelist_t *list;
    double len2, newX, newY;
    int count;

    subg = sn->sub_graph;
#ifdef OLD
    parent = sn->parent;
#endif

    list = sn->circle_list;

    if (sn->parent_pos >= 0) {
	theta += M_PI - sn->parent_pos;
	if (theta < 0)
	    theta += 2 * M_PI;

	return theta;
    }

    count = sizeNodelist(list);
    if (count == 2) {
	return (theta - M_PI / 2.0);
    }

    /* Find node in block connected to block's parent */
    neighbor = CHILD(sn);
#ifdef OLD
    for (e = agfstedge(g, parent); e; e = agnxtedge(g, e, parent)) {
	n = e->head;
	if (n == parent)
	    n = e->tail;

	if ((BLOCK(n) == sn) && (PARENT(n) == parent)) {
	    neighbor = n;
	    break;
	}
    }
#endif
    newX = ND_pos(neighbor)[0] + x;
    newY = ND_pos(neighbor)[1] + y;
    mindist2 = LEN2(newX, newY);    /* save sqrts by using sqr of dist to find min */
    closest_node = neighbor;

    for (n = agfstnode(subg); n; n = agnxtnode(subg, n)) {
	if (n == neighbor)
	    continue;

	newX = ND_pos(n)[0] + x;
	newY = ND_pos(n)[1] + y;

	len2 = LEN2(newX, newY);
	if (len2 < mindist2) {
	    mindist2 = len2;
	    closest_node = n;
	}
    }

    /* if((neighbor != closest_node) && !ISPARENT(neighbor)) { */
    if (neighbor != closest_node) {
	double rho = sn->rad0;
	double r = sn->radius - rho;
	double n_x = ND_pos(neighbor)[0];
	if (COALESCED(sn) && (-r < n_x)) {
	    double R = LEN(x, y);
	    double n_y = ND_pos(neighbor)[1];
	    double phi = atan2(n_y, n_x + r);
	    double l = r - rho / (cos(phi));

	    theta += M_PI / 2.0 - phi - asin((l / R) * (cos(phi)));
	} else {		/* Origin still at center of this block */
	    double phi = atan2(ND_pos(neighbor)[1], ND_pos(neighbor)[0]);
	    theta += M_PI - phi - PSI(neighbor);
	    if (theta > 2 * M_PI)
		theta -= 2 * M_PI;
	}
    } else
	theta = 0;
    return theta;
}
Exemplo n.º 2
0
//查找比较长的线段
const line *longer_line(const line *p_line1, const line *p_line2) {
    return LEN2(p_line1) > LEN2(p_line2) ? p_line1 : p_line2;
}