如何将对象插入到四叉树的多个节点中

时间:2013-12-02 01:26:03

标签: java data-structures 2d game-engine quadtree

我正在制作2D游戏,看看我能做些什么。现在我正处于我必须进行物体碰撞的部分,我选择使用四叉树。手头的问题是将对象插入多个子节点。所以我遇到的问题是当我将一个对象插入树中时,树应该将对象放入可能的最低叶节点。但由于某种原因,我还没有发现每个父节点中至少有一个对象仍然存在。

所以我的问题是你们可以帮助识别并提供上述问题的可能解决方案。如果你们这些问题无法解决,你们可以提供另一种解决方法。

我的代码:

package net.evergone.engine;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.lwjgl.util.vector.Vector2f;
import org.newdawn.slick.Color;

import net.evergone.EverGone;
import net.evergone.game.BasicRectangle;

public class QuadtreeNode
{
    private int MAX_OBJECTS = 2;
    private int MAX_LEVELS = 6;
    private int level = 0;
    private boolean children = false;
    private static boolean temp = false;
    private BasicRectangle boundBox;
    private ArrayList<BasicRectangle> objects;
    private QuadtreeNode[] nodes;

    /**
     * 
     * Default constructor for QuadtreeNode
     */
    public QuadtreeNode(int level, BasicRectangle boundBox)
    {
        this.level = level;
        this.boundBox = boundBox;
        objects = new ArrayList<BasicRectangle>();
        nodes = new QuadtreeNode[4];
    }

    /**
     * 
     * Splits the parent node into 4 leef nodes
     */
    public void split()
    {
        float parentX = boundBox.getPosition().getX();
        float parentY = boundBox.getPosition().getY();

        nodes[0] = new QuadtreeNode(level+1, new BasicRectangle(new Vector2f(parentX+boundBox.getWidth()/2, parentY), boundBox.getWidth()/2, boundBox.getHeight()/2));
        nodes[1] = new QuadtreeNode(level+1, new BasicRectangle(new Vector2f(parentX, parentY), boundBox.getWidth()/2, boundBox.getHeight()/2));
        nodes[2] = new QuadtreeNode(level+1, new BasicRectangle(new Vector2f(parentX, parentY+boundBox.getHeight()/2), boundBox.getWidth()/2, boundBox.getHeight()/2));
        nodes[3] = new QuadtreeNode(level+1, new BasicRectangle(new Vector2f(parentX+boundBox.getWidth()/2, parentY+boundBox.getHeight()/2), boundBox.getWidth()/2, boundBox.getHeight()/2));
        children  = true;
    }

    public int[] getIndex(BasicRectangle r)//TODO   use intersection methods
    {
        int[] indexs = new int[4];
        int e = 0;
        float verticalMidpoint = boundBox.getPosition().getX() + (boundBox.getWidth() / 2);
        float horizontalMidpoint = boundBox.getPosition().getY() + (boundBox.getHeight() / 2);
        //BasicRectangle can completely fit within the top quadrants
        boolean topQuadrant = (r.getPosition().getY() <= horizontalMidpoint);
        //BasicRectangle can completely fit within the bottom quadrants
        boolean bottomQuadrant = (r.getPosition().getY()+r.getHeight() >= horizontalMidpoint);
        //BasicRectangle can completely fit within the left quadrants
        boolean leftquadrant = (r.getPosition().getX() <= verticalMidpoint);
        //BasicRectangle can completely fit within the right quadrants
        boolean rightQuadrant = (r.getPosition().getX()+r.getWidth() >= verticalMidpoint);
        if(topQuadrant && rightQuadrant)
        {
            indexs[e] = 0;
            e++;
        }
        if(topQuadrant && leftquadrant)
        {
            indexs[e] = 1;
            e++;
        }
        if(bottomQuadrant && leftquadrant)
        {
            indexs[e] = 2;
            e++;
        }
        if(bottomQuadrant && rightQuadrant)
        {
            indexs[e] = 3;
        }
        for(int i =1;i<indexs.length;i++)
            if(indexs[i] == 0)
                indexs[i]=-1;
        return indexs;
    }

    public void insert(BasicRectangle r)//TODO
    {
        if(children)
        {
            int[] indexs = getIndex(r);
            for(int e : indexs)
                if(e != -1)
                    nodes[e].insert(r);
            return;
        }
        objects.add(r);
        if(objects.size()>MAX_OBJECTS && level < MAX_LEVELS)
        {
            if(!children)
                split();
            int i = 0;
            while(i<objects.size())
            {
                int[] indexs = getIndex(objects.get(i));
                for(int e : indexs)
                    if(e != -1)
                        nodes[e].insert(objects.get(i));
                objects.remove(i);
                i++;
            }
        }
        objects.trimToSize();
    }

    /**
     * Return all objects that could collide with the given object
     */
    public void retrieve(List<BasicRectangle> returnObjects, BasicRectangle r)
    {
        if(children)
        {
            int[] indexs = getIndex(r);
            for(int e : indexs)
                if(e != -1)
                    nodes[e].retrieve(returnObjects, r);
            return;
        }
        for(BasicRectangle e : objects)
            if(!returnObjects.contains(e))
                returnObjects.addAll(objects);
        /*if(!temp)
            retrieveHelper(returnObjects);
        temp = true;*/
        while(returnObjects.contains(r))
            returnObjects.remove(r);
    }

    public void retrieveHelper(List<BasicRectangle> returnObjects)
    {
        if(children)
            for(QuadtreeNode e : nodes)
                e.retrieveHelper(returnObjects);
        returnObjects.addAll(objects);
    }

    /**
     * 
     * clears the node
     */
    public void clear()
    {
        objects.clear();
        if(children)
            for(QuadtreeNode e : nodes)
                if(e != null)
                {
                    e.clear();
                    e = null;
                }
        children = false;
        temp = false;
    }

    public BasicRectangle getBoundBox()
    {
        return boundBox;
    }

    /**
     * 
     * Strictly debug only (draw method with be Quadtree.java)
     */
    public void draw()
    {
        if(children)
            for(QuadtreeNode e : nodes)
                e.draw();
        else
            boundBox.drawOutLine();
    }

    public void debugIndex(BasicRectangle r)
    {
        int[] indexs = getIndex(r);
        System.out.println(Arrays.toString(indexs));
        System.out.println("Parent node: "+objects.size());
        for(BasicRectangle e : objects)
            e.setColor(Color.yellow);
        for(int e : indexs)
            if(e != -1)
                System.out.println("node "+e+": "+nodes[e].objects.size());
    }

    public QuadtreeNode[] getNodes()
    {
        return nodes;
    }
}

1 个答案:

答案 0 :(得分:0)

在insert方法中,而不是删除对象(objects.remove(i);)将i的对象设置为null(objects.set(i,null);)。