diff --git a/src/GlobWeb.js b/src/GlobWeb.js index 7a0843c..6bd77a8 100644 --- a/src/GlobWeb.js +++ b/src/GlobWeb.js @@ -20,7 +20,7 @@ define( ["./Globe", "./GeoBound", "./WMSLayer", "./WMTSLayer", "./WCSElevationLayer", "./OSMLayer", "./BingLayer", "./VectorLayer", "./AtmosphereLayer", // Layers "./Navigation", "./FeatureStyle", "./Stats", "./KMLParser", // Others - "./PointRenderer", "./LineStringRenderable"], // Renderers + "./PointRenderer", "./LineStringRenderable", "./PolygonRenderer" ], // Renderers function(Globe, GeoBound, WMSLayer, WMTSLayer, WCSElevationLayer, OSMLayer, BingLayer, VectorLayer, AtmosphereLayer, Navigation, FeatureStyle, Stats, KMLParser) { // Declare GlobWeb diff --git a/src/KMLParser.js b/src/KMLParser.js index ae81d6e..d678df2 100644 --- a/src/KMLParser.js +++ b/src/KMLParser.js @@ -60,16 +60,16 @@ var KMLParser = (function() var coords = coordsText.trim().split(/[\s,]+/); for ( var i = 0; i < coords.length; i += 3 ) { - coordinates.push( [ parseFloat(coords[i]), parseFloat(coords[i+1]) ] ); + coordinates.push( [ parseFloat(coords[i]), parseFloat(coords[i+1]), parseFloat(coords[i+2]) ] ); } return coordinates; - } + }; /* * Parse KML geometry, return a GeoJSON geometry * @param node : a candiate node for geoemtry */ - var checkAndParseGeometry = function(node) + var checkAndParseGeometry = function(node,style) { switch ( node.nodeName ) { @@ -80,7 +80,7 @@ var KMLParser = (function() var children = node.childNodes; for (var i = 0; i < children.length; i++) { - var geometry = checkAndParseGeometry(children[i]); + var geometry = checkAndParseGeometry(children[i],style); if ( geometry ) { geoms.push( geometry ); @@ -102,8 +102,18 @@ var KMLParser = (function() break; case "Polygon": { + // Take into accout extresion + var extrude = node.getElementsByTagName("extrude"); + if ( extrude.length == 1 ) + { + style.extrude = parseInt( extrude[0].childNodes[0].nodeValue ) != 0; + } + + style.fill = true; + // TODO : manage holes - var coordNode = node.firstElementChild.getElementsByTagName("coordinates"); + var outerBoundary = node.getElementsByTagName("outerBoundaryIs"); + var coordNode = outerBoundary[0].getElementsByTagName("coordinates"); if ( coordNode.length == 1 ) { return { type: "Polygon", @@ -158,7 +168,7 @@ var KMLParser = (function() break; case "Style": { - var style = parseStyle(child,feature.properties.name); + var style = parseStyle(child,feature.properties.name,feature.properties.style); if ( style ) { feature.properties.style = style; @@ -169,7 +179,7 @@ var KMLParser = (function() // Try with geometry if ( feature.geometry == null ) { - feature.geometry = checkAndParseGeometry(child); + feature.geometry = checkAndParseGeometry(child,style); } } child = child.nextElementSibling; @@ -217,6 +227,24 @@ var KMLParser = (function() } } + /* + * Parse poly style + */ + var parsePolyStyle = function(node,style) + { + var child = node.firstElementChild; + while ( child ) + { + switch ( child.nodeName ) + { + case "color": + style.fillColor = fromStringToColor( child.childNodes[0].nodeValue ); + break; + } + child = child.nextElementSibling; + } + } + /* * Parse line style */ @@ -290,15 +318,15 @@ var KMLParser = (function() child = child.nextElementSibling; } } - + /* * Parse style */ - var parseStyle = function(node) + var parseStyle = function(node,parentStyle) { var id = '#' + node.getAttribute("id"); - var style = new FeatureStyle(); + var style = new FeatureStyle(parentStyle); styles[id] = style; // Iterate through child to manage all different style element @@ -307,6 +335,9 @@ var KMLParser = (function() { switch ( child.nodeName ) { + case "PolyStyle": + parsePolyStyle(child,style); + break; case "LineStyle": parseLineStyle(child,style); break; @@ -330,6 +361,9 @@ var KMLParser = (function() { switch ( node.nodeName ) { + case "Style": + parseStyle( node ); + break case "Placemark": parsePlacemark( node ); break diff --git a/src/PolygonRenderer.js b/src/PolygonRenderer.js new file mode 100644 index 0000000..a5f78a0 --- /dev/null +++ b/src/PolygonRenderer.js @@ -0,0 +1,260 @@ +/*************************************** + * Copyright 2011, 2012 GlobWeb contributors. + * + * This file is part of GlobWeb. + * + * GlobWeb is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License, or + * (at your option) any later version. + * + * GlobWeb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with If not, see . + ***************************************/ + +define( ['./CoordinateSystem','./VectorRendererManager','./FeatureStyle','./Program','./Triangulator'], + function(CoordinateSystem,VectorRendererManager,FeatureStyle,Program,Triangulator) { + +/**************************************************************************************************************/ + +/** @constructor + * Basic renderer for polygon + */ + +var PolygonRenderer = function(tileManager) +{ + this.renderContext = tileManager.renderContext; + var gl = this.renderContext.gl; + + this.renderables = []; + + this.vertexShader = "\ + attribute vec3 vertex;\n\ + uniform mat4 viewProjectionMatrix;\n\ + void main(void) \n\ + {\n\ + gl_Position = viewProjectionMatrix * vec4(vertex, 1.0);\n\ + }\n\ + "; + +var fragmentShader = "\ + precision lowp float; \n\ + uniform vec4 u_color;\n\ + void main(void)\n\ + {\n\ + gl_FragColor = u_color;\n\ + }\n\ + "; + + this.program = new Program(this.renderContext); + this.program.createFromSource(this.vertexShader, fragmentShader); +} + +/**************************************************************************************************************/ + +/** + * Add polygon to renderer + */ +PolygonRenderer.prototype.addGeometry = function(geometry, layer, style){ + + var gl = this.renderContext.gl; + + // Create renderable + var renderable = { + geometry : geometry, + style : style, + layer: layer, + vertexBuffer : gl.createBuffer(), + indexBuffer : gl.createBuffer(), + }; + + // Create texture + var self = this; + + // Create vertex buffer + gl.bindBuffer(gl.ARRAY_BUFFER, renderable.vertexBuffer); + + var coords = geometry['coordinates'][0]; + var vertices = new Float32Array( style.extrude ? coords.length * 6 : coords.length * 3 ); + + // For polygons only + for ( var i=0; i < coords.length; i++) + { + var pos3d = []; + CoordinateSystem.fromGeoTo3D(coords[i], pos3d); + vertices[i*3] = pos3d[0]; + vertices[i*3+1] = pos3d[1]; + vertices[i*3+2] = pos3d[2]; + } + + if ( style.extrude ) + { + var offset = coords.length * 3; + for ( var i=0; i < coords.length; i++) + { + var pos3d = []; + var coordAtZero = [ coords[i][0], coords[i][1], 0.0 ]; + CoordinateSystem.fromGeoTo3D( coordAtZero, pos3d); + vertices[offset] = pos3d[0]; + vertices[offset+1] = pos3d[1]; + vertices[offset+2] = pos3d[2]; + offset += 3; + } + } + + gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); + // Create index buffer(make shared ?) + var indices = []; + indices = Triangulator.process( coords ); + + if ( indices == null ) + { + console.error("Triangulation error ! Check if your GeoJSON geometry is valid"); + return false; + } + + + if ( style.extrude ) + { + var upOffset = 0; + var lowOffset = coords.length; + + for ( var i = 0; i < coords.length-1; i++ ) + { + indices.push( upOffset, upOffset + 1, lowOffset ); + indices.push( upOffset + 1, lowOffset + 1, lowOffset ); + + upOffset += 1; + lowOffset += 1; + } + } + + renderable.numTriIndices = indices.length; + + var offset = 0; + for ( var i = 0; i < coords.length-1; i++ ) + { + indices.push( offset, offset + 1 ); + offset += 1; + } + if ( style.extrude ) + { + var upOffset = 0; + var lowOffset = coords.length; + for ( var i = 0; i < coords.length-1; i++ ) + { + indices.push( upOffset, lowOffset ); + + upOffset += 1; + lowOffset += 1; + } + } + + renderable.numLineIndices = indices.length - renderable.numTriIndices; + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderable.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); + + this.renderables.push(renderable); + +} + +/**************************************************************************************************************/ + +/** + * Remove polygon from renderer + */ +PolygonRenderer.prototype.removeGeometry = function(geometry,style){ + + for ( var i = 0; i 0 ) + { + gl.uniform4f(this.program.uniforms["u_color"], style.strokeColor[0], style.strokeColor[1], style.strokeColor[2], style.strokeColor[3] * renderable.layer._opacity); + gl.drawElements( gl.LINES, renderable.numLineIndices, gl.UNSIGNED_SHORT, renderable.numTriIndices * 2); + } + } + + //gl.enable(gl.DEPTH_TEST); + gl.depthFunc(gl.LESS); + gl.disable(gl.BLEND); +} + +/**************************************************************************************************************/ + +// Register the renderer +VectorRendererManager.registerRenderer({ + creator: function(globe) { + return new PolygonRenderer(globe.tileManager); + }, + canApply: function(type,style) {return (type == "Polygon") && (style.fill == true); } +}); + +}); \ No newline at end of file