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(['./Tile', './HEALPixBase', './GeoBound', './CoordinateSystem', './Numeric', './AstroCoordTransform'], 21 function(Tile, HEALPixBase, GeoBound, CoordinateSystem, Numeric, AstroCoordTransform) { 22 23 /**************************************************************************************************************/ 24 25 /** @constructor 26 HEALPixTiling constructor 27 */ 28 var HEALPixTiling = function(order, options) 29 { 30 this.order = order; 31 this.nside = Math.pow(2,this.order); 32 this.coordSystem = options.coordSystem || "EQUATORIAL"; 33 } 34 35 /**************************************************************************************************************/ 36 37 /** 38 Generate the tiles for level zero 39 */ 40 HEALPixTiling.prototype.generateLevelZeroTiles = function( config, tilePool ) 41 { 42 config.skirt = false; 43 config.cullSign = -1; 44 config.tesselation = 5; 45 config.coordSystem = this.coordSystem; 46 47 var level0Tiles = []; 48 49 var qpf = Math.pow(this.nside,2); // quad per face 50 var nFaces = 12; 51 var nQuads = nFaces * qpf; 52 53 for (var i = 0; i < nQuads; i++){ 54 var face = Math.floor(i/qpf); 55 var tile = new HEALPixTile(this.order, i, face); 56 tile.config = config; 57 level0Tiles.push( tile ); 58 tile.generate(tilePool); 59 tile.state = Tile.State.NONE; 60 } 61 62 return level0Tiles; 63 } 64 65 /**************************************************************************************************************/ 66 67 /** 68 Locate a level zero tile 69 */ 70 HEALPixTiling.prototype.lonlat2LevelZeroIndex = function(lon,lat) 71 { 72 // var i = Math.floor( (lon + 180) * this.level0NumTilesX / 360 ); 73 // var j = Math.floor( (lat + 90) * this.level0NumTilesY / 180 ); 74 // return j * this.level0NumTilesX + i; 75 return 0; 76 77 } 78 79 /**************************************************************************************************************/ 80 81 /** 82 Return tile of given longitude/latitude from tiles array if exists, null otherwise 83 */ 84 HEALPixTiling.prototype.findInsideTile = function(lon, lat, tiles) 85 { 86 for ( var i=0; i<tiles.length; i++ ) 87 { 88 var tile = tiles[i]; 89 var index = HEALPixBase.lonLat2pix( tile.order, lon, lat ); 90 if ( index == tile.pixelIndex ) 91 return tile; 92 } 93 return null; 94 } 95 96 /**************************************************************************************************************/ 97 98 /** @constructor 99 Tile constructor 100 101 Quadrilateral which composes one pixel of HEALPix sphere 102 103 nside : 2^order 104 order : log2(nside); 105 pix : pixel index number 106 face : face number = [0..11] 107 */ 108 var HEALPixTile = function( order, pix, face ) 109 { 110 // Call ancestor constructor 111 Tile.prototype.constructor.call(this); 112 113 this.order = order; 114 this.nside = Math.pow(2, this.order); 115 this.pixelIndex = pix; 116 this.face = face; 117 118 // Compute texture transform 119 var width = 1728/64; 120 var height = 1856/64; 121 this.texTransform = [64/1728, 64/1856, ((this.pixelIndex % width))/width, ((Math.floor(this.pixelIndex/width))/height)]; 122 123 this.geoBound = null; 124 } 125 126 /**************************************************************************************************************/ 127 128 /** inherits from Tile */ 129 HEALPixTile.prototype = new Tile; 130 131 /**************************************************************************************************************/ 132 133 /** 134 Create the children 135 */ 136 HEALPixTile.prototype.createChildren = function() 137 { 138 // Create the children 139 140 var child00 = new HEALPixTile(this.order + 1, this.pixelIndex*4, this.face); 141 var child10 = new HEALPixTile(this.order + 1, this.pixelIndex*4+2, this.face); 142 var child01 = new HEALPixTile(this.order + 1, this.pixelIndex*4+1, this.face); 143 var child11 = new HEALPixTile(this.order + 1, this.pixelIndex*4+3, this.face); 144 145 child00.initFromParent( this, 0, 0 ); 146 child10.initFromParent( this, 1, 0 ); 147 child01.initFromParent( this, 0, 1 ); 148 child11.initFromParent( this, 1, 1 ); 149 150 this.children = [ child00, child10, child01, child11 ]; 151 152 } 153 154 /**************************************************************************************************************/ 155 156 /** 157 Compute the local matrix for the tile 158 */ 159 HEALPixTile.prototype.computeLocalMatrix = function(vertices){ 160 var matrix = mat4.create(); 161 162 var east = vec3.create(); 163 var north = vec3.create(); 164 var up = vec3.create(); 165 166 var mx = 0; 167 var my = 0; 168 var mz = 0; 169 for(var i=0; i<vertices.length; i++){ 170 mx+=vertices[i][0]; 171 my+=vertices[i][1]; 172 mz+=vertices[i][2]; 173 } 174 var barycenter = vec3.create([mx/vertices.length,my/vertices.length,mz/vertices.length]); 175 176 vec3.set(barycenter,up); 177 vec3.normalize(up); 178 179 vec3.subtract(vertices[0],vertices[3],north); 180 181 vec3.cross(up, north, east); 182 vec3.normalize(east); 183 vec3.cross(up, east, north); 184 vec3.normalize(north); 185 186 matrix[0] = east[0]; 187 matrix[1] = east[1]; 188 matrix[2] = east[2]; 189 matrix[3] = 0.0; 190 191 matrix[4] = north[0]; 192 matrix[5] = north[1]; 193 matrix[6] = north[2]; 194 matrix[7] = 0.0; 195 196 matrix[8] = up[0]; 197 matrix[9] = up[1]; 198 matrix[10] = up[2]; 199 matrix[11] = 0.0; 200 201 matrix[12] = barycenter[0]; 202 matrix[13] = barycenter[1]; 203 matrix[14] = barycenter[2]; 204 matrix[15] = 1.0; 205 206 return matrix; 207 } 208 209 /**************************************************************************************************************/ 210 211 /** 212 Generate vertices for tile 213 */ 214 HEALPixTile.prototype.generateVertices = function() 215 { 216 // Build the vertices 217 var size = this.config.tesselation; 218 var worldSpaceVertices = new Array(); 219 var step = 1./(size - 1); 220 221 // xyf calculation 222 //var xyf = new healpixBase.Xyf(this.pixelIndex, this.order); 223 var pix=this.pixelIndex&(this.nside*this.nside-1); 224 var ix = HEALPixBase.compress_bits(pix); 225 var iy = HEALPixBase.compress_bits(pix>>>1); 226 227 // Compute array of worldspace coordinates 228 for(var u = 0; u < size; u++){ 229 for(var v = 0; v < size; v++){ 230 if ( this.config.coordSystem == 'GALACTIC' ) 231 { 232 var vertice = HEALPixBase.fxyf((ix+u*step)/this.nside, (iy+v*step)/this.nside, this.face); 233 var geo = CoordinateSystem.from3DToGeo( vertice ); 234 var eq = AstroCoordTransform.transformInDeg( geo, AstroCoordTransform.Type.GAL2EQ ); 235 236 worldSpaceVertices[u*size + v] = CoordinateSystem.fromGeoTo3D( eq ); 237 } 238 else 239 { 240 worldSpaceVertices[u*size + v] = HEALPixBase.fxyf((ix+u*step)/this.nside, (iy+v*step)/this.nside, this.face); 241 } 242 } 243 } 244 245 // Compute geoBound using corners of tile 246 this.geoBound = new GeoBound(); 247 248 var corners = []; 249 corners.push( CoordinateSystem.from3DToGeo( worldSpaceVertices[0] ) ); 250 corners.push( CoordinateSystem.from3DToGeo( worldSpaceVertices[size-1] ) ); 251 corners.push( CoordinateSystem.from3DToGeo( worldSpaceVertices[size*(size-1)] ) ); 252 corners.push( CoordinateSystem.from3DToGeo( worldSpaceVertices[size*size-1] ) ); 253 254 this.geoBound.computeFromCoordinates( corners ); 255 256 // Compute tile matrix 257 this.matrix = this.computeLocalMatrix(worldSpaceVertices); 258 var invMatrix = mat4.create(); 259 mat4.inverse( this.matrix, invMatrix ); 260 this.inverseMatrix = invMatrix; 261 262 // Compute tile matrix 263 /*var center = HEALPixBase.fxyf((ix+0.5)/this.nside, (iy+0.5)/this.nside, face); 264 var geoCenter = CoordinateSystem.from3DToGeo(center); 265 this.matrix = CoordinateSystem.getLHVTransform( geoCenter ); 266 var invMatrix = mat4.create(); 267 mat4.inverse( this.matrix, invMatrix ); 268 this.inverseMatrix = invMatrix;*/ 269 270 // Build the vertices 271 var vertices = new Float32Array( 3*size*size ); 272 273 // Vertex coordinates in local space 274 var vertexOffset = 0; 275 for(var i=0;i<worldSpaceVertices.length;i++){ 276 vertices[vertexOffset] = invMatrix[0]*worldSpaceVertices[i][0] + invMatrix[4]*worldSpaceVertices[i][1] + invMatrix[8]*worldSpaceVertices[i][2] + invMatrix[12]; 277 vertices[vertexOffset+1] = invMatrix[1]*worldSpaceVertices[i][0] + invMatrix[5]*worldSpaceVertices[i][1] + invMatrix[9]*worldSpaceVertices[i][2] + invMatrix[13]; 278 vertices[vertexOffset+2] = invMatrix[2]*worldSpaceVertices[i][0] + invMatrix[6]*worldSpaceVertices[i][1] + invMatrix[10]*worldSpaceVertices[i][2] + invMatrix[14]; 279 vertexOffset += 3; 280 } 281 282 return vertices; 283 } 284 285 /**************************************************************************************************************/ 286 287 return HEALPixTiling; 288 289 });