1 /***********************************************************************
2  * Copyright (c) 2013-2024 Commonwealth Computer Research, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Apache License, Version 2.0
5  * which accompanies this distribution and is available at
6  * http://www.opensource.org/licenses/apache2.0.php.
7  ***********************************************************************/
8 
9 package org.locationtech.geomesa.utils.geohash
10 
11 import com.typesafe.scalalogging.LazyLogging
12 import org.locationtech.jts.geom.{Coordinate, GeometryFactory, Point, PrecisionModel}
13 
14 import scala.collection.BitSet
15 import scala.collection.immutable.{BitSet => IBitSet}
16 
17 /**
18  * GeoHashes above GeoHash.MAX_PRECISION are not supported.
19  * @param x
20  * @param y
21  * @param bbox
22  * @param bitset
23  * @param prec
24  */
25 case class GeoHash private(x: Double,
26                            y: Double,
27                            bbox: BoundingBox,
28                            bitset: BitSet,
29                            prec: Int, // checked in factory methods in companion object
30                            private val optHash: Option[String]) extends Comparable[GeoHash] {
31   require(x >= -180.0 && x <= 180.0)
32   require(y >= -90.0  && y <= 90.0)
33 
34   import org.locationtech.geomesa.utils.geohash.GeoHash._
35 
36   /**
37    * Hash string is calculated lazily if GeoHash object was created
38    * from a Point, because calculation is expensive
39    */
40   lazy val hash = optHash.getOrElse(toBase32(bitset, prec))
41 
42   lazy val geom = bbox.geom
43 
44   /**
45    * Utility method to return the bit-string as a full binary string.
46    *
47    * NB:  We align our bits to the RIGHT by default, not to the LEFT.
48    * This means that the most significant bit in the GeoHash (as it is
49    * interpreted to a geometry) is actually the least significant bit
50    * in the bit-set.  In other words:  Interpret the bit-set from
51    * right to left.
52    *
53    * For clarity (?), this routine prints out the bits in MSB -> LSB
54    * order, so that their correspondence with the base-32
55    * characters is directly readable.
56    */
57   def toBinaryString: String =
58     (0 until prec).map(bitIndex => boolMap(bitset(bitIndex))).mkString
59 
60   /**
61     * Converts the geohash into an int.
62     *
63     * Note: geohashes with more than 6 base32 digits will not fit in an int
64     *
65     * @return the geohash as an int
66     */
67   def toInt: Int = {
68     var i = 0
69     var asInt = 0
70     while (i < prec) {
71       if (bitset(i)) {
72         asInt += 1 << prec - 1 - i
73       }
74       i += 1
75     }
76     asInt
77   }
78 
79   def getPoint = GeoHash.factory.createPoint(new Coordinate(x,y))
80 
81   def contains(gh: GeoHash): Boolean = prec <= gh.prec && bitset.subsetOf(gh.bitset)
82 
83   def next(): GeoHash =  GeoHash(GeoHash.next(bitset, prec), prec)
84 
85   override def equals(obj: Any): Boolean = obj match {
86     case that: GeoHash => this.bitset == that.bitset && this.prec == that.prec
87     case _ => false
88   }
89 
90   // Overriding equals obligates us to override hashCode.
91   override def hashCode: Int = bitset.hashCode + prec
92 
93   override def compareTo(gh: GeoHash) = this.hash.compareTo(gh.hash)
94 }
95 
96 case class Bounds(low: Double,
97                   high: Double) {
98   lazy val mid = (low+high)/2.0
99 }
100 
101 object GeoHash extends LazyLogging {
102 
103   val MAX_PRECISION = 63 // our bitset operations assume all bits fit in one Long
104 
105   implicit def toGeometry(gh: GeoHash) = gh.geom
106 
107   private val boolMap : Map[Boolean,String] = Map(false -> "0", true -> "1")
108 
109   lazy val factory: GeometryFactory = new GeometryFactory(new PrecisionModel, 4326)
110 
111   private val latBounds = Bounds(-90.0,90.0)
112   private lazy val latRange: Double = latBounds.high - latBounds.low
113   private val lonBounds = Bounds(-180.0,180.0)
114   private lazy val lonRange: Double = lonBounds.high - lonBounds.low
115 
116   private lazy val powersOf2Map: Map[Int, Long] =
117     (0 to   MAX_PRECISION).map(i => (i, 1L << i)).toMap // 1L << i == math.pow(2,i).toLong
118 
119   private lazy val latDeltaMap: Map[Int, Double]  =
120     (0 to MAX_PRECISION).map(i => (i, latRange / powersOf2Map(i / 2))).toMap
121   def latitudeDeltaForPrecision(prec: Int): Double = {
122     checkPrecision(prec)
123     latDeltaMap(prec)
124   }
125 
126   private lazy val lonDeltaMap: Map[Int, Double] =
127     (0 to MAX_PRECISION).map(i => (i, lonRange / powersOf2Map(i / 2 + i % 2))).toMap
128   def longitudeDeltaForPrecision(prec: Int): Double = {
129     checkPrecision(prec)
130     lonDeltaMap(prec)
131   }
132 
133   private val bits = Array(16,8,4,2,1)
134   protected[geohash] val base32 = "0123456789bcdefghjkmnpqrstuvwxyz"
135   private val characterMap: Map[Char, BitSet] =
136     base32.zipWithIndex.map { case (c, i) => c -> bitSetFromBase32Character(i) }.toMap
137 
138   private val lonMax = 360 - math.pow(0.5, 32)
139   private val latMax = 180 - math.pow(0.5, 32)
140 
141   // create a new GeoHash from a binary string in MSB -> LSB format
142   // (analogous to what is output by the "toBinaryString" method)
143   def fromBinaryString(bitsString: String): GeoHash = {
144     val numBits = bitsString.length
145     val bitSet: BitSet = bitsString.zipWithIndex.foldLeft(BitSet())((bsSoFar, bitPosTuple) => bitPosTuple match {
146       case (bitChar, pos) if bitChar == '1' => bsSoFar + pos
147       case _                                => bsSoFar
148     })
149     apply(bitSet, numBits)
150   }
151 
152   def apply(string: String): GeoHash = decode(string) // precision checked in decode
153   def apply(string: String, precision:Int): GeoHash = decode(string, Some[Int](precision)) // precision checked in decode
154 
155   // We expect points in x,y order, i.e., longitude first.
156   def apply(p: Point, prec: Int): GeoHash = apply(p.getX, p.getY, prec) // precision checked in apply
157   def apply(bs: BitSet, prec: Int): GeoHash = decode(toBase32(bs, prec), Some(prec)) // precision checked in decode
158 
159   // We expect points x,y i.e., lon-lat
160   def apply(lon: Double, lat: Double, prec: Int = 25): GeoHash = {
161     require(lon >= -180.0 && lon <= 180.0)
162     require(lat >= -90.0  && lat <= 90.0)
163     checkPrecision(prec)
164 
165     val lonDelta = lonDeltaMap(prec)
166     val latDelta = latDeltaMap(prec)
167     val lonIndex = if(lon == 180.0) (lonMax / lonDelta).toLong else ((lon - lonBounds.low) / lonDelta).toLong
168     val latIndex = if(lat == 90.0)  (latMax / latDelta).toLong else ((lat - latBounds.low) / latDelta).toLong
169 
170     encode(lonIndex, latIndex, lonDelta, latDelta, prec)
171   }
172 
173   def covering(ll: GeoHash, ur: GeoHash, prec: Int = 25) = {
174     checkPrecision(prec)
175 
176     val bbox = BoundingBox(ll.getPoint, ur.getPoint)
177 
178     def subsIntersecting(hash: GeoHash): Seq[GeoHash] = {
179       if (hash.prec == prec) List(hash)
180       else {
181         val subs = BoundingBox.generateSubGeoHashes(hash)
182         subs.flatMap { case sub =>
183           if (!bbox.intersects(sub.bbox)) List()
184           else subsIntersecting(sub)
185         }
186       }
187     }
188     val init = BoundingBox.getCoveringGeoHash(bbox, prec)
189     subsIntersecting(init)
190   }
191 
192   def checkPrecision(precision: Int) =
193     require(precision <= MAX_PRECISION,
194             s"GeoHash precision of $precision requested, but precisions above $MAX_PRECISION are not supported")
195 
196   /**
197    * Get the dimensions of the geohash grid bounded by ll and ur at precision.
198    * @param g1
199    * @param g2
200    * @param precision
201    * @return tuple containing (latitude span count, longitude span count)
202    */
203   def getLatitudeLongitudeSpanCount(g1: GeoHash, g2: GeoHash, precision: Int): (Int, Int) = {
204     require(g1.prec == precision,
205             s"Geohash ${g1.hash} has precision ${g1.prec} but precision ${precision} is required")
206     require(g2.prec == precision,
207             s"Geohash ${g2.hash} has precision ${g2.prec} but precision ${precision} is required")
208 
209     val Array(latIndex1, lonIndex1) = GeoHash.gridIndicesForLatLong(g1)
210     val Array(latIndex2, lonIndex2) = GeoHash.gridIndicesForLatLong(g2)
211 
212     ((math.abs(latIndex2 - latIndex1) + 1).toInt, (math.abs(lonIndex2 - lonIndex1) + 1).toInt)
213   }
214 
215   /**
216    * Convenience method to return both the latitude and longitude indices within
217    * the grid of geohashes at the precision of the specified geohash
218    *
219    * @param gh the geohash
220    * @return an array containing first the latitude index and then the longitude index
221    */
222   def gridIndicesForLatLong(gh: GeoHash) = {
223     val (lonIndex, latIndex) = extractReverseBits(gh.bitset.toBitMask.head, gh.prec)
224     Array(latIndex, lonIndex)
225   }
226 
227   /**
228    * Gets a long value representing a latitude index within the grid of geohashes
229    * at the precision of the specified geohash
230    *
231    * @param gh the geohash
232    * @return latitude index
233    */
234   def gridIndexForLatitude(gh: GeoHash) = {
235     val (_, latIndex) = extractReverseBits(gh.bitset.toBitMask.head, gh.prec)
236     latIndex
237   }
238 
239 
240   /**
241    * Gets a long value representing a longitude index within th grid of geohashes
242    * at the precision of the specified geohash
243    *
244    * @param gh the geohash
245    * @return longitude index
246    */
247   def gridIndexForLongitude(gh: GeoHash) = {
248     val (lonIndex, _) = extractReverseBits(gh.bitset.toBitMask.head, gh.prec)
249     lonIndex
250   }
251 
252 
253   /**
254    * Composes a geohash from a latitude and longitude index for the grid of geohashes
255    * at the specified precision.
256    *
257    * Note that the maximum latitude index is 2^(prec / 2) - 1 and the maximum longitude index
258    * is 2^(prec / 2 + prec % 2) -1 for the given precision.  An exception will be thrown if a
259    * larger index value is passed to this function.
260    *
261    * @param latIndex latitude index
262    * @param lonIndex longitude index
263    * @param prec the precision
264    * @return a geohash at the specified latitude and longitude index for the given geohash precision
265    */
266   def composeGeoHashFromBitIndicesAndPrec(latIndex: Long, lonIndex: Long, prec: Int): GeoHash = {
267     checkPrecision(prec)
268     encode(lonIndex, latIndex, lonDeltaMap(prec), latDeltaMap(prec), prec)
269   }
270 
271 
272   def next(gh: GeoHash): GeoHash = GeoHash(GeoHash.next(gh.bitset), gh.prec)
273 
274   def next(bs:BitSet, precision:Int=63) : BitSet = {
275     (0 until precision).reverse.foldLeft(true,BitSet())((t,idx) => t match { case (carry,newBS) => {
276       if (carry) {
277         if (bs(idx)) (true, newBS)
278         else (false, newBS+idx)
279       } else {
280         if (bs(idx)) (false, newBS+idx)
281         else (false, newBS)
282       }
283     }})._2
284   }
285 
286 
287   /**
288    * Create the geohash at the given latitude and longitude index with the given deltas and precision.
289    * Assumes prec <= 63, that is, all bits in the bitset fit in one Long
290    * @param lonIndex: the longitude index (x index)
291    * @param latIndex: the latitude index (y index)
292    * @param lonDelta the longitude (x) delta per grid cell for the given precision
293    * @param latDelta the latitude (y) delta per grid cell for the given precision
294    * @param prec precision (# of bits)
295    * @return the encoded GeoHash (note that calculation of the actual hash string is lazy)
296    */
297   def encode(lonIndex: Long, latIndex: Long, lonDelta: Double, latDelta: Double, prec: Int): GeoHash = {
298 
299     val bitSet = IBitSet.fromBitMaskNoCopy(Array(interleaveReverseBits(lonIndex, latIndex, prec)))
300     val bbox = bboxFromIndiciesDeltas(lonIndex, latIndex, lonDelta, latDelta)
301 
302     GeoHash(bbox.midLon, bbox.midLat, bbox, bitSet, prec, None)
303   }
304 
305   /**
306    * There is no visible difference between "t4bt" as a 20-bit GeoHash and
307    * the same string as a 17-bit GeoHash.  Unless otherwise specified, assume
308    * that the string represents a full complement of bits.
309    *
310    * If the call specifies a precision, then there is some additional work:
311    * 1.  the full-characters (those each representing a full 5 bits) should
312    *     be interpreted as they were before
313    * 2.  the partial-character (zero or one; representing the remainder bits,
314    *     guaranteed to be fewer than 5) must be appended
315    *
316    * @param string the base-32 encoded string to decode
317    * @param precisionOption the desired precision as an option
318    * @return the decoded GeoHash
319    */
320   private def decode(string: String, precisionOption: Option[Int] = None): GeoHash = {
321     // figure out what precision we should use
322     val prec = precisionOption.getOrElse(5*string.length)
323     checkPrecision(prec)
324 
325     // compute bit-sets for both the full and partial characters
326     val bitsets = string.zipWithIndex.map { case (c: Char, i: Int) => shift(i*5, characterMap(c)) }
327 
328     // OR all of these bit-sets together
329     val finalBitset: BitSet = bitsets.size match {
330       case 0 => BitSet()
331       case 1 => bitsets(0)
332       case _ => bitsets.reduce(_|_)
333     }
334 
335     val (lonIndex, latIndex) = extractReverseBits(finalBitset.toBitMask.head, prec)
336     val (lonDelta, latDelta) = (lonDeltaMap(prec), latDeltaMap(prec))
337     val bbox = bboxFromIndiciesDeltas(lonIndex, latIndex, lonDelta, latDelta)
338 
339     GeoHash(bbox.midLon, bbox.midLat, bbox, finalBitset, prec, Some(string))
340   }
341 
342   private def bboxFromIndiciesDeltas(lonIndex: Long,
343                                      latIndex: Long,
344                                      lonDelta: Double,
345                                      latDelta: Double): BoundingBox =
346     BoundingBox(Bounds((lonBounds.low+lonDelta*lonIndex), (lonBounds.low+lonDelta*(lonIndex+1))),
347                 Bounds((latBounds.low+latDelta*latIndex), (latBounds.low+latDelta*(latIndex+1))))
348 
349   /**
350    * Reverses and interleaves every other bits of two longs into one long. The two longs must be
351    * same size or first can be one bit longer than second.
352    * @param first first long
353    * @param second second long
354    * @param numBits The total number of bits of the interleaved & reversed result
355    * @return long with a total of numBits bits of first and second interleaved & reversed
356    */
357   private def interleaveReverseBits(first: Long, second: Long, numBits: Int): Long = {
358     /* We start with the first value of the interleaved long, coming from first if
359        numBits is odd or from second if numBits is even */
360     val even = (numBits & 0x01) == 0
361     val (actualFirst, actualSecond) = if(even) (second, first) else (first, second)
362     val numPairs = numBits >> 1
363     var result = 0L
364     (0 until numPairs).foreach{ pairNum =>
365       result = (result << 1) | ((actualFirst >> pairNum) & 1L)
366       result = (result << 1) | ((actualSecond >> pairNum) & 1L)
367     }
368     if (!even) (result << 1) | ((actualFirst >> numPairs) & 1L) else result
369   }
370 
371   /**
372    * Reverses and extracts every other bit up to numBits and extracts them into two longs.
373    * @param value the long
374    * @param numBits the number of bits to extract from the long
375    * @return (first long, second long)  The first long will be one bit longer than the second if
376    *         numBits is odd
377    */
378   private def extractReverseBits(value: Long, numBits: Int): (Long, Long) = {
379     val numPairs = numBits >> 1
380     var first = 0L
381     var second = 0L
382     (0 until numPairs).foreach{ pairNum =>
383       first = (first << 1) | ((value >> pairNum * 2) & 1L)
384       second = (second << 1) | ((value >> (pairNum * 2 + 1)) & 1L)
385     }
386     ((if((numBits & 0x01) == 1) ((first << 1) | ((value >> (numBits - 1)) & 1L)) else first), second)
387   }
388 
389   private def shift(n: Int, bs: BitSet): BitSet = bs.map(_ + n)
390 
391   private def bitSetFromBase32Character(charIndex: Long): BitSet =
392     BitSet(toPaddedBinaryString(charIndex, 5).zipWithIndex.filter { case (c,idx) => c == '1' }.map(_._2): _*)
393 
394   private def toPaddedBinaryString(i: Long, length: Int): String =
395     String.format("%" + length + "s", i.toBinaryString).replace(' ', '0')
396 
397   private def toBase32(bitset: BitSet, prec: Int): String = {
398     // compute the precision padded to the next 5-bit boundary
399     val numLeftoverBits = prec % 5
400     val precision = prec + (numLeftoverBits match {
401       case 0 => 0
402       case _ => (5-numLeftoverBits)
403     })
404 
405     // take the bit positions in groups of 5, and map each set to a character
406     // (based on the current bit-set); this works for off-5 precisions, because
407     // the additional bits will simply not be there (assumed to be zero)
408     (0 until precision).grouped(5).map(i=>ch(i, bitset)).mkString
409   }
410 
411   private def ch(v: IndexedSeq[Int], bitset: BitSet) =
412     base32(v.foldLeft(0)((cur,i) => cur + (if (bitset(i)) bits(i%bits.length) else 0)))
413 
414 }
Line Stmt Id Pos Tree Symbol Tests Code
31 4961 1232 - 1238 Literal <nosymbol> -180.0
31 4962 1242 - 1252 Apply scala.Double.<= GeoHash.this.x.<=(180.0)
31 4963 1227 - 1252 Apply scala.Boolean.&& GeoHash.this.x.>=(-180.0).&&(GeoHash.this.x.<=(180.0))
31 4964 1219 - 1253 Apply scala.Predef.require scala.Predef.require(GeoHash.this.x.>=(-180.0).&&(GeoHash.this.x.<=(180.0)))
32 4965 1269 - 1274 Literal <nosymbol> -90.0
32 4966 1279 - 1288 Apply scala.Double.<= GeoHash.this.y.<=(90.0)
32 4967 1264 - 1288 Apply scala.Boolean.&& GeoHash.this.y.>=(-90.0).&&(GeoHash.this.y.<=(90.0))
32 4968 1256 - 1289 Apply scala.Predef.require scala.Predef.require(GeoHash.this.y.>=(-90.0).&&(GeoHash.this.y.<=(90.0)))
58 4969 2162 - 2163 Literal <nosymbol> 0
58 4970 2170 - 2174 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec GeoHash.this.prec
58 4971 2200 - 2216 Apply scala.collection.GenSetLike.apply GeoHash.this.bitset.apply(bitIndex)
58 4972 2192 - 2217 Apply scala.collection.MapLike.apply org.locationtech.geomesa.utils.geohash.GeoHash.boolMap.apply(GeoHash.this.bitset.apply(bitIndex))
58 4973 2179 - 2179 TypeApply scala.collection.immutable.IndexedSeq.canBuildFrom immutable.this.IndexedSeq.canBuildFrom[String]
58 4974 2161 - 2227 Select scala.collection.TraversableOnce.mkString scala.Predef.intWrapper(0).until(GeoHash.this.prec).map[String, scala.collection.immutable.IndexedSeq[String]](((bitIndex: Int) => org.locationtech.geomesa.utils.geohash.GeoHash.boolMap.apply(GeoHash.this.bitset.apply(bitIndex))))(immutable.this.IndexedSeq.canBuildFrom[String]).mkString
68 4975 2439 - 2440 Literal <nosymbol> 0
69 4976 2457 - 2458 Literal <nosymbol> 0
70 4977 2474 - 2478 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec GeoHash.this.prec
70 4978 2470 - 2478 Apply scala.Int.< i.<(GeoHash.this.prec)
70 4988 2480 - 2480 Apply org.locationtech.geomesa.utils.geohash.GeoHash.while$1 while$1()
70 4989 2480 - 2566 Block <nosymbol> { { if (GeoHash.this.bitset.apply(i)) asInt = asInt.+(1.<<(GeoHash.this.prec.-(1).-(i))) else (); i = i.+(1) }; while$1() }
70 4990 2463 - 2463 Literal <nosymbol> ()
70 4991 2463 - 2463 Block <nosymbol> ()
71 4979 2492 - 2501 Apply scala.collection.GenSetLike.apply GeoHash.this.bitset.apply(i)
71 4985 2488 - 2488 Literal <nosymbol> ()
71 4986 2488 - 2488 Block <nosymbol> ()
72 4980 2522 - 2523 Literal <nosymbol> 1
72 4981 2527 - 2539 Apply scala.Int.- GeoHash.this.prec.-(1).-(i)
72 4982 2522 - 2539 Apply scala.Int.<< 1.<<(GeoHash.this.prec.-(1).-(i))
72 4983 2513 - 2539 Apply scala.Int.+ asInt.+(1.<<(GeoHash.this.prec.-(1).-(i)))
72 4984 2513 - 2539 Assign <nosymbol> asInt = asInt.+(1.<<(GeoHash.this.prec.-(1).-(i)))
74 4987 2554 - 2560 Apply scala.Int.+ i.+(1)
79 4992 2642 - 2643 Select org.locationtech.geomesa.utils.geohash.GeoHash.x GeoHash.this.x
79 4993 2644 - 2645 Select org.locationtech.geomesa.utils.geohash.GeoHash.y GeoHash.this.y
79 4994 2627 - 2646 Apply org.locationtech.jts.geom.Coordinate.<init> new org.locationtech.jts.geom.Coordinate(GeoHash.this.x, GeoHash.this.y)
79 4995 2599 - 2647 Apply org.locationtech.jts.geom.GeometryFactory.createPoint GeoHash.factory.createPoint(new org.locationtech.jts.geom.Coordinate(GeoHash.this.x, GeoHash.this.y))
81 4996 2696 - 2703 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec gh.prec
81 4997 2723 - 2732 Select org.locationtech.geomesa.utils.geohash.GeoHash.bitset gh.bitset
81 4998 2707 - 2733 Apply scala.collection.BitSetLike.subsetOf GeoHash.this.bitset.subsetOf(gh.bitset)
81 4999 2688 - 2733 Apply scala.Boolean.&& GeoHash.this.prec.<=(gh.prec).&&(GeoHash.this.bitset.subsetOf(gh.bitset))
83 5000 2781 - 2787 Select org.locationtech.geomesa.utils.geohash.GeoHash.bitset GeoHash.this.bitset
83 5001 2789 - 2793 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec GeoHash.this.prec
83 5002 2768 - 2794 Apply org.locationtech.geomesa.utils.geohash.GeoHash.next GeoHash.next(GeoHash.this.bitset, GeoHash.this.prec)
83 5003 2796 - 2800 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec GeoHash.this.prec
83 5004 2760 - 2801 Apply org.locationtech.geomesa.utils.geohash.GeoHash.apply GeoHash.apply(GeoHash.next(GeoHash.this.bitset, GeoHash.this.prec), GeoHash.this.prec)
86 5005 2899 - 2910 Select org.locationtech.geomesa.utils.geohash.GeoHash.bitset that.bitset
86 5006 2927 - 2936 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec that.prec
86 5007 2914 - 2936 Apply scala.Int.== this.prec.==(that.prec)
86 5008 2884 - 2936 Apply scala.Boolean.&& this.bitset.==(that.bitset).&&(this.prec.==(that.prec))
86 5009 2884 - 2936 Block scala.Boolean.&& this.bitset.==(that.bitset).&&(this.prec.==(that.prec))
87 5010 2951 - 2956 Literal <nosymbol> false
87 5011 2951 - 2956 Block <nosymbol> false
91 5012 3069 - 3073 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec GeoHash.this.prec
91 5013 3051 - 3073 Apply scala.Int.+ GeoHash.this.bitset.hashCode().+(GeoHash.this.prec)
93 5014 3115 - 3143 Apply java.lang.String.compareTo this.hash.compareTo(gh.hash)
103 5015 3307 - 3309 Literal <nosymbol> 63
107 5016 3468 - 3480 Apply scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[Boolean](false).->[String]("0")
107 5017 3482 - 3493 Apply scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[Boolean](true).->[String]("1")
107 5018 3464 - 3494 Apply scala.collection.generic.GenMapFactory.apply scala.Predef.Map.apply[Boolean, String](scala.Predef.ArrowAssoc[Boolean](false).->[String]("0"), scala.Predef.ArrowAssoc[Boolean](true).->[String]("1"))
111 5019 3607 - 3625 Apply org.locationtech.geomesa.utils.geohash.Bounds.apply Bounds.apply(-90.0, 90.0)
113 5020 3721 - 3741 Apply org.locationtech.geomesa.utils.geohash.Bounds.apply Bounds.apply(-180.0, 180.0)
122 5021 4142 - 4162 Apply org.locationtech.geomesa.utils.geohash.GeoHash.checkPrecision GeoHash.this.checkPrecision(prec)
123 5022 4167 - 4184 Apply scala.collection.MapLike.apply GeoHash.this.latDeltaMap.apply(prec)
129 5023 4386 - 4406 Apply org.locationtech.geomesa.utils.geohash.GeoHash.checkPrecision GeoHash.this.checkPrecision(prec)
130 5024 4411 - 4428 Apply scala.collection.MapLike.apply GeoHash.this.lonDeltaMap.apply(prec)
133 5025 4455 - 4472 Apply scala.Array.apply scala.Array.apply(16, 8, 4, 2, 1)
134 5026 4507 - 4541 Literal <nosymbol> "0123456789bcdefghjkmnpqrstuvwxyz"
136 5027 4594 - 4600 Select org.locationtech.geomesa.utils.geohash.GeoHash.base32 GeoHash.this.base32
136 5028 4601 - 4601 TypeApply scala.LowPriorityImplicits.fallbackStringCanBuildFrom scala.Predef.fallbackStringCanBuildFrom[(Char, Int)]
136 5029 4666 - 4667 Select scala.Int.toLong i.toLong
136 5030 4640 - 4668 Apply org.locationtech.geomesa.utils.geohash.GeoHash.bitSetFromBase32Character GeoHash.this.bitSetFromBase32Character(i.toLong)
136 5031 4635 - 4668 Apply scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[Char](c).->[scala.collection.BitSet](GeoHash.this.bitSetFromBase32Character(i.toLong))
136 5032 4635 - 4668 Block scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[Char](c).->[scala.collection.BitSet](GeoHash.this.bitSetFromBase32Character(i.toLong))
136 5033 4618 - 4618 TypeApply scala.collection.immutable.IndexedSeq.canBuildFrom immutable.this.IndexedSeq.canBuildFrom[(Char, scala.collection.BitSet)]
136 5034 4671 - 4671 TypeApply scala.Predef.$conforms scala.Predef.$conforms[(Char, scala.collection.BitSet)]
136 5035 4594 - 4676 ApplyToImplicitArgs scala.collection.TraversableOnce.toMap scala.Predef.augmentString(GeoHash.this.base32).zipWithIndex[Char, scala.collection.immutable.IndexedSeq[(Char, Int)]](scala.Predef.fallbackStringCanBuildFrom[(Char, Int)]).map[(Char, scala.collection.BitSet), scala.collection.immutable.IndexedSeq[(Char, scala.collection.BitSet)]](((x0$1: (Char, Int)) => x0$1 match { case (_1: Char, _2: Int)(Char, Int)((c @ _), (i @ _)) => scala.Predef.ArrowAssoc[Char](c).->[scala.collection.BitSet](GeoHash.this.bitSetFromBase32Character(i.toLong)) }))(immutable.this.IndexedSeq.canBuildFrom[(Char, scala.collection.BitSet)]).toMap[Char, scala.collection.BitSet](scala.Predef.$conforms[(Char, scala.collection.BitSet)])
138 5036 4701 - 4704 Literal <nosymbol> 360
138 5037 4707 - 4724 Apply scala.math.pow scala.math.`package`.pow(0.5, 32.0)
138 5038 4701 - 4724 Apply scala.Int.- 360.-(scala.math.`package`.pow(0.5, 32.0))
139 5039 4748 - 4751 Literal <nosymbol> 180
139 5040 4754 - 4771 Apply scala.math.pow scala.math.`package`.pow(0.5, 32.0)
139 5041 4748 - 4771 Apply scala.Int.- 180.-(scala.math.`package`.pow(0.5, 32.0))
144 5042 4981 - 4998 Apply java.lang.String.length bitsString.length()
145 5043 5035 - 5035 TypeApply scala.LowPriorityImplicits.fallbackStringCanBuildFrom scala.Predef.fallbackStringCanBuildFrom[(Char, Int)]
145 5044 5057 - 5065 Apply scala.collection.generic.BitSetFactory.apply scala.collection.BitSet.apply()
145 5049 5024 - 5235 Apply scala.collection.TraversableOnce.foldLeft scala.Predef.augmentString(bitsString).zipWithIndex[Char, scala.collection.immutable.IndexedSeq[(Char, Int)]](scala.Predef.fallbackStringCanBuildFrom[(Char, Int)]).foldLeft[scala.collection.BitSet](scala.collection.BitSet.apply())(((bsSoFar: scala.collection.BitSet, bitPosTuple: (Char, Int)) => bitPosTuple match { case (_1: Char, _2: Int)(Char, Int)((bitChar @ _), (pos @ _)) if bitChar.==('1') => bsSoFar.+(pos) case _ => bsSoFar }))
146 5045 5142 - 5156 Apply scala.Char.== bitChar.==('1')
146 5046 5160 - 5173 Apply scala.collection.SetLike.+ bsSoFar.+(pos)
146 5047 5160 - 5173 Block scala.collection.SetLike.+ bsSoFar.+(pos)
147 5048 5221 - 5228 Ident org.locationtech.geomesa.utils.geohash.GeoHash.bsSoFar bsSoFar
149 5050 5240 - 5262 Apply org.locationtech.geomesa.utils.geohash.GeoHash.apply GeoHash.this.apply(bitSet, numBits)
152 5051 5307 - 5321 Apply org.locationtech.geomesa.utils.geohash.GeoHash.decode GeoHash.this.decode(string, GeoHash.this.decode$default$2)
153 5052 5422 - 5442 Apply scala.Some.apply scala.Some.apply[Int](precision)
153 5053 5407 - 5443 Apply org.locationtech.geomesa.utils.geohash.GeoHash.decode GeoHash.this.decode(string, scala.Some.apply[Int](precision))
156 5054 5585 - 5591 Apply org.locationtech.jts.geom.Point.getX p.getX()
156 5055 5593 - 5599 Apply org.locationtech.jts.geom.Point.getY p.getY()
156 5056 5579 - 5606 Apply org.locationtech.geomesa.utils.geohash.GeoHash.apply GeoHash.this.apply(p.getX(), p.getY(), prec)
157 5057 5690 - 5708 Apply org.locationtech.geomesa.utils.geohash.GeoHash.toBase32 GeoHash.this.toBase32(bs, prec)
157 5058 5710 - 5720 Apply scala.Some.apply scala.Some.apply[Int](prec)
157 5059 5683 - 5721 Apply org.locationtech.geomesa.utils.geohash.GeoHash.decode GeoHash.this.decode(GeoHash.this.toBase32(bs, prec), scala.Some.apply[Int](prec))
161 5060 5880 - 5886 Literal <nosymbol> -180.0
161 5061 5890 - 5902 Apply scala.Double.<= lon.<=(180.0)
161 5062 5873 - 5902 Apply scala.Boolean.&& lon.>=(-180.0).&&(lon.<=(180.0))
161 5063 5865 - 5903 Apply scala.Predef.require scala.Predef.require(lon.>=(-180.0).&&(lon.<=(180.0)))
162 5064 5923 - 5928 Literal <nosymbol> -90.0
162 5065 5933 - 5944 Apply scala.Double.<= lat.<=(90.0)
162 5066 5916 - 5944 Apply scala.Boolean.&& lat.>=(-90.0).&&(lat.<=(90.0))
162 5067 5908 - 5945 Apply scala.Predef.require scala.Predef.require(lat.>=(-90.0).&&(lat.<=(90.0)))
163 5068 5950 - 5970 Apply org.locationtech.geomesa.utils.geohash.GeoHash.checkPrecision GeoHash.this.checkPrecision(prec)
165 5069 5991 - 6008 Apply scala.collection.MapLike.apply GeoHash.this.lonDeltaMap.apply(prec)
166 5070 6028 - 6045 Apply scala.collection.MapLike.apply GeoHash.this.latDeltaMap.apply(prec)
167 5071 6068 - 6080 Apply scala.Double.== lon.==(180.0)
167 5072 6082 - 6108 Select scala.Double.toLong GeoHash.this.lonMax./(lonDelta).toLong
167 5073 6082 - 6108 Block scala.Double.toLong GeoHash.this.lonMax./(lonDelta).toLong
167 5074 6122 - 6135 Select org.locationtech.geomesa.utils.geohash.Bounds.low GeoHash.this.lonBounds.low
167 5075 6114 - 6155 Select scala.Double.toLong lon.-(GeoHash.this.lonBounds.low)./(lonDelta).toLong
167 5076 6114 - 6155 Block scala.Double.toLong lon.-(GeoHash.this.lonBounds.low)./(lonDelta).toLong
168 5077 6178 - 6189 Apply scala.Double.== lat.==(90.0)
168 5078 6192 - 6218 Select scala.Double.toLong GeoHash.this.latMax./(latDelta).toLong
168 5079 6192 - 6218 Block scala.Double.toLong GeoHash.this.latMax./(latDelta).toLong
168 5080 6232 - 6245 Select org.locationtech.geomesa.utils.geohash.Bounds.low GeoHash.this.latBounds.low
168 5081 6224 - 6265 Select scala.Double.toLong lat.-(GeoHash.this.latBounds.low)./(latDelta).toLong
168 5082 6224 - 6265 Block scala.Double.toLong lat.-(GeoHash.this.latBounds.low)./(latDelta).toLong
170 5083 6271 - 6323 Apply org.locationtech.geomesa.utils.geohash.GeoHash.encode GeoHash.this.encode(lonIndex, latIndex, lonDelta, latDelta, prec)
174 5084 6394 - 6414 Apply org.locationtech.geomesa.utils.geohash.GeoHash.checkPrecision GeoHash.this.checkPrecision(prec)
176 5085 6443 - 6454 Select org.locationtech.geomesa.utils.geohash.GeoHash.getPoint ll.getPoint
176 5086 6456 - 6467 Select org.locationtech.geomesa.utils.geohash.GeoHash.getPoint ur.getPoint
176 5087 6431 - 6468 Apply org.locationtech.geomesa.utils.geohash.BoundingBox.apply BoundingBox.apply(ll.getPoint, ur.getPoint)
179 5088 6538 - 6555 Apply scala.Int.== hash.prec.==(prec)
179 5089 6557 - 6567 Apply scala.collection.immutable.List.apply scala.collection.immutable.List.apply[org.locationtech.geomesa.utils.geohash.GeoHash](hash)
179 5090 6557 - 6567 Block scala.collection.immutable.List.apply scala.collection.immutable.List.apply[org.locationtech.geomesa.utils.geohash.GeoHash](hash)
180 5101 6579 - 6777 Block <nosymbol> { val subs: Seq[org.locationtech.geomesa.utils.geohash.GeoHash] = BoundingBox.generateSubGeoHashes(hash); subs.flatMap[org.locationtech.geomesa.utils.geohash.GeoHash, Seq[org.locationtech.geomesa.utils.geohash.GeoHash]](((x0$1: org.locationtech.geomesa.utils.geohash.GeoHash) => x0$1 match { case (sub @ _) => if (bbox.intersects(sub.bbox).unary_!) scala.collection.immutable.Nil else subsIntersecting(sub) }))(collection.this.Seq.canBuildFrom[org.locationtech.geomesa.utils.geohash.GeoHash]) }
181 5091 6600 - 6638 Apply org.locationtech.geomesa.utils.geohash.BoundingBox.generateSubGeoHashes BoundingBox.generateSubGeoHashes(hash)
182 5099 6660 - 6660 TypeApply scala.collection.Seq.canBuildFrom collection.this.Seq.canBuildFrom[org.locationtech.geomesa.utils.geohash.GeoHash]
182 5100 6647 - 6769 ApplyToImplicitArgs scala.collection.TraversableLike.flatMap subs.flatMap[org.locationtech.geomesa.utils.geohash.GeoHash, Seq[org.locationtech.geomesa.utils.geohash.GeoHash]](((x0$1: org.locationtech.geomesa.utils.geohash.GeoHash) => x0$1 match { case (sub @ _) => if (bbox.intersects(sub.bbox).unary_!) scala.collection.immutable.Nil else subsIntersecting(sub) }))(collection.this.Seq.canBuildFrom[org.locationtech.geomesa.utils.geohash.GeoHash])
183 5092 6705 - 6713 Select org.locationtech.geomesa.utils.geohash.GeoHash.bbox sub.bbox
183 5093 6688 - 6714 Select scala.Boolean.unary_! bbox.intersects(sub.bbox).unary_!
183 5094 6716 - 6722 Select scala.collection.immutable.Nil scala.collection.immutable.Nil
183 5095 6716 - 6722 Block scala.collection.immutable.Nil scala.collection.immutable.Nil
183 5098 6684 - 6759 If <nosymbol> if (bbox.intersects(sub.bbox).unary_!) scala.collection.immutable.Nil else subsIntersecting(sub)
184 5096 6738 - 6759 Apply org.locationtech.geomesa.utils.geohash.GeoHash.subsIntersecting subsIntersecting(sub)
184 5097 6738 - 6759 Block org.locationtech.geomesa.utils.geohash.GeoHash.subsIntersecting subsIntersecting(sub)
188 5102 6799 - 6841 Apply org.locationtech.geomesa.utils.geohash.BoundingBox.getCoveringGeoHash BoundingBox.getCoveringGeoHash(bbox, prec)
189 5103 6846 - 6868 Apply org.locationtech.geomesa.utils.geohash.GeoHash.subsIntersecting subsIntersecting(init)
193 5104 6938 - 6951 Select org.locationtech.geomesa.utils.geohash.GeoHash.MAX_PRECISION GeoHash.this.MAX_PRECISION
193 5105 6925 - 6951 Apply scala.Int.<= precision.<=(GeoHash.this.MAX_PRECISION)
193 5111 6917 - 7065 Apply scala.Predef.require scala.Predef.require(precision.<=(GeoHash.this.MAX_PRECISION), scala.StringContext.apply("GeoHash precision of ", " requested, but precisions above ", " are not supported").s(precision, GeoHash.this.MAX_PRECISION))
194 5106 6967 - 6989 Literal <nosymbol> "GeoHash precision of "
194 5107 6998 - 7032 Literal <nosymbol> " requested, but precisions above "
194 5108 7045 - 7064 Literal <nosymbol> " are not supported"
194 5109 7032 - 7045 Select org.locationtech.geomesa.utils.geohash.GeoHash.MAX_PRECISION GeoHash.this.MAX_PRECISION
194 5110 6965 - 7064 Apply scala.StringContext.s scala.StringContext.apply("GeoHash precision of ", " requested, but precisions above ", " are not supported").s(precision, GeoHash.this.MAX_PRECISION)
204 5112 7390 - 7410 Apply scala.Int.== g1.prec.==(precision)
204 5119 7382 - 7510 Apply scala.Predef.require scala.Predef.require(g1.prec.==(precision), scala.StringContext.apply("Geohash ", " has precision ", " but precision ", " is required").s(g1.hash, g1.prec, precision))
205 5113 7426 - 7435 Literal <nosymbol> "Geohash "
205 5114 7444 - 7460 Literal <nosymbol> " has precision "
205 5115 7469 - 7485 Literal <nosymbol> " but precision "
205 5116 7496 - 7509 Literal <nosymbol> " is required"
205 5117 7461 - 7468 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec g1.prec
205 5118 7424 - 7509 Apply scala.StringContext.s scala.StringContext.apply("Geohash ", " has precision ", " but precision ", " is required").s(g1.hash, g1.prec, precision)
206 5120 7523 - 7543 Apply scala.Int.== g2.prec.==(precision)
206 5127 7515 - 7643 Apply scala.Predef.require scala.Predef.require(g2.prec.==(precision), scala.StringContext.apply("Geohash ", " has precision ", " but precision ", " is required").s(g2.hash, g2.prec, precision))
207 5121 7559 - 7568 Literal <nosymbol> "Geohash "
207 5122 7577 - 7593 Literal <nosymbol> " has precision "
207 5123 7602 - 7618 Literal <nosymbol> " but precision "
207 5124 7629 - 7642 Literal <nosymbol> " is required"
207 5125 7594 - 7601 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec g2.prec
207 5126 7557 - 7642 Apply scala.StringContext.s scala.StringContext.apply("Geohash ", " has precision ", " but precision ", " is required").s(g2.hash, g2.prec, precision)
209 5128 7659 - 7659 Select scala.Tuple2._1 x$1._1
209 5129 7670 - 7670 Select scala.Tuple2._2 x$1._2
210 5130 7731 - 7731 Select scala.Tuple2._1 x$2._1
210 5131 7742 - 7742 Select scala.Tuple2._2 x$2._2
212 5132 7805 - 7826 Apply scala.Long.- latIndex2.-(latIndex1)
212 5133 7830 - 7831 Literal <nosymbol> 1
212 5134 7795 - 7838 Select scala.Long.toInt scala.math.`package`.abs(latIndex2.-(latIndex1)).+(1).toInt
212 5135 7850 - 7871 Apply scala.Long.- lonIndex2.-(lonIndex1)
212 5136 7875 - 7876 Literal <nosymbol> 1
212 5137 7840 - 7883 Select scala.Long.toInt scala.math.`package`.abs(lonIndex2.-(lonIndex1)).+(1).toInt
212 5138 7794 - 7884 Apply scala.Tuple2.apply scala.Tuple2.apply[Int, Int](scala.math.`package`.abs(latIndex2.-(latIndex1)).+(1).toInt, scala.math.`package`.abs(lonIndex2.-(lonIndex1)).+(1).toInt)
223 5139 8225 - 8225 Select scala.Tuple2._1 x$3._1
223 5140 8235 - 8235 Select scala.Tuple2._2 x$3._2
224 5141 8305 - 8330 Apply scala.Array.apply scala.Array.apply(latIndex, lonIndex)
235 5142 8624 - 8643 Select scala.collection.BitSetLike.toBitMask gh.bitset.toBitMask
235 5143 8624 - 8648 Select scala.collection.IndexedSeqOptimized.head scala.Predef.longArrayOps(gh.bitset.toBitMask).head
235 5144 8650 - 8657 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec gh.prec
235 5145 8605 - 8658 Apply org.locationtech.geomesa.utils.geohash.GeoHash.extractReverseBits GeoHash.this.extractReverseBits(scala.Predef.longArrayOps(gh.bitset.toBitMask).head, gh.prec)
235 5146 8589 - 8602 Ident org.locationtech.geomesa.utils.geohash.GeoHash.latIndex latIndex
248 5147 8968 - 8987 Select scala.collection.BitSetLike.toBitMask gh.bitset.toBitMask
248 5148 8968 - 8992 Select scala.collection.IndexedSeqOptimized.head scala.Predef.longArrayOps(gh.bitset.toBitMask).head
248 5149 8994 - 9001 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec gh.prec
248 5150 8949 - 9002 Apply org.locationtech.geomesa.utils.geohash.GeoHash.extractReverseBits GeoHash.this.extractReverseBits(scala.Predef.longArrayOps(gh.bitset.toBitMask).head, gh.prec)
248 5151 8933 - 8946 Ident org.locationtech.geomesa.utils.geohash.GeoHash.lonIndex lonIndex
267 5152 9710 - 9730 Apply org.locationtech.geomesa.utils.geohash.GeoHash.checkPrecision GeoHash.this.checkPrecision(prec)
268 5153 9762 - 9779 Apply scala.collection.MapLike.apply GeoHash.this.lonDeltaMap.apply(prec)
268 5154 9781 - 9798 Apply scala.collection.MapLike.apply GeoHash.this.latDeltaMap.apply(prec)
268 5155 9735 - 9805 Apply org.locationtech.geomesa.utils.geohash.GeoHash.encode GeoHash.this.encode(lonIndex, latIndex, GeoHash.this.lonDeltaMap.apply(prec), GeoHash.this.latDeltaMap.apply(prec), prec)
272 5156 9868 - 9877 Select org.locationtech.geomesa.utils.geohash.GeoHash.bitset gh.bitset
272 5157 9855 - 9878 Apply org.locationtech.geomesa.utils.geohash.GeoHash.next GeoHash.next(gh.bitset, GeoHash.next$default$2)
272 5158 9880 - 9887 Select org.locationtech.geomesa.utils.geohash.GeoHash.prec gh.prec
272 5159 9847 - 9888 Apply org.locationtech.geomesa.utils.geohash.GeoHash.apply GeoHash.apply(GeoHash.next(gh.bitset, GeoHash.next$default$2), gh.prec)
275 5160 9948 - 9949 Literal <nosymbol> 0
275 5161 9984 - 9988 Literal <nosymbol> true
275 5162 9989 - 9997 Apply scala.collection.generic.BitSetFactory.apply scala.collection.BitSet.apply()
275 5163 9947 - 9998 Apply scala.Tuple2.apply scala.Tuple2.apply[Boolean, scala.collection.BitSet](true, scala.collection.BitSet.apply())
276 5180 10050 - 10220 If <nosymbol> if (carry) if (bs.apply(idx)) scala.Tuple2.apply[Boolean, scala.collection.BitSet](true, newBS) else scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS.+(idx)) else if (bs.apply(idx)) scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS.+(idx)) else scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS)
277 5164 10075 - 10082 Apply scala.collection.GenSetLike.apply bs.apply(idx)
277 5165 10084 - 10097 Apply scala.Tuple2.apply scala.Tuple2.apply[Boolean, scala.collection.BitSet](true, newBS)
277 5166 10084 - 10097 Block scala.Tuple2.apply scala.Tuple2.apply[Boolean, scala.collection.BitSet](true, newBS)
277 5171 10071 - 10129 If <nosymbol> if (bs.apply(idx)) scala.Tuple2.apply[Boolean, scala.collection.BitSet](true, newBS) else scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS.+(idx))
278 5167 10112 - 10117 Literal <nosymbol> false
278 5168 10119 - 10128 Apply scala.collection.SetLike.+ newBS.+(idx)
278 5169 10111 - 10129 Apply scala.Tuple2.apply scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS.+(idx))
278 5170 10111 - 10129 Block scala.Tuple2.apply scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS.+(idx))
280 5172 10157 - 10164 Apply scala.collection.GenSetLike.apply bs.apply(idx)
280 5173 10167 - 10172 Literal <nosymbol> false
280 5174 10174 - 10183 Apply scala.collection.SetLike.+ newBS.+(idx)
280 5175 10166 - 10184 Apply scala.Tuple2.apply scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS.+(idx))
280 5176 10166 - 10184 Block scala.Tuple2.apply scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS.+(idx))
280 5179 10153 - 10212 If <nosymbol> if (bs.apply(idx)) scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS.+(idx)) else scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS)
281 5177 10198 - 10212 Apply scala.Tuple2.apply scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS)
281 5178 10198 - 10212 Block scala.Tuple2.apply scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS)
283 5181 9947 - 10231 Select scala.Tuple2._2 scala.Predef.intWrapper(0).until(precision).reverse.foldLeft[(Boolean, scala.collection.BitSet)](scala.Tuple2.apply[Boolean, scala.collection.BitSet](true, scala.collection.BitSet.apply()))(((t: (Boolean, scala.collection.BitSet), idx: Int) => t match { case (_1: Boolean, _2: scala.collection.BitSet)(Boolean, scala.collection.BitSet)((carry @ _), (newBS @ _)) => if (carry) if (bs.apply(idx)) scala.Tuple2.apply[Boolean, scala.collection.BitSet](true, newBS) else scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS.+(idx)) else if (bs.apply(idx)) scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS.+(idx)) else scala.Tuple2.apply[Boolean, scala.collection.BitSet](false, newBS) }))._2
299 5182 10979 - 11026 Apply org.locationtech.geomesa.utils.geohash.GeoHash.interleaveReverseBits GeoHash.this.interleaveReverseBits(lonIndex, latIndex, prec)
299 5183 10973 - 11027 Apply scala.Array.apply scala.Array.apply(GeoHash.this.interleaveReverseBits(lonIndex, latIndex, prec))
299 5184 10947 - 11028 Apply scala.collection.immutable.BitSet.fromBitMaskNoCopy scala.collection.immutable.BitSet.fromBitMaskNoCopy(scala.Array.apply(GeoHash.this.interleaveReverseBits(lonIndex, latIndex, prec)))
300 5185 11044 - 11106 Apply org.locationtech.geomesa.utils.geohash.GeoHash.bboxFromIndiciesDeltas GeoHash.this.bboxFromIndiciesDeltas(lonIndex, latIndex, lonDelta, latDelta)
302 5186 11166 - 11170 Select scala.None scala.None
302 5187 11112 - 11171 Apply org.locationtech.geomesa.utils.geohash.GeoHash.apply GeoHash.apply(bbox.midLon, bbox.midLat, bbox, bitSet, prec, scala.None)
322 5188 12069 - 12070 Literal <nosymbol> 5
322 5189 12071 - 12084 Apply java.lang.String.length string.length()
322 5190 12069 - 12084 Apply scala.Int.* 5.*(string.length())
322 5191 12043 - 12085 Apply scala.Option.getOrElse precisionOption.getOrElse[Int](5.*(string.length()))
323 5192 12090 - 12110 Apply org.locationtech.geomesa.utils.geohash.GeoHash.checkPrecision GeoHash.this.checkPrecision(prec)
326 5193 12202 - 12202 TypeApply scala.LowPriorityImplicits.fallbackStringCanBuildFrom scala.Predef.fallbackStringCanBuildFrom[(Char, Int)]
326 5194 12253 - 12256 Apply scala.Int.* i.*(5)
326 5195 12258 - 12273 Apply scala.collection.MapLike.apply GeoHash.this.characterMap.apply(c)
326 5196 12247 - 12274 Apply org.locationtech.geomesa.utils.geohash.GeoHash.shift GeoHash.this.shift(i.*(5), GeoHash.this.characterMap.apply(c))
326 5197 12247 - 12274 Block org.locationtech.geomesa.utils.geohash.GeoHash.shift GeoHash.this.shift(i.*(5), GeoHash.this.characterMap.apply(c))
326 5198 12219 - 12219 TypeApply scala.collection.immutable.IndexedSeq.canBuildFrom immutable.this.IndexedSeq.canBuildFrom[scala.collection.BitSet]
326 5199 12195 - 12276 ApplyToImplicitArgs scala.collection.TraversableLike.map scala.Predef.augmentString(string).zipWithIndex[Char, scala.collection.immutable.IndexedSeq[(Char, Int)]](scala.Predef.fallbackStringCanBuildFrom[(Char, Int)]).map[scala.collection.BitSet, scala.collection.immutable.IndexedSeq[scala.collection.BitSet]](((x0$1: (Char, Int)) => x0$1 match { case (_1: Char, _2: Int)(Char, Int)((c @ (_: Char)), (i @ (_: Int))) => GeoHash.this.shift(i.*(5), GeoHash.this.characterMap.apply(c)) }))(immutable.this.IndexedSeq.canBuildFrom[scala.collection.BitSet])
329 5200 12349 - 12361 Select scala.collection.SeqLike.size bitsets.size
330 5201 12386 - 12394 Apply scala.collection.generic.BitSetFactory.apply scala.collection.BitSet.apply()
330 5202 12386 - 12394 Block scala.collection.generic.BitSetFactory.apply scala.collection.BitSet.apply()
331 5203 12411 - 12421 Apply scala.collection.SeqLike.apply bitsets.apply(0)
331 5204 12411 - 12421 Block scala.collection.SeqLike.apply bitsets.apply(0)
332 5205 12453 - 12456 Apply scala.collection.BitSetLike.| x$4.|(x$5)
332 5206 12438 - 12457 Apply scala.collection.TraversableOnce.reduce bitsets.reduce[scala.collection.BitSet](((x$4: scala.collection.BitSet, x$5: scala.collection.BitSet) => x$4.|(x$5)))
332 5207 12438 - 12457 Block scala.collection.TraversableOnce.reduce bitsets.reduce[scala.collection.BitSet](((x$4: scala.collection.BitSet, x$5: scala.collection.BitSet) => x$4.|(x$5)))
335 5208 12474 - 12474 Select scala.Tuple2._1 x$6._1
335 5209 12484 - 12484 Select scala.Tuple2._2 x$6._2
336 5210 12558 - 12558 Select scala.Tuple2._1 x$7._1
336 5211 12568 - 12568 Select scala.Tuple2._2 x$7._2
337 5212 12634 - 12696 Apply org.locationtech.geomesa.utils.geohash.GeoHash.bboxFromIndiciesDeltas GeoHash.this.bboxFromIndiciesDeltas(lonIndex, latIndex, lonDelta, latDelta)
339 5213 12761 - 12773 Apply scala.Some.apply scala.Some.apply[String](string)
339 5214 12702 - 12774 Apply org.locationtech.geomesa.utils.geohash.GeoHash.apply GeoHash.apply(bbox.midLon, bbox.midLat, bbox, finalBitset, prec, scala.Some.apply[String](string))
346 5215 13049 - 13066 Apply scala.Double.* lonDelta.*(lonIndex)
346 5216 13035 - 13066 Apply scala.Double.+ GeoHash.this.lonBounds.low.+(lonDelta.*(lonIndex))
346 5217 13094 - 13104 Apply scala.Long.+ lonIndex.+(1)
346 5218 13084 - 13105 Apply scala.Double.* lonDelta.*(lonIndex.+(1))
346 5219 13070 - 13105 Apply scala.Double.+ GeoHash.this.lonBounds.low.+(lonDelta.*(lonIndex.+(1)))
346 5220 13027 - 13107 Apply org.locationtech.geomesa.utils.geohash.Bounds.apply Bounds.apply(GeoHash.this.lonBounds.low.+(lonDelta.*(lonIndex)), GeoHash.this.lonBounds.low.+(lonDelta.*(lonIndex.+(1))))
346 5227 13015 - 13206 Apply org.locationtech.geomesa.utils.geohash.BoundingBox.apply BoundingBox.apply(Bounds.apply(GeoHash.this.lonBounds.low.+(lonDelta.*(lonIndex)), GeoHash.this.lonBounds.low.+(lonDelta.*(lonIndex.+(1)))), Bounds.apply(GeoHash.this.latBounds.low.+(latDelta.*(latIndex)), GeoHash.this.latBounds.low.+(latDelta.*(latIndex.+(1)))))
347 5221 13147 - 13164 Apply scala.Double.* latDelta.*(latIndex)
347 5222 13133 - 13164 Apply scala.Double.+ GeoHash.this.latBounds.low.+(latDelta.*(latIndex))
347 5223 13192 - 13202 Apply scala.Long.+ latIndex.+(1)
347 5224 13182 - 13203 Apply scala.Double.* latDelta.*(latIndex.+(1))
347 5225 13168 - 13203 Apply scala.Double.+ GeoHash.this.latBounds.low.+(latDelta.*(latIndex.+(1)))
347 5226 13125 - 13205 Apply org.locationtech.geomesa.utils.geohash.Bounds.apply Bounds.apply(GeoHash.this.latBounds.low.+(latDelta.*(latIndex)), GeoHash.this.latBounds.low.+(latDelta.*(latIndex.+(1))))
360 5228 13852 - 13873 Apply scala.Int.== numBits.&(1).==(0)
361 5229 13883 - 13883 Select scala.Tuple2._1 x$8._1
361 5230 13896 - 13896 Select scala.Tuple2._2 x$8._2
362 5231 13977 - 13989 Apply scala.Int.>> numBits.>>(1)
363 5232 14007 - 14009 Literal <nosymbol> 0L
364 5233 14015 - 14016 Literal <nosymbol> 0
364 5240 14014 - 14185 Apply scala.collection.immutable.Range.foreach scala.Predef.intWrapper(0).until(numPairs).foreach[Unit](((pairNum: Int) => { result = result.<<(1).|(actualFirst.>>(pairNum).&(1L)); result = result.<<(1).|(actualSecond.>>(pairNum).&(1L)) }))
365 5234 14079 - 14080 Literal <nosymbol> 1
365 5235 14085 - 14114 Apply scala.Long.& actualFirst.>>(pairNum).&(1L)
365 5236 14068 - 14115 Apply scala.Long.| result.<<(1).|(actualFirst.>>(pairNum).&(1L))
366 5237 14142 - 14143 Literal <nosymbol> 1
366 5238 14148 - 14178 Apply scala.Long.& actualSecond.>>(pairNum).&(1L)
366 5239 14131 - 14179 Apply scala.Long.| result.<<(1).|(actualSecond.>>(pairNum).&(1L))
368 5241 14194 - 14199 Select scala.Boolean.unary_! even.unary_!
368 5242 14212 - 14213 Literal <nosymbol> 1
368 5243 14218 - 14248 Apply scala.Long.& actualFirst.>>(numPairs).&(1L)
368 5244 14201 - 14249 Apply scala.Long.| result.<<(1).|(actualFirst.>>(numPairs).&(1L))
368 5245 14201 - 14249 Block scala.Long.| result.<<(1).|(actualFirst.>>(numPairs).&(1L))
368 5246 14255 - 14261 Ident org.locationtech.geomesa.utils.geohash.GeoHash.result result
379 5247 14683 - 14695 Apply scala.Int.>> numBits.>>(1)
380 5248 14712 - 14714 Literal <nosymbol> 0L
381 5249 14732 - 14734 Literal <nosymbol> 0L
382 5250 14740 - 14741 Literal <nosymbol> 0
382 5257 14739 - 14909 Apply scala.collection.immutable.Range.foreach scala.Predef.intWrapper(0).until(numPairs).foreach[Unit](((pairNum: Int) => { first = first.<<(1).|(value.>>(pairNum.*(2)).&(1L)); second = second.<<(1).|(value.>>(pairNum.*(2).+(1)).&(1L)) }))
383 5251 14802 - 14803 Literal <nosymbol> 1
383 5252 14808 - 14835 Apply scala.Long.& value.>>(pairNum.*(2)).&(1L)
383 5253 14792 - 14836 Apply scala.Long.| first.<<(1).|(value.>>(pairNum.*(2)).&(1L))
384 5254 14863 - 14864 Literal <nosymbol> 1
384 5255 14869 - 14902 Apply scala.Long.& value.>>(pairNum.*(2).+(1)).&(1L)
384 5256 14852 - 14903 Apply scala.Long.| second.<<(1).|(value.>>(pairNum.*(2).+(1)).&(1L))
386 5258 14919 - 14940 Apply scala.Int.== numBits.&(1).==(1)
386 5259 14953 - 14954 Literal <nosymbol> 1
386 5260 14959 - 14988 Apply scala.Long.& value.>>(numBits.-(1)).&(1L)
386 5261 14943 - 14989 Apply scala.Long.| first.<<(1).|(value.>>(numBits.-(1)).&(1L))
386 5262 14943 - 14989 Block scala.Long.| first.<<(1).|(value.>>(numBits.-(1)).&(1L))
386 5263 14996 - 15001 Ident org.locationtech.geomesa.utils.geohash.GeoHash.first first
386 5264 14914 - 15011 Apply scala.Tuple2.apply scala.Tuple2.apply[Long, Long](if (numBits.&(1).==(1)) first.<<(1).|(value.>>(numBits.-(1)).&(1L)) else first, second)
389 5265 15074 - 15079 Apply scala.Int.+ x$9.+(n)
389 5266 15073 - 15073 Select scala.collection.BitSet.canBuildFrom collection.this.BitSet.canBuildFrom
389 5267 15067 - 15080 ApplyToImplicitArgs scala.collection.SetLike.map bs.map[Int, scala.collection.BitSet](((x$9: Int) => x$9.+(n)))(collection.this.BitSet.canBuildFrom)
392 5268 15160 - 15194 Apply org.locationtech.geomesa.utils.geohash.GeoHash.toPaddedBinaryString GeoHash.this.toPaddedBinaryString(charIndex, 5)
392 5269 15195 - 15195 TypeApply scala.LowPriorityImplicits.fallbackStringCanBuildFrom scala.Predef.fallbackStringCanBuildFrom[(Char, Int)]
392 5270 15233 - 15241 Apply scala.Char.== c.==('1')
392 5271 15233 - 15241 Block scala.Char.== c.==('1')
392 5272 15248 - 15252 Select scala.Tuple2._2 x$10._2
392 5273 15247 - 15247 TypeApply scala.collection.immutable.IndexedSeq.canBuildFrom immutable.this.IndexedSeq.canBuildFrom[Int]
392 5274 15160 - 15253 ApplyToImplicitArgs scala.collection.TraversableLike.map scala.Predef.augmentString(GeoHash.this.toPaddedBinaryString(charIndex, 5)).zipWithIndex[Char, scala.collection.immutable.IndexedSeq[(Char, Int)]](scala.Predef.fallbackStringCanBuildFrom[(Char, Int)]).filter(((x0$1: (Char, Int)) => x0$1 match { case (_1: Char, _2: Int)(Char, Int)((c @ _), (idx @ _)) => c.==('1') })).map[Int, scala.collection.immutable.IndexedSeq[Int]](((x$10: (Char, Int)) => x$10._2))(immutable.this.IndexedSeq.canBuildFrom[Int])
392 5275 15153 - 15258 Apply scala.collection.generic.BitSetFactory.apply scala.collection.BitSet.apply((scala.Predef.augmentString(GeoHash.this.toPaddedBinaryString(charIndex, 5)).zipWithIndex[Char, scala.collection.immutable.IndexedSeq[(Char, Int)]](scala.Predef.fallbackStringCanBuildFrom[(Char, Int)]).filter(((x0$1: (Char, Int)) => x0$1 match { case (_1: Char, _2: Int)(Char, Int)((c @ _), (idx @ _)) => c.==('1') })).map[Int, scala.collection.immutable.IndexedSeq[Int]](((x$10: (Char, Int)) => x$10._2))(immutable.this.IndexedSeq.canBuildFrom[Int]): _*))
395 5276 15331 - 15400 Apply java.lang.String.replace java.lang.String.format("%".+(length).+("s"), scala.Predef.longWrapper(i).toBinaryString).replace(' ', '0')
399 5277 15553 - 15561 Apply scala.Int.% prec.%(5)
400 5282 15582 - 15674 Apply scala.Int.+ prec.+(numLeftoverBits match { case 0 => 0 case _ => 5.-(numLeftoverBits) })
401 5278 15630 - 15631 Literal <nosymbol> 0
401 5279 15630 - 15631 Block <nosymbol> 0
402 5280 15649 - 15666 Apply scala.Int.- 5.-(numLeftoverBits)
402 5281 15649 - 15666 Block scala.Int.- 5.-(numLeftoverBits)
408 5283 15912 - 15913 Literal <nosymbol> 0
408 5284 15939 - 15940 Literal <nosymbol> 5
408 5285 15949 - 15962 Apply org.locationtech.geomesa.utils.geohash.GeoHash.ch GeoHash.this.ch(i, bitset)
408 5286 15911 - 15972 Select scala.collection.TraversableOnce.mkString scala.Predef.intWrapper(0).until(precision).grouped(5).map[Char](((i: scala.collection.immutable.IndexedSeq[Int]) => GeoHash.this.ch(i, bitset))).mkString
412 5287 16037 - 16043 Select org.locationtech.geomesa.utils.geohash.GeoHash.base32 GeoHash.this.base32
412 5288 16055 - 16056 Literal <nosymbol> 0
412 5289 16080 - 16089 Apply scala.collection.GenSetLike.apply bitset.apply(i)
412 5290 16098 - 16109 Select scala.Array.length GeoHash.this.bits.length
412 5291 16096 - 16109 Apply scala.Int.% i.%(GeoHash.this.bits.length)
412 5292 16091 - 16110 Apply scala.Array.apply GeoHash.this.bits.apply(i.%(GeoHash.this.bits.length))
412 5293 16091 - 16110 Block scala.Array.apply GeoHash.this.bits.apply(i.%(GeoHash.this.bits.length))
412 5294 16116 - 16117 Literal <nosymbol> 0
412 5295 16116 - 16117 Block <nosymbol> 0
412 5296 16069 - 16118 Apply scala.Int.+ cur.+(if (bitset.apply(i)) GeoHash.this.bits.apply(i.%(GeoHash.this.bits.length)) else 0)
412 5297 16044 - 16119 Apply scala.collection.TraversableOnce.foldLeft v.foldLeft[Int](0)(((cur: Int, i: Int) => cur.+(if (bitset.apply(i)) GeoHash.this.bits.apply(i.%(GeoHash.this.bits.length)) else 0)))
412 5298 16037 - 16120 Apply scala.collection.immutable.StringOps.apply scala.Predef.augmentString(GeoHash.this.base32).apply(v.foldLeft[Int](0)(((cur: Int, i: Int) => cur.+(if (bitset.apply(i)) GeoHash.this.bits.apply(i.%(GeoHash.this.bits.length)) else 0))))