predicates.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2019 Qingnan Zhou <[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 <igl/predicates/predicates.h>
  9. #include <predicates.h>
  10. #include <type_traits>
  11. namespace igl {
  12. namespace predicates {
  13. using REAL = IGL_PREDICATES_REAL;
  14. #ifdef LIBIGL_PREDICATES_USE_FLOAT
  15. #define IGL_ASSERT_SCALAR(Vector) \
  16. static_assert( \
  17. std::is_same<typename Vector::Scalar, float>::value, \
  18. "Shewchuk's exact predicates only support float")
  19. #else
  20. #define IGL_ASSERT_SCALAR(Vector) \
  21. static_assert( \
  22. std::is_same<typename Vector::Scalar, double>::value || \
  23. std::is_same<typename Vector::Scalar, float>::value, \
  24. "Shewchuk's exact predicates only support float and double")
  25. #endif
  26. IGL_INLINE void exactinit() {
  27. // Thread-safe initialization using Meyers' singleton
  28. class MySingleton {
  29. public:
  30. static MySingleton& instance() {
  31. static MySingleton instance;
  32. return instance;
  33. }
  34. private:
  35. MySingleton() { ::exactinit(); }
  36. };
  37. MySingleton::instance();
  38. }
  39. template<typename Vector2D>
  40. IGL_INLINE Orientation orient2d(
  41. const Eigen::MatrixBase<Vector2D>& pa,
  42. const Eigen::MatrixBase<Vector2D>& pb,
  43. const Eigen::MatrixBase<Vector2D>& pc)
  44. {
  45. EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2D, 2);
  46. IGL_ASSERT_SCALAR(Vector2D);
  47. using Point = Eigen::Matrix<REAL, 2, 1>;
  48. Point a{pa[0], pa[1]};
  49. Point b{pb[0], pb[1]};
  50. Point c{pc[0], pc[1]};
  51. const auto r = ::orient2d(a.data(), b.data(), c.data());
  52. if (r > 0) return Orientation::POSITIVE;
  53. else if (r < 0) return Orientation::NEGATIVE;
  54. else return Orientation::COLLINEAR;
  55. }
  56. template<typename Vector3D>
  57. IGL_INLINE Orientation orient3d(
  58. const Eigen::MatrixBase<Vector3D>& pa,
  59. const Eigen::MatrixBase<Vector3D>& pb,
  60. const Eigen::MatrixBase<Vector3D>& pc,
  61. const Eigen::MatrixBase<Vector3D>& pd)
  62. {
  63. EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3D, 3);
  64. IGL_ASSERT_SCALAR(Vector3D);
  65. using Point = Eigen::Matrix<REAL, 3, 1>;
  66. Point a{pa[0], pa[1], pa[2]};
  67. Point b{pb[0], pb[1], pb[2]};
  68. Point c{pc[0], pc[1], pc[2]};
  69. Point d{pd[0], pd[1], pd[2]};
  70. const auto r = ::orient3d(a.data(), b.data(), c.data(), d.data());
  71. if (r > 0) return Orientation::POSITIVE;
  72. else if (r < 0) return Orientation::NEGATIVE;
  73. else return Orientation::COPLANAR;
  74. }
  75. template<typename Vector2D>
  76. IGL_INLINE Orientation incircle(
  77. const Eigen::MatrixBase<Vector2D>& pa,
  78. const Eigen::MatrixBase<Vector2D>& pb,
  79. const Eigen::MatrixBase<Vector2D>& pc,
  80. const Eigen::MatrixBase<Vector2D>& pd)
  81. {
  82. EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2D, 2);
  83. IGL_ASSERT_SCALAR(Vector2D);
  84. using Point = Eigen::Matrix<REAL, 2, 1>;
  85. Point a{pa[0], pa[1]};
  86. Point b{pb[0], pb[1]};
  87. Point c{pc[0], pc[1]};
  88. Point d{pd[0], pd[1]};
  89. const auto r = ::incircle(a.data(), b.data(), c.data(), d.data());
  90. if (r > 0) return Orientation::INSIDE;
  91. else if (r < 0) return Orientation::OUTSIDE;
  92. else return Orientation::COCIRCULAR;
  93. }
  94. template<typename Vector3D>
  95. IGL_INLINE Orientation insphere(
  96. const Eigen::MatrixBase<Vector3D>& pa,
  97. const Eigen::MatrixBase<Vector3D>& pb,
  98. const Eigen::MatrixBase<Vector3D>& pc,
  99. const Eigen::MatrixBase<Vector3D>& pd,
  100. const Eigen::MatrixBase<Vector3D>& pe)
  101. {
  102. EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3D, 3);
  103. IGL_ASSERT_SCALAR(Vector3D);
  104. using Point = Eigen::Matrix<REAL, 3, 1>;
  105. Point a{pa[0], pa[1], pa[2]};
  106. Point b{pb[0], pb[1], pb[2]};
  107. Point c{pc[0], pc[1], pc[2]};
  108. Point d{pd[0], pd[1], pd[2]};
  109. Point e{pe[0], pe[1], pe[2]};
  110. const auto r = ::insphere(a.data(), b.data(), c.data(), d.data(), e.data());
  111. if (r > 0) return Orientation::INSIDE;
  112. else if (r < 0) return Orientation::OUTSIDE;
  113. else return Orientation::COSPHERICAL;
  114. }
  115. }
  116. }
  117. #undef IGL_ASSERT_SCALAR
  118. #ifdef IGL_STATIC_LIBRARY
  119. // Explicit template instantiation
  120. #define IGL_ORIENT2D(Vector) template igl::predicates::Orientation igl::predicates::orient2d<Vector>(const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&)
  121. #define IGL_INCIRCLE(Vector) template igl::predicates::Orientation igl::predicates::incircle<Vector>(const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&)
  122. #define IGL_ORIENT3D(Vector) template igl::predicates::Orientation igl::predicates::orient3d<Vector>(const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&)
  123. #define IGL_INSPHERE(Vector) template igl::predicates::Orientation igl::predicates::insphere<Vector>(const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&, const Eigen::MatrixBase<Vector>&)
  124. #define IGL_MATRIX(T, R, C) Eigen::Matrix<T, R, C>
  125. IGL_ORIENT2D(IGL_MATRIX(float, 1, 2));
  126. IGL_INCIRCLE(IGL_MATRIX(float, 1, 2));
  127. IGL_ORIENT2D(IGL_MATRIX(float, 2, 1));
  128. IGL_INCIRCLE(IGL_MATRIX(float, 2, 1));
  129. IGL_ORIENT3D(IGL_MATRIX(float, 1, 3));
  130. IGL_INSPHERE(IGL_MATRIX(float, 1, 3));
  131. IGL_ORIENT3D(IGL_MATRIX(float, 3, 1));
  132. IGL_INSPHERE(IGL_MATRIX(float, 3, 1));
  133. #ifndef LIBIGL_PREDICATES_USE_FLOAT
  134. IGL_ORIENT2D(IGL_MATRIX(double, 1, 2));
  135. IGL_INCIRCLE(IGL_MATRIX(double, 1, 2));
  136. IGL_ORIENT2D(IGL_MATRIX(double, 2, 1));
  137. IGL_INCIRCLE(IGL_MATRIX(double, 2, 1));
  138. IGL_ORIENT3D(IGL_MATRIX(double, 1, 3));
  139. IGL_INSPHERE(IGL_MATRIX(double, 1, 3));
  140. IGL_ORIENT3D(IGL_MATRIX(double, 3, 1));
  141. IGL_INSPHERE(IGL_MATRIX(double, 3, 1));
  142. #endif
  143. #undef IGL_MATRIX
  144. #undef IGL_ORIENT2D
  145. #undef IGL_ORIENT3D
  146. #undef IGL_INCIRCLE
  147. #undef IGL_INSPHERE
  148. #endif