2013-11-12 8 views
1

Итак, вот вопрос, который я получил от кода Дуга Мура от http://www.tiac.net/~sw/2008/10/Hilbert/moore/hilbert.c и преобразовал его в java для использования в моей магистерской диссертации по внедрению метода LSH для хранения фотонов в лучшем ракете с фотоном. Но вот в этом проблема. Из-за того, как я использую индексы Гильберта позже в моих порогах процесса, используются. Но пороги выстраиваются с трещинами в кривой Гильберта и вызывают артефакты в моем конечном изображении. Согласно исследованию, я решил, что это необходимо, чтобы немного повернуть пространство кривой Гильберта относительно первичной оси, но я не знаю, как это сделать. Если у кого-то есть какие-то мысли об этом, я очень застрял в данный момент и могу использовать какую-то помощь.Как выполнить поворот на пространстве кривых Гильберта вокруг первичной оси

temp = photonsBH [i] .key = h.hilbert_c2i (ТРЕХ, ШЕСТЬДЕСЯТ, координируется); Эта строка - это то, как я называю функцию гильберта, которую он принимает в 3 параграфа, первым является число измерений, второе - количество бит, а третье - это точка, которая была отправлена, хотя следующее уравнение для сохранения точности и сдвига точки положительного ,

xi = (int) (EPSILONSHIFT * photonsBH[i].pos[0]) + XYZ_shift[0]; 
yi = (int) (EPSILONSHIFT * photonsBH[i].pos[1]) + XYZ_shift[1]; 
zi = (int) (EPSILONSHIFT * photonsBH[i].pos[2]) + XYZ_shift[2]; 
coord[0] = new BigInteger("" + xi); 
coord[1] = new BigInteger("" + yi); 
coord[2] = new BigInteger("" + zi); 

код из hilbert.java

public class hilbert 
{ 
    // BigInteger bitmask_t; 
    // BigInteger halfmask_t; 

    public int size; 

    public hilbert(int s) 
    { 
     size = s; 
    } 

    /* 
    * #define adjust_rotation(rotation,nDims,bits) \ do { \ // rotation = 
    * (rotation + 1 + ffs(bits)) % nDims; \ bits &= -bits & nd1Ones; \ while 
    * (bits) \ bits >>= 1, ++rotation; \ if (++rotation >= nDims) \ rotation 
    * -= nDims; \ } while (0) 
    */ 

    public BigInteger adjust_rotation(BigInteger rotation, BigInteger nDims, 
      BigInteger bits, BigInteger nd1Ones) 
    { 

     bits = bits.and(nd1Ones.and(bits.negate())); 
     while (bits.signum() > 0) 
     { 
      bits = bits.shiftRight(1); 
      rotation = rotation.add(BigInteger.ONE); 
     } 
     if ((rotation = rotation.add(BigInteger.ONE)).compareTo(nDims) >= 0) 
     { 
      rotation = rotation.subtract(nDims); 
     } 

     return rotation; 
    } 

    // #define ones(T,k) ((((T)2) << (k-1)) - 1) 
    public BigInteger ones(BigInteger k) 
    { 
     BigInteger r = new BigInteger("2"); 
     r = r.shiftLeft(k.subtract(BigInteger.ONE).intValue()); 
     r = r.subtract(BigInteger.ONE); 
     // System.out.println("r:" + r); 
     return r; 
    } 

    // #define rdbit(w,k) (((w) >> (k)) & 1) 

    public BigInteger rdbit(BigInteger w, BigInteger k) 
    { 
     BigInteger r = w; 
     r = r.shiftRight(k.intValue()); 
     r = r.and(BigInteger.ONE); 
     return r; 
    } 

    // #define rotateRight(arg, nRots, nDims) ((((arg) >> (nRots)) | ((arg) << 
    // ((nDims)-(nRots)))) & ones(bitmask_t,nDims)) 
    public BigInteger rotateRight(BigInteger arg, BigInteger nRots, 
      BigInteger nDims) 
    { 
     BigInteger r1 = arg.shiftRight(nRots.intValue()); 
     BigInteger r2 = nDims.subtract(nRots); 
     BigInteger r3 = arg.shiftLeft(r2.intValue()); 
     BigInteger r4 = r1.or(r3); 
     BigInteger r5 = r4.and(ones(nDims)); 
     return r5; 
    } 

    // #define rotateLeft(arg, nRots, nDims) ((((arg) << (nRots)) | ((arg) >> 
    // ((nDims)-(nRots)))) & ones(bitmask_t,nDims)) 

    public BigInteger rotateLeft(BigInteger arg, BigInteger nRots, 
      BigInteger nDims) 
    { 
     BigInteger r1 = arg.shiftLeft(nRots.intValue()); 
     BigInteger r2 = nDims.subtract(nRots); 
     BigInteger r3 = arg.shiftRight(r2.intValue()); 
     BigInteger r4 = r1.or(r3); 
     BigInteger r5 = r4.and(ones(nDims)); 
     return r5; 
    } 

    public BigInteger bitTranspose(BigInteger nDims, BigInteger nBits, 
      BigInteger inCoords) 
    { 
     BigInteger nDims1 = nDims.subtract(BigInteger.ONE); 
     BigInteger inB = nBits; 
     BigInteger utB; 
     BigInteger inFieldEnds = BigInteger.ONE; 
     BigInteger inMask = ones(inB); 
     BigInteger coords = BigInteger.ZERO; 

     while ((utB = (inB.divide(new BigInteger("2")))).compareTo(BigInteger.ZERO) != 0) 
     { 
      BigInteger shiftAmt = nDims1.multiply(utB); 
      BigInteger utFieldEnds = inFieldEnds.or((inFieldEnds.shiftLeft((shiftAmt.add(utB)).intValue()))); 
      BigInteger utMask = utFieldEnds.shiftLeft(utB.intValue()).subtract(utFieldEnds); 
      BigInteger utCoords = BigInteger.ZERO; 
      BigInteger d; 

      if ((inB.and(BigInteger.ONE)).compareTo(BigInteger.ZERO) > 0) 
      { 
       BigInteger inFieldStarts = inFieldEnds.shiftLeft((inB.subtract(BigInteger.ONE)).intValue()); 
       BigInteger oddShift = shiftAmt.multiply(new BigInteger("2")); 

       for (d = BigInteger.ZERO; d.compareTo(nDims) < 0; d = d.add(BigInteger.ONE)) 
       { 
        BigInteger in = inCoords.and(inMask); 
        inCoords = inCoords.shiftRight(inB.intValue()); 
        BigInteger x1 = in.and(inFieldStarts); 
        BigInteger x3 = x1.shiftLeft(oddShift.intValue()); 
        oddShift = oddShift.add(BigInteger.ONE); 
        coords = coords.or(x3); 
        in = in.and(inFieldStarts.not()); 
        in = (in.or(in.shiftLeft(shiftAmt.intValue()))).and(utMask); 
        utCoords = utCoords.or(in.shiftLeft((d.multiply(utB)).intValue())); 
       } 
      } 
      else 
      { 
       for (d = BigInteger.ZERO; d.compareTo(nDims) < 0; d = d.add(BigInteger.ONE)) 
       { 
        BigInteger in = inCoords.and(inMask); 
        inCoords = inCoords.shiftRight(inB.intValue()); 
        in = (in.or(in.shiftLeft(shiftAmt.intValue()))).and(utMask); 
        utCoords = utCoords.or(in.shiftLeft((d.multiply(utB)).intValue())); 
       } 
      } 
      inCoords = utCoords; 
      inB = utB; 
      inFieldEnds = utFieldEnds; 
      inMask = utMask; 
     } 
     coords = coords.or(inCoords); 
     return coords; 

    } 

    /***************************************************************** 
    * hilbert_i2c 
    * 
    * Convert an index into a Hilbert curve to a set of coordinates. Inputs: 
    * nDims: Number of coordinate axes. nBits: Number of bits per axis. index: 
    * The index, contains nDims*nBits bits (so nDims*nBits must be <= 
    * 8*sizeof(bitmask_t)). Outputs: coord: The list of nDims coordinates, each 
    * with nBits bits. Assumptions: nDims*nBits <= (sizeof index) * 
    * (bits_per_byte) 
    */ 

    public double[] hilbert_i2c(BigInteger nDims, BigInteger nBits,BigInteger index) 
    { 
     double[] coord = new double[3]; 
     if (nDims.intValue() > 1) 
     { 
      BigInteger coords; 
      BigInteger nbOnes = ones(nBits); 

      if (nBits.compareTo(BigInteger.ONE) > 0) 
      { 
       BigInteger nDimsBits = nDims.multiply(nBits); 
       BigInteger ndOnes = ones(nDims); 
       BigInteger nd1Ones = ndOnes.shiftRight(1); 
       BigInteger b = nDimsBits; 
       BigInteger rotation = BigInteger.ZERO; 
       BigInteger flipBit = BigInteger.ZERO; 
       BigInteger nthbits = ones(nDimsBits).divide(ndOnes); 
       index = index.xor((index.xor(nthbits).shiftRight(1))); 
       coords = BigInteger.ZERO; 

       do 
       { 
        BigInteger bits = index.shiftRight((b = b.subtract(nDims)).intValue()).and(ndOnes); 
        coords = coords.shiftLeft(nDims.intValue()); 
        coords = coords.or(rotateLeft(bits, rotation, nDims).xor(flipBit)); 
        flipBit = (BigInteger.ONE).shiftLeft(rotation.intValue()); 
        rotation = adjust_rotation(rotation, nDims, bits, nd1Ones); 
       } while (b.intValue() > 0); 
       for (b = nDims; b.compareTo(nDimsBits) < 0; b = b.multiply(new BigInteger("2"))) 
       { 
        BigInteger c1 = coords.shiftRight(b.intValue()); 
        coords = coords.xor(c1); 
       } 
       coords = bitTranspose(nBits, nDims, coords); 
      } 
      else 
      { 
       coords = index.xor(index.shiftRight(1)); 
      } 

      for (int i = 0; i < coord.length; i++) 
      { 
       coord[i] = coords.and(nbOnes).doubleValue(); 
       coords = coords.shiftRight(nBits.intValue()); 
      } 
     } 
     else 
     { 
      coord[0] = index.doubleValue(); 
     } 

     return coord; 
    } 

    /***************************************************************** 
    * hilbert_c2i 
    * 
    * Convert coordinates of a point on a Hilbert curve to its index. Inputs: 
    * nDims: Number of coordinates. nBits: Number of bits/coordinate. coord: 
    * Array of n nBits-bit coordinates. Outputs: index: Output index value. 
    * nDims*nBits bits. Assumptions: nDims*nBits <= (sizeof bitmask_t) * 
    * (bits_per_byte) 
    */ 

    public BigInteger hilbert_c2i(BigInteger nDims, BigInteger nBits,BigInteger[] coord) 
    { 
     if (nDims.compareTo(BigInteger.ONE) > 0) 
     { 
      BigInteger index; 
      BigInteger nDimsBits = nDims.multiply(nBits); 
      BigInteger d; 
      BigInteger coords = BigInteger.ZERO; 

      for (int i = nDims.intValue(); i > 0; i--) 
      { 
       coords = coords.shiftLeft(nBits.intValue()); 
       coords = coords.or(coord[i - 1]); 
      } 

      if (nBits.compareTo(BigInteger.ONE) > 0) 
      { 
       BigInteger ndOnes = ones(nDims); 
       BigInteger nd1Ones = ndOnes.shiftRight(1); 
       BigInteger b = nDimsBits; 
       BigInteger rotation = BigInteger.ZERO; 
       BigDecimal rotation2 = new BigDecimal(""+ (-45.0 * (Math.PI/180))); 
       BigInteger flipBit = BigInteger.ZERO; 
       BigInteger nthBits = ones(nDimsBits).divide(ndOnes); 
       coords = bitTranspose(nDims, nBits, coords); 
       coords = coords.xor(coords.shiftRight(nDims.intValue())); 
       index = BigInteger.ZERO; 

       do 
       { 
        BigInteger bits = coords.shiftRight((b = b.subtract(nDims)).intValue()).and(ndOnes); 
        bits = rotateRight((flipBit.xor(bits)), rotation, nDims); 
        index = index.shiftLeft(nDims.intValue()); 
        index = index.or(bits); 
        flipBit = (BigInteger.ONE).shiftLeft(rotation.intValue()); 
        rotation = adjust_rotation(rotation, nDims, bits, nd1Ones); 
       } while (b.compareTo(BigInteger.ZERO) > 0); 

       index = index.xor(nthBits.shiftRight(1)); 
      } 
      else 
      { 
       index = coords; 
      } 
      for (d = BigInteger.ONE; d.compareTo(nDimsBits) < 0; d = d.multiply(new BigInteger("2"))) 
      { 
       index = index.xor((index.shiftRight(d.intValue()))); 
      } 
      return index; 
     } 
     else 
      return coord[0]; 
    } 
} 

ответ

0

Мда. Ну, у меня есть идея, но я не уверен, что это то, о чем вы просите - это в основном кажется слишком простым. Возможно, я не совсем понимаю вашу проблему. Тем не менее, мне кажется, что если вы хотите, чтобы повернуть пространство вокруг основной оси (я предполагаю, что первая координата является главной осью), вы могли бы изменить, что первый блок кода из:

xi = (int) (EPSILONSHIFT * photonsBH[i].pos[0]) + XYZ_shift[0]; 
yi = (int) (EPSILONSHIFT * photonsBH[i].pos[1]) + XYZ_shift[1]; 
zi = (int) (EPSILONSHIFT * photonsBH[i].pos[2]) + XYZ_shift[2]; 
coord[0] = new BigInteger("" + xi); 
coord[1] = new BigInteger("" + yi); 
coord[2] = new BigInteger("" + zi); 

в одно из следующего.

Я не уверен, хочет ли она повернута, прежде чем перенести его, или что, или вокруг чего вы хотите сдвинуты, но если повернуть его вокруг начала координат, прежде чем перенести его, вы можете использовать

double theta = 0.1; // in radians 
xi = (int) (EPSILONSHIFT * photonsBH[i].pos[0]) + XYZ_shift[0]; 
yi = (int) (EPSILONSHIFT * ((Math.cos(theta) * photonsBH[i].pos[1])-(Math.sin(theta) * photonsBH[i].pos[2]))) + XYZ_shift[1]; 
zi = (int) (EPSILONSHIFT * ((Math.sin(theta) * photonsBH[i].pos[1])+(Math.cos(theta) * photonsBH[i].pos[2]))) + XYZ_shift[2]; 
coord[0] = new BigInteger("" + xi); 
coord[1] = new BigInteger("" + yi); 
coord[2] = new BigInteger("" + zi); 

Я в основном применяю матрицу (или уравнения) от https://en.wikipedia.org/wiki/Rotation_%28mathematics%29. theta, однако, вы хотите, чтобы вращение было (в радианах). Помните, что вам нужно будет повернуть назад, когда вы вернетесь назад. Например, вот как я отменил вышеуказанную функцию:

xi = coord[0].intValue(); 
yi = coord[1].intValue(); 
zi = coord[2].intValue(); 
photonsBH[i].pos[0] = (int)((xi - XYZ_shift[0])/EPSILONSHIFT); 
double yt = (yi - XYZ_shift[1])/EPSILONSHIFT; 
double zt = (zi - XYZ_shift[2])/EPSILONSHIFT; 
photonsBH[i].pos[1] = (int)((Math.cos(theta) * yt)+(Math.sin(theta) * zt)); 
photonsBH[i].pos[2] = (int)((-Math.sin(theta) * yt)+(Math.cos(theta) * zt)); 

Я не знаю точно, как округление повлияет на ваши результаты. Я также не знаю, хотите ли вы, чтобы он повернулся, прежде чем переключиться, или что. На самом деле, я даже не знаю, действительно ли это то, что вы ищете. Может быть, это просто сбой вашего кода. Сообщите мне, хотите ли вы версию, которая вращается после смены или вращается вокруг определенной точки или чего-то еще.

+0

Да, я попробовал это решение, но не имел никакого эффекта. Спасибо за предложение tho. – John

+0

@John Odd. Полагаю, стоит подумать: что именно вы имеете в виду под «порогами»? Какие? – Erhannis

Смежные вопросы