List of usage examples for org.apache.hadoop.util IndexedSortable IndexedSortable
IndexedSortable
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; }