ContCylinder3.h 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/ApprOrthogonalLine3.h>
  9. #include <Mathematics/Cylinder3.h>
  10. #include <Mathematics/DistPointLine.h>
  11. namespace WwiseGTE
  12. {
  13. // Compute the cylinder axis segment using least-squares fit. The radius
  14. // is the maximum distance from points to the axis. The height is
  15. // determined by projection of points onto the axis and determining the
  16. // containing interval.
  17. template <typename Real>
  18. bool GetContainer(int numPoints, Vector3<Real> const* points, Cylinder3<Real>& cylinder)
  19. {
  20. ApprOrthogonalLine3<Real> fitter;
  21. fitter.Fit(numPoints, points);
  22. Line3<Real> line = fitter.GetParameters();
  23. DCPQuery<Real, Vector3<Real>, Line3<Real>> plQuery;
  24. Real maxRadiusSqr = (Real)0;
  25. for (int i = 0; i < numPoints; ++i)
  26. {
  27. auto result = plQuery(points[i], line);
  28. if (result.sqrDistance > maxRadiusSqr)
  29. {
  30. maxRadiusSqr = result.sqrDistance;
  31. }
  32. }
  33. Vector3<Real> diff = points[0] - line.origin;
  34. Real wMin = Dot(line.direction, diff);
  35. Real wMax = wMin;
  36. for (int i = 1; i < numPoints; ++i)
  37. {
  38. diff = points[i] - line.origin;
  39. Real w = Dot(line.direction, diff);
  40. if (w < wMin)
  41. {
  42. wMin = w;
  43. }
  44. else if (w > wMax)
  45. {
  46. wMax = w;
  47. }
  48. }
  49. cylinder.axis.origin = line.origin + ((Real)0.5 * (wMax + wMin)) * line.direction;
  50. cylinder.axis.direction = line.direction;
  51. cylinder.radius = std::sqrt(maxRadiusSqr);
  52. cylinder.height = wMax - wMin;
  53. return true;
  54. }
  55. // Test for containment of a point by a cylinder.
  56. template <typename Real>
  57. bool InContainer(Vector3<Real> const& point, Cylinder3<Real> const& cylinder)
  58. {
  59. Vector3<Real> diff = point - cylinder.axis.origin;
  60. Real zProj = Dot(diff, cylinder.axis.direction);
  61. if (std::fabs(zProj) * (Real)2 > cylinder.height)
  62. {
  63. return false;
  64. }
  65. Vector3<Real> xyProj = diff - zProj * cylinder.axis.direction;
  66. return Length(xyProj) <= cylinder.radius;
  67. }
  68. }