You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

S3MTilesLayer.js 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. import S3MTile from './S3MTile.js'
  2. import S3MLayerScheduler from './S3MLayerScheduler.js'
  3. import S3MLayerCache from './S3MLayerCache.js'
  4. import OperationType from './Enum/OperationType.js'
  5. import Style3D from './Style3D.js'
  6. const { Cesium } = DC.Namespace
  7. function S3MTilesLayer(options) {
  8. options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT)
  9. Cesium.Check.defined('options.url', options.url)
  10. Cesium.Check.defined('options.context', options.context)
  11. this.id = Cesium.createGuid()
  12. this.name = options.name
  13. this.context = options.context
  14. this._url = undefined
  15. this._basePath = undefined
  16. this._baseResource = undefined
  17. this.modelMatrix = new Cesium.Matrix4()
  18. this.invModelMatrix = new Cesium.Matrix4()
  19. this._visibleDistanceMax = Cesium.defaultValue(
  20. options.maxVisibleDistance,
  21. Number.MAX_VALUE
  22. )
  23. this._visibleDistanceMin = Cesium.defaultValue(
  24. options.minVisibleDistance,
  25. 0.0
  26. )
  27. this._lodRangeScale = Cesium.defaultValue(options.lodRangeScale, 1.0)
  28. this._selectedColor = new Cesium.Color(0.7, 0.7, 1.0, 1.0)
  29. this.fileType = undefined
  30. this._position = undefined
  31. this._rectangle = undefined
  32. this._rootTiles = []
  33. this._schuduler = new S3MLayerScheduler()
  34. this._selections = []
  35. this._objsOperationList = {}
  36. this._requestTiles = []
  37. this._processTiles = []
  38. this._selectedTiles = []
  39. this._cache = new S3MLayerCache()
  40. this._maximumMemoryUsage = -1
  41. this._totalMemoryUsageInBytes = 0
  42. this._style3D = new Style3D()
  43. this._maximumPriority = {
  44. foveatedFactor: -Number.MAX_VALUE,
  45. depth: -Number.MAX_VALUE,
  46. distance: -Number.MAX_VALUE,
  47. pixel: -Number.MAX_VALUE
  48. }
  49. this._minimumPriority = {
  50. foveatedFactor: Number.MAX_VALUE,
  51. depth: Number.MAX_VALUE,
  52. distance: Number.MAX_VALUE,
  53. pixel: Number.MAX_VALUE
  54. }
  55. this._readyPromise = Cesium.when.defer()
  56. this.loadConfig(options.url)
  57. }
  58. Object.defineProperties(S3MTilesLayer.prototype, {
  59. ready: {
  60. get: function() {
  61. return this._rootTiles.length > 0
  62. }
  63. },
  64. readyPromise: {
  65. get: function() {
  66. return this._readyPromise
  67. }
  68. },
  69. rectangle: {
  70. get: function() {
  71. return this._rectangle
  72. }
  73. },
  74. visibleDistanceMax: {
  75. get: function() {
  76. return this._visibleDistanceMax
  77. },
  78. set: function(value) {
  79. Cesium.Check.typeOf.number('max visible distance', value)
  80. this._visibleDistanceMax = value
  81. }
  82. },
  83. visibleDistanceMin: {
  84. get: function() {
  85. return this._visibleDistanceMin
  86. },
  87. set: function(value) {
  88. Cesium.Check.typeOf.number('min visible distance', value)
  89. this._visibleDistanceMin = value
  90. }
  91. },
  92. lodRangeScale: {
  93. get: function() {
  94. return this._lodRangeScale
  95. },
  96. set: function(value) {
  97. Cesium.Check.typeOf.number('set layer lod range scale', value)
  98. this._lodRangeScale = value
  99. }
  100. },
  101. totalMemoryUsageInBytes: {
  102. get: function() {
  103. return this._totalMemoryUsageInBytes
  104. },
  105. set: function(value) {
  106. this._totalMemoryUsageInBytes = value
  107. }
  108. },
  109. maximumMemoryUsage: {
  110. get: function() {
  111. return this._maximumMemoryUsage
  112. },
  113. set: function(value) {
  114. this._maximumMemoryUsage = value
  115. }
  116. },
  117. style3D: {
  118. get: function() {
  119. return this._style3D
  120. },
  121. set: function(value) {
  122. this._style3D = value
  123. }
  124. }
  125. })
  126. // Cesium.Scene.prototype.hookPickFunc = Cesium.Scene.prototype.pick;
  127. //
  128. // Cesium.Scene.prototype.pick = function(windowPosition, width, height) {
  129. // let picked = this.hookPickFunc(windowPosition, width, height);
  130. // if (picked) {
  131. // let isS3MTilesLayer = picked.primitive && picked.primitive instanceof S3MTilesLayer;
  132. // if(isS3MTilesLayer){
  133. // picked.primitive.setSelection(picked.id);
  134. // }
  135. // }
  136. // else{
  137. // for(let i = 0,j = this.primitives.length;i < j;i++){
  138. // let primitive = this.primitives.get(i);
  139. // primitive instanceof S3MTilesLayer && primitive.releaseSelection();
  140. // }
  141. // }
  142. //
  143. // return picked;
  144. // };
  145. S3MTilesLayer.prototype.loadConfig = function(url) {
  146. let that = this
  147. Cesium.when(url)
  148. .then(function(url) {
  149. let basePath
  150. let resource = Cesium.Resource.createIfNeeded(url)
  151. basePath = resource.getBaseUri(true)
  152. that._url = resource.url
  153. that._basePath = basePath
  154. that._baseResource = resource
  155. return resource.fetchJson()
  156. })
  157. .then(function(config) {
  158. let extensions = config.extensions
  159. that.fileType = extensions['s3m:FileType']
  160. let lon = config.position.x
  161. let lat = config.position.y
  162. let height = config.position.z
  163. that._position = Cesium.Cartesian3.fromDegrees(lon, lat, height)
  164. that.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
  165. that._position
  166. )
  167. that.invModelMatrix = Cesium.Matrix4.inverse(
  168. that.modelMatrix,
  169. that.invModelMatrix
  170. )
  171. that._rectangle = Cesium.Rectangle.fromDegrees(
  172. config.geoBounds.left,
  173. config.geoBounds.bottom,
  174. config.geoBounds.right,
  175. config.geoBounds.top
  176. )
  177. if (config.heightRange) {
  178. that._minHeight = config.heightRange.min
  179. that._maxHeight = config.heightRange.max
  180. }
  181. if (config.wDescript) {
  182. let wDescript = config.wDescript.range
  183. that._minWValue = wDescript.min
  184. that._maxWValue = wDescript.max
  185. }
  186. for (let i = 0, len = config.tiles.length; i < len; i++) {
  187. let fileName = config.tiles[i].url
  188. let boundingVolume = {
  189. box: config.tiles[i].boundingbox
  190. }
  191. let tile = new S3MTile(that, undefined, boundingVolume, fileName)
  192. tile.isRootTile = true
  193. that._cache.add(tile)
  194. that._rootTiles.push(tile)
  195. }
  196. that._readyPromise.resolve(that)
  197. })
  198. .otherwise(function(error) {
  199. that._readyPromise.reject(error)
  200. })
  201. }
  202. S3MTilesLayer.prototype._tranverseRenderEntity = function(options, callback) {
  203. let stack = []
  204. for (let i = 0, j = this._rootTiles.length; i < j; i++) {
  205. let rootTile = this._rootTiles[i]
  206. stack.push(rootTile)
  207. }
  208. while (stack.length) {
  209. let tile = stack.pop()
  210. for (let i = 0, j = tile.renderEntities.length; i < j; i++) {
  211. const renderEntity = tile.renderEntities[i]
  212. if (renderEntity.ready) {
  213. callback(renderEntity, options)
  214. }
  215. }
  216. for (let i = 0, j = tile.children.length; i < j; i++) {
  217. stack.push(tile.children[i])
  218. }
  219. }
  220. }
  221. function updateObjsOperationCallback(renderEntity, options) {
  222. renderEntity.updateObjsOperation(options.ids, options)
  223. }
  224. S3MTilesLayer.prototype._updateObjsOperation = function(ids) {
  225. this._tranverseRenderEntity(
  226. {
  227. ids: ids
  228. },
  229. updateObjsOperationCallback
  230. )
  231. }
  232. S3MTilesLayer.prototype._setObjsOperationType = function(ids, operationType) {
  233. Cesium.Check.defined('set Objs Operation ids', ids)
  234. Cesium.Check.defined('set Objs Operation operationType', operationType)
  235. if (!Array.isArray(ids)) {
  236. ids = [ids]
  237. }
  238. let tmpArr = new Cesium.AssociativeArray()
  239. let id
  240. for (let i = 0, j = ids.length; i < j; i++) {
  241. id = ids[i]
  242. if (!Cesium.defined(id)) {
  243. continue
  244. }
  245. let operation = Cesium.defaultValue(this._objsOperationList[id], 0)
  246. if (operation === operationType) {
  247. continue
  248. }
  249. operation = operation | operationType
  250. this._objsOperationList[id] = operation
  251. tmpArr.set(id, operation)
  252. }
  253. if (tmpArr.length > 0) {
  254. this._updateObjsOperation(tmpArr._hash)
  255. }
  256. }
  257. S3MTilesLayer.prototype._removeObjsOperationType = function(
  258. ids,
  259. operationType
  260. ) {
  261. Cesium.Check.defined('set Objs Operation ids', ids)
  262. if (!Array.isArray(ids)) {
  263. ids = [ids]
  264. }
  265. let nonOperationType = OperationType.ALL ^ operationType
  266. let tmpArr = new Cesium.AssociativeArray()
  267. let id
  268. for (let i = 0, j = ids.length; i < j; i++) {
  269. id = ids[i]
  270. let operation = this._objsOperationList[id]
  271. if (!Cesium.defined(operation)) {
  272. continue
  273. }
  274. operation &= nonOperationType
  275. if (operation === OperationType.RESET) {
  276. delete this._objsOperationList[id]
  277. } else {
  278. this._objsOperationList[id] = operation
  279. }
  280. tmpArr.set(id, operation)
  281. }
  282. if (tmpArr.length > 0) {
  283. this._updateObjsOperation(tmpArr._hash)
  284. }
  285. }
  286. S3MTilesLayer.prototype.releaseSelection = function() {
  287. if (this._selections.length < 1) {
  288. return
  289. }
  290. this._removeObjsOperationType(this._selections, OperationType.SELECTED)
  291. this._selections.length = 0
  292. }
  293. S3MTilesLayer.prototype.setSelection = function(ids) {
  294. Cesium.Check.defined('setSelection ids', ids)
  295. if (!Array.isArray(ids)) {
  296. ids = [ids]
  297. }
  298. this.releaseSelection()
  299. this._selections = this._selections.concat(ids)
  300. this._setObjsOperationType(ids, OperationType.SELECTED)
  301. }
  302. function sortRequestByPriority(a, b) {
  303. return a.priority - b.priority
  304. }
  305. function requestTiles(layer) {
  306. let requestTiles = layer._requestTiles
  307. let length = requestTiles.length
  308. requestTiles.sort(sortRequestByPriority)
  309. for (let i = 0; i < length; ++i) {
  310. let tile = requestTiles[i]
  311. tile.requestContent()
  312. }
  313. }
  314. function processTiles(layer, frameState) {
  315. let tiles = layer._processTiles
  316. let length = tiles.length
  317. for (let i = 0; i < length; ++i) {
  318. let tile = tiles[i]
  319. tile.update(frameState, layer)
  320. }
  321. }
  322. function updateTiles(layer, frameState) {
  323. let selectedTiles = layer._selectedTiles
  324. let length = selectedTiles.length
  325. for (let i = 0; i < length; i++) {
  326. selectedTiles[i].update(frameState, layer)
  327. }
  328. }
  329. function unloadTile(layer, tile) {
  330. tile.free()
  331. }
  332. function freeResource(layer) {
  333. layer._cache.unloadTiles(layer, unloadTile)
  334. }
  335. S3MTilesLayer.prototype.prePassesUpdate = function(frameState) {
  336. if (!this.ready) {
  337. return
  338. }
  339. if (frameState.newFrame) {
  340. this._cache.reset()
  341. this._requestTiles.length = 0
  342. this._processTiles.length = 0
  343. this._selectedTiles.length = 0
  344. }
  345. }
  346. S3MTilesLayer.prototype.postPassesUpdate = function(frameState) {
  347. if (!this.ready) {
  348. return
  349. }
  350. freeResource(this)
  351. }
  352. S3MTilesLayer.prototype.update = function(frameState) {
  353. if (!this.ready) {
  354. return
  355. }
  356. this._schuduler.schedule(this, frameState)
  357. requestTiles(this)
  358. processTiles(this, frameState)
  359. updateTiles(this, frameState)
  360. }
  361. S3MTilesLayer.prototype.isDestroyed = function() {
  362. return false
  363. }
  364. S3MTilesLayer.prototype.destroy = function() {
  365. this._cache.reset()
  366. freeResource(this)
  367. this._rootTiles.length = 0
  368. this._requestTiles.length = 0
  369. this._processTiles.length = 0
  370. this._selectedTiles.length = 0
  371. return Cesium.destroyObject(this)
  372. }
  373. export default S3MTilesLayer