AP_GeodesicGrid.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Copyright (C) 2016 Intel Corporation. All rights reserved.
  3. *
  4. * This file is free software: you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This file is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. * See the GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #pragma once
  18. #include "AP_Math.h"
  19. /**
  20. * AP_GeodesicGrid is a class for working on geodesic sections.
  21. *
  22. * For quick information regarding geodesic grids, see:
  23. * https://en.wikipedia.org/wiki/Geodesic_grid
  24. *
  25. * The grid is formed by a tessellation of an icosahedron by a factor of 2,
  26. * i.e., each triangular face of the icosahedron is divided into 4 by splitting
  27. * each edge into 2 line segments and projecting the vertices to the
  28. * icosahedron's circumscribed sphere. That will give a total of 80 triangular
  29. * faces, which are called sections in this context.
  30. *
  31. * A section index is given by the icosahedron's triangle it belongs to and by
  32. * its index in that triangle. Let i in [0,20) be the icosahedron's triangle
  33. * index and j in [0,4) be the sub-triangle's (which is the section) index
  34. * inside the greater triangle. Then the section index is given by
  35. * s = 4 * i + j .
  36. *
  37. * The icosahedron's triangles are defined by the tuple (T_0, T_1, ..., T_19),
  38. * where T_i is the i-th triangle. Each triangle is represented with a tuple of
  39. * the form (a, b, c), where a, b and c are the triangle vertices in the space.
  40. *
  41. * Given the definitions above and the golden ration as g, the triangles must
  42. * be defined in the following order:
  43. *
  44. * (
  45. * ((-g, 1, 0), (-1, 0,-g), (-g,-1, 0)),
  46. * ((-1, 0,-g), (-g,-1, 0), ( 0,-g,-1)),
  47. * ((-g,-1, 0), ( 0,-g,-1), ( 0,-g, 1)),
  48. * ((-1, 0,-g), ( 0,-g,-1), ( 1, 0,-g)),
  49. * (( 0,-g,-1), ( 0,-g, 1), ( g,-1, 0)),
  50. * (( 0,-g,-1), ( 1, 0,-g), ( g,-1, 0)),
  51. * (( g,-1, 0), ( 1, 0,-g), ( g, 1, 0)),
  52. * (( 1, 0,-g), ( g, 1, 0), ( 0, g,-1)),
  53. * (( 1, 0,-g), ( 0, g,-1), (-1, 0,-g)),
  54. * (( 0, g,-1), (-g, 1, 0), (-1, 0,-g)),
  55. * -T_0,
  56. * -T_1,
  57. * -T_2,
  58. * -T_3,
  59. * -T_4,
  60. * -T_5,
  61. * -T_6,
  62. * -T_7,
  63. * -T_8,
  64. * -T_9,
  65. * )
  66. *
  67. * Where for a given T_i = (a, b, c), -T_i = (-a, -b, -c). We call -T_i the
  68. * opposite triangle of T_i in this specification. For any i in [0,20), T_j is
  69. * the opposite of T_i iff j = (i + 10) % 20.
  70. *
  71. * Let an icosahedron triangle T be defined as T = (a, b, c). The "middle
  72. * triangle" M is defined as the triangle formed by the points that bisect the
  73. * edges of T. M is defined by:
  74. *
  75. * M = (m_a, m_b, m_c) = ((a + b) / 2, (b + c) / 2, (c + a) / 2)
  76. *
  77. * Let elements of the tuple (W_0, W_1, W_2, W_3) comprise the sub-triangles of
  78. * T, so that W_j is the j-th sub-triangle of T. The sub-triangles are defined
  79. * as the following:
  80. *
  81. * W_0 = M
  82. * W_1 = (a, m_a, m_c)
  83. * W_2 = (m_a, b, m_b)
  84. * W_3 = (m_c, m_b, c)
  85. */
  86. class AP_GeodesicGrid {
  87. friend class GeodesicGridTest;
  88. public:
  89. /*
  90. * The following concepts are used by the description of this class'
  91. * members.
  92. *
  93. * Vector crossing objects
  94. * -----------------------
  95. * We say that a vector v crosses an object in space (point, line, line
  96. * segment, plane etc) iff the line, being Q the set of points of that
  97. * object, the vector v crosses it iff there exists a positive scalar alpha
  98. * such that alpha * v is in Q.
  99. */
  100. /**
  101. * Number of sub-triangles for an icosahedron triangle.
  102. */
  103. static const int NUM_SUBTRIANGLES = 4;
  104. /**
  105. * Find which section is crossed by \p v.
  106. *
  107. * @param v[in] The vector to be verified.
  108. *
  109. * @param inclusive[in] If true, then if \p v crosses one of the edges of
  110. * one of the sections, then that section is returned. If \p inclusive is
  111. * false, then \p v is considered to cross no section. Note that, if \p
  112. * inclusive is true, then \p v can belong to more than one section and
  113. * only the first one found is returned. The order in which the triangles
  114. * are checked is unspecified. The default value for \p inclusive is
  115. * false.
  116. *
  117. * @return The index of the section. The value -1 is returned if \p v is
  118. * the null vector or the section isn't found, which might happen when \p
  119. * inclusive is false.
  120. */
  121. static int section(const Vector3f &v, bool inclusive = false);
  122. private:
  123. /*
  124. * The following are concepts used in the description of the private
  125. * members.
  126. *
  127. * Neighbor triangle with respect to an edge
  128. * -----------------------------------------
  129. * Let T be a triangle. The triangle W is a neighbor of T with respect to
  130. * edge e if T and W share that edge. If e is formed by vectors a and b,
  131. * then W can be said to be a neighbor of T with respect to a and b.
  132. *
  133. * Umbrella of a vector
  134. * --------------------
  135. * Let v be one vertex of the icosahedron. The umbrella of v is the set of
  136. * icosahedron triangles that share that vertex. The vector v is called the
  137. * umbrella's pivot.
  138. *
  139. * Let T have vertices v, a and b. Then, with respect to (a, b):
  140. * - The vector a is the umbrella's 0-th vertex.
  141. * - The vector b is the 1-th vertex.
  142. * - The triangle formed by the v, the i-th and ((i + 1) % 5)-th vertex is
  143. * the umbrella's i-th component.
  144. * - For i in [2,5), the i-th vertex is the vertex that, with the
  145. * (i - 1)-th and v, forms the neighbor of the (i - 2)-th component with
  146. * respect to v and the (i - 1)-th vertex.
  147. *
  148. * Still with respect to (a, b), the umbrella's i-th component is the
  149. * triangle formed by the i-th and ((i + 1) % 5)-th vertices and the pivot.
  150. *
  151. * Neighbor umbrella with respect to an icosahedron triangle's edge
  152. * ----------------------------------------------------------------
  153. * Let T be an icosahedron triangle. Let W be the T's neighbor triangle wrt
  154. * the edge e. Let w be the W's vertex that is opposite to e. Then the
  155. * neighbor umbrella of T with respect to e is the umbrella of w.
  156. */
  157. /**
  158. * The inverses of the change-of-basis matrices for the icosahedron
  159. * triangles.
  160. *
  161. * The i-th matrix is the inverse of the change-of-basis matrix from
  162. * natural basis to the basis formed by T_i's vectors.
  163. */
  164. static const Matrix3f _inverses[10];
  165. /**
  166. * The inverses of the change-of-basis matrices for the middle triangles.
  167. *
  168. * The i-th matrix is the inverse of the change-of-basis matrix from
  169. * natural basis to the basis formed by T_i's middle triangle's vectors.
  170. */
  171. static const Matrix3f _mid_inverses[10];
  172. /**
  173. * The representation of the neighbor umbrellas of T_0.
  174. *
  175. * The values for the neighbors of T_10 can be derived from the values for
  176. * T_0. How to find the correct values is explained on each member.
  177. *
  178. * Let T_0 = (a, b, c). Thus, 6 indexes can be used for this data
  179. * structure, so that:
  180. * - index 0 represents the neighbor of T_0 with respect to (a, b).
  181. * - index 1 represents the neighbor of T_0 with respect to (b, c).
  182. * - index 2 represents the neighbor of T_0 with respect to (c, a).
  183. * - index 3 represents the neighbor of T_10 with respect to (-a, -b).
  184. * - index 4 represents the neighbor of T_10 with respect to (-b, -c).
  185. * - index 5 represents the neighbor of T_10 with respect to (-c, -a).
  186. *
  187. * Those indexes are mapped to this array with index % 3.
  188. *
  189. * The edges are represented with pairs because the order of the vertices
  190. * matters to the order the triangles' indexes are defined - the order of
  191. * the umbrellas' vertices and components is convertioned to be with
  192. * respect to those pairs.
  193. */
  194. static const struct neighbor_umbrella {
  195. /**
  196. * The umbrella's components. The value of #components[i] is the
  197. * icosahedron triangle index of the i-th component.
  198. *
  199. * In order to find the components for T_10, the following just finding
  200. * the index of the opposite triangle is enough. In other words,
  201. * (#components[i] + 10) % 20.
  202. */
  203. uint8_t components[5];
  204. /**
  205. * The fields with name in the format vi_cj are interpreted as the
  206. * following: vi_cj is the index of the vector, in the icosahedron
  207. * triangle pointed by #components[j], that matches the umbrella's i-th
  208. * vertex.
  209. *
  210. * The values don't change for T_10.
  211. */
  212. uint8_t v0_c0;
  213. uint8_t v1_c1;
  214. uint8_t v2_c1;
  215. uint8_t v4_c4;
  216. uint8_t v0_c4;
  217. } _neighbor_umbrellas[3];
  218. /**
  219. * Get the component_index-th component of the umbrella_index-th neighbor
  220. * umbrella.
  221. *
  222. * @param umbrella_index[in] The neighbor umbrella's index.
  223. *
  224. * @param component_index[in] The component's index.
  225. *
  226. * @return The icosahedron triangle's index of the component.
  227. */
  228. static int _neighbor_umbrella_component(int umbrella_index, int component_idx);
  229. /**
  230. * Find the icosahedron triangle index of the component of
  231. * #_neighbor_umbrellas[umbrella_index] that is crossed by \p v.
  232. *
  233. * @param umbrella_index[in] The umbrella index. Must be in [0,6).
  234. *
  235. * @param v[in] The vector to be tested.
  236. *
  237. * @param u[in] The vector \p u must be \p v expressed with respect to the
  238. * base formed by the umbrella's 0-th, 1-th and 3-th vertices, in that
  239. * order.
  240. *
  241. * @param inclusive[in] This parameter follows the same rules defined in
  242. * #section() const.
  243. *
  244. * @return The index of the icosahedron triangle. The value -1 is returned
  245. * if \p v is the null vector or the triangle isn't found, which might
  246. * happen when \p inclusive is false.
  247. */
  248. static int _from_neighbor_umbrella(int umbrella_index,
  249. const Vector3f &v,
  250. const Vector3f &u,
  251. bool inclusive);
  252. /**
  253. * Find which icosahedron's triangle is crossed by \p v.
  254. *
  255. * @param v[in] The vector to be verified.
  256. *
  257. * @param inclusive[in] This parameter follow the same rules defined in
  258. * #section() const.
  259. *
  260. * @return The index of the triangle. The value -1 is returned if the
  261. * triangle isn't found, which might happen when \p inclusive is false.
  262. */
  263. static int _triangle_index(const Vector3f &v, bool inclusive);
  264. /**
  265. * Find which sub-triangle of the icosahedron's triangle pointed by \p
  266. * triangle_index is crossed by \p v.
  267. *
  268. * The vector \p v must belong to the super-section formed by the triangle
  269. * pointed by \p triangle_index, otherwise the result is undefined.
  270. *
  271. * @param triangle_index[in] The icosahedron's triangle index, it must be in
  272. * the interval [0,20). Passing invalid values is undefined behavior.
  273. *
  274. * @param v[in] The vector to be verified.
  275. *
  276. * @param inclusive[in] This parameter follow the same rules defined in
  277. * #section() const.
  278. *
  279. * @return The index of the sub-triangle. The value -1 is returned if the
  280. * triangle isn't found, which might happen when \p inclusive is false.
  281. */
  282. static int _subtriangle_index(const unsigned int triangle_index,
  283. const Vector3f &v,
  284. bool inclusive);
  285. };