createPolygonGeometry.js 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422
  1. /* This file is automatically rebuilt by the Cesium build process. */
  2. define(['./defaultValue-94c3e563', './Matrix2-fc7e9822', './ArcType-0cf52f8c', './GeometryOffsetAttribute-3e8c299c', './BoundingRectangle-cbfe06ff', './Transforms-a076dbe6', './RuntimeError-c581ca93', './ComponentDatatype-4a60b8d6', './EllipsoidGeodesic-dc94f381', './EllipsoidTangentPlane-d2c0c530', './GeometryAttribute-2ecf73f6', './GeometryInstance-97bd792f', './GeometryPipeline-b4816e69', './IndexDatatype-db156785', './PolygonGeometryLibrary-6d3a5ed4', './PolygonPipeline-cc031b9f', './VertexFormat-e46f29d6', './_commonjsHelpers-3aae1032-f55dc0c4', './combine-761d9c3f', './WebGLConstants-7dccdc96', './AxisAlignedBoundingBox-8103739f', './IntersectionTests-5deed78b', './Plane-e20fba8c', './AttributeCompression-4d18cc04', './EncodedCartesian3-d3e254ea', './arrayRemoveDuplicates-06991c15', './EllipsoidRhumbLine-daebc75b', './GeometryAttributes-7df9bef6'], (function (defaultValue, Matrix2, ArcType, GeometryOffsetAttribute, BoundingRectangle, Transforms, RuntimeError, ComponentDatatype, EllipsoidGeodesic, EllipsoidTangentPlane, GeometryAttribute, GeometryInstance, GeometryPipeline, IndexDatatype, PolygonGeometryLibrary, PolygonPipeline, VertexFormat, _commonjsHelpers3aae1032, combine, WebGLConstants, AxisAlignedBoundingBox, IntersectionTests, Plane, AttributeCompression, EncodedCartesian3, arrayRemoveDuplicates, EllipsoidRhumbLine, GeometryAttributes) { 'use strict';
  3. const scratchCarto1 = new Matrix2.Cartographic();
  4. const scratchCarto2 = new Matrix2.Cartographic();
  5. function adjustPosHeightsForNormal(position, p1, p2, ellipsoid) {
  6. const carto1 = ellipsoid.cartesianToCartographic(position, scratchCarto1);
  7. const height = carto1.height;
  8. const p1Carto = ellipsoid.cartesianToCartographic(p1, scratchCarto2);
  9. p1Carto.height = height;
  10. ellipsoid.cartographicToCartesian(p1Carto, p1);
  11. const p2Carto = ellipsoid.cartesianToCartographic(p2, scratchCarto2);
  12. p2Carto.height = height - 100;
  13. ellipsoid.cartographicToCartesian(p2Carto, p2);
  14. }
  15. const scratchBoundingRectangle = new BoundingRectangle.BoundingRectangle();
  16. const scratchPosition = new Matrix2.Cartesian3();
  17. const scratchNormal = new Matrix2.Cartesian3();
  18. const scratchTangent = new Matrix2.Cartesian3();
  19. const scratchBitangent = new Matrix2.Cartesian3();
  20. const p1Scratch = new Matrix2.Cartesian3();
  21. const p2Scratch = new Matrix2.Cartesian3();
  22. let scratchPerPosNormal = new Matrix2.Cartesian3();
  23. let scratchPerPosTangent = new Matrix2.Cartesian3();
  24. let scratchPerPosBitangent = new Matrix2.Cartesian3();
  25. const appendTextureCoordinatesOrigin = new Matrix2.Cartesian2();
  26. const appendTextureCoordinatesCartesian2 = new Matrix2.Cartesian2();
  27. const appendTextureCoordinatesCartesian3 = new Matrix2.Cartesian3();
  28. const appendTextureCoordinatesQuaternion = new Transforms.Quaternion();
  29. const appendTextureCoordinatesMatrix3 = new Matrix2.Matrix3();
  30. const tangentMatrixScratch = new Matrix2.Matrix3();
  31. function computeAttributes(options) {
  32. const vertexFormat = options.vertexFormat;
  33. const geometry = options.geometry;
  34. const shadowVolume = options.shadowVolume;
  35. const flatPositions = geometry.attributes.position.values;
  36. const flatTexcoords = defaultValue.defined(geometry.attributes.st)
  37. ? geometry.attributes.st.values
  38. : undefined;
  39. let length = flatPositions.length;
  40. const wall = options.wall;
  41. const top = options.top || wall;
  42. const bottom = options.bottom || wall;
  43. if (
  44. vertexFormat.st ||
  45. vertexFormat.normal ||
  46. vertexFormat.tangent ||
  47. vertexFormat.bitangent ||
  48. shadowVolume
  49. ) {
  50. // PERFORMANCE_IDEA: Compute before subdivision, then just interpolate during subdivision.
  51. // PERFORMANCE_IDEA: Compute with createGeometryFromPositions() for fast path when there's no holes.
  52. const boundingRectangle = options.boundingRectangle;
  53. const tangentPlane = options.tangentPlane;
  54. const ellipsoid = options.ellipsoid;
  55. const stRotation = options.stRotation;
  56. const perPositionHeight = options.perPositionHeight;
  57. const origin = appendTextureCoordinatesOrigin;
  58. origin.x = boundingRectangle.x;
  59. origin.y = boundingRectangle.y;
  60. const textureCoordinates = vertexFormat.st
  61. ? new Float32Array(2 * (length / 3))
  62. : undefined;
  63. let normals;
  64. if (vertexFormat.normal) {
  65. if (perPositionHeight && top && !wall) {
  66. normals = geometry.attributes.normal.values;
  67. } else {
  68. normals = new Float32Array(length);
  69. }
  70. }
  71. const tangents = vertexFormat.tangent
  72. ? new Float32Array(length)
  73. : undefined;
  74. const bitangents = vertexFormat.bitangent
  75. ? new Float32Array(length)
  76. : undefined;
  77. const extrudeNormals = shadowVolume ? new Float32Array(length) : undefined;
  78. let textureCoordIndex = 0;
  79. let attrIndex = 0;
  80. let normal = scratchNormal;
  81. let tangent = scratchTangent;
  82. let bitangent = scratchBitangent;
  83. let recomputeNormal = true;
  84. let textureMatrix = appendTextureCoordinatesMatrix3;
  85. let tangentRotationMatrix = tangentMatrixScratch;
  86. if (stRotation !== 0.0) {
  87. let rotation = Transforms.Quaternion.fromAxisAngle(
  88. tangentPlane._plane.normal,
  89. stRotation,
  90. appendTextureCoordinatesQuaternion
  91. );
  92. textureMatrix = Matrix2.Matrix3.fromQuaternion(rotation, textureMatrix);
  93. rotation = Transforms.Quaternion.fromAxisAngle(
  94. tangentPlane._plane.normal,
  95. -stRotation,
  96. appendTextureCoordinatesQuaternion
  97. );
  98. tangentRotationMatrix = Matrix2.Matrix3.fromQuaternion(
  99. rotation,
  100. tangentRotationMatrix
  101. );
  102. } else {
  103. textureMatrix = Matrix2.Matrix3.clone(Matrix2.Matrix3.IDENTITY, textureMatrix);
  104. tangentRotationMatrix = Matrix2.Matrix3.clone(
  105. Matrix2.Matrix3.IDENTITY,
  106. tangentRotationMatrix
  107. );
  108. }
  109. let bottomOffset = 0;
  110. let bottomOffset2 = 0;
  111. if (top && bottom) {
  112. bottomOffset = length / 2;
  113. bottomOffset2 = length / 3;
  114. length /= 2;
  115. }
  116. for (let i = 0; i < length; i += 3) {
  117. const position = Matrix2.Cartesian3.fromArray(
  118. flatPositions,
  119. i,
  120. appendTextureCoordinatesCartesian3
  121. );
  122. if (vertexFormat.st) {
  123. if (!defaultValue.defined(flatTexcoords)) {
  124. let p = Matrix2.Matrix3.multiplyByVector(
  125. textureMatrix,
  126. position,
  127. scratchPosition
  128. );
  129. p = ellipsoid.scaleToGeodeticSurface(p, p);
  130. const st = tangentPlane.projectPointOntoPlane(
  131. p,
  132. appendTextureCoordinatesCartesian2
  133. );
  134. Matrix2.Cartesian2.subtract(st, origin, st);
  135. const stx = ComponentDatatype.CesiumMath.clamp(st.x / boundingRectangle.width, 0, 1);
  136. const sty = ComponentDatatype.CesiumMath.clamp(st.y / boundingRectangle.height, 0, 1);
  137. if (bottom) {
  138. textureCoordinates[textureCoordIndex + bottomOffset2] = stx;
  139. textureCoordinates[textureCoordIndex + 1 + bottomOffset2] = sty;
  140. }
  141. if (top) {
  142. textureCoordinates[textureCoordIndex] = stx;
  143. textureCoordinates[textureCoordIndex + 1] = sty;
  144. }
  145. textureCoordIndex += 2;
  146. }
  147. }
  148. if (
  149. vertexFormat.normal ||
  150. vertexFormat.tangent ||
  151. vertexFormat.bitangent ||
  152. shadowVolume
  153. ) {
  154. const attrIndex1 = attrIndex + 1;
  155. const attrIndex2 = attrIndex + 2;
  156. if (wall) {
  157. if (i + 3 < length) {
  158. const p1 = Matrix2.Cartesian3.fromArray(flatPositions, i + 3, p1Scratch);
  159. if (recomputeNormal) {
  160. const p2 = Matrix2.Cartesian3.fromArray(
  161. flatPositions,
  162. i + length,
  163. p2Scratch
  164. );
  165. if (perPositionHeight) {
  166. adjustPosHeightsForNormal(position, p1, p2, ellipsoid);
  167. }
  168. Matrix2.Cartesian3.subtract(p1, position, p1);
  169. Matrix2.Cartesian3.subtract(p2, position, p2);
  170. normal = Matrix2.Cartesian3.normalize(
  171. Matrix2.Cartesian3.cross(p2, p1, normal),
  172. normal
  173. );
  174. recomputeNormal = false;
  175. }
  176. if (Matrix2.Cartesian3.equalsEpsilon(p1, position, ComponentDatatype.CesiumMath.EPSILON10)) {
  177. // if we've reached a corner
  178. recomputeNormal = true;
  179. }
  180. }
  181. if (vertexFormat.tangent || vertexFormat.bitangent) {
  182. bitangent = ellipsoid.geodeticSurfaceNormal(position, bitangent);
  183. if (vertexFormat.tangent) {
  184. tangent = Matrix2.Cartesian3.normalize(
  185. Matrix2.Cartesian3.cross(bitangent, normal, tangent),
  186. tangent
  187. );
  188. }
  189. }
  190. } else {
  191. normal = ellipsoid.geodeticSurfaceNormal(position, normal);
  192. if (vertexFormat.tangent || vertexFormat.bitangent) {
  193. if (perPositionHeight) {
  194. scratchPerPosNormal = Matrix2.Cartesian3.fromArray(
  195. normals,
  196. attrIndex,
  197. scratchPerPosNormal
  198. );
  199. scratchPerPosTangent = Matrix2.Cartesian3.cross(
  200. Matrix2.Cartesian3.UNIT_Z,
  201. scratchPerPosNormal,
  202. scratchPerPosTangent
  203. );
  204. scratchPerPosTangent = Matrix2.Cartesian3.normalize(
  205. Matrix2.Matrix3.multiplyByVector(
  206. tangentRotationMatrix,
  207. scratchPerPosTangent,
  208. scratchPerPosTangent
  209. ),
  210. scratchPerPosTangent
  211. );
  212. if (vertexFormat.bitangent) {
  213. scratchPerPosBitangent = Matrix2.Cartesian3.normalize(
  214. Matrix2.Cartesian3.cross(
  215. scratchPerPosNormal,
  216. scratchPerPosTangent,
  217. scratchPerPosBitangent
  218. ),
  219. scratchPerPosBitangent
  220. );
  221. }
  222. }
  223. tangent = Matrix2.Cartesian3.cross(Matrix2.Cartesian3.UNIT_Z, normal, tangent);
  224. tangent = Matrix2.Cartesian3.normalize(
  225. Matrix2.Matrix3.multiplyByVector(tangentRotationMatrix, tangent, tangent),
  226. tangent
  227. );
  228. if (vertexFormat.bitangent) {
  229. bitangent = Matrix2.Cartesian3.normalize(
  230. Matrix2.Cartesian3.cross(normal, tangent, bitangent),
  231. bitangent
  232. );
  233. }
  234. }
  235. }
  236. if (vertexFormat.normal) {
  237. if (options.wall) {
  238. normals[attrIndex + bottomOffset] = normal.x;
  239. normals[attrIndex1 + bottomOffset] = normal.y;
  240. normals[attrIndex2 + bottomOffset] = normal.z;
  241. } else if (bottom) {
  242. normals[attrIndex + bottomOffset] = -normal.x;
  243. normals[attrIndex1 + bottomOffset] = -normal.y;
  244. normals[attrIndex2 + bottomOffset] = -normal.z;
  245. }
  246. if ((top && !perPositionHeight) || wall) {
  247. normals[attrIndex] = normal.x;
  248. normals[attrIndex1] = normal.y;
  249. normals[attrIndex2] = normal.z;
  250. }
  251. }
  252. if (shadowVolume) {
  253. if (wall) {
  254. normal = ellipsoid.geodeticSurfaceNormal(position, normal);
  255. }
  256. extrudeNormals[attrIndex + bottomOffset] = -normal.x;
  257. extrudeNormals[attrIndex1 + bottomOffset] = -normal.y;
  258. extrudeNormals[attrIndex2 + bottomOffset] = -normal.z;
  259. }
  260. if (vertexFormat.tangent) {
  261. if (options.wall) {
  262. tangents[attrIndex + bottomOffset] = tangent.x;
  263. tangents[attrIndex1 + bottomOffset] = tangent.y;
  264. tangents[attrIndex2 + bottomOffset] = tangent.z;
  265. } else if (bottom) {
  266. tangents[attrIndex + bottomOffset] = -tangent.x;
  267. tangents[attrIndex1 + bottomOffset] = -tangent.y;
  268. tangents[attrIndex2 + bottomOffset] = -tangent.z;
  269. }
  270. if (top) {
  271. if (perPositionHeight) {
  272. tangents[attrIndex] = scratchPerPosTangent.x;
  273. tangents[attrIndex1] = scratchPerPosTangent.y;
  274. tangents[attrIndex2] = scratchPerPosTangent.z;
  275. } else {
  276. tangents[attrIndex] = tangent.x;
  277. tangents[attrIndex1] = tangent.y;
  278. tangents[attrIndex2] = tangent.z;
  279. }
  280. }
  281. }
  282. if (vertexFormat.bitangent) {
  283. if (bottom) {
  284. bitangents[attrIndex + bottomOffset] = bitangent.x;
  285. bitangents[attrIndex1 + bottomOffset] = bitangent.y;
  286. bitangents[attrIndex2 + bottomOffset] = bitangent.z;
  287. }
  288. if (top) {
  289. if (perPositionHeight) {
  290. bitangents[attrIndex] = scratchPerPosBitangent.x;
  291. bitangents[attrIndex1] = scratchPerPosBitangent.y;
  292. bitangents[attrIndex2] = scratchPerPosBitangent.z;
  293. } else {
  294. bitangents[attrIndex] = bitangent.x;
  295. bitangents[attrIndex1] = bitangent.y;
  296. bitangents[attrIndex2] = bitangent.z;
  297. }
  298. }
  299. }
  300. attrIndex += 3;
  301. }
  302. }
  303. if (vertexFormat.st && !defaultValue.defined(flatTexcoords)) {
  304. geometry.attributes.st = new GeometryAttribute.GeometryAttribute({
  305. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  306. componentsPerAttribute: 2,
  307. values: textureCoordinates,
  308. });
  309. }
  310. if (vertexFormat.normal) {
  311. geometry.attributes.normal = new GeometryAttribute.GeometryAttribute({
  312. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  313. componentsPerAttribute: 3,
  314. values: normals,
  315. });
  316. }
  317. if (vertexFormat.tangent) {
  318. geometry.attributes.tangent = new GeometryAttribute.GeometryAttribute({
  319. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  320. componentsPerAttribute: 3,
  321. values: tangents,
  322. });
  323. }
  324. if (vertexFormat.bitangent) {
  325. geometry.attributes.bitangent = new GeometryAttribute.GeometryAttribute({
  326. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  327. componentsPerAttribute: 3,
  328. values: bitangents,
  329. });
  330. }
  331. if (shadowVolume) {
  332. geometry.attributes.extrudeDirection = new GeometryAttribute.GeometryAttribute({
  333. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  334. componentsPerAttribute: 3,
  335. values: extrudeNormals,
  336. });
  337. }
  338. }
  339. if (options.extrude && defaultValue.defined(options.offsetAttribute)) {
  340. const size = flatPositions.length / 3;
  341. let offsetAttribute = new Uint8Array(size);
  342. if (options.offsetAttribute === GeometryOffsetAttribute.GeometryOffsetAttribute.TOP) {
  343. if ((top && bottom) || wall) {
  344. offsetAttribute = GeometryOffsetAttribute.arrayFill(offsetAttribute, 1, 0, size / 2);
  345. } else if (top) {
  346. offsetAttribute = GeometryOffsetAttribute.arrayFill(offsetAttribute, 1);
  347. }
  348. } else {
  349. const offsetValue =
  350. options.offsetAttribute === GeometryOffsetAttribute.GeometryOffsetAttribute.NONE ? 0 : 1;
  351. offsetAttribute = GeometryOffsetAttribute.arrayFill(offsetAttribute, offsetValue);
  352. }
  353. geometry.attributes.applyOffset = new GeometryAttribute.GeometryAttribute({
  354. componentDatatype: ComponentDatatype.ComponentDatatype.UNSIGNED_BYTE,
  355. componentsPerAttribute: 1,
  356. values: offsetAttribute,
  357. });
  358. }
  359. return geometry;
  360. }
  361. const startCartographicScratch = new Matrix2.Cartographic();
  362. const endCartographicScratch = new Matrix2.Cartographic();
  363. const idlCross = {
  364. westOverIDL: 0.0,
  365. eastOverIDL: 0.0,
  366. };
  367. let ellipsoidGeodesic = new EllipsoidGeodesic.EllipsoidGeodesic();
  368. function computeRectangle(positions, ellipsoid, arcType, granularity, result) {
  369. result = defaultValue.defaultValue(result, new Matrix2.Rectangle());
  370. if (!defaultValue.defined(positions) || positions.length < 3) {
  371. result.west = 0.0;
  372. result.north = 0.0;
  373. result.south = 0.0;
  374. result.east = 0.0;
  375. return result;
  376. }
  377. if (arcType === ArcType.ArcType.RHUMB) {
  378. return Matrix2.Rectangle.fromCartesianArray(positions, ellipsoid, result);
  379. }
  380. if (!ellipsoidGeodesic.ellipsoid.equals(ellipsoid)) {
  381. ellipsoidGeodesic = new EllipsoidGeodesic.EllipsoidGeodesic(undefined, undefined, ellipsoid);
  382. }
  383. result.west = Number.POSITIVE_INFINITY;
  384. result.east = Number.NEGATIVE_INFINITY;
  385. result.south = Number.POSITIVE_INFINITY;
  386. result.north = Number.NEGATIVE_INFINITY;
  387. idlCross.westOverIDL = Number.POSITIVE_INFINITY;
  388. idlCross.eastOverIDL = Number.NEGATIVE_INFINITY;
  389. const inverseChordLength =
  390. 1.0 / ComponentDatatype.CesiumMath.chordLength(granularity, ellipsoid.maximumRadius);
  391. const positionsLength = positions.length;
  392. let endCartographic = ellipsoid.cartesianToCartographic(
  393. positions[0],
  394. endCartographicScratch
  395. );
  396. let startCartographic = startCartographicScratch;
  397. let swap;
  398. for (let i = 1; i < positionsLength; i++) {
  399. swap = startCartographic;
  400. startCartographic = endCartographic;
  401. endCartographic = ellipsoid.cartesianToCartographic(positions[i], swap);
  402. ellipsoidGeodesic.setEndPoints(startCartographic, endCartographic);
  403. interpolateAndGrowRectangle(
  404. ellipsoidGeodesic,
  405. inverseChordLength,
  406. result,
  407. idlCross
  408. );
  409. }
  410. swap = startCartographic;
  411. startCartographic = endCartographic;
  412. endCartographic = ellipsoid.cartesianToCartographic(positions[0], swap);
  413. ellipsoidGeodesic.setEndPoints(startCartographic, endCartographic);
  414. interpolateAndGrowRectangle(
  415. ellipsoidGeodesic,
  416. inverseChordLength,
  417. result,
  418. idlCross
  419. );
  420. if (result.east - result.west > idlCross.eastOverIDL - idlCross.westOverIDL) {
  421. result.west = idlCross.westOverIDL;
  422. result.east = idlCross.eastOverIDL;
  423. if (result.east > ComponentDatatype.CesiumMath.PI) {
  424. result.east = result.east - ComponentDatatype.CesiumMath.TWO_PI;
  425. }
  426. if (result.west > ComponentDatatype.CesiumMath.PI) {
  427. result.west = result.west - ComponentDatatype.CesiumMath.TWO_PI;
  428. }
  429. }
  430. return result;
  431. }
  432. const interpolatedCartographicScratch = new Matrix2.Cartographic();
  433. function interpolateAndGrowRectangle(
  434. ellipsoidGeodesic,
  435. inverseChordLength,
  436. result,
  437. idlCross
  438. ) {
  439. const segmentLength = ellipsoidGeodesic.surfaceDistance;
  440. const numPoints = Math.ceil(segmentLength * inverseChordLength);
  441. const subsegmentDistance =
  442. numPoints > 0 ? segmentLength / (numPoints - 1) : Number.POSITIVE_INFINITY;
  443. let interpolationDistance = 0.0;
  444. for (let i = 0; i < numPoints; i++) {
  445. const interpolatedCartographic = ellipsoidGeodesic.interpolateUsingSurfaceDistance(
  446. interpolationDistance,
  447. interpolatedCartographicScratch
  448. );
  449. interpolationDistance += subsegmentDistance;
  450. const longitude = interpolatedCartographic.longitude;
  451. const latitude = interpolatedCartographic.latitude;
  452. result.west = Math.min(result.west, longitude);
  453. result.east = Math.max(result.east, longitude);
  454. result.south = Math.min(result.south, latitude);
  455. result.north = Math.max(result.north, latitude);
  456. const lonAdjusted =
  457. longitude >= 0 ? longitude : longitude + ComponentDatatype.CesiumMath.TWO_PI;
  458. idlCross.westOverIDL = Math.min(idlCross.westOverIDL, lonAdjusted);
  459. idlCross.eastOverIDL = Math.max(idlCross.eastOverIDL, lonAdjusted);
  460. }
  461. }
  462. const createGeometryFromPositionsExtrudedPositions = [];
  463. function createGeometryFromPositionsExtruded(
  464. ellipsoid,
  465. polygon,
  466. textureCoordinates,
  467. granularity,
  468. hierarchy,
  469. perPositionHeight,
  470. closeTop,
  471. closeBottom,
  472. vertexFormat,
  473. arcType
  474. ) {
  475. const geos = {
  476. walls: [],
  477. };
  478. let i;
  479. if (closeTop || closeBottom) {
  480. const topGeo = PolygonGeometryLibrary.PolygonGeometryLibrary.createGeometryFromPositions(
  481. ellipsoid,
  482. polygon,
  483. textureCoordinates,
  484. granularity,
  485. perPositionHeight,
  486. vertexFormat,
  487. arcType
  488. );
  489. const edgePoints = topGeo.attributes.position.values;
  490. const indices = topGeo.indices;
  491. let numPositions;
  492. let newIndices;
  493. if (closeTop && closeBottom) {
  494. const topBottomPositions = edgePoints.concat(edgePoints);
  495. numPositions = topBottomPositions.length / 3;
  496. newIndices = IndexDatatype.IndexDatatype.createTypedArray(
  497. numPositions,
  498. indices.length * 2
  499. );
  500. newIndices.set(indices);
  501. const ilength = indices.length;
  502. const length = numPositions / 2;
  503. for (i = 0; i < ilength; i += 3) {
  504. const i0 = newIndices[i] + length;
  505. const i1 = newIndices[i + 1] + length;
  506. const i2 = newIndices[i + 2] + length;
  507. newIndices[i + ilength] = i2;
  508. newIndices[i + 1 + ilength] = i1;
  509. newIndices[i + 2 + ilength] = i0;
  510. }
  511. topGeo.attributes.position.values = topBottomPositions;
  512. if (perPositionHeight && vertexFormat.normal) {
  513. const normals = topGeo.attributes.normal.values;
  514. topGeo.attributes.normal.values = new Float32Array(
  515. topBottomPositions.length
  516. );
  517. topGeo.attributes.normal.values.set(normals);
  518. }
  519. if (vertexFormat.st && defaultValue.defined(textureCoordinates)) {
  520. const texcoords = topGeo.attributes.st.values;
  521. topGeo.attributes.st.values = new Float32Array(numPositions * 2);
  522. topGeo.attributes.st.values = texcoords.concat(texcoords);
  523. }
  524. topGeo.indices = newIndices;
  525. } else if (closeBottom) {
  526. numPositions = edgePoints.length / 3;
  527. newIndices = IndexDatatype.IndexDatatype.createTypedArray(numPositions, indices.length);
  528. for (i = 0; i < indices.length; i += 3) {
  529. newIndices[i] = indices[i + 2];
  530. newIndices[i + 1] = indices[i + 1];
  531. newIndices[i + 2] = indices[i];
  532. }
  533. topGeo.indices = newIndices;
  534. }
  535. geos.topAndBottom = new GeometryInstance.GeometryInstance({
  536. geometry: topGeo,
  537. });
  538. }
  539. let outerRing = hierarchy.outerRing;
  540. let tangentPlane = EllipsoidTangentPlane.EllipsoidTangentPlane.fromPoints(outerRing, ellipsoid);
  541. let positions2D = tangentPlane.projectPointsOntoPlane(
  542. outerRing,
  543. createGeometryFromPositionsExtrudedPositions
  544. );
  545. let windingOrder = PolygonPipeline.PolygonPipeline.computeWindingOrder2D(positions2D);
  546. if (windingOrder === PolygonPipeline.WindingOrder.CLOCKWISE) {
  547. outerRing = outerRing.slice().reverse();
  548. }
  549. let wallGeo = PolygonGeometryLibrary.PolygonGeometryLibrary.computeWallGeometry(
  550. outerRing,
  551. textureCoordinates,
  552. ellipsoid,
  553. granularity,
  554. perPositionHeight,
  555. arcType
  556. );
  557. geos.walls.push(
  558. new GeometryInstance.GeometryInstance({
  559. geometry: wallGeo,
  560. })
  561. );
  562. const holes = hierarchy.holes;
  563. for (i = 0; i < holes.length; i++) {
  564. let hole = holes[i];
  565. tangentPlane = EllipsoidTangentPlane.EllipsoidTangentPlane.fromPoints(hole, ellipsoid);
  566. positions2D = tangentPlane.projectPointsOntoPlane(
  567. hole,
  568. createGeometryFromPositionsExtrudedPositions
  569. );
  570. windingOrder = PolygonPipeline.PolygonPipeline.computeWindingOrder2D(positions2D);
  571. if (windingOrder === PolygonPipeline.WindingOrder.COUNTER_CLOCKWISE) {
  572. hole = hole.slice().reverse();
  573. }
  574. wallGeo = PolygonGeometryLibrary.PolygonGeometryLibrary.computeWallGeometry(
  575. hole,
  576. textureCoordinates,
  577. ellipsoid,
  578. granularity,
  579. perPositionHeight,
  580. arcType
  581. );
  582. geos.walls.push(
  583. new GeometryInstance.GeometryInstance({
  584. geometry: wallGeo,
  585. })
  586. );
  587. }
  588. return geos;
  589. }
  590. /**
  591. * A description of a polygon on the ellipsoid. The polygon is defined by a polygon hierarchy. Polygon geometry can be rendered with both {@link Primitive} and {@link GroundPrimitive}.
  592. *
  593. * @alias PolygonGeometry
  594. * @constructor
  595. *
  596. * @param {Object} options Object with the following properties:
  597. * @param {PolygonHierarchy} options.polygonHierarchy A polygon hierarchy that can include holes.
  598. * @param {Number} [options.height=0.0] The distance in meters between the polygon and the ellipsoid surface.
  599. * @param {Number} [options.extrudedHeight] The distance in meters between the polygon's extruded face and the ellipsoid surface.
  600. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.
  601. * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise.
  602. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.
  603. * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
  604. * @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.
  605. * @param {Boolean} [options.closeTop=true] When false, leaves off the top of an extruded polygon open.
  606. * @param {Boolean} [options.closeBottom=true] When false, leaves off the bottom of an extruded polygon open.
  607. * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polygon edges must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.
  608. * @param {PolygonHierarchy} [options.textureCoordinates] Texture coordinates as a {@link PolygonHierarchy} of {@link Cartesian2} points. Has no effect for ground primitives.
  609. *
  610. * @see PolygonGeometry#createGeometry
  611. * @see PolygonGeometry#fromPositions
  612. *
  613. * @demo {@link https://sandcastle.cesium.com/index.html?src=Polygon.html|Cesium Sandcastle Polygon Demo}
  614. *
  615. * @example
  616. * // 1. create a polygon from points
  617. * const polygon = new Cesium.PolygonGeometry({
  618. * polygonHierarchy : new Cesium.PolygonHierarchy(
  619. * Cesium.Cartesian3.fromDegreesArray([
  620. * -72.0, 40.0,
  621. * -70.0, 35.0,
  622. * -75.0, 30.0,
  623. * -70.0, 30.0,
  624. * -68.0, 40.0
  625. * ])
  626. * )
  627. * });
  628. * const geometry = Cesium.PolygonGeometry.createGeometry(polygon);
  629. *
  630. * // 2. create a nested polygon with holes
  631. * const polygonWithHole = new Cesium.PolygonGeometry({
  632. * polygonHierarchy : new Cesium.PolygonHierarchy(
  633. * Cesium.Cartesian3.fromDegreesArray([
  634. * -109.0, 30.0,
  635. * -95.0, 30.0,
  636. * -95.0, 40.0,
  637. * -109.0, 40.0
  638. * ]),
  639. * [new Cesium.PolygonHierarchy(
  640. * Cesium.Cartesian3.fromDegreesArray([
  641. * -107.0, 31.0,
  642. * -107.0, 39.0,
  643. * -97.0, 39.0,
  644. * -97.0, 31.0
  645. * ]),
  646. * [new Cesium.PolygonHierarchy(
  647. * Cesium.Cartesian3.fromDegreesArray([
  648. * -105.0, 33.0,
  649. * -99.0, 33.0,
  650. * -99.0, 37.0,
  651. * -105.0, 37.0
  652. * ]),
  653. * [new Cesium.PolygonHierarchy(
  654. * Cesium.Cartesian3.fromDegreesArray([
  655. * -103.0, 34.0,
  656. * -101.0, 34.0,
  657. * -101.0, 36.0,
  658. * -103.0, 36.0
  659. * ])
  660. * )]
  661. * )]
  662. * )]
  663. * )
  664. * });
  665. * const geometry = Cesium.PolygonGeometry.createGeometry(polygonWithHole);
  666. *
  667. * // 3. create extruded polygon
  668. * const extrudedPolygon = new Cesium.PolygonGeometry({
  669. * polygonHierarchy : new Cesium.PolygonHierarchy(
  670. * Cesium.Cartesian3.fromDegreesArray([
  671. * -72.0, 40.0,
  672. * -70.0, 35.0,
  673. * -75.0, 30.0,
  674. * -70.0, 30.0,
  675. * -68.0, 40.0
  676. * ])
  677. * ),
  678. * extrudedHeight: 300000
  679. * });
  680. * const geometry = Cesium.PolygonGeometry.createGeometry(extrudedPolygon);
  681. */
  682. function PolygonGeometry(options) {
  683. //>>includeStart('debug', pragmas.debug);
  684. RuntimeError.Check.typeOf.object("options", options);
  685. RuntimeError.Check.typeOf.object("options.polygonHierarchy", options.polygonHierarchy);
  686. if (
  687. defaultValue.defined(options.perPositionHeight) &&
  688. options.perPositionHeight &&
  689. defaultValue.defined(options.height)
  690. ) {
  691. throw new RuntimeError.DeveloperError(
  692. "Cannot use both options.perPositionHeight and options.height"
  693. );
  694. }
  695. if (
  696. defaultValue.defined(options.arcType) &&
  697. options.arcType !== ArcType.ArcType.GEODESIC &&
  698. options.arcType !== ArcType.ArcType.RHUMB
  699. ) {
  700. throw new RuntimeError.DeveloperError(
  701. "Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB."
  702. );
  703. }
  704. //>>includeEnd('debug');
  705. const polygonHierarchy = options.polygonHierarchy;
  706. const vertexFormat = defaultValue.defaultValue(options.vertexFormat, VertexFormat.VertexFormat.DEFAULT);
  707. const ellipsoid = defaultValue.defaultValue(options.ellipsoid, Matrix2.Ellipsoid.WGS84);
  708. const granularity = defaultValue.defaultValue(
  709. options.granularity,
  710. ComponentDatatype.CesiumMath.RADIANS_PER_DEGREE
  711. );
  712. const stRotation = defaultValue.defaultValue(options.stRotation, 0.0);
  713. const textureCoordinates = options.textureCoordinates;
  714. const perPositionHeight = defaultValue.defaultValue(options.perPositionHeight, false);
  715. const perPositionHeightExtrude =
  716. perPositionHeight && defaultValue.defined(options.extrudedHeight);
  717. let height = defaultValue.defaultValue(options.height, 0.0);
  718. let extrudedHeight = defaultValue.defaultValue(options.extrudedHeight, height);
  719. if (!perPositionHeightExtrude) {
  720. const h = Math.max(height, extrudedHeight);
  721. extrudedHeight = Math.min(height, extrudedHeight);
  722. height = h;
  723. }
  724. this._vertexFormat = VertexFormat.VertexFormat.clone(vertexFormat);
  725. this._ellipsoid = Matrix2.Ellipsoid.clone(ellipsoid);
  726. this._granularity = granularity;
  727. this._stRotation = stRotation;
  728. this._height = height;
  729. this._extrudedHeight = extrudedHeight;
  730. this._closeTop = defaultValue.defaultValue(options.closeTop, true);
  731. this._closeBottom = defaultValue.defaultValue(options.closeBottom, true);
  732. this._polygonHierarchy = polygonHierarchy;
  733. this._perPositionHeight = perPositionHeight;
  734. this._perPositionHeightExtrude = perPositionHeightExtrude;
  735. this._shadowVolume = defaultValue.defaultValue(options.shadowVolume, false);
  736. this._workerName = "createPolygonGeometry";
  737. this._offsetAttribute = options.offsetAttribute;
  738. this._arcType = defaultValue.defaultValue(options.arcType, ArcType.ArcType.GEODESIC);
  739. this._rectangle = undefined;
  740. this._textureCoordinateRotationPoints = undefined;
  741. this._textureCoordinates = textureCoordinates;
  742. /**
  743. * The number of elements used to pack the object into an array.
  744. * @type {Number}
  745. */
  746. this.packedLength =
  747. PolygonGeometryLibrary.PolygonGeometryLibrary.computeHierarchyPackedLength(
  748. polygonHierarchy,
  749. Matrix2.Cartesian3
  750. ) +
  751. Matrix2.Ellipsoid.packedLength +
  752. VertexFormat.VertexFormat.packedLength +
  753. (textureCoordinates
  754. ? PolygonGeometryLibrary.PolygonGeometryLibrary.computeHierarchyPackedLength(
  755. textureCoordinates,
  756. Matrix2.Cartesian2
  757. )
  758. : 1) +
  759. 12;
  760. }
  761. /**
  762. * A description of a polygon from an array of positions. Polygon geometry can be rendered with both {@link Primitive} and {@link GroundPrimitive}.
  763. *
  764. * @param {Object} options Object with the following properties:
  765. * @param {Cartesian3[]} options.positions An array of positions that defined the corner points of the polygon.
  766. * @param {Number} [options.height=0.0] The height of the polygon.
  767. * @param {Number} [options.extrudedHeight] The height of the polygon extrusion.
  768. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.
  769. * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise.
  770. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.
  771. * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
  772. * @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.
  773. * @param {Boolean} [options.closeTop=true] When false, leaves off the top of an extruded polygon open.
  774. * @param {Boolean} [options.closeBottom=true] When false, leaves off the bottom of an extruded polygon open.
  775. * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polygon edges must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.
  776. * @param {PolygonHierarchy} [options.textureCoordinates] Texture coordinates as a {@link PolygonHierarchy} of {@link Cartesian2} points. Has no effect for ground primitives.
  777. * @returns {PolygonGeometry}
  778. *
  779. * @example
  780. * // create a polygon from points
  781. * const polygon = Cesium.PolygonGeometry.fromPositions({
  782. * positions : Cesium.Cartesian3.fromDegreesArray([
  783. * -72.0, 40.0,
  784. * -70.0, 35.0,
  785. * -75.0, 30.0,
  786. * -70.0, 30.0,
  787. * -68.0, 40.0
  788. * ])
  789. * });
  790. * const geometry = Cesium.PolygonGeometry.createGeometry(polygon);
  791. *
  792. * @see PolygonGeometry#createGeometry
  793. */
  794. PolygonGeometry.fromPositions = function (options) {
  795. options = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  796. //>>includeStart('debug', pragmas.debug);
  797. RuntimeError.Check.defined("options.positions", options.positions);
  798. //>>includeEnd('debug');
  799. const newOptions = {
  800. polygonHierarchy: {
  801. positions: options.positions,
  802. },
  803. height: options.height,
  804. extrudedHeight: options.extrudedHeight,
  805. vertexFormat: options.vertexFormat,
  806. stRotation: options.stRotation,
  807. ellipsoid: options.ellipsoid,
  808. granularity: options.granularity,
  809. perPositionHeight: options.perPositionHeight,
  810. closeTop: options.closeTop,
  811. closeBottom: options.closeBottom,
  812. offsetAttribute: options.offsetAttribute,
  813. arcType: options.arcType,
  814. textureCoordinates: options.textureCoordinates,
  815. };
  816. return new PolygonGeometry(newOptions);
  817. };
  818. /**
  819. * Stores the provided instance into the provided array.
  820. *
  821. * @param {PolygonGeometry} value The value to pack.
  822. * @param {Number[]} array The array to pack into.
  823. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
  824. *
  825. * @returns {Number[]} The array that was packed into
  826. */
  827. PolygonGeometry.pack = function (value, array, startingIndex) {
  828. //>>includeStart('debug', pragmas.debug);
  829. RuntimeError.Check.typeOf.object("value", value);
  830. RuntimeError.Check.defined("array", array);
  831. //>>includeEnd('debug');
  832. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  833. startingIndex = PolygonGeometryLibrary.PolygonGeometryLibrary.packPolygonHierarchy(
  834. value._polygonHierarchy,
  835. array,
  836. startingIndex,
  837. Matrix2.Cartesian3
  838. );
  839. Matrix2.Ellipsoid.pack(value._ellipsoid, array, startingIndex);
  840. startingIndex += Matrix2.Ellipsoid.packedLength;
  841. VertexFormat.VertexFormat.pack(value._vertexFormat, array, startingIndex);
  842. startingIndex += VertexFormat.VertexFormat.packedLength;
  843. array[startingIndex++] = value._height;
  844. array[startingIndex++] = value._extrudedHeight;
  845. array[startingIndex++] = value._granularity;
  846. array[startingIndex++] = value._stRotation;
  847. array[startingIndex++] = value._perPositionHeightExtrude ? 1.0 : 0.0;
  848. array[startingIndex++] = value._perPositionHeight ? 1.0 : 0.0;
  849. array[startingIndex++] = value._closeTop ? 1.0 : 0.0;
  850. array[startingIndex++] = value._closeBottom ? 1.0 : 0.0;
  851. array[startingIndex++] = value._shadowVolume ? 1.0 : 0.0;
  852. array[startingIndex++] = defaultValue.defaultValue(value._offsetAttribute, -1);
  853. array[startingIndex++] = value._arcType;
  854. if (defaultValue.defined(value._textureCoordinates)) {
  855. startingIndex = PolygonGeometryLibrary.PolygonGeometryLibrary.packPolygonHierarchy(
  856. value._textureCoordinates,
  857. array,
  858. startingIndex,
  859. Matrix2.Cartesian2
  860. );
  861. } else {
  862. array[startingIndex++] = -1.0;
  863. }
  864. array[startingIndex++] = value.packedLength;
  865. return array;
  866. };
  867. const scratchEllipsoid = Matrix2.Ellipsoid.clone(Matrix2.Ellipsoid.UNIT_SPHERE);
  868. const scratchVertexFormat = new VertexFormat.VertexFormat();
  869. //Only used to avoid inability to default construct.
  870. const dummyOptions = {
  871. polygonHierarchy: {},
  872. };
  873. /**
  874. * Retrieves an instance from a packed array.
  875. *
  876. * @param {Number[]} array The packed array.
  877. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
  878. * @param {PolygonGeometry} [result] The object into which to store the result.
  879. */
  880. PolygonGeometry.unpack = function (array, startingIndex, result) {
  881. //>>includeStart('debug', pragmas.debug);
  882. RuntimeError.Check.defined("array", array);
  883. //>>includeEnd('debug');
  884. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  885. const polygonHierarchy = PolygonGeometryLibrary.PolygonGeometryLibrary.unpackPolygonHierarchy(
  886. array,
  887. startingIndex,
  888. Matrix2.Cartesian3
  889. );
  890. startingIndex = polygonHierarchy.startingIndex;
  891. delete polygonHierarchy.startingIndex;
  892. const ellipsoid = Matrix2.Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);
  893. startingIndex += Matrix2.Ellipsoid.packedLength;
  894. const vertexFormat = VertexFormat.VertexFormat.unpack(
  895. array,
  896. startingIndex,
  897. scratchVertexFormat
  898. );
  899. startingIndex += VertexFormat.VertexFormat.packedLength;
  900. const height = array[startingIndex++];
  901. const extrudedHeight = array[startingIndex++];
  902. const granularity = array[startingIndex++];
  903. const stRotation = array[startingIndex++];
  904. const perPositionHeightExtrude = array[startingIndex++] === 1.0;
  905. const perPositionHeight = array[startingIndex++] === 1.0;
  906. const closeTop = array[startingIndex++] === 1.0;
  907. const closeBottom = array[startingIndex++] === 1.0;
  908. const shadowVolume = array[startingIndex++] === 1.0;
  909. const offsetAttribute = array[startingIndex++];
  910. const arcType = array[startingIndex++];
  911. const textureCoordinates =
  912. array[startingIndex] === -1.0
  913. ? undefined
  914. : PolygonGeometryLibrary.PolygonGeometryLibrary.unpackPolygonHierarchy(
  915. array,
  916. startingIndex,
  917. Matrix2.Cartesian2
  918. );
  919. if (defaultValue.defined(textureCoordinates)) {
  920. startingIndex = textureCoordinates.startingIndex;
  921. delete textureCoordinates.startingIndex;
  922. } else {
  923. startingIndex++;
  924. }
  925. const packedLength = array[startingIndex++];
  926. if (!defaultValue.defined(result)) {
  927. result = new PolygonGeometry(dummyOptions);
  928. }
  929. result._polygonHierarchy = polygonHierarchy;
  930. result._ellipsoid = Matrix2.Ellipsoid.clone(ellipsoid, result._ellipsoid);
  931. result._vertexFormat = VertexFormat.VertexFormat.clone(vertexFormat, result._vertexFormat);
  932. result._height = height;
  933. result._extrudedHeight = extrudedHeight;
  934. result._granularity = granularity;
  935. result._stRotation = stRotation;
  936. result._perPositionHeightExtrude = perPositionHeightExtrude;
  937. result._perPositionHeight = perPositionHeight;
  938. result._closeTop = closeTop;
  939. result._closeBottom = closeBottom;
  940. result._shadowVolume = shadowVolume;
  941. result._offsetAttribute =
  942. offsetAttribute === -1 ? undefined : offsetAttribute;
  943. result._arcType = arcType;
  944. result._textureCoordinates = textureCoordinates;
  945. result.packedLength = packedLength;
  946. return result;
  947. };
  948. /**
  949. * Returns the bounding rectangle given the provided options
  950. *
  951. * @param {Object} options Object with the following properties:
  952. * @param {PolygonHierarchy} options.polygonHierarchy A polygon hierarchy that can include holes.
  953. * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions sampled.
  954. * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polygon edges must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.
  955. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.
  956. * @param {Rectangle} [result] An object in which to store the result.
  957. *
  958. * @returns {Rectangle} The result rectangle
  959. */
  960. PolygonGeometry.computeRectangle = function (options, result) {
  961. //>>includeStart('debug', pragmas.debug);
  962. RuntimeError.Check.typeOf.object("options", options);
  963. RuntimeError.Check.typeOf.object("options.polygonHierarchy", options.polygonHierarchy);
  964. //>>includeEnd('debug');
  965. const granularity = defaultValue.defaultValue(
  966. options.granularity,
  967. ComponentDatatype.CesiumMath.RADIANS_PER_DEGREE
  968. );
  969. const arcType = defaultValue.defaultValue(options.arcType, ArcType.ArcType.GEODESIC);
  970. //>>includeStart('debug', pragmas.debug);
  971. if (arcType !== ArcType.ArcType.GEODESIC && arcType !== ArcType.ArcType.RHUMB) {
  972. throw new RuntimeError.DeveloperError(
  973. "Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB."
  974. );
  975. }
  976. //>>includeEnd('debug');
  977. const polygonHierarchy = options.polygonHierarchy;
  978. const ellipsoid = defaultValue.defaultValue(options.ellipsoid, Matrix2.Ellipsoid.WGS84);
  979. return computeRectangle(
  980. polygonHierarchy.positions,
  981. ellipsoid,
  982. arcType,
  983. granularity,
  984. result
  985. );
  986. };
  987. /**
  988. * Computes the geometric representation of a polygon, including its vertices, indices, and a bounding sphere.
  989. *
  990. * @param {PolygonGeometry} polygonGeometry A description of the polygon.
  991. * @returns {Geometry|undefined} The computed vertices and indices.
  992. */
  993. PolygonGeometry.createGeometry = function (polygonGeometry) {
  994. const vertexFormat = polygonGeometry._vertexFormat;
  995. const ellipsoid = polygonGeometry._ellipsoid;
  996. const granularity = polygonGeometry._granularity;
  997. const stRotation = polygonGeometry._stRotation;
  998. const polygonHierarchy = polygonGeometry._polygonHierarchy;
  999. const perPositionHeight = polygonGeometry._perPositionHeight;
  1000. const closeTop = polygonGeometry._closeTop;
  1001. const closeBottom = polygonGeometry._closeBottom;
  1002. const arcType = polygonGeometry._arcType;
  1003. const textureCoordinates = polygonGeometry._textureCoordinates;
  1004. const hasTextureCoordinates = defaultValue.defined(textureCoordinates);
  1005. let outerPositions = polygonHierarchy.positions;
  1006. if (outerPositions.length < 3) {
  1007. return;
  1008. }
  1009. const tangentPlane = EllipsoidTangentPlane.EllipsoidTangentPlane.fromPoints(
  1010. outerPositions,
  1011. ellipsoid
  1012. );
  1013. const results = PolygonGeometryLibrary.PolygonGeometryLibrary.polygonsFromHierarchy(
  1014. polygonHierarchy,
  1015. hasTextureCoordinates,
  1016. tangentPlane.projectPointsOntoPlane.bind(tangentPlane),
  1017. !perPositionHeight,
  1018. ellipsoid
  1019. );
  1020. const hierarchy = results.hierarchy;
  1021. const polygons = results.polygons;
  1022. const dummyFunction = function (identity) {
  1023. return identity;
  1024. };
  1025. const textureCoordinatePolygons = hasTextureCoordinates
  1026. ? PolygonGeometryLibrary.PolygonGeometryLibrary.polygonsFromHierarchy(
  1027. textureCoordinates,
  1028. true,
  1029. dummyFunction,
  1030. false
  1031. ).polygons
  1032. : undefined;
  1033. if (hierarchy.length === 0) {
  1034. return;
  1035. }
  1036. outerPositions = hierarchy[0].outerRing;
  1037. const boundingRectangle = PolygonGeometryLibrary.PolygonGeometryLibrary.computeBoundingRectangle(
  1038. tangentPlane.plane.normal,
  1039. tangentPlane.projectPointOntoPlane.bind(tangentPlane),
  1040. outerPositions,
  1041. stRotation,
  1042. scratchBoundingRectangle
  1043. );
  1044. const geometries = [];
  1045. const height = polygonGeometry._height;
  1046. const extrudedHeight = polygonGeometry._extrudedHeight;
  1047. const extrude =
  1048. polygonGeometry._perPositionHeightExtrude ||
  1049. !ComponentDatatype.CesiumMath.equalsEpsilon(height, extrudedHeight, 0, ComponentDatatype.CesiumMath.EPSILON2);
  1050. const options = {
  1051. perPositionHeight: perPositionHeight,
  1052. vertexFormat: vertexFormat,
  1053. geometry: undefined,
  1054. tangentPlane: tangentPlane,
  1055. boundingRectangle: boundingRectangle,
  1056. ellipsoid: ellipsoid,
  1057. stRotation: stRotation,
  1058. textureCoordinates: undefined,
  1059. bottom: false,
  1060. top: true,
  1061. wall: false,
  1062. extrude: false,
  1063. arcType: arcType,
  1064. };
  1065. let i;
  1066. if (extrude) {
  1067. options.extrude = true;
  1068. options.top = closeTop;
  1069. options.bottom = closeBottom;
  1070. options.shadowVolume = polygonGeometry._shadowVolume;
  1071. options.offsetAttribute = polygonGeometry._offsetAttribute;
  1072. for (i = 0; i < polygons.length; i++) {
  1073. const splitGeometry = createGeometryFromPositionsExtruded(
  1074. ellipsoid,
  1075. polygons[i],
  1076. hasTextureCoordinates ? textureCoordinatePolygons[i] : undefined,
  1077. granularity,
  1078. hierarchy[i],
  1079. perPositionHeight,
  1080. closeTop,
  1081. closeBottom,
  1082. vertexFormat,
  1083. arcType
  1084. );
  1085. let topAndBottom;
  1086. if (closeTop && closeBottom) {
  1087. topAndBottom = splitGeometry.topAndBottom;
  1088. options.geometry = PolygonGeometryLibrary.PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(
  1089. topAndBottom.geometry,
  1090. height,
  1091. extrudedHeight,
  1092. ellipsoid,
  1093. perPositionHeight
  1094. );
  1095. } else if (closeTop) {
  1096. topAndBottom = splitGeometry.topAndBottom;
  1097. topAndBottom.geometry.attributes.position.values = PolygonPipeline.PolygonPipeline.scaleToGeodeticHeight(
  1098. topAndBottom.geometry.attributes.position.values,
  1099. height,
  1100. ellipsoid,
  1101. !perPositionHeight
  1102. );
  1103. options.geometry = topAndBottom.geometry;
  1104. } else if (closeBottom) {
  1105. topAndBottom = splitGeometry.topAndBottom;
  1106. topAndBottom.geometry.attributes.position.values = PolygonPipeline.PolygonPipeline.scaleToGeodeticHeight(
  1107. topAndBottom.geometry.attributes.position.values,
  1108. extrudedHeight,
  1109. ellipsoid,
  1110. true
  1111. );
  1112. options.geometry = topAndBottom.geometry;
  1113. }
  1114. if (closeTop || closeBottom) {
  1115. options.wall = false;
  1116. topAndBottom.geometry = computeAttributes(options);
  1117. geometries.push(topAndBottom);
  1118. }
  1119. const walls = splitGeometry.walls;
  1120. options.wall = true;
  1121. for (let k = 0; k < walls.length; k++) {
  1122. const wall = walls[k];
  1123. options.geometry = PolygonGeometryLibrary.PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(
  1124. wall.geometry,
  1125. height,
  1126. extrudedHeight,
  1127. ellipsoid,
  1128. perPositionHeight
  1129. );
  1130. wall.geometry = computeAttributes(options);
  1131. geometries.push(wall);
  1132. }
  1133. }
  1134. } else {
  1135. for (i = 0; i < polygons.length; i++) {
  1136. const geometryInstance = new GeometryInstance.GeometryInstance({
  1137. geometry: PolygonGeometryLibrary.PolygonGeometryLibrary.createGeometryFromPositions(
  1138. ellipsoid,
  1139. polygons[i],
  1140. hasTextureCoordinates ? textureCoordinatePolygons[i] : undefined,
  1141. granularity,
  1142. perPositionHeight,
  1143. vertexFormat,
  1144. arcType
  1145. ),
  1146. });
  1147. geometryInstance.geometry.attributes.position.values = PolygonPipeline.PolygonPipeline.scaleToGeodeticHeight(
  1148. geometryInstance.geometry.attributes.position.values,
  1149. height,
  1150. ellipsoid,
  1151. !perPositionHeight
  1152. );
  1153. options.geometry = geometryInstance.geometry;
  1154. geometryInstance.geometry = computeAttributes(options);
  1155. if (defaultValue.defined(polygonGeometry._offsetAttribute)) {
  1156. const length =
  1157. geometryInstance.geometry.attributes.position.values.length;
  1158. const applyOffset = new Uint8Array(length / 3);
  1159. const offsetValue =
  1160. polygonGeometry._offsetAttribute === GeometryOffsetAttribute.GeometryOffsetAttribute.NONE
  1161. ? 0
  1162. : 1;
  1163. GeometryOffsetAttribute.arrayFill(applyOffset, offsetValue);
  1164. geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute.GeometryAttribute(
  1165. {
  1166. componentDatatype: ComponentDatatype.ComponentDatatype.UNSIGNED_BYTE,
  1167. componentsPerAttribute: 1,
  1168. values: applyOffset,
  1169. }
  1170. );
  1171. }
  1172. geometries.push(geometryInstance);
  1173. }
  1174. }
  1175. const geometry = GeometryPipeline.GeometryPipeline.combineInstances(geometries)[0];
  1176. geometry.attributes.position.values = new Float64Array(
  1177. geometry.attributes.position.values
  1178. );
  1179. geometry.indices = IndexDatatype.IndexDatatype.createTypedArray(
  1180. geometry.attributes.position.values.length / 3,
  1181. geometry.indices
  1182. );
  1183. const attributes = geometry.attributes;
  1184. const boundingSphere = Transforms.BoundingSphere.fromVertices(
  1185. attributes.position.values
  1186. );
  1187. if (!vertexFormat.position) {
  1188. delete attributes.position;
  1189. }
  1190. return new GeometryAttribute.Geometry({
  1191. attributes: attributes,
  1192. indices: geometry.indices,
  1193. primitiveType: geometry.primitiveType,
  1194. boundingSphere: boundingSphere,
  1195. offsetAttribute: polygonGeometry._offsetAttribute,
  1196. });
  1197. };
  1198. /**
  1199. * @private
  1200. */
  1201. PolygonGeometry.createShadowVolume = function (
  1202. polygonGeometry,
  1203. minHeightFunc,
  1204. maxHeightFunc
  1205. ) {
  1206. const granularity = polygonGeometry._granularity;
  1207. const ellipsoid = polygonGeometry._ellipsoid;
  1208. const minHeight = minHeightFunc(granularity, ellipsoid);
  1209. const maxHeight = maxHeightFunc(granularity, ellipsoid);
  1210. return new PolygonGeometry({
  1211. polygonHierarchy: polygonGeometry._polygonHierarchy,
  1212. ellipsoid: ellipsoid,
  1213. stRotation: polygonGeometry._stRotation,
  1214. granularity: granularity,
  1215. perPositionHeight: false,
  1216. extrudedHeight: minHeight,
  1217. height: maxHeight,
  1218. vertexFormat: VertexFormat.VertexFormat.POSITION_ONLY,
  1219. shadowVolume: true,
  1220. arcType: polygonGeometry._arcType,
  1221. });
  1222. };
  1223. function textureCoordinateRotationPoints(polygonGeometry) {
  1224. const stRotation = -polygonGeometry._stRotation;
  1225. if (stRotation === 0.0) {
  1226. return [0, 0, 0, 1, 1, 0];
  1227. }
  1228. const ellipsoid = polygonGeometry._ellipsoid;
  1229. const positions = polygonGeometry._polygonHierarchy.positions;
  1230. const boundingRectangle = polygonGeometry.rectangle;
  1231. return GeometryAttribute.Geometry._textureCoordinateRotationPoints(
  1232. positions,
  1233. stRotation,
  1234. ellipsoid,
  1235. boundingRectangle
  1236. );
  1237. }
  1238. Object.defineProperties(PolygonGeometry.prototype, {
  1239. /**
  1240. * @private
  1241. */
  1242. rectangle: {
  1243. get: function () {
  1244. if (!defaultValue.defined(this._rectangle)) {
  1245. const positions = this._polygonHierarchy.positions;
  1246. this._rectangle = computeRectangle(
  1247. positions,
  1248. this._ellipsoid,
  1249. this._arcType,
  1250. this._granularity
  1251. );
  1252. }
  1253. return this._rectangle;
  1254. },
  1255. },
  1256. /**
  1257. * For remapping texture coordinates when rendering PolygonGeometries as GroundPrimitives.
  1258. * @private
  1259. */
  1260. textureCoordinateRotationPoints: {
  1261. get: function () {
  1262. if (!defaultValue.defined(this._textureCoordinateRotationPoints)) {
  1263. this._textureCoordinateRotationPoints = textureCoordinateRotationPoints(
  1264. this
  1265. );
  1266. }
  1267. return this._textureCoordinateRotationPoints;
  1268. },
  1269. },
  1270. });
  1271. function createPolygonGeometry(polygonGeometry, offset) {
  1272. if (defaultValue.defined(offset)) {
  1273. polygonGeometry = PolygonGeometry.unpack(polygonGeometry, offset);
  1274. }
  1275. polygonGeometry._ellipsoid = Matrix2.Ellipsoid.clone(polygonGeometry._ellipsoid);
  1276. return PolygonGeometry.createGeometry(polygonGeometry);
  1277. }
  1278. return createPolygonGeometry;
  1279. }));