/** * Calculate the distance for encoded {@code double} values. * This distance function calculates the distance of the center-points of rectangles, * rather than the distance of the closest corners. * * @see PhDistance#dist(long[], long[]) */ @Override public double dist(long[] v1, long[] v2) { int dimsHalf = v1.length>>1; double[] d1lo = new double[dimsHalf]; double[] d1up = new double[dimsHalf]; double[] d2lo = new double[dimsHalf]; double[] d2up = new double[dimsHalf]; //center1 = (d1lo + d1up)/2 //center2 = (d2lo + d2up)/2 //dist = center2-center1 = (d1lo + d1up)/2 - (d2lo + d2up)/2 // = (d1lo + d1up - d2lo - d2up)/2 pre.post(v1, d1lo, d1up); pre.post(v2, d2lo, d2up); double d = 0; for (int i = 0; i < dimsHalf; i++) { double dOnAxis = d1lo[i] - d2lo[i] + d1up[i] - d2up[i]; dOnAxis /= 2; d += dOnAxis*dOnAxis; } return Math.sqrt(d); }
/** * Calculate the distance for encoded {@code double} values. * This distance function calculates the minimum distance between the rectangles. * If the the rectangles overlap, the distance is set to '0'. * * @see PhDistance#dist(long[], long[]) */ @Override public double dist(long[] v1, long[] v2) { double d = 0; double[] d1lo = new double[v1.length>>1]; double[] d1up = new double[v1.length>>1]; double[] d2lo = new double[v2.length>>1]; double[] d2up = new double[v2.length>>1]; pre.post(v1, d1lo, d1up); pre.post(v2, d2lo, d2up); for (int i = 0; i < d1lo.length; i++) { double dOnAxis = 0; if (d1up[i] < d2lo[i]) { dOnAxis = d2lo[i] - d1up[i]; } else if (d1lo[i] > d2up[i]) { dOnAxis = d1lo[i] - d2up[i]; } d += dOnAxis*dOnAxis; } return Math.sqrt(d); }
@Override public PHREntry next() { double[] lower = new double[dims]; double[] upper = new double[dims]; pre.post(iter.next(), lower, upper); return new PHREntry(lower, upper); } @Override
@Override public PHREntry next() { double[] lower = new double[DIM]; double[] upper = new double[DIM]; pre.post(iter.nextKey(), lower, upper); return new PHREntry(lower, upper); } @Override
/** * Calculates a MBB (minimal bounding box) for use with a query. * This is not strictly a box, but generates a query that returns all rectangles whose * centerpoint may be closer than the given distance. */ @Override public void toMBB(double distance, long[] center, long[] outMin, long[] outMax) { int dimsHalf = center.length>>1; double[] cLo = new double[dimsHalf]; double[] cUp = new double[dimsHalf]; double[] min = new double[dimsHalf]; double[] max = new double[dimsHalf]; //The simplest way to get all rectangles whose centerpoint may be within the distance, //is to perform an 'intersect' type query around center+/-distance. pre.post(center, cLo, cUp); for (int i = 0; i < dimsHalf; i++) { double c = (cUp[i] + cLo[i])/2; min[i] = c - distance; max[i] = c + distance; } //outMin contains the minimum allowed values for the lower and the upper corner //outMax contains the maximum allowed values for the lower and the upper corner pre.pre(qMIN, min, outMin); pre.pre(max, qMAX, outMax); }
/** * Calculates a MBB (minimal bounding box) for use with a query. * This is not strictly a box, but generates a query that returns all rectangles whose * edges may be closer than the given distance. */ @Override public void toMBB(double distance, long[] center, long[] outMin, long[] outMax) { int dimsHalf = center.length>>1; double[] cLo = new double[dimsHalf]; double[] cUp = new double[dimsHalf]; double[] min = new double[dimsHalf]; double[] max = new double[dimsHalf]; //The simplest way to get all rectangles whose centerpoint may be within the distance, //is to perform an 'intersect' type query around center+/-distance. pre.post(center, cLo, cUp); for (int i = 0; i < dimsHalf; i++) { min[i] = cLo[i] - distance; max[i] = cUp[i] + distance; } //outMin contains the minimum allowed values for the lower and the upper corner //outMax contains the maximum allowed values for the lower and the upper corner pre.pre(qMIN, min, outMin); pre.pre(max, qMAX, outMax); }
@Override public PhEntrySF<T> nextEntry() { double[] lower = new double[dims]; double[] upper = new double[dims]; PhEntry<T> pvEntry = iter.nextEntryReuse(); pre.post(pvEntry.getKey(), lower, upper); return new PhEntrySF<>(lower, upper, pvEntry.getValue()); } @Override
@Override public PhEntrySF<T> nextEntryReuse() { PhEntry<T> pvEntry = iter.nextEntryReuse(); pre.post(pvEntry.getKey(), buffer.lower, buffer.upper); buffer.setValue( pvEntry.getValue() ); return buffer; } @Override
/** * Same as {@link #queryIntersect(double[], double[])}, except that it returns a list * instead of an iterator. This may be faster for small result sets. * @param lower min value * @param upper max value * @return List of query results */ public List<PhEntrySF<T>> queryIntersectAll(double[] lower, double[] upper) { return queryIntersectAll(lower, upper, Integer.MAX_VALUE, null, e -> { double[] lo = new double[lower.length]; double[] up = new double[lower.length]; pre.post(e.getKey(), lo, up); return new PhEntrySF<>(lo, up, e.getValue()); }); }
@Override public PhEntryDistSF<T> nextEntry() { double[] lower = new double[dims]; double[] upper = new double[dims]; PhEntryDist<T> pvEntry = q.nextEntryReuse(); pre.post(pvEntry.getKey(), lower, upper); return new PhEntryDistSF<>(lower, upper, pvEntry.getValue(), pvEntry.dist()); } @Override
@Override public PhEntryDistSF<T> nextEntryReuse() { PhEntryDist<T> pvEntry = q.nextEntryReuse(); pre.post(pvEntry.getKey(), buffer.lower(), buffer.upper()); buffer.setValueDist( pvEntry.getValue(), pvEntry.dist() ); return buffer; } @Override