四叉数之box索引box

那是在很久很久以前,我在QQ群里面看到过别人用四叉树渲染无限地图, 当时一直想用C写以个。

奈何当时过于无知, 一直没学会。

最近一同事需要实现给定一个地标范围搜索下面所有的酒店, 四叉树是最为理想的结构。


凭借我当前肤浅的认为, 四叉树有3个功能:

1. 根据box 搜索在box范围内的所有点

2. 根据box 搜索所有包含或者与之相交的box

3. 根据点搜索这个点在那些box中


零零散散的画了一个下午的时间,终于解掉N久以前的心结。

渲染一个英雄周边范围的地图demo.{仅仅只是生成周边范围的Box}

搜索地标范围所有酒店应该算是第一种应用常景。我之前的心结应该算是第二种应用常景。



声明Box, Node对象

  enum BoxRelation {
        CROSS, CONTAIN, CONTAINED, NO_RELATION, UN_KNOW
    }

public static class Node<T> {

        private T s;
        private int depth;
        private Box box;
        private Node<T> NW, NE, SE, SW;

        private Node(Box box, int depth) {
            this.box = box;
            this.depth = depth;
        }

        @Override
        public String toString() {
            return "Node{" + "depth=" + depth + ", box=" + box + '}';
        }
    }

     public static class Box {

        private double xLow, yHigh, xHigh, yLow;

        public Box(double xLow, double yHigh, double xHigh, double yLow) {
            this.xLow = xLow;
            this.xHigh = xHigh;
            this.yLow = yLow;
            this.yHigh = yHigh;
        }

        public boolean contain(double x, double y) {
            return (x > xLow && x < xHigh && y > yLow && y < yHigh);
        }

        public static BoxRelation contain(Box box1, Box box2) {

            BoxRelation result = containInner(box1, box2);

            if (result != null) {
                return result;
            }

            if (BoxRelation.CONTAIN == containInner(box2, box1)) {
                return BoxRelation.CONTAINED;
            }

            return BoxRelation.NO_RELATION;

        }

        private static BoxRelation containInner(Box box1, Box box2) {

            boolean hadIn = false;
            boolean allIn = true;

            boolean contain;
            contain = box1.contain(box2.xLow, box2.yHigh);
            hadIn |= contain;
            allIn &= contain;

            contain = box1.contain(box2.xHigh, box2.yHigh);
            hadIn |= contain;
            allIn &= contain;

            contain = box1.contain(box2.xLow, box2.yLow);
            hadIn |= contain;
            allIn &= contain;

            contain = box1.contain(box2.xHigh, box2.yLow);
            hadIn |= contain;
            allIn &= contain;

            if (allIn) {
                return BoxRelation.CONTAIN;
            }

            if (hadIn) {
                return BoxRelation.CROSS;
            }

            return null;
        }

        @Override
        public String toString() {
            return "Box{" + "xLow=" + xLow + ", yHigh=" + yHigh + ", xHigh=" + xHigh + ", yLow=" + yLow + '}';
        }
    }

构建QuadTreeBox

public class QuadTreeBox<T> {

    private T s;
    private int depth;
    private Node<T> root;

    public QuadTreeBox(int depth, Box box, T s) {
        this.depth = depth;
        this.s = s;
        root = new Node<T>(box, depth);
        initQuadTree(root);
    }

//初始化数
    private void initQuadTree(Node<T> node) {

        Box box = node.box;
        int depth = node.depth;

        if (node.depth > 0) {

            node.NW = new Node<T>(new Box(box.xLow, box.yHigh, box.xLow + (box.xHigh - box.xLow) / 2, box.yHigh
                    - (box.yHigh - box.yLow) / 2), depth - 1);
            initQuadTree(node.NW);

            node.NE = new Node<T>(new Box(box.xLow + (box.xHigh - box.xLow) / 2, box.yHigh, box.xHigh, box.yHigh
                    - (box.yHigh - box.yLow) / 2), depth - 1);
            initQuadTree(node.NE);

            node.SE = new Node<T>(new Box(box.xLow + (box.xHigh - box.xLow) / 2,
                    box.yHigh - (box.yHigh - box.yLow) / 2, box.xHigh, box.yLow), depth - 1);
            initQuadTree(node.SE);

            node.SW = new Node<T>(new Box(box.xLow, box.yHigh - (box.yHigh - box.yLow) / 2, box.xLow
                    + (box.xHigh - box.xLow) / 2, box.yLow), depth - 1);
            initQuadTree(node.SW);

        }

    }

    private void queryB(Node<T> node, Box box, List<Node<T>> result) {

        if(node == null){
            return;
        }

        switch (Box.contain(node.box, box)) {
        case CONTAIN:
            if(node.depth != 0){
                queryA(node, box, result);
                break;
            }
            result.add(node);
        case CROSS:
            if(node.depth != 0){
                queryA(node, box, result);
                break;
            }
            result.add(node);
            break;
        case CONTAINED:
            if(node.depth != 0){
                queryA(node, box, result);
                break;
            }
            result.add(node);
            break;
        default:
            break;
        }
    }

    private void queryA(Node<T> node, Box box, List<Node<T>> result) {

        if (node == null) {
            return;
        }

        queryB(node.NW, box, result);
        queryB(node.NE, box, result);
        queryB(node.SE, box, result);
        queryB(node.SW, box, result);

    }

//查需与Box范围内应该渲染的Box
    public List<Node<T>> query(Box box) {

        List<Node<T>> result = Lists.newArrayList();
        queryA(root, box, result);
        return result;
    }

   
    
}



测试代码

<pre name="code" class="java">   private void display(Node<T> node, String label) {

        if (node == null) {
            return;
        }

        System.out.println(node.depth + "\t" + label + "\t" + node.box.toString());
        display(node.NW, "NW");
        display(node.NE, "NE");
        display(node.SE, "SE");
        display(node.SW, "SW");

    }

    public void display() {
        display(root, "root");
    }


   public static void main(String[] args) {

        QuadTreeBox<String> treeBox = new QuadTreeBox<String>(5, new Box(-10, 10, 10, -10), "root");
        treeBox.display();

        System.out.println("----------------------------");

        for (Node<String> node : treeBox.query(new Box(-1, 1, 1, 1))) {
            System.out.println(node.depth + "\t" + node.box.toString());
        }
    }


测试结果:

----------------------------
0    Box{xLow=-1.25, yHigh=1.25, xHigh=-0.625, yLow=0.625}
0    Box{xLow=0.625, yHigh=1.25, xHigh=1.25, yLow=0.625}














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值