/// <summary> /// Given a normalized coordinate in multiple dimensions, calculate its derived key for given level /// </summary> private long?DerivedValueFor(long[] normalizedValues, int level) { AssertValidLevel(level); long derivedValue = 0; long mask = 1L << (_maxLevel - 1); // The starting curve depends on the dimensions CurveRule currentCurve = RootCurve(); for (int i = 1; i <= _maxLevel; i++) { int bitIndex = _maxLevel - i; int npoint = 0; foreach (long val in normalizedValues) { npoint = npoint << 1 | ( int )((val & mask) >> bitIndex); } int derivedIndex = currentCurve.IndexForNPoint(npoint); derivedValue = (derivedValue << _nbrDim) | derivedIndex; mask = mask >> 1; currentCurve = currentCurve.ChildAt(derivedIndex); } if (level < _maxLevel) { derivedValue = derivedValue << (_nbrDim * _maxLevel - level); } return(derivedValue); }
/// <summary> /// Given a derived key, find the normalized coordinate it corresponds to on a specific level /// </summary> internal virtual long[] NormalizedCoordinateFor(long derivedValue, int level) { AssertValidLevel(level); long mask = _initialNormMask; long[] coordinate = new long[_nbrDim]; // First level is a single curveUp CurveRule currentCurve = RootCurve(); for (int i = 1; i <= level; i++) { int bitIndex = _maxLevel - i; int derivedIndex = ( int )((derivedValue & mask) >> bitIndex * _nbrDim); int npoint = currentCurve.NpointForIndex(derivedIndex); int[] bitValues = bitValues(npoint); for (int dim = 0; dim < _nbrDim; dim++) { coordinate[dim] = coordinate[dim] << 1 | bitValues[dim]; } mask = mask >> _nbrDim; currentCurve = currentCurve.ChildAt(derivedIndex); } if (level < _maxLevel) { for (int dim = 0; dim < _nbrDim; dim++) { coordinate[dim] = coordinate[dim] << _maxLevel - level; } } return(coordinate); }
private void AddTilesIntersectingEnvelopeAt(SpaceFillingCurveConfiguration config, SpaceFillingCurveMonitor monitor, int depth, int maxDepth, SearchEnvelope search, SearchEnvelope currentExtent, CurveRule curve, long left, long right, List <LongRange> results) { if (right - left == 1) { long[] coord = NormalizedCoordinateFor(left, _maxLevel); if (search.Contains(coord)) { LongRange current = (results.Count > 0) ? results[results.Count - 1] : null; if (current != null && current.Max == left - 1) { current.ExpandToMax(left); } else { current = new LongRange(left); results.Add(current); } if (monitor != null) { monitor.AddRangeAtDepth(depth); monitor.AddToCoveredArea(currentExtent.Area); } } } else if (search.Intersects(currentExtent)) { double overlap = search.FractionOf(currentExtent); if (config.StopAtThisDepth(overlap, depth, maxDepth)) { // Note that LongRange upper bound is inclusive, hence the '-1' in several places LongRange current = (results.Count > 0) ? results[results.Count - 1] : null; if (current != null && current.Max == left - 1) { current.ExpandToMax(right - 1); } else { current = new LongRange(left, right - 1); results.Add(current); } if (monitor != null) { monitor.AddRangeAtDepth(depth); monitor.AddToCoveredArea(currentExtent.Area); } } else { long width = (right - left) / _quadFactor; for (int i = 0; i < _quadFactor; i++) { int npoint = curve.NpointForIndex(i); SearchEnvelope quadrant = currentExtent.Quadrant(BitValues(npoint)); AddTilesIntersectingEnvelopeAt(config, monitor, depth + 1, maxDepth, search, quadrant, curve.ChildAt(i), left + i * width, left + (i + 1) * width, results); } } } }