如何清理四叉树的边缘?

时间:2016-10-14 03:52:28

标签: java algorithm quadtree

我一直在实现一个四叉树的版本来处理正方形的交叉点测试。但是,在测试算法后,似乎有很多噪声。示例可以在这里看到: a preview can be seen here。根据我的理解,四叉树应该只返回交叉象限内的物体,但是有残留的边缘。

我的代码可以在这里看到:

public class QuadTree extends BoundingBox implements IntersectionAlgorithm {

@Setter
private int MAX_OBJECTS = 10;
@Setter
private int MAX_LEVELS = 12;

private int level;
private List<BoundingBox> objects;
private QuadTree[] nodes;

public QuadTree(int width, int height){
    this(0, 0, 0, width, height);
}

private QuadTree(int pLevel, int x, int y, int width, int height) {
    super(x, y, width, height);
    this.level = pLevel;
    this.objects = new ArrayList<>();
    this.nodes = new QuadTree[4];
}

@Override
public void insert(BoundingBox box) {
    if (nodes[0] != null) {
        int index = getIndex(box);

        if (index != -1) {
            nodes[index].insert(box);

            return;
        }
    }

    objects.add(box);

    if (objects.size() > MAX_OBJECTS && level < MAX_LEVELS) {
        if (nodes[0] == null) {
            split();
        }

        int i = 0;
        while (i < objects.size()) {
            int index = getIndex(objects.get(i));
            if (index != -1) {
                nodes[index].insert(objects.remove(i));
            } else {
                i++;
            }
        }
    }
}

@Override
public List<BoundingBox> retrieve(BoundingBox box) {
    return this.retrieve(box, new ArrayList<>());
}

private List<BoundingBox> retrieve(BoundingBox box, List<BoundingBox> returns) {
    int index = getIndex(box);
    if (index != -1 && nodes[0] != null) {
        nodes[index].retrieve(box, returns);
    }

    returns.addAll(objects);

    return returns;
}

private void split() {
    int subWidth = (width / 2);
    int subHeight = (height / 2);

    nodes[0] = new QuadTree(level + 1, x + subWidth, y, subWidth, subHeight);
    nodes[1] = new QuadTree(level + 1, x, y, subWidth, subHeight);
    nodes[2] = new QuadTree(level + 1, x, y + subHeight, subWidth, subHeight);
    nodes[3] = new QuadTree(level + 1, x + subWidth, y + subHeight, subWidth, subHeight);
}

private int getIndex(BoundingBox pRect) {
    int index = -1;
    double verticalMidpoint = x + (width / 2);
    double horizontalMidpoint = y + (width/ 2);

    boolean topQuadrant = (pRect.getY() < horizontalMidpoint && pRect.getY() + pRect.getHeight() < horizontalMidpoint);
    boolean bottomQuadrant = (pRect.getY() > horizontalMidpoint);

    if (pRect.getX() < verticalMidpoint && pRect.getX() + pRect.getWidth() < verticalMidpoint) {
        if (topQuadrant) {
            index = 1;
        } else if (bottomQuadrant) {
            index = 2;
        }
    }
    else if (pRect.getX() > verticalMidpoint) {
        if (topQuadrant) {
            index = 0;
        } else if (bottomQuadrant) {
            index = 3;
        }
    }

    return index;
}

我不确定我是否错误地实现了算法或使用了错误的算法,但是我们将非常感谢任何帮助! 我想进行更改,使盒子基于象限,并解决边缘问题。

1 个答案:

答案 0 :(得分:0)

你在哪里

returns.addAll(objects);

在将其添加到returns之前,您需要检查每个对象是否实际与边界框相交(或者它是否在边界框内,具体取决于您希望它返回的对象)。