智慧水务管理系统 - 精河县供水工程综合管理平台

PropertyTable.js 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. import Check from "../Core/Check.js";
  2. import Frozen from "../Core/Frozen.js";
  3. import DeveloperError from "../Core/DeveloperError.js";
  4. import defined from "../Core/defined.js";
  5. import JsonMetadataTable from "./JsonMetadataTable.js";
  6. import addAllToArray from "../Core/addAllToArray.js";
  7. import { destroyObject } from "@cesium/engine";
  8. /**
  9. * A property table for use with the <code>EXT_structural_metadata</code> extension or
  10. * legacy <code>EXT_feature_metadata</code> glTF extension. It also includes some
  11. * options to be compatible with the 3D Tiles 1.0 batch table.
  12. * <p>
  13. * For batch tables, properties are resolved in the following order:
  14. * </p>
  15. * <ol>
  16. * <li>binary properties from options.metadataTable</li>
  17. * <li>JSON properties from options.jsonMetadataTable</li>
  18. * <li>batch table hierarchy properties from options.batchTableHierarchy</li>
  19. * </ol>
  20. * <p>
  21. * See the {@link https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata|EXT_structural_metadata Extension} as well as the
  22. * previous {@link https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_feature_metadata|EXT_feature_metadata Extension} for glTF.
  23. * </p>
  24. *
  25. * @param {object} options Object with the following properties:
  26. * @param {string} [options.name] Human-readable name to describe the table
  27. * @param {string|number} [options.id] A unique id to identify the property table, useful for debugging. For <code>EXT_structural_metadata</code>, this is the array index in the property tables array, for <code>EXT_feature_metadata</code> this is the dictionary key in the property tables dictionary.
  28. * @param {number} options.count The number of features in the table.
  29. * @param {MetadataTable} [options.metadataTable] A table of binary properties.
  30. * @param {JsonMetadataTable} [options.jsonMetadataTable] For compatibility with the old batch table, free-form JSON properties can be passed in.
  31. * @param {BatchTableHierarchy} [options.batchTableHierarchy] For compatibility with the <code>3DTILES_batch_table_hierarchy</code> extension, a hierarchy can be provided.
  32. * @param {object} [options.extras] Extra user-defined properties
  33. * @param {object} [options.extensions] An object containing extensions
  34. *
  35. * @alias PropertyTable
  36. * @constructor
  37. *
  38. * @private
  39. * @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
  40. */
  41. function PropertyTable(options) {
  42. options = options ?? Frozen.EMPTY_OBJECT;
  43. //>>includeStart('debug', pragmas.debug);
  44. Check.typeOf.number("options.count", options.count);
  45. //>>includeEnd('debug');
  46. this._name = options.name;
  47. this._id = options.id;
  48. this._count = options.count;
  49. this._extras = options.extras;
  50. this._extensions = options.extensions;
  51. this._metadataTable = options.metadataTable;
  52. this._jsonMetadataTable = options.jsonMetadataTable;
  53. this._batchTableHierarchy = options.batchTableHierarchy;
  54. this._texture = options.texture; // Property table buffer data packed into a GPU texture
  55. }
  56. Object.defineProperties(PropertyTable.prototype, {
  57. /**
  58. * A human-readable name for this table
  59. *
  60. * @memberof PropertyTable.prototype
  61. * @type {string}
  62. * @readonly
  63. * @private
  64. */
  65. name: {
  66. get: function () {
  67. return this._name;
  68. },
  69. },
  70. /**
  71. * An identifier for this table. Useful for debugging.
  72. *
  73. * @memberof PropertyTable.prototype
  74. * @type {string|number}
  75. * @readonly
  76. * @private
  77. */
  78. id: {
  79. get: function () {
  80. return this._id;
  81. },
  82. },
  83. /**
  84. * The number of features in the table.
  85. *
  86. * @memberof PropertyTable.prototype
  87. * @type {number}
  88. * @readonly
  89. * @private
  90. */
  91. count: {
  92. get: function () {
  93. return this._count;
  94. },
  95. },
  96. /**
  97. * The class that properties conform to.
  98. *
  99. * @memberof PropertyTable.prototype
  100. * @type {MetadataClass}
  101. * @readonly
  102. */
  103. class: {
  104. get: function () {
  105. if (defined(this._metadataTable)) {
  106. return this._metadataTable.class;
  107. }
  108. return undefined;
  109. },
  110. },
  111. /**
  112. * The properties stored in this table.
  113. *
  114. * @memberof PropertyTable.prototype
  115. * @type {Object<string, MetadataTableProperty>}
  116. * @readonly
  117. */
  118. properties: {
  119. get: function () {
  120. if (defined(this._metadataTable)) {
  121. return this._metadataTable.properties;
  122. }
  123. return undefined;
  124. },
  125. },
  126. /**
  127. * Extra user-defined properties.
  128. *
  129. * @memberof PropertyTable.prototype
  130. * @type {*}
  131. * @readonly
  132. * @private
  133. */
  134. extras: {
  135. get: function () {
  136. return this._extras;
  137. },
  138. },
  139. /**
  140. * An object containing extensions.
  141. *
  142. * @memberof PropertyTable.prototype
  143. * @type {object}
  144. * @readonly
  145. * @private
  146. */
  147. extensions: {
  148. get: function () {
  149. return this._extensions;
  150. },
  151. },
  152. /**
  153. * Get the total amount of binary metadata stored in memory. This does
  154. * not include JSON metadata
  155. *
  156. * @memberof PropertyTable.prototype
  157. * @type {number}
  158. * @readonly
  159. * @private
  160. */
  161. byteLength: {
  162. get: function () {
  163. let totalByteLength = 0;
  164. if (defined(this._metadataTable)) {
  165. totalByteLength += this._metadataTable.byteLength;
  166. }
  167. if (defined(this._batchTableHierarchy)) {
  168. totalByteLength += this._batchTableHierarchy.byteLength;
  169. }
  170. return totalByteLength;
  171. },
  172. },
  173. /**
  174. * The texture containing the property table data, if any.
  175. *
  176. * @memberof PropertyTable.prototype
  177. * @type {Texture | undefined}
  178. * @readonly
  179. * @private
  180. */
  181. texture: {
  182. get: function () {
  183. return this._texture;
  184. },
  185. },
  186. });
  187. /**
  188. * Returns whether the feature has this property. For compatibility with the <code>3DTILES_batch_table_hierarchy</code> extension, this is computed for a specific feature.
  189. *
  190. * @param {number} index The index of the feature.
  191. * @param {string} propertyId The case-sensitive ID of the property.
  192. * @returns {boolean} Whether the feature has this property.
  193. * @private
  194. */
  195. PropertyTable.prototype.hasProperty = function (index, propertyId) {
  196. //>>includeStart('debug', pragmas.debug);
  197. Check.typeOf.number("index", index);
  198. Check.typeOf.string("propertyId", propertyId);
  199. //>>includeEnd('debug');
  200. if (
  201. defined(this._metadataTable) &&
  202. this._metadataTable.hasProperty(propertyId)
  203. ) {
  204. return true;
  205. }
  206. if (
  207. defined(this._batchTableHierarchy) &&
  208. this._batchTableHierarchy.hasProperty(index, propertyId)
  209. ) {
  210. return true;
  211. }
  212. if (
  213. defined(this._jsonMetadataTable) &&
  214. this._jsonMetadataTable.hasProperty(propertyId)
  215. ) {
  216. return true;
  217. }
  218. return false;
  219. };
  220. /**
  221. * Returns whether the feature has a property with the given semantic.
  222. *
  223. * @param {string} semantic The case-sensitive semantic of the property.
  224. * @returns {boolean} Whether the feature has a property with the given semantic.
  225. * @private
  226. */
  227. PropertyTable.prototype.hasPropertyBySemantic = function (index, semantic) {
  228. //>>includeStart('debug', pragmas.debug);
  229. Check.typeOf.number("index", index);
  230. Check.typeOf.string("semantic", semantic);
  231. //>>includeEnd('debug');
  232. if (defined(this._metadataTable)) {
  233. return this._metadataTable.hasPropertyBySemantic(semantic);
  234. }
  235. return false;
  236. };
  237. /**
  238. * Returns whether any feature has this property.
  239. * This is mainly useful for checking whether a property exists in the class
  240. * hierarchy when using the <code>3DTILES_batch_table_hierarchy</code> extension.
  241. *
  242. * @param {string} propertyId The case-sensitive ID of the property.
  243. * @returns {boolean} Whether any feature has this property.
  244. * @private
  245. */
  246. PropertyTable.prototype.propertyExists = function (propertyId) {
  247. //>>includeStart('debug', pragmas.debug);
  248. Check.typeOf.string("propertyId", propertyId);
  249. //>>includeEnd('debug');
  250. if (
  251. defined(this._metadataTable) &&
  252. this._metadataTable.hasProperty(propertyId)
  253. ) {
  254. return true;
  255. }
  256. if (
  257. defined(this._batchTableHierarchy) &&
  258. this._batchTableHierarchy.propertyExists(propertyId)
  259. ) {
  260. return true;
  261. }
  262. if (
  263. defined(this._jsonMetadataTable) &&
  264. this._jsonMetadataTable.hasProperty(propertyId)
  265. ) {
  266. return true;
  267. }
  268. return false;
  269. };
  270. /**
  271. * Returns whether any feature has a property with the given semantic.
  272. *
  273. * @param {string} semantic The case-sensitive semantic of the property.
  274. * @returns {boolean} Whether any feature has a property with the given semantic.
  275. * @private
  276. */
  277. PropertyTable.prototype.propertyExistsBySemantic = function (semantic) {
  278. //>>includeStart('debug', pragmas.debug);
  279. Check.typeOf.string("semantic", semantic);
  280. //>>includeEnd('debug');
  281. if (defined(this._metadataTable)) {
  282. return this._metadataTable.hasPropertyBySemantic(semantic);
  283. }
  284. return false;
  285. };
  286. const scratchResults = [];
  287. /**
  288. * Returns an array of property IDs. For compatibility with the <code>3DTILES_batch_table_hierarchy</code> extension, this is computed for a specific feature.
  289. *
  290. * @param {number} index The index of the feature.
  291. * @param {string[]} [results] An array into which to store the results.
  292. * @returns {string[]} The property IDs.
  293. * @private
  294. */
  295. PropertyTable.prototype.getPropertyIds = function (index, results) {
  296. results = defined(results) ? results : [];
  297. results.length = 0;
  298. if (defined(this._metadataTable)) {
  299. // concat in place to avoid unnecessary array allocation
  300. const ids = this._metadataTable.getPropertyIds(scratchResults);
  301. addAllToArray(results, ids);
  302. }
  303. if (defined(this._batchTableHierarchy)) {
  304. const ids = this._batchTableHierarchy.getPropertyIds(index, scratchResults);
  305. addAllToArray(results, ids);
  306. }
  307. if (defined(this._jsonMetadataTable)) {
  308. const ids = this._jsonMetadataTable.getPropertyIds(scratchResults);
  309. addAllToArray(results, ids);
  310. }
  311. return results;
  312. };
  313. /**
  314. * Returns a copy of the value of the property with the given ID.
  315. * <p>
  316. * If the property is normalized the normalized value is returned.
  317. * </p>
  318. *
  319. * @param {number} index The index of the feature.
  320. * @param {string} propertyId The case-sensitive ID of the property.
  321. * @returns {*} The value of the property or <code>undefined</code> if the feature does not have this property.
  322. * @private
  323. */
  324. PropertyTable.prototype.getProperty = function (index, propertyId) {
  325. let result;
  326. if (defined(this._metadataTable)) {
  327. result = this._metadataTable.getProperty(index, propertyId);
  328. if (defined(result)) {
  329. return result;
  330. }
  331. }
  332. if (defined(this._batchTableHierarchy)) {
  333. result = this._batchTableHierarchy.getProperty(index, propertyId);
  334. if (defined(result)) {
  335. return result;
  336. }
  337. }
  338. if (defined(this._jsonMetadataTable)) {
  339. result = this._jsonMetadataTable.getProperty(index, propertyId);
  340. if (defined(result)) {
  341. return result;
  342. }
  343. }
  344. return undefined;
  345. };
  346. /**
  347. * Sets the value of the property with the given ID. If the property did not
  348. * exist, it will be created as a JSON metadata property
  349. *
  350. * <p>
  351. * If the property is normalized a normalized value must be provided to this function.
  352. * </p>
  353. *
  354. * @param {number} index The index of the feature.
  355. * @param {string} propertyId The case-sensitive ID of the property.
  356. * @param {*} value The value of the property that will be copied.
  357. * @private
  358. */
  359. PropertyTable.prototype.setProperty = function (index, propertyId, value) {
  360. if (
  361. defined(this._metadataTable) &&
  362. this._metadataTable.setProperty(index, propertyId, value)
  363. ) {
  364. return;
  365. }
  366. if (
  367. defined(this._batchTableHierarchy) &&
  368. this._batchTableHierarchy.setProperty(index, propertyId, value)
  369. ) {
  370. return;
  371. }
  372. // Ensure we have a table for JSON properties
  373. if (!defined(this._jsonMetadataTable)) {
  374. this._jsonMetadataTable = new JsonMetadataTable({
  375. count: this._count,
  376. properties: {},
  377. });
  378. }
  379. // JsonMetadataTable will handle creating a new property at runtime.
  380. this._jsonMetadataTable.setProperty(index, propertyId, value);
  381. };
  382. /**
  383. * Returns a copy of the value of the property with the given semantic.
  384. * <p>
  385. * This only operates on the underlying {@link MetadataTable} (if present) as
  386. * {@link JsonMetadataTable} and {@link BatchTableHierarchy} do not have
  387. * semantics.
  388. * </p>
  389. *
  390. * @param {number} index The index of the feature.
  391. * @param {string} semantic The case-sensitive semantic of the property.
  392. * @returns {*} The value of the property or <code>undefined</code> if the feature does not have this semantic.
  393. * @private
  394. */
  395. PropertyTable.prototype.getPropertyBySemantic = function (index, semantic) {
  396. if (defined(this._metadataTable)) {
  397. return this._metadataTable.getPropertyBySemantic(index, semantic);
  398. }
  399. return undefined;
  400. };
  401. /**
  402. * Sets the value of the property with the given semantic.
  403. * <p>
  404. * This only operates on the underlying {@link MetadataTable} (if present) as
  405. * {@link JsonMetadataTable} and {@link BatchTableHierarchy} do not have
  406. * semantics.
  407. * </p>
  408. *
  409. * @param {number} index The index of the feature.
  410. * @param {string} semantic The case-sensitive semantic of the property.
  411. * @param {*} value The value of the property that will be copied.
  412. * @returns {boolean} <code>true</code> if the property was set, <code>false</code> otherwise.
  413. * @private
  414. */
  415. PropertyTable.prototype.setPropertyBySemantic = function (
  416. index,
  417. semantic,
  418. value,
  419. ) {
  420. if (defined(this._metadataTable)) {
  421. return this._metadataTable.setPropertyBySemantic(index, semantic, value);
  422. }
  423. return false;
  424. };
  425. /**
  426. * Returns a typed array containing the property values for a given propertyId.
  427. * <p>
  428. * This only operates on the underlying {@link MetadataTable} (if present) as
  429. * {@link JsonMetadataTable} and {@link BatchTableHierarchy} do not store
  430. * values in typed arrays.
  431. * </p>
  432. *
  433. * @param {string} propertyId The case-sensitive ID of the property.
  434. * @returns {*} The typed array containing the property values or <code>undefined</code> if the property values are not stored in a typed array.
  435. *
  436. * @private
  437. */
  438. PropertyTable.prototype.getPropertyTypedArray = function (propertyId) {
  439. //>>includeStart('debug', pragmas.debug);
  440. Check.typeOf.string("propertyId", propertyId);
  441. //>>includeEnd('debug');
  442. if (defined(this._metadataTable)) {
  443. return this._metadataTable.getPropertyTypedArray(propertyId);
  444. }
  445. return undefined;
  446. };
  447. /**
  448. * Returns a typed array containing the property values for the property with the given semantic.
  449. * <p>
  450. * This only operates on the underlying {@link MetadataTable} (if present) as
  451. * {@link JsonMetadataTable} and {@link BatchTableHierarchy} do not have
  452. * semantics.
  453. * </p>
  454. *
  455. * @param {string} semantic The case-sensitive semantic of the property.
  456. * @returns {*} The typed array containing the property values or <code>undefined</code> if the property values are not stored in a typed array.
  457. *
  458. * @private
  459. */
  460. PropertyTable.prototype.getPropertyTypedArrayBySemantic = function (semantic) {
  461. //>>includeStart('debug', pragmas.debug);
  462. Check.typeOf.string("semantic", semantic);
  463. //>>includeEnd('debug');
  464. if (defined(this._metadataTable)) {
  465. return this._metadataTable.getPropertyTypedArrayBySemantic(semantic);
  466. }
  467. return undefined;
  468. };
  469. function checkFeatureId(featureId, featuresLength) {
  470. if (!defined(featureId) || featureId < 0 || featureId >= featuresLength) {
  471. throw new DeveloperError(
  472. `featureId is required and must be between zero and featuresLength - 1 (${featuresLength}` -
  473. +").",
  474. );
  475. }
  476. }
  477. PropertyTable.prototype.isClass = function (featureId, className) {
  478. //>>includeStart('debug', pragmas.debug);
  479. checkFeatureId(featureId, this.count);
  480. Check.typeOf.string("className", className);
  481. //>>includeEnd('debug');
  482. const hierarchy = this._batchTableHierarchy;
  483. if (!defined(hierarchy)) {
  484. return false;
  485. }
  486. return hierarchy.isClass(featureId, className);
  487. };
  488. PropertyTable.prototype.isExactClass = function (featureId, className) {
  489. //>>includeStart('debug', pragmas.debug);
  490. checkFeatureId(featureId, this.count);
  491. Check.typeOf.string("className", className);
  492. //>>includeEnd('debug');
  493. return this.getExactClassName(featureId) === className;
  494. };
  495. PropertyTable.prototype.getExactClassName = function (featureId) {
  496. //>>includeStart('debug', pragmas.debug);
  497. checkFeatureId(featureId, this.count);
  498. //>>includeEnd('debug');
  499. const hierarchy = this._batchTableHierarchy;
  500. if (!defined(hierarchy)) {
  501. return undefined;
  502. }
  503. return hierarchy.getClassName(featureId);
  504. };
  505. /**
  506. * Destroys any resources that need cleaning up in the property table.
  507. *
  508. * @private
  509. */
  510. PropertyTable.prototype.destroy = function () {
  511. this._texture = this._texture && this._texture.destroy();
  512. return destroyObject(this);
  513. };
  514. export default PropertyTable;