All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.conversantmedia.util.collection.spatial.Branch Maven / Gradle / Ivy

There is a newer version: 1.0.5
Show newest version
package com.conversantmedia.util.collection.spatial;

/*
 * #%L
 * Conversant RTree
 * ~~
 * Conversantmedia.com © 2016, Conversant, Inc. Conversant® is a trademark of Conversant, Inc.
 * ~~
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import java.util.function.Consumer;

/**
 * RTree node that contains leaf nodes
 *
 * Created by jcairns on 4/30/15.
 */
final class Branch implements Node {

    private final RectBuilder builder;

    private final int mMax;

    private final int mMin;

    private final RTree.Split splitType;

    private final Node[] child;

    private HyperRect mbr;

    private int size;

    Branch(final RectBuilder builder, final int mMin, final int mMax, final RTree.Split splitType) {
        this.mMin = mMin;
        this.mMax = mMax;
        this.builder = builder;
        this.mbr = null;
        this.size = 0;
        this.child = new Node[mMax];
        this.splitType = splitType;
    }

    /**
     * Add a new node to this branch's list of children
     *
     * @param n node to be added (can be leaf or branch)
     * @return position of the added node
     */
    protected int addChild(final Node n) {
        if(size < mMax) {
            child[size++] = n;

            if(mbr != null) {
                mbr = mbr.getMbr(n.getBound());
            } else {
                mbr = n.getBound();
            }

            return size - 1;
        }
        else {
            throw new RuntimeException("Too many children");
        }
    }

    @Override
    public boolean isLeaf() {
        return false;
    }

    @Override
    public HyperRect getBound() {
        return mbr;
    }

    /**
     * Adds a data entry to one of the child nodes of this branch
     *
     * @param t data entry to add
     * @return Node that the entry was added to
     */
    @Override
    public Node add(final T t) {
        final HyperRect tRect = builder.getBBox(t);
        if(size < mMin) {
            for(int i=0; i nextLeaf = Leaf.create(builder, mMin, mMax, splitType);
            nextLeaf.add(t);
            final int nextChild = addChild(nextLeaf);
            mbr = mbr.getMbr(child[nextChild].getBound());

            return this;

        } else {
            final int bestLeaf = chooseLeaf(t, tRect);

            child[bestLeaf] = child[bestLeaf].add(t);
            mbr = mbr.getMbr(child[bestLeaf].getBound());

            return this;
        }
    }

    @Override
    public Node remove(final T t) {
        final HyperRect tRect = builder.getBBox(t);

        for (int i = 0; i < size; i++) {
            if (child[i].getBound().intersects(tRect)) {
                child[i] = child[i].remove(t);

                if (child[i] == null) {
                    System.arraycopy(child, i+1, child, i, size-i-1);
                    size--;
                    child[size] = null;
                    if(size > 0) i--;
                }
            }
        }

        if (size == 0) {
            return null;
        } else if (size == 1) {
            // unsplit branch
            return child[0];
        }

        mbr = child[0].getBound();
        for(int i=1; i update(final T told, final T tnew) {
        final HyperRect tRect = builder.getBBox(told);
        for(int i = 0; i < size; i++){
            if(tRect.intersects(child[i].getBound())) {
                child[i] = child[i].update(told, tnew);
            }
            if(i==0) {
                mbr = child[i].getBound();
            } else {
                mbr = mbr.getMbr(child[i].getBound());
            }
        }
        return this;
    }

    @Override
    public void search(HyperRect rect, Consumer consumer) {
        for(int i = 0; i < size; i++) {
            if(rect.intersects(child[i].getBound())) {
                child[i].search(rect, consumer);
            }
        }
    }

    @Override
    public int search(final HyperRect rect, final T[] t, int n) {
        final int tLen = t.length;
        final int n0 = n;
        for(int i=0; i < size && n < tLen; i++) {
            if (rect.intersects(child[i].getBound())) {
                n += child[i].search(rect, t, n);
            }
        }
        return n-n0;
    }

    @Override
    public void intersects(HyperRect rect, Consumer consumer) {
        for(int i = 0; i < size; i++) {
            if(rect.intersects(child[i].getBound())) {
                child[i].intersects(rect, consumer);
            }
        }
    }

    @Override
    public int intersects(final HyperRect rect, final T[] t, int n) {
        final int tLen = t.length;
        final int n0 = n;
        for(int i=0; i < size && n < tLen; i++) {
            if (rect.intersects(child[i].getBound())) {
                n += child[i].intersects(rect, t, n);
            }
        }
        return n-n0;
    }

    /**
     * @return number of child nodes
     */
    @Override
    public int size() {
        return size;
    }

    @Override
    public int totalSize() {
        int s = 0;
        for(int i=0; i 0) {
            int bestNode = 0;
            HyperRect childMbr = child[0].getBound().getMbr(tRect);
            double leastEnlargement = childMbr.cost() - (child[0].getBound().cost() + tRect.cost());
            double leastPerimeter   = childMbr.perimeter();

            for(int i = 1; i n = Leaf.create(builder, mMin, mMax, splitType);
            n.add(t);
            child[size++] = n;

            if(mbr == null) {
                mbr = n.getBound();
            }
            else {
                mbr = mbr.getMbr(n.getBound());
            }

            return size-1;
        }
    }

    /**
     * Return child nodes of this branch.
     *
     * @return array of child nodes (leaves or branches)
     */
    public Node[] getChildren() {
        return child;
    }

    @Override
    public void forEach(Consumer consumer) {
        for(int i = 0; i < size; i++) {
            child[i].forEach(consumer);
        }
    }

    @Override
    public boolean contains(HyperRect rect, T t) {
        for(int i = 0; i < size; i++) {
            if(rect.intersects(child[i].getBound())) {
                child[i].contains(rect, t);
            }
        }
        return false;
    }

    @Override
    public void collectStats(Stats stats, int depth) {
        for(int i = 0; i < size; i++) {
            child[i].collectStats(stats, depth + 1);
        }
        stats.countBranchAtDepth(depth);
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder(128);
        sb.append("BRANCH[");
        sb.append(mbr);
        sb.append(']');

        return sb.toString();
    }

    @Override
    public Node instrument() {
        for(int i = 0; i < size; i++) {
            child[i] = child[i].instrument();
        }
        return new CounterNode<>(this);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy