PolygonPipeline-dd4a5392.js 47 KB

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