PolygonGeometryLibrary.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. import ArcType from "./ArcType.js";
  2. import arrayRemoveDuplicates from "./arrayRemoveDuplicates.js";
  3. import Cartesian2 from "./Cartesian2.js";
  4. import Cartesian3 from "./Cartesian3.js";
  5. import Cartographic from "./Cartographic.js";
  6. import ComponentDatatype from "./ComponentDatatype.js";
  7. import defaultValue from "./defaultValue.js";
  8. import defined from "./defined.js";
  9. import Ellipsoid from "./Ellipsoid.js";
  10. import EllipsoidRhumbLine from "./EllipsoidRhumbLine.js";
  11. import Geometry from "./Geometry.js";
  12. import GeometryAttribute from "./GeometryAttribute.js";
  13. import GeometryAttributes from "./GeometryAttributes.js";
  14. import GeometryPipeline from "./GeometryPipeline.js";
  15. import IndexDatatype from "./IndexDatatype.js";
  16. import CesiumMath from "./Math.js";
  17. import Matrix3 from "./Matrix3.js";
  18. import PolygonPipeline from "./PolygonPipeline.js";
  19. import PrimitiveType from "./PrimitiveType.js";
  20. import Quaternion from "./Quaternion.js";
  21. import Queue from "./Queue.js";
  22. import WindingOrder from "./WindingOrder.js";
  23. /**
  24. * @private
  25. */
  26. const PolygonGeometryLibrary = {};
  27. PolygonGeometryLibrary.computeHierarchyPackedLength = function (
  28. polygonHierarchy
  29. ) {
  30. let numComponents = 0;
  31. const stack = [polygonHierarchy];
  32. while (stack.length > 0) {
  33. const hierarchy = stack.pop();
  34. if (!defined(hierarchy)) {
  35. continue;
  36. }
  37. numComponents += 2;
  38. const positions = hierarchy.positions;
  39. const holes = hierarchy.holes;
  40. if (defined(positions)) {
  41. numComponents += positions.length * Cartesian3.packedLength;
  42. }
  43. if (defined(holes)) {
  44. const length = holes.length;
  45. for (let i = 0; i < length; ++i) {
  46. stack.push(holes[i]);
  47. }
  48. }
  49. }
  50. return numComponents;
  51. };
  52. PolygonGeometryLibrary.packPolygonHierarchy = function (
  53. polygonHierarchy,
  54. array,
  55. startingIndex
  56. ) {
  57. const stack = [polygonHierarchy];
  58. while (stack.length > 0) {
  59. const hierarchy = stack.pop();
  60. if (!defined(hierarchy)) {
  61. continue;
  62. }
  63. const positions = hierarchy.positions;
  64. const holes = hierarchy.holes;
  65. array[startingIndex++] = defined(positions) ? positions.length : 0;
  66. array[startingIndex++] = defined(holes) ? holes.length : 0;
  67. if (defined(positions)) {
  68. const positionsLength = positions.length;
  69. for (let i = 0; i < positionsLength; ++i, startingIndex += 3) {
  70. Cartesian3.pack(positions[i], array, startingIndex);
  71. }
  72. }
  73. if (defined(holes)) {
  74. const holesLength = holes.length;
  75. for (let j = 0; j < holesLength; ++j) {
  76. stack.push(holes[j]);
  77. }
  78. }
  79. }
  80. return startingIndex;
  81. };
  82. PolygonGeometryLibrary.unpackPolygonHierarchy = function (
  83. array,
  84. startingIndex
  85. ) {
  86. const positionsLength = array[startingIndex++];
  87. const holesLength = array[startingIndex++];
  88. const positions = new Array(positionsLength);
  89. const holes = holesLength > 0 ? new Array(holesLength) : undefined;
  90. for (
  91. let i = 0;
  92. i < positionsLength;
  93. ++i, startingIndex += Cartesian3.packedLength
  94. ) {
  95. positions[i] = Cartesian3.unpack(array, startingIndex);
  96. }
  97. for (let j = 0; j < holesLength; ++j) {
  98. holes[j] = PolygonGeometryLibrary.unpackPolygonHierarchy(
  99. array,
  100. startingIndex
  101. );
  102. startingIndex = holes[j].startingIndex;
  103. delete holes[j].startingIndex;
  104. }
  105. return {
  106. positions: positions,
  107. holes: holes,
  108. startingIndex: startingIndex,
  109. };
  110. };
  111. const distanceScratch = new Cartesian3();
  112. function getPointAtDistance(p0, p1, distance, length) {
  113. Cartesian3.subtract(p1, p0, distanceScratch);
  114. Cartesian3.multiplyByScalar(
  115. distanceScratch,
  116. distance / length,
  117. distanceScratch
  118. );
  119. Cartesian3.add(p0, distanceScratch, distanceScratch);
  120. return [distanceScratch.x, distanceScratch.y, distanceScratch.z];
  121. }
  122. PolygonGeometryLibrary.subdivideLineCount = function (p0, p1, minDistance) {
  123. const distance = Cartesian3.distance(p0, p1);
  124. const n = distance / minDistance;
  125. const countDivide = Math.max(0, Math.ceil(CesiumMath.log2(n)));
  126. return Math.pow(2, countDivide);
  127. };
  128. const scratchCartographic0 = new Cartographic();
  129. const scratchCartographic1 = new Cartographic();
  130. const scratchCartographic2 = new Cartographic();
  131. const scratchCartesian0 = new Cartesian3();
  132. PolygonGeometryLibrary.subdivideRhumbLineCount = function (
  133. ellipsoid,
  134. p0,
  135. p1,
  136. minDistance
  137. ) {
  138. const c0 = ellipsoid.cartesianToCartographic(p0, scratchCartographic0);
  139. const c1 = ellipsoid.cartesianToCartographic(p1, scratchCartographic1);
  140. const rhumb = new EllipsoidRhumbLine(c0, c1, ellipsoid);
  141. const n = rhumb.surfaceDistance / minDistance;
  142. const countDivide = Math.max(0, Math.ceil(CesiumMath.log2(n)));
  143. return Math.pow(2, countDivide);
  144. };
  145. PolygonGeometryLibrary.subdivideLine = function (p0, p1, minDistance, result) {
  146. const numVertices = PolygonGeometryLibrary.subdivideLineCount(
  147. p0,
  148. p1,
  149. minDistance
  150. );
  151. const length = Cartesian3.distance(p0, p1);
  152. const distanceBetweenVertices = length / numVertices;
  153. if (!defined(result)) {
  154. result = [];
  155. }
  156. const positions = result;
  157. positions.length = numVertices * 3;
  158. let index = 0;
  159. for (let i = 0; i < numVertices; i++) {
  160. const p = getPointAtDistance(p0, p1, i * distanceBetweenVertices, length);
  161. positions[index++] = p[0];
  162. positions[index++] = p[1];
  163. positions[index++] = p[2];
  164. }
  165. return positions;
  166. };
  167. PolygonGeometryLibrary.subdivideRhumbLine = function (
  168. ellipsoid,
  169. p0,
  170. p1,
  171. minDistance,
  172. result
  173. ) {
  174. const c0 = ellipsoid.cartesianToCartographic(p0, scratchCartographic0);
  175. const c1 = ellipsoid.cartesianToCartographic(p1, scratchCartographic1);
  176. const rhumb = new EllipsoidRhumbLine(c0, c1, ellipsoid);
  177. const n = rhumb.surfaceDistance / minDistance;
  178. const countDivide = Math.max(0, Math.ceil(CesiumMath.log2(n)));
  179. const numVertices = Math.pow(2, countDivide);
  180. const distanceBetweenVertices = rhumb.surfaceDistance / numVertices;
  181. if (!defined(result)) {
  182. result = [];
  183. }
  184. const positions = result;
  185. positions.length = numVertices * 3;
  186. let index = 0;
  187. for (let i = 0; i < numVertices; i++) {
  188. const c = rhumb.interpolateUsingSurfaceDistance(
  189. i * distanceBetweenVertices,
  190. scratchCartographic2
  191. );
  192. const p = ellipsoid.cartographicToCartesian(c, scratchCartesian0);
  193. positions[index++] = p.x;
  194. positions[index++] = p.y;
  195. positions[index++] = p.z;
  196. }
  197. return positions;
  198. };
  199. const scaleToGeodeticHeightN1 = new Cartesian3();
  200. const scaleToGeodeticHeightN2 = new Cartesian3();
  201. const scaleToGeodeticHeightP1 = new Cartesian3();
  202. const scaleToGeodeticHeightP2 = new Cartesian3();
  203. PolygonGeometryLibrary.scaleToGeodeticHeightExtruded = function (
  204. geometry,
  205. maxHeight,
  206. minHeight,
  207. ellipsoid,
  208. perPositionHeight
  209. ) {
  210. ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
  211. const n1 = scaleToGeodeticHeightN1;
  212. let n2 = scaleToGeodeticHeightN2;
  213. const p = scaleToGeodeticHeightP1;
  214. let p2 = scaleToGeodeticHeightP2;
  215. if (
  216. defined(geometry) &&
  217. defined(geometry.attributes) &&
  218. defined(geometry.attributes.position)
  219. ) {
  220. const positions = geometry.attributes.position.values;
  221. const length = positions.length / 2;
  222. for (let i = 0; i < length; i += 3) {
  223. Cartesian3.fromArray(positions, i, p);
  224. ellipsoid.geodeticSurfaceNormal(p, n1);
  225. p2 = ellipsoid.scaleToGeodeticSurface(p, p2);
  226. n2 = Cartesian3.multiplyByScalar(n1, minHeight, n2);
  227. n2 = Cartesian3.add(p2, n2, n2);
  228. positions[i + length] = n2.x;
  229. positions[i + 1 + length] = n2.y;
  230. positions[i + 2 + length] = n2.z;
  231. if (perPositionHeight) {
  232. p2 = Cartesian3.clone(p, p2);
  233. }
  234. n2 = Cartesian3.multiplyByScalar(n1, maxHeight, n2);
  235. n2 = Cartesian3.add(p2, n2, n2);
  236. positions[i] = n2.x;
  237. positions[i + 1] = n2.y;
  238. positions[i + 2] = n2.z;
  239. }
  240. }
  241. return geometry;
  242. };
  243. PolygonGeometryLibrary.polygonOutlinesFromHierarchy = function (
  244. polygonHierarchy,
  245. scaleToEllipsoidSurface,
  246. ellipsoid
  247. ) {
  248. // create from a polygon hierarchy
  249. // Algorithm adapted from http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf
  250. const polygons = [];
  251. const queue = new Queue();
  252. queue.enqueue(polygonHierarchy);
  253. let i;
  254. let j;
  255. let length;
  256. while (queue.length !== 0) {
  257. const outerNode = queue.dequeue();
  258. let outerRing = outerNode.positions;
  259. if (scaleToEllipsoidSurface) {
  260. length = outerRing.length;
  261. for (i = 0; i < length; i++) {
  262. ellipsoid.scaleToGeodeticSurface(outerRing[i], outerRing[i]);
  263. }
  264. }
  265. outerRing = arrayRemoveDuplicates(
  266. outerRing,
  267. Cartesian3.equalsEpsilon,
  268. true
  269. );
  270. if (outerRing.length < 3) {
  271. continue;
  272. }
  273. const numChildren = outerNode.holes ? outerNode.holes.length : 0;
  274. // The outer polygon contains inner polygons
  275. for (i = 0; i < numChildren; i++) {
  276. const hole = outerNode.holes[i];
  277. let holePositions = hole.positions;
  278. if (scaleToEllipsoidSurface) {
  279. length = holePositions.length;
  280. for (j = 0; j < length; ++j) {
  281. ellipsoid.scaleToGeodeticSurface(holePositions[j], holePositions[j]);
  282. }
  283. }
  284. holePositions = arrayRemoveDuplicates(
  285. holePositions,
  286. Cartesian3.equalsEpsilon,
  287. true
  288. );
  289. if (holePositions.length < 3) {
  290. continue;
  291. }
  292. polygons.push(holePositions);
  293. let numGrandchildren = 0;
  294. if (defined(hole.holes)) {
  295. numGrandchildren = hole.holes.length;
  296. }
  297. for (j = 0; j < numGrandchildren; j++) {
  298. queue.enqueue(hole.holes[j]);
  299. }
  300. }
  301. polygons.push(outerRing);
  302. }
  303. return polygons;
  304. };
  305. PolygonGeometryLibrary.polygonsFromHierarchy = function (
  306. polygonHierarchy,
  307. projectPointsTo2D,
  308. scaleToEllipsoidSurface,
  309. ellipsoid
  310. ) {
  311. // create from a polygon hierarchy
  312. // Algorithm adapted from http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf
  313. const hierarchy = [];
  314. const polygons = [];
  315. const queue = new Queue();
  316. queue.enqueue(polygonHierarchy);
  317. while (queue.length !== 0) {
  318. const outerNode = queue.dequeue();
  319. let outerRing = outerNode.positions;
  320. const holes = outerNode.holes;
  321. let i;
  322. let length;
  323. if (scaleToEllipsoidSurface) {
  324. length = outerRing.length;
  325. for (i = 0; i < length; i++) {
  326. ellipsoid.scaleToGeodeticSurface(outerRing[i], outerRing[i]);
  327. }
  328. }
  329. outerRing = arrayRemoveDuplicates(
  330. outerRing,
  331. Cartesian3.equalsEpsilon,
  332. true
  333. );
  334. if (outerRing.length < 3) {
  335. continue;
  336. }
  337. let positions2D = projectPointsTo2D(outerRing);
  338. if (!defined(positions2D)) {
  339. continue;
  340. }
  341. const holeIndices = [];
  342. let originalWindingOrder = PolygonPipeline.computeWindingOrder2D(
  343. positions2D
  344. );
  345. if (originalWindingOrder === WindingOrder.CLOCKWISE) {
  346. positions2D.reverse();
  347. outerRing = outerRing.slice().reverse();
  348. }
  349. let positions = outerRing.slice();
  350. const numChildren = defined(holes) ? holes.length : 0;
  351. const polygonHoles = [];
  352. let j;
  353. for (i = 0; i < numChildren; i++) {
  354. const hole = holes[i];
  355. let holePositions = hole.positions;
  356. if (scaleToEllipsoidSurface) {
  357. length = holePositions.length;
  358. for (j = 0; j < length; ++j) {
  359. ellipsoid.scaleToGeodeticSurface(holePositions[j], holePositions[j]);
  360. }
  361. }
  362. holePositions = arrayRemoveDuplicates(
  363. holePositions,
  364. Cartesian3.equalsEpsilon,
  365. true
  366. );
  367. if (holePositions.length < 3) {
  368. continue;
  369. }
  370. const holePositions2D = projectPointsTo2D(holePositions);
  371. if (!defined(holePositions2D)) {
  372. continue;
  373. }
  374. originalWindingOrder = PolygonPipeline.computeWindingOrder2D(
  375. holePositions2D
  376. );
  377. if (originalWindingOrder === WindingOrder.CLOCKWISE) {
  378. holePositions2D.reverse();
  379. holePositions = holePositions.slice().reverse();
  380. }
  381. polygonHoles.push(holePositions);
  382. holeIndices.push(positions.length);
  383. positions = positions.concat(holePositions);
  384. positions2D = positions2D.concat(holePositions2D);
  385. let numGrandchildren = 0;
  386. if (defined(hole.holes)) {
  387. numGrandchildren = hole.holes.length;
  388. }
  389. for (j = 0; j < numGrandchildren; j++) {
  390. queue.enqueue(hole.holes[j]);
  391. }
  392. }
  393. hierarchy.push({
  394. outerRing: outerRing,
  395. holes: polygonHoles,
  396. });
  397. polygons.push({
  398. positions: positions,
  399. positions2D: positions2D,
  400. holes: holeIndices,
  401. });
  402. }
  403. return {
  404. hierarchy: hierarchy,
  405. polygons: polygons,
  406. };
  407. };
  408. const computeBoundingRectangleCartesian2 = new Cartesian2();
  409. const computeBoundingRectangleCartesian3 = new Cartesian3();
  410. const computeBoundingRectangleQuaternion = new Quaternion();
  411. const computeBoundingRectangleMatrix3 = new Matrix3();
  412. PolygonGeometryLibrary.computeBoundingRectangle = function (
  413. planeNormal,
  414. projectPointTo2D,
  415. positions,
  416. angle,
  417. result
  418. ) {
  419. const rotation = Quaternion.fromAxisAngle(
  420. planeNormal,
  421. angle,
  422. computeBoundingRectangleQuaternion
  423. );
  424. const textureMatrix = Matrix3.fromQuaternion(
  425. rotation,
  426. computeBoundingRectangleMatrix3
  427. );
  428. let minX = Number.POSITIVE_INFINITY;
  429. let maxX = Number.NEGATIVE_INFINITY;
  430. let minY = Number.POSITIVE_INFINITY;
  431. let maxY = Number.NEGATIVE_INFINITY;
  432. const length = positions.length;
  433. for (let i = 0; i < length; ++i) {
  434. const p = Cartesian3.clone(
  435. positions[i],
  436. computeBoundingRectangleCartesian3
  437. );
  438. Matrix3.multiplyByVector(textureMatrix, p, p);
  439. const st = projectPointTo2D(p, computeBoundingRectangleCartesian2);
  440. if (defined(st)) {
  441. minX = Math.min(minX, st.x);
  442. maxX = Math.max(maxX, st.x);
  443. minY = Math.min(minY, st.y);
  444. maxY = Math.max(maxY, st.y);
  445. }
  446. }
  447. result.x = minX;
  448. result.y = minY;
  449. result.width = maxX - minX;
  450. result.height = maxY - minY;
  451. return result;
  452. };
  453. PolygonGeometryLibrary.createGeometryFromPositions = function (
  454. ellipsoid,
  455. polygon,
  456. granularity,
  457. perPositionHeight,
  458. vertexFormat,
  459. arcType
  460. ) {
  461. let indices = PolygonPipeline.triangulate(polygon.positions2D, polygon.holes);
  462. /* If polygon is completely unrenderable, just use the first three vertices */
  463. if (indices.length < 3) {
  464. indices = [0, 1, 2];
  465. }
  466. const positions = polygon.positions;
  467. if (perPositionHeight) {
  468. const length = positions.length;
  469. const flattenedPositions = new Array(length * 3);
  470. let index = 0;
  471. for (let i = 0; i < length; i++) {
  472. const p = positions[i];
  473. flattenedPositions[index++] = p.x;
  474. flattenedPositions[index++] = p.y;
  475. flattenedPositions[index++] = p.z;
  476. }
  477. const geometry = new Geometry({
  478. attributes: {
  479. position: new GeometryAttribute({
  480. componentDatatype: ComponentDatatype.DOUBLE,
  481. componentsPerAttribute: 3,
  482. values: flattenedPositions,
  483. }),
  484. },
  485. indices: indices,
  486. primitiveType: PrimitiveType.TRIANGLES,
  487. });
  488. if (vertexFormat.normal) {
  489. return GeometryPipeline.computeNormal(geometry);
  490. }
  491. return geometry;
  492. }
  493. if (arcType === ArcType.GEODESIC) {
  494. return PolygonPipeline.computeSubdivision(
  495. ellipsoid,
  496. positions,
  497. indices,
  498. granularity
  499. );
  500. } else if (arcType === ArcType.RHUMB) {
  501. return PolygonPipeline.computeRhumbLineSubdivision(
  502. ellipsoid,
  503. positions,
  504. indices,
  505. granularity
  506. );
  507. }
  508. };
  509. const computeWallIndicesSubdivided = [];
  510. const p1Scratch = new Cartesian3();
  511. const p2Scratch = new Cartesian3();
  512. PolygonGeometryLibrary.computeWallGeometry = function (
  513. positions,
  514. ellipsoid,
  515. granularity,
  516. perPositionHeight,
  517. arcType
  518. ) {
  519. let edgePositions;
  520. let topEdgeLength;
  521. let i;
  522. let p1;
  523. let p2;
  524. let length = positions.length;
  525. let index = 0;
  526. if (!perPositionHeight) {
  527. const minDistance = CesiumMath.chordLength(
  528. granularity,
  529. ellipsoid.maximumRadius
  530. );
  531. let numVertices = 0;
  532. if (arcType === ArcType.GEODESIC) {
  533. for (i = 0; i < length; i++) {
  534. numVertices += PolygonGeometryLibrary.subdivideLineCount(
  535. positions[i],
  536. positions[(i + 1) % length],
  537. minDistance
  538. );
  539. }
  540. } else if (arcType === ArcType.RHUMB) {
  541. for (i = 0; i < length; i++) {
  542. numVertices += PolygonGeometryLibrary.subdivideRhumbLineCount(
  543. ellipsoid,
  544. positions[i],
  545. positions[(i + 1) % length],
  546. minDistance
  547. );
  548. }
  549. }
  550. topEdgeLength = (numVertices + length) * 3;
  551. edgePositions = new Array(topEdgeLength * 2);
  552. for (i = 0; i < length; i++) {
  553. p1 = positions[i];
  554. p2 = positions[(i + 1) % length];
  555. let tempPositions;
  556. if (arcType === ArcType.GEODESIC) {
  557. tempPositions = PolygonGeometryLibrary.subdivideLine(
  558. p1,
  559. p2,
  560. minDistance,
  561. computeWallIndicesSubdivided
  562. );
  563. } else if (arcType === ArcType.RHUMB) {
  564. tempPositions = PolygonGeometryLibrary.subdivideRhumbLine(
  565. ellipsoid,
  566. p1,
  567. p2,
  568. minDistance,
  569. computeWallIndicesSubdivided
  570. );
  571. }
  572. const tempPositionsLength = tempPositions.length;
  573. for (let j = 0; j < tempPositionsLength; ++j, ++index) {
  574. edgePositions[index] = tempPositions[j];
  575. edgePositions[index + topEdgeLength] = tempPositions[j];
  576. }
  577. edgePositions[index] = p2.x;
  578. edgePositions[index + topEdgeLength] = p2.x;
  579. ++index;
  580. edgePositions[index] = p2.y;
  581. edgePositions[index + topEdgeLength] = p2.y;
  582. ++index;
  583. edgePositions[index] = p2.z;
  584. edgePositions[index + topEdgeLength] = p2.z;
  585. ++index;
  586. }
  587. } else {
  588. topEdgeLength = length * 3 * 2;
  589. edgePositions = new Array(topEdgeLength * 2);
  590. for (i = 0; i < length; i++) {
  591. p1 = positions[i];
  592. p2 = positions[(i + 1) % length];
  593. edgePositions[index] = edgePositions[index + topEdgeLength] = p1.x;
  594. ++index;
  595. edgePositions[index] = edgePositions[index + topEdgeLength] = p1.y;
  596. ++index;
  597. edgePositions[index] = edgePositions[index + topEdgeLength] = p1.z;
  598. ++index;
  599. edgePositions[index] = edgePositions[index + topEdgeLength] = p2.x;
  600. ++index;
  601. edgePositions[index] = edgePositions[index + topEdgeLength] = p2.y;
  602. ++index;
  603. edgePositions[index] = edgePositions[index + topEdgeLength] = p2.z;
  604. ++index;
  605. }
  606. }
  607. length = edgePositions.length;
  608. const indices = IndexDatatype.createTypedArray(
  609. length / 3,
  610. length - positions.length * 6
  611. );
  612. let edgeIndex = 0;
  613. length /= 6;
  614. for (i = 0; i < length; i++) {
  615. const UL = i;
  616. const UR = UL + 1;
  617. const LL = UL + length;
  618. const LR = LL + 1;
  619. p1 = Cartesian3.fromArray(edgePositions, UL * 3, p1Scratch);
  620. p2 = Cartesian3.fromArray(edgePositions, UR * 3, p2Scratch);
  621. if (
  622. Cartesian3.equalsEpsilon(
  623. p1,
  624. p2,
  625. CesiumMath.EPSILON10,
  626. CesiumMath.EPSILON10
  627. )
  628. ) {
  629. //skip corner
  630. continue;
  631. }
  632. indices[edgeIndex++] = UL;
  633. indices[edgeIndex++] = LL;
  634. indices[edgeIndex++] = UR;
  635. indices[edgeIndex++] = UR;
  636. indices[edgeIndex++] = LL;
  637. indices[edgeIndex++] = LR;
  638. }
  639. return new Geometry({
  640. attributes: new GeometryAttributes({
  641. position: new GeometryAttribute({
  642. componentDatatype: ComponentDatatype.DOUBLE,
  643. componentsPerAttribute: 3,
  644. values: edgePositions,
  645. }),
  646. }),
  647. indices: indices,
  648. primitiveType: PrimitiveType.TRIANGLES,
  649. });
  650. };
  651. export default PolygonGeometryLibrary;