static double getMaxDiff(AttributeGrid indexGrid, double pntx[], double pnty[], double pntz[]) {

    int nx = indexGrid.getWidth();
    int ny = indexGrid.getHeight();
    int nz = indexGrid.getDepth();
    double coord[] = new double[3];
    double maxDiff = 0;
    for (int z = 0; z < nz; z++) {
      for (int y = 0; y < ny; y++) {
        for (int x = 0; x < nx; x++) {
          int ind = (int) indexGrid.getAttribute(x, y, z);
          if (ind != 0) {
            double dx = pntx[ind] - (x + 0.5),
                dy = pnty[ind] - (y + 0.5),
                dz = pntz[ind] - (z + 0.5);
            double dist = sqrt(dx * dx + dy * dy + dz * dz);
            double edist = minDistance((x + 0.5), (y + 0.5), (z + 0.5), pntx, pnty, pntz);
            double diff = abs(dist - edist);
            if (diff > maxDiff) maxDiff = diff;
          }
        }
      }
    }
    return maxDiff;
  }
  AttributeGrid makeDistanceGrid(
      Bounds bounds, double minDistance, double maxDistance, int bitCount, double voxelSize) {

    AttributeGrid grid = new ArrayAttributeGridShort(bounds, voxelSize, voxelSize);
    grid.setDataDesc(
        new GridDataDesc(
            new GridDataChannel(
                GridDataChannel.DISTANCE, "dist", bitCount, 0, minDistance, maxDistance)));
    return grid;
  }
Beispiel #3
0
    void processModelVoxel6(int x, int y, int z) {

      if (grid.getState(x + 1, y, z) == OUTSIDE
          || grid.getState(x - 1, y, z) == OUTSIDE
          || grid.getState(x, y + 1, z) == OUTSIDE
          || grid.getState(x, y - 1, z) == OUTSIDE
          || grid.getState(x, y, z + 1) == OUTSIDE
          || grid.getState(x, y, z - 1) == OUTSIDE) {
        surfaceMask.set(x, y, z, 1);
      }
    }
Beispiel #4
0
    CustomVoxelsCollector(
        AttributeGrid grid,
        GridBitIntervals surfaceMask,
        int neighbors[],
        VoxelChecker voxelChecker) {

      this.grid = grid;
      this.surfaceMask = surfaceMask;
      this.neighbors = neighbors;
      this.voxelChecker = voxelChecker;
      this.nx = grid.getWidth();
      this.ny = grid.getHeight();
      this.nz = grid.getDepth();
    }
  static void printDiff(
      AttributeGrid indexGrid, double pntx[], double pnty[], double pntz[], boolean printInd) {

    int nx = indexGrid.getWidth();
    int ny = indexGrid.getHeight();
    int nz = indexGrid.getDepth();
    double coord[] = new double[3];
    double maxDiff = 0;
    for (int z = 0; z < nz; z++) {
      if (DEBUG) printf("z: %d\n", z);
      for (int y = 0; y < ny; y++) {
        for (int x = 0; x < nx; x++) {
          int ind = (int) indexGrid.getAttribute(x, y, z);
          if (ind != 0) {
            double dx = pntx[ind] - (x + 0.5),
                dy = pnty[ind] - (y + 0.5),
                dz = pntz[ind] - (z + 0.5);
            double dist = sqrt(dx * dx + dy * dy + dz * dz);
            double edist = minDistance((x + 0.5), (y + 0.5), (z + 0.5), pntx, pnty, pntz);
            double diff = abs(dist - edist);
            if (diff > maxDiff) maxDiff = diff;
            int inde = minIndex((x + 0.5), (y + 0.5), (z + 0.5), pntx, pnty, pntz);
            // if(inde != ind) printf("%2d ", inde);
            if (inde != ind) {
              if (printInd) printf("%2d ", inde);
              else {
                int d = (int) (diff * 100 + 0.5);
                if (d != 0) printf("%2d ", d);
                else printf(" . ");
              }
            } else {
              if (printInd) printf("%2d ", inde);
              else printf(" . ");
            }
            // if(diffind != 0.0)
            // voxel has point accociated with it
            //    printf("%3d ", diffind);
            // else
            //    printf("  o ");
          } else {
            printf("  x ");
          }
        }
        printf("\n");
      }
      printf("--\n");
    }
    printf("maxDiff: %10.3e\n", maxDiff);
  }
Beispiel #6
0
    void processModelVoxel(int x, int y, int z) {
      if (voxelChecker != null) {
        if (!voxelChecker.canProcess(x, y, z)) {
          return;
        }
      }
      int nlength = neighbors.length;
      int index = 0;
      while (index < nlength) {
        int ix = neighbors[index++];
        int iy = neighbors[index++];
        int iz = neighbors[index++];
        int xx = x + ix;
        int yy = y + iy;
        int zz = z + iz;
        if (xx >= 0 && xx < nx && yy >= 0 && yy < ny && zz >= 0 && zz < nz) {

          if (grid.getState(xx, yy, zz) == OUTSIDE) {
            // we have outside neighbor, set mask to
            surfaceMask.set(x, y, z, 1);
            return;
          }
        }
      }
    }
  /**
   * Set the value of a voxel.
   *
   * @param x The x world coordinate
   * @param y The y world coordinate
   * @param z The z world coordinate
   * @param state The value. 0 = nothing. > 0 materialID
   * @param material The materialID
   */
  public void setDataWorld(double x, double y, double z, byte state, long material) {
    /*
          // Not sure why this was here, doesn't seem to make sense.

          if (vd.getState() != Grid.OUTSIDE && state != Grid.OUTSIDE
              && vd.getAttribute() != material ) {
              throw new IllegalArgumentException("Invalid state change at pos: " + x + " " + y + " " + z);
          }
    */
    ((AttributeGrid) grid).setDataWorld(x, y, z, state, material);
  }
  /**
   * Set the value of a voxel.
   *
   * @param x The x world coordinate
   * @param y The y world coordinate
   * @param z The z world coordinate
   * @param state The new state
   * @param material The new material value. 0 = nothing. > 0 materialID
   */
  public void setData(int x, int y, int z, byte state, long material) {
    /*
          // Not sure why this was here, doesn't seem to make sense.
          if (vd.getState() != Grid.OUTSIDE && state != Grid.OUTSIDE
              && vd.getAttribute() != material ) {

              System.out.println("curr state: " + vd.getState() + " new state: " + state);
              System.out.println("old material: " + vd.getAttribute() + " new mat: " + material);
              throw new IllegalArgumentException("Invalid state change at index: " + x + " " + y + " " + z);
          }
    */
    ((AttributeGrid) grid).setData(x, y, z, state, material);
  }
Beispiel #9
0
  public AttributeGrid execute(AttributeGrid grid) {

    printf("ErosionMask.execute()\n");

    m_grid = grid;

    int nx = grid.getWidth();
    int ny = grid.getHeight();
    int nz = grid.getDepth();
    m_surfaceMask = new GridBitIntervals(nx, ny, nz);

    if (m_nnCount == 0) {

      // spherical erosion
      m_grid.find(
          VoxelClasses.INSIDE,
          new CustomVoxelsCollector(
              m_grid, m_surfaceMask, MaskFactory.makeBall(m_iterCount), m_voxelChecker));
      // m_grid.find(VoxelClasses.INSIDE, new SphericalVoxelsCollector(m_grid, m_surfaceMask,
      // m_iterCount, m_voxelChecker));
      // set marked voxels as OUTSIDE
      m_surfaceMask.find(VoxelClasses.INSIDE, new VoxelStateSetter(m_grid, Grid.OUTSIDE));
      m_surfaceMask.clear();

    } else {

      for (int i = 0; i < m_iterCount; i++) {

        makeOneIteration(getCount(i));
      }
    }

    m_grid = null;
    m_surfaceMask = null;

    return grid;
  }
  static void printIndices(AttributeGrid indexGrid) {

    int nx = indexGrid.getWidth();
    int ny = indexGrid.getHeight();
    int nz = indexGrid.getDepth();
    double coord[] = new double[3];

    for (int z = 0; z < nz; z++) {
      printf("z: %d\n", z);
      for (int y = 0; y < ny; y++) {
        for (int x = 0; x < nx; x++) {
          int ind = (int) indexGrid.getAttribute(x, y, z);
          if (ind != 0) {
            // voxel has point accociated with it
            printf("%2d ", ind);
          } else {
            printf(" . ");
          }
        }
        printf("\n");
      }
      printf("--\n");
    }
  }
Beispiel #11
0
  protected void createMipMap(AttributeGrid grid) {
    grid.getGridBounds(gbounds);
    xgmin = gbounds[0];
    ygmin = gbounds[2];
    zgmin = gbounds[4];

    scaleFactor = grid.getWidth() / (gbounds[1] - gbounds[0]);

    int nx = grid.getWidth();
    int ny = grid.getHeight();
    int nz = grid.getDepth();

    if (DEBUG) {
      printf("createMipMap()\n grid [%d x %d x %d]\n", nx, ny, nz);
    }
    Vector vgrids = new Vector();
    vgrids.add(grid);
    int levelCount = 1;
    while (nx > 1 || ny > 1 || nz > 1) {

      grid = makeGridHalfSize(grid, nx, ny, nz, m_scalingType);
      vgrids.add(grid);

      nx = (nx + 1) / 2;
      ny = (ny + 1) / 2;
      nz = (nz + 1) / 2;

      if (DEBUG) {
        printf("  mipmap level [%d x %d x %d]\n", nx, ny, nz);
      }
      levelCount++;
    }
    printf("  levelCount: %d\n", levelCount);

    m_grids = (AttributeGrid[]) vgrids.toArray(new AttributeGrid[levelCount]);
  }
Beispiel #12
0
 void processModelVoxel(int x, int y, int z) {
   if (voxelChecker != null) {
     if (!voxelChecker.canProcess(x, y, z)) {
       return;
     }
   }
   for (int iy = -ballSize; iy <= ballSize; iy++) {
     for (int ix = -ballSize; ix <= ballSize; ix++) {
       for (int iz = -ballSize; iz <= ballSize; iz++) {
         int r2 = (ix * ix + iy * iy + iz * iz);
         if (r2 <= ballSize2) {
           // printf("%d \n", r2, );
           if (grid.getState(x + ix, y + iy, z + iz) == OUTSIDE) {
             //
             surfaceMask.set(x, y, z, 1);
             return;
           }
         }
       }
     }
   }
 }
Beispiel #13
0
  /** removes one layer of surface voxels */
  public void makeOneIteration(int nnCount) {

    // m_markedCount = 0;

    // long t0 = currentTimeMillis();
    // if(m_surfaceMask != null){
    // we have surface voxels stored on previous step
    // scan only surface voxels
    // processSurfaceVoxel(x,y,z);

    // } else {
    // no surface calculated yet. Scan the whole grid to find marked voxels

    m_grid.find(VoxelClasses.INSIDE, new SurfaceVoxelsCollector(m_grid, m_surfaceMask, nnCount));

    // }

    // set marked voxels as OUTSIDE
    m_surfaceMask.find(VoxelClasses.INSIDE, new VoxelStateSetter(m_grid, Grid.OUTSIDE));

    m_surfaceMask.clear();
  }
 /**
  * Set the attribute value of a voxel. Leaves the state unchanged.
  *
  * @param x The x world coordinate
  * @param y The y world coordinate
  * @param attribute The attribute
  */
 public void setAttributes(int x, int y, long[] attribute) {
   int nz = attribute.length;
   for (int z = 0; z < nz; z++) {
     ((AttributeGrid) grid).setAttribute(x, y, z, attribute[z]);
   }
 }
 /**
  * Set the material value of a voxel. Leaves the state unchanged.
  *
  * @param x The x world coordinate
  * @param y The y world coordinate
  * @param z The z world coordinate
  * @param material The materialID
  */
 public void setAttribute(int x, int y, int z, long material) {
   ((AttributeGrid) grid).setAttribute(x, y, z, material);
 }
Beispiel #16
0
 public boolean foundInterruptible(int x, int y, int z, byte _state) {
   grid.setState(x, y, z, state);
   return true;
 }
Beispiel #17
0
 public void found(int x, int y, int z, byte _state) {
   grid.setState(x, y, z, state);
 }
 /**
  * Traverse a class of voxels types. May be much faster then full grid traversal for some
  * implementations.
  *
  * @param vc The class of voxels to traverse
  * @param t The traverer to call for each voxel
  */
 public void findAttribute(VoxelClasses vc, ClassAttributeTraverser t) {
   ((AttributeGrid) grid).findAttribute(vc, t);
 }
 /**
  * Traverse a class of voxels types over given rectangle in xy plane. May be much faster then full
  * grid traversal for some implementations.
  *
  * @param vc The class of voxels to traverse
  * @param t The traverer to call for each voxel
  * @param xmin - minimal x - coordinate of voxels
  * @param xmax - maximal x - coordinate of voxels
  * @param ymin - minimal y - coordinate of voxels
  * @param ymax - maximal y - coordinate of voxels
  */
 public void findAttribute(
     VoxelClasses vc, ClassAttributeTraverser t, int xmin, int xmax, int ymin, int ymax) {
   ((AttributeGrid) grid).findAttribute(vc, t, xmin, xmax, ymin, ymax);
 }
 /**
  * Traverse a class of material types. May be much faster then full grid traversal for some
  * implementations.
  *
  * @param mat The material to traverse
  * @param t The traverer to call for each voxel
  */
 public void findAttributeInterruptible(long mat, ClassAttributeTraverser t) {
   ((AttributeGrid) grid).findAttributeInterruptible(mat, t);
 }
 /**
  * Traverse a class of voxel and material types. May be much faster then full grid traversal for
  * some implementations.
  *
  * @param vc The class of voxels to traverse
  * @param mat The material to traverse
  * @param t The traverer to call for each voxel
  */
 public void findAttributeInterruptible(VoxelClasses vc, long mat, ClassAttributeTraverser t) {
   ((AttributeGrid) grid).findAttributeInterruptible(vc, mat, t);
 }
  static void renderDiff(
      AttributeGrid indexGrid,
      int z,
      double pntx[],
      double pnty[],
      double pntz[],
      int vs,
      String filePath,
      boolean renderErrors)
      throws Exception {

    int nx = indexGrid.getWidth();
    int ny = indexGrid.getHeight();
    int nz = indexGrid.getDepth();

    int picx = nx * vs;
    int picy = ny * vs;
    BufferedImage image = new BufferedImage(picx, picy, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = (Graphics2D) image.getGraphics();
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    Color backgroundColor = new Color(240, 240, 240);
    Color voxelColor = new Color(255, 255, 255);
    Color pointColor = new Color(0, 0, 0);
    Color calcLineColor = new Color(255, 0, 0);
    Color exactLineColor = new Color(0, 0, 255);
    Color colors[] =
        new Color[] {
          new Color(255, 150, 150),
          new Color(255, 255, 150),
          new Color(150, 255, 150),
          new Color(150, 255, 255),
          new Color(200, 150, 255),
          new Color(255, 150, 255),
          new Color(200, 150, 150),
          new Color(50, 150, 200),
          new Color(250, 150, 150),
          new Color(150, 250, 150),
          new Color(200, 150, 150),
          new Color(255, 200, 150),
          new Color(255, 255, 150),
          new Color(150, 255, 200),
          new Color(100, 200, 255),
          new Color(150, 150, 255),
          new Color(230, 190, 255),
          new Color(200, 150, 150),
          new Color(150, 150, 200),
          new Color(200, 250, 150),
        };

    colors = getRainbowColors(61);

    int pointSize = 4;

    g.setColor(backgroundColor);
    g.fillRect(0, 0, picx, picy);

    g.setColor(voxelColor);

    for (int y = 0; y < ny; y++) {
      for (int x = 0; x < nx; x++) {
        g.fillRect(x * vs, y * vs, vs - 1, vs - 1);
      }
    }
    for (int y = 0; y < ny; y++) {
      for (int x = 0; x < nx; x++) {
        int ind = (int) indexGrid.getAttribute(x, y, z);
        if (ind != 0) {
          g.setColor(colors[(ind - 1) % colors.length]);
          g.fillRect(x * vs, y * vs, vs - 1, vs - 1);
        }
      }
    }

    g.setColor(pointColor);
    for (int k = 1; k < pntx.length; k++) {

      int pz = (int) (pntz[k]);
      if (pz == z) {
        // point is in the z-slice
        int px = iround(vs * pntx[k]);
        int py = iround(vs * pnty[k]);
        g.fillOval(px - pointSize / 2, py - pointSize / 2, pointSize, pointSize);
      }
    }

    for (int y = 0; y < ny; y++) {
      for (int x = 0; x < nx; x++) {
        int ind = (int) indexGrid.getAttribute(x, y, z);
        if (ind != 0) {
          double x0 = (x + 0.5), y0 = (y + 0.5), z0 = (z + 0.5);

          double dx = pntx[ind] - x0, dy = pnty[ind] - y0, dz = pntz[ind] - z0;
          double dist = sqrt(dx * dx + dy * dy + dz * dz);
          double edist = minDistance(x0, y0, z0, pntx, pnty, pntz);
          int inde = minIndex(x0, y0, z0, pntx, pnty, pntz);
          double error = abs(dist - edist);
          if (inde != ind && error > 0.01 && renderErrors) {
            g.setColor(pointColor);
            if (error > 0.8) error = 0.8;
            double s = (vs * error);
            g.drawRect(iround(vs * x0 - s / 2), iround(vs * y0 - s / 2), iround(s), iround(s));
            // g.setColor(calcLineColor);
            // g.drawLine(iround(vs*x0), iround(vs*y0), iround(vs*pntx[ind]), iround(vs*pnty[ind]));
            // g.setColor(exactLineColor);
            // g.drawLine(iround(vs*x0), iround(vs*y0), iround(vs*pntx[inde]),
            // iround(vs*pnty[inde]));
          }
        }
      }
    }

    ImageIO.write(image, "png", new File(filePath));
  }
 /**
  * Remove all voxels associated with the Material.
  *
  * @param mat The aterialID
  */
 public void removeAttribute(long mat) {
   ((AttributeGrid) grid).removeAttribute(mat);
 }
 /** copy data from fromGrid into this grid */
 public void copyData(AttributeGrid fromGrid) {
   ((AttributeGrid) grid).copyData(fromGrid);
 }
 /**
  * assign to the grid a description of a voxel attributes
  *
  * @param description The attirbute description
  * @override
  */
 public void setDataDesc(GridDataDesc description) {
   ((AttributeGrid) grid).setDataDesc(description);
 }
 /**
  * Reassign a group of materials to a new materialID
  *
  * @param materials The new list of materials
  * @param matID The new materialID
  */
 public void reassignAttribute(long[] materials, long matID) {
   ((AttributeGrid) grid).reassignAttribute(materials, matID);
 }
Beispiel #27
0
  /** returns interpolated value from one grid; */
  double getValue(AttributeGrid grid, double x, double y, double z) {

    int nx = grid.getWidth(), ny = grid.getHeight(), nz = grid.getDepth();

    // half voxel shift to get to the voxels centers
    x -= 0.5;
    y -= 0.5;
    z -= 0.5;

    int ix = (int) floor(x), iy = (int) floor(y), iz = (int) floor(z);

    int ix1 = (ix + 1), iy1 = (iy + 1), iz1 = (iz + 1);

    double dx = x - ix, dy = y - iy, dz = z - iz, dx1 = 1. - dx, dy1 = 1. - dy, dz1 = 1. - dz;

    int mask = ALLCORNERS; // mask to calculate 8 corners of the cube

    if ((m_repeatType & REPEAT_X) != 0) {
      ix = reminder(ix, nx);
      ix1 = reminder(ix1, nx);
    } else {
      if (isOutside(ix, nx)) mask &= MASKX0;
      if (isOutside(ix1, nx)) mask &= MASKX1;
    }
    if ((m_repeatType & REPEAT_Y) != 0) {
      iy = reminder(iy, ny);
      iy1 = reminder(iy1, ny);
    } else {
      if (isOutside(iy, ny)) mask &= MASKY0;
      if (isOutside(iy1, ny)) mask &= MASKY1;
    }

    if ((m_repeatType & REPEAT_Z) != 0) {
      iz = reminder(iz, nz);
      iz1 = reminder(iz1, nz);
    } else {
      if (isOutside(iz, nz)) mask &= MASKZ0;
      if (isOutside(iz1, nz)) mask &= MASKZ1;
    }

    // try {
    long v000 = ((mask & B000) != 0) ? grid.getAttribute(ix, iy, iz) : 0,
        v100 = ((mask & B100) != 0) ? grid.getAttribute(ix1, iy, iz) : 0,
        v010 = ((mask & B010) != 0) ? grid.getAttribute(ix, iy1, iz) : 0,
        v110 = ((mask & B110) != 0) ? grid.getAttribute(ix1, iy1, iz) : 0,
        v001 = ((mask & B001) != 0) ? grid.getAttribute(ix, iy, iz1) : 0,
        v101 = ((mask & B101) != 0) ? grid.getAttribute(ix1, iy, iz1) : 0,
        v011 = ((mask & B011) != 0) ? grid.getAttribute(ix, iy1, iz1) : 0,
        v111 = ((mask & B111) != 0) ? grid.getAttribute(ix1, iy1, iz1) : 0;
    double d =
        dx1 * (dy1 * (dz1 * v000 + dz * v001) + dy * (dz1 * v010 + dz * v011))
            + dx * (dy1 * (dz1 * v100 + dz * v101) + dy * (dz1 * v110 + dz * v111));

    return d;
    // } catch(Exception e){
    // e.printStackTrace();
    //    printf("        ix: (%d %d %d), nx: (%d %d %d)  [%s %s %s]\n", ix, iy, iz, nx, ny, nz,
    //           ((m_repeatType & REPEAT_X) != 0),((m_repeatType & REPEAT_Y) != 0),((m_repeatType &
    // REPEAT_Z) != 0));
    // }
    // return 0;
  }
Beispiel #28
0
  /** creates grid of half size */
  static AttributeGrid makeGridHalfSize(AttributeGrid inGrid, int nx, int ny, int nz, int type) {

    int nx1 = (nx + 1) / 2;
    int ny1 = (ny + 1) / 2;
    int nz1 = (nz + 1) / 2;
    AttributeGrid grid =
        (AttributeGrid)
            inGrid.createEmpty(
                nx1, ny1, nz1, 2 * inGrid.getVoxelSize(), 2 * inGrid.getSliceHeight());

    long att[] = new long[8];

    for (int y = 0; y < ny1; y++) {
      int yy = 2 * y;
      int yy1 = (yy + 1);
      if (yy1 >= ny) yy1 = yy;
      for (int x = 0; x < nx1; x++) {

        int xx = 2 * x;
        int xx1 = (xx + 1);
        if (xx1 >= nx) xx1 = xx;

        for (int z = 0; z < nz1; z++) {

          int zz = 2 * z;
          int zz1 = (zz + 1) % nz;
          if (zz1 >= nz) zz1 = zz;
          int c = 0;

          att[c++] = inGrid.getAttribute(xx, yy, zz);
          att[c++] = inGrid.getAttribute(xx, yy, zz1);
          att[c++] = inGrid.getAttribute(xx1, yy, zz);
          att[c++] = inGrid.getAttribute(xx1, yy, zz1);
          att[c++] = inGrid.getAttribute(xx1, yy1, zz);
          att[c++] = inGrid.getAttribute(xx1, yy1, zz1);
          att[c++] = inGrid.getAttribute(xx, yy1, zz);
          att[c++] = inGrid.getAttribute(xx, yy1, zz1);

          switch (type) {
            default:
            case SCALING_AVERAGE:
              grid.setAttribute(x, y, z, average(att));
              break;
            case SCALING_MAX:
              grid.setAttribute(x, y, z, max(att));
              break;
          }
        }
      }
    }

    return grid;
  }
  @Override
  public AttributeGrid execute(AttributeGrid dest) {

    if (dest.getWidth() != distanceGrid.getWidth()
        || dest.getHeight() != distanceGrid.getHeight()
        || dest.getDepth() != distanceGrid.getDepth()) {
      printf(
          "Distance grid: %d %d %d\n",
          distanceGrid.getWidth(), distanceGrid.getHeight(), distanceGrid.getDepth());
      printf("Dest grid: %d %d %d\n", dest.getWidth(), dest.getHeight(), dest.getDepth());
      throw new IllegalArgumentException(
          "DistanceGrid and DensityGrid must be the same dimensions");
    }

    double vs = distanceGrid.getVoxelSize();

    int nx = distanceGrid.getWidth();
    int ny = distanceGrid.getHeight();
    int nz = distanceGrid.getDepth();

    // 5 intervals for distance values
    // -INF,  inDistanceMinus, inDistancePlus, outDistanceMinus, outDistancePlus, +INF
    int inDistanceMinus = (int) ((inDistanceValue / vs - 0.5) * subvoxelResolution);
    int inDistancePlus = (int) ((inDistanceValue / vs + 0.5) * subvoxelResolution);
    int outDistanceMinus = (int) ((outDistanceValue / vs - 0.5) * subvoxelResolution);
    int outDistancePlus = (int) ((outDistanceValue / vs + 0.5) * subvoxelResolution);
    if (inDistanceValue < maxInDistanceValue) {
      // no interior shell will be generated
      inDistanceMinus = inDistancePlus = DEFAULT_IN_VALUE;
    }
    if (outDistanceValue > maxOutDistanceValue) {
      // no exterior shell will be generated
      outDistanceMinus = outDistancePlus = DEFAULT_OUT_VALUE;
    }
    //
    // TODO make it MT
    //
    for (int y = 0; y < ny; y++) {
      for (int x = 0; x < nx; x++) {
        for (int z = 0; z < nz; z++) {
          long att = (long) (short) distanceGrid.getAttribute(x, y, z);

          short dest_att;

          if (att < inDistanceMinus) {
            dest.setAttribute(x, y, z, 0);
          } else if (att >= inDistanceMinus && att < inDistancePlus) {
            dest_att = (short) (att - inDistanceMinus);
            dest.setAttribute(x, y, z, dest_att);
          } else if (att >= inDistancePlus && att < outDistanceMinus || att == DEFAULT_IN_VALUE) {
            dest_att = (short) subvoxelResolution;
            dest.setAttribute(x, y, z, dest_att);
          } else if (att >= outDistanceMinus && att <= outDistancePlus) {
            dest_att = (short) (outDistancePlus - att);
            dest.setAttribute(x, y, z, dest_att);
          } else {
            dest.setAttribute(x, y, z, 0);
          }
        }
      }
    }

    return dest;
  }
 public void setAttributeWorld(double x, double y, double z, long attribute) {
   ((AttributeGrid) grid).setAttributeWorld(x, y, z, attribute);
 }