| 
<?php/***************************************************************
 *  hilbert curve
 *  Version 0.3
 *
 *  Copyright (c) 2010-2015 Chi Hoang
 *  All rights reserved
 ***************************************************************/
 /*************************
 *  hilbert_map_1  =  N
 *  hilbert_map_9  =  S
 *  hilbert_map_3  =  W
 *  hilbert_map_7  =  E
 *************************/
 
 class hilbert {
 
 var $moore_map = array (     "0,0" => array ( 0, "hilbert_map_7"),
 "0,1" => array ( 1, "hilbert_map_7"),
 "1,1" => array ( 2, "hilbert_map_3"),
 "1,0" => array ( 3, "hilbert_map_3"),
 );
 
 var $hilbert_map_1 = array (    'a' => array (
 "0, 0" => array (0, 'd'),
 "0, 1" => array (1, 'a'),
 "1, 0" => array (3, 'b'),
 "1, 1" => array (2, 'a')
 ),
 'b' => array (
 "0, 0" => array (2, 'b'),
 "0, 1" => array (1, 'b'),
 "1, 0" => array (3, 'a'),
 "1, 1" => array (0, 'c')
 ),
 'c' => array (
 "0, 0" => array (2, 'c'),
 "0, 1" => array (3, 'd'),
 "1, 0" => array (1, 'c'),
 "1, 1" => array (0, 'b')
 ),
 'd' => array (
 "0, 0" => array (0, 'a'),
 "0, 1" => array (3, 'c'),
 "1, 0" => array (1, 'd'),
 "1, 1" => array (2, 'd')
 ),
 );
 
 var $hilbert_map_7 = array (     'a' => array (
 "0, 0" => array (2, 'a'),
 "0, 1" => array (1, 'a'),
 "1, 0" => array (3, 'b'),
 "1, 1" => array (0, 'c')
 ),
 'b' => array (
 "0, 0" => array (0, 'd'),
 "0, 1" => array (1, 'b'),
 "1, 0" => array (3, 'a'),
 "1, 1" => array (2, 'b')
 ),
 'c' => array (
 "0, 0" => array (2, 'c'),
 "0, 1" => array (3, 'd'),
 "1, 0" => array (1, 'c'),
 "1, 1" => array (0, 'a')
 ),
 'd' => array (
 "0, 0" => array (0, 'b'),
 "0, 1" => array (3, 'c'),
 "1, 0" => array (1, 'd'),
 "1, 1" => array (2, 'd')
 ),
 );
 
 var $hilbert_map_3 = array (     'a' => array (
 "0, 0" => array (0, 'b'),
 "0, 1" => array (3, 'c'),
 "1, 0" => array (1, 'a'),
 "1, 1" => array (2, 'a')
 ),
 'b' => array (
 "0, 0" => array (0, 'a'),
 "0, 1" => array (1, 'b'),
 "1, 0" => array (3, 'd'),
 "1, 1" => array (2, 'b')
 ),
 'c' => array (
 "0, 0" => array (2, 'c'),
 "0, 1" => array (3, 'a'),
 "1, 0" => array (1, 'c'),
 "1, 1" => array (0, 'd')
 ),
 'd' => array (
 "0, 0" => array (2, 'd'),
 "0, 1" => array (1, 'd'),
 "1, 0" => array (3, 'b'),
 "1, 1" => array (0, 'c')
 ),
 );
 
 var $hilbert_map_9 = array (     'a' => array (
 "0, 0" => array (2, 'a'),
 "0, 1" => array (3, 'c'),
 "1, 0" => array (1, 'a'),
 "1, 1" => array (0, 'd')
 ),
 'b' => array (
 "0, 0" => array (0, 'c'),
 "0, 1" => array (1, 'b'),
 "1, 0" => array (3, 'd'),
 "1, 1" => array (2, 'b')
 ),
 'c' => array (
 "0, 0" => array (0, 'b'),
 "0, 1" => array (3, 'a'),
 "1, 0" => array (1, 'c'),
 "1, 1" => array (2, 'c')
 ),
 'd' => array (
 "0, 0" => array (2, 'd'),
 "0, 1" => array (1, 'd'),
 "1, 0" => array (3, 'b'),
 "1, 1" => array (0, 'a')
 ),
 );
 
 var $rev_map = Array ( 'a' => Array (
 Array (3, 'd'),
 Array (1, 'a'),
 Array (0, 'a'),
 Array (2, 'c')
 ),
 'b' => Array (
 Array (0, 'c'),
 Array (2, 'b'),
 Array (3, 'b'),
 Array (1, 'd')
 ),
 'c' => Array (
 Array (0, 'b'),
 Array (1, 'c'),
 Array (3, 'c'),
 Array (2, 'a')
 ),
 'd' => Array (
 Array (3, 'a'),
 Array (2, 'd'),
 Array (0, 'd'),
 Array (1, 'b')
 ),
 );
 
 var $z_map = array       (  'a' => array (
 "0, 0" => array (1, 'a'),
 "0, 1" => array (3, 'a'),
 "1, 0" => array (0, 'a'),
 "1, 1" => array (2, 'a')
 ),
 );
 
 function power($number,$base)
 {
 //use when the power is needed
 $pow=0;
 do {
 $number=ceil($number/$base);
 $pow++;
 } while ($number>1);
 
 if ($number==1)
 {
 return $pow;
 } else
 {
 return false;
 }
 }
 
 function point2quadkey($x, $y, $order=16, $map="hilbert_map_1", $mode="hilbert")
 {
 switch ($mode)
 {
 case "moore":
 {
 list( $moore, $map) = $this->point2moore ($x, $y, $order, "quadtree");
 //echo "\n$moore:$map\n";
 list( $x, $y) = $this->hilbert2point($moore, $order);
 //echo "\n$x:$y\n";
 $payload = $this->point2quadkey($x, $y, $order, $map);
 break;
 }
 default:
 {
 $current_square = 'a' ;
 $payload = 0;
 foreach (range($order-1, 0, -1) as $i) {
 $quad_x = $x & (1 << $i) ? 1 : 0;
 $quad_y = $y & (1 << $i) ? 1 : 0;
 list($quad_position, $current_square) = $this->{$map}[$current_square]["$quad_x, $quad_y"];
 $payload .= $quad_position;
 }
 break;
 }
 }
 return $payload;
 }
 
 function point2hilbert($x, $y, $order=16, $map="hilbert_map_1", $mode = "hilbert")
 {
 $current_square = 'a' ;
 $position = 0;
 foreach (range($order-1, 0, -1) as $i)
 {
 $position <<= 2;
 $quad_x = $x & (1 << $i) ? 1 : 0;
 $quad_y = $y & (1 << $i) ? 1 : 0;
 list($quad_position, $current_square) = $this->{$map}[$current_square]["$quad_x, $quad_y"];
 $position |= $quad_position;
 }
 return $position;
 }
 
 function hilbert2point ( $hilbert, $order ) {
 $current_square = "a";
 $amount = 1 << $order - 1;
 $x = $y = 0;
 for ($i=2*$order;  $i>0; $i -= 2) {
 list ( $position, $current_square ) = $this->rev_map [ $current_square ] [ $hilbert >> $i - 2 ];
 switch ( $position ) {
 case 1:  $x+=$amount;
 break;
 case 2:  $y+=$amount;
 break;
 case 3:  $y+=$amount;
 $x+=$amount;
 default: break;
 }
 $amount /= 2;
 $hilbert &=(1 << ($i - 2)) - 1;
 }
 }
 
 function point2zorder($x, $y, $order=16)
 {
 $current_square = 'a' ;
 $position = 0;
 foreach (range($order-1, 0, -1) as $i)
 {
 $position <<= 2;
 $quad_x = $x & (1 << $i) ? 1 : 0;
 $quad_y = $y & (1 << $i) ? 1 : 0;
 list($quad_position, $current_square) = $this->z_map[$current_square]["$quad_x, $quad_y"];
 $position |= $quad_position;
 }
 return $position;
 }
 
 // points $x,$y should be 2^1 higher than $order
 // example $this->point2moore(7,7,2);
 // $this->point2moore(15,15,3);
 function point2moore($x, $y, $order=4, $mode="normal")
 {
 $quad = pow(2, $order)-1;
 switch ($order)
 {
 case 2:
 {
 $curve_length = 16;
 break;
 }
 case  1:
 {
 $curve_length = 8;
 break;
 }
 case 0:
 {
 $curve_length = 4;
 break;
 }
 default:
 {
 $curve_length = pow(2, $quad)+1;
 break;
 }
 }
 
 $quad_x = $x & (1 << $order) ? 1 : 0;
 $quad_y = $y & (1 << $order) ? 1 : 0;
 
 list( $pos, $map ) = $this->moore_map[  "$quad_x,$quad_y" ];
 $pos *= $curve_length;
 $quad_x *= $quad+1;
 $quad_y *= $quad+1;
 list( $px, $py ) =  array ( $x-$quad_x , $y-$quad_y );
 
 switch ($mode)
 {
 case "quadtree":
 {
 //echo "\n$pos:$x:$y:$order:$map:$curve_length\n";
 $payload = array ($pos - $this->point2hilbert($px, $py, $order, $map)-$curve_length, $map);
 break;
 }
 default:
 {
 $payload =  $pos - $this->point2hilbert($px, $py, $order, $map)-$curve_length;
 break;
 }
 }
 return $payload;
 }
 }
 ?>
 |