package com.lfk.justweengine.utils.quad; import android.graphics.RectF; import java.util.ArrayList; import java.util.List; /** * Created by liufengkai on 16/9/18. */ public class QuadTree { private int MAX_OBJECTS = 10; private int MAX_LEVELS = 5; private int level; private List<RectF> objects; private RectF bounds; private QuadTree[] nodes; public QuadTree(int level, RectF bounds) { this.level = level; this.objects = new ArrayList<>(); this.bounds = bounds; this.nodes = new QuadTree[4]; } /** * clear all sub nodes */ public void clear() { objects.clear(); for (int i = 0; i < nodes.length; i++) { if (nodes[i] != null) { nodes[i].clear(); nodes[i] = null; } } } /** * split nodes */ private void split() { // width & height int subWidth = (int) (bounds.width() / 2); int subHeight = (int) (bounds.height() / 2); // x & y int x = (int) bounds.left; int y = (int) bounds.top; // split to four nodes nodes[0] = new QuadTree(level + 1, new RectF(x + subWidth, y, subWidth, subHeight)); nodes[1] = new QuadTree(level + 1, new RectF(x, y, subWidth, subHeight)); nodes[2] = new QuadTree(level + 1, new RectF(x, y + subHeight, subWidth, subHeight)); nodes[3] = new QuadTree(level + 1, new RectF(x + subWidth, y + subHeight, subWidth, subHeight)); } /** * 获取rect 所在的 index * * @param rectF 传入对象所在的矩形 * @return index 使用类别区分所在象限 */ private int getIndex(RectF rectF) { int index = -1; double verticalMidpoint = bounds.left + (bounds.width() / 2); double horizontalMidpoint = bounds.top + (bounds.height() / 2); // contain top boolean topQuadrant = rectF.top < horizontalMidpoint && rectF.top + rectF.height() < horizontalMidpoint; // contain bottom boolean bottomQuadrant = rectF.top > horizontalMidpoint; // contain left if (rectF.left < verticalMidpoint && rectF.left + rectF.width() < verticalMidpoint) { if (topQuadrant) { index = 1; } else if (bottomQuadrant) { index = 2; } // contain right } else if (rectF.left > verticalMidpoint) { if (topQuadrant) { index = 0; } else if (bottomQuadrant) { index = 3; } } return index; } /** * insert object to tree * * @param rectF object */ public void insert(RectF rectF) { if (nodes[0] != null) { int index = getIndex(rectF); if (index != -1) { nodes[index].insert(rectF); return; } } objects.add(rectF); if (objects.size() > MAX_OBJECTS && level < MAX_OBJECTS) { // don't have subNodes // split node 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 { // don't in subNode save to parent node. // eq: object on line i++; } } } } /** * return all the object collision with the object * * @param returnObjects return list * @param rectF object * @return list of collision */ public List<List<RectF>> retrieve(List<List<RectF>> returnObjects, RectF rectF) { int index = getIndex(rectF); if (index != -1 && nodes[0] != null) { nodes[index].retrieve(returnObjects, rectF); } returnObjects.add(objects); return returnObjects; } }