------------------------------------------------------------------------------ Compute the number of divisions given the current bounding box and a target number of buckets/bins. Note that degenerate bounding boxes (i.e., one or more of the edges are zero length) are handled properly.
| 470 | // target number of buckets/bins. Note that degenerate bounding boxes (i.e., |
| 471 | // one or more of the edges are zero length) are handled properly. |
| 472 | vtkIdType vtkBoundingBox::ComputeDivisions(vtkIdType totalBins, double bounds[6], int divs[3]) const |
| 473 | { |
| 474 | // This will always produce at least one bin |
| 475 | totalBins = (totalBins <= 0 ? 1 : totalBins); |
| 476 | |
| 477 | // First determine the maximum length of the side of the bounds. Keep track |
| 478 | // of zero width sides of the bounding box. |
| 479 | int numNonZero = 0, nonZero[3], maxIdx = (-1); |
| 480 | double max = 0.0, lengths[3]; |
| 481 | this->GetLengths(lengths); |
| 482 | |
| 483 | // Use a finite tolerance when detecting zero width sides to ensure that |
| 484 | // numerical noise doesn't cause an explosion later on. We'll consider any |
| 485 | // length that's less than 0.1% of the average length to be zero: |
| 486 | double totLen = lengths[0] + lengths[1] + lengths[2]; |
| 487 | const double zeroDetectionTolerance = totLen * (0.001 / 3.); |
| 488 | |
| 489 | for (int i = 0; i < 3; ++i) |
| 490 | { |
| 491 | if (lengths[i] > max) |
| 492 | { |
| 493 | maxIdx = i; |
| 494 | max = lengths[i]; |
| 495 | } |
| 496 | if (lengths[i] > zeroDetectionTolerance) |
| 497 | { |
| 498 | nonZero[i] = 1; |
| 499 | numNonZero++; |
| 500 | } |
| 501 | else |
| 502 | { |
| 503 | nonZero[i] = 0; |
| 504 | } |
| 505 | } |
| 506 | |
| 507 | // If the bounding box is degenerate, then one bin of arbitrary size |
| 508 | if (numNonZero < 1) |
| 509 | { |
| 510 | divs[0] = divs[1] = divs[2] = 1; |
| 511 | bounds[0] = this->MinPnt[0] - 0.5; |
| 512 | bounds[1] = this->MaxPnt[0] + 0.5; |
| 513 | bounds[2] = this->MinPnt[1] - 0.5; |
| 514 | bounds[3] = this->MaxPnt[1] + 0.5; |
| 515 | bounds[4] = this->MinPnt[2] - 0.5; |
| 516 | bounds[5] = this->MaxPnt[2] + 0.5; |
| 517 | return 1; |
| 518 | } |
| 519 | |
| 520 | // Okay we need to compute the divisions roughly in proportion to the |
| 521 | // bounding box edge lengths. The idea is to make the bins as close to a |
| 522 | // cube as possible. Ensure that the number of divisions is valid. |
| 523 | double f = static_cast<double>(totalBins); |
| 524 | f /= (nonZero[0] ? (lengths[0] / totLen) : 1.0); |
| 525 | f /= (nonZero[1] ? (lengths[1] / totLen) : 1.0); |
| 526 | f /= (nonZero[2] ? (lengths[2] / totLen) : 1.0); |
| 527 | f = pow(f, (1.0 / static_cast<double>(numNonZero))); |
| 528 | |
| 529 | for (int i = 0; i < 3; ++i) |
no test coverage detected