------------------------------------------------------------------------------
| 2560 | |
| 2561 | //------------------------------------------------------------------------------ |
| 2562 | void vtkCubeAxesActor::ComputeStickyAxesBoundingSphere(vtkViewport* viewport, |
| 2563 | const double originalBounds[6], double sphereCenter[3], double& sphereRadius) |
| 2564 | { |
| 2565 | double aspect[2]; |
| 2566 | viewport->GetAspect(aspect); |
| 2567 | vtkPlanes* frustumPlanes = vtkPlanes::New(); |
| 2568 | double frustumPlanesArray[24]; |
| 2569 | this->GetCamera()->GetFrustumPlanes(aspect[0], frustumPlanesArray); |
| 2570 | frustumPlanes->SetFrustumPlanes(frustumPlanesArray); |
| 2571 | |
| 2572 | vtkFrustumSource* frustumSource = vtkFrustumSource::New(); |
| 2573 | frustumSource->SetPlanes(frustumPlanes); |
| 2574 | frustumPlanes->Delete(); |
| 2575 | frustumSource->Update(); |
| 2576 | |
| 2577 | vtkPoints* points = frustumSource->GetOutput()->GetPoints(); |
| 2578 | |
| 2579 | // From http://gamedev.stackexchange.com/questions/60104/largest-sphere-inside-a-frustum |
| 2580 | // Point indices are set up to match the second figure. |
| 2581 | double p0[3], p1[3], p2[3], p3[3], p4[3]; |
| 2582 | double q0[3], q1[3], q2[3], q3[3], q4[3]; |
| 2583 | points->GetPoint(0, p1); // left bottom near |
| 2584 | points->GetPoint(1, p2); // right bottom near |
| 2585 | points->GetPoint(2, p4); // right top near |
| 2586 | points->GetPoint(3, p3); // left top near |
| 2587 | |
| 2588 | points->GetPoint(4, q1); // left bottom far |
| 2589 | points->GetPoint(5, q2); // right bottom far |
| 2590 | points->GetPoint(6, q4); // right top far |
| 2591 | points->GetPoint(7, q3); // left top far |
| 2592 | |
| 2593 | for (int i = 0; i < 3; ++i) |
| 2594 | { |
| 2595 | p0[i] = 0.25 * (p1[i] + p2[i] + p3[i] + p4[i]); // near center |
| 2596 | q0[i] = 0.25 * (q1[i] + q2[i] + q3[i] + q4[i]); // far center |
| 2597 | } |
| 2598 | frustumSource->Delete(); |
| 2599 | |
| 2600 | double view[3]; |
| 2601 | vtkMath::Subtract(p0, q0, view); |
| 2602 | double d = vtkMath::Norm(view); |
| 2603 | |
| 2604 | double v0[3], v1[3]; |
| 2605 | vtkMath::Subtract(p1, q1, v0); |
| 2606 | vtkMath::Subtract(q2, q1, v1); |
| 2607 | double l = 0.5 * vtkMath::Norm(v1); |
| 2608 | double alpha = atan(vtkMath::Dot(v0, v1) / (d * vtkMath::Norm(v1))); |
| 2609 | double halfWidth = l * tan((vtkMath::Pi() - 2.0 * alpha) / 4.0); |
| 2610 | |
| 2611 | vtkMath::Subtract(q3, q1, v1); |
| 2612 | l = 0.5 * vtkMath::Norm(v1); |
| 2613 | alpha = atan(vtkMath::Dot(v0, v1) / (d * vtkMath::Norm(v1))); |
| 2614 | double halfHeight = l * tan((vtkMath::Pi() - 2.0 * alpha) / 4.0); |
| 2615 | |
| 2616 | sphereRadius = std::min(halfWidth, halfHeight); |
| 2617 | |
| 2618 | vtkMath::Normalize(view); |
| 2619 | sphereCenter[0] = q0[0] + sphereRadius * view[0]; |
no test coverage detected