createPolygonGeometry.js 52 KB

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