/* * convert slicing tree into actual floorplan * returns the number of dead blocks compacted */ int tree_to_flp(tree_node_t *root, flp_t *flp, int compact_dead, double compact_ratio) { /* for now, only choose the floorplan with * the minimum area regardless of the overall * aspect ratio */ int pos = min_area_pos(root->curve); #if VERBOSE > 1 double compacted_area = 0.0; #endif int dead_count = recursive_sizing(root, pos, 0.0, 0.0, 0, compact_dead, compact_ratio, #if VERBOSE > 1 &compacted_area, #endif flp); int compacted = (flp->n_units - 1) / 2 - dead_count; flp->n_units -= compacted; #if VERBOSE > 1 fprintf(stdout, "%d dead blocks, %.2f%% of the core compacted\n", compacted, compacted_area / (get_total_area(flp)-compacted_area) * 100); #endif return compacted; }
/* * recursive sizing - given the slicing tree containing * the added up shape curves. 'pos' denotes the current * added up orientation. 'leftx' & 'bottomy' denote the * left and bottom ends of the current bounding rectangle */ int recursive_sizing (tree_node_t *node, int pos, double leftx, double bottomy, int dead_count, int compact_dead, double compact_ratio, #if VERBOSE > 1 double *compacted_area, #endif flp_t *flp) { /* leaf node. fill the placeholder */ if (node->label.unit >= 0) { flp->units[node->label.unit].width = node->curve->x[pos]; flp->units[node->label.unit].height = node->curve->y[pos]; flp->units[node->label.unit].leftx = leftx; flp->units[node->label.unit].bottomy = bottomy; } else { /* shortcuts */ int idx; double x1, x2, y1, y2; /* location of the first dead block + offset */ idx = (flp->n_units + 1) / 2 + dead_count; x1 = node->left->curve->x[node->curve->left_pos[pos]]; x2 = node->right->curve->x[node->curve->right_pos[pos]]; y1 = node->left->curve->y[node->curve->left_pos[pos]]; y2 = node->right->curve->y[node->curve->right_pos[pos]]; /* add a dead block - possibly of zero area */ if (node->label.unit == CUT_VERTICAL) { flp->units[idx].width = (y2 >= y1) ? x1 : x2; flp->units[idx].height = fabs(y2 - y1); flp->units[idx].leftx = leftx + ((y2 >= y1) ? 0 : x1); flp->units[idx].bottomy = bottomy + MIN(y1, y2); /* * ignore dead blocks smaller than compact_ratio times the area * of the smaller of the constituent rectangles. instead, increase * the size of the rectangle by that amount */ if (compact_dead && fabs(y2-y1) / MIN(y1, y2) < compact_ratio) { #if VERBOSE > 1 *compacted_area += (flp->units[idx].width * flp->units[idx].height); #endif if (y2 >= y1) node->left->curve->y[node->curve->left_pos[pos]] = y2; else node->right->curve->y[node->curve->right_pos[pos]] = y1; } else { dead_count++; } /* left and bottom don't change for the left child */ dead_count = recursive_sizing(node->left, node->curve->left_pos[pos], leftx, bottomy, dead_count, compact_dead, compact_ratio, #if VERBOSE > 1 compacted_area, #endif flp); dead_count = recursive_sizing(node->right, node->curve->right_pos[pos], leftx + node->curve->median[pos], bottomy, dead_count, compact_dead, compact_ratio, #if VERBOSE > 1 compacted_area, #endif flp); } else { flp->units[idx].width = fabs(x2 - x1); flp->units[idx].height = (x2 >= x1) ? y1 : y2; flp->units[idx].leftx = leftx + MIN(x1, x2); flp->units[idx].bottomy = bottomy + ((x2 >= x1) ? 0 : y1); if (compact_dead && fabs(x2-x1) / MIN(x1, x2) < compact_ratio) { #if VERBOSE > 1 *compacted_area += (flp->units[idx].width * flp->units[idx].height); #endif if (x2 >= x1) node->left->curve->x[node->curve->left_pos[pos]] = x2; else node->right->curve->x[node->curve->right_pos[pos]] = x1; } else { dead_count++; } /* left and bottom don't change for the bottom child */ dead_count = recursive_sizing(node->left, node->curve->left_pos[pos], leftx, bottomy, dead_count, compact_dead, compact_ratio, #if VERBOSE > 1 compacted_area, #endif flp); dead_count = recursive_sizing(node->right, node->curve->right_pos[pos], leftx, bottomy + node->curve->median[pos], dead_count, compact_dead, compact_ratio, #if VERBOSE > 1 compacted_area, #endif flp); } } return dead_count; }
/* * recursive sizing - given the slicing tree containing * the added up shape curves. 'pos' denotes the current * added up orientation. 'leftx' & 'bottomy' denote the * left and bottom ends of the current bounding rectangle */ int recursive_sizing (tree_node_t *node, int pos, double leftx, double bottomy, int dead_count, int compact_dead, double compact_ratio, #if VERBOSE > 1 double *compacted_area, #endif flp_t *flp) { /* shortcut */ shape_t *self = node->curve; /* leaf node. fill the placeholder */ if (node->label.unit >= 0) { flp->units[node->label.unit].width = self->x[pos]; flp->units[node->label.unit].height = self->y[pos]; flp->units[node->label.unit].leftx = leftx; flp->units[node->label.unit].bottomy = bottomy; } else { /* shortcuts */ int idx; double x1, x2, y1, y2; shape_t *left = node->left->curve; shape_t *right = node->right->curve; /* location of the first dead block + offset */ idx = (flp->n_units + 1) / 2 + dead_count; x1 = left->x[self->left_pos[pos]]; x2 = right->x[self->right_pos[pos]]; y1 = left->y[self->left_pos[pos]]; y2 = right->y[self->right_pos[pos]]; /* add a dead block - possibly of zero area */ if (node->label.unit == CUT_VERTICAL) { /* * if a dead block has been previously compacted away from this * bounding rectangle, absorb that area into the child also */ if(self->y[pos] > MAX(y1, y2)) { left->y[self->left_pos[pos]] += (self->y[pos] - MAX(y1, y2)); right->y[self->right_pos[pos]] += (self->y[pos] - MAX(y1, y2)); y1 = left->y[self->left_pos[pos]]; y2 = right->y[self->right_pos[pos]]; } if(self->x[pos] > (x1+x2)) { right->x[self->right_pos[pos]] += self->x[pos]-(x1+x2); x2 = right->x[self->right_pos[pos]]; } flp->units[idx].width = (y2 >= y1) ? x1 : x2; flp->units[idx].height = fabs(y2 - y1); flp->units[idx].leftx = leftx + ((y2 >= y1) ? 0 : x1); flp->units[idx].bottomy = bottomy + MIN(y1, y2); /* * ignore dead blocks smaller than compact_ratio times the area * of the smaller of the constituent rectangles. instead, increase * the size of the rectangle by that amount */ if (compact_dead && fabs(y2-y1) / MIN(y1, y2) <= compact_ratio) { #if VERBOSE > 1 *compacted_area += (flp->units[idx].width * flp->units[idx].height); #endif if (y2 >= y1) left->y[self->left_pos[pos]] = y2; else right->y[self->right_pos[pos]] = y1; } else { dead_count++; } /* left and bottom don't change for the left child */ dead_count = recursive_sizing(node->left, self->left_pos[pos], leftx, bottomy, dead_count, compact_dead, compact_ratio, #if VERBOSE > 1 compacted_area, #endif flp); dead_count = recursive_sizing(node->right, self->right_pos[pos], leftx + self->median[pos], bottomy, dead_count, compact_dead, compact_ratio, #if VERBOSE > 1 compacted_area, #endif flp); } else { if(self->x[pos] > MAX(x1, x2)) { left->x[self->left_pos[pos]] += (self->x[pos] - MAX(x1, x2)); right->x[self->right_pos[pos]] += (self->x[pos] - MAX(x1, x2)); x1 = left->x[self->left_pos[pos]]; x2 = right->x[self->right_pos[pos]]; } if(self->y[pos] > (y1+y2)) { right->y[self->right_pos[pos]] += self->y[pos]-(y1+y2); y2 = right->y[self->right_pos[pos]]; } flp->units[idx].width = fabs(x2 - x1); flp->units[idx].height = (x2 >= x1) ? y1 : y2; flp->units[idx].leftx = leftx + MIN(x1, x2); flp->units[idx].bottomy = bottomy + ((x2 >= x1) ? 0 : y1); if (compact_dead && fabs(x2-x1) / MIN(x1, x2) <= compact_ratio) { #if VERBOSE > 1 *compacted_area += (flp->units[idx].width * flp->units[idx].height); #endif if (x2 >= x1) left->x[self->left_pos[pos]] = x2; else right->x[self->right_pos[pos]] = x1; } else { dead_count++; } /* left and bottom don't change for the left child */ dead_count = recursive_sizing(node->left, self->left_pos[pos], leftx, bottomy, dead_count, compact_dead, compact_ratio, #if VERBOSE > 1 compacted_area, #endif flp); dead_count = recursive_sizing(node->right, self->right_pos[pos], leftx, bottomy + self->median[pos], dead_count, compact_dead, compact_ratio, #if VERBOSE > 1 compacted_area, #endif flp); } } return dead_count; }