PolygonPipeline-1fe328c0.js 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  1. define(['exports', './Math-0a2ac845', './Matrix2-e1298525', './Matrix3-41c58dde', './Check-6ede7e26', './ComponentDatatype-cf1fa08e', './defaultValue-fe22d8c0', './EllipsoidRhumbLine-ef872433', './GeometryAttribute-a466e9c7', './WebGLConstants-0b1ce7ba'], (function (exports, Math$1, Matrix2, Matrix3, Check, ComponentDatatype, defaultValue, EllipsoidRhumbLine, GeometryAttribute, WebGLConstants) { 'use strict';
  2. var earcut$2 = {exports: {}};
  3. earcut$2.exports = earcut;
  4. earcut$2.exports.default = earcut;
  5. function earcut(data, holeIndices, dim) {
  6. dim = dim || 2;
  7. var hasHoles = holeIndices && holeIndices.length,
  8. outerLen = hasHoles ? holeIndices[0] * dim : data.length,
  9. outerNode = linkedList(data, 0, outerLen, dim, true),
  10. triangles = [];
  11. if (!outerNode || outerNode.next === outerNode.prev) return triangles;
  12. var minX, minY, maxX, maxY, x, y, invSize;
  13. if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
  14. // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
  15. if (data.length > 80 * dim) {
  16. minX = maxX = data[0];
  17. minY = maxY = data[1];
  18. for (var i = dim; i < outerLen; i += dim) {
  19. x = data[i];
  20. y = data[i + 1];
  21. if (x < minX) minX = x;
  22. if (y < minY) minY = y;
  23. if (x > maxX) maxX = x;
  24. if (y > maxY) maxY = y;
  25. }
  26. // minX, minY and invSize are later used to transform coords into integers for z-order calculation
  27. invSize = Math.max(maxX - minX, maxY - minY);
  28. invSize = invSize !== 0 ? 32767 / invSize : 0;
  29. }
  30. earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
  31. return triangles;
  32. }
  33. // create a circular doubly linked list from polygon points in the specified winding order
  34. function linkedList(data, start, end, dim, clockwise) {
  35. var i, last;
  36. if (clockwise === (signedArea(data, start, end, dim) > 0)) {
  37. for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
  38. } else {
  39. for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
  40. }
  41. if (last && equals(last, last.next)) {
  42. removeNode(last);
  43. last = last.next;
  44. }
  45. return last;
  46. }
  47. // eliminate colinear or duplicate points
  48. function filterPoints(start, end) {
  49. if (!start) return start;
  50. if (!end) end = start;
  51. var p = start,
  52. again;
  53. do {
  54. again = false;
  55. if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
  56. removeNode(p);
  57. p = end = p.prev;
  58. if (p === p.next) break;
  59. again = true;
  60. } else {
  61. p = p.next;
  62. }
  63. } while (again || p !== end);
  64. return end;
  65. }
  66. // main ear slicing loop which triangulates a polygon (given as a linked list)
  67. function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
  68. if (!ear) return;
  69. // interlink polygon nodes in z-order
  70. if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
  71. var stop = ear,
  72. prev, next;
  73. // iterate through ears, slicing them one by one
  74. while (ear.prev !== ear.next) {
  75. prev = ear.prev;
  76. next = ear.next;
  77. if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
  78. // cut off the triangle
  79. triangles.push(prev.i / dim | 0);
  80. triangles.push(ear.i / dim | 0);
  81. triangles.push(next.i / dim | 0);
  82. removeNode(ear);
  83. // skipping the next vertex leads to less sliver triangles
  84. ear = next.next;
  85. stop = next.next;
  86. continue;
  87. }
  88. ear = next;
  89. // if we looped through the whole remaining polygon and can't find any more ears
  90. if (ear === stop) {
  91. // try filtering points and slicing again
  92. if (!pass) {
  93. earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
  94. // if this didn't work, try curing all small self-intersections locally
  95. } else if (pass === 1) {
  96. ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
  97. earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
  98. // as a last resort, try splitting the remaining polygon into two
  99. } else if (pass === 2) {
  100. splitEarcut(ear, triangles, dim, minX, minY, invSize);
  101. }
  102. break;
  103. }
  104. }
  105. }
  106. // check whether a polygon node forms a valid ear with adjacent nodes
  107. function isEar(ear) {
  108. var a = ear.prev,
  109. b = ear,
  110. c = ear.next;
  111. if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
  112. // now make sure we don't have other points inside the potential ear
  113. var ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
  114. // triangle bbox; min & max are calculated like this for speed
  115. var x0 = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx),
  116. y0 = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy),
  117. x1 = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx),
  118. y1 = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy);
  119. var p = c.next;
  120. while (p !== a) {
  121. if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&
  122. pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) &&
  123. area(p.prev, p, p.next) >= 0) return false;
  124. p = p.next;
  125. }
  126. return true;
  127. }
  128. function isEarHashed(ear, minX, minY, invSize) {
  129. var a = ear.prev,
  130. b = ear,
  131. c = ear.next;
  132. if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
  133. var ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
  134. // triangle bbox; min & max are calculated like this for speed
  135. var x0 = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx),
  136. y0 = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy),
  137. x1 = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx),
  138. y1 = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy);
  139. // z-order range for the current triangle bbox;
  140. var minZ = zOrder(x0, y0, minX, minY, invSize),
  141. maxZ = zOrder(x1, y1, minX, minY, invSize);
  142. var p = ear.prevZ,
  143. n = ear.nextZ;
  144. // look for points inside the triangle in both directions
  145. while (p && p.z >= minZ && n && n.z <= maxZ) {
  146. if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
  147. pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
  148. p = p.prevZ;
  149. if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
  150. pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
  151. n = n.nextZ;
  152. }
  153. // look for remaining points in decreasing z-order
  154. while (p && p.z >= minZ) {
  155. if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
  156. pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
  157. p = p.prevZ;
  158. }
  159. // look for remaining points in increasing z-order
  160. while (n && n.z <= maxZ) {
  161. if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
  162. pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
  163. n = n.nextZ;
  164. }
  165. return true;
  166. }
  167. // go through all polygon nodes and cure small local self-intersections
  168. function cureLocalIntersections(start, triangles, dim) {
  169. var p = start;
  170. do {
  171. var a = p.prev,
  172. b = p.next.next;
  173. if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
  174. triangles.push(a.i / dim | 0);
  175. triangles.push(p.i / dim | 0);
  176. triangles.push(b.i / dim | 0);
  177. // remove two nodes involved
  178. removeNode(p);
  179. removeNode(p.next);
  180. p = start = b;
  181. }
  182. p = p.next;
  183. } while (p !== start);
  184. return filterPoints(p);
  185. }
  186. // try splitting polygon into two and triangulate them independently
  187. function splitEarcut(start, triangles, dim, minX, minY, invSize) {
  188. // look for a valid diagonal that divides the polygon into two
  189. var a = start;
  190. do {
  191. var b = a.next.next;
  192. while (b !== a.prev) {
  193. if (a.i !== b.i && isValidDiagonal(a, b)) {
  194. // split the polygon in two by the diagonal
  195. var c = splitPolygon(a, b);
  196. // filter colinear points around the cuts
  197. a = filterPoints(a, a.next);
  198. c = filterPoints(c, c.next);
  199. // run earcut on each half
  200. earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
  201. earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
  202. return;
  203. }
  204. b = b.next;
  205. }
  206. a = a.next;
  207. } while (a !== start);
  208. }
  209. // link every hole into the outer loop, producing a single-ring polygon without holes
  210. function eliminateHoles(data, holeIndices, outerNode, dim) {
  211. var queue = [],
  212. i, len, start, end, list;
  213. for (i = 0, len = holeIndices.length; i < len; i++) {
  214. start = holeIndices[i] * dim;
  215. end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
  216. list = linkedList(data, start, end, dim, false);
  217. if (list === list.next) list.steiner = true;
  218. queue.push(getLeftmost(list));
  219. }
  220. queue.sort(compareX);
  221. // process holes from left to right
  222. for (i = 0; i < queue.length; i++) {
  223. outerNode = eliminateHole(queue[i], outerNode);
  224. }
  225. return outerNode;
  226. }
  227. function compareX(a, b) {
  228. return a.x - b.x;
  229. }
  230. // find a bridge between vertices that connects hole with an outer ring and and link it
  231. function eliminateHole(hole, outerNode) {
  232. var bridge = findHoleBridge(hole, outerNode);
  233. if (!bridge) {
  234. return outerNode;
  235. }
  236. var bridgeReverse = splitPolygon(bridge, hole);
  237. // filter collinear points around the cuts
  238. filterPoints(bridgeReverse, bridgeReverse.next);
  239. return filterPoints(bridge, bridge.next);
  240. }
  241. // David Eberly's algorithm for finding a bridge between hole and outer polygon
  242. function findHoleBridge(hole, outerNode) {
  243. var p = outerNode,
  244. hx = hole.x,
  245. hy = hole.y,
  246. qx = -Infinity,
  247. m;
  248. // find a segment intersected by a ray from the hole's leftmost point to the left;
  249. // segment's endpoint with lesser x will be potential connection point
  250. do {
  251. if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
  252. var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
  253. if (x <= hx && x > qx) {
  254. qx = x;
  255. m = p.x < p.next.x ? p : p.next;
  256. if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint
  257. }
  258. }
  259. p = p.next;
  260. } while (p !== outerNode);
  261. if (!m) return null;
  262. // look for points inside the triangle of hole point, segment intersection and endpoint;
  263. // if there are no points found, we have a valid connection;
  264. // otherwise choose the point of the minimum angle with the ray as connection point
  265. var stop = m,
  266. mx = m.x,
  267. my = m.y,
  268. tanMin = Infinity,
  269. tan;
  270. p = m;
  271. do {
  272. if (hx >= p.x && p.x >= mx && hx !== p.x &&
  273. pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
  274. tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
  275. if (locallyInside(p, hole) &&
  276. (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {
  277. m = p;
  278. tanMin = tan;
  279. }
  280. }
  281. p = p.next;
  282. } while (p !== stop);
  283. return m;
  284. }
  285. // whether sector in vertex m contains sector in vertex p in the same coordinates
  286. function sectorContainsSector(m, p) {
  287. return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
  288. }
  289. // interlink polygon nodes in z-order
  290. function indexCurve(start, minX, minY, invSize) {
  291. var p = start;
  292. do {
  293. if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
  294. p.prevZ = p.prev;
  295. p.nextZ = p.next;
  296. p = p.next;
  297. } while (p !== start);
  298. p.prevZ.nextZ = null;
  299. p.prevZ = null;
  300. sortLinked(p);
  301. }
  302. // Simon Tatham's linked list merge sort algorithm
  303. // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
  304. function sortLinked(list) {
  305. var i, p, q, e, tail, numMerges, pSize, qSize,
  306. inSize = 1;
  307. do {
  308. p = list;
  309. list = null;
  310. tail = null;
  311. numMerges = 0;
  312. while (p) {
  313. numMerges++;
  314. q = p;
  315. pSize = 0;
  316. for (i = 0; i < inSize; i++) {
  317. pSize++;
  318. q = q.nextZ;
  319. if (!q) break;
  320. }
  321. qSize = inSize;
  322. while (pSize > 0 || (qSize > 0 && q)) {
  323. if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
  324. e = p;
  325. p = p.nextZ;
  326. pSize--;
  327. } else {
  328. e = q;
  329. q = q.nextZ;
  330. qSize--;
  331. }
  332. if (tail) tail.nextZ = e;
  333. else list = e;
  334. e.prevZ = tail;
  335. tail = e;
  336. }
  337. p = q;
  338. }
  339. tail.nextZ = null;
  340. inSize *= 2;
  341. } while (numMerges > 1);
  342. return list;
  343. }
  344. // z-order of a point given coords and inverse of the longer side of data bbox
  345. function zOrder(x, y, minX, minY, invSize) {
  346. // coords are transformed into non-negative 15-bit integer range
  347. x = (x - minX) * invSize | 0;
  348. y = (y - minY) * invSize | 0;
  349. x = (x | (x << 8)) & 0x00FF00FF;
  350. x = (x | (x << 4)) & 0x0F0F0F0F;
  351. x = (x | (x << 2)) & 0x33333333;
  352. x = (x | (x << 1)) & 0x55555555;
  353. y = (y | (y << 8)) & 0x00FF00FF;
  354. y = (y | (y << 4)) & 0x0F0F0F0F;
  355. y = (y | (y << 2)) & 0x33333333;
  356. y = (y | (y << 1)) & 0x55555555;
  357. return x | (y << 1);
  358. }
  359. // find the leftmost node of a polygon ring
  360. function getLeftmost(start) {
  361. var p = start,
  362. leftmost = start;
  363. do {
  364. if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;
  365. p = p.next;
  366. } while (p !== start);
  367. return leftmost;
  368. }
  369. // check if a point lies within a convex triangle
  370. function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
  371. return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&
  372. (ax - px) * (by - py) >= (bx - px) * (ay - py) &&
  373. (bx - px) * (cy - py) >= (cx - px) * (by - py);
  374. }
  375. // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
  376. function isValidDiagonal(a, b) {
  377. return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges
  378. (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
  379. (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
  380. equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case
  381. }
  382. // signed area of a triangle
  383. function area(p, q, r) {
  384. return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
  385. }
  386. // check if two points are equal
  387. function equals(p1, p2) {
  388. return p1.x === p2.x && p1.y === p2.y;
  389. }
  390. // check if two segments intersect
  391. function intersects(p1, q1, p2, q2) {
  392. var o1 = sign(area(p1, q1, p2));
  393. var o2 = sign(area(p1, q1, q2));
  394. var o3 = sign(area(p2, q2, p1));
  395. var o4 = sign(area(p2, q2, q1));
  396. if (o1 !== o2 && o3 !== o4) return true; // general case
  397. if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
  398. if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
  399. if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
  400. if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
  401. return false;
  402. }
  403. // for collinear points p, q, r, check if point q lies on segment pr
  404. function onSegment(p, q, r) {
  405. return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
  406. }
  407. function sign(num) {
  408. return num > 0 ? 1 : num < 0 ? -1 : 0;
  409. }
  410. // check if a polygon diagonal intersects any polygon segments
  411. function intersectsPolygon(a, b) {
  412. var p = a;
  413. do {
  414. if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
  415. intersects(p, p.next, a, b)) return true;
  416. p = p.next;
  417. } while (p !== a);
  418. return false;
  419. }
  420. // check if a polygon diagonal is locally inside the polygon
  421. function locallyInside(a, b) {
  422. return area(a.prev, a, a.next) < 0 ?
  423. area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :
  424. area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
  425. }
  426. // check if the middle point of a polygon diagonal is inside the polygon
  427. function middleInside(a, b) {
  428. var p = a,
  429. inside = false,
  430. px = (a.x + b.x) / 2,
  431. py = (a.y + b.y) / 2;
  432. do {
  433. if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&
  434. (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
  435. inside = !inside;
  436. p = p.next;
  437. } while (p !== a);
  438. return inside;
  439. }
  440. // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
  441. // if one belongs to the outer ring and another to a hole, it merges it into a single ring
  442. function splitPolygon(a, b) {
  443. var a2 = new Node(a.i, a.x, a.y),
  444. b2 = new Node(b.i, b.x, b.y),
  445. an = a.next,
  446. bp = b.prev;
  447. a.next = b;
  448. b.prev = a;
  449. a2.next = an;
  450. an.prev = a2;
  451. b2.next = a2;
  452. a2.prev = b2;
  453. bp.next = b2;
  454. b2.prev = bp;
  455. return b2;
  456. }
  457. // create a node and optionally link it with previous one (in a circular doubly linked list)
  458. function insertNode(i, x, y, last) {
  459. var p = new Node(i, x, y);
  460. if (!last) {
  461. p.prev = p;
  462. p.next = p;
  463. } else {
  464. p.next = last.next;
  465. p.prev = last;
  466. last.next.prev = p;
  467. last.next = p;
  468. }
  469. return p;
  470. }
  471. function removeNode(p) {
  472. p.next.prev = p.prev;
  473. p.prev.next = p.next;
  474. if (p.prevZ) p.prevZ.nextZ = p.nextZ;
  475. if (p.nextZ) p.nextZ.prevZ = p.prevZ;
  476. }
  477. function Node(i, x, y) {
  478. // vertex index in coordinates array
  479. this.i = i;
  480. // vertex coordinates
  481. this.x = x;
  482. this.y = y;
  483. // previous and next vertex nodes in a polygon ring
  484. this.prev = null;
  485. this.next = null;
  486. // z-order curve value
  487. this.z = 0;
  488. // previous and next nodes in z-order
  489. this.prevZ = null;
  490. this.nextZ = null;
  491. // indicates whether this is a steiner point
  492. this.steiner = false;
  493. }
  494. // return a percentage difference between the polygon area and its triangulation area;
  495. // used to verify correctness of triangulation
  496. earcut.deviation = function (data, holeIndices, dim, triangles) {
  497. var hasHoles = holeIndices && holeIndices.length;
  498. var outerLen = hasHoles ? holeIndices[0] * dim : data.length;
  499. var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));
  500. if (hasHoles) {
  501. for (var i = 0, len = holeIndices.length; i < len; i++) {
  502. var start = holeIndices[i] * dim;
  503. var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
  504. polygonArea -= Math.abs(signedArea(data, start, end, dim));
  505. }
  506. }
  507. var trianglesArea = 0;
  508. for (i = 0; i < triangles.length; i += 3) {
  509. var a = triangles[i] * dim;
  510. var b = triangles[i + 1] * dim;
  511. var c = triangles[i + 2] * dim;
  512. trianglesArea += Math.abs(
  513. (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -
  514. (data[a] - data[b]) * (data[c + 1] - data[a + 1]));
  515. }
  516. return polygonArea === 0 && trianglesArea === 0 ? 0 :
  517. Math.abs((trianglesArea - polygonArea) / polygonArea);
  518. };
  519. function signedArea(data, start, end, dim) {
  520. var sum = 0;
  521. for (var i = start, j = end - dim; i < end; i += dim) {
  522. sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
  523. j = i;
  524. }
  525. return sum;
  526. }
  527. // turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts
  528. earcut.flatten = function (data) {
  529. var dim = data[0][0].length,
  530. result = {vertices: [], holes: [], dimensions: dim},
  531. holeIndex = 0;
  532. for (var i = 0; i < data.length; i++) {
  533. for (var j = 0; j < data[i].length; j++) {
  534. for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]);
  535. }
  536. if (i > 0) {
  537. holeIndex += data[i - 1].length;
  538. result.holes.push(holeIndex);
  539. }
  540. }
  541. return result;
  542. };
  543. var earcutExports = earcut$2.exports;
  544. var earcut$1 = /*@__PURE__*/Math$1.getDefaultExportFromCjs(earcutExports);
  545. /**
  546. * Winding order defines the order of vertices for a triangle to be considered front-facing.
  547. *
  548. * @enum {number}
  549. */
  550. const WindingOrder = {
  551. /**
  552. * Vertices are in clockwise order.
  553. *
  554. * @type {number}
  555. * @constant
  556. */
  557. CLOCKWISE: WebGLConstants.WebGLConstants.CW,
  558. /**
  559. * Vertices are in counter-clockwise order.
  560. *
  561. * @type {number}
  562. * @constant
  563. */
  564. COUNTER_CLOCKWISE: WebGLConstants.WebGLConstants.CCW,
  565. };
  566. /**
  567. * @private
  568. */
  569. WindingOrder.validate = function (windingOrder) {
  570. return (
  571. windingOrder === WindingOrder.CLOCKWISE ||
  572. windingOrder === WindingOrder.COUNTER_CLOCKWISE
  573. );
  574. };
  575. var WindingOrder$1 = Object.freeze(WindingOrder);
  576. const scaleToGeodeticHeightN = new Matrix3.Cartesian3();
  577. const scaleToGeodeticHeightP = new Matrix3.Cartesian3();
  578. /**
  579. * @private
  580. */
  581. const PolygonPipeline = {};
  582. /**
  583. * @exception {DeveloperError} At least three positions are required.
  584. */
  585. PolygonPipeline.computeArea2D = function (positions) {
  586. //>>includeStart('debug', pragmas.debug);
  587. Check.Check.defined("positions", positions);
  588. Check.Check.typeOf.number.greaterThanOrEquals(
  589. "positions.length",
  590. positions.length,
  591. 3
  592. );
  593. //>>includeEnd('debug');
  594. const length = positions.length;
  595. let area = 0.0;
  596. for (let i0 = length - 1, i1 = 0; i1 < length; i0 = i1++) {
  597. const v0 = positions[i0];
  598. const v1 = positions[i1];
  599. area += v0.x * v1.y - v1.x * v0.y;
  600. }
  601. return area * 0.5;
  602. };
  603. /**
  604. * @returns {WindingOrder} The winding order.
  605. *
  606. * @exception {DeveloperError} At least three positions are required.
  607. */
  608. PolygonPipeline.computeWindingOrder2D = function (positions) {
  609. const area = PolygonPipeline.computeArea2D(positions);
  610. return area > 0.0 ? WindingOrder$1.COUNTER_CLOCKWISE : WindingOrder$1.CLOCKWISE;
  611. };
  612. /**
  613. * Triangulate a polygon.
  614. *
  615. * @param {Cartesian2[]} positions Cartesian2 array containing the vertices of the polygon
  616. * @param {number[]} [holes] An array of the staring indices of the holes.
  617. * @returns {number[]} Index array representing triangles that fill the polygon
  618. */
  619. PolygonPipeline.triangulate = function (positions, holes) {
  620. //>>includeStart('debug', pragmas.debug);
  621. Check.Check.defined("positions", positions);
  622. //>>includeEnd('debug');
  623. const flattenedPositions = Matrix2.Cartesian2.packArray(positions);
  624. return earcut$1(flattenedPositions, holes, 2);
  625. };
  626. const subdivisionV0Scratch = new Matrix3.Cartesian3();
  627. const subdivisionV1Scratch = new Matrix3.Cartesian3();
  628. const subdivisionV2Scratch = new Matrix3.Cartesian3();
  629. const subdivisionS0Scratch = new Matrix3.Cartesian3();
  630. const subdivisionS1Scratch = new Matrix3.Cartesian3();
  631. const subdivisionS2Scratch = new Matrix3.Cartesian3();
  632. const subdivisionMidScratch = new Matrix3.Cartesian3();
  633. const subdivisionT0Scratch = new Matrix2.Cartesian2();
  634. const subdivisionT1Scratch = new Matrix2.Cartesian2();
  635. const subdivisionT2Scratch = new Matrix2.Cartesian2();
  636. const subdivisionTexcoordMidScratch = new Matrix2.Cartesian2();
  637. /**
  638. * Subdivides positions and raises points to the surface of the ellipsoid.
  639. *
  640. * @param {Ellipsoid} ellipsoid The ellipsoid the polygon in on.
  641. * @param {Cartesian3[]} positions An array of {@link Cartesian3} positions of the polygon.
  642. * @param {number[]} indices An array of indices that determines the triangles in the polygon.
  643. * @param {Cartesian2[]} texcoords An optional array of {@link Cartesian2} texture coordinates of the polygon.
  644. * @param {number} [granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
  645. *
  646. * @exception {DeveloperError} At least three indices are required.
  647. * @exception {DeveloperError} The number of indices must be divisable by three.
  648. * @exception {DeveloperError} Granularity must be greater than zero.
  649. */
  650. PolygonPipeline.computeSubdivision = function (
  651. ellipsoid,
  652. positions,
  653. indices,
  654. texcoords,
  655. granularity
  656. ) {
  657. granularity = defaultValue.defaultValue(granularity, Math$1.CesiumMath.RADIANS_PER_DEGREE);
  658. const hasTexcoords = defaultValue.defined(texcoords);
  659. //>>includeStart('debug', pragmas.debug);
  660. Check.Check.typeOf.object("ellipsoid", ellipsoid);
  661. Check.Check.defined("positions", positions);
  662. Check.Check.defined("indices", indices);
  663. Check.Check.typeOf.number.greaterThanOrEquals("indices.length", indices.length, 3);
  664. Check.Check.typeOf.number.equals("indices.length % 3", "0", indices.length % 3, 0);
  665. Check.Check.typeOf.number.greaterThan("granularity", granularity, 0.0);
  666. //>>includeEnd('debug');
  667. // triangles that need (or might need) to be subdivided.
  668. const triangles = indices.slice(0);
  669. // New positions due to edge splits are appended to the positions list.
  670. let i;
  671. const length = positions.length;
  672. const subdividedPositions = new Array(length * 3);
  673. const subdividedTexcoords = new Array(length * 2);
  674. let q = 0;
  675. let p = 0;
  676. for (i = 0; i < length; i++) {
  677. const item = positions[i];
  678. subdividedPositions[q++] = item.x;
  679. subdividedPositions[q++] = item.y;
  680. subdividedPositions[q++] = item.z;
  681. if (hasTexcoords) {
  682. const texcoordItem = texcoords[i];
  683. subdividedTexcoords[p++] = texcoordItem.x;
  684. subdividedTexcoords[p++] = texcoordItem.y;
  685. }
  686. }
  687. const subdividedIndices = [];
  688. // Used to make sure shared edges are not split more than once.
  689. const edges = {};
  690. const radius = ellipsoid.maximumRadius;
  691. const minDistance = Math$1.CesiumMath.chordLength(granularity, radius);
  692. const minDistanceSqrd = minDistance * minDistance;
  693. while (triangles.length > 0) {
  694. const i2 = triangles.pop();
  695. const i1 = triangles.pop();
  696. const i0 = triangles.pop();
  697. const v0 = Matrix3.Cartesian3.fromArray(
  698. subdividedPositions,
  699. i0 * 3,
  700. subdivisionV0Scratch
  701. );
  702. const v1 = Matrix3.Cartesian3.fromArray(
  703. subdividedPositions,
  704. i1 * 3,
  705. subdivisionV1Scratch
  706. );
  707. const v2 = Matrix3.Cartesian3.fromArray(
  708. subdividedPositions,
  709. i2 * 3,
  710. subdivisionV2Scratch
  711. );
  712. let t0, t1, t2;
  713. if (hasTexcoords) {
  714. t0 = Matrix2.Cartesian2.fromArray(
  715. subdividedTexcoords,
  716. i0 * 2,
  717. subdivisionT0Scratch
  718. );
  719. t1 = Matrix2.Cartesian2.fromArray(
  720. subdividedTexcoords,
  721. i1 * 2,
  722. subdivisionT1Scratch
  723. );
  724. t2 = Matrix2.Cartesian2.fromArray(
  725. subdividedTexcoords,
  726. i2 * 2,
  727. subdivisionT2Scratch
  728. );
  729. }
  730. const s0 = Matrix3.Cartesian3.multiplyByScalar(
  731. Matrix3.Cartesian3.normalize(v0, subdivisionS0Scratch),
  732. radius,
  733. subdivisionS0Scratch
  734. );
  735. const s1 = Matrix3.Cartesian3.multiplyByScalar(
  736. Matrix3.Cartesian3.normalize(v1, subdivisionS1Scratch),
  737. radius,
  738. subdivisionS1Scratch
  739. );
  740. const s2 = Matrix3.Cartesian3.multiplyByScalar(
  741. Matrix3.Cartesian3.normalize(v2, subdivisionS2Scratch),
  742. radius,
  743. subdivisionS2Scratch
  744. );
  745. const g0 = Matrix3.Cartesian3.magnitudeSquared(
  746. Matrix3.Cartesian3.subtract(s0, s1, subdivisionMidScratch)
  747. );
  748. const g1 = Matrix3.Cartesian3.magnitudeSquared(
  749. Matrix3.Cartesian3.subtract(s1, s2, subdivisionMidScratch)
  750. );
  751. const g2 = Matrix3.Cartesian3.magnitudeSquared(
  752. Matrix3.Cartesian3.subtract(s2, s0, subdivisionMidScratch)
  753. );
  754. const max = Math.max(g0, g1, g2);
  755. let edge;
  756. let mid;
  757. let midTexcoord;
  758. // if the max length squared of a triangle edge is greater than the chord length of squared
  759. // of the granularity, subdivide the triangle
  760. if (max > minDistanceSqrd) {
  761. if (g0 === max) {
  762. edge = `${Math.min(i0, i1)} ${Math.max(i0, i1)}`;
  763. i = edges[edge];
  764. if (!defaultValue.defined(i)) {
  765. mid = Matrix3.Cartesian3.add(v0, v1, subdivisionMidScratch);
  766. Matrix3.Cartesian3.multiplyByScalar(mid, 0.5, mid);
  767. subdividedPositions.push(mid.x, mid.y, mid.z);
  768. i = subdividedPositions.length / 3 - 1;
  769. edges[edge] = i;
  770. if (hasTexcoords) {
  771. midTexcoord = Matrix2.Cartesian2.add(t0, t1, subdivisionTexcoordMidScratch);
  772. Matrix2.Cartesian2.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
  773. subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
  774. }
  775. }
  776. triangles.push(i0, i, i2);
  777. triangles.push(i, i1, i2);
  778. } else if (g1 === max) {
  779. edge = `${Math.min(i1, i2)} ${Math.max(i1, i2)}`;
  780. i = edges[edge];
  781. if (!defaultValue.defined(i)) {
  782. mid = Matrix3.Cartesian3.add(v1, v2, subdivisionMidScratch);
  783. Matrix3.Cartesian3.multiplyByScalar(mid, 0.5, mid);
  784. subdividedPositions.push(mid.x, mid.y, mid.z);
  785. i = subdividedPositions.length / 3 - 1;
  786. edges[edge] = i;
  787. if (hasTexcoords) {
  788. midTexcoord = Matrix2.Cartesian2.add(t1, t2, subdivisionTexcoordMidScratch);
  789. Matrix2.Cartesian2.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
  790. subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
  791. }
  792. }
  793. triangles.push(i1, i, i0);
  794. triangles.push(i, i2, i0);
  795. } else if (g2 === max) {
  796. edge = `${Math.min(i2, i0)} ${Math.max(i2, i0)}`;
  797. i = edges[edge];
  798. if (!defaultValue.defined(i)) {
  799. mid = Matrix3.Cartesian3.add(v2, v0, subdivisionMidScratch);
  800. Matrix3.Cartesian3.multiplyByScalar(mid, 0.5, mid);
  801. subdividedPositions.push(mid.x, mid.y, mid.z);
  802. i = subdividedPositions.length / 3 - 1;
  803. edges[edge] = i;
  804. if (hasTexcoords) {
  805. midTexcoord = Matrix2.Cartesian2.add(t2, t0, subdivisionTexcoordMidScratch);
  806. Matrix2.Cartesian2.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
  807. subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
  808. }
  809. }
  810. triangles.push(i2, i, i1);
  811. triangles.push(i, i0, i1);
  812. }
  813. } else {
  814. subdividedIndices.push(i0);
  815. subdividedIndices.push(i1);
  816. subdividedIndices.push(i2);
  817. }
  818. }
  819. const geometryOptions = {
  820. attributes: {
  821. position: new GeometryAttribute.GeometryAttribute({
  822. componentDatatype: ComponentDatatype.ComponentDatatype.DOUBLE,
  823. componentsPerAttribute: 3,
  824. values: subdividedPositions,
  825. }),
  826. },
  827. indices: subdividedIndices,
  828. primitiveType: GeometryAttribute.PrimitiveType.TRIANGLES,
  829. };
  830. if (hasTexcoords) {
  831. geometryOptions.attributes.st = new GeometryAttribute.GeometryAttribute({
  832. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  833. componentsPerAttribute: 2,
  834. values: subdividedTexcoords,
  835. });
  836. }
  837. return new GeometryAttribute.Geometry(geometryOptions);
  838. };
  839. const subdivisionC0Scratch = new Matrix3.Cartographic();
  840. const subdivisionC1Scratch = new Matrix3.Cartographic();
  841. const subdivisionC2Scratch = new Matrix3.Cartographic();
  842. const subdivisionCartographicScratch = new Matrix3.Cartographic();
  843. /**
  844. * Subdivides positions on rhumb lines and raises points to the surface of the ellipsoid.
  845. *
  846. * @param {Ellipsoid} ellipsoid The ellipsoid the polygon in on.
  847. * @param {Cartesian3[]} positions An array of {@link Cartesian3} positions of the polygon.
  848. * @param {number[]} indices An array of indices that determines the triangles in the polygon.
  849. * @param {Cartesian2[]} texcoords An optional array of {@link Cartesian2} texture coordinates of the polygon.
  850. * @param {number} [granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
  851. *
  852. * @exception {DeveloperError} At least three indices are required.
  853. * @exception {DeveloperError} The number of indices must be divisable by three.
  854. * @exception {DeveloperError} Granularity must be greater than zero.
  855. */
  856. PolygonPipeline.computeRhumbLineSubdivision = function (
  857. ellipsoid,
  858. positions,
  859. indices,
  860. texcoords,
  861. granularity
  862. ) {
  863. granularity = defaultValue.defaultValue(granularity, Math$1.CesiumMath.RADIANS_PER_DEGREE);
  864. const hasTexcoords = defaultValue.defined(texcoords);
  865. //>>includeStart('debug', pragmas.debug);
  866. Check.Check.typeOf.object("ellipsoid", ellipsoid);
  867. Check.Check.defined("positions", positions);
  868. Check.Check.defined("indices", indices);
  869. Check.Check.typeOf.number.greaterThanOrEquals("indices.length", indices.length, 3);
  870. Check.Check.typeOf.number.equals("indices.length % 3", "0", indices.length % 3, 0);
  871. Check.Check.typeOf.number.greaterThan("granularity", granularity, 0.0);
  872. //>>includeEnd('debug');
  873. // triangles that need (or might need) to be subdivided.
  874. const triangles = indices.slice(0);
  875. // New positions due to edge splits are appended to the positions list.
  876. let i;
  877. const length = positions.length;
  878. const subdividedPositions = new Array(length * 3);
  879. const subdividedTexcoords = new Array(length * 2);
  880. let q = 0;
  881. let p = 0;
  882. for (i = 0; i < length; i++) {
  883. const item = positions[i];
  884. subdividedPositions[q++] = item.x;
  885. subdividedPositions[q++] = item.y;
  886. subdividedPositions[q++] = item.z;
  887. if (hasTexcoords) {
  888. const texcoordItem = texcoords[i];
  889. subdividedTexcoords[p++] = texcoordItem.x;
  890. subdividedTexcoords[p++] = texcoordItem.y;
  891. }
  892. }
  893. const subdividedIndices = [];
  894. // Used to make sure shared edges are not split more than once.
  895. const edges = {};
  896. const radius = ellipsoid.maximumRadius;
  897. const minDistance = Math$1.CesiumMath.chordLength(granularity, radius);
  898. const rhumb0 = new EllipsoidRhumbLine.EllipsoidRhumbLine(undefined, undefined, ellipsoid);
  899. const rhumb1 = new EllipsoidRhumbLine.EllipsoidRhumbLine(undefined, undefined, ellipsoid);
  900. const rhumb2 = new EllipsoidRhumbLine.EllipsoidRhumbLine(undefined, undefined, ellipsoid);
  901. while (triangles.length > 0) {
  902. const i2 = triangles.pop();
  903. const i1 = triangles.pop();
  904. const i0 = triangles.pop();
  905. const v0 = Matrix3.Cartesian3.fromArray(
  906. subdividedPositions,
  907. i0 * 3,
  908. subdivisionV0Scratch
  909. );
  910. const v1 = Matrix3.Cartesian3.fromArray(
  911. subdividedPositions,
  912. i1 * 3,
  913. subdivisionV1Scratch
  914. );
  915. const v2 = Matrix3.Cartesian3.fromArray(
  916. subdividedPositions,
  917. i2 * 3,
  918. subdivisionV2Scratch
  919. );
  920. let t0, t1, t2;
  921. if (hasTexcoords) {
  922. t0 = Matrix2.Cartesian2.fromArray(
  923. subdividedTexcoords,
  924. i0 * 2,
  925. subdivisionT0Scratch
  926. );
  927. t1 = Matrix2.Cartesian2.fromArray(
  928. subdividedTexcoords,
  929. i1 * 2,
  930. subdivisionT1Scratch
  931. );
  932. t2 = Matrix2.Cartesian2.fromArray(
  933. subdividedTexcoords,
  934. i2 * 2,
  935. subdivisionT2Scratch
  936. );
  937. }
  938. const c0 = ellipsoid.cartesianToCartographic(v0, subdivisionC0Scratch);
  939. const c1 = ellipsoid.cartesianToCartographic(v1, subdivisionC1Scratch);
  940. const c2 = ellipsoid.cartesianToCartographic(v2, subdivisionC2Scratch);
  941. rhumb0.setEndPoints(c0, c1);
  942. const g0 = rhumb0.surfaceDistance;
  943. rhumb1.setEndPoints(c1, c2);
  944. const g1 = rhumb1.surfaceDistance;
  945. rhumb2.setEndPoints(c2, c0);
  946. const g2 = rhumb2.surfaceDistance;
  947. const max = Math.max(g0, g1, g2);
  948. let edge;
  949. let mid;
  950. let midHeight;
  951. let midCartesian3;
  952. let midTexcoord;
  953. // if the max length squared of a triangle edge is greater than granularity, subdivide the triangle
  954. if (max > minDistance) {
  955. if (g0 === max) {
  956. edge = `${Math.min(i0, i1)} ${Math.max(i0, i1)}`;
  957. i = edges[edge];
  958. if (!defaultValue.defined(i)) {
  959. mid = rhumb0.interpolateUsingFraction(
  960. 0.5,
  961. subdivisionCartographicScratch
  962. );
  963. midHeight = (c0.height + c1.height) * 0.5;
  964. midCartesian3 = Matrix3.Cartesian3.fromRadians(
  965. mid.longitude,
  966. mid.latitude,
  967. midHeight,
  968. ellipsoid,
  969. subdivisionMidScratch
  970. );
  971. subdividedPositions.push(
  972. midCartesian3.x,
  973. midCartesian3.y,
  974. midCartesian3.z
  975. );
  976. i = subdividedPositions.length / 3 - 1;
  977. edges[edge] = i;
  978. if (hasTexcoords) {
  979. midTexcoord = Matrix2.Cartesian2.add(t0, t1, subdivisionTexcoordMidScratch);
  980. Matrix2.Cartesian2.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
  981. subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
  982. }
  983. }
  984. triangles.push(i0, i, i2);
  985. triangles.push(i, i1, i2);
  986. } else if (g1 === max) {
  987. edge = `${Math.min(i1, i2)} ${Math.max(i1, i2)}`;
  988. i = edges[edge];
  989. if (!defaultValue.defined(i)) {
  990. mid = rhumb1.interpolateUsingFraction(
  991. 0.5,
  992. subdivisionCartographicScratch
  993. );
  994. midHeight = (c1.height + c2.height) * 0.5;
  995. midCartesian3 = Matrix3.Cartesian3.fromRadians(
  996. mid.longitude,
  997. mid.latitude,
  998. midHeight,
  999. ellipsoid,
  1000. subdivisionMidScratch
  1001. );
  1002. subdividedPositions.push(
  1003. midCartesian3.x,
  1004. midCartesian3.y,
  1005. midCartesian3.z
  1006. );
  1007. i = subdividedPositions.length / 3 - 1;
  1008. edges[edge] = i;
  1009. if (hasTexcoords) {
  1010. midTexcoord = Matrix2.Cartesian2.add(t1, t2, subdivisionTexcoordMidScratch);
  1011. Matrix2.Cartesian2.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
  1012. subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
  1013. }
  1014. }
  1015. triangles.push(i1, i, i0);
  1016. triangles.push(i, i2, i0);
  1017. } else if (g2 === max) {
  1018. edge = `${Math.min(i2, i0)} ${Math.max(i2, i0)}`;
  1019. i = edges[edge];
  1020. if (!defaultValue.defined(i)) {
  1021. mid = rhumb2.interpolateUsingFraction(
  1022. 0.5,
  1023. subdivisionCartographicScratch
  1024. );
  1025. midHeight = (c2.height + c0.height) * 0.5;
  1026. midCartesian3 = Matrix3.Cartesian3.fromRadians(
  1027. mid.longitude,
  1028. mid.latitude,
  1029. midHeight,
  1030. ellipsoid,
  1031. subdivisionMidScratch
  1032. );
  1033. subdividedPositions.push(
  1034. midCartesian3.x,
  1035. midCartesian3.y,
  1036. midCartesian3.z
  1037. );
  1038. i = subdividedPositions.length / 3 - 1;
  1039. edges[edge] = i;
  1040. if (hasTexcoords) {
  1041. midTexcoord = Matrix2.Cartesian2.add(t2, t0, subdivisionTexcoordMidScratch);
  1042. Matrix2.Cartesian2.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
  1043. subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
  1044. }
  1045. }
  1046. triangles.push(i2, i, i1);
  1047. triangles.push(i, i0, i1);
  1048. }
  1049. } else {
  1050. subdividedIndices.push(i0);
  1051. subdividedIndices.push(i1);
  1052. subdividedIndices.push(i2);
  1053. }
  1054. }
  1055. const geometryOptions = {
  1056. attributes: {
  1057. position: new GeometryAttribute.GeometryAttribute({
  1058. componentDatatype: ComponentDatatype.ComponentDatatype.DOUBLE,
  1059. componentsPerAttribute: 3,
  1060. values: subdividedPositions,
  1061. }),
  1062. },
  1063. indices: subdividedIndices,
  1064. primitiveType: GeometryAttribute.PrimitiveType.TRIANGLES,
  1065. };
  1066. if (hasTexcoords) {
  1067. geometryOptions.attributes.st = new GeometryAttribute.GeometryAttribute({
  1068. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  1069. componentsPerAttribute: 2,
  1070. values: subdividedTexcoords,
  1071. });
  1072. }
  1073. return new GeometryAttribute.Geometry(geometryOptions);
  1074. };
  1075. /**
  1076. * Scales each position of a geometry's position attribute to a height, in place.
  1077. *
  1078. * @param {number[]} positions The array of numbers representing the positions to be scaled
  1079. * @param {number} [height=0.0] The desired height to add to the positions
  1080. * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the positions lie.
  1081. * @param {boolean} [scaleToSurface=true] <code>true</code> if the positions need to be scaled to the surface before the height is added.
  1082. * @returns {number[]} The input array of positions, scaled to height
  1083. */
  1084. PolygonPipeline.scaleToGeodeticHeight = function (
  1085. positions,
  1086. height,
  1087. ellipsoid,
  1088. scaleToSurface
  1089. ) {
  1090. ellipsoid = defaultValue.defaultValue(ellipsoid, Matrix3.Ellipsoid.WGS84);
  1091. let n = scaleToGeodeticHeightN;
  1092. let p = scaleToGeodeticHeightP;
  1093. height = defaultValue.defaultValue(height, 0.0);
  1094. scaleToSurface = defaultValue.defaultValue(scaleToSurface, true);
  1095. if (defaultValue.defined(positions)) {
  1096. const length = positions.length;
  1097. for (let i = 0; i < length; i += 3) {
  1098. Matrix3.Cartesian3.fromArray(positions, i, p);
  1099. if (scaleToSurface) {
  1100. p = ellipsoid.scaleToGeodeticSurface(p, p);
  1101. }
  1102. if (height !== 0) {
  1103. n = ellipsoid.geodeticSurfaceNormal(p, n);
  1104. Matrix3.Cartesian3.multiplyByScalar(n, height, n);
  1105. Matrix3.Cartesian3.add(p, n, p);
  1106. }
  1107. positions[i] = p.x;
  1108. positions[i + 1] = p.y;
  1109. positions[i + 2] = p.z;
  1110. }
  1111. }
  1112. return positions;
  1113. };
  1114. var PolygonPipeline$1 = PolygonPipeline;
  1115. exports.PolygonPipeline = PolygonPipeline$1;
  1116. exports.WindingOrder = WindingOrder$1;
  1117. }));