/**
  * Test for the geohash::contains() and geohash_set::contains() functions.
  * This test constructs the test points and ranges in and around the geohash.
  * 
  * @dataProvider geohashProvider
  * @param string $geohash
  */
 public function testContains($geohash)
 {
     $north = geohash::neighbor($geohash, geohash::north);
     $south = geohash::neighbor($geohash, geohash::south);
     $east = geohash::neighbor($geohash, geohash::east);
     $west = geohash::neighbor($geohash, geohash::west);
     $outside_tests = array($east, $west);
     if ($north) {
         $outside_tests[] = $north;
     }
     if ($south) {
         $outside_tests[] = $south;
     }
     // test points outside the geohash box
     foreach ($outside_tests as $test) {
         for ($i = 0; $i < 32; $i++) {
             $point = geohash::decode($test . geohash::encode_digit($i));
             $this->assertFalse(geohash::contains($geohash, $point));
         }
     }
     // test points inside the box
     for ($i = 0; $i < 32; $i++) {
         $point = geohash::decode($geohash . geohash::encode_digit($i));
         $this->assertTrue(geohash::contains($geohash, $point));
     }
     // and the four edge cases (all corners)
     $box = geohash::decode_box($geohash);
     $this->assertTrue(geohash::contains($geohash, new geopoint($box->north, $box->west)));
     $this->assertTrue(geohash::contains($geohash, new geopoint($box->north, $box->east)));
     $this->assertTrue(geohash::contains($geohash, new geopoint($box->south, $box->west)));
     $this->assertTrue(geohash::contains($geohash, new geopoint($box->south, $box->east)));
     // make a geohash set and test points inside and out
     $set = new geohash_set();
     $set->add_range($geohash . geohash::encode_digit(8), $geohash . geohash::encode_digit(23));
     // test points outside the set
     foreach ($outside_tests as $test) {
         $point = geohash::decode($test);
         $this->assertFalse($set->contains($point));
     }
     // test closer points outside the set
     for ($i = 0; $i < 8; $i++) {
         $point = geohash::decode($geohash . geohash::encode_digit($i));
         $this->assertFalse($set->contains($point));
     }
     for ($i = 24; $i < 32; $i++) {
         $point = geohash::decode($geohash . geohash::encode_digit($i));
         $this->assertFalse($set->contains($point));
     }
     // test points inside the set
     for ($i = 8; $i < 24; $i++) {
         $point = geohash::decode($geohash . geohash::encode_digit($i));
         $this->assertTrue($set->contains($point));
     }
     // make a compound geohash set and test points inside and out
     $set = new geohash_set();
     $set->add($geohash);
     $set->add($east);
     // test points outside the set
     $outside_tests = array(geohash::neighbor($east, geohash::east), $west);
     if ($north) {
         $outside_tests[] = $north;
     }
     if ($south) {
         $outside_tests[] = $south;
     }
     foreach ($outside_tests as $test) {
         $point = geohash::decode($test);
         $this->assertFalse($set->contains($point));
     }
     // test points inside the set
     $point = geohash::decode($geohash);
     $this->assertTrue($set->contains($point));
     $point = geohash::decode($east);
     $this->assertTrue($set->contains($point));
 }
 /**
  * Reduce this geohash to a region of one quadrant.
  * @param string $hash
  * @param string $direction one of geohash::northeast, geohash::northwest, geohash::southeast, geohash::southwest
  * @return geohash_set
  */
 public static function quarter($hash, $direction)
 {
     $odd = strlen($hash) % 2;
     switch ($direction) {
         case geohash::northeast:
             $range = array(24, 31);
             break;
         case geohash::northwest:
             $range = $odd ? array(16, 23) : array(8, 15);
             break;
         case geohash::southeast:
             $range = $odd ? array(8, 15) : array(16, 23);
             break;
         case geohash::southwest:
             $range = array(0, 7);
             break;
         default:
             trigger_error('Illegal quarter direction, "' . $direction . '"', E_USER_ERROR);
             break;
     }
     $set = new geohash_set();
     $set->add_range($hash . geohash::encode_digit($range[0]), $hash . geohash::encode_digit($range[1]));
     return $set;
 }