在孩子面前为父母排序的算法

时间:2009-10-26 21:16:02

标签: javascript canvas

我正在编写一个包含可以生孩子的形状的绘图应用程序。当我需要重绘画布时,我想对要绘制的形状进行排序,以便父母出现在他们的孩子面前。这样,父形状将不会在子形状上绘制。这是相关的功能(用JavaScript编写)。前缀为my.的变量是实例变量。 my.draw_order是一个需要重绘的形状索引数组(由下面的代码填充),my.ctx是绘制形状的HTML画布上下文,my.shapes是一个形状数组在任意顺序中,my.update_rects是一个脏矩形数组,可以选择非常大的形状使用,只进行部分重绘。

redraw = function () {
    var i, shape_count, shape;

    shape_count = 0;
    for (i = 0; i < my.shapes.length; i++) {
        shape = my.shapes[i];

        if (shape.visible && shape.dirty) {
            my.draw_order[shape_count] = i;
            shape_count++;
        }
    }

    my.draw_order.length = shape_count;

    // sort shapes to draw so that parents appear before children ???
    my.draw_order.sort(shape_sort);

    for (i = 0; i < my.draw_order.length; i++) {
        shape = my.shapes[my.draw_order[i]];

        shape.draw(my.ctx, my.update_rects);
        shape.dirty = false;
    }

    my.update_rects.length = 0;
};

我的问题是:代码引用的实现shape_sort的最佳方法是什么?这是一个经常被调用的例程,因此效率可能是一个问题。每个形状都有一个父属性,其中包含对其父级形状的引用。欢迎提出更好的设计建议。按排序顺序维护my.shapes数组是一种不合需要的选择。

2 个答案:

答案 0 :(得分:3)

如果您需要比树更复杂的数据结构,则应检查Topological Sort算法。

答案 1 :(得分:2)

我会将形状保持为树状。创建一个根(代表整个屏幕),并给父母指点他们的孩子。然后一个简单的前序遍历树就足够了。

要根据现有设计实施,您无需抛弃my.shapes数组。只需添加一个my.root,添加从父项到子项的指针,然后遍历:

function preorder_draw(root) {

    //do stuff with root
    draw(root);

    for (child in root.children) {
        preorder_draw(child);
    }

}