/** this test compares result of MT and ST distance calculations */
  void devTestMTvsSTprecision() throws Exception {

    if (DEBUG) printf("%s.testPrecisionMTvsST()\n", this.getClass().getName());
    double vs = 0.5 * MM;
    double w = 10 * MM; // half width
    // double firstLayerThickness = 0.7;
    // double firstLayerThickness = 1.7;
    double firstLayerThickness = 2.7;
    // double xmin = -w, xmax = w, ymin = -w, ymax = w, zmin = -vs, zmax = 2*vs;
    double xmin = -w, xmax = w, ymin = -w, ymax = w, zmin = -w, zmax = w;
    int densityBitCount = 8;
    int distanceBitCount = 16;

    int subvoxelResolution = (1 << densityBitCount) - 1;

    int voxelSquareSize = 20; // for visualization
    boolean snapToGrid = false;
    int iterationsCount = 0;
    int threadCount = 4;
    boolean writeViz = false;
    boolean compareDistances = false;

    Bounds bounds = new Bounds(xmin, xmax, ymin, ymax, zmin, zmax);
    double pnts[];
    pnts = makeCircleZ(0.5 * vs, 0.5 * vs, 0.5 * vs, 0.9 * w, 128);
    // double pnts[] = makeCircleX(0.5*vs, 0.5*vs, 0.5*vs, 0.9*w, 128);
    // double pnts[]  = makeCircleY(0.5*vs, 0.5*vs, 0.5*vs, 0.9*w, 128);
    // pnts = makeUnion(makeUnion(makeCircleX(0.5*vs, 0.5*vs, 0.5*vs, 0.9*w,
    // 128),makeCircleY(0.5*vs, 0.5*vs, 0.5*vs, 0.9*w, 128)),makeCircleZ(0.5*vs, 0.5*vs, 0.5*vs,
    // 0.9*w, 128));
    // double pnts[] = makeUnion(makeUnion(makeCircleZ(0.5*vs, 0.25*vs, 0.5*w, 0.9*w,
    // 128),makeCircleZ(0.5*vs, 0.5*vs, 0.5*w, 0.9*w, 128)),makeCircleZ(0.5*vs, 0.5*vs, 0.5*vs,
    // 0.9*w, 128));

    ArrayAttributeGridInt indexGrid1 = new ArrayAttributeGridInt(bounds, vs, vs);
    ArrayAttributeGridInt indexGrid2 = new ArrayAttributeGridInt(bounds, vs, vs);

    int pcount = pnts.length / 3;
    double pntx[] = new double[pcount];
    double pnty[] = new double[pcount];
    double pntz[] = new double[pcount];

    ClosestPointIndexer.getPointsInGridUnits(indexGrid1, pnts, pntx, pnty, pntz);
    if (snapToGrid) {
      ClosestPointIndexer.snapToVoxels(pntx);
      ClosestPointIndexer.snapToVoxels(pnty);
      ClosestPointIndexer.snapToVoxels(pntz);
    }

    ClosestPointIndexer.initFirstLayer(indexGrid1, pntx, pnty, pntz, firstLayerThickness);
    ClosestPointIndexer.initFirstLayer(indexGrid2, pntx, pnty, pntz, firstLayerThickness);

    for (int z = 0; z < indexGrid1.getDepth(); z++) {
      renderDiff(
          indexGrid1,
          z,
          pntx,
          pnty,
          pntz,
          voxelSquareSize,
          fmt("/tmp/dist/dist00_%02d.png", z),
          true);
    }

    int usedCount = ClosestPointIndexer.removeUnusedPoints(indexGrid1, pntx, pnty, pntz);
    printf(
        "grid: [%d x %d x %d] threads: %d points: %d usedPoints: %d \n",
        indexGrid1.getWidth(),
        indexGrid1.getHeight(),
        indexGrid1.getDepth(),
        threadCount,
        pcount,
        usedCount);

    // distribute distances to the whole grid
    long t0 = time();
    ClosestPointIndexer.PI3_sorted(pntx, pnty, pntz, indexGrid1);
    printf("ClosestPointIndexer done: %d\n", (time() - t0));
    t0 = time();
    ClosestPointIndexerMT.PI3_MT(pntx, pnty, pntz, indexGrid2, threadCount);
    printf("ClosestPointIndexerMT done: %d\n ", (time() - t0));
    long diff = GridUtil.compareGrids(indexGrid1, indexGrid2);
    printf("index difference count: %d\n", diff);

    printf("maxDiff1: %6.4f\n", getMaxDiff(indexGrid1, pntx, pnty, pntz));
    printf("maxDiff2: %6.4f\n", getMaxDiff(indexGrid1, pntx, pnty, pntz));

    if (writeViz) {
      for (int z = 0; z < indexGrid1.getDepth(); z++) {
        // renderDiff(indexGrid1, z, pntx, pnty, pntz, voxelSquareSize,
        // fmt("/tmp/dist/dist01_%02d.png",z), true);
        renderDiff(
            indexGrid2,
            z,
            pntx,
            pnty,
            pntz,
            voxelSquareSize,
            fmt("/tmp/dist/distDiff2_%02d.png", z),
            true);
      }
    }

    if (compareDistances) {
      AttributeGrid distGrid1 = makeDistanceGrid(bounds, -w, w, distanceBitCount, vs);
      AttributeGrid distGrid2 = makeDistanceGrid(bounds, -w, w, distanceBitCount, vs);
      ClosestPointIndexer.getPointsInWorldUnits(indexGrid1, pntx, pnty, pntz);

      ClosestPointIndexer.makeDistanceGrid(indexGrid1, pntx, pnty, pntz, null, -w, w, distGrid1);
      ClosestPointIndexer.makeDistanceGrid(indexGrid2, pntx, pnty, pntz, null, -w, w, distGrid2);
      long diffDist = GridUtil.compareGrids(distGrid1, distGrid2);
      printf("distance difference count: %d\n", diffDist);
    }
  }