Example usage for org.apache.hadoop.util IndexedSortable IndexedSortable

List of usage examples for org.apache.hadoop.util IndexedSortable IndexedSortable

Introduction

In this page you can find the example usage for org.apache.hadoop.util IndexedSortable IndexedSortable.

Prototype

IndexedSortable

Source Link

Usage

From source file:com.ricemap.spateDB.core.GlobalIndex.java

License:Apache License

public int knn(final double qt, final double qx, final double qy, int k, ResultCollector2<S, Double> output) {
    double query_area = ((getMBR().t2 - getMBR().t1) * (getMBR().x2 - getMBR().x1)
            * (getMBR().y2 - getMBR().y1)) * k / size();
    double query_radius = Math.sqrt(query_area / Math.PI);

    boolean result_correct;
    final Vector<Double> distances = new Vector<Double>();
    final Vector<S> shapes = new Vector<S>();
    // Find results in the range and increase this range if needed to ensure
    // correctness of the answer
    do {/*from   ww w. ja va  2 s.c  om*/
        // Initialize result and query range
        distances.clear();
        shapes.clear();
        Prism queryRange = new Prism();
        queryRange.t1 = qt - query_radius / 2;
        queryRange.x1 = qx - query_radius / 2;
        queryRange.y1 = qy - query_radius / 2;
        queryRange.t2 = qt + query_radius / 2;
        queryRange.x2 = qx + query_radius / 2;
        queryRange.y2 = qy + query_radius / 2;
        // Retrieve all results in range
        rangeQuery(queryRange, new ResultCollector<S>() {
            @Override
            public void collect(S shape) {
                distances.add(shape.distanceTo(qt, qx, qy));
                shapes.add((S) shape.clone());
            }
        });
        if (shapes.size() <= k) {
            // Didn't find k elements in range, double the range to get more
            // items
            if (shapes.size() == size() || shapes.size() == k) {
                // Already returned all possible elements
                result_correct = true;
            } else {
                query_radius *= 2;
                result_correct = false;
            }
        } else {
            // Sort items by distance to get the kth neighbor
            IndexedSortable s = new IndexedSortable() {
                @Override
                public void swap(int i, int j) {
                    double temp_distance = distances.elementAt(i);
                    distances.set(i, distances.elementAt(j));
                    distances.set(j, temp_distance);

                    S temp_shape = shapes.elementAt(i);
                    shapes.set(i, shapes.elementAt(j));
                    shapes.set(j, temp_shape);
                }

                @Override
                public int compare(int i, int j) {
                    // Note. Equality is not important to check because
                    // items with the
                    // same distance can be ordered anyway.
                    if (distances.elementAt(i) < distances.elementAt(j))
                        return -1;
                    return 1;
                }
            };
            IndexedSorter sorter = new QuickSort();
            sorter.sort(s, 0, shapes.size());
            if (distances.elementAt(k - 1) > query_radius) {
                result_correct = false;
                query_radius = distances.elementAt(k);
            } else {
                result_correct = true;
            }
        }
    } while (!result_correct);

    int result_size = Math.min(k, shapes.size());
    if (output != null) {
        for (int i = 0; i < result_size; i++) {
            output.collect(shapes.elementAt(i), distances.elementAt(i));
        }
    }
    return result_size;
}

From source file:com.ricemap.spateDB.core.RTree.java

License:Apache License

/**
 * Builds the RTree given a serialized list of elements. It uses the given
 * stockObject to deserialize these elements and build the tree. Also writes
 * the created tree to the disk directly.
 * //from   ww  w  . j  a va  2s . co m
 * @param elements
 *            - serialization of elements to be written
 * @param offset
 *            - index of the first element to use in the elements array
 * @param len
 *            - number of bytes to user from the elements array
 * @param bytesAvailable
 *            - size available (in bytes) to store the tree structures
 * @param dataOut
 *            - an output to use for writing the tree to
 * @param fast_sort
 *            - setting this to <code>true</code> allows the method to run
 *            faster by materializing the offset of each element in the list
 *            which speeds up the comparison. However, this requires an
 *            additional 16 bytes per element. So, for each 1M elements, the
 *            method will require an additional 16 M bytes (approximately).
 */
public void bulkLoadWrite(final byte[] element_bytes, final int offset, final int len, final int degree,
        DataOutput dataOut, final boolean fast_sort, final boolean columnarStorage) {
    try {
        columnar = columnarStorage;
        //TODO: the order of fields should be stable under Oracle JVM, but not guaranteed
        Field[] fields = stockObject.getClass().getDeclaredFields();

        // Count number of elements in the given text
        int i_start = offset;
        final Text line = new Text();
        while (i_start < offset + len) {
            int i_end = skipToEOL(element_bytes, i_start);
            // Extract the line without end of line character
            line.set(element_bytes, i_start, i_end - i_start - 1);
            stockObject.fromText(line);

            elementCount++;
            i_start = i_end;
        }
        LOG.info("Bulk loading an RTree with " + elementCount + " elements");

        // It turns out the findBestDegree returns the best degree when the
        // whole
        // tree is loaded to memory when processed. However, as current
        // algorithms
        // process the tree while it's on disk, a higher degree should be
        // selected
        // such that a node fits one file block (assumed to be 4K).
        // final int degree = findBestDegree(bytesAvailable, elementCount);
        LOG.info("Writing an RTree with degree " + degree);

        int height = Math.max(1, (int) Math.ceil(Math.log(elementCount) / Math.log(degree)));
        int leafNodeCount = (int) Math.pow(degree, height - 1);
        if (elementCount < 2 * leafNodeCount && height > 1) {
            height--;
            leafNodeCount = (int) Math.pow(degree, height - 1);
        }
        int nodeCount = (int) ((Math.pow(degree, height) - 1) / (degree - 1));
        int nonLeafNodeCount = nodeCount - leafNodeCount;

        // Keep track of the offset of each element in the text
        final int[] offsets = new int[elementCount];
        final int[] ids = new int[elementCount];
        final double[] ts = fast_sort ? new double[elementCount] : null;
        final double[] xs = fast_sort ? new double[elementCount] : null;
        final double[] ys = fast_sort ? new double[elementCount] : null;

        //initialize columnar data output
        ByteArrayOutputStream index_bos = new ByteArrayOutputStream();
        DataOutputStream index_dos = new DataOutputStream(index_bos);
        ByteArrayOutputStream[] bos = new ByteArrayOutputStream[fields.length];
        DataOutputStream[] dos = new DataOutputStream[fields.length];
        for (int i = 0; i < bos.length; i++) {
            bos[i] = new ByteArrayOutputStream();
            dos[i] = new DataOutputStream(bos[i]);
        }

        i_start = offset;
        line.clear();
        for (int i = 0; i < elementCount; i++) {
            offsets[i] = i_start;
            ids[i] = i;
            int i_end = skipToEOL(element_bytes, i_start);
            if (xs != null) {
                // Extract the line with end of line character
                line.set(element_bytes, i_start, i_end - i_start - 1);
                stockObject.fromText(line);
                // Sample center of the shape
                ts[i] = (stockObject.getMBR().t1 + stockObject.getMBR().t2) / 2;
                xs[i] = (stockObject.getMBR().x1 + stockObject.getMBR().x2) / 2;
                ys[i] = (stockObject.getMBR().y1 + stockObject.getMBR().y2) / 2;

                //build columnar storage
                if (stockObject instanceof Point3d) {
                    index_dos.writeDouble(ts[i]);
                    index_dos.writeDouble(xs[i]);
                    index_dos.writeDouble(ys[i]);
                } else {
                    throw new RuntimeException("Indexing non-point shape with RTREE is not supported yet");
                }

                for (int j = 0; j < fields.length; j++) {
                    if (fields[j].getType().equals(Integer.TYPE)) {
                        dos[j].writeInt(fields[j].getInt(stockObject));
                    } else if (fields[j].getType().equals(Double.TYPE)) {
                        dos[j].writeDouble(fields[j].getDouble(stockObject));
                    } else if (fields[j].getType().equals(Long.TYPE)) {
                        dos[j].writeLong(fields[j].getLong(stockObject));
                    } else {
                        continue;
                        //throw new RuntimeException("Field type is not supported yet");
                    }
                }
            }
            i_start = i_end;
        }
        index_dos.close();
        for (int i = 0; i < dos.length; i++) {
            dos[i].close();
        }

        /** A struct to store information about a split */
        class SplitStruct extends Prism {
            /** Start and end index for this split */
            int index1, index2;
            /** Direction of this split */
            byte direction;
            /** Index of first element on disk */
            int offsetOfFirstElement;

            static final byte DIRECTION_T = 0;
            static final byte DIRECTION_X = 1;
            static final byte DIRECTION_Y = 2;

            SplitStruct(int index1, int index2, byte direction) {
                this.index1 = index1;
                this.index2 = index2;
                this.direction = direction;
            }

            @Override
            public void write(DataOutput out) throws IOException {
                //
                if (columnarStorage)
                    out.writeInt(index1);
                else
                    out.writeInt(offsetOfFirstElement);
                super.write(out);
            }

            void partition(Queue<SplitStruct> toBePartitioned) {
                IndexedSortable sortableT;
                IndexedSortable sortableX;
                IndexedSortable sortableY;

                if (fast_sort) {
                    // Use materialized xs[] and ys[] to do the comparisons
                    sortableT = new IndexedSortable() {
                        @Override
                        public void swap(int i, int j) {
                            // Swap ts
                            double tempt = ts[i];
                            ts[i] = ts[j];
                            ts[j] = tempt;
                            // Swap xs
                            double tempx = xs[i];
                            xs[i] = xs[j];
                            xs[j] = tempx;
                            // Swap ys
                            double tempY = ys[i];
                            ys[i] = ys[j];
                            ys[j] = tempY;
                            // Swap id
                            int tempid = offsets[i];
                            offsets[i] = offsets[j];
                            offsets[j] = tempid;

                            tempid = ids[i];
                            ids[i] = ids[j];
                            ids[j] = tempid;
                        }

                        @Override
                        public int compare(int i, int j) {
                            if (ts[i] < ts[j])
                                return -1;
                            if (ts[i] > ts[j])
                                return 1;
                            return 0;
                        }
                    };
                    sortableX = new IndexedSortable() {
                        @Override
                        public void swap(int i, int j) {
                            // Swap ts
                            double tempt = ts[i];
                            ts[i] = ts[j];
                            ts[j] = tempt;
                            // Swap xs
                            double tempx = xs[i];
                            xs[i] = xs[j];
                            xs[j] = tempx;
                            // Swap ys
                            double tempY = ys[i];
                            ys[i] = ys[j];
                            ys[j] = tempY;
                            // Swap id
                            int tempid = offsets[i];
                            offsets[i] = offsets[j];
                            offsets[j] = tempid;
                            tempid = ids[i];
                            ids[i] = ids[j];
                            ids[j] = tempid;
                        }

                        @Override
                        public int compare(int i, int j) {
                            if (ts[i] < ts[j])
                                return -1;
                            if (xs[i] < xs[j])
                                return -1;
                            if (xs[i] > xs[j])
                                return 1;
                            return 0;
                        }
                    };

                    sortableY = new IndexedSortable() {
                        @Override
                        public void swap(int i, int j) {
                            // Swap ts
                            double tempt = ts[i];
                            ts[i] = ts[j];
                            ts[j] = tempt;
                            // Swap xs
                            double tempx = xs[i];
                            xs[i] = xs[j];
                            xs[j] = tempx;
                            // Swap ys
                            double tempY = ys[i];
                            ys[i] = ys[j];
                            ys[j] = tempY;
                            // Swap id
                            int tempid = offsets[i];
                            offsets[i] = offsets[j];
                            offsets[j] = tempid;

                            tempid = ids[i];
                            ids[i] = ids[j];
                            ids[j] = tempid;
                        }

                        @Override
                        public int compare(int i, int j) {
                            if (ys[i] < ys[j])
                                return -1;
                            if (ys[i] > ys[j])
                                return 1;
                            return 0;
                        }
                    };
                } else {
                    // No materialized xs and ys. Always deserialize objects
                    // to compare
                    sortableT = new IndexedSortable() {
                        @Override
                        public void swap(int i, int j) {
                            // Swap id
                            int tempid = offsets[i];
                            offsets[i] = offsets[j];
                            offsets[j] = tempid;

                            tempid = ids[i];
                            ids[i] = ids[j];
                            ids[j] = tempid;
                        }

                        @Override
                        public int compare(int i, int j) {
                            // Get end of line
                            int eol = skipToEOL(element_bytes, offsets[i]);
                            line.set(element_bytes, offsets[i], eol - offsets[i] - 1);
                            stockObject.fromText(line);
                            double ti = (stockObject.getMBR().t1 + stockObject.getMBR().t2) / 2;

                            eol = skipToEOL(element_bytes, offsets[j]);
                            line.set(element_bytes, offsets[j], eol - offsets[j] - 1);
                            stockObject.fromText(line);
                            double tj = (stockObject.getMBR().t1 + stockObject.getMBR().t2) / 2;
                            if (ti < tj)
                                return -1;
                            if (ti > tj)
                                return 1;
                            return 0;
                        }
                    };
                    sortableX = new IndexedSortable() {
                        @Override
                        public void swap(int i, int j) {
                            // Swap id
                            int tempid = offsets[i];
                            offsets[i] = offsets[j];
                            offsets[j] = tempid;

                            tempid = ids[i];
                            ids[i] = ids[j];
                            ids[j] = tempid;
                        }

                        @Override
                        public int compare(int i, int j) {
                            // Get end of line
                            int eol = skipToEOL(element_bytes, offsets[i]);
                            line.set(element_bytes, offsets[i], eol - offsets[i] - 1);
                            stockObject.fromText(line);
                            double xi = (stockObject.getMBR().x1 + stockObject.getMBR().x2) / 2;

                            eol = skipToEOL(element_bytes, offsets[j]);
                            line.set(element_bytes, offsets[j], eol - offsets[j] - 1);
                            stockObject.fromText(line);
                            double xj = (stockObject.getMBR().x1 + stockObject.getMBR().x2) / 2;
                            if (xi < xj)
                                return -1;
                            if (xi > xj)
                                return 1;
                            return 0;
                        }
                    };

                    sortableY = new IndexedSortable() {
                        @Override
                        public void swap(int i, int j) {
                            // Swap id
                            int tempid = offsets[i];
                            offsets[i] = offsets[j];
                            offsets[j] = tempid;

                            tempid = ids[i];
                            ids[i] = ids[j];
                            ids[j] = tempid;
                        }

                        @Override
                        public int compare(int i, int j) {
                            int eol = skipToEOL(element_bytes, offsets[i]);
                            line.set(element_bytes, offsets[i], eol - offsets[i] - 1);
                            stockObject.fromText(line);
                            double yi = (stockObject.getMBR().y1 + stockObject.getMBR().y2) / 2;

                            eol = skipToEOL(element_bytes, offsets[j]);
                            line.set(element_bytes, offsets[j], eol - offsets[j] - 1);
                            stockObject.fromText(line);
                            double yj = (stockObject.getMBR().y1 + stockObject.getMBR().y2) / 2;
                            if (yi < yj)
                                return -1;
                            if (yi > yj)
                                return 1;
                            return 0;
                        }
                    };
                }

                final IndexedSorter sorter = new QuickSort();

                final IndexedSortable[] sortables = new IndexedSortable[3];
                sortables[SplitStruct.DIRECTION_T] = sortableT;
                sortables[SplitStruct.DIRECTION_X] = sortableX;
                sortables[SplitStruct.DIRECTION_Y] = sortableY;

                sorter.sort(sortables[direction], index1, index2);

                // Partition into maxEntries partitions (equally) and
                // create a SplitStruct for each partition
                int i1 = index1;
                for (int iSplit = 0; iSplit < degree; iSplit++) {
                    int i2 = index1 + (index2 - index1) * (iSplit + 1) / degree;
                    SplitStruct newSplit;
                    if (direction == 0) {
                        newSplit = new SplitStruct(i1, i2, (byte) 1);
                    } else if (direction == 1) {
                        newSplit = new SplitStruct(i1, i2, (byte) 2);
                    } else {
                        newSplit = new SplitStruct(i1, i2, (byte) 0);
                    }
                    toBePartitioned.add(newSplit);
                    i1 = i2;
                }
            }
        }

        // All nodes stored in level-order traversal
        Vector<SplitStruct> nodes = new Vector<SplitStruct>();
        final Queue<SplitStruct> toBePartitioned = new LinkedList<SplitStruct>();
        toBePartitioned.add(new SplitStruct(0, elementCount, SplitStruct.DIRECTION_X));

        while (!toBePartitioned.isEmpty()) {
            SplitStruct split = toBePartitioned.poll();
            if (nodes.size() < nonLeafNodeCount) {
                // This is a non-leaf
                split.partition(toBePartitioned);
            }
            nodes.add(split);
        }

        if (nodes.size() != nodeCount) {
            throw new RuntimeException(
                    "Expected node count: " + nodeCount + ". Real node count: " + nodes.size());
        }

        // Now we have our data sorted in the required order. Start building
        // the tree.
        // Store the offset of each leaf node in the tree
        FSDataOutputStream fakeOut = new FSDataOutputStream(new java.io.OutputStream() {
            // Null output stream
            @Override
            public void write(int b) throws IOException {
                // Do nothing
            }

            @Override
            public void write(byte[] b, int off, int len) throws IOException {
                // Do nothing
            }

            @Override
            public void write(byte[] b) throws IOException {
                // Do nothing
            }
        }, null, TreeHeaderSize + nodes.size() * NodeSize);
        for (int i_leaf = nonLeafNodeCount, i = 0; i_leaf < nodes.size(); i_leaf++) {
            nodes.elementAt(i_leaf).offsetOfFirstElement = (int) fakeOut.getPos();
            if (i != nodes.elementAt(i_leaf).index1)
                throw new RuntimeException();
            double t1, x1, y1, t2, x2, y2;

            // Initialize MBR to first object
            int eol = skipToEOL(element_bytes, offsets[i]);
            fakeOut.write(element_bytes, offsets[i], eol - offsets[i]);
            line.set(element_bytes, offsets[i], eol - offsets[i] - 1);
            stockObject.fromText(line);
            Prism mbr = stockObject.getMBR();
            t1 = mbr.t1;
            x1 = mbr.x1;
            y1 = mbr.y1;
            t2 = mbr.t2;
            x2 = mbr.x2;
            y2 = mbr.y2;
            i++;

            while (i < nodes.elementAt(i_leaf).index2) {
                eol = skipToEOL(element_bytes, offsets[i]);
                fakeOut.write(element_bytes, offsets[i], eol - offsets[i]);
                line.set(element_bytes, offsets[i], eol - offsets[i] - 1);
                stockObject.fromText(line);
                mbr = stockObject.getMBR();
                if (mbr.t1 < t1)
                    t1 = mbr.t1;
                if (mbr.x1 < x1)
                    x1 = mbr.x1;
                if (mbr.y1 < y1)
                    y1 = mbr.y1;
                if (mbr.t2 > t2)
                    t2 = mbr.t2;
                if (mbr.x2 > x2)
                    x2 = mbr.x2;
                if (mbr.y2 > y2)
                    y2 = mbr.y2;
                i++;
            }
            nodes.elementAt(i_leaf).set(t1, x1, y1, t2, x2, y2);
        }
        fakeOut.close();
        fakeOut = null;

        // Calculate MBR and offsetOfFirstElement for non-leaves
        for (int i_node = nonLeafNodeCount - 1; i_node >= 0; i_node--) {
            int i_first_child = i_node * degree + 1;
            nodes.elementAt(i_node).offsetOfFirstElement = nodes.elementAt(i_first_child).offsetOfFirstElement;
            int i_child = 0;
            Prism mbr;
            mbr = nodes.elementAt(i_first_child + i_child);
            double t1 = mbr.t1;
            double x1 = mbr.x1;
            double y1 = mbr.y1;
            double t2 = mbr.t2;
            double x2 = mbr.x2;
            double y2 = mbr.y2;
            i_child++;

            while (i_child < degree) {
                mbr = nodes.elementAt(i_first_child + i_child);
                if (mbr.t1 < t1)
                    t1 = mbr.t1;
                if (mbr.x1 < x1)
                    x1 = mbr.x1;
                if (mbr.y1 < y1)
                    y1 = mbr.y1;
                if (mbr.t2 > t2)
                    t2 = mbr.t2;
                if (mbr.x2 > x2)
                    x2 = mbr.x2;
                if (mbr.y2 > y2)
                    y2 = mbr.y2;
                i_child++;
            }
            nodes.elementAt(i_node).set(t1, x1, y1, t2, x2, y2);
        }

        // Start writing the tree
        // write tree header (including size)
        // Total tree size. (== Total bytes written - 8 bytes for the size
        // itself)
        dataOut.writeInt(TreeHeaderSize + NodeSize * nodeCount + len);
        // Tree height
        dataOut.writeInt(height);
        // Degree
        dataOut.writeInt(degree);
        dataOut.writeInt(elementCount);

        //isColumnar
        dataOut.writeInt(columnarStorage ? 1 : 0);

        // write nodes
        for (SplitStruct node : nodes) {
            node.write(dataOut);
        }
        // write elements
        if (columnarStorage) {
            byte[] index_bs = index_bos.toByteArray();
            byte[][] bss = new byte[bos.length][];
            for (int i = 0; i < bss.length; i++) {
                bss[i] = bos[i].toByteArray();
            }
            for (int element_i = 0; element_i < elementCount; element_i++) {
                //int eol = skipToEOL(element_bytes, offsets[element_i]);
                //dataOut.write(element_bytes, offsets[element_i], eol - offsets[element_i]);
                dataOut.write(index_bs, ids[element_i] * IndexUnitSize, IndexUnitSize);
            }

            for (int i = 0; i < fields.length; i++) {
                int fieldSize = 0;
                if (fields[i].getType().equals(Integer.TYPE)) {
                    fieldSize = 4;
                } else if (fields[i].getType().equals(Long.TYPE)) {
                    fieldSize = 8;
                } else if (fields[i].getType().equals(Double.TYPE)) {
                    fieldSize = 8;
                } else {
                    //throw new RuntimeException("Unsupported field type: " + fields[i].getType().getName());
                    continue;
                }
                for (int element_i = 0; element_i < elementCount; element_i++) {
                    //int eol = skipToEOL(element_bytes, offsets[element_i]);
                    //dataOut.write(element_bytes, offsets[element_i], eol - offsets[element_i]);
                    dataOut.write(bss[i], ids[element_i] * fieldSize, fieldSize);
                }
            }
        } else {
            for (int element_i = 0; element_i < elementCount; element_i++) {
                int eol = skipToEOL(element_bytes, offsets[element_i]);
                dataOut.write(element_bytes, offsets[element_i], eol - offsets[element_i]);
            }
        }

    } catch (IOException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

From source file:com.ricemap.spateDB.core.RTree.java

License:Apache License

/**
 * Create Prisms that together pack all points in sample such that each
 * Prism contains roughly the same number of points. In other words it tries
 * to balance number of points in each Prism. Works similar to the logic of
 * bulkLoad but does only one level of Prisms.
 * //  w ww . jav  a 2s  .c  om
 * @param samples
 * @param gridInfo
 *            - Used as a hint for number of Prisms per row or column
 * @return
 */
public static Prism[] packInPrisms(GridInfo gridInfo, final Point3d[] sample) {
    Prism[] Prisms = new Prism[gridInfo.layers * gridInfo.columns * gridInfo.rows];
    int iPrism = 0;
    // Sort in t direction
    final IndexedSortable sortableT = new IndexedSortable() {
        @Override
        public void swap(int i, int j) {
            Point3d temp = sample[i];
            sample[i] = sample[j];
            sample[j] = temp;
        }

        @Override
        public int compare(int i, int j) {
            if (sample[i].t < sample[j].t)
                return -1;
            if (sample[i].t > sample[j].t)
                return 1;
            return 0;
        }
    };
    // Sort in x direction
    final IndexedSortable sortableX = new IndexedSortable() {
        @Override
        public void swap(int i, int j) {
            Point3d temp = sample[i];
            sample[i] = sample[j];
            sample[j] = temp;
        }

        @Override
        public int compare(int i, int j) {
            if (sample[i].x < sample[j].x)
                return -1;
            if (sample[i].x > sample[j].x)
                return 1;
            return 0;
        }
    };

    // Sort in y direction
    final IndexedSortable sortableY = new IndexedSortable() {
        @Override
        public void swap(int i, int j) {
            Point3d temp = sample[i];
            sample[i] = sample[j];
            sample[j] = temp;
        }

        @Override
        public int compare(int i, int j) {
            if (sample[i].y < sample[j].y)
                return -1;
            if (sample[i].y > sample[j].y)
                return 1;
            return 0;
        }
    };

    final QuickSort quickSort = new QuickSort();

    quickSort.sort(sortableT, 0, sample.length);
    //tony
    int tindex1 = 0;
    double t1 = gridInfo.t1;
    for (int lay = 0; lay < gridInfo.layers; lay++) {
        int tindex2 = sample.length * (lay + 1) / gridInfo.layers;

        double t2 = lay == gridInfo.layers - 1 ? gridInfo.t2 : sample[tindex2 - 1].t;

        quickSort.sort(sortableX, tindex1, tindex2);

        int xindex1 = tindex1;
        double x1 = gridInfo.x1;
        for (int col = 0; col < gridInfo.columns; col++) {
            int xindex2 = sample.length * (col + 1) / gridInfo.columns;

            // Determine extents for all Prisms in this column
            double x2 = col == gridInfo.columns - 1 ? gridInfo.x2 : sample[xindex2 - 1].x;

            // Sort all points in this column according to its y-coordinate
            quickSort.sort(sortableY, xindex1, xindex2);

            // Create Prisms in this column
            double y1 = gridInfo.y1;
            for (int row = 0; row < gridInfo.rows; row++) {
                int yindex2 = xindex1 + (xindex2 - xindex1) * (row + 1) / gridInfo.rows;
                double y2 = row == gridInfo.rows - 1 ? gridInfo.y2 : sample[yindex2 - 1].y;

                Prisms[iPrism++] = new Prism(t1, x1, y1, t2, x2, y2);
                y1 = y2;
            }

            xindex1 = xindex2;
            x1 = x2;
        }
    }
    return Prisms;
}

From source file:com.ricemap.spateDB.core.RTree.java

License:Apache License

/**
 * k nearest neighbor query Note: Current algorithm is approximate just for
 * simplicity. Writing an exact algorithm is on our TODO list
 * /*from www . j  a va  2 s.co  m*/
 * @param qx
 * @param qy
 * @param k
 * @param output
 */
public int knn(final double qt, final double qx, final double qy, int k,
        final ResultCollector2<T, Double> output) {
    double query_area = ((getMBR().x2 - getMBR().x1) * (getMBR().y2 - getMBR().y1)) * k / getElementCount();
    double query_radius = Math.sqrt(query_area / Math.PI);

    boolean result_correct;
    final Vector<Double> distances = new Vector<Double>();
    final Vector<T> shapes = new Vector<T>();
    // Find results in the range and increase this range if needed to ensure
    // correctness of the answer
    do {
        // Initialize result and query range
        distances.clear();
        shapes.clear();
        Prism queryRange = new Prism();
        queryRange.x1 = qx - query_radius / 2;
        queryRange.y1 = qy - query_radius / 2;
        queryRange.x2 = qx + query_radius / 2;
        queryRange.y2 = qy + query_radius / 2;
        // Retrieve all results in range
        searchColumnar(queryRange, new ResultCollector<Writable>() {
            @Override
            public void collect(Writable shape) {
                distances.add(((T) shape).distanceTo(qt, qx, qy));
                shapes.add((T) ((T) shape).clone());
            }
        }, null);
        if (shapes.size() < k) {
            // Didn't find k elements in range, double the range to get more
            // items
            if (shapes.size() == getElementCount()) {
                // Already returned all possible elements
                result_correct = true;
            } else {
                query_radius *= 2;
                result_correct = false;
            }
        } else {
            // Sort items by distance to get the kth neighbor
            IndexedSortable s = new IndexedSortable() {
                @Override
                public void swap(int i, int j) {
                    double temp_distance = distances.elementAt(i);
                    distances.set(i, distances.elementAt(j));
                    distances.set(j, temp_distance);

                    T temp_shape = shapes.elementAt(i);
                    shapes.set(i, shapes.elementAt(j));
                    shapes.set(j, temp_shape);
                }

                @Override
                public int compare(int i, int j) {
                    // Note. Equality is not important to check because
                    // items with the
                    // same distance can be ordered anyway.
                    if (distances.elementAt(i) < distances.elementAt(j))
                        return -1;
                    return 1;
                }
            };
            IndexedSorter sorter = new QuickSort();
            sorter.sort(s, 0, shapes.size());
            if (distances.elementAt(k - 1) > query_radius) {
                result_correct = false;
                query_radius = distances.elementAt(k);
            } else {
                result_correct = true;
            }
        }
    } while (!result_correct);

    int result_size = Math.min(k, shapes.size());
    if (output != null) {
        for (int i = 0; i < result_size; i++) {
            output.collect(shapes.elementAt(i), distances.elementAt(i));
        }
    }
    return result_size;
}

From source file:com.ricemap.spateDB.util.MergeSorter.java

License:Apache License

public static void main(String[] args) {
    for (int i = 0; i < 1000000; i++) {
        x.add((int) (Math.random() * 100000));
    }//from   ww w.  j  a v  a 2s  .co m

    IndexedSortable sortable = new IndexedSortable() {
        @Override
        public void swap(int i, int j) {
            Integer temp = x.elementAt(i);
            x.set(i, x.elementAt(j));
            x.set(j, temp);
        }

        @Override
        public int compare(int i, int j) {
            return x.elementAt(i) - x.elementAt(j);
        }
    };

    MergeSorter sorter = new MergeSorter();
    System.out.println(x);
    sorter.sort(sortable, 0, x.size());
    for (int i = 1; i < x.size(); i++) {
        if (x.elementAt(i - 1) > x.elementAt(i))
            System.out.println("tozzzzzzzzzzzzzzzzzzzzzz");
    }
    System.out.println(x);
}

From source file:edu.umn.cs.pigeon.SJPlaneSweep.java

License:Open Source License

@Override
public DataBag exec(Tuple input) throws IOException {
    DataBag lRelation = (DataBag) input.get(0);
    DataBag rRelation = (DataBag) input.get(1);

    boolean dupAvoidance = false;
    double mbrX1 = 0, mbrY1 = 0, mbrX2 = 0, mbrY2 = 0;
    if (input.size() > 2) {
        // Implement duplicate avoidance based on the MBR as specified by
        // the third argument
        Geometry cellMBR = geomParser.parseGeom(input.get(2));
        if (cellMBR != null) {
            dupAvoidance = true;//from   w  w w . ja  v a  2 s.  c o m
            Coordinate[] mbrCoords = cellMBR.getCoordinates();
            mbrX1 = Math.min(mbrCoords[0].x, mbrCoords[2].x);
            mbrY1 = Math.min(mbrCoords[0].y, mbrCoords[2].y);
            mbrX2 = Math.max(mbrCoords[0].x, mbrCoords[2].x);
            mbrY2 = Math.max(mbrCoords[0].y, mbrCoords[2].y);
        }
    }

    Iterator<Tuple> irGeoms = null;
    if (input.size() > 4 && input.get(4) instanceof DataBag) {
        // User specified a column of values for right geometries
        DataBag rGeoms = (DataBag) input.get(4);
        if (rGeoms.size() != rRelation.size())
            throw new ExecException(
                    String.format("Mismatched sizes of right records column (%d) and geometry column (%d)",
                            rRelation.size(), rGeoms.size()));
        irGeoms = rGeoms.iterator();
    }

    // TODO ensure that the left bag is the smaller one for efficiency
    if (lRelation.size() > Integer.MAX_VALUE)
        throw new ExecException("Size of left dataset is too large " + lRelation.size());

    // Read all of the left dataset in memory
    final Tuple[] lTuples = new Tuple[(int) lRelation.size()];
    int leftSize = 0;
    tupleFactory = TupleFactory.getInstance();
    for (Tuple t : lRelation) {
        lTuples[leftSize++] = tupleFactory.newTupleNoCopy(t.getAll());
    }

    // Extract MBRs of objects for filter-refine approach
    final double[] lx1 = new double[(int) lRelation.size()];
    final double[] ly1 = new double[(int) lRelation.size()];
    final double[] lx2 = new double[(int) lRelation.size()];
    final double[] ly2 = new double[(int) lRelation.size()];

    if (input.size() > 3 && input.get(3) instanceof DataBag) {
        // User specified a column of values that contain the geometries
        DataBag lGeoms = (DataBag) input.get(3);
        if (lRelation.size() != lGeoms.size())
            throw new ExecException(
                    String.format("Mismatched sizes of left records column (%d) and geometry column (%d)",
                            lRelation.size(), lGeoms.size()));
        Iterator<Tuple> ilGeoms = lGeoms.iterator();
        for (int i = 0; i < lTuples.length; i++) {
            Geometry geom = geomParser.parseGeom(ilGeoms.next().get(0));
            Coordinate[] mbrCoords = geom.getEnvelope().getCoordinates();
            lx1[i] = Math.min(mbrCoords[0].x, mbrCoords[2].x);
            ly1[i] = Math.min(mbrCoords[0].y, mbrCoords[2].y);
            lx2[i] = Math.max(mbrCoords[0].x, mbrCoords[2].x);
            ly2[i] = Math.max(mbrCoords[0].y, mbrCoords[2].y);
        }
    } else {
        int lGeomColumn;
        if (input.size() > 3 && input.get(3) instanceof Integer)
            lGeomColumn = (Integer) input.get(3);
        else if (input.size() > 3 && input.get(3) instanceof Long)
            lGeomColumn = (int) ((long) (Long) input.get(3));
        else
            lGeomColumn = detectGeomColumn(lTuples[0]);

        for (int i = 0; i < lTuples.length; i++) {
            Geometry geom = geomParser.parseGeom(lTuples[i].get(lGeomColumn));
            Coordinate[] mbrCoords = geom.getEnvelope().getCoordinates();
            lx1[i] = Math.min(mbrCoords[0].x, mbrCoords[2].x);
            ly1[i] = Math.min(mbrCoords[0].y, mbrCoords[2].y);
            lx2[i] = Math.max(mbrCoords[0].x, mbrCoords[2].x);
            ly2[i] = Math.max(mbrCoords[0].y, mbrCoords[2].y);
        }
    }

    // Sort left MBRs by x to prepare for the plane-sweep algorithm
    IndexedSortable lSortable = new IndexedSortable() {
        @Override
        public void swap(int i, int j) {
            Tuple tt = lTuples[i];
            lTuples[i] = lTuples[j];
            lTuples[j] = tt;
            double td = lx1[i];
            lx1[i] = lx1[j];
            lx1[j] = td;
            td = ly1[i];
            ly1[i] = ly1[j];
            ly1[j] = td;
            td = lx2[i];
            lx2[i] = lx2[j];
            lx2[j] = td;
            td = ly2[i];
            ly2[i] = ly2[j];
            ly2[j] = td;
        }

        @Override
        public int compare(int i, int j) {
            if (lx1[i] < lx1[j])
                return -1;
            if (lx2[i] > lx2[j])
                return 1;
            return 0;
        }
    };
    QuickSort quickSort = new QuickSort();
    quickSort.sort(lSortable, 0, lTuples.length);

    // Retrieve objects from the right relation in batches and join with left
    Iterator<Tuple> ri = rRelation.iterator();
    final int batchSize = 10000;
    final Tuple[] rTuples = new Tuple[batchSize];
    final double[] rx1 = new double[batchSize];
    final double[] ry1 = new double[batchSize];
    final double[] rx2 = new double[batchSize];
    final double[] ry2 = new double[batchSize];
    IndexedSortable rSortable = new IndexedSortable() {
        @Override
        public void swap(int i, int j) {
            Tuple tt = rTuples[i];
            rTuples[i] = rTuples[j];
            rTuples[j] = tt;
            double td = rx1[i];
            rx1[i] = rx1[j];
            rx1[j] = td;
            td = ry1[i];
            ry1[i] = ry1[j];
            ry1[j] = td;
            td = rx2[i];
            rx2[i] = rx2[j];
            rx2[j] = td;
            td = ry2[i];
            ry2[i] = ry2[j];
            ry2[j] = td;
        }

        @Override
        public int compare(int i, int j) {
            if (rx1[i] < rx1[j])
                return -1;
            if (rx2[i] > rx2[j])
                return 1;
            return 0;
        }
    };
    int rSize = 0;
    DataBag output = BagFactory.getInstance().newDefaultBag();
    int rGeomColumn = -1;
    while (ri.hasNext()) {
        rTuples[rSize++] = tupleFactory.newTupleNoCopy(ri.next().getAll());
        if (rSize == batchSize || !ri.hasNext()) {
            // Extract MBRs of geometries on the right
            if (irGeoms != null) {
                for (int i = 0; i < rSize; i++) {
                    Geometry geom = geomParser.parseGeom(irGeoms.next().get(0));
                    Coordinate[] mbrCoords = geom.getEnvelope().getCoordinates();
                    rx1[i] = Math.min(mbrCoords[0].x, mbrCoords[2].x);
                    ry1[i] = Math.min(mbrCoords[0].y, mbrCoords[2].y);
                    rx2[i] = Math.max(mbrCoords[0].x, mbrCoords[2].x);
                    ry2[i] = Math.max(mbrCoords[0].y, mbrCoords[2].y);
                }
            } else {
                if (rGeomColumn == -1)
                    rGeomColumn = detectGeomColumn(rTuples[0]);
                for (int i = 0; i < rSize; i++) {
                    Geometry geom = geomParser.parseGeom(rTuples[i].get(rGeomColumn));
                    Coordinate[] mbrCoords = geom.getEnvelope().getCoordinates();
                    rx1[i] = Math.min(mbrCoords[0].x, mbrCoords[2].x);
                    ry1[i] = Math.min(mbrCoords[0].y, mbrCoords[2].y);
                    rx2[i] = Math.max(mbrCoords[0].x, mbrCoords[2].x);
                    ry2[i] = Math.max(mbrCoords[0].y, mbrCoords[2].y);
                }
            }

            // Perform the join now
            quickSort.sort(rSortable, 0, rSize);
            int i = 0, j = 0;

            while (i < lTuples.length && j < rSize) {
                if (lx1[i] < rx1[j]) {
                    int jj = j;
                    // Compare left object i to all right object jj
                    while (jj < rSize && rx1[jj] <= lx2[i]) {
                        if (lx2[i] > rx1[jj] && rx2[jj] > lx1[i] && ly2[i] > ry1[jj] && ry2[jj] > ly1[i]) {
                            boolean report = true;
                            if (dupAvoidance) {
                                // Performs the reference point technique to avoid duplicates
                                double intersectX = Math.max(lx1[i], rx1[jj]);
                                if (intersectX >= mbrX1 && intersectX < mbrX2) {
                                    double intersectY = Math.max(ly1[i], ry1[jj]);
                                    report = intersectY >= mbrY1 && intersectY < mbrY2;
                                } else {
                                    report = false;
                                }
                            }
                            if (report) {
                                addToAnswer(output, lTuples[i], rTuples[jj]);
                            }
                        }
                        jj++;
                        progress();
                    }
                    i++;
                } else {
                    int ii = i;
                    // Compare all left objects ii to the right object j
                    while (ii < lTuples.length && lx1[ii] <= rx2[j]) {
                        if (lx2[ii] > rx1[j] && rx2[j] > lx1[ii] && ly2[ii] > ry1[j] && ry2[j] > ly1[ii]) {
                            boolean report = true;
                            if (dupAvoidance) {
                                // Performs the reference point technique to avoid duplicates
                                double intersectX = Math.max(lx1[ii], rx1[j]);
                                if (intersectX >= mbrX1 && intersectX < mbrX2) {
                                    double intersectY = Math.max(ly1[ii], ry1[j]);
                                    report = intersectY >= mbrY1 && intersectY < mbrY2;
                                } else {
                                    report = false;
                                }
                            }
                            if (report) {
                                addToAnswer(output, lTuples[ii], rTuples[j]);
                            }
                        }
                        ii++;
                        progress();
                    }
                    j++;
                }
                progress();
            }
        }
    }
    return output;
}

From source file:edu.umn.cs.spatialHadoop.core.GlobalIndex.java

License:Open Source License

public int knn(final double qx, final double qy, int k, ResultCollector2<S, Double> output) {
    double query_area = (getMBR().getWidth() * getMBR().getHeight()) * k / size();
    double query_radius = Math.sqrt(query_area / Math.PI);

    boolean result_correct;
    final Vector<Double> distances = new Vector<Double>();
    final Vector<S> shapes = new Vector<S>();
    // Find results in the range and increase this range if needed to ensure
    // correctness of the answer
    do {//from   w ww .j ava  2 s  .  c  om
        // Initialize result and query range
        distances.clear();
        shapes.clear();
        Rectangle queryRange = new Rectangle();
        queryRange.x1 = qx - query_radius / 2;
        queryRange.y1 = qy - query_radius / 2;
        queryRange.x2 = qx + query_radius / 2;
        queryRange.y2 = qy + query_radius / 2;
        // Retrieve all results in range
        rangeQuery(queryRange, new ResultCollector<S>() {
            @Override
            public void collect(S shape) {
                distances.add(shape.distanceTo(qx, qy));
                shapes.add((S) shape.clone());
            }
        });
        if (shapes.size() <= k) {
            // Didn't find k elements in range, double the range to get more items
            if (shapes.size() == size() || shapes.size() == k) {
                // Already returned all possible elements
                result_correct = true;
            } else {
                query_radius *= 2;
                result_correct = false;
            }
        } else {
            // Sort items by distance to get the kth neighbor
            IndexedSortable s = new IndexedSortable() {
                @Override
                public void swap(int i, int j) {
                    double temp_distance = distances.elementAt(i);
                    distances.set(i, distances.elementAt(j));
                    distances.set(j, temp_distance);

                    S temp_shape = shapes.elementAt(i);
                    shapes.set(i, shapes.elementAt(j));
                    shapes.set(j, temp_shape);
                }

                @Override
                public int compare(int i, int j) {
                    // Note. Equality is not important to check because items with the
                    // same distance can be ordered anyway. 
                    if (distances.elementAt(i) == distances.elementAt(j))
                        return 0;
                    if (distances.elementAt(i) < distances.elementAt(j))
                        return -1;
                    return 1;
                }
            };
            IndexedSorter sorter = new QuickSort();
            sorter.sort(s, 0, shapes.size());
            if (distances.elementAt(k - 1) > query_radius) {
                result_correct = false;
                query_radius = distances.elementAt(k);
            } else {
                result_correct = true;
            }
        }
    } while (!result_correct);

    int result_size = Math.min(k, shapes.size());
    if (output != null) {
        for (int i = 0; i < result_size; i++) {
            output.collect(shapes.elementAt(i), distances.elementAt(i));
        }
    }
    return result_size;
}

From source file:edu.umn.cs.spatialHadoop.core.RTree.java

License:Open Source License

/**
 * Builds the RTree given a serialized list of elements. It uses the given
 * stockObject to deserialize these elements using
 * {@link TextSerializable#fromText(Text)} and build the tree. Also writes the
 * created tree to the disk directly./*from   w  ww .j  a  va 2  s .co m*/
 * 
 * @param element_bytes
 *          - serialization of all elements separated by new lines
 * @param offset
 *          - offset of the first byte to use in elements_bytes
 * @param len
 *          - number of bytes to use in elements_bytes
 * @param degree
 *          - Degree of the R-tree to build in terms of number of children per
 *          node
 * @param dataOut
 *          - output stream to write the result to.
 * @param fast_sort
 *          - setting this to <code>true</code> allows the method to run
 *          faster by materializing the offset of each element in the list
 *          which speeds up the comparison. However, this requires an
 *          additional 16 bytes per element. So, for each 1M elements, the
 *          method will require an additional 16 M bytes (approximately).
 */
public void bulkLoadWrite(final byte[] element_bytes, final int offset, final int len, final int degree,
        DataOutput dataOut, final boolean fast_sort) {
    try {

        // Count number of elements in the given text
        int i_start = offset;
        final Text line = new Text();
        while (i_start < offset + len) {
            int i_end = skipToEOL(element_bytes, i_start);
            // Extract the line without end of line character
            line.set(element_bytes, i_start, i_end - i_start - 1);
            stockObject.fromText(line);
            elementCount++;
            i_start = i_end;
        }
        LOG.info("Bulk loading an RTree with " + elementCount + " elements");

        // It turns out the findBestDegree returns the best degree when the whole
        // tree is loaded to memory when processed. However, as current algorithms
        // process the tree while it's on disk, a higher degree should be selected
        // such that a node fits one file block (assumed to be 4K).
        //final int degree = findBestDegree(bytesAvailable, elementCount);
        LOG.info("Writing an RTree with degree " + degree);

        int height = Math.max(1, (int) Math.ceil(Math.log(elementCount) / Math.log(degree)));
        int leafNodeCount = (int) Math.pow(degree, height - 1);
        if (elementCount < 2 * leafNodeCount && height > 1) {
            height--;
            leafNodeCount = (int) Math.pow(degree, height - 1);
        }
        int nodeCount = (int) ((Math.pow(degree, height) - 1) / (degree - 1));
        int nonLeafNodeCount = nodeCount - leafNodeCount;

        // Keep track of the offset of each element in the text
        final int[] offsets = new int[elementCount];
        final double[] xs = fast_sort ? new double[elementCount] : null;
        final double[] ys = fast_sort ? new double[elementCount] : null;

        i_start = offset;
        line.clear();
        for (int i = 0; i < elementCount; i++) {
            offsets[i] = i_start;
            int i_end = skipToEOL(element_bytes, i_start);
            if (xs != null) {
                // Extract the line with end of line character
                line.set(element_bytes, i_start, i_end - i_start - 1);
                stockObject.fromText(line);
                // Sample center of the shape
                xs[i] = (stockObject.getMBR().x1 + stockObject.getMBR().x2) / 2;
                ys[i] = (stockObject.getMBR().y1 + stockObject.getMBR().y2) / 2;
            }
            i_start = i_end;
        }

        /**A struct to store information about a split*/
        class SplitStruct extends Rectangle {
            /**Start and end index for this split*/
            int index1, index2;
            /**Direction of this split*/
            byte direction;
            /**Index of first element on disk*/
            int offsetOfFirstElement;

            static final byte DIRECTION_X = 0;
            static final byte DIRECTION_Y = 1;

            SplitStruct(int index1, int index2, byte direction) {
                this.index1 = index1;
                this.index2 = index2;
                this.direction = direction;
            }

            @Override
            public void write(DataOutput out) throws IOException {
                out.writeInt(offsetOfFirstElement);
                super.write(out);
            }

            void partition(Queue<SplitStruct> toBePartitioned) {
                IndexedSortable sortableX;
                IndexedSortable sortableY;

                if (fast_sort) {
                    // Use materialized xs[] and ys[] to do the comparisons
                    sortableX = new IndexedSortable() {
                        @Override
                        public void swap(int i, int j) {
                            // Swap xs
                            double tempx = xs[i];
                            xs[i] = xs[j];
                            xs[j] = tempx;
                            // Swap ys
                            double tempY = ys[i];
                            ys[i] = ys[j];
                            ys[j] = tempY;
                            // Swap id
                            int tempid = offsets[i];
                            offsets[i] = offsets[j];
                            offsets[j] = tempid;
                        }

                        @Override
                        public int compare(int i, int j) {
                            if (xs[i] < xs[j])
                                return -1;
                            if (xs[i] > xs[j])
                                return 1;
                            return 0;
                        }
                    };

                    sortableY = new IndexedSortable() {
                        @Override
                        public void swap(int i, int j) {
                            // Swap xs
                            double tempx = xs[i];
                            xs[i] = xs[j];
                            xs[j] = tempx;
                            // Swap ys
                            double tempY = ys[i];
                            ys[i] = ys[j];
                            ys[j] = tempY;
                            // Swap id
                            int tempid = offsets[i];
                            offsets[i] = offsets[j];
                            offsets[j] = tempid;
                        }

                        @Override
                        public int compare(int i, int j) {
                            if (ys[i] < ys[j])
                                return -1;
                            if (ys[i] > ys[j])
                                return 1;
                            return 0;
                        }
                    };
                } else {
                    // No materialized xs and ys. Always deserialize objects to compare
                    sortableX = new IndexedSortable() {
                        @Override
                        public void swap(int i, int j) {
                            // Swap id
                            int tempid = offsets[i];
                            offsets[i] = offsets[j];
                            offsets[j] = tempid;
                        }

                        @Override
                        public int compare(int i, int j) {
                            // Get end of line
                            int eol = skipToEOL(element_bytes, offsets[i]);
                            line.set(element_bytes, offsets[i], eol - offsets[i] - 1);
                            stockObject.fromText(line);
                            double xi = (stockObject.getMBR().x1 + stockObject.getMBR().x2) / 2;

                            eol = skipToEOL(element_bytes, offsets[j]);
                            line.set(element_bytes, offsets[j], eol - offsets[j] - 1);
                            stockObject.fromText(line);
                            double xj = (stockObject.getMBR().x1 + stockObject.getMBR().x2) / 2;
                            if (xi < xj)
                                return -1;
                            if (xi > xj)
                                return 1;
                            return 0;
                        }
                    };

                    sortableY = new IndexedSortable() {
                        @Override
                        public void swap(int i, int j) {
                            // Swap id
                            int tempid = offsets[i];
                            offsets[i] = offsets[j];
                            offsets[j] = tempid;
                        }

                        @Override
                        public int compare(int i, int j) {
                            int eol = skipToEOL(element_bytes, offsets[i]);
                            line.set(element_bytes, offsets[i], eol - offsets[i] - 1);
                            stockObject.fromText(line);
                            double yi = (stockObject.getMBR().y1 + stockObject.getMBR().y2) / 2;

                            eol = skipToEOL(element_bytes, offsets[j]);
                            line.set(element_bytes, offsets[j], eol - offsets[j] - 1);
                            stockObject.fromText(line);
                            double yj = (stockObject.getMBR().y1 + stockObject.getMBR().y2) / 2;
                            if (yi < yj)
                                return -1;
                            if (yi > yj)
                                return 1;
                            return 0;
                        }
                    };
                }

                final IndexedSorter sorter = new QuickSort();

                final IndexedSortable[] sortables = new IndexedSortable[2];
                sortables[SplitStruct.DIRECTION_X] = sortableX;
                sortables[SplitStruct.DIRECTION_Y] = sortableY;

                sorter.sort(sortables[direction], index1, index2);

                // Partition into maxEntries partitions (equally) and
                // create a SplitStruct for each partition
                int i1 = index1;
                for (int iSplit = 0; iSplit < degree; iSplit++) {
                    int i2 = index1 + (index2 - index1) * (iSplit + 1) / degree;
                    SplitStruct newSplit = new SplitStruct(i1, i2, (byte) (1 - direction));
                    toBePartitioned.add(newSplit);
                    i1 = i2;
                }
            }
        }

        // All nodes stored in level-order traversal
        Vector<SplitStruct> nodes = new Vector<SplitStruct>();
        final Queue<SplitStruct> toBePartitioned = new LinkedList<SplitStruct>();
        toBePartitioned.add(new SplitStruct(0, elementCount, SplitStruct.DIRECTION_X));

        while (!toBePartitioned.isEmpty()) {
            SplitStruct split = toBePartitioned.poll();
            if (nodes.size() < nonLeafNodeCount) {
                // This is a non-leaf
                split.partition(toBePartitioned);
            }
            nodes.add(split);
        }

        if (nodes.size() != nodeCount) {
            throw new RuntimeException(
                    "Expected node count: " + nodeCount + ". Real node count: " + nodes.size());
        }

        // Now we have our data sorted in the required order. Start building
        // the tree.
        // Store the offset of each leaf node in the tree
        FSDataOutputStream fakeOut = null;
        try {
            fakeOut = new FSDataOutputStream(new java.io.OutputStream() {
                // Null output stream
                @Override
                public void write(int b) throws IOException {
                    // Do nothing
                }

                @Override
                public void write(byte[] b, int off, int len) throws IOException {
                    // Do nothing
                }

                @Override
                public void write(byte[] b) throws IOException {
                    // Do nothing
                }
            }, null, TreeHeaderSize + nodes.size() * NodeSize);
            for (int i_leaf = nonLeafNodeCount, i = 0; i_leaf < nodes.size(); i_leaf++) {
                nodes.elementAt(i_leaf).offsetOfFirstElement = (int) fakeOut.getPos();
                if (i != nodes.elementAt(i_leaf).index1)
                    throw new RuntimeException();
                double x1, y1, x2, y2;

                // Initialize MBR to first object
                int eol = skipToEOL(element_bytes, offsets[i]);
                fakeOut.write(element_bytes, offsets[i], eol - offsets[i]);
                line.set(element_bytes, offsets[i], eol - offsets[i] - 1);
                stockObject.fromText(line);
                Rectangle mbr = stockObject.getMBR();
                x1 = mbr.x1;
                y1 = mbr.y1;
                x2 = mbr.x2;
                y2 = mbr.y2;
                i++;

                while (i < nodes.elementAt(i_leaf).index2) {
                    eol = skipToEOL(element_bytes, offsets[i]);
                    fakeOut.write(element_bytes, offsets[i], eol - offsets[i]);
                    line.set(element_bytes, offsets[i], eol - offsets[i] - 1);
                    stockObject.fromText(line);
                    mbr = stockObject.getMBR();
                    if (mbr.x1 < x1)
                        x1 = mbr.x1;
                    if (mbr.y1 < y1)
                        y1 = mbr.y1;
                    if (mbr.x2 > x2)
                        x2 = mbr.x2;
                    if (mbr.y2 > y2)
                        y2 = mbr.y2;
                    i++;
                }
                nodes.elementAt(i_leaf).set(x1, y1, x2, y2);
            }

        } finally {
            if (fakeOut != null)
                fakeOut.close();
        }

        // Calculate MBR and offsetOfFirstElement for non-leaves
        for (int i_node = nonLeafNodeCount - 1; i_node >= 0; i_node--) {
            int i_first_child = i_node * degree + 1;
            nodes.elementAt(i_node).offsetOfFirstElement = nodes.elementAt(i_first_child).offsetOfFirstElement;
            int i_child = 0;
            Rectangle mbr;
            mbr = nodes.elementAt(i_first_child + i_child);
            double x1 = mbr.x1;
            double y1 = mbr.y1;
            double x2 = mbr.x2;
            double y2 = mbr.y2;
            i_child++;

            while (i_child < degree) {
                mbr = nodes.elementAt(i_first_child + i_child);
                if (mbr.x1 < x1)
                    x1 = mbr.x1;
                if (mbr.y1 < y1)
                    y1 = mbr.y1;
                if (mbr.x2 > x2)
                    x2 = mbr.x2;
                if (mbr.y2 > y2)
                    y2 = mbr.y2;
                i_child++;
            }
            nodes.elementAt(i_node).set(x1, y1, x2, y2);
        }

        // Start writing the tree
        // write tree header (including size)
        // Total tree size. (== Total bytes written - 8 bytes for the size itself)
        dataOut.writeInt(TreeHeaderSize + NodeSize * nodeCount + len);
        // Tree height
        dataOut.writeInt(height);
        // Degree
        dataOut.writeInt(degree);
        dataOut.writeInt(elementCount);

        // write nodes
        for (SplitStruct node : nodes) {
            node.write(dataOut);
        }
        // write elements
        for (int element_i = 0; element_i < elementCount; element_i++) {
            int eol = skipToEOL(element_bytes, offsets[element_i]);
            dataOut.write(element_bytes, offsets[element_i], eol - offsets[element_i]);
        }

    } catch (IOException e) {
        e.printStackTrace();
    }
}

From source file:edu.umn.cs.spatialHadoop.core.RTree.java

License:Open Source License

/**
 * Create rectangles that together pack all points in sample such that
 * each rectangle contains roughly the same number of points. In other words
 * it tries to balance number of points in each rectangle.
 * Works similar to the logic of bulkLoad but does only one level of
 * rectangles./*  w w  w.jav  a2  s .  co  m*/
 * @param samples
 * @param gridInfo - Used as a hint for number of rectangles per row or column
 * @return
 */
public static Rectangle[] packInRectangles(GridInfo gridInfo, final Point[] sample) {
    Rectangle[] rectangles = new Rectangle[gridInfo.columns * gridInfo.rows];
    int iRectangle = 0;
    // Sort in x direction
    final IndexedSortable sortableX = new IndexedSortable() {
        @Override
        public void swap(int i, int j) {
            Point temp = sample[i];
            sample[i] = sample[j];
            sample[j] = temp;
        }

        @Override
        public int compare(int i, int j) {
            if (sample[i].x < sample[j].x)
                return -1;
            if (sample[i].x > sample[j].x)
                return 1;
            return 0;
        }
    };

    // Sort in y direction
    final IndexedSortable sortableY = new IndexedSortable() {
        @Override
        public void swap(int i, int j) {
            Point temp = sample[i];
            sample[i] = sample[j];
            sample[j] = temp;
        }

        @Override
        public int compare(int i, int j) {
            if (sample[i].y < sample[j].y)
                return -1;
            if (sample[i].y > sample[j].y)
                return 1;
            return 0;
        }
    };

    final QuickSort quickSort = new QuickSort();

    quickSort.sort(sortableX, 0, sample.length);

    int xindex1 = 0;
    double x1 = gridInfo.x1;
    for (int col = 0; col < gridInfo.columns; col++) {
        int xindex2 = sample.length * (col + 1) / gridInfo.columns;

        // Determine extents for all rectangles in this column
        double x2 = col == gridInfo.columns - 1 ? gridInfo.x2 : sample[xindex2 - 1].x;

        // Sort all points in this column according to its y-coordinate
        quickSort.sort(sortableY, xindex1, xindex2);

        // Create rectangles in this column
        double y1 = gridInfo.y1;
        for (int row = 0; row < gridInfo.rows; row++) {
            int yindex2 = xindex1 + (xindex2 - xindex1) * (row + 1) / gridInfo.rows;
            double y2 = row == gridInfo.rows - 1 ? gridInfo.y2 : sample[yindex2 - 1].y;

            rectangles[iRectangle++] = new Rectangle(x1, y1, x2, y2);
            y1 = y2;
        }

        xindex1 = xindex2;
        x1 = x2;
    }
    return rectangles;
}

From source file:edu.umn.cs.spatialHadoop.core.RTree.java

License:Open Source License

/**
 * k nearest neighbor query// www  .j a v a  2  s  .c o  m
 * @param qx
 * @param qy
 * @param k
 * @param output
 */
public int knn(final double qx, final double qy, int k, final ResultCollector2<T, Double> output) {
    double query_area = ((getMBR().x2 - getMBR().x1) * (getMBR().y2 - getMBR().y1)) * k / getElementCount();
    double query_radius = Math.sqrt(query_area / Math.PI);

    boolean result_correct;
    final Vector<Double> distances = new Vector<Double>();
    final Vector<T> shapes = new Vector<T>();
    // Find results in the range and increase this range if needed to ensure
    // correctness of the answer
    do {
        // Initialize result and query range
        distances.clear();
        shapes.clear();
        Rectangle queryRange = new Rectangle();
        queryRange.x1 = qx - query_radius;
        queryRange.y1 = qy - query_radius;
        queryRange.x2 = qx + query_radius;
        queryRange.y2 = qy + query_radius;
        // Retrieve all results in range
        search(queryRange, new ResultCollector<T>() {
            @Override
            public void collect(T shape) {
                distances.add(shape.distanceTo(qx, qy));
                shapes.add((T) shape.clone());
            }
        });
        if (shapes.size() < k) {
            // Didn't find k elements in range, double the range to get more items
            if (shapes.size() == getElementCount()) {
                // Already returned all possible elements
                result_correct = true;
            } else {
                query_radius *= 2;
                result_correct = false;
            }
        } else {
            // Sort items by distance to get the kth neighbor
            IndexedSortable s = new IndexedSortable() {
                @Override
                public void swap(int i, int j) {
                    double temp_distance = distances.elementAt(i);
                    distances.set(i, distances.elementAt(j));
                    distances.set(j, temp_distance);

                    T temp_shape = shapes.elementAt(i);
                    shapes.set(i, shapes.elementAt(j));
                    shapes.set(j, temp_shape);
                }

                @Override
                public int compare(int i, int j) {
                    // Note. Equality is not important to check because items with the
                    // same distance can be ordered anyway. 
                    if (distances.elementAt(i) == distances.elementAt(j))
                        return 0;
                    if (distances.elementAt(i) < distances.elementAt(j))
                        return -1;
                    return 1;
                }
            };
            IndexedSorter sorter = new QuickSort();
            sorter.sort(s, 0, shapes.size());
            if (distances.elementAt(k - 1) > query_radius) {
                result_correct = false;
                query_radius = distances.elementAt(k);
            } else {
                result_correct = true;
            }
        }
    } while (!result_correct);

    int result_size = Math.min(k, shapes.size());
    if (output != null) {
        for (int i = 0; i < result_size; i++) {
            output.collect(shapes.elementAt(i), distances.elementAt(i));
        }
    }
    return result_size;
}