PageRenderTime 67ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/com/panosalado/model/ViewData.as

http://github.com/mstandio/SaladoPlayer
ActionScript | 733 lines | 321 code | 89 blank | 323 comment | 112 complexity | 7c7aa729c2a83e587064e6744e9d69d5 MD5 | raw file
Possible License(s): LGPL-3.0
  1. /*
  2. Copyright 2010 Zephyr Renner.
  3. This file is part of PanoSalado.
  4. PanoSalado is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. PanoSalado is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with PanoSalado. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package com.panosalado.model{
  16. import com.panosalado.events.ReadyEvent;
  17. import com.panosalado.events.ViewEvent;
  18. import flash.display.Sprite;
  19. import flash.events.Event;
  20. import flash.geom.Matrix3D;
  21. import flash.geom.PerspectiveProjection;
  22. import flash.geom.Point;
  23. import flash.geom.Vector3D;
  24. /**
  25. * Model class. Uses a getter/setter + public underlying property style implementation to allow fast access to properties.
  26. * The properties should NEVER be set directly using the "_" prefixed property. The setters for all of the properties
  27. * invalidate the stage, (which causes a RENDER dispatch to redraw the panorama), in addition to setting the invalid properties
  28. * of this class itself (invalid, invalidTransform, invalidPerspective), and setting of properties must happen via the setter
  29. * function for the change to be reflected in the rendered panorama.
  30. */
  31. public class ViewData extends Sprite {
  32. /**
  33. * Minimum renderable field of view
  34. * @default 0.1
  35. */
  36. public static const MINIMUM_FOV:Number = 0.1;
  37. /**
  38. * Maximum renderable field of view
  39. * @default 179.9
  40. */
  41. public static const MAXIMUM_FOV:Number = 179.9;
  42. /**
  43. * Matrix3D recomposed from pan and tilt angles. For internal use.
  44. */
  45. public var transformMatrix3D:Matrix3D;
  46. /**
  47. * PerspectiveProjection set from field of view, boundsWidth and boundsHeight. For internal use.
  48. */
  49. public var perspectiveProjection:PerspectiveProjection;
  50. /**
  51. * Matrix3D from perspectiveProjection.toMatrix3d(). For internal use.
  52. */
  53. public var perspectiveMatrix3D:Matrix3D;
  54. /**
  55. * Left frustum plane as determined by field of view. For internal use.
  56. */
  57. public var frustumLeft:Vector3D;
  58. /**
  59. * Right frustum plane as determined by field of view. For internal use.
  60. */
  61. public var frustumRight:Vector3D;
  62. /**
  63. * Top frustum plane as determined by field of view. For internal use.
  64. */
  65. public var frustumTop:Vector3D;
  66. /**
  67. * Bottom frustum plane as determined by field of view. For internal use.
  68. */
  69. public var frustumBottom:Vector3D;
  70. /**
  71. * Pixels per degree as determined from field of view, boundsWidth and boundsHeight. For internal use.
  72. */
  73. public var pixelsPerDegree:Number;
  74. /**
  75. * Pan angle. Can be used in place of getter for faster access. Do NOT use in place of setter.
  76. * @see pan
  77. */
  78. public var _pan:Number;
  79. /**
  80. * Tilt angle. Can be used in place of getter for faster access. Do NOT use in place of setter.
  81. * @see tilt
  82. */
  83. public var _tilt:Number;
  84. /**
  85. * Field of view. Can be used in place of getter for faster access. Do NOT use in place of setter.
  86. * @see fieldOfView
  87. */
  88. public var _fieldOfView:Number;
  89. /**
  90. * Tier threshold. Can be used in place of getter for faster access. Do NOT use in place of setter.
  91. * @see tierThreshold
  92. */
  93. public var _tierThreshold:Number;
  94. /**
  95. * Width of panorama. Can be used in place of getter for faster access. Do NOT use in place of setter.
  96. * @see boundsWidth
  97. */
  98. public var _boundsWidth:Number;
  99. /**
  100. * Height of panorama. Can be used in place of getter for faster access. Do NOT use in place of setter.
  101. * @see boundsHeight
  102. */
  103. public var _boundsHeight:Number;
  104. /**
  105. * Path for panorama. Can be used in place of getter for faster access. Do NOT use in place of setter.
  106. * @see path
  107. */
  108. public var _path:String;
  109. /**
  110. * Tile. Can be used in place of getter for faster access. Do NOT use in place of setter.
  111. * @see tile
  112. */
  113. public var _tile:Tile;
  114. /**
  115. * Minimum field of view. Can be used in place of getter for faster access. Do NOT use in place of setter.
  116. * @see minimumFieldOfView
  117. */
  118. public var _minimumFieldOfView:Number;
  119. public var _minimumFieldOfViewDefault:Number;
  120. /**
  121. * Maximum field of view. Can be used in place of getter for faster access. Do NOT use in place of setter.
  122. * @see maximumFieldOfView
  123. */
  124. public var _maximumFieldOfView:Number;
  125. public var _maximumFieldOfViewDefault:Number;
  126. /**
  127. * Minimum pan. Can be used in place of getter for faster access. Do NOT use in place of setter.
  128. * @see minimumPan
  129. */
  130. public var _minimumPan:Number;
  131. /**
  132. * Maximum pan. Can be used in place of getter for faster access. Do NOT use in place of setter.
  133. * @see maximumPan
  134. */
  135. public var _maximumPan:Number;
  136. /**
  137. * Minimum tilt. Can be used in place of getter for faster access. Do NOT use in place of setter.
  138. * @see minimumTilt
  139. */
  140. public var _minimumTilt:Number;
  141. /**
  142. * Maximum tilt. Can be used in place of getter for faster access. Do NOT use in place of setter.
  143. * @see maximumTilt
  144. */
  145. public var _maximumTilt:Number;
  146. /**
  147. * Minimum horizontal field of view. Can be used in place of getter for faster access. Do NOT use in place of setter.
  148. * @see minimumHorizontalFieldOfView
  149. */
  150. public var _minimumHorizontalFieldOfView:Number;
  151. /**
  152. * Maximum horizontal field of view. Can be used in place of getter for faster access. Do NOT use in place of setter.
  153. * @see maximumHorizontalFieldOfView
  154. */
  155. public var _maximumHorizontalFieldOfView:Number;
  156. /**
  157. * Minimum vertical field of view. Can be used in place of getter for faster access. Do NOT use in place of setter.
  158. * @see minimumVerticalFieldOfView
  159. */
  160. public var _minimumVerticalFieldOfView:Number;
  161. /**
  162. * Maximum vertical field of view. Can be used in place of getter for faster access. Do NOT use in place of setter.
  163. * @see maximumVerticalFieldOfView
  164. */
  165. public var _maximumVerticalFieldOfView:Number;
  166. /**
  167. * Maximum pixel zoom. Can be used in place of getter for faster access. Do NOT use in place of setter.
  168. * @see maximumVerticalFieldOfView
  169. */
  170. public var _maximumPixelZoom:Number;
  171. /**
  172. * Invalidation flag for all properties. i.e. if one of them is invalid, this must be invalid as well.
  173. */
  174. public var invalid:Boolean;
  175. /**
  176. * Invalidation flag for pan and tilt, which determine the transformMatrix3D
  177. */
  178. public var invalidTransform:Boolean;
  179. /**
  180. * Invalidation flag for field of view, boundsWidth and boundsHeight, which determine perspectiveProjection and perspectiveMatrix3D
  181. */
  182. public var invalidPerspective:Boolean;
  183. /**
  184. * Secondary ViewData, which is used for the secondary (outgoing) panorama.
  185. * @see DependentViewData
  186. */
  187. public var secondaryViewData:DependentViewData;
  188. protected var constructed:Boolean;
  189. /**
  190. * Constructor.
  191. * @param constructSecondaryViewData Boolean true. When a DependentViewData object is constructed it will pass
  192. * false so that the DendentViewData object does not create its own DependentViewData into an infinite loop.
  193. */
  194. public function ViewData(constructSecondaryViewData:Boolean = true) {
  195. super();
  196. transformMatrix3D = new Matrix3D();
  197. perspectiveProjection = new PerspectiveProjection();
  198. perspectiveMatrix3D = new Matrix3D();
  199. perspectiveProjection.projectionCenter = new Point(0,0);
  200. frustumLeft = new Vector3D(0,0,0,0);
  201. frustumRight = new Vector3D(0,0,0,0);
  202. frustumTop = new Vector3D(0,0,0,0);
  203. frustumBottom = new Vector3D(0,0,0,0);
  204. // initialize all vars with "default" values
  205. invalid = false;
  206. invalidTransform = false;
  207. invalidPerspective = false;
  208. if (constructSecondaryViewData) secondaryViewData = new DependentViewData(this);
  209. pan = 0;
  210. tilt = 0;
  211. fieldOfView = 90;
  212. boundsWidth = 500; // Must be default stage size (500) to calculate FOV correctly.
  213. boundsHeight = 375;
  214. path = null;
  215. minimumFieldOfView = MINIMUM_FOV;
  216. maximumFieldOfView = MAXIMUM_FOV;
  217. minimumPan = Number.NEGATIVE_INFINITY;
  218. maximumPan = Number.POSITIVE_INFINITY;
  219. minimumTilt = Number.NEGATIVE_INFINITY;
  220. maximumTilt = Number.POSITIVE_INFINITY;
  221. tierThreshold = 1.0;
  222. }
  223. /**
  224. * Pan angle.
  225. * @default 0
  226. */
  227. public function get pan():Number { return _pan; }
  228. /**
  229. * @private
  230. */
  231. public function set pan(value:Number):void {
  232. //clamp values to -180 to 180. camera controller can do further clamping if desired.
  233. if (value == _pan || isNaN(value)) return;
  234. if (value <= -180) value = (((value + 180) % 360) + 180);
  235. if (value > 180) value = (((value + 180) % 360) - 180);
  236. if (value < _minimumPan) value = _minimumPan;
  237. if (value > _maximumPan) value = _maximumPan;
  238. _pan = value;
  239. invalidTransform = invalid = true;
  240. if (stage) stage.invalidate();
  241. }
  242. /**
  243. * Tilt angle.
  244. * @default 0
  245. */
  246. public function get tilt():Number { return _tilt; }
  247. /**
  248. * @private
  249. */
  250. public function set tilt(value:Number):void {
  251. //clamp values to -180 to 180. camera controller can do further clamping if desired.
  252. if (value == _tilt || isNaN(value) ) return;
  253. if (value <= -180) value = (((value + 180) % 360) + 180);
  254. if (value > 180) value = (((value + 180) % 360) - 180);
  255. if (value < _minimumTilt) value = _minimumTilt;
  256. if (value > _maximumTilt) value = _maximumTilt;
  257. _tilt = value;
  258. invalidTransform = invalid = true;
  259. if (stage) stage.invalidate();
  260. }
  261. /**
  262. * Field of view.
  263. * @default 90
  264. */
  265. public function get fieldOfView():Number { return _fieldOfView; }
  266. /**
  267. * @private
  268. */
  269. public function set fieldOfView(value:Number):void{
  270. if (value == _fieldOfView || isNaN(value)) return;
  271. if (value < _minimumFieldOfView) value = _minimumFieldOfView;
  272. if (value > _maximumFieldOfView) value = _maximumFieldOfView;
  273. if (_fieldOfView == value) return;
  274. _fieldOfView = value;
  275. adjustLimits();
  276. invalidPerspective = invalid = true;
  277. if (stage) stage.invalidate();
  278. }
  279. /**
  280. * Width of rendered panorama.
  281. * @default 500
  282. */
  283. public function get boundsWidth():Number { return _boundsWidth;}
  284. /**
  285. * @private
  286. */
  287. public function set boundsWidth(value:Number):void{
  288. if ( _boundsWidth == value || isNaN(value) ) return;
  289. _boundsWidth = value;
  290. updateMinimumFieldOfView();
  291. invalidPerspective = invalid = true;
  292. if (stage) stage.invalidate();
  293. adjustLimits();
  294. dispatchEvent(new ViewEvent(ViewEvent.BOUNDS_CHANGED));
  295. }
  296. /**
  297. * Height of rendered panorama.
  298. * @default 375
  299. */
  300. public function get boundsHeight():Number { return _boundsHeight;}
  301. /**
  302. * @private
  303. */
  304. public function set boundsHeight(value:Number):void{
  305. if ( _boundsHeight == value || isNaN(value) ) return;
  306. _boundsHeight = value;
  307. invalidPerspective = invalid = true;
  308. if (stage) stage.invalidate();
  309. adjustLimits();
  310. dispatchEvent(new ViewEvent(ViewEvent.BOUNDS_CHANGED));
  311. }
  312. /**
  313. * Tier Threshold. Specifies multiplier on pixels per degree which is used in the rendering cycle to
  314. * determine which tier of tiles to display/load. Can be used to blur or sharpen the
  315. * rendering by forcing use of higher or lower resolution tiles. E.g a value of 1.5 will blur the panorama.
  316. * @default 1
  317. */
  318. public function get tierThreshold():Number { return _tierThreshold; }
  319. /**
  320. * @private
  321. */
  322. public function set tierThreshold(value:Number):void{
  323. if ( _tierThreshold == value || isNaN(value) ) return;
  324. _tierThreshold = value;
  325. invalidPerspective = invalid = true;
  326. }
  327. private function updateMinimumFieldOfView():void {
  328. //if ( _tile != null && (_tile.tilePyramid != null && (!isNaN(_tile.tilePyramid.width))) ) // COREMOD
  329. //minimumFieldOfView = (_boundsWidth / _tile.tilePyramid.width) * 90; // TODO: check why i had to comment this out
  330. }
  331. /**
  332. * Path. Depending on the type of panorama images (tiled, QTVR, etc) the path will differ.
  333. * Note that this property changes asynchronously. In other words, after you set it,
  334. * accessing the value will return the previous value until the new panorama has loaded
  335. * sufficiently to display.
  336. * DeepZoom Style cubic: front face xml descriptor file
  337. * Zoomify cubic: front face xml descriptor file
  338. * cubic: front face image file
  339. * QTVR: .mov file
  340. * @default null
  341. */
  342. public function get path():String { return _path;}
  343. /**
  344. * @private
  345. */
  346. public function set path(value:String):void{
  347. // if (_path == value && value != null) return;
  348. if (value == null) { //delete current tile.
  349. _tile = null;
  350. _path = null;
  351. invalid = true;
  352. if (stage) stage.invalidate();
  353. dispatchEvent(new ViewEvent(ViewEvent.NULL_PATH));
  354. return;
  355. }
  356. //var panoramaImageType:String = guessPanoramaImageType(value);
  357. //if ( panoramaImageType == null )
  358. //throw new Error("Given path: " + value + " can not be resolved to one of the types in PanoramaImageType by com.panosalado.controller.guessPanoramaImageType()");
  359. var qtc:QuadTreeCube = new QuadTreeCube(value);
  360. if (qtc.ready) commitPath( new ReadyEvent(ReadyEvent.READY,qtc.tilePyramid) );
  361. else qtc.addEventListener(ReadyEvent.READY, commitPath); //NB: do NOT use a weak event listener; tile will be gc'ed.
  362. /*NB: path is NOT committed yet, since it could result in unrenderable data if QuadTreeCube
  363. has to load a descriptor file before it can initialize. path will be committed in commitPath
  364. called synchronously if quadtree cube shows ready flag after instantiation or asynchronously
  365. if not ready (loading descriptor).
  366. */
  367. }
  368. /**
  369. * this is called when the QuadTreeCube, TilePyramid and root tile bitmaps are ready.
  370. * @private
  371. */
  372. protected function commitPath(e:ReadyEvent,updateFOV:Boolean=true):void {
  373. var tile:QuadTreeCube = e.target as QuadTreeCube;
  374. var path:String = e.tilePyramid.path;
  375. tile.removeEventListener(ReadyEvent.READY, commitPath); //NB: strongly referenced; must remove
  376. //push current values to secondary
  377. secondaryViewData._path = _path;
  378. secondaryViewData._tile = _tile;
  379. secondaryViewData.invalidTransform = secondaryViewData.invalidPerspective = secondaryViewData.invalid = true;
  380. //set current with new values
  381. _path = path
  382. _tile = tile;
  383. if (updateFOV) updateMinimumFieldOfView();
  384. invalidTransform = invalidPerspective = invalid = true;
  385. if (stage) stage.invalidate();
  386. //default behavior is to immediately dispose of the secondary panorama.
  387. //So any transition class needs to listen for the PATH event and call preventDefault()
  388. //on the event object in the listener handler function
  389. var event:Event = new ViewEvent(ViewEvent.PATH, null, true); //NB: 3rd arg is cancelable, must be true. transitions call preventDefault().
  390. var success:Boolean = dispatchEvent(event);
  391. dispatchEvent( new Event(Event.COMPLETE));
  392. if (!success && (event.isDefaultPrevented())) return;
  393. secondaryViewData.path = null;
  394. adjustLimits();
  395. }
  396. /**
  397. * The root tile in the tile linked list data structure. Read-only. It is dependent on the path.
  398. */
  399. public function get tile():Tile { return _tile; }
  400. /**
  401. * minimumFieldOfView
  402. * @default 0.1
  403. */
  404. public function get minimumFieldOfView():Number { return _minimumFieldOfView; }
  405. /**
  406. * @private
  407. */
  408. public function set minimumFieldOfView(value:Number):void {
  409. if (value == _minimumFieldOfView || isNaN(value)) return;
  410. if (value < MINIMUM_FOV) value = MINIMUM_FOV;
  411. if (value > MAXIMUM_FOV) value = MAXIMUM_FOV;
  412. _minimumFieldOfView = value;
  413. if (_fieldOfView < value) fieldOfView = value; //check against current fieldOfView and use setter
  414. }
  415. /**
  416. * maximumFieldOfView
  417. * @default 179.9
  418. */
  419. public function get maximumFieldOfView():Number { return _maximumFieldOfView; }
  420. /**
  421. * @private
  422. */
  423. public function set maximumFieldOfView(value:Number):void{
  424. if (value == _maximumFieldOfView || isNaN(value)) return;
  425. if (value < MINIMUM_FOV) value = MINIMUM_FOV;
  426. if (value > MAXIMUM_FOV) value = MAXIMUM_FOV;
  427. _maximumFieldOfView = value;
  428. if (_fieldOfView > value) fieldOfView = value; //check against current fieldOfView and use setter
  429. }
  430. /**
  431. * minimumPan
  432. * @default Number.NEGATIVE_INFINITY
  433. */
  434. public function get minimumPan():Number { return _minimumPan; }
  435. /**
  436. * @private
  437. */
  438. public function set minimumPan(value:Number):void {
  439. if (value == _minimumPan || isNaN(value)) return;
  440. _minimumPan = value;
  441. if (_pan < value) pan = value;
  442. }
  443. /**
  444. * maximumPan
  445. * @default Number.POSITIVE_INFINITY
  446. */
  447. public function get maximumPan():Number { return _maximumPan; }
  448. /**
  449. * @private
  450. */
  451. public function set maximumPan(value:Number):void {
  452. if (_maximumPan == value || isNaN(value)) return;
  453. _maximumPan = value;
  454. if (_pan > value) pan = value;
  455. }
  456. /**
  457. * minimumTilt
  458. * @default Number.NEGATIVE_INFINITY
  459. */
  460. public function get minimumTilt():Number { return _minimumTilt; }
  461. /**
  462. * @private
  463. */
  464. public function set minimumTilt(value:Number):void {
  465. if (value == _minimumTilt || isNaN(value)) return;
  466. _minimumTilt = value;
  467. if (_tilt < value) tilt = value;
  468. }
  469. /**
  470. * maximumTilt
  471. * @default Number.POSITIVE_INFINITY
  472. */
  473. public function get maximumTilt():Number { return _maximumTilt; }
  474. /**
  475. * @private
  476. */
  477. public function set maximumTilt(value:Number):void {
  478. if (value == _maximumTilt || isNaN(value)) return;
  479. _maximumTilt = value;
  480. if (_tilt > value) tilt = value;
  481. }
  482. /**
  483. * minimumHorizontalFieldOfView
  484. * @default NaN
  485. */
  486. public function get minimumHorizontalFieldOfView():Number { return _minimumHorizontalFieldOfView; }
  487. /**
  488. * @private
  489. */
  490. public function set minimumHorizontalFieldOfView(value:Number):void {
  491. if (value == _minimumHorizontalFieldOfView || isNaN(value)) return;
  492. _minimumHorizontalFieldOfView = value;
  493. adjustLimits();
  494. }
  495. /**
  496. * maximumHorizontalFieldOfView
  497. * @default NaN
  498. */
  499. public function get maximumHorizontalFieldOfView():Number { return _maximumHorizontalFieldOfView; }
  500. /**
  501. * @private
  502. */
  503. public function set maximumHorizontalFieldOfView(value:Number):void {
  504. if (value == _maximumHorizontalFieldOfView || isNaN(value)) return;
  505. _maximumHorizontalFieldOfView = value;
  506. adjustLimits();
  507. }
  508. /**
  509. * minimumVerticalFieldOfView
  510. * @default NaN
  511. */
  512. public function get minimumVerticalFieldOfView():Number { return _minimumVerticalFieldOfView; }
  513. /**
  514. * @private
  515. */
  516. public function set minimumVerticalFieldOfView(value:Number):void {
  517. if (value == _minimumVerticalFieldOfView || isNaN(value)) return;
  518. _minimumVerticalFieldOfView = value;
  519. adjustLimits();
  520. }
  521. /**
  522. * maximumVerticalFieldOfView
  523. * @default NaN
  524. */
  525. public function get maximumVerticalFieldOfView():Number { return _maximumVerticalFieldOfView; }
  526. /**
  527. * @private
  528. */
  529. public function set maximumVerticalFieldOfView(value:Number):void {
  530. if (value == _maximumVerticalFieldOfView || isNaN(value)) return;
  531. _maximumVerticalFieldOfView = value;
  532. adjustLimits();
  533. }
  534. /**
  535. * maximumPixelZoom
  536. * @default 1.0
  537. */
  538. public function get maximumPixelZoom():Number { return _maximumPixelZoom; }
  539. /**
  540. * @private
  541. */
  542. public function set maximumPixelZoom(value:Number):void {
  543. if (value == _maximumPixelZoom || isNaN(value)) return;
  544. _maximumPixelZoom = value;
  545. adjustLimits();
  546. }
  547. /**
  548. * Clones the properties of this view data object into another. If into arg is not null it will
  549. * clone into that ViewData object, otherwise it will clone into a new ViewData
  550. * @param into ViewData to clone into (optional, will create new if null)
  551. * @returns ViewData
  552. */
  553. public function clone(into:ViewData = null):ViewData {
  554. var ret:ViewData = (into == null) ? new ViewData() : into;
  555. ret.secondaryViewData = secondaryViewData;
  556. ret._pan = _pan;
  557. ret._tilt = _tilt;
  558. ret._fieldOfView = _fieldOfView;
  559. ret._boundsWidth = _boundsWidth;
  560. ret._boundsHeight = _boundsHeight;
  561. ret._tierThreshold = _tierThreshold;
  562. ret._path = _path;
  563. ret._tile = _tile;
  564. ret._minimumFieldOfView = _minimumFieldOfView;
  565. ret._minimumFieldOfViewDefault = _minimumFieldOfView
  566. ret._maximumFieldOfView = _maximumFieldOfView;
  567. ret._maximumFieldOfViewDefault = _maximumFieldOfView;
  568. ret._minimumPan = _minimumPan;
  569. ret._maximumPan = _maximumPan;
  570. ret._minimumTilt = _minimumTilt;
  571. ret._maximumTilt = _maximumTilt;
  572. ret._minimumVerticalFieldOfView = _minimumVerticalFieldOfView;
  573. ret._maximumVerticalFieldOfView = _maximumVerticalFieldOfView;
  574. ret._minimumHorizontalFieldOfView = _minimumHorizontalFieldOfView;
  575. ret._maximumHorizontalFieldOfView = _maximumHorizontalFieldOfView;
  576. ret._maximumPixelZoom = _maximumPixelZoom;
  577. ret.invalidTransform = invalidTransform;
  578. ret.invalidPerspective = invalidPerspective;
  579. ret.invalid = invalid;
  580. return ret;
  581. }
  582. private var __toRadians:Number = Math.PI / 180;
  583. private var __toDegrees:Number = 180 / Math.PI;
  584. /**
  585. * Sets minimumTilt, maximumTilt and maximumFieldOfView
  586. * according to minimumVerticalFieldOfView and maximumVerticalFieldOfView
  587. * needs to be called whenever panorama is loaded
  588. */
  589. private function adjustLimits():void {
  590. if (isNaN(_boundsWidth) || isNaN(_boundsHeight) || isNaN(_fieldOfView)) return;
  591. var maximumFieldOfViewVerticalTmp:Number;
  592. if (!isNaN(_minimumVerticalFieldOfView) && !isNaN(_maximumVerticalFieldOfView) &&
  593. (_maximumVerticalFieldOfView - _minimumVerticalFieldOfView) < 180) {
  594. maximumFieldOfViewVerticalTmp = __toDegrees * 2 *
  595. Math.atan((_boundsWidth/_boundsHeight) *
  596. Math.tan(__toRadians * 0.5 *
  597. (_maximumVerticalFieldOfView - _minimumVerticalFieldOfView)));
  598. if (isNaN(_maximumFieldOfViewDefault) || maximumFieldOfViewVerticalTmp < _maximumFieldOfViewDefault) {
  599. maximumFieldOfView = maximumFieldOfViewVerticalTmp;
  600. }else {
  601. maximumFieldOfView = _maximumFieldOfViewDefault;
  602. }
  603. }
  604. var maximumFieldOfViewHorizontalTmp:Number;
  605. if (!isNaN(_minimumHorizontalFieldOfView) && !isNaN(_maximumHorizontalFieldOfView) &&
  606. (_maximumHorizontalFieldOfView - _minimumHorizontalFieldOfView) < 180) {
  607. maximumFieldOfViewHorizontalTmp = __toDegrees * 2 *
  608. Math.atan((_boundsHeight/_boundsWidth) *
  609. Math.tan(__toRadians * 0.5 *
  610. (_maximumHorizontalFieldOfView - _minimumHorizontalFieldOfView)));
  611. if (isNaN(_maximumFieldOfViewDefault) || maximumFieldOfViewHorizontalTmp < _maximumFieldOfViewDefault) {
  612. maximumFieldOfView = maximumFieldOfViewHorizontalTmp;
  613. }else {
  614. maximumFieldOfView = _maximumFieldOfViewDefault;
  615. }
  616. }
  617. var cameraVFOV:Number = __toDegrees * 2 *
  618. Math.atan((_boundsHeight/_boundsWidth) *
  619. Math.tan(__toRadians * 0.5 *
  620. _fieldOfView));
  621. if (!isNaN(_minimumVerticalFieldOfView)) minimumTilt = _minimumVerticalFieldOfView + cameraVFOV / 2;
  622. if (!isNaN(_maximumVerticalFieldOfView)) maximumTilt = _maximumVerticalFieldOfView - cameraVFOV / 2;
  623. if (!isNaN(_minimumHorizontalFieldOfView)) minimumPan = _minimumHorizontalFieldOfView + _fieldOfView / 2;
  624. if (!isNaN(_maximumHorizontalFieldOfView)) maximumPan = _maximumHorizontalFieldOfView - _fieldOfView / 2;
  625. if (!isNaN(_maximumPixelZoom) && tile != null && tile.tilePyramid != null){
  626. var boundsDiagonal:Number = Math.sqrt( _boundsWidth * _boundsWidth + _boundsHeight * _boundsHeight);
  627. var minimumFieldOfViewTmp:Number = Math.atan(boundsWidth * 0.5 / (boundsDiagonal * 0.5 /
  628. Math.tan(boundsDiagonal / (0.0175 * tile.tilePyramid.width * 0.5 * _maximumPixelZoom)
  629. * 0.5 * __toRadians))) * 2 * __toDegrees; // 0.0175 = tg(1)
  630. if (!isNaN(_minimumFieldOfViewDefault) && minimumFieldOfViewTmp > 0){
  631. if (minimumFieldOfViewTmp < _minimumFieldOfViewDefault) {
  632. minimumFieldOfView = minimumFieldOfViewTmp;
  633. }else {
  634. minimumFieldOfView = _minimumFieldOfViewDefault;
  635. }
  636. }
  637. }
  638. }
  639. }
  640. }