WallGeometryLibrary.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import arrayRemoveDuplicates from "./arrayRemoveDuplicates.js";
  2. import Cartesian3 from "./Cartesian3.js";
  3. import Cartographic from "./Cartographic.js";
  4. import defined from "./defined.js";
  5. import CesiumMath from "./Math.js";
  6. import PolylinePipeline from "./PolylinePipeline.js";
  7. /**
  8. * @private
  9. */
  10. const WallGeometryLibrary = {};
  11. function latLonEquals(c0, c1) {
  12. return (
  13. CesiumMath.equalsEpsilon(c0.latitude, c1.latitude, CesiumMath.EPSILON10) &&
  14. CesiumMath.equalsEpsilon(c0.longitude, c1.longitude, CesiumMath.EPSILON10)
  15. );
  16. }
  17. const scratchCartographic1 = new Cartographic();
  18. const scratchCartographic2 = new Cartographic();
  19. function removeDuplicates(ellipsoid, positions, topHeights, bottomHeights) {
  20. positions = arrayRemoveDuplicates(positions, Cartesian3.equalsEpsilon);
  21. const length = positions.length;
  22. if (length < 2) {
  23. return;
  24. }
  25. const hasBottomHeights = defined(bottomHeights);
  26. const hasTopHeights = defined(topHeights);
  27. const cleanedPositions = new Array(length);
  28. const cleanedTopHeights = new Array(length);
  29. const cleanedBottomHeights = new Array(length);
  30. const v0 = positions[0];
  31. cleanedPositions[0] = v0;
  32. const c0 = ellipsoid.cartesianToCartographic(v0, scratchCartographic1);
  33. if (hasTopHeights) {
  34. c0.height = topHeights[0];
  35. }
  36. cleanedTopHeights[0] = c0.height;
  37. if (hasBottomHeights) {
  38. cleanedBottomHeights[0] = bottomHeights[0];
  39. } else {
  40. cleanedBottomHeights[0] = 0.0;
  41. }
  42. const startTopHeight = cleanedTopHeights[0];
  43. const startBottomHeight = cleanedBottomHeights[0];
  44. let hasAllSameHeights = startTopHeight === startBottomHeight;
  45. let index = 1;
  46. for (let i = 1; i < length; ++i) {
  47. const v1 = positions[i];
  48. const c1 = ellipsoid.cartesianToCartographic(v1, scratchCartographic2);
  49. if (hasTopHeights) {
  50. c1.height = topHeights[i];
  51. }
  52. hasAllSameHeights = hasAllSameHeights && c1.height === 0;
  53. if (!latLonEquals(c0, c1)) {
  54. cleanedPositions[index] = v1; // Shallow copy!
  55. cleanedTopHeights[index] = c1.height;
  56. if (hasBottomHeights) {
  57. cleanedBottomHeights[index] = bottomHeights[i];
  58. } else {
  59. cleanedBottomHeights[index] = 0.0;
  60. }
  61. hasAllSameHeights =
  62. hasAllSameHeights &&
  63. cleanedTopHeights[index] === cleanedBottomHeights[index];
  64. Cartographic.clone(c1, c0);
  65. ++index;
  66. } else if (c0.height < c1.height) {
  67. // two adjacent positions are the same, so use whichever has the greater height
  68. cleanedTopHeights[index - 1] = c1.height;
  69. }
  70. }
  71. if (hasAllSameHeights || index < 2) {
  72. return;
  73. }
  74. cleanedPositions.length = index;
  75. cleanedTopHeights.length = index;
  76. cleanedBottomHeights.length = index;
  77. return {
  78. positions: cleanedPositions,
  79. topHeights: cleanedTopHeights,
  80. bottomHeights: cleanedBottomHeights,
  81. };
  82. }
  83. const positionsArrayScratch = new Array(2);
  84. const heightsArrayScratch = new Array(2);
  85. const generateArcOptionsScratch = {
  86. positions: undefined,
  87. height: undefined,
  88. granularity: undefined,
  89. ellipsoid: undefined,
  90. };
  91. /**
  92. * @private
  93. */
  94. WallGeometryLibrary.computePositions = function (
  95. ellipsoid,
  96. wallPositions,
  97. maximumHeights,
  98. minimumHeights,
  99. granularity,
  100. duplicateCorners
  101. ) {
  102. const o = removeDuplicates(
  103. ellipsoid,
  104. wallPositions,
  105. maximumHeights,
  106. minimumHeights
  107. );
  108. if (!defined(o)) {
  109. return;
  110. }
  111. wallPositions = o.positions;
  112. maximumHeights = o.topHeights;
  113. minimumHeights = o.bottomHeights;
  114. const length = wallPositions.length;
  115. const numCorners = length - 2;
  116. let topPositions;
  117. let bottomPositions;
  118. const minDistance = CesiumMath.chordLength(
  119. granularity,
  120. ellipsoid.maximumRadius
  121. );
  122. const generateArcOptions = generateArcOptionsScratch;
  123. generateArcOptions.minDistance = minDistance;
  124. generateArcOptions.ellipsoid = ellipsoid;
  125. if (duplicateCorners) {
  126. let count = 0;
  127. let i;
  128. for (i = 0; i < length - 1; i++) {
  129. count +=
  130. PolylinePipeline.numberOfPoints(
  131. wallPositions[i],
  132. wallPositions[i + 1],
  133. minDistance
  134. ) + 1;
  135. }
  136. topPositions = new Float64Array(count * 3);
  137. bottomPositions = new Float64Array(count * 3);
  138. const generateArcPositions = positionsArrayScratch;
  139. const generateArcHeights = heightsArrayScratch;
  140. generateArcOptions.positions = generateArcPositions;
  141. generateArcOptions.height = generateArcHeights;
  142. let offset = 0;
  143. for (i = 0; i < length - 1; i++) {
  144. generateArcPositions[0] = wallPositions[i];
  145. generateArcPositions[1] = wallPositions[i + 1];
  146. generateArcHeights[0] = maximumHeights[i];
  147. generateArcHeights[1] = maximumHeights[i + 1];
  148. const pos = PolylinePipeline.generateArc(generateArcOptions);
  149. topPositions.set(pos, offset);
  150. generateArcHeights[0] = minimumHeights[i];
  151. generateArcHeights[1] = minimumHeights[i + 1];
  152. bottomPositions.set(
  153. PolylinePipeline.generateArc(generateArcOptions),
  154. offset
  155. );
  156. offset += pos.length;
  157. }
  158. } else {
  159. generateArcOptions.positions = wallPositions;
  160. generateArcOptions.height = maximumHeights;
  161. topPositions = new Float64Array(
  162. PolylinePipeline.generateArc(generateArcOptions)
  163. );
  164. generateArcOptions.height = minimumHeights;
  165. bottomPositions = new Float64Array(
  166. PolylinePipeline.generateArc(generateArcOptions)
  167. );
  168. }
  169. return {
  170. bottomPositions: bottomPositions,
  171. topPositions: topPositions,
  172. numCorners: numCorners,
  173. };
  174. };
  175. export default WallGeometryLibrary;