Scrambler  1
hilbert.bg.c
Go to the documentation of this file.
00001 //#########################################################################
00002 //              
00003 //    Copyright (C) 2003-2012 Department of Physics and Astronomy,
00004 //                            University of Rochester,
00005 //                            Rochester, NY
00006 //
00007 //    hilbert.bg.c is part of AstroBEAR.
00008 //
00009 //    AstroBEAR is free software: you can redistribute it and/or modify   
00010 //    it under the terms of the GNU General Public License as published by 
00011 //    the Free Software Foundation, either version 3 of the License, or    
00012 //    (at your option) any later version.
00013 //
00014 //    AstroBEAR is distributed in the hope that it will be useful, 
00015 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 //    GNU General Public License for more details.
00018 //
00019 //    You should have received a copy of the GNU General Public License
00020 //    along with AstroBEAR.  If not, see <http://www.gnu.org/licenses/>.
00021 //
00022 //#########################################################################
00026 #include <stdio.h>
00027 #include <math.h>
00028 
00029 
00030 void closedformhilbert2d(int * nn, int * rr, int  * cc, int * hh) {
00031   unsigned h=0;
00032   unsigned ri=0;
00033   unsigned ci=0;
00034   unsigned pos; 
00035   unsigned mask; 
00036   unsigned i, tmp;
00037   unsigned n;
00038   unsigned r;
00039   unsigned c;
00040   n = *nn;
00041   r = *rr;
00042   c = *cc;
00043 
00044   // In 2D the hilbert curve looks like
00045   //    ___
00046   //   |   |  Ordering for cases  2  4   Hilbert Order       1  2
00047   //   |   |  ----------------->  1  3   ----------------->  0  3
00048 
00049   //                      
00050   //   __    __                  __    __
00051   //  |  |__|  |  4 sub pieces  |  |  |  |  2    4  | 2 is in standard orientation
00052   //  |__    __|   -------->     __    __           | 4 is also instandard orientation
00053   //   __|  |__                  __|  |__   1    3  | 1 needs to be flipped about x=y 
00054   //                                                | 3 needs to be flipped about x=-y
00055 
00056   // Basic idea is to coarsen hilbert curve out to get the 
00057   // meta position which determins the case and the coarse "meta" hilbert value
00058   // Then depending on which case, re-orient the sub grid so that it is in standard 
00059   // orientation.  Then multiply the meta hilbert value by 4 before adding the next 
00060   // level value and so on...
00061 
00062   // example n=3, r=4=100 ,c=5=101
00063   // pos=100
00064   // mask=011
00065 
00066   // i=0-> ri=001, ci=001 -> case 4 (meta hilbert value = 2)
00067   // ri->1, ci->0
00068   // r=000, c=001
00069   // h=10
00070   // pos=010
00071   // mask=001
00072 
00073   // i=1-> ri=000, ci=000 -> case 1 (meta hilbert value = 0)
00074   // ri->0, ci->0
00075   // r=001, c=000
00076   // h=1000
00077   // pos=001
00078   // mask=000
00079 
00080   // i=2-> ri=1, ci=0 -> case 3 (meta hilbert value = 3)
00081   // ri->1, ci->1
00082   // r=000, c=000
00083   // h=100011
00084   // pos=000
00085   // mask=000
00086 
00087   //hilbert value = 100011 = 35
00088 
00089   pos = 1 << (n-1);           // bit mask used to extract ri and ci which are meta positions of the coarsened hilbert curve
00090   mask = pow(2,(n-1))-1;      // 0001111111 mask used to subtract off ci and ri to get relative positions within the coarsened hilbert curve
00091   for (i=0; i<n; i++) {
00092 
00093     ri = (r & pos) >> (n-i-1);   // meta row position of coarsened hilbert curve
00094     ci = (c & pos) >> (n-i-1);   // meta column position of coarsened hilbert curve
00095     r = r & mask; c = c & mask;  // local row and column positions within the current section of the meta hilbert curve
00096 
00097     if (ri==0 && ci==0) {               // Case 1 (Lower left corner)
00098       ri = 0; ci = 0;                   //  meta hilbert value = 0 -> 00 in binary  
00099       tmp = r; r = c; c = tmp; }        // In order to rotate the next meta hilbert tree into standard order we need to reflect about x=y or swap r and c
00100     else if (ri==0 && ci==1) {          // Case 2 (Upper Left corner)
00101       ri = 0; ci = 1; }                 // meta hilbert value = 1 -> 01 in binary (already in standard order)
00102     else if (ri==1 && ci==0) {          // Case 3 (Lower right corner)
00103       ri = 1; ci = 1;                   // meta hilbert value = 3 -> 11 in binary
00104       tmp = r; r = c; c = tmp;          // Need to rotate -90 and reflect in x (x->-y->-y, y->x->-x) or (x=-y, y=-x)
00105       r = ~r & mask; c = ~c & mask; }   // to arrange in standard order
00106     else {                              // Case 4 (Upper right corner)
00107       ri = 1; ci = 0; }                 // meta hilbert value = 2 -> 10 in binary (Already in standard order)
00108 
00109     pos = pos >> 1; mask = mask >> 1;   // shift pos and mask to next finer level of hilbert fractal
00110     h = (((h << 1) | ri) << 1) | ci;    // multiply h by 4 and add contribution from meta hilbert value
00111   }
00112   *hh=h;
00113 }
00114 
00115 
00116 void closedformhilbert3d(int * nn, int * rr, int  * cc, int * dd, int * hh) {
00117   unsigned h=0;
00118   unsigned ri;
00119   unsigned ci;
00120   unsigned di;
00121   unsigned pos; 
00122   unsigned mask; 
00123   unsigned i, tmp;
00124   unsigned n;
00125   unsigned r;
00126   unsigned c;
00127   unsigned d;
00128   n = *nn;
00129   r = *rr;
00130   c = *cc;
00131   d = *dd;
00132 
00133   // And In 3D the hilbert curve looks like
00134   //    ____
00135   //   /   /  Ordering for cases  5  7    Hilbert Order     6  5
00136   //  / __/_  -----------------> 4  6   -----------------> 7  4
00137   //   / | /  ----------------->  1  3  ----------------->  1  2
00138   //  /  |/                      0  2                      0  3
00139 
00140 
00141   // I won't draw the second generation hilbert curve - but basic idea is the same for 2D.
00142   // For each case add the appropriate hilbert value based on the hilbert order
00143   // Then reorient the subsection into standard orientation using flips/rotations etc...
00144   // The second generation hilbert curve was taken from Space Filling Curves by ...
00145 
00146   h=0;
00147 
00148   pos = 1 << (n-1);           // bit mask used to extract ri and ci which are meta positions of the coarsened hilbert curve
00149   mask = pow(2,(n-1))-1;      // 0001111111 mask used to subtract off ci and ri to get relative positions within the coarsened hilbert curve
00150   for (i=0; i<n; i++) {
00151     ri = (r & pos) >> (n-i-1);   // meta row position of coarsened hilbert curve
00152     ci = (c & pos) >> (n-i-1);   // meta column position of coarsened hilbert curve
00153     di = (d & pos) >> (n-i-1);   // meta depth position
00154     r = r & mask; c = c & mask; d = d & mask;  // local row and column positions within the current section of the meta hilbert curve
00155     if (di==0 && ri==0 && ci==0) {                        // Case 1 (Bottom-Front-Left corner)
00156       di = 0; ri = 0; ci = 0;                             // meta hilbert value = 0 -> 000 in binary        
00157       tmp = c; c = d; d = tmp; }                          // Need to reflect around c=d
00158 
00159     else if (di==0 && ri==0 && ci==1) {                   // Case 2 (Bottom-Back-Left corner)
00160       di = 0; ri = 0; ci = 1;                             // meta hilbert value = 1 -> 001 in binary (already in standard order) 
00161       tmp = r; r = d; d = tmp; }                          // Need to reflect about r=d
00162 
00163     else if (di==0 && ri==1 && ci==0) {                   // Case 3 (Bottom-Front-Right corner)
00164       di = 0; ri = 1; ci = 1;                             // meta hilbert value = 3 -> 011 in binary
00165       tmp = r; r = ~c & mask; c = ~d & mask ; d = tmp;}   // need to rotate about [r,-c,d]
00166 
00167     else if (di==0 && ri==1 && ci==1) {                   // Case 4 (Bottom-Back-Right)
00168       di = 0; ri = 1; ci = 0; }                           // meta hilbert value = 2 -> 010 in binary (Already in standard order)
00169 
00170     else if (di==1 && ri==0 && ci==0) {                   // Case 5 (Top-Front-Left corner)
00171       di = 1; ri = 1; ci = 1;                             // meta hilbert value = 7 -> 111 in binary  
00172       tmp = c; c = ~d & mask; d = ~tmp & mask;}           // Need to reflect about c=-d
00173 
00174 
00175     else if (di==1 && ri==0 && ci==1) {                   // Case 6 (Top-Back-Left)
00176       di = 1; ri = 1; ci = 0;                             // meta hilbert value = 6 -> 110 in binary (already in standard order)
00177       tmp = r; r=~d & mask; d=~tmp & mask; }              // Need to reflect about d=-r
00178 
00179     else if (di==1 && ri==1 && ci==0) {                   // Case 7 (Top-Front-Right corner)
00180       di = 1; ri = 0; ci = 0;                             // meta hilbert value = 4 -> 100 in binary
00181       tmp = d; d = ~r & mask; r = ~c & mask; c = tmp;}    // Need to reflect about c=-r and then reflect about c=d
00182 
00183     else {// (di==1 && ri==1 && ci==1)                    // Case 8 (Top-Back-Right corner)
00184       di = 1; ri = 0; ci = 1; }                           // meta hilbert value = 5 -> 101 in binary (Already in standard order)
00185 
00186     pos = pos >> 1; mask = mask >> 1;                     // shift pos and mask to next finer level of hilbert fractal
00187     h = ((((h << 1) | di) << 1) | ri) << 1 | ci;          // multiply h by 8 and add contribution from meta hilbert value
00188   }
00189   *hh=h;
00190 }
 All Classes Files Functions Variables