@Override public BigInteger getEstimatedIdCount(final MultiDimensionalNumericData data) { final double[] mins = data.getMinValuesPerDimension(); final double[] maxes = data.getMaxValuesPerDimension(); BigInteger estimatedIdCount = BigInteger.valueOf(1); for (int d = 0; d < data.getDimensionCount(); d++) { final double binMin = dimensionDefs[d].normalize(mins[d]) * binsPerDimension; final double binMax = dimensionDefs[d].normalize(maxes[d]) * binsPerDimension; estimatedIdCount = estimatedIdCount.multiply(BigInteger.valueOf((long) (Math.abs(binMax - binMin) + 1))); } return estimatedIdCount; }
/** @return an array of NumericData objects associated with this object. */ @Override public NumericData[] getDataPerDimension() { return indexRanges.getDataPerDimension(); }
/** Returns an insertion id selected round-robin from a predefined pool */ @Override public byte[][] getInsertionPartitionKeys(final MultiDimensionalNumericData insertionData) { final long hashCode; if (insertionData.isEmpty()) { hashCode = insertionData.hashCode(); } else { hashCode = Math.abs( hashCode( insertionData.getMaxValuesPerDimension(), hashCode(insertionData.getMinValuesPerDimension(), 1))); } final int position = (int) (hashCode % keys.length); return new byte[][] {keys[position]}; }
private static int getRanges(final MultiDimensionalNumericData indexedData) { final double[] mins = indexedData.getMinValuesPerDimension(); final double[] maxes = indexedData.getMaxValuesPerDimension(); int ranges = 0; for (int d = 0; d < mins.length; d++) { if (!FloatCompareUtils.checkDoublesEqual(mins[d], maxes[d])) { ranges++; } } return ranges; }
protected boolean validateConstraints( final BasicQueryCompareOp op, final MultiDimensionalNumericData queryRange, final MultiDimensionalNumericData dataRange) { final NumericData[] queryRangePerDimension = queryRange.getDataPerDimension(); final double[] minPerDimension = dataRange.getMinValuesPerDimension(); final double[] maxPerDimension = dataRange.getMaxValuesPerDimension(); boolean ok = true; for (int d = 0; (d < dimensionFields.length) && ok; d++) { ok &= op.compare( minPerDimension[d], maxPerDimension[d], queryRangePerDimension[d].getMin(), queryRangePerDimension[d].getMax()); } return ok; }
if (dimensions[d] instanceof LatitudeDefinition) { latitudeIndex = d; minDP[1] = originalBounds.getMinValuesPerDimension()[d]; maxDP[1] = originalBounds.getMaxValuesPerDimension()[d]; } else if (dimensions[d] instanceof LongitudeDefinition) { longitudeIndex = d; minDP[0] = originalBounds.getMinValuesPerDimension()[d]; maxDP[0] = originalBounds.getMaxValuesPerDimension()[d]; } else if (dimensions[d] instanceof CustomCRSSpatialDimension) { minDP[d] = originalBounds.getMinValuesPerDimension()[d]; maxDP[d] = originalBounds.getMaxValuesPerDimension()[d]; final double[] minsPerDimension = rangePerDimension.getMinValuesPerDimension(); final double[] maxesPerDimension = rangePerDimension.getMaxValuesPerDimension(); final ReferencedEnvelope mapExtent = new ReferencedEnvelope( final double[] centroids = rangePerDimension.getCentroidPerDimension(); final double[] mins = rangePerDimension.getMinValuesPerDimension(); final NumericRange[] ranges = new NumericRange[centroids.length]; for (int d = 0; d < centroids.length; d++) {
/** * Tool can be used custom index strategies to check if the tiles actual intersect with the * provided bounding box. * * @param boxRangeData * @param innerTile * @return */ private boolean checkCoverage( final MultiDimensionalNumericData boxRangeData, final MultiDimensionalNumericData innerTile) { for (int i = 0; i < boxRangeData.getDimensionCount(); i++) { final double i1 = innerTile.getDataPerDimension()[i].getMin(); final double i2 = innerTile.getDataPerDimension()[i].getMax(); final double j1 = boxRangeData.getDataPerDimension()[i].getMin(); final double j2 = boxRangeData.getDataPerDimension()[i].getMax(); final boolean overlaps = ((i1 < j2) || DoubleMath.fuzzyEquals(i1, j2, DOUBLE_TOLERANCE)) && ((i2 > j1) || DoubleMath.fuzzyEquals(i2, j1, DOUBLE_TOLERANCE)); if (!overlaps) { return false; } } return true; }
/** @return an array of max values associated with each dimension */ @Override public double[] getMaxValuesPerDimension() { return indexRanges.getMaxValuesPerDimension(); }
/** @return an array of min values associated with each dimension */ @Override public double[] getMinValuesPerDimension() { return indexRanges.getMinValuesPerDimension(); }
@Override public boolean isEmpty() { return indexRanges.isEmpty(); }
private static boolean queryRangeDimensionsMatch( final int indexDimensions, final List<MultiDimensionalNumericData> queryRanges) { for (final MultiDimensionalNumericData qr : queryRanges) { if (qr.getDimensionCount() != indexDimensions) { return false; } } return true; } }
/** @return an array of centroid values associated with each dimension */ @Override public double[] getCentroidPerDimension() { return indexRanges.getCentroidPerDimension(); }
/** * Returns all of the insertion ids for the range. Since this index strategy doensn't use binning, * it will return the ByteArrayId of every value in the range (i.e. if you are storing a range * using this index strategy, your data will be replicated for every integer value in the range). * * <p> {@inheritDoc} */ @Override public InsertionIds getInsertionIds( final MultiDimensionalNumericData indexedData, final int maxEstimatedDuplicateIds) { final long min = (long) indexedData.getMinValuesPerDimension()[0]; final long max = (long) Math.ceil(indexedData.getMaxValuesPerDimension()[0]); final List<byte[]> insertionIds = new ArrayList<>((int) (max - min) + 1); for (long i = min; i <= max; i++) { insertionIds.add(lexicoder.toByteArray(cast(i))); } return new InsertionIds(insertionIds); }
/** * {@inheritDoc} */ @Override public RangeDecomposition decomposeRange( final MultiDimensionalNumericData query, final boolean overInclusiveOnEdge, int maxFilteredIndexedRanges) { if (maxFilteredIndexedRanges == -1) { maxFilteredIndexedRanges = Integer.MAX_VALUE; } final QueryCacheKey key = new QueryCacheKey( query.getMinValuesPerDimension(), query.getMaxValuesPerDimension(), overInclusiveOnEdge, maxFilteredIndexedRanges); RangeDecomposition rangeDecomp = queryDecompositionCache.get(key); if (rangeDecomp == null) { rangeDecomp = decomposeQueryOperations.decomposeRange( query.getDataPerDimension(), compactHilbertCurve, dimensionDefinitions, totalPrecision, maxFilteredIndexedRanges, REMOVE_VACUUM, overInclusiveOnEdge); queryDecompositionCache.put(key, rangeDecomp); } return rangeDecomp; }
@Override public byte[] toBinary() { int byteBufferLength = VarintUtils.unsignedIntByteLength(compareOp.ordinal()); final int dimensions = Math.min(constraints.getDimensionCount(), dimensionFields.length); byteBufferLength += VarintUtils.unsignedIntByteLength(dimensions); final byte[][] lengthDimensionAndQueryBinaries = new byte[dimensions][]; final NumericData[] dataPerDimension = constraints.getDataPerDimension(); for (int d = 0; d < dimensions; d++) { final NumericDimensionField<?> dimension = dimensionFields[d]; final NumericData data = dataPerDimension[d]; final byte[] dimensionBinary = PersistenceUtils.toBinary(dimension); final int currentDimensionByteBufferLength = (16 + dimensionBinary.length + VarintUtils.unsignedIntByteLength(dimensionBinary.length)); final ByteBuffer buf = ByteBuffer.allocate(currentDimensionByteBufferLength); VarintUtils.writeUnsignedInt(dimensionBinary.length, buf); buf.putDouble(data.getMin()); buf.putDouble(data.getMax()); buf.put(dimensionBinary); byteBufferLength += currentDimensionByteBufferLength; lengthDimensionAndQueryBinaries[d] = buf.array(); } final ByteBuffer buf = ByteBuffer.allocate(byteBufferLength); VarintUtils.writeUnsignedInt(compareOp.ordinal(), buf); VarintUtils.writeUnsignedInt(dimensions, buf); for (final byte[] binary : lengthDimensionAndQueryBinaries) { buf.put(binary); } return buf.array(); }
/** * Constraints that are empty indicate full table scan. A full table scan occurs if ANY one * dimension is unbounded. * * @param constraints * @return true if any one dimension is unbounded */ public static final boolean isFullTableScan(final List<MultiDimensionalNumericData> constraints) { for (final MultiDimensionalNumericData constraint : constraints) { if (constraint.isEmpty()) { return false; } } return constraints.isEmpty(); }
/** @return the number of total dimensions */ @Override public int getDimensionCount() { return indexRanges.getDimensionCount(); }
/** * The estimated ID count is the cross product of normalized range of all dimensions per the bits * of precision provided by the dimension definitions. */ @Override public BigInteger getEstimatedIdCount( final MultiDimensionalNumericData data, final SFCDimensionDefinition[] dimensionDefinitions) { final double[] mins = data.getMinValuesPerDimension(); final double[] maxes = data.getMaxValuesPerDimension(); long estimatedIdCount = 1L; for (int d = 0; d < data.getDimensionCount(); d++) { final long binMin = normalizeDimension(dimensionDefinitions[d], mins[d], binsPerDimension[d], true, false); long binMax = normalizeDimension(dimensionDefinitions[d], maxes[d], binsPerDimension[d], false, false); if (binMin > binMax) { // if they're both equal, which is possible because we treat max // as exclusive, set bin max to bin min (ie. treat it as // inclusive in this case) binMax = binMin; } estimatedIdCount *= (Math.abs(binMax - binMin) + 1); } return BigInteger.valueOf(estimatedIdCount); }
public static InsertionIds trimIndexIds( InsertionIds rawIds, Geometry geom, NumericIndexStrategy index) { for (final SinglePartitionInsertionIds insertionId : rawIds.getPartitionKeys()) { final byte[] partitionKey = insertionId.getPartitionKey(); final int size = insertionId.getSortKeys().size(); if (size > 3) { final Iterator<byte[]> it = insertionId.getSortKeys().iterator(); while (it.hasNext()) { final byte[] sortKey = it.next(); MultiDimensionalNumericData keyTile = index.getRangeForId(partitionKey, sortKey); Envelope other = new Envelope(); other.init( keyTile.getMinValuesPerDimension()[0], keyTile.getMaxValuesPerDimension()[0], keyTile.getMinValuesPerDimension()[1], keyTile.getMaxValuesPerDimension()[1]); Polygon rect = JTS.toGeometry(other); if (!RectangleIntersects.intersects(rect, geom)) { it.remove(); } } } } return rawIds; }
public static BinRange[][] getBinnedRangesPerDimension( final MultiDimensionalNumericData numericData, final NumericDimensionDefinition[] dimensionDefinitions) { if (dimensionDefinitions.length == 0) { return new BinRange[0][]; } final BinRange[][] binRangesPerDimension = new BinRange[dimensionDefinitions.length][]; for (int d = 0; d < dimensionDefinitions.length; d++) { binRangesPerDimension[d] = dimensionDefinitions[d].getNormalizedRanges(numericData.getDataPerDimension()[d]); } return binRangesPerDimension; }