PolygonGeometry.js 44 KB

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