geodesicMesh.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. import { Vector3, TmpVectors } from "../Maths/math.vector.js";
  2. import { Scalar } from "../Maths/math.scalar.js";
  3. import { PHI } from "../Maths/math.constants.js";
  4. import { _IsoVector } from "../Maths/math.isovector.js";
  5. /**
  6. * Class representing data for one face OAB of an equilateral icosahedron
  7. * When O is the isovector (0, 0), A is isovector (m, n)
  8. * @internal
  9. */
  10. // eslint-disable-next-line @typescript-eslint/naming-convention
  11. export class _PrimaryIsoTriangle {
  12. constructor() {
  13. this.cartesian = [];
  14. this.vertices = [];
  15. this.max = [];
  16. this.min = [];
  17. this.closestTo = [];
  18. this.innerFacets = [];
  19. this.isoVecsABOB = [];
  20. this.isoVecsOBOA = [];
  21. this.isoVecsBAOA = [];
  22. this.vertexTypes = [];
  23. // eslint-disable-next-line @typescript-eslint/naming-convention
  24. this.IDATA = new PolyhedronData("icosahedron", "Regular", [
  25. [0, PHI, -1],
  26. [-PHI, 1, 0],
  27. [-1, 0, -PHI],
  28. [1, 0, -PHI],
  29. [PHI, 1, 0],
  30. [0, PHI, 1],
  31. [-1, 0, PHI],
  32. [-PHI, -1, 0],
  33. [0, -PHI, -1],
  34. [PHI, -1, 0],
  35. [1, 0, PHI],
  36. [0, -PHI, 1],
  37. ], [
  38. [0, 2, 1],
  39. [0, 3, 2],
  40. [0, 4, 3],
  41. [0, 5, 4],
  42. [0, 1, 5],
  43. [7, 6, 1],
  44. [8, 7, 2],
  45. [9, 8, 3],
  46. [10, 9, 4],
  47. [6, 10, 5],
  48. [2, 7, 1],
  49. [3, 8, 2],
  50. [4, 9, 3],
  51. [5, 10, 4],
  52. [1, 6, 5],
  53. [11, 6, 7],
  54. [11, 7, 8],
  55. [11, 8, 9],
  56. [11, 9, 10],
  57. [11, 10, 6],
  58. ]);
  59. }
  60. /**
  61. * Creates the PrimaryIsoTriangle Triangle OAB
  62. * @param m an integer
  63. * @param n an integer
  64. */
  65. //operators
  66. setIndices() {
  67. let indexCount = 12; // 12 vertices already assigned
  68. const vecToidx = {}; //maps iso-vectors to indexCount;
  69. const m = this.m;
  70. const n = this.n;
  71. let g = m; // hcf of m, n when n != 0
  72. let m1 = 1;
  73. let n1 = 0;
  74. if (n !== 0) {
  75. g = Scalar.HCF(m, n);
  76. }
  77. m1 = m / g;
  78. n1 = n / g;
  79. let fr; //face to the right of current face
  80. let rot; //rotation about which vertex for fr
  81. let O;
  82. let A;
  83. let B;
  84. const oVec = _IsoVector.Zero();
  85. const aVec = new _IsoVector(m, n);
  86. const bVec = new _IsoVector(-n, m + n);
  87. const oaVec = _IsoVector.Zero();
  88. const abVec = _IsoVector.Zero();
  89. const obVec = _IsoVector.Zero();
  90. let verts = [];
  91. let idx;
  92. let idxR;
  93. let isoId;
  94. let isoIdR;
  95. const closestTo = [];
  96. const vDist = this.vertByDist;
  97. const matchIdx = (f, fr, isoId, isoIdR) => {
  98. idx = f + "|" + isoId;
  99. idxR = fr + "|" + isoIdR;
  100. if (!(idx in vecToidx || idxR in vecToidx)) {
  101. vecToidx[idx] = indexCount;
  102. vecToidx[idxR] = indexCount;
  103. indexCount++;
  104. }
  105. else if (idx in vecToidx && !(idxR in vecToidx)) {
  106. vecToidx[idxR] = vecToidx[idx];
  107. }
  108. else if (idxR in vecToidx && !(idx in vecToidx)) {
  109. vecToidx[idx] = vecToidx[idxR];
  110. }
  111. if (vDist[isoId][0] > 2) {
  112. closestTo[vecToidx[idx]] = [-vDist[isoId][0], vDist[isoId][1], vecToidx[idx]];
  113. }
  114. else {
  115. closestTo[vecToidx[idx]] = [verts[vDist[isoId][0]], vDist[isoId][1], vecToidx[idx]];
  116. }
  117. };
  118. this.IDATA.edgematch = [
  119. [1, "B"],
  120. [2, "B"],
  121. [3, "B"],
  122. [4, "B"],
  123. [0, "B"],
  124. [10, "O", 14, "A"],
  125. [11, "O", 10, "A"],
  126. [12, "O", 11, "A"],
  127. [13, "O", 12, "A"],
  128. [14, "O", 13, "A"],
  129. [0, "O"],
  130. [1, "O"],
  131. [2, "O"],
  132. [3, "O"],
  133. [4, "O"],
  134. [19, "B", 5, "A"],
  135. [15, "B", 6, "A"],
  136. [16, "B", 7, "A"],
  137. [17, "B", 8, "A"],
  138. [18, "B", 9, "A"],
  139. ];
  140. /***edges AB to OB***** rotation about B*/
  141. for (let f = 0; f < 20; f++) {
  142. //f current face
  143. verts = this.IDATA.face[f];
  144. O = verts[2];
  145. A = verts[1];
  146. B = verts[0];
  147. isoId = oVec.x + "|" + oVec.y;
  148. idx = f + "|" + isoId;
  149. if (!(idx in vecToidx)) {
  150. vecToidx[idx] = O;
  151. closestTo[O] = [verts[vDist[isoId][0]], vDist[isoId][1]];
  152. }
  153. isoId = aVec.x + "|" + aVec.y;
  154. idx = f + "|" + isoId;
  155. if (!(idx in vecToidx)) {
  156. vecToidx[idx] = A;
  157. closestTo[A] = [verts[vDist[isoId][0]], vDist[isoId][1]];
  158. }
  159. isoId = bVec.x + "|" + bVec.y;
  160. idx = f + "|" + isoId;
  161. if (!(idx in vecToidx)) {
  162. vecToidx[idx] = B;
  163. closestTo[B] = [verts[vDist[isoId][0]], vDist[isoId][1]];
  164. }
  165. //for edge vertices
  166. fr = this.IDATA.edgematch[f][0];
  167. rot = this.IDATA.edgematch[f][1];
  168. if (rot === "B") {
  169. for (let i = 1; i < g; i++) {
  170. abVec.x = m - i * (m1 + n1);
  171. abVec.y = n + i * m1;
  172. obVec.x = -i * n1;
  173. obVec.y = i * (m1 + n1);
  174. isoId = abVec.x + "|" + abVec.y;
  175. isoIdR = obVec.x + "|" + obVec.y;
  176. matchIdx(f, fr, isoId, isoIdR);
  177. }
  178. }
  179. if (rot === "O") {
  180. for (let i = 1; i < g; i++) {
  181. obVec.x = -i * n1;
  182. obVec.y = i * (m1 + n1);
  183. oaVec.x = i * m1;
  184. oaVec.y = i * n1;
  185. isoId = obVec.x + "|" + obVec.y;
  186. isoIdR = oaVec.x + "|" + oaVec.y;
  187. matchIdx(f, fr, isoId, isoIdR);
  188. }
  189. }
  190. fr = this.IDATA.edgematch[f][2];
  191. rot = this.IDATA.edgematch[f][3];
  192. if (rot && rot === "A") {
  193. for (let i = 1; i < g; i++) {
  194. oaVec.x = i * m1;
  195. oaVec.y = i * n1;
  196. abVec.x = m - (g - i) * (m1 + n1); //reversed for BA
  197. abVec.y = n + (g - i) * m1; //reversed for BA
  198. isoId = oaVec.x + "|" + oaVec.y;
  199. isoIdR = abVec.x + "|" + abVec.y;
  200. matchIdx(f, fr, isoId, isoIdR);
  201. }
  202. }
  203. for (let i = 0; i < this.vertices.length; i++) {
  204. isoId = this.vertices[i].x + "|" + this.vertices[i].y;
  205. idx = f + "|" + isoId;
  206. if (!(idx in vecToidx)) {
  207. vecToidx[idx] = indexCount++;
  208. if (vDist[isoId][0] > 2) {
  209. closestTo[vecToidx[idx]] = [-vDist[isoId][0], vDist[isoId][1], vecToidx[idx]];
  210. }
  211. else {
  212. closestTo[vecToidx[idx]] = [verts[vDist[isoId][0]], vDist[isoId][1], vecToidx[idx]];
  213. }
  214. }
  215. }
  216. }
  217. this.closestTo = closestTo;
  218. this.vecToidx = vecToidx;
  219. }
  220. calcCoeffs() {
  221. const m = this.m;
  222. const n = this.n;
  223. const thirdR3 = Math.sqrt(3) / 3;
  224. const LSQD = m * m + n * n + m * n;
  225. this.coau = (m + n) / LSQD;
  226. this.cobu = -n / LSQD;
  227. this.coav = (-thirdR3 * (m - n)) / LSQD;
  228. this.cobv = (thirdR3 * (2 * m + n)) / LSQD;
  229. }
  230. createInnerFacets() {
  231. const m = this.m;
  232. const n = this.n;
  233. for (let y = 0; y < n + m + 1; y++) {
  234. for (let x = this.min[y]; x < this.max[y] + 1; x++) {
  235. if (x < this.max[y] && x < this.max[y + 1] + 1) {
  236. this.innerFacets.push(["|" + x + "|" + y, "|" + x + "|" + (y + 1), "|" + (x + 1) + "|" + y]);
  237. }
  238. if (y > 0 && x < this.max[y - 1] && x + 1 < this.max[y] + 1) {
  239. this.innerFacets.push(["|" + x + "|" + y, "|" + (x + 1) + "|" + y, "|" + (x + 1) + "|" + (y - 1)]);
  240. }
  241. }
  242. }
  243. }
  244. edgeVecsABOB() {
  245. const m = this.m;
  246. const n = this.n;
  247. const B = new _IsoVector(-n, m + n);
  248. for (let y = 1; y < m + n; y++) {
  249. const point = new _IsoVector(this.min[y], y);
  250. const prev = new _IsoVector(this.min[y - 1], y - 1);
  251. const next = new _IsoVector(this.min[y + 1], y + 1);
  252. const pointR = point.clone();
  253. const prevR = prev.clone();
  254. const nextR = next.clone();
  255. pointR.rotate60About(B);
  256. prevR.rotate60About(B);
  257. nextR.rotate60About(B);
  258. const maxPoint = new _IsoVector(this.max[pointR.y], pointR.y);
  259. const maxPrev = new _IsoVector(this.max[pointR.y - 1], pointR.y - 1);
  260. const maxLeftPrev = new _IsoVector(this.max[pointR.y - 1] - 1, pointR.y - 1);
  261. if (pointR.x !== maxPoint.x || pointR.y !== maxPoint.y) {
  262. if (pointR.x !== maxPrev.x) {
  263. // type2
  264. //up
  265. this.vertexTypes.push([1, 0, 0]);
  266. this.isoVecsABOB.push([point, maxPrev, maxLeftPrev]);
  267. //down
  268. this.vertexTypes.push([1, 0, 0]);
  269. this.isoVecsABOB.push([point, maxLeftPrev, maxPoint]);
  270. }
  271. else if (pointR.y === nextR.y) {
  272. // type1
  273. //up
  274. this.vertexTypes.push([1, 1, 0]);
  275. this.isoVecsABOB.push([point, prev, maxPrev]);
  276. //down
  277. this.vertexTypes.push([1, 0, 1]);
  278. this.isoVecsABOB.push([point, maxPrev, next]);
  279. }
  280. else {
  281. // type 0
  282. //up
  283. this.vertexTypes.push([1, 1, 0]);
  284. this.isoVecsABOB.push([point, prev, maxPrev]);
  285. //down
  286. this.vertexTypes.push([1, 0, 0]);
  287. this.isoVecsABOB.push([point, maxPrev, maxPoint]);
  288. }
  289. }
  290. }
  291. }
  292. mapABOBtoOBOA() {
  293. const point = new _IsoVector(0, 0);
  294. for (let i = 0; i < this.isoVecsABOB.length; i++) {
  295. const temp = [];
  296. for (let j = 0; j < 3; j++) {
  297. point.x = this.isoVecsABOB[i][j].x;
  298. point.y = this.isoVecsABOB[i][j].y;
  299. if (this.vertexTypes[i][j] === 0) {
  300. point.rotateNeg120(this.m, this.n);
  301. }
  302. temp.push(point.clone());
  303. }
  304. this.isoVecsOBOA.push(temp);
  305. }
  306. }
  307. mapABOBtoBAOA() {
  308. const point = new _IsoVector(0, 0);
  309. for (let i = 0; i < this.isoVecsABOB.length; i++) {
  310. const temp = [];
  311. for (let j = 0; j < 3; j++) {
  312. point.x = this.isoVecsABOB[i][j].x;
  313. point.y = this.isoVecsABOB[i][j].y;
  314. if (this.vertexTypes[i][j] === 1) {
  315. point.rotate120(this.m, this.n);
  316. }
  317. temp.push(point.clone());
  318. }
  319. this.isoVecsBAOA.push(temp);
  320. }
  321. }
  322. // eslint-disable-next-line @typescript-eslint/naming-convention
  323. MapToFace(faceNb, geodesicData) {
  324. const F = this.IDATA.face[faceNb];
  325. const oidx = F[2];
  326. const aidx = F[1];
  327. const bidx = F[0];
  328. const O = Vector3.FromArray(this.IDATA.vertex[oidx]);
  329. const A = Vector3.FromArray(this.IDATA.vertex[aidx]);
  330. const B = Vector3.FromArray(this.IDATA.vertex[bidx]);
  331. const OA = A.subtract(O);
  332. const OB = B.subtract(O);
  333. const x = OA.scale(this.coau).add(OB.scale(this.cobu));
  334. const y = OA.scale(this.coav).add(OB.scale(this.cobv));
  335. const mapped = [];
  336. let idx;
  337. let tempVec = TmpVectors.Vector3[0];
  338. for (let i = 0; i < this.cartesian.length; i++) {
  339. tempVec = x.scale(this.cartesian[i].x).add(y.scale(this.cartesian[i].y)).add(O);
  340. mapped[i] = [tempVec.x, tempVec.y, tempVec.z];
  341. idx = faceNb + "|" + this.vertices[i].x + "|" + this.vertices[i].y;
  342. geodesicData.vertex[this.vecToidx[idx]] = [tempVec.x, tempVec.y, tempVec.z];
  343. }
  344. }
  345. //statics
  346. /**Creates a primary triangle
  347. * @internal
  348. */
  349. build(m, n) {
  350. const vertices = [];
  351. const O = _IsoVector.Zero();
  352. const A = new _IsoVector(m, n);
  353. const B = new _IsoVector(-n, m + n);
  354. vertices.push(O, A, B);
  355. //max internal isoceles triangle vertices
  356. for (let y = n; y < m + 1; y++) {
  357. for (let x = 0; x < m + 1 - y; x++) {
  358. vertices.push(new _IsoVector(x, y));
  359. }
  360. }
  361. //shared vertices along edges when needed
  362. if (n > 0) {
  363. const g = Scalar.HCF(m, n);
  364. const m1 = m / g;
  365. const n1 = n / g;
  366. for (let i = 1; i < g; i++) {
  367. vertices.push(new _IsoVector(i * m1, i * n1)); //OA
  368. vertices.push(new _IsoVector(-i * n1, i * (m1 + n1))); //OB
  369. vertices.push(new _IsoVector(m - i * (m1 + n1), n + i * m1)); // AB
  370. }
  371. //lower rows vertices and their rotations
  372. const ratio = m / n;
  373. for (let y = 1; y < n; y++) {
  374. for (let x = 0; x < y * ratio; x++) {
  375. vertices.push(new _IsoVector(x, y));
  376. vertices.push(new _IsoVector(x, y).rotate120(m, n));
  377. vertices.push(new _IsoVector(x, y).rotateNeg120(m, n));
  378. }
  379. }
  380. }
  381. //order vertices by x and then y
  382. vertices.sort((a, b) => {
  383. return a.x - b.x;
  384. });
  385. vertices.sort((a, b) => {
  386. return a.y - b.y;
  387. });
  388. const min = new Array(m + n + 1);
  389. const max = new Array(m + n + 1);
  390. for (let i = 0; i < min.length; i++) {
  391. min[i] = Infinity;
  392. max[i] = -Infinity;
  393. }
  394. let y = 0;
  395. let x = 0;
  396. const len = vertices.length;
  397. for (let i = 0; i < len; i++) {
  398. x = vertices[i].x;
  399. y = vertices[i].y;
  400. min[y] = Math.min(x, min[y]);
  401. max[y] = Math.max(x, max[y]);
  402. }
  403. //calculates the distance of a vertex from a given primary vertex
  404. const distFrom = (vert, primVert) => {
  405. const v = vert.clone();
  406. if (primVert === "A") {
  407. v.rotateNeg120(m, n);
  408. }
  409. if (primVert === "B") {
  410. v.rotate120(m, n);
  411. }
  412. if (v.x < 0) {
  413. return v.y;
  414. }
  415. return v.x + v.y;
  416. };
  417. const cartesian = [];
  418. const distFromO = [];
  419. const distFromA = [];
  420. const distFromB = [];
  421. const vertByDist = {};
  422. const vertData = [];
  423. let closest = -1;
  424. let dist = -1;
  425. for (let i = 0; i < len; i++) {
  426. cartesian[i] = vertices[i].toCartesianOrigin(new _IsoVector(0, 0), 0.5);
  427. distFromO[i] = distFrom(vertices[i], "O");
  428. distFromA[i] = distFrom(vertices[i], "A");
  429. distFromB[i] = distFrom(vertices[i], "B");
  430. if (distFromO[i] === distFromA[i] && distFromA[i] === distFromB[i]) {
  431. closest = 3;
  432. dist = distFromO[i];
  433. }
  434. else if (distFromO[i] === distFromA[i]) {
  435. closest = 4;
  436. dist = distFromO[i];
  437. }
  438. else if (distFromA[i] === distFromB[i]) {
  439. closest = 5;
  440. dist = distFromA[i];
  441. }
  442. else if (distFromB[i] === distFromO[i]) {
  443. closest = 6;
  444. dist = distFromO[i];
  445. }
  446. if (distFromO[i] < distFromA[i] && distFromO[i] < distFromB[i]) {
  447. closest = 2;
  448. dist = distFromO[i];
  449. }
  450. if (distFromA[i] < distFromO[i] && distFromA[i] < distFromB[i]) {
  451. closest = 1;
  452. dist = distFromA[i];
  453. }
  454. if (distFromB[i] < distFromA[i] && distFromB[i] < distFromO[i]) {
  455. closest = 0;
  456. dist = distFromB[i];
  457. }
  458. vertData.push([closest, dist, vertices[i].x, vertices[i].y]);
  459. }
  460. vertData.sort((a, b) => {
  461. return a[2] - b[2];
  462. });
  463. vertData.sort((a, b) => {
  464. return a[3] - b[3];
  465. });
  466. vertData.sort((a, b) => {
  467. return a[1] - b[1];
  468. });
  469. vertData.sort((a, b) => {
  470. return a[0] - b[0];
  471. });
  472. for (let v = 0; v < vertData.length; v++) {
  473. vertByDist[vertData[v][2] + "|" + vertData[v][3]] = [vertData[v][0], vertData[v][1], v];
  474. }
  475. this.m = m;
  476. this.n = n;
  477. this.vertices = vertices;
  478. this.vertByDist = vertByDist;
  479. this.cartesian = cartesian;
  480. this.min = min;
  481. this.max = max;
  482. return this;
  483. }
  484. }
  485. /** Builds Polyhedron Data
  486. * @internal
  487. */
  488. export class PolyhedronData {
  489. constructor(
  490. /**
  491. * The name of the polyhedron
  492. */
  493. name,
  494. /**
  495. * The category of the polyhedron
  496. */
  497. category,
  498. /**
  499. * vertex data
  500. */
  501. vertex,
  502. /**
  503. * face data
  504. */
  505. face) {
  506. this.name = name;
  507. this.category = category;
  508. this.vertex = vertex;
  509. this.face = face;
  510. }
  511. }
  512. /**
  513. * This class Extends the PolyhedronData Class to provide measures for a Geodesic Polyhedron
  514. */
  515. export class GeodesicData extends PolyhedronData {
  516. /**
  517. * @internal
  518. */
  519. innerToData(face, primTri) {
  520. for (let i = 0; i < primTri.innerFacets.length; i++) {
  521. this.face.push(primTri.innerFacets[i].map((el) => primTri.vecToidx[face + el]));
  522. }
  523. }
  524. /**
  525. * @internal
  526. */
  527. mapABOBtoDATA(faceNb, primTri) {
  528. const fr = primTri.IDATA.edgematch[faceNb][0];
  529. for (let i = 0; i < primTri.isoVecsABOB.length; i++) {
  530. const temp = [];
  531. for (let j = 0; j < 3; j++) {
  532. if (primTri.vertexTypes[i][j] === 0) {
  533. temp.push(faceNb + "|" + primTri.isoVecsABOB[i][j].x + "|" + primTri.isoVecsABOB[i][j].y);
  534. }
  535. else {
  536. temp.push(fr + "|" + primTri.isoVecsABOB[i][j].x + "|" + primTri.isoVecsABOB[i][j].y);
  537. }
  538. }
  539. this.face.push([primTri.vecToidx[temp[0]], primTri.vecToidx[temp[1]], primTri.vecToidx[temp[2]]]);
  540. }
  541. }
  542. /**
  543. * @internal
  544. */
  545. mapOBOAtoDATA(faceNb, primTri) {
  546. const fr = primTri.IDATA.edgematch[faceNb][0];
  547. for (let i = 0; i < primTri.isoVecsOBOA.length; i++) {
  548. const temp = [];
  549. for (let j = 0; j < 3; j++) {
  550. if (primTri.vertexTypes[i][j] === 1) {
  551. temp.push(faceNb + "|" + primTri.isoVecsOBOA[i][j].x + "|" + primTri.isoVecsOBOA[i][j].y);
  552. }
  553. else {
  554. temp.push(fr + "|" + primTri.isoVecsOBOA[i][j].x + "|" + primTri.isoVecsOBOA[i][j].y);
  555. }
  556. }
  557. this.face.push([primTri.vecToidx[temp[0]], primTri.vecToidx[temp[1]], primTri.vecToidx[temp[2]]]);
  558. }
  559. }
  560. /**
  561. * @internal
  562. */
  563. mapBAOAtoDATA(faceNb, primTri) {
  564. const fr = primTri.IDATA.edgematch[faceNb][2];
  565. for (let i = 0; i < primTri.isoVecsBAOA.length; i++) {
  566. const temp = [];
  567. for (let j = 0; j < 3; j++) {
  568. if (primTri.vertexTypes[i][j] === 1) {
  569. temp.push(faceNb + "|" + primTri.isoVecsBAOA[i][j].x + "|" + primTri.isoVecsBAOA[i][j].y);
  570. }
  571. else {
  572. temp.push(fr + "|" + primTri.isoVecsBAOA[i][j].x + "|" + primTri.isoVecsBAOA[i][j].y);
  573. }
  574. }
  575. this.face.push([primTri.vecToidx[temp[0]], primTri.vecToidx[temp[1]], primTri.vecToidx[temp[2]]]);
  576. }
  577. }
  578. /**
  579. * @internal
  580. */
  581. orderData(primTri) {
  582. const nearTo = [];
  583. for (let i = 0; i < 13; i++) {
  584. nearTo[i] = [];
  585. }
  586. const close = primTri.closestTo;
  587. for (let i = 0; i < close.length; i++) {
  588. if (close[i][0] > -1) {
  589. if (close[i][1] > 0) {
  590. nearTo[close[i][0]].push([i, close[i][1]]);
  591. }
  592. }
  593. else {
  594. nearTo[12].push([i, close[i][0]]);
  595. }
  596. }
  597. const near = [];
  598. for (let i = 0; i < 12; i++) {
  599. near[i] = i;
  600. }
  601. let nearIndex = 12;
  602. for (let i = 0; i < 12; i++) {
  603. nearTo[i].sort((a, b) => {
  604. return a[1] - b[1];
  605. });
  606. for (let j = 0; j < nearTo[i].length; j++) {
  607. near[nearTo[i][j][0]] = nearIndex++;
  608. }
  609. }
  610. for (let j = 0; j < nearTo[12].length; j++) {
  611. near[nearTo[12][j][0]] = nearIndex++;
  612. }
  613. for (let i = 0; i < this.vertex.length; i++) {
  614. this.vertex[i].push(near[i]);
  615. }
  616. this.vertex.sort((a, b) => {
  617. return a[3] - b[3];
  618. });
  619. for (let i = 0; i < this.vertex.length; i++) {
  620. this.vertex[i].pop();
  621. }
  622. for (let i = 0; i < this.face.length; i++) {
  623. for (let j = 0; j < this.face[i].length; j++) {
  624. this.face[i][j] = near[this.face[i][j]];
  625. }
  626. }
  627. this.sharedNodes = nearTo[12].length;
  628. this.poleNodes = this.vertex.length - this.sharedNodes;
  629. }
  630. /**
  631. * @internal
  632. */
  633. setOrder(m, faces) {
  634. const adjVerts = [];
  635. const dualFaces = [];
  636. let face = faces.pop();
  637. dualFaces.push(face);
  638. let index = this.face[face].indexOf(m);
  639. index = (index + 2) % 3;
  640. let v = this.face[face][index];
  641. adjVerts.push(v);
  642. let f = 0;
  643. while (faces.length > 0) {
  644. face = faces[f];
  645. if (this.face[face].indexOf(v) > -1) {
  646. // v is a vertex of face f
  647. index = (this.face[face].indexOf(v) + 1) % 3;
  648. v = this.face[face][index];
  649. adjVerts.push(v);
  650. dualFaces.push(face);
  651. faces.splice(f, 1);
  652. f = 0;
  653. }
  654. else {
  655. f++;
  656. }
  657. }
  658. this.adjacentFaces.push(adjVerts);
  659. return dualFaces;
  660. }
  661. /**
  662. * @internal
  663. */
  664. toGoldbergPolyhedronData() {
  665. const goldbergPolyhedronData = new PolyhedronData("GeoDual", "Goldberg", [], []);
  666. goldbergPolyhedronData.name = "GD dual";
  667. const verticesNb = this.vertex.length;
  668. const map = new Array(verticesNb);
  669. for (let v = 0; v < verticesNb; v++) {
  670. map[v] = [];
  671. }
  672. for (let f = 0; f < this.face.length; f++) {
  673. for (let i = 0; i < 3; i++) {
  674. map[this.face[f][i]].push(f);
  675. }
  676. }
  677. let cx = 0;
  678. let cy = 0;
  679. let cz = 0;
  680. let face = [];
  681. let vertex = [];
  682. this.adjacentFaces = [];
  683. for (let m = 0; m < map.length; m++) {
  684. goldbergPolyhedronData.face[m] = this.setOrder(m, map[m].concat([]));
  685. map[m].forEach((el) => {
  686. cx = 0;
  687. cy = 0;
  688. cz = 0;
  689. face = this.face[el];
  690. for (let i = 0; i < 3; i++) {
  691. vertex = this.vertex[face[i]];
  692. cx += vertex[0];
  693. cy += vertex[1];
  694. cz += vertex[2];
  695. }
  696. goldbergPolyhedronData.vertex[el] = [cx / 3, cy / 3, cz / 3];
  697. });
  698. }
  699. return goldbergPolyhedronData;
  700. }
  701. //statics
  702. /**Builds the data for a Geodesic Polyhedron from a primary triangle
  703. * @param primTri the primary triangle
  704. * @internal
  705. */
  706. static BuildGeodesicData(primTri) {
  707. const geodesicData = new GeodesicData("Geodesic-m-n", "Geodesic", [
  708. [0, PHI, -1],
  709. [-PHI, 1, 0],
  710. [-1, 0, -PHI],
  711. [1, 0, -PHI],
  712. [PHI, 1, 0],
  713. [0, PHI, 1],
  714. [-1, 0, PHI],
  715. [-PHI, -1, 0],
  716. [0, -PHI, -1],
  717. [PHI, -1, 0],
  718. [1, 0, PHI],
  719. [0, -PHI, 1],
  720. ], []);
  721. primTri.setIndices();
  722. primTri.calcCoeffs();
  723. primTri.createInnerFacets();
  724. primTri.edgeVecsABOB();
  725. primTri.mapABOBtoOBOA();
  726. primTri.mapABOBtoBAOA();
  727. for (let f = 0; f < primTri.IDATA.face.length; f++) {
  728. primTri.MapToFace(f, geodesicData);
  729. geodesicData.innerToData(f, primTri);
  730. if (primTri.IDATA.edgematch[f][1] === "B") {
  731. geodesicData.mapABOBtoDATA(f, primTri);
  732. }
  733. if (primTri.IDATA.edgematch[f][1] === "O") {
  734. geodesicData.mapOBOAtoDATA(f, primTri);
  735. }
  736. if (primTri.IDATA.edgematch[f][3] === "A") {
  737. geodesicData.mapBAOAtoDATA(f, primTri);
  738. }
  739. }
  740. geodesicData.orderData(primTri);
  741. const radius = 1;
  742. geodesicData.vertex = geodesicData.vertex.map(function (el) {
  743. const a = el[0];
  744. const b = el[1];
  745. const c = el[2];
  746. const d = Math.sqrt(a * a + b * b + c * c);
  747. el[0] *= radius / d;
  748. el[1] *= radius / d;
  749. el[2] *= radius / d;
  750. return el;
  751. });
  752. return geodesicData;
  753. }
  754. }
  755. //# sourceMappingURL=geodesicMesh.js.map