PrimalQuery2.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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.10.17
  7. #pragma once
  8. #include <Mathematics/Vector2.h>
  9. // Queries about the relation of a point to various geometric objects. The
  10. // choices for N when using UIntegerFP32<N> for either BSNumber of BSRational
  11. // are determined in GeometricTools/GTEngine/Tools/PrecisionCalculator. These
  12. // N-values are worst case scenarios. Your specific input data might require
  13. // much smaller N, in which case you can modify PrecisionCalculator to use the
  14. // BSPrecision(int32_t,int32_t,int32_t,bool) constructors.
  15. namespace WwiseGTE
  16. {
  17. template <typename Real>
  18. class PrimalQuery2
  19. {
  20. public:
  21. // The caller is responsible for ensuring that the array is not empty
  22. // before calling queries and that the indices passed to the queries
  23. // are valid. The class does no range checking.
  24. PrimalQuery2()
  25. :
  26. mNumVertices(0),
  27. mVertices(nullptr)
  28. {
  29. }
  30. PrimalQuery2(int numVertices, Vector2<Real> const* vertices)
  31. :
  32. mNumVertices(numVertices),
  33. mVertices(vertices)
  34. {
  35. }
  36. // Member access.
  37. inline void Set(int numVertices, Vector2<Real> const* vertices)
  38. {
  39. mNumVertices = numVertices;
  40. mVertices = vertices;
  41. }
  42. inline int GetNumVertices() const
  43. {
  44. return mNumVertices;
  45. }
  46. inline Vector2<Real> const* GetVertices() const
  47. {
  48. return mVertices;
  49. }
  50. // In the following, point P refers to vertices[i] or 'test' and Vi
  51. // refers to vertices[vi].
  52. // For a line with origin V0 and direction <V0,V1>, ToLine returns
  53. // +1, P on right of line
  54. // -1, P on left of line
  55. // 0, P on the line
  56. //
  57. // Choice of N for UIntegerFP32<N>.
  58. // input type | compute type | N
  59. // -----------+--------------+----
  60. // float | BSNumber | 18
  61. // double | BSNumber | 132
  62. // float | BSRational | 35
  63. // double | BSRational | 263
  64. int ToLine(int i, int v0, int v1) const
  65. {
  66. return ToLine(mVertices[i], v0, v1);
  67. }
  68. int ToLine(Vector2<Real> const& test, int v0, int v1) const
  69. {
  70. Vector2<Real> const& vec0 = mVertices[v0];
  71. Vector2<Real> const& vec1 = mVertices[v1];
  72. Real x0 = test[0] - vec0[0];
  73. Real y0 = test[1] - vec0[1];
  74. Real x1 = vec1[0] - vec0[0];
  75. Real y1 = vec1[1] - vec0[1];
  76. Real x0y1 = x0 * y1;
  77. Real x1y0 = x1 * y0;
  78. Real det = x0y1 - x1y0;
  79. Real const zero(0);
  80. return (det > zero ? +1 : (det < zero ? -1 : 0));
  81. }
  82. // For a line with origin V0 and direction <V0,V1>, ToLine returns
  83. // +1, P on right of line
  84. // -1, P on left of line
  85. // 0, P on the line
  86. // The 'order' parameter is
  87. // -3, points not collinear, P on left of line
  88. // -2, P strictly left of V0 on the line
  89. // -1, P = V0
  90. // 0, P interior to line segment [V0,V1]
  91. // +1, P = V1
  92. // +2, P strictly right of V0 on the line
  93. //
  94. // Choice of N for UIntegerFP32<N>.
  95. // input type | compute type | N
  96. // -----------+--------------+----
  97. // float | BSNumber | 18
  98. // double | BSNumber | 132
  99. // float | BSRational | 35
  100. // double | BSRational | 263
  101. // This is the same as the first-listed ToLine calls because the
  102. // worst-case path has the same computational complexity.
  103. int ToLine(int i, int v0, int v1, int& order) const
  104. {
  105. return ToLine(mVertices[i], v0, v1, order);
  106. }
  107. int ToLine(Vector2<Real> const& test, int v0, int v1, int& order) const
  108. {
  109. Vector2<Real> const& vec0 = mVertices[v0];
  110. Vector2<Real> const& vec1 = mVertices[v1];
  111. Real x0 = test[0] - vec0[0];
  112. Real y0 = test[1] - vec0[1];
  113. Real x1 = vec1[0] - vec0[0];
  114. Real y1 = vec1[1] - vec0[1];
  115. Real x0y1 = x0 * y1;
  116. Real x1y0 = x1 * y0;
  117. Real det = x0y1 - x1y0;
  118. Real const zero(0);
  119. if (det > zero)
  120. {
  121. order = +3;
  122. return +1;
  123. }
  124. if (det < zero)
  125. {
  126. order = -3;
  127. return -1;
  128. }
  129. Real x0x1 = x0 * x1;
  130. Real y0y1 = y0 * y1;
  131. Real dot = x0x1 + y0y1;
  132. if (dot == zero)
  133. {
  134. order = -1;
  135. }
  136. else if (dot < zero)
  137. {
  138. order = -2;
  139. }
  140. else
  141. {
  142. Real x0x0 = x0 * x0;
  143. Real y0y0 = y0 * y0;
  144. Real sqrLength = x0x0 + y0y0;
  145. if (dot == sqrLength)
  146. {
  147. order = +1;
  148. }
  149. else if (dot > sqrLength)
  150. {
  151. order = +2;
  152. }
  153. else
  154. {
  155. order = 0;
  156. }
  157. }
  158. return 0;
  159. }
  160. // For a triangle with counterclockwise vertices V0, V1, and V2,
  161. // ToTriangle returns
  162. // +1, P outside triangle
  163. // -1, P inside triangle
  164. // 0, P on triangle
  165. //
  166. // Choice of N for UIntegerFP32<N>.
  167. // input type | compute type | N
  168. // -----------+--------------+-----
  169. // float | BSNumber | 18
  170. // double | BSNumber | 132
  171. // float | BSRational | 35
  172. // double | BSRational | 263
  173. // The query involves three calls to ToLine, so the numbers match
  174. // those of ToLine.
  175. int ToTriangle(int i, int v0, int v1, int v2) const
  176. {
  177. return ToTriangle(mVertices[i], v0, v1, v2);
  178. }
  179. int ToTriangle(Vector2<Real> const& test, int v0, int v1, int v2) const
  180. {
  181. int sign0 = ToLine(test, v1, v2);
  182. if (sign0 > 0)
  183. {
  184. return +1;
  185. }
  186. int sign1 = ToLine(test, v0, v2);
  187. if (sign1 < 0)
  188. {
  189. return +1;
  190. }
  191. int sign2 = ToLine(test, v0, v1);
  192. if (sign2 > 0)
  193. {
  194. return +1;
  195. }
  196. return ((sign0 && sign1 && sign2) ? -1 : 0);
  197. }
  198. // For a triangle with counterclockwise vertices V0, V1, and V2,
  199. // ToCircumcircle returns
  200. // +1, P outside circumcircle of triangle
  201. // -1, P inside circumcircle of triangle
  202. // 0, P on circumcircle of triangle
  203. //
  204. // Choice of N for UIntegerFP32<N>.
  205. // input type | compute type | N
  206. // -----------+--------------+----
  207. // float | BSNumber | 35
  208. // double | BSNumber | 263
  209. // float | BSRational | 105
  210. // double | BSRational | 788
  211. // The query involves three calls of ToLine, so the numbers match
  212. // those of ToLine.
  213. int ToCircumcircle(int i, int v0, int v1, int v2) const
  214. {
  215. return ToCircumcircle(mVertices[i], v0, v1, v2);
  216. }
  217. int ToCircumcircle(Vector2<Real> const& test, int v0, int v1, int v2) const
  218. {
  219. Vector2<Real> const& vec0 = mVertices[v0];
  220. Vector2<Real> const& vec1 = mVertices[v1];
  221. Vector2<Real> const& vec2 = mVertices[v2];
  222. Real x0 = vec0[0] - test[0];
  223. Real y0 = vec0[1] - test[1];
  224. Real s00 = vec0[0] + test[0];
  225. Real s01 = vec0[1] + test[1];
  226. Real t00 = s00 * x0;
  227. Real t01 = s01 * y0;
  228. Real z0 = t00 + t01;
  229. Real x1 = vec1[0] - test[0];
  230. Real y1 = vec1[1] - test[1];
  231. Real s10 = vec1[0] + test[0];
  232. Real s11 = vec1[1] + test[1];
  233. Real t10 = s10 * x1;
  234. Real t11 = s11 * y1;
  235. Real z1 = t10 + t11;
  236. Real x2 = vec2[0] - test[0];
  237. Real y2 = vec2[1] - test[1];
  238. Real s20 = vec2[0] + test[0];
  239. Real s21 = vec2[1] + test[1];
  240. Real t20 = s20 * x2;
  241. Real t21 = s21 * y2;
  242. Real z2 = t20 + t21;
  243. Real y0z1 = y0 * z1;
  244. Real y0z2 = y0 * z2;
  245. Real y1z0 = y1 * z0;
  246. Real y1z2 = y1 * z2;
  247. Real y2z0 = y2 * z0;
  248. Real y2z1 = y2 * z1;
  249. Real c0 = y1z2 - y2z1;
  250. Real c1 = y2z0 - y0z2;
  251. Real c2 = y0z1 - y1z0;
  252. Real x0c0 = x0 * c0;
  253. Real x1c1 = x1 * c1;
  254. Real x2c2 = x2 * c2;
  255. Real term = x0c0 + x1c1;
  256. Real det = term + x2c2;
  257. Real const zero(0);
  258. return (det < zero ? 1 : (det > zero ? -1 : 0));
  259. }
  260. // An extended classification of the relationship of a point to a line
  261. // segment. For noncollinear points, the return value is
  262. // ORDER_POSITIVE when <P,Q0,Q1> is a counterclockwise triangle
  263. // ORDER_NEGATIVE when <P,Q0,Q1> is a clockwise triangle
  264. // For collinear points, the line direction is Q1-Q0. The return
  265. // value is
  266. // ORDER_COLLINEAR_LEFT when the line ordering is <P,Q0,Q1>
  267. // ORDER_COLLINEAR_RIGHT when the line ordering is <Q0,Q1,P>
  268. // ORDER_COLLINEAR_CONTAIN when the line ordering is <Q0,P,Q1>
  269. enum OrderType
  270. {
  271. ORDER_Q0_EQUALS_Q1,
  272. ORDER_P_EQUALS_Q0,
  273. ORDER_P_EQUALS_Q1,
  274. ORDER_POSITIVE,
  275. ORDER_NEGATIVE,
  276. ORDER_COLLINEAR_LEFT,
  277. ORDER_COLLINEAR_RIGHT,
  278. ORDER_COLLINEAR_CONTAIN
  279. };
  280. // Choice of N for UIntegerFP32<N>.
  281. // input type | compute type | N
  282. // -----------+--------------+----
  283. // float | BSNumber | 18
  284. // double | BSNumber | 132
  285. // float | BSRational | 35
  286. // double | BSRational | 263
  287. // This is the same as the first-listed ToLine calls because the
  288. // worst-case path has the same computational complexity.
  289. OrderType ToLineExtended(Vector2<Real> const& P, Vector2<Real> const& Q0, Vector2<Real> const& Q1) const
  290. {
  291. Real const zero(0);
  292. Real x0 = Q1[0] - Q0[0];
  293. Real y0 = Q1[1] - Q0[1];
  294. if (x0 == zero && y0 == zero)
  295. {
  296. return ORDER_Q0_EQUALS_Q1;
  297. }
  298. Real x1 = P[0] - Q0[0];
  299. Real y1 = P[1] - Q0[1];
  300. if (x1 == zero && y1 == zero)
  301. {
  302. return ORDER_P_EQUALS_Q0;
  303. }
  304. Real x2 = P[0] - Q1[0];
  305. Real y2 = P[1] - Q1[1];
  306. if (x2 == zero && y2 == zero)
  307. {
  308. return ORDER_P_EQUALS_Q1;
  309. }
  310. // The theoretical classification relies on computing exactly the
  311. // sign of the determinant. Numerical roundoff errors can cause
  312. // misclassification.
  313. Real x0y1 = x0 * y1;
  314. Real x1y0 = x1 * y0;
  315. Real det = x0y1 - x1y0;
  316. if (det != zero)
  317. {
  318. if (det > zero)
  319. {
  320. // The points form a counterclockwise triangle <P,Q0,Q1>.
  321. return ORDER_POSITIVE;
  322. }
  323. else
  324. {
  325. // The points form a clockwise triangle <P,Q1,Q0>.
  326. return ORDER_NEGATIVE;
  327. }
  328. }
  329. else
  330. {
  331. // The points are collinear; P is on the line through
  332. // Q0 and Q1.
  333. Real x0x1 = x0 * x1;
  334. Real y0y1 = y0 * y1;
  335. Real dot = x0x1 + y0y1;
  336. if (dot < zero)
  337. {
  338. // The line ordering is <P,Q0,Q1>.
  339. return ORDER_COLLINEAR_LEFT;
  340. }
  341. Real x0x0 = x0 * x0;
  342. Real y0y0 = y0 * y0;
  343. Real sqrLength = x0x0 + y0y0;
  344. if (dot > sqrLength)
  345. {
  346. // The line ordering is <Q0,Q1,P>.
  347. return ORDER_COLLINEAR_RIGHT;
  348. }
  349. // The line ordering is <Q0,P,Q1> with P strictly between
  350. // Q0 and Q1.
  351. return ORDER_COLLINEAR_CONTAIN;
  352. }
  353. }
  354. private:
  355. int mNumVertices;
  356. Vector2<Real> const* mVertices;
  357. };
  358. }