segment_segment_intersect.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 Francisca Gil Ureta <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "segment_segment_intersect.h"
  9. #include <Eigen/Geometry>
  10. template<typename DerivedSource, typename DerivedDir>
  11. IGL_INLINE bool igl::segment_segment_intersect(
  12. const Eigen::MatrixBase <DerivedSource> &p,
  13. const Eigen::MatrixBase <DerivedDir> &r,
  14. const Eigen::MatrixBase <DerivedSource> &q,
  15. const Eigen::MatrixBase <DerivedDir> &s,
  16. double &a_t,
  17. double &a_u,
  18. double eps
  19. )
  20. {
  21. // http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
  22. // Search intersection between two segments
  23. // p + t*r : t \in [0,1]
  24. // q + u*s : u \in [0,1]
  25. // p + t * r = q + u * s // x s
  26. // t(r x s) = (q - p) x s
  27. // t = (q - p) x s / (r x s)
  28. // (r x s) ~ 0 --> directions are parallel, they will never cross
  29. Eigen::Matrix<typename DerivedDir::Scalar, 1, 3> rxs = r.cross(s);
  30. if (rxs.norm() <= eps)
  31. return false;
  32. int sign;
  33. double u;
  34. // u = (q − p) × r / (r × s)
  35. Eigen::Matrix<typename DerivedDir::Scalar, 1, 3> u1 = (q - p).cross(r);
  36. sign = ((u1.dot(rxs)) > 0) ? 1 : -1;
  37. u = u1.norm() / rxs.norm();
  38. u = u * sign;
  39. double t;
  40. // t = (q - p) x s / (r x s)
  41. Eigen::Matrix<typename DerivedDir::Scalar, 1, 3> t1 = (q - p).cross(s);
  42. sign = ((t1.dot(rxs)) > 0) ? 1 : -1;
  43. t = t1.norm() / rxs.norm();
  44. t = t * sign;
  45. a_t = t;
  46. a_u = u;
  47. if ((u - 1.) > eps || u < -eps)
  48. return false;
  49. if ((t - 1.) > eps || t < -eps)
  50. return false;
  51. return true;
  52. };
  53. template <> bool igl::segment_segment_intersect<Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(
  54. Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const& p,
  55. Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const& r,
  56. Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const& q,
  57. Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const& s,
  58. double& t,
  59. double& u,
  60. double eps)
  61. {
  62. const Eigen::Vector3d p3(p(0),p(1),0);
  63. const Eigen::Vector3d r3(r(0),r(1),0);
  64. const Eigen::Vector3d q3(q(0),q(1),0);
  65. const Eigen::Vector3d s3(s(0),s(1),0);
  66. return segment_segment_intersect(p3,r3,q3,s3,t,u,eps);
  67. }
  68. #ifdef IGL_STATIC_LIBRARY
  69. // Explicit template instantiation
  70. template bool igl::segment_segment_intersect<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, double&, double&, double);
  71. #endif