PolygonOutlineGeometry.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. import ArcType from "./ArcType.js";
  2. import arrayFill from "./arrayFill.js";
  3. import BoundingSphere from "./BoundingSphere.js";
  4. import Check from "./Check.js";
  5. import ComponentDatatype from "./ComponentDatatype.js";
  6. import defaultValue from "./defaultValue.js";
  7. import defined from "./defined.js";
  8. import DeveloperError from "./DeveloperError.js";
  9. import Ellipsoid from "./Ellipsoid.js";
  10. import EllipsoidTangentPlane from "./EllipsoidTangentPlane.js";
  11. import Geometry from "./Geometry.js";
  12. import GeometryAttribute from "./GeometryAttribute.js";
  13. import GeometryAttributes from "./GeometryAttributes.js";
  14. import GeometryInstance from "./GeometryInstance.js";
  15. import GeometryOffsetAttribute from "./GeometryOffsetAttribute.js";
  16. import GeometryPipeline from "./GeometryPipeline.js";
  17. import IndexDatatype from "./IndexDatatype.js";
  18. import CesiumMath from "./Math.js";
  19. import PolygonGeometryLibrary from "./PolygonGeometryLibrary.js";
  20. import PolygonPipeline from "./PolygonPipeline.js";
  21. import PrimitiveType from "./PrimitiveType.js";
  22. import WindingOrder from "./WindingOrder.js";
  23. const createGeometryFromPositionsPositions = [];
  24. const createGeometryFromPositionsSubdivided = [];
  25. function createGeometryFromPositions(
  26. ellipsoid,
  27. positions,
  28. minDistance,
  29. perPositionHeight,
  30. arcType
  31. ) {
  32. const tangentPlane = EllipsoidTangentPlane.fromPoints(positions, ellipsoid);
  33. const positions2D = tangentPlane.projectPointsOntoPlane(
  34. positions,
  35. createGeometryFromPositionsPositions
  36. );
  37. const originalWindingOrder = PolygonPipeline.computeWindingOrder2D(
  38. positions2D
  39. );
  40. if (originalWindingOrder === WindingOrder.CLOCKWISE) {
  41. positions2D.reverse();
  42. positions = positions.slice().reverse();
  43. }
  44. let subdividedPositions;
  45. let i;
  46. let length = positions.length;
  47. let index = 0;
  48. if (!perPositionHeight) {
  49. let numVertices = 0;
  50. if (arcType === ArcType.GEODESIC) {
  51. for (i = 0; i < length; i++) {
  52. numVertices += PolygonGeometryLibrary.subdivideLineCount(
  53. positions[i],
  54. positions[(i + 1) % length],
  55. minDistance
  56. );
  57. }
  58. } else if (arcType === ArcType.RHUMB) {
  59. for (i = 0; i < length; i++) {
  60. numVertices += PolygonGeometryLibrary.subdivideRhumbLineCount(
  61. ellipsoid,
  62. positions[i],
  63. positions[(i + 1) % length],
  64. minDistance
  65. );
  66. }
  67. }
  68. subdividedPositions = new Float64Array(numVertices * 3);
  69. for (i = 0; i < length; i++) {
  70. let tempPositions;
  71. if (arcType === ArcType.GEODESIC) {
  72. tempPositions = PolygonGeometryLibrary.subdivideLine(
  73. positions[i],
  74. positions[(i + 1) % length],
  75. minDistance,
  76. createGeometryFromPositionsSubdivided
  77. );
  78. } else if (arcType === ArcType.RHUMB) {
  79. tempPositions = PolygonGeometryLibrary.subdivideRhumbLine(
  80. ellipsoid,
  81. positions[i],
  82. positions[(i + 1) % length],
  83. minDistance,
  84. createGeometryFromPositionsSubdivided
  85. );
  86. }
  87. const tempPositionsLength = tempPositions.length;
  88. for (let j = 0; j < tempPositionsLength; ++j) {
  89. subdividedPositions[index++] = tempPositions[j];
  90. }
  91. }
  92. } else {
  93. subdividedPositions = new Float64Array(length * 2 * 3);
  94. for (i = 0; i < length; i++) {
  95. const p0 = positions[i];
  96. const p1 = positions[(i + 1) % length];
  97. subdividedPositions[index++] = p0.x;
  98. subdividedPositions[index++] = p0.y;
  99. subdividedPositions[index++] = p0.z;
  100. subdividedPositions[index++] = p1.x;
  101. subdividedPositions[index++] = p1.y;
  102. subdividedPositions[index++] = p1.z;
  103. }
  104. }
  105. length = subdividedPositions.length / 3;
  106. const indicesSize = length * 2;
  107. const indices = IndexDatatype.createTypedArray(length, indicesSize);
  108. index = 0;
  109. for (i = 0; i < length - 1; i++) {
  110. indices[index++] = i;
  111. indices[index++] = i + 1;
  112. }
  113. indices[index++] = length - 1;
  114. indices[index++] = 0;
  115. return new GeometryInstance({
  116. geometry: new Geometry({
  117. attributes: new GeometryAttributes({
  118. position: new GeometryAttribute({
  119. componentDatatype: ComponentDatatype.DOUBLE,
  120. componentsPerAttribute: 3,
  121. values: subdividedPositions,
  122. }),
  123. }),
  124. indices: indices,
  125. primitiveType: PrimitiveType.LINES,
  126. }),
  127. });
  128. }
  129. function createGeometryFromPositionsExtruded(
  130. ellipsoid,
  131. positions,
  132. minDistance,
  133. perPositionHeight,
  134. arcType
  135. ) {
  136. const tangentPlane = EllipsoidTangentPlane.fromPoints(positions, ellipsoid);
  137. const positions2D = tangentPlane.projectPointsOntoPlane(
  138. positions,
  139. createGeometryFromPositionsPositions
  140. );
  141. const originalWindingOrder = PolygonPipeline.computeWindingOrder2D(
  142. positions2D
  143. );
  144. if (originalWindingOrder === WindingOrder.CLOCKWISE) {
  145. positions2D.reverse();
  146. positions = positions.slice().reverse();
  147. }
  148. let subdividedPositions;
  149. let i;
  150. let length = positions.length;
  151. const corners = new Array(length);
  152. let index = 0;
  153. if (!perPositionHeight) {
  154. let numVertices = 0;
  155. if (arcType === ArcType.GEODESIC) {
  156. for (i = 0; i < length; i++) {
  157. numVertices += PolygonGeometryLibrary.subdivideLineCount(
  158. positions[i],
  159. positions[(i + 1) % length],
  160. minDistance
  161. );
  162. }
  163. } else if (arcType === ArcType.RHUMB) {
  164. for (i = 0; i < length; i++) {
  165. numVertices += PolygonGeometryLibrary.subdivideRhumbLineCount(
  166. ellipsoid,
  167. positions[i],
  168. positions[(i + 1) % length],
  169. minDistance
  170. );
  171. }
  172. }
  173. subdividedPositions = new Float64Array(numVertices * 3 * 2);
  174. for (i = 0; i < length; ++i) {
  175. corners[i] = index / 3;
  176. let tempPositions;
  177. if (arcType === ArcType.GEODESIC) {
  178. tempPositions = PolygonGeometryLibrary.subdivideLine(
  179. positions[i],
  180. positions[(i + 1) % length],
  181. minDistance,
  182. createGeometryFromPositionsSubdivided
  183. );
  184. } else if (arcType === ArcType.RHUMB) {
  185. tempPositions = PolygonGeometryLibrary.subdivideRhumbLine(
  186. ellipsoid,
  187. positions[i],
  188. positions[(i + 1) % length],
  189. minDistance,
  190. createGeometryFromPositionsSubdivided
  191. );
  192. }
  193. const tempPositionsLength = tempPositions.length;
  194. for (let j = 0; j < tempPositionsLength; ++j) {
  195. subdividedPositions[index++] = tempPositions[j];
  196. }
  197. }
  198. } else {
  199. subdividedPositions = new Float64Array(length * 2 * 3 * 2);
  200. for (i = 0; i < length; ++i) {
  201. corners[i] = index / 3;
  202. const p0 = positions[i];
  203. const p1 = positions[(i + 1) % length];
  204. subdividedPositions[index++] = p0.x;
  205. subdividedPositions[index++] = p0.y;
  206. subdividedPositions[index++] = p0.z;
  207. subdividedPositions[index++] = p1.x;
  208. subdividedPositions[index++] = p1.y;
  209. subdividedPositions[index++] = p1.z;
  210. }
  211. }
  212. length = subdividedPositions.length / (3 * 2);
  213. const cornersLength = corners.length;
  214. const indicesSize = (length * 2 + cornersLength) * 2;
  215. const indices = IndexDatatype.createTypedArray(
  216. length + cornersLength,
  217. indicesSize
  218. );
  219. index = 0;
  220. for (i = 0; i < length; ++i) {
  221. indices[index++] = i;
  222. indices[index++] = (i + 1) % length;
  223. indices[index++] = i + length;
  224. indices[index++] = ((i + 1) % length) + length;
  225. }
  226. for (i = 0; i < cornersLength; i++) {
  227. const corner = corners[i];
  228. indices[index++] = corner;
  229. indices[index++] = corner + length;
  230. }
  231. return new GeometryInstance({
  232. geometry: new Geometry({
  233. attributes: new GeometryAttributes({
  234. position: new GeometryAttribute({
  235. componentDatatype: ComponentDatatype.DOUBLE,
  236. componentsPerAttribute: 3,
  237. values: subdividedPositions,
  238. }),
  239. }),
  240. indices: indices,
  241. primitiveType: PrimitiveType.LINES,
  242. }),
  243. });
  244. }
  245. /**
  246. * A description of the outline of a polygon on the ellipsoid. The polygon is defined by a polygon hierarchy.
  247. *
  248. * @alias PolygonOutlineGeometry
  249. * @constructor
  250. *
  251. * @param {Object} options Object with the following properties:
  252. * @param {PolygonHierarchy} options.polygonHierarchy A polygon hierarchy that can include holes.
  253. * @param {Number} [options.height=0.0] The distance in meters between the polygon and the ellipsoid surface.
  254. * @param {Number} [options.extrudedHeight] The distance in meters between the polygon's extruded face and the ellipsoid surface.
  255. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.
  256. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.
  257. * @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.
  258. * @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.
  259. * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of path the outline must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.
  260. *
  261. * @see PolygonOutlineGeometry#createGeometry
  262. * @see PolygonOutlineGeometry#fromPositions
  263. *
  264. * @example
  265. * // 1. create a polygon outline from points
  266. * const polygon = new Cesium.PolygonOutlineGeometry({
  267. * polygonHierarchy : new Cesium.PolygonHierarchy(
  268. * Cesium.Cartesian3.fromDegreesArray([
  269. * -72.0, 40.0,
  270. * -70.0, 35.0,
  271. * -75.0, 30.0,
  272. * -70.0, 30.0,
  273. * -68.0, 40.0
  274. * ])
  275. * )
  276. * });
  277. * const geometry = Cesium.PolygonOutlineGeometry.createGeometry(polygon);
  278. *
  279. * // 2. create a nested polygon with holes outline
  280. * const polygonWithHole = new Cesium.PolygonOutlineGeometry({
  281. * polygonHierarchy : new Cesium.PolygonHierarchy(
  282. * Cesium.Cartesian3.fromDegreesArray([
  283. * -109.0, 30.0,
  284. * -95.0, 30.0,
  285. * -95.0, 40.0,
  286. * -109.0, 40.0
  287. * ]),
  288. * [new Cesium.PolygonHierarchy(
  289. * Cesium.Cartesian3.fromDegreesArray([
  290. * -107.0, 31.0,
  291. * -107.0, 39.0,
  292. * -97.0, 39.0,
  293. * -97.0, 31.0
  294. * ]),
  295. * [new Cesium.PolygonHierarchy(
  296. * Cesium.Cartesian3.fromDegreesArray([
  297. * -105.0, 33.0,
  298. * -99.0, 33.0,
  299. * -99.0, 37.0,
  300. * -105.0, 37.0
  301. * ]),
  302. * [new Cesium.PolygonHierarchy(
  303. * Cesium.Cartesian3.fromDegreesArray([
  304. * -103.0, 34.0,
  305. * -101.0, 34.0,
  306. * -101.0, 36.0,
  307. * -103.0, 36.0
  308. * ])
  309. * )]
  310. * )]
  311. * )]
  312. * )
  313. * });
  314. * const geometry = Cesium.PolygonOutlineGeometry.createGeometry(polygonWithHole);
  315. *
  316. * // 3. create extruded polygon outline
  317. * const extrudedPolygon = new Cesium.PolygonOutlineGeometry({
  318. * polygonHierarchy : new Cesium.PolygonHierarchy(
  319. * Cesium.Cartesian3.fromDegreesArray([
  320. * -72.0, 40.0,
  321. * -70.0, 35.0,
  322. * -75.0, 30.0,
  323. * -70.0, 30.0,
  324. * -68.0, 40.0
  325. * ])
  326. * ),
  327. * extrudedHeight: 300000
  328. * });
  329. * const geometry = Cesium.PolygonOutlineGeometry.createGeometry(extrudedPolygon);
  330. */
  331. function PolygonOutlineGeometry(options) {
  332. //>>includeStart('debug', pragmas.debug);
  333. Check.typeOf.object("options", options);
  334. Check.typeOf.object("options.polygonHierarchy", options.polygonHierarchy);
  335. if (options.perPositionHeight && defined(options.height)) {
  336. throw new DeveloperError(
  337. "Cannot use both options.perPositionHeight and options.height"
  338. );
  339. }
  340. if (
  341. defined(options.arcType) &&
  342. options.arcType !== ArcType.GEODESIC &&
  343. options.arcType !== ArcType.RHUMB
  344. ) {
  345. throw new DeveloperError(
  346. "Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB."
  347. );
  348. }
  349. //>>includeEnd('debug');
  350. const polygonHierarchy = options.polygonHierarchy;
  351. const ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);
  352. const granularity = defaultValue(
  353. options.granularity,
  354. CesiumMath.RADIANS_PER_DEGREE
  355. );
  356. const perPositionHeight = defaultValue(options.perPositionHeight, false);
  357. const perPositionHeightExtrude =
  358. perPositionHeight && defined(options.extrudedHeight);
  359. const arcType = defaultValue(options.arcType, ArcType.GEODESIC);
  360. let height = defaultValue(options.height, 0.0);
  361. let extrudedHeight = defaultValue(options.extrudedHeight, height);
  362. if (!perPositionHeightExtrude) {
  363. const h = Math.max(height, extrudedHeight);
  364. extrudedHeight = Math.min(height, extrudedHeight);
  365. height = h;
  366. }
  367. this._ellipsoid = Ellipsoid.clone(ellipsoid);
  368. this._granularity = granularity;
  369. this._height = height;
  370. this._extrudedHeight = extrudedHeight;
  371. this._arcType = arcType;
  372. this._polygonHierarchy = polygonHierarchy;
  373. this._perPositionHeight = perPositionHeight;
  374. this._perPositionHeightExtrude = perPositionHeightExtrude;
  375. this._offsetAttribute = options.offsetAttribute;
  376. this._workerName = "createPolygonOutlineGeometry";
  377. /**
  378. * The number of elements used to pack the object into an array.
  379. * @type {Number}
  380. */
  381. this.packedLength =
  382. PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) +
  383. Ellipsoid.packedLength +
  384. 8;
  385. }
  386. /**
  387. * Stores the provided instance into the provided array.
  388. *
  389. * @param {PolygonOutlineGeometry} value The value to pack.
  390. * @param {Number[]} array The array to pack into.
  391. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
  392. *
  393. * @returns {Number[]} The array that was packed into
  394. */
  395. PolygonOutlineGeometry.pack = function (value, array, startingIndex) {
  396. //>>includeStart('debug', pragmas.debug);
  397. Check.typeOf.object("value", value);
  398. Check.defined("array", array);
  399. //>>includeEnd('debug');
  400. startingIndex = defaultValue(startingIndex, 0);
  401. startingIndex = PolygonGeometryLibrary.packPolygonHierarchy(
  402. value._polygonHierarchy,
  403. array,
  404. startingIndex
  405. );
  406. Ellipsoid.pack(value._ellipsoid, array, startingIndex);
  407. startingIndex += Ellipsoid.packedLength;
  408. array[startingIndex++] = value._height;
  409. array[startingIndex++] = value._extrudedHeight;
  410. array[startingIndex++] = value._granularity;
  411. array[startingIndex++] = value._perPositionHeightExtrude ? 1.0 : 0.0;
  412. array[startingIndex++] = value._perPositionHeight ? 1.0 : 0.0;
  413. array[startingIndex++] = value._arcType;
  414. array[startingIndex++] = defaultValue(value._offsetAttribute, -1);
  415. array[startingIndex] = value.packedLength;
  416. return array;
  417. };
  418. const scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);
  419. const dummyOptions = {
  420. polygonHierarchy: {},
  421. };
  422. /**
  423. * Retrieves an instance from a packed array.
  424. *
  425. * @param {Number[]} array The packed array.
  426. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
  427. * @param {PolygonOutlineGeometry} [result] The object into which to store the result.
  428. * @returns {PolygonOutlineGeometry} The modified result parameter or a new PolygonOutlineGeometry instance if one was not provided.
  429. */
  430. PolygonOutlineGeometry.unpack = function (array, startingIndex, result) {
  431. //>>includeStart('debug', pragmas.debug);
  432. Check.defined("array", array);
  433. //>>includeEnd('debug');
  434. startingIndex = defaultValue(startingIndex, 0);
  435. const polygonHierarchy = PolygonGeometryLibrary.unpackPolygonHierarchy(
  436. array,
  437. startingIndex
  438. );
  439. startingIndex = polygonHierarchy.startingIndex;
  440. delete polygonHierarchy.startingIndex;
  441. const ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);
  442. startingIndex += Ellipsoid.packedLength;
  443. const height = array[startingIndex++];
  444. const extrudedHeight = array[startingIndex++];
  445. const granularity = array[startingIndex++];
  446. const perPositionHeightExtrude = array[startingIndex++] === 1.0;
  447. const perPositionHeight = array[startingIndex++] === 1.0;
  448. const arcType = array[startingIndex++];
  449. const offsetAttribute = array[startingIndex++];
  450. const packedLength = array[startingIndex];
  451. if (!defined(result)) {
  452. result = new PolygonOutlineGeometry(dummyOptions);
  453. }
  454. result._polygonHierarchy = polygonHierarchy;
  455. result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);
  456. result._height = height;
  457. result._extrudedHeight = extrudedHeight;
  458. result._granularity = granularity;
  459. result._perPositionHeight = perPositionHeight;
  460. result._perPositionHeightExtrude = perPositionHeightExtrude;
  461. result._arcType = arcType;
  462. result._offsetAttribute =
  463. offsetAttribute === -1 ? undefined : offsetAttribute;
  464. result.packedLength = packedLength;
  465. return result;
  466. };
  467. /**
  468. * A description of a polygon outline from an array of positions.
  469. *
  470. * @param {Object} options Object with the following properties:
  471. * @param {Cartesian3[]} options.positions An array of positions that defined the corner points of the polygon.
  472. * @param {Number} [options.height=0.0] The height of the polygon.
  473. * @param {Number} [options.extrudedHeight] The height of the polygon extrusion.
  474. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.
  475. * @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.
  476. * @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.
  477. * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of path the outline must follow. Valid options are {@link LinkType.GEODESIC} and {@link ArcType.RHUMB}.
  478. * @returns {PolygonOutlineGeometry}
  479. *
  480. *
  481. * @example
  482. * // create a polygon from points
  483. * const polygon = Cesium.PolygonOutlineGeometry.fromPositions({
  484. * positions : Cesium.Cartesian3.fromDegreesArray([
  485. * -72.0, 40.0,
  486. * -70.0, 35.0,
  487. * -75.0, 30.0,
  488. * -70.0, 30.0,
  489. * -68.0, 40.0
  490. * ])
  491. * });
  492. * const geometry = Cesium.PolygonOutlineGeometry.createGeometry(polygon);
  493. *
  494. * @see PolygonOutlineGeometry#createGeometry
  495. */
  496. PolygonOutlineGeometry.fromPositions = function (options) {
  497. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  498. //>>includeStart('debug', pragmas.debug);
  499. Check.defined("options.positions", options.positions);
  500. //>>includeEnd('debug');
  501. const newOptions = {
  502. polygonHierarchy: {
  503. positions: options.positions,
  504. },
  505. height: options.height,
  506. extrudedHeight: options.extrudedHeight,
  507. ellipsoid: options.ellipsoid,
  508. granularity: options.granularity,
  509. perPositionHeight: options.perPositionHeight,
  510. arcType: options.arcType,
  511. offsetAttribute: options.offsetAttribute,
  512. };
  513. return new PolygonOutlineGeometry(newOptions);
  514. };
  515. /**
  516. * Computes the geometric representation of a polygon outline, including its vertices, indices, and a bounding sphere.
  517. *
  518. * @param {PolygonOutlineGeometry} polygonGeometry A description of the polygon outline.
  519. * @returns {Geometry|undefined} The computed vertices and indices.
  520. */
  521. PolygonOutlineGeometry.createGeometry = function (polygonGeometry) {
  522. const ellipsoid = polygonGeometry._ellipsoid;
  523. const granularity = polygonGeometry._granularity;
  524. const polygonHierarchy = polygonGeometry._polygonHierarchy;
  525. const perPositionHeight = polygonGeometry._perPositionHeight;
  526. const arcType = polygonGeometry._arcType;
  527. const polygons = PolygonGeometryLibrary.polygonOutlinesFromHierarchy(
  528. polygonHierarchy,
  529. !perPositionHeight,
  530. ellipsoid
  531. );
  532. if (polygons.length === 0) {
  533. return undefined;
  534. }
  535. let geometryInstance;
  536. const geometries = [];
  537. const minDistance = CesiumMath.chordLength(
  538. granularity,
  539. ellipsoid.maximumRadius
  540. );
  541. const height = polygonGeometry._height;
  542. const extrudedHeight = polygonGeometry._extrudedHeight;
  543. const extrude =
  544. polygonGeometry._perPositionHeightExtrude ||
  545. !CesiumMath.equalsEpsilon(height, extrudedHeight, 0, CesiumMath.EPSILON2);
  546. let offsetValue;
  547. let i;
  548. if (extrude) {
  549. for (i = 0; i < polygons.length; i++) {
  550. geometryInstance = createGeometryFromPositionsExtruded(
  551. ellipsoid,
  552. polygons[i],
  553. minDistance,
  554. perPositionHeight,
  555. arcType
  556. );
  557. geometryInstance.geometry = PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(
  558. geometryInstance.geometry,
  559. height,
  560. extrudedHeight,
  561. ellipsoid,
  562. perPositionHeight
  563. );
  564. if (defined(polygonGeometry._offsetAttribute)) {
  565. const size =
  566. geometryInstance.geometry.attributes.position.values.length / 3;
  567. let offsetAttribute = new Uint8Array(size);
  568. if (polygonGeometry._offsetAttribute === GeometryOffsetAttribute.TOP) {
  569. offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);
  570. } else {
  571. offsetValue =
  572. polygonGeometry._offsetAttribute === GeometryOffsetAttribute.NONE
  573. ? 0
  574. : 1;
  575. offsetAttribute = arrayFill(offsetAttribute, offsetValue);
  576. }
  577. geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute(
  578. {
  579. componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
  580. componentsPerAttribute: 1,
  581. values: offsetAttribute,
  582. }
  583. );
  584. }
  585. geometries.push(geometryInstance);
  586. }
  587. } else {
  588. for (i = 0; i < polygons.length; i++) {
  589. geometryInstance = createGeometryFromPositions(
  590. ellipsoid,
  591. polygons[i],
  592. minDistance,
  593. perPositionHeight,
  594. arcType
  595. );
  596. geometryInstance.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(
  597. geometryInstance.geometry.attributes.position.values,
  598. height,
  599. ellipsoid,
  600. !perPositionHeight
  601. );
  602. if (defined(polygonGeometry._offsetAttribute)) {
  603. const length =
  604. geometryInstance.geometry.attributes.position.values.length;
  605. const applyOffset = new Uint8Array(length / 3);
  606. offsetValue =
  607. polygonGeometry._offsetAttribute === GeometryOffsetAttribute.NONE
  608. ? 0
  609. : 1;
  610. arrayFill(applyOffset, offsetValue);
  611. geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute(
  612. {
  613. componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
  614. componentsPerAttribute: 1,
  615. values: applyOffset,
  616. }
  617. );
  618. }
  619. geometries.push(geometryInstance);
  620. }
  621. }
  622. const geometry = GeometryPipeline.combineInstances(geometries)[0];
  623. const boundingSphere = BoundingSphere.fromVertices(
  624. geometry.attributes.position.values
  625. );
  626. return new Geometry({
  627. attributes: geometry.attributes,
  628. indices: geometry.indices,
  629. primitiveType: geometry.primitiveType,
  630. boundingSphere: boundingSphere,
  631. offsetAttribute: polygonGeometry._offsetAttribute,
  632. });
  633. };
  634. export default PolygonOutlineGeometry;