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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. import Cesium3DTileset from "./Cesium3DTileset.js";
  2. import defined from "../Core/defined.js";
  3. import Resource from "../Core/Resource.js";
  4. import ITwinPlatform from "../Core/ITwinPlatform.js";
  5. import RuntimeError from "../Core/RuntimeError.js";
  6. import Check from "../Core/Check.js";
  7. import KmlDataSource from "../DataSources/KmlDataSource.js";
  8. import GeoJsonDataSource from "../DataSources/GeoJsonDataSource.js";
  9. import DeveloperError from "../Core/DeveloperError.js";
  10. /**
  11. * Methods for loading iTwin platform data into CesiumJS
  12. *
  13. * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
  14. *
  15. * @see ITwinPlatform
  16. * @namespace ITwinData
  17. */
  18. const ITwinData = {};
  19. /**
  20. * Create a {@link Cesium3DTileset} for the given iModel id using iTwin's Mesh Export API.
  21. *
  22. * If there is not a completed export available for the given iModel id, the returned promise will resolve to <code>undefined</code>.
  23. * We recommend waiting 10-20 seconds and trying to load the tileset again.
  24. * If all exports are Invalid this will throw an error.
  25. *
  26. * See the {@link https://developer.bentley.com/apis/mesh-export/overview/|iTwin Platform Mesh Export API documentation} for more information on request parameters
  27. *
  28. * @example
  29. * const tileset = await Cesium.ITwinData.createTilesetFromIModelId({ iModelId });
  30. * if (Cesium.defined(tileset)) {
  31. * viewer.scene.primitives.add(tileset);
  32. * }
  33. *
  34. * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
  35. *
  36. * @param {object} options
  37. * @param {string} options.iModelId The id of the iModel to load
  38. * @param {Cesium3DTileset.ConstructorOptions} [options.tilesetOptions] Object containing options to pass to the internally created {@link Cesium3DTileset}.
  39. * @param {string} [options.changesetId] The id of the changeset to load, if not provided the latest changesets will be used
  40. * @returns {Promise<Cesium3DTileset | undefined>} A promise that will resolve to the created 3D tileset or <code>undefined</code> if there is no completed export for the given iModel id
  41. *
  42. * @throws {RuntimeError} If all exports for the given iModel are Invalid
  43. * @throws {RuntimeError} If the iTwin API request is not successful
  44. */
  45. ITwinData.createTilesetFromIModelId = async function ({
  46. iModelId,
  47. changesetId,
  48. tilesetOptions,
  49. }) {
  50. const { exports } = await ITwinPlatform.getExports(iModelId, changesetId);
  51. if (
  52. exports.length > 0 &&
  53. exports.every((exportObj) => {
  54. return exportObj.status === ITwinPlatform.ExportStatus.Invalid;
  55. })
  56. ) {
  57. throw new RuntimeError(
  58. `All exports for this iModel are Invalid: ${iModelId}`,
  59. );
  60. }
  61. const completeExport = exports.find((exportObj) => {
  62. return exportObj.status === ITwinPlatform.ExportStatus.Complete;
  63. });
  64. if (!defined(completeExport)) {
  65. return;
  66. }
  67. // Convert the link to the tileset url while preserving the search paramaters
  68. // This link is only valid 1 hour
  69. const baseUrl = new URL(completeExport._links.mesh.href);
  70. baseUrl.pathname = `${baseUrl.pathname}/tileset.json`;
  71. const tilesetUrl = baseUrl.toString();
  72. const resource = new Resource({
  73. url: tilesetUrl,
  74. });
  75. return Cesium3DTileset.fromUrl(resource, tilesetOptions);
  76. };
  77. /**
  78. * Create a tileset for the specified reality data id. This function only works
  79. * with 3D Tiles meshes and point clouds.
  80. *
  81. * If the <code>type</code> or <code>rootDocument</code> are not provided this function
  82. * will first request the full metadata for the specified reality data to fill these values.
  83. *
  84. * The <code>maximumScreenSpaceError</code> of the resulting tileset will default to 4,
  85. * unless it is explicitly overridden with the given tileset options.
  86. *
  87. * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
  88. *
  89. * @param {object} options
  90. * @param {string} options.iTwinId The id of the iTwin to load data from
  91. * @param {string} options.realityDataId The id of the reality data to load
  92. * @param {ITwinPlatform.RealityDataType} [options.type] The type of this reality data
  93. * @param {string} [options.rootDocument] The path of the root document for this reality data
  94. * @param {Cesium3DTileset.ConstructorOptions} [options.tilesetOptions] Object containing
  95. * options to pass to the internally created {@link Cesium3DTileset}.
  96. * @returns {Promise<Cesium3DTileset>}
  97. *
  98. * @throws {RuntimeError} if the type of reality data is not supported by this function
  99. */
  100. ITwinData.createTilesetForRealityDataId = async function ({
  101. iTwinId,
  102. realityDataId,
  103. type,
  104. rootDocument,
  105. tilesetOptions,
  106. }) {
  107. //>>includeStart('debug', pragmas.debug);
  108. Check.typeOf.string("iTwinId", iTwinId);
  109. Check.typeOf.string("realityDataId", realityDataId);
  110. if (defined(type)) {
  111. Check.typeOf.string("type", type);
  112. }
  113. if (defined(rootDocument)) {
  114. Check.typeOf.string("rootDocument", rootDocument);
  115. }
  116. //>>includeEnd('debug');
  117. if (!defined(type) || !defined(rootDocument)) {
  118. const metadata = await ITwinPlatform.getRealityDataMetadata(
  119. iTwinId,
  120. realityDataId,
  121. );
  122. rootDocument = metadata.rootDocument;
  123. type = metadata.type;
  124. }
  125. const supportedRealityDataTypes = [
  126. ITwinPlatform.RealityDataType.Cesium3DTiles,
  127. ITwinPlatform.RealityDataType.PNTS,
  128. ITwinPlatform.RealityDataType.RealityMesh3DTiles,
  129. ITwinPlatform.RealityDataType.Terrain3DTiles,
  130. ITwinPlatform.RealityDataType.GaussianSplat3DTiles,
  131. ];
  132. if (!supportedRealityDataTypes.includes(type)) {
  133. throw new RuntimeError(`Reality data type is not a mesh type: ${type}`);
  134. }
  135. const tilesetAccessUrl = await ITwinPlatform.getRealityDataURL(
  136. iTwinId,
  137. realityDataId,
  138. rootDocument,
  139. );
  140. // The maximum screen space error was defined to default to 4 for
  141. // reality data tilesets, because they did not show the expected
  142. // amount of detail with the default value of 16. Values that are
  143. // given in the tilesetOptions should still override that default.
  144. const internalTilesetOptions = {
  145. maximumScreenSpaceError: 4,
  146. ...tilesetOptions,
  147. };
  148. return Cesium3DTileset.fromUrl(tilesetAccessUrl, internalTilesetOptions);
  149. };
  150. /**
  151. * Create a data source of the correct type for the specified reality data id.
  152. * This function only works for KML and GeoJSON type data.
  153. *
  154. * If the <code>type</code> or <code>rootDocument</code> are not provided this function
  155. * will first request the full metadata for the specified reality data to fill these values.
  156. *
  157. * @param {object} options
  158. * @param {string} options.iTwinId The id of the iTwin to load data from
  159. * @param {string} options.realityDataId The id of the reality data to load
  160. * @param {ITwinPlatform.RealityDataType} [options.type] The type of this reality data
  161. * @param {string} [options.rootDocument] The path of the root document for this reality data
  162. * @returns {Promise<GeoJsonDataSource | KmlDataSource>}
  163. *
  164. * @throws {RuntimeError} if the type of reality data is not supported by this function
  165. */
  166. ITwinData.createDataSourceForRealityDataId = async function ({
  167. iTwinId,
  168. realityDataId,
  169. type,
  170. rootDocument,
  171. }) {
  172. //>>includeStart('debug', pragmas.debug);
  173. Check.typeOf.string("iTwinId", iTwinId);
  174. Check.typeOf.string("realityDataId", realityDataId);
  175. if (defined(type)) {
  176. Check.typeOf.string("type", type);
  177. }
  178. if (defined(rootDocument)) {
  179. Check.typeOf.string("rootDocument", rootDocument);
  180. }
  181. //>>includeEnd('debug');
  182. if (!defined(type) || !defined(rootDocument)) {
  183. const metadata = await ITwinPlatform.getRealityDataMetadata(
  184. iTwinId,
  185. realityDataId,
  186. );
  187. rootDocument = metadata.rootDocument;
  188. type = metadata.type;
  189. }
  190. const supportedRealityDataTypes = [
  191. ITwinPlatform.RealityDataType.KML,
  192. ITwinPlatform.RealityDataType.GeoJSON,
  193. ];
  194. if (!supportedRealityDataTypes.includes(type)) {
  195. throw new RuntimeError(
  196. `Reality data type is not a data source type: ${type}`,
  197. );
  198. }
  199. const tilesetAccessUrl = await ITwinPlatform.getRealityDataURL(
  200. iTwinId,
  201. realityDataId,
  202. rootDocument,
  203. );
  204. if (type === ITwinPlatform.RealityDataType.GeoJSON) {
  205. return GeoJsonDataSource.load(tilesetAccessUrl);
  206. }
  207. // If we get here it's guaranteed to be a KML type
  208. return KmlDataSource.load(tilesetAccessUrl);
  209. };
  210. /**
  211. * Load data from the Geospatial Features API as GeoJSON.
  212. *
  213. * @param {object} options
  214. * @param {string} options.iTwinId The id of the iTwin to load data from
  215. * @param {string} options.collectionId The id of the data collection to load
  216. * @param {number} [options.limit=10000] number of items per page, must be between 1 and 10,000 inclusive
  217. * @returns {Promise<GeoJsonDataSource>}
  218. */
  219. ITwinData.loadGeospatialFeatures = async function ({
  220. iTwinId,
  221. collectionId,
  222. limit,
  223. }) {
  224. //>>includeStart('debug', pragmas.debug);
  225. Check.typeOf.string("iTwinId", iTwinId);
  226. Check.typeOf.string("collectionId", collectionId);
  227. if (defined(limit)) {
  228. Check.typeOf.number("limit", limit);
  229. Check.typeOf.number.lessThanOrEquals("limit", limit, 10000);
  230. Check.typeOf.number.greaterThanOrEquals("limit", limit, 1);
  231. }
  232. if (
  233. !defined(ITwinPlatform.defaultAccessToken) &&
  234. !defined(ITwinPlatform.defaultShareKey)
  235. ) {
  236. throw new DeveloperError(
  237. "Must set ITwinPlatform.defaultAccessToken or ITwinPlatform.defaultShareKey first",
  238. );
  239. }
  240. //>>includeEnd('debug');
  241. const pageLimit = limit ?? 10000;
  242. const tilesetUrl = `${ITwinPlatform.apiEndpoint}geospatial-features/itwins/${iTwinId}/ogc/collections/${collectionId}/items`;
  243. const resource = new Resource({
  244. url: tilesetUrl,
  245. headers: {
  246. Authorization: ITwinPlatform._getAuthorizationHeader(),
  247. Accept: "application/vnd.bentley.itwin-platform.v1+json",
  248. },
  249. queryParameters: {
  250. limit: pageLimit,
  251. client: "CesiumJS",
  252. },
  253. });
  254. return GeoJsonDataSource.load(resource);
  255. };
  256. export default ITwinData;