调整矩形大小但保持它们之间距离的算法

时间:2014-06-12 22:05:37

标签: algorithm resize

我正在寻找一种算法,它可以将所有矩形的大小调整为新的宽度,场景中所有对象的高度,但保持它们之间的距离。这可能吗?

tree structure

每个矩形的锚点是左上角(0,0)。谢谢。

1 个答案:

答案 0 :(得分:0)

我找到了算法,不确定它是最好的还是优化的。

基本上找到深度,然后排序,但深度增加额外或x乘以深度。该算法也应该适用于Y.

1.首先获得最左边没有标记的元素。 (制作深度时标记) 2.找到所有兄弟姐妹的上/下(兄弟元素,从pos.x-width到pos.x + width) 3.Mark元素深度。 4.重复

使用堆栈而不是递归代码并不完全是DRY。

vt.iccode.DrawScene.prototype.ClearDepths = function () {
    for (var i=0,ii=this.nodes.length;i<ii;i++) {
        var node = this.nodes[i];
        node.ClearDepths();
    }
};

/*
 * @private
 */
vt.iccode.DrawScene.prototype.MarkTopSiblings = function(node_start, depth) {
    var stack = new Array();
    stack.push(node_start);

    while (stack.length > 0) {
        var node = stack[stack.length - 1];
        stack.splice(stack.length - 1, 1);

        console.info("marking top :"+node.name+" depth ->"+depth);
        node.depth_x = depth;

        var pos = node.GetPosition();
        var size = node.GetSize();
        var next_node = this.GetClosestElementWithinBounds(node, pos.x - size.width, pos.x + size.width, Number.NEGATIVE_INFINITY, pos.y);

        if (next_node) {
            stack.push(next_node);
        }
    }
};

vt.iccode.DrawScene.prototype.MarkBottomSiblings = function(node_start, depth) {
    var stack = new Array();
    stack.push(node_start);

    while (stack.length > 0) {
        var node = stack[stack.length - 1];
        stack.splice(stack.length - 1, 1);

        console.info("marking bottom :"+node.name+" depth ->"+depth);
        node.depth_x = depth;

        var pos = node.GetPosition();
        var size = node.GetSize();
        var next_node = this.GetClosestElementWithinBounds(node, pos.x - size.width, pos.x + size.width, pos.y + size.height, Number.POSITIVE_INFINITY);
        if (next_node) {
            stack.push(next_node);
        }
    }
};

vt.iccode.DrawScene.prototype.GetMostLeftUnmarked = function() {
    var s_x = Number.POSITIVE_INFINITY;
    var best_match = null;

    for (var i=0,ii=0;i<this.nodes.length;i++) {
        var node = this.nodes[i];
        var pos = node.GetPosition();

        if (goog.isNull(node.depth_x) && pos.x < s_x) {
            s_x = pos.x;
            best_match = node;
        }
    }

    return best_match;
};

vt.iccode.DrawScene.prototype.GetClosestElementWithinBounds = function(node, x_min, x_max, y_min, y_max) {
    var found = new Array();

    for (var i = 0, ii = this.nodes.length; i < ii; i++) {
        var node_test = this.nodes[i];
        var pos = node_test.GetPosition();

        if (pos.x >= x_min && pos.x <= x_max && pos.y >= y_min && pos.y <= y_max && goog.isNull(node_test.depth_x) && goog.isNull(node_test.depth_y)) {
            found.push(node_test);
        }
    }

    var s_distance = Number.POSITIVE_INFINITY;
    var best_match = null;

    for (var i = 0, ii = found.length; i < ii; i++) {
        var node_test = found[i];
        var dist = node.FindDistanceBetweenAnchorPoints(node_test);
        if (dist < s_distance) {
            s_distance = dist;
            best_match = node_test;
        }
    }
    ;

    return best_match;
};

使用类似:

this.ClearDepths();

var most_left_node = this.nodes[0];
var stack = new Array();
stack.push(most_left_node);
var depth_x = 0;

while(stack.length>0) {
    var node = stack[stack.length - 1];
    stack.splice(stack.length - 1, 1);

    this.MarkBottomSiblings(node,depth_x);
    this.MarkTopSiblings(node, depth_x);

    var node_next = this.GetMostLeftUnmarked();
    if (!goog.isNull(node_next)) {
        // 
        console.info(node_next.name);
        stack.push(node_next);
        // return;
    }

    depth_x++;
}

在我们知道深度后,我们可以移动x,反之亦然。