/** * Tests of the geohash::quarter() function. * * @dataProvider geohashProvider * @param string $geohash */ public function testQuarter($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(geohash::decode($east), geohash::decode($west)); if ($north) { $outside_tests[] = geohash::decode($north); } if ($south) { $outside_tests[] = geohash::decode($south); } $northwest = geohash::quarter($geohash, geohash::northwest); $northeast = geohash::quarter($geohash, geohash::northeast); $southwest = geohash::quarter($geohash, geohash::southwest); $southeast = geohash::quarter($geohash, geohash::southeast); // do the obvious outside tests foreach ($outside_tests as $test) { $this->assertFalse($northwest->contains($test)); $this->assertFalse($northeast->contains($test)); $this->assertFalse($southwest->contains($test)); $this->assertFalse($southeast->contains($test)); } // test points from the four quadrants $box = geohash::decode_box($geohash); $dlat = $box->north - $box->south; $dlon = $box->east - $box->west; $northwest_point = new geopoint($box->north - $dlat / 4, $box->west + $dlon / 4); $northeast_point = new geopoint($box->north - $dlat / 4, $box->east - $dlon / 4); $southwest_point = new geopoint($box->south + $dlat / 4, $box->west + $dlon / 4); $southeast_point = new geopoint($box->south + $dlat / 4, $box->east - $dlon / 4); $this->assertTrue($northwest->contains($northwest_point)); $this->assertFalse($northwest->contains($northeast_point)); $this->assertFalse($northwest->contains($southwest_point)); $this->assertFalse($northwest->contains($southeast_point)); $this->assertFalse($northeast->contains($northwest_point)); $this->assertTrue($northeast->contains($northeast_point)); $this->assertFalse($northeast->contains($southwest_point)); $this->assertFalse($northeast->contains($southeast_point)); $this->assertFalse($southwest->contains($northwest_point)); $this->assertFalse($southwest->contains($northeast_point)); $this->assertTrue($southwest->contains($southwest_point)); $this->assertFalse($southwest->contains($southeast_point)); $this->assertFalse($southeast->contains($northwest_point)); $this->assertFalse($southeast->contains($northeast_point)); $this->assertFalse($southeast->contains($southwest_point)); $this->assertTrue($southeast->contains($southeast_point)); // test the corners $northwest_point = new geopoint($box->north, $box->west); $northeast_point = new geopoint($box->north, $box->east); $southwest_point = new geopoint($box->south, $box->west); $southeast_point = new geopoint($box->south, $box->east); $this->assertTrue($northwest->contains($northwest_point)); $this->assertFalse($northwest->contains($northeast_point)); $this->assertFalse($northwest->contains($southwest_point)); $this->assertFalse($northwest->contains($southeast_point)); $this->assertFalse($northeast->contains($northwest_point)); $this->assertTrue($northeast->contains($northeast_point)); $this->assertFalse($northeast->contains($southwest_point)); $this->assertFalse($northeast->contains($southeast_point)); $this->assertFalse($southwest->contains($northwest_point)); $this->assertFalse($southwest->contains($northeast_point)); $this->assertTrue($southwest->contains($southwest_point)); $this->assertFalse($southwest->contains($southeast_point)); $this->assertFalse($southeast->contains($northwest_point)); $this->assertFalse($southeast->contains($northeast_point)); $this->assertFalse($southeast->contains($southwest_point)); $this->assertTrue($southeast->contains($southeast_point)); // test the center $center_point = new geopoint($box->north - $dlat / 2, $box->west + $dlon / 2); $this->assertTrue($northwest->contains($center_point)); $this->assertTrue($northeast->contains($center_point)); $this->assertTrue($southwest->contains($center_point)); $this->assertTrue($southeast->contains($center_point)); }
/** * Increase the size the of the circle. * @param int $amount * @return boolean success|failure */ public function expand($amount = 1) { if ($this->precision == 1) { // currently unwilling to expand to cover the entire globe return false; } $this->precision = max($this->precision - $amount, 1); // shrink the geohash, grow the box $center = substr($this->center_geohash, 0, $this->precision); $box = geohash::decode_box($center); $dlat = $box->north - $box->south; $dlon = $box->east - $box->west; $set = new geohash_set(); $set->add($center); $quadrant = geohash::quadrant($this->center_geohash, $this->precision); if ($quadrant == geohash::northeast || $quadrant == geohash::northwest) { // north side $north = geohash::neighbor($center, geohash::north); if ($north) { $set->add_set(geohash::halve($north, geohash::south)); if ($quadrant == geohash::northeast) { $set->add_set(geohash::quarter(geohash::neighbor($north, geohash::east), geohash::southwest)); } else { // northwest $set->add_set(geohash::quarter(geohash::neighbor($north, geohash::west), geohash::southeast)); } $box->north += $dlat / 2; } } else { // south side $south = geohash::neighbor($center, geohash::south); if ($south) { $set->add_set(geohash::halve($south, geohash::north)); if ($quadrant == geohash::southeast) { $set->add_set(geohash::quarter(geohash::neighbor($south, geohash::east), geohash::northwest)); } else { // southwest $set->add_set(geohash::quarter(geohash::neighbor($south, geohash::west), geohash::northeast)); } $box->south -= $dlat / 2; } } if ($quadrant == geohash::northeast || $quadrant == geohash::southeast) { // east side $set->add_set(geohash::halve(geohash::neighbor($center, geohash::east), geohash::west)); $box->east += $dlon / 2; } else { // west side $set->add_set(geohash::halve(geohash::neighbor($center, geohash::west), geohash::east)); $box->west -= $dlon / 2; } $this->geohash_set = $set; $this->max_radius = min($this->center->distance_to_longitude($box->east), $this->center->distance_to_longitude($box->west)); if ($box->north < 90) { $this->max_radius = min($this->center->distance_to_latitude(min($box->north, 90)), $this->max_radius); } if ($box->south > -90) { $this->max_radius = min($this->center->distance_to_latitude(max($box->south, -90)), $this->max_radius); } return true; }