createPolygonGeometry.js 50 KB

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