1 /*************************************** 2 * Copyright 2011, 2012 GlobWeb contributors. 3 * 4 * This file is part of GlobWeb. 5 * 6 * GlobWeb is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation, version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * GlobWeb is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GlobWeb. If not, see <http://www.gnu.org/licenses/>. 18 ***************************************/ 19 20 define(['./Utils', './BaseLayer', './GeoBound', './GroundOverlayRenderer'], 21 function(Utils, BaseLayer, GeoBound, GroundOverlayRenderer) { 22 23 24 /**************************************************************************************************************/ 25 26 /** @constructor 27 @export 28 This layer draws an image overlay draped onto the terrain 29 Arg : options 30 image : the image to drape on the terrain, can be an Image element or a string (url of the image) 31 quad : An array of 4 points to define the area on the terrain to drape the image 32 opacity : opacity of the layer 33 flipY : flip or not the image 34 */ 35 var GroundOverlayLayer = function( options ) 36 { 37 BaseLayer.prototype.constructor.call( this, options ); 38 39 this.quad = options.quad; 40 this.opacity = options.opacity || 1.0; 41 if ( typeof options.flipY === 'undefined' ) 42 { 43 this.flipY = true; 44 } 45 else 46 { 47 this.flipY = options.flipY; 48 } 49 50 // Compute the geo bound of the ground overlay 51 this.geoBound = new GeoBound(); 52 this.geoBound.computeFromCoordinates( this.quad ); 53 this.computeTransform(); 54 55 if (typeof options.image == "string") 56 { 57 this.image = new Image(); 58 this.image.crossOrigin = ''; 59 this.image.src = options.image; 60 } 61 else if ( options.image instanceof HTMLImageElement ) 62 { 63 this.image = options.image; 64 } 65 this.globe = null; 66 } 67 68 /**************************************************************************************************************/ 69 70 Utils.inherits( BaseLayer,GroundOverlayLayer ); 71 72 /**************************************************************************************************************/ 73 74 /** 75 Attach layer to the globe 76 */ 77 GroundOverlayLayer.prototype._attach = function( globe ) 78 { 79 // Add layer to ground overlay renderer, create one if needed 80 var renderer = globe.groundOverlayRenderer; 81 if ( !renderer ) 82 { 83 renderer = new GroundOverlayRenderer(globe.tileManager); 84 globe.tileManager.addPostRenderer( renderer ); 85 globe.groundOverlayRenderer = renderer; 86 } 87 renderer.groundOverlays.push( this ); 88 89 this.globe = globe; 90 } 91 92 //************************************************************************* 93 94 /** 95 Dtach layer from the globe 96 */ 97 GroundOverlayLayer.prototype._detach = function( globe ) 98 { 99 // Remove layer from the globe renderer for ground overlay 100 var prevRenderer = this.globe.groundOverlayRenderer; 101 if ( prevRenderer ) 102 { 103 var index = prevRenderer.groundOverlays.indexOf( this ); 104 if ( index != - 1 ) 105 { 106 prevRenderer.groundOverlays.splice(index,1); 107 108 if ( prevRenderer.groundOverlays.length == 0 ) 109 { 110 this.globe.tileManager.removePostRenderer( prevRenderer ); 111 this.globe.groundOverlayRenderer = null; 112 } 113 } 114 } 115 } 116 117 //************************************************************************* 118 119 /** 120 Transform a geographic position into the unit square of the ground overlay 121 */ 122 GroundOverlayLayer.prototype.transformFromSquare = function( point ) 123 { 124 var x = this.transform[0] * point[0] + this.transform[3] * point[1] + this.transform[6]; 125 var y = this.transform[1] * point[0] + this.transform[4] * point[1] + this.transform[7]; 126 var w = 1.0 / (this.transform[2] * point[0] + this.transform[5] * point[1] + this.transform[8]); 127 x *= w; 128 y *= w; 129 return [ x, y ]; 130 } 131 132 //************************************************************************* 133 134 /** 135 Transform from the unit square of the ground overlay into a unit square 136 */ 137 GroundOverlayLayer.prototype.transformToSquare = function( point ) 138 { 139 var x = this.inverseTransform[0] * point[0] + this.inverseTransform[3] * point[1] + this.inverseTransform[6]; 140 var y = this.inverseTransform[1] * point[0] + this.inverseTransform[4] * point[1] + this.inverseTransform[7]; 141 var w = 1.0 / (this.inverseTransform[2] * point[0] + this.inverseTransform[5] * point[1] + this.inverseTransform[8]); 142 x *= w; 143 y *= w; 144 return [ x, y ]; 145 } 146 147 //************************************************************************* 148 149 /** 150 Compute the inverse transform from unit square to geo position 151 Code taken from QTransform 152 */ 153 GroundOverlayLayer.prototype.computeInverse = function() 154 { 155 var det = this.transform[0] * (this.transform[8] * this.transform[4] - this.transform[5] * this.transform[7]) - 156 this.transform[3] * (this.transform[8] * this.transform[1] - this.transform[7]) * this.transform[3] 157 + this.transform[6] * ( this.transform[5] * this.transform[1] - this.transform[4] * this.transform[2]); 158 159 var h11, h12, h13, 160 h21, h22, h23, 161 h31, h32, h33; 162 h11 = this.transform[4]*this.transform[8] - this.transform[5]*this.transform[7]; 163 h21 = this.transform[5]*this.transform[6] - this.transform[3]*this.transform[8]; 164 h31 = this.transform[3]*this.transform[7] - this.transform[4]*this.transform[6]; 165 h12 = this.transform[2]*this.transform[7] - this.transform[1]*this.transform[8]; 166 h22 = this.transform[0]*this.transform[8] - this.transform[2]*this.transform[6]; 167 h32 = this.transform[1]*this.transform[6] - this.transform[0]*this.transform[7]; 168 h13 = this.transform[1]*this.transform[5] - this.transform[2]*this.transform[4]; 169 h23 = this.transform[2]*this.transform[3] - this.transform[0]*this.transform[5]; 170 h33 = this.transform[0]*this.transform[4] - this.transform[1]*this.transform[3]; 171 172 this.inverseTransform = [ h11 / det, h12 / det, h13 / det, 173 h21 / det, h22 / det, h23 / det, 174 h31 / det, h32 / det, h33 / det ]; 175 } 176 177 //************************************************************************* 178 179 /** 180 Compute the transform from geo position to unit square 181 Code taken from QTransform 182 */ 183 GroundOverlayLayer.prototype.computeTransform = function() 184 { 185 var dx0 = this.quad[0][0]; 186 var dx1 = this.quad[1][0]; 187 var dx2 = this.quad[2][0]; 188 var dx3 = this.quad[3][0]; 189 190 var dy0 = this.quad[0][1]; 191 var dy1 = this.quad[1][1]; 192 var dy2 = this.quad[2][1]; 193 var dy3 = this.quad[3][1]; 194 195 var ax = dx0 - dx1 + dx2 - dx3; 196 var ay = dy0 - dy1 + dy2 - dy3; 197 198 if (!ax && !ay) { //afine transform 199 this.transform = [ dx1 - dx0, dy1 - dy0, 0, 200 dx2 - dx1, dy2 - dy1, 0, 201 dx0, dy0, 1 ]; 202 } 203 else 204 { 205 var ax1 = dx1 - dx2; 206 var ax2 = dx3 - dx2; 207 var ay1 = dy1 - dy2; 208 var ay2 = dy3 - dy2; 209 210 /*determinants */ 211 var gtop = ax * ay2 - ax2 * ay; 212 var htop = ax1 * ay - ax * ay1; 213 var bottom = ax1 * ay2 - ax2 * ay1; 214 215 var a, b, c, d, e, f, g, h; /*i is always 1*/ 216 217 if (!bottom) 218 return; 219 220 g = gtop/bottom; 221 h = htop/bottom; 222 223 a = dx1 - dx0 + g * dx1; 224 b = dx3 - dx0 + h * dx3; 225 c = dx0; 226 d = dy1 - dy0 + g * dy1; 227 e = dy3 - dy0 + h * dy3; 228 f = dy0; 229 230 this.transform = [ a, d, g, 231 b, e, h, 232 c, f, 1.0 ]; 233 } 234 235 this.computeInverse(); 236 } 237 238 //************************************************************************* 239 240 return GroundOverlayLayer; 241 242 });