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','./VectorRendererManager','./TiledVectorRenderable','./TiledVectorRenderer','./Numeric'], 21 function(Utils,VectorRendererManager,TiledVectorRenderable,TiledVectorRenderer,Numeric) { 22 23 /**************************************************************************************************************/ 24 25 26 /** @constructor 27 * @extends TiledVectorRenderable 28 * LineStringRenderable manages lineString data to be rendered on a tile. 29 */ 30 var LineStringRenderable = function( bucket, gl ) 31 { 32 TiledVectorRenderable.prototype.constructor.call(this,bucket,gl); 33 this.glMode = gl.LINES; 34 } 35 36 /**************************************************************************************************************/ 37 38 // Inheritance 39 Utils.inherits(TiledVectorRenderable,LineStringRenderable); 40 41 /**************************************************************************************************************/ 42 43 /** 44 * Build children indices. 45 * Children indices are used to render a tile children when it is not completely loaded. 46 */ 47 LineStringRenderable.prototype.buildChildrenIndices = function() 48 { 49 this.childrenIndices = [ [], [], [], [] ]; 50 this.childrenIndexBuffers = [ null, null, null, null ]; 51 52 for ( var n = 0; n < this.indices.length/2; n++ ) 53 { 54 var vertexOffset1 = 3 * this.indices[2*n]; 55 var vertexOffset2 = 3 * this.indices[2*n+1]; 56 57 var x1 = this.vertices[vertexOffset1]; 58 var x2 = this.vertices[vertexOffset2]; 59 60 var i = 0; 61 if ( x1 > 0 || ( x1 == 0 && x2 > 0 ) ) 62 i = 1; 63 64 var y1 = this.vertices[vertexOffset1+1]; 65 var y2 = this.vertices[vertexOffset2+1]; 66 67 var j = 1; 68 if ( y1 > 0 || ( y1 == 0 && y2 > 0 ) ) 69 j = 0; 70 71 this.childrenIndices[ 2*j + i ].push( this.indices[2*n] ) 72 this.childrenIndices[ 2*j + i ].push( this.indices[2*n+1] ) 73 } 74 } 75 76 /**************************************************************************************************************/ 77 78 /** 79 * Build vertices and indices from the coordinates. 80 * Clamp a line string on a tile 81 */ 82 LineStringRenderable.prototype.buildVerticesAndIndices = function( tile, coords ) 83 { 84 if ( coords.length == 0 ) 85 return; 86 87 // Fix date line for coordinates first 88 var coordinates = this._fixDateLine( tile, coords ); 89 90 var size = tile.config.tesselation; 91 var vs = tile.config.vertexSize; 92 93 // Convert lon/lat coordinates to tile coordinates (between [0,size-1] inside the tile) 94 var tileCoords = tile.lonlat2tile(coords); 95 96 for ( var i = 0; i < coordinates.length - 1; i++ ) 97 { 98 var u1 = tileCoords[i][0]; 99 var v1 = tileCoords[i][1]; 100 101 var u2 = tileCoords[i+1][0]; 102 var v2 = tileCoords[i+1][1]; 103 104 var intersections = []; 105 106 // Intersect the segment with the tile grid 107 108 // First intersect with columns 109 // uStart, uEnd represent a range of the tile columns that the segement can intersect 110 var uStart = Math.max( -1, Math.min( u1, u2 ) ); 111 var uEnd = Math.min( size-1, Math.max( u1, u2 ) ); 112 for ( var n = Math.floor(uStart)+1; n < Math.floor(uEnd)+1; n++) 113 { 114 var u = n; 115 var res = Numeric.lineIntersection( u1, v1, u2, v2, u, 0.0, u, size-1 ); 116 if ( res[0] > 0.0 && res[0] < 1.0 && res[1] >= 0.0 && res[1] <= 1.0 ) 117 { 118 var v = res[1] * (size-1); 119 var vFloor = Math.floor( v ); 120 var vFrac = v - vFloor; 121 var vertexOffset = vs*( vFloor*size + n ); 122 var x = (1.0 - vFrac) * tile.vertices[ vertexOffset ] + vFrac * tile.vertices[ vertexOffset + vs*size ]; 123 var y = (1.0 - vFrac) * tile.vertices[ vertexOffset + 1 ] + vFrac * tile.vertices[ vertexOffset + vs*size + 1 ]; 124 var z = (1.0 - vFrac) * tile.vertices[ vertexOffset + 2 ] + vFrac * tile.vertices[ vertexOffset + vs*size + 2 ]; 125 intersections.push( [ res[0], x, y, z ] ); 126 } 127 } 128 129 // Then intersect with rows 130 // vStart, vEnd represent a range of the tile rows that the segement can intersect 131 var vStart = Math.max( -1, Math.min( v1, v2 ) ); 132 var vEnd = Math.min( size-1, Math.max( v1, v2 ) ); 133 for ( var n = Math.floor(vStart)+1; n < Math.floor(vEnd)+1; n++) 134 { 135 var v = n; 136 var res = Numeric.lineIntersection( u1, v1, u2, v2, 0.0, v, size-1, v ); 137 if ( res[0] > 0.0 && res[0] < 1.0 && res[1] >= 0.0 && res[1] <= 1.0 ) 138 { 139 var u = res[1] * (size-1); 140 var uFloor = Math.floor( u ); 141 var uFrac = u - uFloor; 142 var vertexOffset = vs*( n*size + uFloor ); 143 var x = (1.0 - uFrac) * tile.vertices[ vertexOffset ] + uFrac * tile.vertices[ vertexOffset + vs ]; 144 var y = (1.0 - uFrac) * tile.vertices[ vertexOffset + 1 ] + uFrac * tile.vertices[ vertexOffset + vs+1 ]; 145 var z = (1.0 - uFrac) * tile.vertices[ vertexOffset + 2 ] + uFrac * tile.vertices[ vertexOffset + vs+2 ]; 146 intersections.push( [ res[0], x, y, z ] ); 147 } 148 } 149 /* for ( var n = 0; n < size; n++) 150 { 151 var u = n; 152 var v = n; 153 var res = lineIntersection( u1, v1, u2, v2, u, 0.0, 0.0, v ); 154 if ( res[0] > 0.0 && res[0] < 1.0 && res[1] > 0.0 && res[1] < 1.0 ) 155 { 156 intersections.push( res[0] ); 157 } 158 if ( n != size-1 ) 159 { 160 var res = lineIntersection( u1, v1, u2, v2, u, size, size, v ); 161 if ( res[0] > 0.0 && res[0] < 1.0 && res[1] > 0.0 && res[1] < 1.0 ) 162 { 163 intersections.push( res[0] ); 164 } 165 } 166 }*/ 167 168 // Sort intersections found on the segment 169 intersections.sort( function(a,b) { return a[0] > b[0]; } ); 170 171 // Build the vertices from the intersections found 172 var startIndex = this.vertices.length / 3; 173 174 if ( u1 >= 0.0 && u1 <= size-1 && v1 >= 0.0 && v1 <= size-1 ) 175 { 176 var vec = tile.computePosition(u1,v1); 177 this.vertices.push( vec[0] ); 178 this.vertices.push( vec[1] ); 179 this.vertices.push( vec[2] ); 180 } 181 182 for ( var n = 0; n < intersections.length; n++ ) 183 { 184 this.vertices.push( intersections[n][1] ); 185 this.vertices.push( intersections[n][2] ); 186 this.vertices.push( intersections[n][3] ); 187 } 188 189 if ( u2 >= 0.0 && u2 <= size-1 && v2 >= 0.0 && v2 <= size-1 ) 190 { 191 var vec = tile.computePosition(u2,v2); 192 this.vertices.push( vec[0] ); 193 this.vertices.push( vec[1] ); 194 this.vertices.push( vec[2] ); 195 } 196 197 var endIndex = this.vertices.length / 3; 198 199 for ( var n = startIndex; n < endIndex - 1; n++ ) 200 { 201 this.indices.push( n ); 202 this.indices.push( n+1 ); 203 } 204 } 205 } 206 207 /**************************************************************************************************************/ 208 209 // Register the renderer 210 VectorRendererManager.registerRenderer({ 211 creator: function(globe) { 212 var lineStringRenderer = new TiledVectorRenderer(globe.tileManager); 213 lineStringRenderer.id = "lineString"; 214 lineStringRenderer.styleEquals = function(s1,s2) { 215 if (!s1.isEqualForLine) 216 console.log(s1); 217 return s1.isEqualForLine(s2); 218 }; 219 lineStringRenderer.renderableConstuctor = LineStringRenderable; 220 return lineStringRenderer; 221 }, 222 canApply: function(type,style) { 223 // LineStringRenderer supports line string (multi or not) and polygon (or multi) when not filled 224 225 return type == "LineString" || type == "MultiLineString" 226 || (!style.fill && (type == "Polygon" || type == "MultiPolygon")); 227 } 228 }); 229 230 return LineStringRenderable; 231 232 }); 233 234