createPolygonGeometry.js 50 KB

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