/**
   * Creates a reoriented copy of this VoxelSelection and add a border of blank voxels on all faces.
   *
   * @param borderWidth the number of voxels in the border added to all faces
   * @param orientation the new orientation (flip, rotate)
   * @param wxzOrigin takes the current [wxMin, wzMin] and returns the new [wxMin, wzMin] - if the
   *     selection is rotated this may change
   * @return the new VoxelSelection
   */
  public VoxelSelection makeReorientedCopyWithBorder(
      QuadOrientation orientation, int borderWidth, Pair<Integer, Integer> wxzOrigin) {
    int wxMin = wxzOrigin.getFirst();
    int wzMin = wxzOrigin.getSecond();
    Pair<Integer, Integer> xrange = new Pair<Integer, Integer>(wxMin, wxMin + xSize - 1);
    Pair<Integer, Integer> zrange = new Pair<Integer, Integer>(wzMin, wzMin + zSize - 1);
    orientation.getWXZranges(xrange, zrange);
    int wxNewMin = xrange.getFirst();
    int wzNewMin = zrange.getFirst();
    wxzOrigin.setFirst(wxNewMin);
    wxzOrigin.setSecond(wzNewMin);

    int newXsize = (xrange.getSecond() - xrange.getFirst() + 1) + 2 * borderWidth;
    int newYsize = ySize + 2 * borderWidth;
    int newZsize = (zrange.getSecond() - zrange.getFirst() + 1) + 2 * borderWidth;
    VoxelSelection copy = new VoxelSelection(newXsize, newYsize, newZsize);
    for (int x = 0; x < xSize; ++x) {
      for (int y = 0; y < ySize; ++y) {
        for (int z = 0; z < zSize; ++z) {
          if (getVoxel(x, y, z)) {
            copy.setVoxel(
                orientation.calcWXfromXZ(x, z) + borderWidth - wxNewMin,
                y + borderWidth,
                orientation.calcWZfromXZ(x, z) + borderWidth - wzNewMin);
          }
        }
      }
    }
    return copy;
  }
 /**
  * Creates a copy of this VoxelSelection, adding a border of blank voxels on all faces. For
  * example - if the VoxelSelection has size 5x6x7, and borderWidth is 2, the resulting
  * VoxelSelection is 9x10x11 in size And (eg) if the initial VoxelSelection is all set, the new
  * selection will be all clear except from the box from [2,2,2] to [6,7,8] inclusive which will be
  * all set
  *
  * @param borderWidth the number of voxels in the border added to all faces
  * @return the new VoxelSelection
  */
 public VoxelSelection makeCopyWithEmptyBorder(int borderWidth) {
   VoxelSelection copy =
       new VoxelSelection(
           xSize + 2 * borderWidth, ySize + 2 * borderWidth, zSize + 2 * borderWidth);
   for (int x = 0; x < xSize; ++x) {
     for (int y = 0; y < ySize; ++y) {
       for (int z = 0; z < zSize; ++z) {
         if (getVoxel(x, y, z)) {
           copy.setVoxel(x + borderWidth, y + borderWidth, z + borderWidth);
         }
       }
     }
   }
   return copy;
 }
 /**
  * For the given VoxelSelection, make a "BorderMask" copy where all the empty voxels adjacent to a
  * set voxel are marked as set. i.e. for a given [x,y,z]: 1) if the voxel is set, the BorderMask
  * voxel is clear 2) if all of the six adjacent voxels are clear, the BorderMask voxel is clear 3)
  * otherwise, the BorderMask voxel is set.
  *
  * @return
  */
 public VoxelSelection generateBorderMask() {
   VoxelSelection copy = new VoxelSelection(xSize, ySize, zSize);
   for (int x = 0; x < xSize; ++x) {
     for (int y = 0; y < ySize; ++y) {
       for (int z = 0; z < zSize; ++z) {
         if (!getVoxel(x, y, z)) {
           if (getVoxel(x - 1, y, z)
               || getVoxel(x + 1, y, z)
               || getVoxel(x, y - 1, z)
               || getVoxel(x, y + 1, z)
               || getVoxel(x, y, z - 1)
               || getVoxel(x, y, z + 1)) {
             copy.setVoxel(x, y, z);
           }
         }
       }
     }
   }
   return copy;
 }
 /**
  * splits this VoxelSelection into two, in accordance with the supplied mask: For each set voxel
  * in this: 1) if the mask is clear, the voxel is removed from this and added to the return value
  * 2) if the mask is set, the voxel remains in this
  *
  * @param mask
  * @param xOffsetOfMask the origin of the mask relative to the origin of this fragment
  * @param yOffsetOfMask
  * @param zOffsetOfMask
  * @return a new VoxelSelection containing those voxels that aren't also present in the mask.
  */
 public VoxelSelection splitByMask(
     VoxelSelection mask, int xOffsetOfMask, int yOffsetOfMask, int zOffsetOfMask) {
   VoxelSelection notOverlapped = new VoxelSelection(this);
   notOverlapped.clearAll();
   int xSize = mask.getxSize();
   int ySize = mask.getySize();
   int zSize = mask.getzSize();
   for (int x = 0; x < xSize; ++x) {
     for (int z = 0; z < zSize; ++z) {
       for (int y = 0; y < ySize; ++y) {
         if (getVoxel(x - xOffsetOfMask, y - yOffsetOfMask, z - zOffsetOfMask)) {
           if (!mask.getVoxel(x, y, z)) {
             notOverlapped.setVoxel(x - xOffsetOfMask, y - yOffsetOfMask, z - zOffsetOfMask);
             this.clearVoxel(x - xOffsetOfMask, y - yOffsetOfMask, z - zOffsetOfMask);
           }
         }
       }
     }
   }
   return notOverlapped;
 }