diff --git a/OpenLayers.js b/OpenLayers.js
new file mode 100644
index 0000000000..6fe09e825b
--- /dev/null
+++ b/OpenLayers.js
@@ -0,0 +1,1352 @@
+/*
+
+ OpenLayers.js -- OpenLayers Map Viewer Library
+
+ Copyright (c) 2006-2012 by OpenLayers Contributors
+ Published under the 2-clause BSD license.
+ See http://openlayers.org/dev/license.txt for the full text of the license, and http://openlayers.org/dev/authors.txt for full list of contributors.
+
+ Includes compressed code under the following licenses:
+
+ (For uncompressed versions of the code used, please see the
+ OpenLayers Github repository: )
+
+*/
+
+/**
+ * Contains XMLHttpRequest.js
+ * Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+/**
+ * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
+ * Copyright (c) 2006, Yahoo! Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission of Yahoo! Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+var OpenLayers={VERSION_NUMBER:"Release 2.13 dev",singleFile:true,_getScriptLocation:(function(){var r=new RegExp("(^|(.*?\\/))(OpenLayers[^\\/]*?\\.js)(\\?|$)"),s=document.getElementsByTagName('script'),src,m,l="";for(var i=0,len=s.length;i0){fig=parseFloat(num.toPrecision(sig));}
+return fig;},format:function(num,dec,tsep,dsep){dec=(typeof dec!="undefined")?dec:0;tsep=(typeof tsep!="undefined")?tsep:OpenLayers.Number.thousandsSeparator;dsep=(typeof dsep!="undefined")?dsep:OpenLayers.Number.decimalSeparator;if(dec!=null){num=parseFloat(num.toFixed(dec));}
+var parts=num.toString().split(".");if(parts.length==1&&dec==null){dec=0;}
+var integer=parts[0];if(tsep){var thousands=/(-?[0-9]+)([0-9]{3})/;while(thousands.test(integer)){integer=integer.replace(thousands,"$1"+tsep+"$2");}}
+var str;if(dec==0){str=integer;}else{var rem=parts.length>1?parts[1]:"0";if(dec!=null){rem=rem+new Array(dec-rem.length+1).join("0");}
+str=integer+dsep+rem;}
+return str;}};OpenLayers.Function={bind:function(func,object){var args=Array.prototype.slice.apply(arguments,[2]);return function(){var newArgs=args.concat(Array.prototype.slice.apply(arguments,[0]));return func.apply(object,newArgs);};},bindAsEventListener:function(func,object){return function(event){return func.call(object,event||window.event);};},False:function(){return false;},True:function(){return true;},Void:function(){}};OpenLayers.Array={filter:function(array,callback,caller){var selected=[];if(Array.prototype.filter){selected=array.filter(callback,caller);}else{var len=array.length;if(typeof callback!="function"){throw new TypeError();}
+for(var i=0;i1){var newArgs=[C,P].concat(Array.prototype.slice.call(arguments).slice(1,len-1),F);OpenLayers.inherit.apply(null,newArgs);}else{C.prototype=F;}
+return C;};OpenLayers.inherit=function(C,P){var F=function(){};F.prototype=P.prototype;C.prototype=new F;var i,l,o;for(i=2,l=arguments.length;ithis.right)){this.right=bounds.right;}
+if((this.top==null)||(bounds.top>this.top)){this.top=bounds.top;}}}},containsLonLat:function(ll,options){if(typeof options==="boolean"){options={inclusive:options};}
+options=options||{};var contains=this.contains(ll.lon,ll.lat,options.inclusive),worldBounds=options.worldBounds;if(worldBounds&&!contains){var worldWidth=worldBounds.getWidth();var worldCenterX=(worldBounds.left+worldBounds.right)/2;var worldsAway=Math.round((ll.lon-worldCenterX)/worldWidth);contains=this.containsLonLat({lon:ll.lon-worldsAway*worldWidth,lat:ll.lat},{inclusive:options.inclusive});}
+return contains;},containsPixel:function(px,inclusive){return this.contains(px.x,px.y,inclusive);},contains:function(x,y,inclusive){if(inclusive==null){inclusive=true;}
+if(x==null||y==null){return false;}
+x=OpenLayers.Util.toFloat(x);y=OpenLayers.Util.toFloat(y);var contains=false;if(inclusive){contains=((x>=this.left)&&(x<=this.right)&&(y>=this.bottom)&&(y<=this.top));}else{contains=((x>this.left)&&(xthis.bottom)&&(y=self.bottom)&&(bounds.bottom<=self.top))||((self.bottom>=bounds.bottom)&&(self.bottom<=bounds.top)));var inTop=(((bounds.top>=self.bottom)&&(bounds.top<=self.top))||((self.top>bounds.bottom)&&(self.top=self.left)&&(bounds.left<=self.right))||((self.left>=bounds.left)&&(self.left<=bounds.right)));var inRight=(((bounds.right>=self.left)&&(bounds.right<=self.right))||((self.right>=bounds.left)&&(self.right<=bounds.right)));intersects=((inBottom||inTop)&&(inLeft||inRight));}
+if(options.worldBounds&&!intersects){var world=options.worldBounds;var width=world.getWidth();var selfCrosses=!world.containsBounds(self);var boundsCrosses=!world.containsBounds(bounds);if(selfCrosses&&!boundsCrosses){bounds=bounds.add(-width,0);intersects=self.intersectsBounds(bounds,{inclusive:options.inclusive});}else if(boundsCrosses&&!selfCrosses){self=self.add(-width,0);intersects=bounds.intersectsBounds(self,{inclusive:options.inclusive});}}
+return intersects;},containsBounds:function(bounds,partial,inclusive){if(partial==null){partial=false;}
+if(inclusive==null){inclusive=true;}
+var bottomLeft=this.contains(bounds.left,bounds.bottom,inclusive);var bottomRight=this.contains(bounds.right,bounds.bottom,inclusive);var topLeft=this.contains(bounds.left,bounds.top,inclusive);var topRight=this.contains(bounds.right,bounds.top,inclusive);return(partial)?(bottomLeft||bottomRight||topLeft||topRight):(bottomLeft&&bottomRight&&topLeft&&topRight);},determineQuadrant:function(lonlat){var quadrant="";var center=this.getCenterLonLat();quadrant+=(lonlat.lat=maxExtent.right&&newBounds.right>maxExtent.right){newBounds=newBounds.add(-width,0);}
+var newLeft=newBounds.left+leftTolerance;if(newLeftmaxExtent.left&&newBounds.right-rightTolerance>maxExtent.right){newBounds=newBounds.add(-width,0);}}
+return newBounds;},CLASS_NAME:"OpenLayers.Bounds"});OpenLayers.Bounds.fromString=function(str,reverseAxisOrder){var bounds=str.split(",");return OpenLayers.Bounds.fromArray(bounds,reverseAxisOrder);};OpenLayers.Bounds.fromArray=function(bbox,reverseAxisOrder){return reverseAxisOrder===true?new OpenLayers.Bounds(bbox[1],bbox[0],bbox[3],bbox[2]):new OpenLayers.Bounds(bbox[0],bbox[1],bbox[2],bbox[3]);};OpenLayers.Bounds.fromSize=function(size){return new OpenLayers.Bounds(0,size.h,size.w,0);};OpenLayers.Bounds.oppositeQuadrant=function(quadrant){var opp="";opp+=(quadrant.charAt(0)=='t')?'b':'t';opp+=(quadrant.charAt(1)=='l')?'r':'l';return opp;};OpenLayers.Element={visible:function(element){return OpenLayers.Util.getElement(element).style.display!='none';},toggle:function(){for(var i=0,len=arguments.length;imaxExtent.right){newLonLat.lon-=maxExtent.getWidth();}}
+return newLonLat;},CLASS_NAME:"OpenLayers.LonLat"});OpenLayers.LonLat.fromString=function(str){var pair=str.split(",");return new OpenLayers.LonLat(pair[0],pair[1]);};OpenLayers.LonLat.fromArray=function(arr){var gotArr=OpenLayers.Util.isArray(arr),lon=gotArr&&arr[0],lat=gotArr&&arr[1];return new OpenLayers.LonLat(lon,lat);};OpenLayers.Pixel=OpenLayers.Class({x:0.0,y:0.0,initialize:function(x,y){this.x=parseFloat(x);this.y=parseFloat(y);},toString:function(){return("x="+this.x+",y="+this.y);},clone:function(){return new OpenLayers.Pixel(this.x,this.y);},equals:function(px){var equals=false;if(px!=null){equals=((this.x==px.x&&this.y==px.y)||(isNaN(this.x)&&isNaN(this.y)&&isNaN(px.x)&&isNaN(px.y)));}
+return equals;},distanceTo:function(px){return Math.sqrt(Math.pow(this.x-px.x,2)+
+Math.pow(this.y-px.y,2));},add:function(x,y){if((x==null)||(y==null)){throw new TypeError('Pixel.add cannot receive null values');}
+return new OpenLayers.Pixel(this.x+x,this.y+y);},offset:function(px){var newPx=this.clone();if(px){newPx=this.add(px.x,px.y);}
+return newPx;},CLASS_NAME:"OpenLayers.Pixel"});OpenLayers.Size=OpenLayers.Class({w:0.0,h:0.0,initialize:function(w,h){this.w=parseFloat(w);this.h=parseFloat(h);},toString:function(){return("w="+this.w+",h="+this.h);},clone:function(){return new OpenLayers.Size(this.w,this.h);},equals:function(sz){var equals=false;if(sz!=null){equals=((this.w==sz.w&&this.h==sz.h)||(isNaN(this.w)&&isNaN(this.h)&&isNaN(sz.w)&&isNaN(sz.h)));}
+return equals;},CLASS_NAME:"OpenLayers.Size"});OpenLayers.Console={log:function(){},debug:function(){},info:function(){},warn:function(){},error:function(){},userError:function(error){alert(error);},assert:function(){},dir:function(){},dirxml:function(){},trace:function(){},group:function(){},groupEnd:function(){},time:function(){},timeEnd:function(){},profile:function(){},profileEnd:function(){},count:function(){},CLASS_NAME:"OpenLayers.Console"};(function(){var scripts=document.getElementsByTagName("script");for(var i=0,len=scripts.length;i=0;i--){if(array[i]==item){array.splice(i,1);}}
+return array;};OpenLayers.Util.indexOf=function(array,obj){if(typeof array.indexOf=="function"){return array.indexOf(obj);}else{for(var i=0,len=array.length;i=0.0&&parseFloat(opacity)<1.0){element.style.filter='alpha(opacity='+(opacity*100)+')';element.style.opacity=opacity;}else if(parseFloat(opacity)==1.0){element.style.filter='';element.style.opacity='';}};OpenLayers.Util.createDiv=function(id,px,sz,imgURL,position,border,overflow,opacity){var dom=document.createElement('div');if(imgURL){dom.style.backgroundImage='url('+imgURL+')';}
+if(!id){id=OpenLayers.Util.createUniqueID("OpenLayersDiv");}
+if(!position){position="absolute";}
+OpenLayers.Util.modifyDOMElement(dom,id,px,sz,position,border,overflow,opacity);return dom;};OpenLayers.Util.createImage=function(id,px,sz,imgURL,position,border,opacity,delayDisplay){var image=document.createElement("img");if(!id){id=OpenLayers.Util.createUniqueID("OpenLayersDiv");}
+if(!position){position="relative";}
+OpenLayers.Util.modifyDOMElement(image,id,px,sz,position,border,null,opacity);if(delayDisplay){image.style.display="none";function display(){image.style.display="";OpenLayers.Event.stopObservingElement(image);}
+OpenLayers.Event.observe(image,"load",display);OpenLayers.Event.observe(image,"error",display);}
+image.style.alt=id;image.galleryImg="no";if(imgURL){image.src=imgURL;}
+return image;};OpenLayers.IMAGE_RELOAD_ATTEMPTS=0;OpenLayers.Util.alphaHackNeeded=null;OpenLayers.Util.alphaHack=function(){if(OpenLayers.Util.alphaHackNeeded==null){var arVersion=navigator.appVersion.split("MSIE");var version=parseFloat(arVersion[1]);var filter=false;try{filter=!!(document.body.filters);}catch(e){}
+OpenLayers.Util.alphaHackNeeded=(filter&&(version>=5.5)&&(version<7));}
+return OpenLayers.Util.alphaHackNeeded;};OpenLayers.Util.modifyAlphaImageDiv=function(div,id,px,sz,imgURL,position,border,sizing,opacity){OpenLayers.Util.modifyDOMElement(div,id,px,sz,position,null,null,opacity);var img=div.childNodes[0];if(imgURL){img.src=imgURL;}
+OpenLayers.Util.modifyDOMElement(img,div.id+"_innerImage",null,sz,"relative",border);if(OpenLayers.Util.alphaHack()){if(div.style.display!="none"){div.style.display="inline-block";}
+if(sizing==null){sizing="scale";}
+div.style.filter="progid:DXImageTransform.Microsoft"+".AlphaImageLoader(src='"+img.src+"', "+"sizingMethod='"+sizing+"')";if(parseFloat(div.style.opacity)>=0.0&&parseFloat(div.style.opacity)<1.0){div.style.filter+=" alpha(opacity="+div.style.opacity*100+")";}
+img.style.filter="alpha(opacity=0)";}};OpenLayers.Util.createAlphaImageDiv=function(id,px,sz,imgURL,position,border,sizing,opacity,delayDisplay){var div=OpenLayers.Util.createDiv();var img=OpenLayers.Util.createImage(null,null,null,null,null,null,null,delayDisplay);img.className="olAlphaImg";div.appendChild(img);OpenLayers.Util.modifyAlphaImageDiv(div,id,px,sz,imgURL,position,border,sizing,opacity);return div;};OpenLayers.Util.upperCaseObject=function(object){var uObject={};for(var key in object){uObject[key.toUpperCase()]=object[key];}
+return uObject;};OpenLayers.Util.applyDefaults=function(to,from){to=to||{};var fromIsEvt=typeof window.Event=="function"&&from instanceof window.Event;for(var key in from){if(to[key]===undefined||(!fromIsEvt&&from.hasOwnProperty&&from.hasOwnProperty(key)&&!to.hasOwnProperty(key))){to[key]=from[key];}}
+if(!fromIsEvt&&from&&from.hasOwnProperty&&from.hasOwnProperty('toString')&&!to.hasOwnProperty('toString')){to.toString=from.toString;}
+return to;};OpenLayers.Util.getParameterString=function(params){var paramsArray=[];for(var key in params){var value=params[key];if((value!=null)&&(typeof value!='function')){var encodedValue;if(typeof value=='object'&&value.constructor==Array){var encodedItemArray=[];var item;for(var itemIndex=0,len=value.length;itemIndex1e-12&&--iterLimit>0){var sinLambda=Math.sin(lambda),cosLambda=Math.cos(lambda);var sinSigma=Math.sqrt((cosU2*sinLambda)*(cosU2*sinLambda)+
+(cosU1*sinU2-sinU1*cosU2*cosLambda)*(cosU1*sinU2-sinU1*cosU2*cosLambda));if(sinSigma==0){return 0;}
+var cosSigma=sinU1*sinU2+cosU1*cosU2*cosLambda;var sigma=Math.atan2(sinSigma,cosSigma);var alpha=Math.asin(cosU1*cosU2*sinLambda/sinSigma);var cosSqAlpha=Math.cos(alpha)*Math.cos(alpha);var cos2SigmaM=cosSigma-2*sinU1*sinU2/cosSqAlpha;var C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));lambdaP=lambda;lambda=L+(1-C)*f*Math.sin(alpha)*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));}
+if(iterLimit==0){return NaN;}
+var uSq=cosSqAlpha*(a*a-b*b)/(b*b);var A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));var B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)));var deltaSigma=B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
+B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));var s=b*A*(sigma-deltaSigma);var d=s.toFixed(3)/1000;return d;};OpenLayers.Util.destinationVincenty=function(lonlat,brng,dist){var u=OpenLayers.Util;var ct=u.VincentyConstants;var a=ct.a,b=ct.b,f=ct.f;var lon1=lonlat.lon;var lat1=lonlat.lat;var s=dist;var alpha1=u.rad(brng);var sinAlpha1=Math.sin(alpha1);var cosAlpha1=Math.cos(alpha1);var tanU1=(1-f)*Math.tan(u.rad(lat1));var cosU1=1/Math.sqrt((1+tanU1*tanU1)),sinU1=tanU1*cosU1;var sigma1=Math.atan2(tanU1,cosAlpha1);var sinAlpha=cosU1*sinAlpha1;var cosSqAlpha=1-sinAlpha*sinAlpha;var uSq=cosSqAlpha*(a*a-b*b)/(b*b);var A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));var B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)));var sigma=s/(b*A),sigmaP=2*Math.PI;while(Math.abs(sigma-sigmaP)>1e-12){var cos2SigmaM=Math.cos(2*sigma1+sigma);var sinSigma=Math.sin(sigma);var cosSigma=Math.cos(sigma);var deltaSigma=B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
+B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));sigmaP=sigma;sigma=s/(b*A)+deltaSigma;}
+var tmp=sinU1*sinSigma-cosU1*cosSigma*cosAlpha1;var lat2=Math.atan2(sinU1*cosSigma+cosU1*sinSigma*cosAlpha1,(1-f)*Math.sqrt(sinAlpha*sinAlpha+tmp*tmp));var lambda=Math.atan2(sinSigma*sinAlpha1,cosU1*cosSigma-sinU1*sinSigma*cosAlpha1);var C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));var L=lambda-(1-C)*f*sinAlpha*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));var revAz=Math.atan2(sinAlpha,-tmp);return new OpenLayers.LonLat(lon1+u.deg(L),u.deg(lat2));};OpenLayers.Util.getParameters=function(url){url=(url===null||url===undefined)?window.location.href:url;var paramsString="";if(OpenLayers.String.contains(url,'?')){var start=url.indexOf('?')+1;var end=OpenLayers.String.contains(url,"#")?url.indexOf('#'):url.length;paramsString=url.substring(start,end);}
+var parameters={};var pairs=paramsString.split(/[&;]/);for(var i=0,len=pairs.length;i1.0)?(1.0/scale):scale;return normScale;};OpenLayers.Util.getResolutionFromScale=function(scale,units){var resolution;if(scale){if(units==null){units="degrees";}
+var normScale=OpenLayers.Util.normalizeScale(scale);resolution=1/(normScale*OpenLayers.INCHES_PER_UNIT[units]*OpenLayers.DOTS_PER_INCH);}
+return resolution;};OpenLayers.Util.getScaleFromResolution=function(resolution,units){if(units==null){units="degrees";}
+var scale=resolution*OpenLayers.INCHES_PER_UNIT[units]*OpenLayers.DOTS_PER_INCH;return scale;};OpenLayers.Util.pagePosition=function(forElement){var pos=[0,0];var viewportElement=OpenLayers.Util.getViewportElement();if(!forElement||forElement==window||forElement==viewportElement){return pos;}
+var BUGGY_GECKO_BOX_OBJECT=OpenLayers.IS_GECKO&&document.getBoxObjectFor&&OpenLayers.Element.getStyle(forElement,'position')=='absolute'&&(forElement.style.top==''||forElement.style.left=='');var parent=null;var box;if(forElement.getBoundingClientRect){box=forElement.getBoundingClientRect();var scrollTop=viewportElement.scrollTop;var scrollLeft=viewportElement.scrollLeft;pos[0]=box.left+scrollLeft;pos[1]=box.top+scrollTop;}else if(document.getBoxObjectFor&&!BUGGY_GECKO_BOX_OBJECT){box=document.getBoxObjectFor(forElement);var vpBox=document.getBoxObjectFor(viewportElement);pos[0]=box.screenX-vpBox.screenX;pos[1]=box.screenY-vpBox.screenY;}else{pos[0]=forElement.offsetLeft;pos[1]=forElement.offsetTop;parent=forElement.offsetParent;if(parent!=forElement){while(parent){pos[0]+=parent.offsetLeft;pos[1]+=parent.offsetTop;parent=parent.offsetParent;}}
+var browser=OpenLayers.BROWSER_NAME;if(browser=="opera"||(browser=="safari"&&OpenLayers.Element.getStyle(forElement,'position')=='absolute')){pos[1]-=document.body.offsetTop;}
+parent=forElement.offsetParent;while(parent&&parent!=document.body){pos[0]-=parent.scrollLeft;if(browser!="opera"||parent.tagName!='TR'){pos[1]-=parent.scrollTop;}
+parent=parent.offsetParent;}}
+return pos;};OpenLayers.Util.getViewportElement=function(){var viewportElement=arguments.callee.viewportElement;if(viewportElement==undefined){viewportElement=(OpenLayers.BROWSER_NAME=="msie"&&document.compatMode!='CSS1Compat')?document.body:document.documentElement;arguments.callee.viewportElement=viewportElement;}
+return viewportElement;};OpenLayers.Util.isEquivalentUrl=function(url1,url2,options){options=options||{};OpenLayers.Util.applyDefaults(options,{ignoreCase:true,ignorePort80:true,ignoreHash:true});var urlObj1=OpenLayers.Util.createUrlObject(url1,options);var urlObj2=OpenLayers.Util.createUrlObject(url2,options);for(var key in urlObj1){if(key!=="args"){if(urlObj1[key]!=urlObj2[key]){return false;}}}
+for(var key in urlObj1.args){if(urlObj1.args[key]!=urlObj2.args[key]){return false;}
+delete urlObj2.args[key];}
+for(var key in urlObj2.args){return false;}
+return true;};OpenLayers.Util.createUrlObject=function(url,options){options=options||{};if(!(/^\w+:\/\//).test(url)){var loc=window.location;var port=loc.port?":"+loc.port:"";var fullUrl=loc.protocol+"//"+loc.host.split(":").shift()+port;if(url.indexOf("/")===0){url=fullUrl+url;}else{var parts=loc.pathname.split("/");parts.pop();url=fullUrl+parts.join("/")+"/"+url;}}
+if(options.ignoreCase){url=url.toLowerCase();}
+var a=document.createElement('a');a.href=url;var urlObject={};urlObject.host=a.host.split(":").shift();urlObject.protocol=a.protocol;if(options.ignorePort80){urlObject.port=(a.port=="80"||a.port=="0")?"":a.port;}else{urlObject.port=(a.port==""||a.port=="0")?"80":a.port;}
+urlObject.hash=(options.ignoreHash||a.hash==="#")?"":a.hash;var queryString=a.search;if(!queryString){var qMark=url.indexOf("?");queryString=(qMark!=-1)?url.substr(qMark):"";}
+urlObject.args=OpenLayers.Util.getParameters(queryString);urlObject.pathname=(a.pathname.charAt(0)=="/")?a.pathname:"/"+a.pathname;return urlObject;};OpenLayers.Util.removeTail=function(url){var head=null;var qMark=url.indexOf("?");var hashMark=url.indexOf("#");if(qMark==-1){head=(hashMark!=-1)?url.substr(0,hashMark):url;}else{head=(hashMark!=-1)?url.substr(0,Math.min(qMark,hashMark)):url.substr(0,qMark);}
+return head;};OpenLayers.IS_GECKO=(function(){var ua=navigator.userAgent.toLowerCase();return ua.indexOf("webkit")==-1&&ua.indexOf("gecko")!=-1;})();OpenLayers.CANVAS_SUPPORTED=(function(){var elem=document.createElement('canvas');return!!(elem.getContext&&elem.getContext('2d'));})();OpenLayers.BROWSER_NAME=(function(){var name="";var ua=navigator.userAgent.toLowerCase();if(ua.indexOf("opera")!=-1){name="opera";}else if(ua.indexOf("msie")!=-1){name="msie";}else if(ua.indexOf("safari")!=-1){name="safari";}else if(ua.indexOf("mozilla")!=-1){if(ua.indexOf("firefox")!=-1){name="firefox";}else{name="mozilla";}}
+return name;})();OpenLayers.Util.getBrowserName=function(){return OpenLayers.BROWSER_NAME;};OpenLayers.Util.getRenderedDimensions=function(contentHTML,size,options){var w,h;var container=document.createElement("div");container.style.visibility="hidden";var containerElement=(options&&options.containerElement)?options.containerElement:document.body;var parentHasPositionAbsolute=false;var superContainer=null;var parent=containerElement;while(parent&&parent.tagName.toLowerCase()!="body"){var parentPosition=OpenLayers.Element.getStyle(parent,"position");if(parentPosition=="absolute"){parentHasPositionAbsolute=true;break;}else if(parentPosition&&parentPosition!="static"){break;}
+parent=parent.parentNode;}
+if(parentHasPositionAbsolute&&(containerElement.clientHeight===0||containerElement.clientWidth===0)){superContainer=document.createElement("div");superContainer.style.visibility="hidden";superContainer.style.position="absolute";superContainer.style.overflow="visible";superContainer.style.width=document.body.clientWidth+"px";superContainer.style.height=document.body.clientHeight+"px";superContainer.appendChild(container);}
+container.style.position="absolute";if(size){if(size.w){w=size.w;container.style.width=w+"px";}else if(size.h){h=size.h;container.style.height=h+"px";}}
+if(options&&options.displayClass){container.className=options.displayClass;}
+var content=document.createElement("div");content.innerHTML=contentHTML;content.style.overflow="visible";if(content.childNodes){for(var i=0,l=content.childNodes.length;i=60){coordinateseconds-=60;coordinateminutes+=1;if(coordinateminutes>=60){coordinateminutes-=60;coordinatedegrees+=1;}}
+if(coordinatedegrees<10){coordinatedegrees="0"+coordinatedegrees;}
+var str=coordinatedegrees+"\u00B0";if(dmsOption.indexOf('dm')>=0){if(coordinateminutes<10){coordinateminutes="0"+coordinateminutes;}
+str+=coordinateminutes+"'";if(dmsOption.indexOf('dms')>=0){if(coordinateseconds<10){coordinateseconds="0"+coordinateseconds;}
+str+=coordinateseconds+'"';}}
+if(axis=="lon"){str+=coordinate<0?OpenLayers.i18n("W"):OpenLayers.i18n("E");}else{str+=coordinate<0?OpenLayers.i18n("S"):OpenLayers.i18n("N");}
+return str;};OpenLayers.Event={observers:false,KEY_SPACE:32,KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,element:function(event){return event.target||event.srcElement;},isSingleTouch:function(event){return event.touches&&event.touches.length==1;},isMultiTouch:function(event){return event.touches&&event.touches.length>1;},isLeftClick:function(event){return(((event.which)&&(event.which==1))||((event.button)&&(event.button==1)));},isRightClick:function(event){return(((event.which)&&(event.which==3))||((event.button)&&(event.button==2)));},stop:function(event,allowDefault){if(!allowDefault){OpenLayers.Event.preventDefault(event);}
+if(event.stopPropagation){event.stopPropagation();}else{event.cancelBubble=true;}},preventDefault:function(event){if(event.preventDefault){event.preventDefault();}else{event.returnValue=false;}},findElement:function(event,tagName){var element=OpenLayers.Event.element(event);while(element.parentNode&&(!element.tagName||(element.tagName.toUpperCase()!=tagName.toUpperCase()))){element=element.parentNode;}
+return element;},observe:function(elementParam,name,observer,useCapture){var element=OpenLayers.Util.getElement(elementParam);useCapture=useCapture||false;if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.attachEvent)){name='keydown';}
+if(!this.observers){this.observers={};}
+if(!element._eventCacheID){var idPrefix="eventCacheID_";if(element.id){idPrefix=element.id+"_"+idPrefix;}
+element._eventCacheID=OpenLayers.Util.createUniqueID(idPrefix);}
+var cacheID=element._eventCacheID;if(!this.observers[cacheID]){this.observers[cacheID]=[];}
+this.observers[cacheID].push({'element':element,'name':name,'observer':observer,'useCapture':useCapture});if(element.addEventListener){element.addEventListener(name,observer,useCapture);}else if(element.attachEvent){element.attachEvent('on'+name,observer);}},stopObservingElement:function(elementParam){var element=OpenLayers.Util.getElement(elementParam);var cacheID=element._eventCacheID;this._removeElementObservers(OpenLayers.Event.observers[cacheID]);},_removeElementObservers:function(elementObservers){if(elementObservers){for(var i=elementObservers.length-1;i>=0;i--){var entry=elementObservers[i];OpenLayers.Event.stopObserving.apply(this,[entry.element,entry.name,entry.observer,entry.useCapture]);}}},stopObserving:function(elementParam,name,observer,useCapture){useCapture=useCapture||false;var element=OpenLayers.Util.getElement(elementParam);var cacheID=element._eventCacheID;if(name=='keypress'){if(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.detachEvent){name='keydown';}}
+var foundEntry=false;var elementObservers=OpenLayers.Event.observers[cacheID];if(elementObservers){var i=0;while(!foundEntry&&i=0;--i){this.target.register(this.events[i],this,this.buttonClick,{extension:true});}},destroy:function(){for(var i=this.events.length-1;i>=0;--i){this.target.unregister(this.events[i],this,this.buttonClick);}
+delete this.target;},getPressedButton:function(element){var depth=3,button;do{if(OpenLayers.Element.hasClass(element,"olButton")){button=element;break;}
+element=element.parentNode;}while(--depth>0&&element);return button;},ignore:function(element){var depth=3,ignore=false;do{if(element.nodeName.toLowerCase()==='a'){ignore=true;break;}
+element=element.parentNode;}while(--depth>0&&element);return ignore;},buttonClick:function(evt){var propagate=true,element=OpenLayers.Event.element(evt);if(element&&(OpenLayers.Event.isLeftClick(evt)||!~evt.type.indexOf("mouse"))){var button=this.getPressedButton(element);if(button){if(evt.type==="keydown"){switch(evt.keyCode){case OpenLayers.Event.KEY_RETURN:case OpenLayers.Event.KEY_SPACE:this.target.triggerEvent("buttonclick",{buttonElement:button});OpenLayers.Event.stop(evt);propagate=false;break;}}else if(this.startEvt){if(this.completeRegEx.test(evt.type)){var pos=OpenLayers.Util.pagePosition(button);this.target.triggerEvent("buttonclick",{buttonElement:button,buttonXY:{x:this.startEvt.clientX-pos[0],y:this.startEvt.clientY-pos[1]}});}
+if(this.cancelRegEx.test(evt.type)){delete this.startEvt;}
+OpenLayers.Event.stop(evt);propagate=false;}
+if(this.startRegEx.test(evt.type)){this.startEvt=evt;OpenLayers.Event.stop(evt);propagate=false;}}else{propagate=!this.ignore(OpenLayers.Event.element(evt));delete this.startEvt;}}
+return propagate;}});OpenLayers.Format=OpenLayers.Class({options:null,externalProjection:null,internalProjection:null,data:null,keepData:false,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;},destroy:function(){},read:function(data){throw new Error('Read not implemented.');},write:function(object){throw new Error('Write not implemented.');},CLASS_NAME:"OpenLayers.Format"});OpenLayers.Format.XML=OpenLayers.Class(OpenLayers.Format,{namespaces:null,namespaceAlias:null,defaultPrefix:null,readers:{},writers:{},xmldom:null,initialize:function(options){if(window.ActiveXObject){this.xmldom=new ActiveXObject("Microsoft.XMLDOM");}
+OpenLayers.Format.prototype.initialize.apply(this,[options]);this.namespaces=OpenLayers.Util.extend({},this.namespaces);this.namespaceAlias={};for(var alias in this.namespaces){this.namespaceAlias[this.namespaces[alias]]=alias;}},destroy:function(){this.xmldom=null;OpenLayers.Format.prototype.destroy.apply(this,arguments);},setNamespace:function(alias,uri){this.namespaces[alias]=uri;this.namespaceAlias[uri]=alias;},read:function(text){var index=text.indexOf('<');if(index>0){text=text.substring(index);}
+var node=OpenLayers.Util.Try(OpenLayers.Function.bind((function(){var xmldom;if(window.ActiveXObject&&!this.xmldom){xmldom=new ActiveXObject("Microsoft.XMLDOM");}else{xmldom=this.xmldom;}
+xmldom.loadXML(text);return xmldom;}),this),function(){return new DOMParser().parseFromString(text,'text/xml');},function(){var req=new XMLHttpRequest();req.open("GET","data:"+"text/xml"+";charset=utf-8,"+encodeURIComponent(text),false);if(req.overrideMimeType){req.overrideMimeType("text/xml");}
+req.send(null);return req.responseXML;});if(this.keepData){this.data=node;}
+return node;},write:function(node){var data;if(this.xmldom){data=node.xml;}else{var serializer=new XMLSerializer();if(node.nodeType==1){var doc=document.implementation.createDocument("","",null);if(doc.importNode){node=doc.importNode(node,true);}
+doc.appendChild(node);data=serializer.serializeToString(doc);}else{data=serializer.serializeToString(node);}}
+return data;},createElementNS:function(uri,name){var element;if(this.xmldom){if(typeof uri=="string"){element=this.xmldom.createNode(1,name,uri);}else{element=this.xmldom.createNode(1,name,"");}}else{element=document.createElementNS(uri,name);}
+return element;},createTextNode:function(text){var node;if(typeof text!=="string"){text=String(text);}
+if(this.xmldom){node=this.xmldom.createTextNode(text);}else{node=document.createTextNode(text);}
+return node;},getElementsByTagNameNS:function(node,uri,name){var elements=[];if(node.getElementsByTagNameNS){elements=node.getElementsByTagNameNS(uri,name);}else{var allNodes=node.getElementsByTagName("*");var potentialNode,fullName;for(var i=0,len=allNodes.length;i0){prefix=name.substring(0,split);local=name.substring(split+1);}else{if(parent){prefix=this.namespaceAlias[parent.namespaceURI];}else{prefix=this.defaultPrefix;}
+local=name;}
+var child=this.writers[prefix][local].apply(this,[obj]);if(parent){parent.appendChild(child);}
+return child;},getChildEl:function(node,name,uri){return node&&this.getThisOrNextEl(node.firstChild,name,uri);},getNextEl:function(node,name,uri){return node&&this.getThisOrNextEl(node.nextSibling,name,uri);},getThisOrNextEl:function(node,name,uri){outer:for(var sibling=node;sibling;sibling=sibling.nextSibling){switch(sibling.nodeType){case 1:if((!name||name===(sibling.localName||sibling.nodeName.split(":").pop()))&&(!uri||uri===sibling.namespaceURI)){break outer;}
+sibling=null;break outer;case 3:if(/^\s*$/.test(sibling.nodeValue)){break;}
+case 4:case 6:case 12:case 10:case 11:sibling=null;break outer;}}
+return sibling||null;},lookupNamespaceURI:function(node,prefix){var uri=null;if(node){if(node.lookupNamespaceURI){uri=node.lookupNamespaceURI(prefix);}else{outer:switch(node.nodeType){case 1:if(node.namespaceURI!==null&&node.prefix===prefix){uri=node.namespaceURI;break outer;}
+var len=node.attributes.length;if(len){var attr;for(var i=0;i0){appliedRules=true;for(var i=0,len=elseRules.length;i0&&appliedRules==false){style.display="none";}
+if(style.label!=null&&typeof style.label!=="string"){style.label=String(style.label);}
+return style;},applySymbolizer:function(rule,style,feature){var symbolizerPrefix=feature.geometry?this.getSymbolizerPrefix(feature.geometry):OpenLayers.Style.SYMBOLIZER_PREFIXES[0];var symbolizer=rule.symbolizer[symbolizerPrefix]||rule.symbolizer;if(this.defaultsPerSymbolizer===true){var defaults=this.defaultStyle;OpenLayers.Util.applyDefaults(symbolizer,{pointRadius:defaults.pointRadius});if(symbolizer.stroke===true||symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{strokeWidth:defaults.strokeWidth,strokeColor:defaults.strokeColor,strokeOpacity:defaults.strokeOpacity,strokeDashstyle:defaults.strokeDashstyle,strokeLinecap:defaults.strokeLinecap});}
+if(symbolizer.fill===true||symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{fillColor:defaults.fillColor,fillOpacity:defaults.fillOpacity});}
+if(symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{pointRadius:this.defaultStyle.pointRadius,externalGraphic:this.defaultStyle.externalGraphic,graphicName:this.defaultStyle.graphicName,graphicOpacity:this.defaultStyle.graphicOpacity,graphicWidth:this.defaultStyle.graphicWidth,graphicHeight:this.defaultStyle.graphicHeight,graphicXOffset:this.defaultStyle.graphicXOffset,graphicYOffset:this.defaultStyle.graphicYOffset});}}
+return this.createLiterals(OpenLayers.Util.extend(style,symbolizer),feature);},createLiterals:function(style,feature){var context=OpenLayers.Util.extend({},feature.attributes||feature.data);OpenLayers.Util.extend(context,this.context);for(var i in this.propertyStyles){style[i]=OpenLayers.Style.createLiteral(style[i],context,feature,i);}
+return style;},findPropertyStyles:function(){var propertyStyles={};var style=this.defaultStyle;this.addPropertyStyles(propertyStyles,style);var rules=this.rules;var symbolizer,value;for(var i=0,len=rules.length;ithis.value;break;case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:result=got<=this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:result=got>=this.value;break;case OpenLayers.Filter.Comparison.BETWEEN:result=(got>=this.lowerBoundary)&&(got<=this.upperBoundary);break;case OpenLayers.Filter.Comparison.LIKE:var regexp=new RegExp(this.value,"gi");result=regexp.test(got);break;}
+return result;},value2regex:function(wildCard,singleChar,escapeChar){if(wildCard=="."){throw new Error("'.' is an unsupported wildCard character for "+"OpenLayers.Filter.Comparison");}
+wildCard=wildCard?wildCard:"*";singleChar=singleChar?singleChar:".";escapeChar=escapeChar?escapeChar:"!";this.value=this.value.replace(new RegExp("\\"+escapeChar+"(.|$)","g"),"\\$1");this.value=this.value.replace(new RegExp("\\"+singleChar,"g"),".");this.value=this.value.replace(new RegExp("\\"+wildCard,"g"),".*");this.value=this.value.replace(new RegExp("\\\\.\\*","g"),"\\"+wildCard);this.value=this.value.replace(new RegExp("\\\\\\.","g"),"\\"+singleChar);return this.value;},regex2value:function(){var value=this.value;value=value.replace(/!/g,"!!");value=value.replace(/(\\)?\\\./g,function($0,$1){return $1?$0:"!.";});value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"!*";});value=value.replace(/\\\\/g,"\\");value=value.replace(/\.\*/g,"*");return value;},clone:function(){return OpenLayers.Util.extend(new OpenLayers.Filter.Comparison(),this);},CLASS_NAME:"OpenLayers.Filter.Comparison"});OpenLayers.Filter.Comparison.EQUAL_TO="==";OpenLayers.Filter.Comparison.NOT_EQUAL_TO="!=";OpenLayers.Filter.Comparison.LESS_THAN="<";OpenLayers.Filter.Comparison.GREATER_THAN=">";OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO="<=";OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO=">=";OpenLayers.Filter.Comparison.BETWEEN="..";OpenLayers.Filter.Comparison.LIKE="~";OpenLayers.Format.Filter=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",CLASS_NAME:"OpenLayers.Format.Filter"});OpenLayers.Filter.Function=OpenLayers.Class(OpenLayers.Filter,{name:null,params:null,CLASS_NAME:"OpenLayers.Filter.Function"});OpenLayers.Format.Filter.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ogc:"http://www.opengis.net/ogc",gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"ogc",schemaLocation:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){var obj={};this.readers.ogc["Filter"].apply(this,[data,obj]);return obj.filter;},readers:{"ogc":{"_expression":function(node){var obj,value="";for(var child=node.firstChild;child;child=child.nextSibling){switch(child.nodeType){case 1:obj=this.readNode(child);if(obj.property){value+="${"+obj.property+"}";}else if(obj.value!==undefined){value+=obj.value;}
+break;case 3:case 4:value+=child.nodeValue;}}
+return value;},"Filter":function(node,parent){var obj={fids:[],filters:[]};this.readChildNodes(node,obj);if(obj.fids.length>0){parent.filter=new OpenLayers.Filter.FeatureId({fids:obj.fids});}else if(obj.filters.length>0){parent.filter=obj.filters[0];}},"FeatureId":function(node,obj){var fid=node.getAttribute("fid");if(fid){obj.fids.push(fid);}},"And":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND});this.readChildNodes(node,filter);obj.filters.push(filter);},"Or":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.OR});this.readChildNodes(node,filter);obj.filters.push(filter);},"Not":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.NOT});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLessThan":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LESS_THAN});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsGreaterThan":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.GREATER_THAN});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLessThanOrEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsGreaterThanOrEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsBetween":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.BETWEEN});this.readChildNodes(node,filter);obj.filters.push(filter);},"Literal":function(node,obj){obj.value=OpenLayers.String.numericIf(this.getChildValue(node),true);},"PropertyName":function(node,filter){filter.property=this.getChildValue(node);},"LowerBoundary":function(node,filter){filter.lowerBoundary=OpenLayers.String.numericIf(this.readers.ogc._expression.call(this,node),true);},"UpperBoundary":function(node,filter){filter.upperBoundary=OpenLayers.String.numericIf(this.readers.ogc._expression.call(this,node),true);},"Intersects":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.INTERSECTS);},"Within":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.WITHIN);},"Contains":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.CONTAINS);},"DWithin":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.DWITHIN);},"Distance":function(node,obj){obj.distance=parseInt(this.getChildValue(node));obj.distanceUnits=node.getAttribute("units");},"Function":function(node,obj){return;}}},readSpatial:function(node,obj,type){var filter=new OpenLayers.Filter.Spatial({type:type});this.readChildNodes(node,filter);filter.value=filter.components[0];delete filter.components;obj.filters.push(filter);},writeOgcExpression:function(value,node){if(value instanceof OpenLayers.Filter.Function){var child=this.writeNode("Function",value,node);node.appendChild(child);}else{this.writeNode("Literal",value,node);}
+return node;},write:function(filter){return this.writers.ogc["Filter"].apply(this,[filter]);},writeFeatureIdNodes:function(filter,node){for(var i=0,ii=filter.fids.length;i":"PropertyIsGreaterThan","<=":"PropertyIsLessThanOrEqualTo",">=":"PropertyIsGreaterThanOrEqualTo","..":"PropertyIsBetween","~":"PropertyIsLike","BBOX":"BBOX","DWITHIN":"DWITHIN","WITHIN":"WITHIN","CONTAINS":"CONTAINS","INTERSECTS":"INTERSECTS","FID":"FeatureId"},CLASS_NAME:"OpenLayers.Format.Filter.v1"});OpenLayers.Geometry=OpenLayers.Class({id:null,parent:null,bounds:null,initialize:function(){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){this.id=null;this.bounds=null;},clone:function(){return new OpenLayers.Geometry();},setBounds:function(bounds){if(bounds){this.bounds=bounds.clone();}},clearBounds:function(){this.bounds=null;if(this.parent){this.parent.clearBounds();}},extendBounds:function(newBounds){var bounds=this.getBounds();if(!bounds){this.setBounds(newBounds);}else{this.bounds.extend(newBounds);}},getBounds:function(){if(this.bounds==null){this.calculateBounds();}
+return this.bounds;},calculateBounds:function(){},distanceTo:function(geometry,options){},getVertices:function(nodes){},atPoint:function(lonlat,toleranceLon,toleranceLat){var atPoint=false;var bounds=this.getBounds();if((bounds!=null)&&(lonlat!=null)){var dX=(toleranceLon!=null)?toleranceLon:0;var dY=(toleranceLat!=null)?toleranceLat:0;var toleranceBounds=new OpenLayers.Bounds(this.bounds.left-dX,this.bounds.bottom-dY,this.bounds.right+dX,this.bounds.top+dY);atPoint=toleranceBounds.containsLonLat(lonlat);}
+return atPoint;},getLength:function(){return 0.0;},getArea:function(){return 0.0;},getCentroid:function(){return null;},toString:function(){var string;if(OpenLayers.Format&&OpenLayers.Format.WKT){string=OpenLayers.Format.WKT.prototype.write(new OpenLayers.Feature.Vector(this));}else{string=Object.prototype.toString.call(this);}
+return string;},CLASS_NAME:"OpenLayers.Geometry"});OpenLayers.Geometry.fromWKT=function(wkt){var geom;if(OpenLayers.Format&&OpenLayers.Format.WKT){var format=OpenLayers.Geometry.fromWKT.format;if(!format){format=new OpenLayers.Format.WKT();OpenLayers.Geometry.fromWKT.format=format;}
+var result=format.read(wkt);if(result instanceof OpenLayers.Feature.Vector){geom=result.geometry;}else if(OpenLayers.Util.isArray(result)){var len=result.length;var components=new Array(len);for(var i=0;i=0&&along1<=1&&along2>=0&&along2<=1){if(!point){intersection=true;}else{var x=seg1.x1+(along1*x12_11);var y=seg1.y1+(along1*y12_11);intersection=new OpenLayers.Geometry.Point(x,y);}}}
+if(tolerance){var dist;if(intersection){if(point){var segs=[seg1,seg2];var seg,x,y;outer:for(var i=0;i<2;++i){seg=segs[i];for(var j=1;j<3;++j){x=seg["x"+j];y=seg["y"+j];dist=Math.sqrt(Math.pow(x-intersection.x,2)+
+Math.pow(y-intersection.y,2));if(dist=1.0){x=x2;y=y2;}else{x=x1+along*dx;y=y1+along*dy;}
+return{distance:Math.sqrt(Math.pow(x-x0,2)+Math.pow(y-y0,2)),x:x,y:y};};OpenLayers.Geometry.Point=OpenLayers.Class(OpenLayers.Geometry,{x:null,y:null,initialize:function(x,y){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.x=parseFloat(x);this.y=parseFloat(y);},clone:function(obj){if(obj==null){obj=new OpenLayers.Geometry.Point(this.x,this.y);}
+OpenLayers.Util.applyDefaults(obj,this);return obj;},calculateBounds:function(){this.bounds=new OpenLayers.Bounds(this.x,this.y,this.x,this.y);},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var distance,x0,y0,x1,y1,result;if(geometry instanceof OpenLayers.Geometry.Point){x0=this.x;y0=this.y;x1=geometry.x;y1=geometry.y;distance=Math.sqrt(Math.pow(x0-x1,2)+Math.pow(y0-y1,2));result=!details?distance:{x0:x0,y0:y0,x1:x1,y1:y1,distance:distance};}else{result=geometry.distanceTo(this,options);if(details){result={x0:result.x1,y0:result.y1,x1:result.x0,y1:result.y0,distance:result.distance};}}
+return result;},equals:function(geom){var equals=false;if(geom!=null){equals=((this.x==geom.x&&this.y==geom.y)||(isNaN(this.x)&&isNaN(this.y)&&isNaN(geom.x)&&isNaN(geom.y)));}
+return equals;},toShortString:function(){return(this.x+", "+this.y);},move:function(x,y){this.x=this.x+x;this.y=this.y+y;this.clearBounds();},rotate:function(angle,origin){angle*=Math.PI/180;var radius=this.distanceTo(origin);var theta=angle+Math.atan2(this.y-origin.y,this.x-origin.x);this.x=origin.x+(radius*Math.cos(theta));this.y=origin.y+(radius*Math.sin(theta));this.clearBounds();},getCentroid:function(){return new OpenLayers.Geometry.Point(this.x,this.y);},resize:function(scale,origin,ratio){ratio=(ratio==undefined)?1:ratio;this.x=origin.x+(scale*ratio*(this.x-origin.x));this.y=origin.y+(scale*(this.y-origin.y));this.clearBounds();return this;},intersects:function(geometry){var intersect=false;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.equals(geometry);}else{intersect=geometry.intersects(this);}
+return intersect;},transform:function(source,dest){if((source&&dest)){OpenLayers.Projection.transform(this,source,dest);this.bounds=null;}
+return this;},getVertices:function(nodes){return[this];},CLASS_NAME:"OpenLayers.Geometry.Point"});OpenLayers.Geometry.Collection=OpenLayers.Class(OpenLayers.Geometry,{components:null,componentTypes:null,initialize:function(components){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.components=[];if(components!=null){this.addComponents(components);}},destroy:function(){this.components.length=0;this.components=null;OpenLayers.Geometry.prototype.destroy.apply(this,arguments);},clone:function(){var geometry=eval("new "+this.CLASS_NAME+"()");for(var i=0,len=this.components.length;i-1)){if(index!=null&&(index=0;--i){removed=this.removeComponent(components[i])||removed;}
+return removed;},removeComponent:function(component){OpenLayers.Util.removeItem(this.components,component);this.clearBounds();return true;},getLength:function(){var length=0.0;for(var i=0,len=this.components.length;i0)?area:minArea;centroids.push(centroid);}
+len=areas.length;if(areaSum===0){for(var i=0;i1)){for(var i=1,len=this.components.length;i1)){var p1,p2;for(var i=1,len=geom.components.length;i2);if(removed){OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);}
+return removed;},intersects:function(geometry){var intersect=false;var type=geometry.CLASS_NAME;if(type=="OpenLayers.Geometry.LineString"||type=="OpenLayers.Geometry.LinearRing"||type=="OpenLayers.Geometry.Point"){var segs1=this.getSortedSegments();var segs2;if(type=="OpenLayers.Geometry.Point"){segs2=[{x1:geometry.x,y1:geometry.y,x2:geometry.x,y2:geometry.y}];}else{segs2=geometry.getSortedSegments();}
+var seg1,seg1x1,seg1x2,seg1y1,seg1y2,seg2,seg2y1,seg2y2;outer:for(var i=0,len=segs1.length;iseg1x2){break;}
+if(seg2.x2Math.max(seg1y1,seg1y2)){continue;}
+if(Math.max(seg2y1,seg2y2)0){var xDir=seg.x10){lines.unshift(j,1);Array.prototype.splice.apply(targetParts,lines);j+=lines.length-2;}
+if(mutual){for(var k=0,len=splits.points.length;k0&&points.length>0){points.push(vert2.clone());sourceParts.push(new OpenLayers.Geometry.LineString(points));}}else{results=target.splitWith(this,options);}
+if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
+if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];}
+if(targetSplit||sourceSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
+return results;},splitWith:function(geometry,options){return geometry.split(this,options);},getVertices:function(nodes){var vertices;if(nodes===true){vertices=[this.components[0],this.components[this.components.length-1]];}else if(nodes===false){vertices=this.components.slice(1,this.components.length-1);}else{vertices=this.components.slice();}
+return vertices;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var result,best={};var min=Number.POSITIVE_INFINITY;if(geometry instanceof OpenLayers.Geometry.Point){var segs=this.getSortedSegments();var x=geometry.x;var y=geometry.y;var seg;for(var i=0,len=segs.length;ix&&((y>seg.y1&&yseg.y2))){break;}}}
+if(details){best={distance:best.distance,x0:best.x,y0:best.y,x1:x,y1:y};}else{best=best.distance;}}else if(geometry instanceof OpenLayers.Geometry.LineString){var segs0=this.getSortedSegments();var segs1=geometry.getSortedSegments();var seg0,seg1,intersection,x0,y0;var len1=segs1.length;var interOptions={point:true};outer:for(var i=0,len=segs0.length;imaxDistance){maxDistance=distance;indexFarthest=index;}}
+if(maxDistance>tolerance&&indexFarthest!=firstPoint){pointIndexsToKeep.push(indexFarthest);douglasPeuckerReduction(points,firstPoint,indexFarthest,tolerance);douglasPeuckerReduction(points,indexFarthest,lastPoint,tolerance);}};var perpendicularDistance=function(point1,point2,point){var area=Math.abs(0.5*(point1.x*point2.y+point2.x*point.y+point.x*point1.y-point2.x*point1.y-point.x*point2.y-point1.x*point.y));var bottom=Math.sqrt(Math.pow(point1.x-point2.x,2)+Math.pow(point1.y-point2.y,2));var height=area/bottom*2;return height;};var firstPoint=0;var lastPoint=points.length-1;var pointIndexsToKeep=[];pointIndexsToKeep.push(firstPoint);pointIndexsToKeep.push(lastPoint);while(points[firstPoint].equals(points[lastPoint])){lastPoint--;pointIndexsToKeep.push(lastPoint);}
+douglasPeuckerReduction(points,firstPoint,lastPoint,tolerance);var returnPoints=[];pointIndexsToKeep.sort(compareNumbers);for(var index=0;index1){sourceSplit=true;}else{sourceParts=[];}
+if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
+if(sourceSplit||targetSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
+return results;},splitWith:function(geometry,options){var results=null;var mutual=options&&options.mutual;var splits,targetLine,sourceLines,sourceSplit,targetSplit,sourceParts,targetParts;if(geometry instanceof OpenLayers.Geometry.LineString){targetParts=[];sourceParts=[geometry];for(var i=0,len=this.components.length;i1){sourceSplit=true;}else{sourceParts=[];}
+if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
+if(sourceSplit||targetSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
+return results;},CLASS_NAME:"OpenLayers.Geometry.MultiLineString"});OpenLayers.Geometry.LinearRing=OpenLayers.Class(OpenLayers.Geometry.LineString,{componentTypes:["OpenLayers.Geometry.Point"],addComponent:function(point,index){var added=false;var lastPoint=this.components.pop();if(index!=null||!point.equals(lastPoint)){added=OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,arguments);}
+var firstPoint=this.components[0];OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);return added;},removeComponent:function(point){var removed=this.components&&(this.components.length>3);if(removed){this.components.pop();OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);var firstPoint=this.components[0];OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);}
+return removed;},move:function(x,y){for(var i=0,len=this.components.length;i0&&len<=2){return this.components[0].clone();}else if(len>2){var sumX=0.0;var sumY=0.0;var x0=this.components[0].x;var y0=this.components[0].y;var area=-1*this.getArea();if(area!=0){for(var i=0;i2)){var sum=0.0;for(var i=0,len=this.components.length;i2){var p1,p2;for(var i=0;i=x1&&px<=x2)||x1>=x2&&(px<=x1&&px>=x2)){crosses=-1;break;}}
+continue;}
+cx=approx(getX(py,x1,y1,x2,y2),digs);if(cx==px){if(y1=y1&&py<=y2)||y1>y2&&(py<=y1&&py>=y2)){crosses=-1;break;}}
+if(cx<=px){continue;}
+if(x1!=x2&&(cxMath.max(x1,x2))){continue;}
+if(y1=y1&&pyy2&&(py=y2)){++crosses;}}
+var contained=(crosses==-1)?1:!!(crosses&1);return contained;},intersects:function(geometry){var intersect=false;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.containsPoint(geometry);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"){intersect=geometry.intersects(this);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){intersect=OpenLayers.Geometry.LineString.prototype.intersects.apply(this,[geometry]);}else{for(var i=0,len=geometry.components.length;i0)){area+=Math.abs(this.components[0].getArea());for(var i=1,len=this.components.length;i0)){area+=Math.abs(this.components[0].getGeodesicArea(projection));for(var i=1,len=this.components.length;i0){contained=this.components[0].containsPoint(point);if(contained!==1){if(contained&&numRings>1){var hole;for(var i=1;i0){parser=this.parseGeometry[type.toLowerCase()];if(parser){geometry=parser.apply(this,[nodeList[0]]);if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}}else{throw new TypeError("Unsupported geometry type: "+type);}
+break;}}
+var bounds;var boxNodes=this.getElementsByTagNameNS(node,this.gmlns,"Box");for(i=0;i0){coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);}
+if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.removeSpace,"");coords=coordString.split(",");}}
+if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coord");if(nodeList.length>0){var xList=this.getElementsByTagNameNS(nodeList[0],this.gmlns,"X");var yList=this.getElementsByTagNameNS(nodeList[0],this.gmlns,"Y");if(xList.length>0&&yList.length>0){coords=[xList[0].firstChild.nodeValue,yList[0].firstChild.nodeValue];}}}
+if(coords.length==2){coords[2]=null;}
+if(this.xy){return new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}
+else{return new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}},multipoint:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"Point");var components=[];if(nodeList.length>0){var point;for(var i=0;i0){coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);var dim=parseInt(nodeList[0].getAttribute("dimension"));var j,x,y,z;for(var i=0;i0){coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coordString=coordString.replace(this.regExes.trimComma,",");var pointList=coordString.split(this.regExes.splitSpace);for(var i=0;i0){var line;for(var i=0;i0){var ring;for(var i=0;i0){var polygon;for(var i=0;i0){var coords=[];if(lpoint.length>0){coordString=lpoint[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);}
+if(coords.length==2){coords[2]=null;}
+if(this.xy){var lowerPoint=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{var lowerPoint=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}}
+var upoint=this.getElementsByTagNameNS(node,this.gmlns,"upperCorner");if(upoint.length>0){var coords=[];if(upoint.length>0){coordString=upoint[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);}
+if(coords.length==2){coords[2]=null;}
+if(this.xy){var upperPoint=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{var upperPoint=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}}
+if(lowerPoint&&upperPoint){components.push(new OpenLayers.Geometry.Point(lowerPoint.x,lowerPoint.y));components.push(new OpenLayers.Geometry.Point(upperPoint.x,lowerPoint.y));components.push(new OpenLayers.Geometry.Point(upperPoint.x,upperPoint.y));components.push(new OpenLayers.Geometry.Point(lowerPoint.x,upperPoint.y));components.push(new OpenLayers.Geometry.Point(lowerPoint.x,lowerPoint.y));var ring=new OpenLayers.Geometry.LinearRing(components);envelope=new OpenLayers.Geometry.Polygon([ring]);}
+return envelope;},box:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");var coordString;var coords,beginPoint=null,endPoint=null;if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coords=coordString.split(" ");if(coords.length==2){beginPoint=coords[0].split(",");endPoint=coords[1].split(",");}}
+if(beginPoint!==null&&endPoint!==null){return new OpenLayers.Bounds(parseFloat(beginPoint[0]),parseFloat(beginPoint[1]),parseFloat(endPoint[0]),parseFloat(endPoint[1]));}}},parseAttributes:function(node){var attributes={};var childNode=node.firstChild;var children,i,child,grandchildren,grandchild,name,value;while(childNode){if(childNode.nodeType==1){children=childNode.childNodes;for(i=0;i0){obj.bounds=container.components[0];}},"Point":function(node,container){var obj={points:[]};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+container.components.push(obj.points[0]);},"coordinates":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);var coords;var numPoints=pointList.length;var points=new Array(numPoints);for(var i=0;i0){container.components=[new OpenLayers.Geometry.MultiLineString(obj.components)];}},"curveMember":function(node,obj){this.readChildNodes(node,obj);},"MultiSurface":function(node,container){var obj={components:[]};this.readers.gml._inherit.apply(this,[node,obj,container]);this.readChildNodes(node,obj);if(obj.components.length>0){container.components=[new OpenLayers.Geometry.MultiPolygon(obj.components)];}},"surfaceMember":function(node,obj){this.readChildNodes(node,obj);},"surfaceMembers":function(node,obj){this.readChildNodes(node,obj);},"pointMembers":function(node,obj){this.readChildNodes(node,obj);},"lineStringMembers":function(node,obj){this.readChildNodes(node,obj);},"polygonMembers":function(node,obj){this.readChildNodes(node,obj);},"geometryMembers":function(node,obj){this.readChildNodes(node,obj);},"Envelope":function(node,container){var obj={points:new Array(2)};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
+var min=obj.points[0];var max=obj.points[1];container.components.push(new OpenLayers.Bounds(min.x,min.y,max.x,max.y));},"lowerCorner":function(node,container){var obj={};this.readers.gml.pos.apply(this,[node,obj]);container.points[0]=obj.points[0];},"upperCorner":function(node,container){var obj={};this.readers.gml.pos.apply(this,[node,obj]);container.points[1]=obj.points[0];}},OpenLayers.Format.GML.Base.prototype.readers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.readers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.readers["wfs"]},write:function(features){var name;if(OpenLayers.Util.isArray(features)){name="featureMembers";}else{name="featureMember";}
+var root=this.writeNode("gml:"+name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":OpenLayers.Util.applyDefaults({"featureMembers":function(features){var node=this.createElementNSPlus("gml:featureMembers");for(var i=0,len=features.length;i0?duration:Number.POSITIVE_INFINITY;var id=++counter;var start=+new Date;loops[id]=function(){if(loops[id]&&+new Date-start<=duration){callback();if(loops[id]){requestFrame(loops[id],element);}}else{delete loops[id];}};requestFrame(loops[id],element);return id;}
+function stop(id){delete loops[id];}
+return{isNative:isNative,requestFrame:requestFrame,start:start,stop:stop};})(window);OpenLayers.Tween=OpenLayers.Class({easing:null,begin:null,finish:null,duration:null,callbacks:null,time:null,animationId:null,playing:false,initialize:function(easing){this.easing=(easing)?easing:OpenLayers.Easing.Expo.easeOut;},start:function(begin,finish,duration,options){this.playing=true;this.begin=begin;this.finish=finish;this.duration=duration;this.callbacks=options.callbacks;this.time=0;OpenLayers.Animation.stop(this.animationId);this.animationId=null;if(this.callbacks&&this.callbacks.start){this.callbacks.start.call(this,this.begin);}
+this.animationId=OpenLayers.Animation.start(OpenLayers.Function.bind(this.play,this));},stop:function(){if(!this.playing){return;}
+if(this.callbacks&&this.callbacks.done){this.callbacks.done.call(this,this.finish);}
+OpenLayers.Animation.stop(this.animationId);this.animationId=null;this.playing=false;},play:function(){var value={};for(var i in this.begin){var b=this.begin[i];var f=this.finish[i];if(b==null||f==null||isNaN(b)||isNaN(f)){throw new TypeError('invalid value for Tween');}
+var c=f-b;value[i]=this.easing.apply(this,[this.time,b,c,this.duration]);}
+this.time++;if(this.callbacks&&this.callbacks.eachStep){this.callbacks.eachStep.call(this,value);}
+if(this.time>this.duration){this.stop();}},CLASS_NAME:"OpenLayers.Tween"});OpenLayers.Easing={CLASS_NAME:"OpenLayers.Easing"};OpenLayers.Easing.Linear={easeIn:function(t,b,c,d){return c*t/d+b;},easeOut:function(t,b,c,d){return c*t/d+b;},easeInOut:function(t,b,c,d){return c*t/d+b;},CLASS_NAME:"OpenLayers.Easing.Linear"};OpenLayers.Easing.Expo={easeIn:function(t,b,c,d){return(t==0)?b:c*Math.pow(2,10*(t/d-1))+b;},easeOut:function(t,b,c,d){return(t==d)?b+c:c*(-Math.pow(2,-10*t/d)+1)+b;},easeInOut:function(t,b,c,d){if(t==0)return b;if(t==d)return b+c;if((t/=d/2)<1)return c/2*Math.pow(2,10*(t-1))+b;return c/2*(-Math.pow(2,-10*--t)+2)+b;},CLASS_NAME:"OpenLayers.Easing.Expo"};OpenLayers.Easing.Quad={easeIn:function(t,b,c,d){return c*(t/=d)*t+b;},easeOut:function(t,b,c,d){return-c*(t/=d)*(t-2)+b;},easeInOut:function(t,b,c,d){if((t/=d/2)<1)return c/2*t*t+b;return-c/2*((--t)*(t-2)-1)+b;},CLASS_NAME:"OpenLayers.Easing.Quad"};OpenLayers.Projection=OpenLayers.Class({proj:null,projCode:null,titleRegEx:/\+title=[^\+]*/,initialize:function(projCode,options){OpenLayers.Util.extend(this,options);this.projCode=projCode;if(typeof Proj4js=="object"){this.proj=new Proj4js.Proj(projCode);}},getCode:function(){return this.proj?this.proj.srsCode:this.projCode;},getUnits:function(){return this.proj?this.proj.units:null;},toString:function(){return this.getCode();},equals:function(projection){var p=projection,equals=false;if(p){if(!(p instanceof OpenLayers.Projection)){p=new OpenLayers.Projection(p);}
+if((typeof Proj4js=="object")&&this.proj.defData&&p.proj.defData){equals=this.proj.defData.replace(this.titleRegEx,"")==p.proj.defData.replace(this.titleRegEx,"");}else if(p.getCode){var source=this.getCode(),target=p.getCode();equals=source==target||!!OpenLayers.Projection.transforms[source]&&OpenLayers.Projection.transforms[source][target]===OpenLayers.Projection.nullTransform;}}
+return equals;},destroy:function(){delete this.proj;delete this.projCode;},CLASS_NAME:"OpenLayers.Projection"});OpenLayers.Projection.transforms={};OpenLayers.Projection.defaults={"EPSG:4326":{units:"degrees",maxExtent:[-180,-90,180,90],yx:true},"CRS:84":{units:"degrees",maxExtent:[-180,-90,180,90]},"EPSG:900913":{units:"m",maxExtent:[-20037508.34,-20037508.34,20037508.34,20037508.34]}};OpenLayers.Projection.addTransform=function(from,to,method){if(method===OpenLayers.Projection.nullTransform){var defaults=OpenLayers.Projection.defaults[from];if(defaults&&!OpenLayers.Projection.defaults[to]){OpenLayers.Projection.defaults[to]=defaults;}}
+if(!OpenLayers.Projection.transforms[from]){OpenLayers.Projection.transforms[from]={};}
+OpenLayers.Projection.transforms[from][to]=method;};OpenLayers.Projection.transform=function(point,source,dest){if(source&&dest){if(!(source instanceof OpenLayers.Projection)){source=new OpenLayers.Projection(source);}
+if(!(dest instanceof OpenLayers.Projection)){dest=new OpenLayers.Projection(dest);}
+if(source.proj&&dest.proj){point=Proj4js.transform(source.proj,dest.proj,point);}else{var sourceCode=source.getCode();var destCode=dest.getCode();var transforms=OpenLayers.Projection.transforms;if(transforms[sourceCode]&&transforms[sourceCode][destCode]){transforms[sourceCode][destCode](point);}}}
+return point;};OpenLayers.Projection.nullTransform=function(point){return point;};(function(){var pole=20037508.34;function inverseMercator(xy){xy.x=180*xy.x/pole;xy.y=180/Math.PI*(2*Math.atan(Math.exp((xy.y/pole)*Math.PI))-Math.PI/2);return xy;}
+function forwardMercator(xy){xy.x=xy.x*pole/180;xy.y=Math.log(Math.tan((90+xy.y)*Math.PI/360))/Math.PI*pole;return xy;}
+function map(base,codes){var add=OpenLayers.Projection.addTransform;var same=OpenLayers.Projection.nullTransform;var i,len,code,other,j;for(i=0,len=codes.length;i=0;--i){map(mercator[i],geographic);}
+for(i=geographic.length-1;i>=0;--i){map(geographic[i],mercator);}})();OpenLayers.Map=OpenLayers.Class({Z_INDEX_BASE:{BaseLayer:100,Overlay:325,Feature:725,Popup:750,Control:1000},id:null,fractionalZoom:false,events:null,allOverlays:false,div:null,dragging:false,size:null,viewPortDiv:null,layerContainerOrigin:null,layerContainerDiv:null,layers:null,controls:null,popups:null,baseLayer:null,center:null,resolution:null,zoom:0,panRatio:1.5,options:null,tileSize:null,projection:"EPSG:4326",units:null,resolutions:null,maxResolution:null,minResolution:null,maxScale:null,minScale:null,maxExtent:null,minExtent:null,restrictedExtent:null,numZoomLevels:16,theme:null,displayProjection:null,fallThrough:true,autoUpdateSize:true,panTween:null,eventListeners:null,panMethod:OpenLayers.Easing.Expo.easeOut,panDuration:50,paddingForPopups:null,layerContainerOriginPx:null,minPx:null,maxPx:null,initialize:function(div,options){if(arguments.length===1&&typeof div==="object"){options=div;div=options&&options.div;}
+this.tileSize=new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH,OpenLayers.Map.TILE_HEIGHT);this.paddingForPopups=new OpenLayers.Bounds(15,15,15,15);this.theme=OpenLayers._getScriptLocation()+'theme/default/style.css';this.options=OpenLayers.Util.extend({},options);OpenLayers.Util.extend(this,options);var projCode=this.projection instanceof OpenLayers.Projection?this.projection.projCode:this.projection;OpenLayers.Util.applyDefaults(this,OpenLayers.Projection.defaults[projCode]);if(this.maxExtent&&!(this.maxExtent instanceof OpenLayers.Bounds)){this.maxExtent=new OpenLayers.Bounds(this.maxExtent);}
+if(this.minExtent&&!(this.minExtent instanceof OpenLayers.Bounds)){this.minExtent=new OpenLayers.Bounds(this.minExtent);}
+if(this.restrictedExtent&&!(this.restrictedExtent instanceof OpenLayers.Bounds)){this.restrictedExtent=new OpenLayers.Bounds(this.restrictedExtent);}
+if(this.center&&!(this.center instanceof OpenLayers.LonLat)){this.center=new OpenLayers.LonLat(this.center);}
+this.layers=[];this.id=OpenLayers.Util.createUniqueID("OpenLayers.Map_");this.div=OpenLayers.Util.getElement(div);if(!this.div){this.div=document.createElement("div");this.div.style.height="1px";this.div.style.width="1px";}
+OpenLayers.Element.addClass(this.div,'olMap');var id=this.id+"_OpenLayers_ViewPort";this.viewPortDiv=OpenLayers.Util.createDiv(id,null,null,null,"relative",null,"hidden");this.viewPortDiv.style.width="100%";this.viewPortDiv.style.height="100%";this.viewPortDiv.className="olMapViewport";this.div.appendChild(this.viewPortDiv);this.events=new OpenLayers.Events(this,this.viewPortDiv,null,this.fallThrough,{includeXY:true});id=this.id+"_OpenLayers_Container";this.layerContainerDiv=OpenLayers.Util.createDiv(id);this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;this.layerContainerOriginPx={x:0,y:0};this.viewPortDiv.appendChild(this.layerContainerDiv);this.updateSize();if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}
+if(this.autoUpdateSize===true){this.updateSizeDestroy=OpenLayers.Function.bind(this.updateSize,this);OpenLayers.Event.observe(window,'resize',this.updateSizeDestroy);}
+if(this.theme){var addNode=true;var nodes=document.getElementsByTagName('link');for(var i=0,len=nodes.length;i=0;--i){this.controls[i].destroy();}
+this.controls=null;}
+if(this.layers!=null){for(var i=this.layers.length-1;i>=0;--i){this.layers[i].destroy(false);}
+this.layers=null;}
+if(this.viewPortDiv){this.div.removeChild(this.viewPortDiv);}
+this.viewPortDiv=null;if(this.eventListeners){this.events.un(this.eventListeners);this.eventListeners=null;}
+this.events.destroy();this.events=null;this.options=null;},setOptions:function(options){var updatePxExtent=this.minPx&&options.restrictedExtent!=this.restrictedExtent;OpenLayers.Util.extend(this,options);updatePxExtent&&this.moveTo(this.getCachedCenter(),this.zoom,{forceZoomChange:true});},getTileSize:function(){return this.tileSize;},getBy:function(array,property,match){var test=(typeof match.test=="function");var found=OpenLayers.Array.filter(this[array],function(item){return item[property]==match||(test&&match.test(item[property]));});return found;},getLayersBy:function(property,match){return this.getBy("layers",property,match);},getLayersByName:function(match){return this.getLayersBy("name",match);},getLayersByClass:function(match){return this.getLayersBy("CLASS_NAME",match);},getControlsBy:function(property,match){return this.getBy("controls",property,match);},getControlsByClass:function(match){return this.getControlsBy("CLASS_NAME",match);},getLayer:function(id){var foundLayer=null;for(var i=0,len=this.layers.length;ithis.layers.length){idx=this.layers.length;}
+if(base!=idx){this.layers.splice(base,1);this.layers.splice(idx,0,layer);for(var i=0,len=this.layers.length;i=0;--i){this.removePopup(this.popups[i]);}}
+popup.map=this;this.popups.push(popup);var popupDiv=popup.draw();if(popupDiv){popupDiv.style.zIndex=this.Z_INDEX_BASE['Popup']+
+this.popups.length;this.layerContainerDiv.appendChild(popupDiv);}},removePopup:function(popup){OpenLayers.Util.removeItem(this.popups,popup);if(popup.div){try{this.layerContainerDiv.removeChild(popup.div);}
+catch(e){}}
+popup.map=null;},getSize:function(){var size=null;if(this.size!=null){size=this.size.clone();}
+return size;},updateSize:function(){var newSize=this.getCurrentSize();if(newSize&&!isNaN(newSize.h)&&!isNaN(newSize.w)){this.events.clearMouseCache();var oldSize=this.getSize();if(oldSize==null){this.size=oldSize=newSize;}
+if(!newSize.equals(oldSize)){this.size=newSize;for(var i=0,len=this.layers.length;i=this.minPx.x+xRestriction?Math.round(dx):0;dy=y<=this.maxPx.y-yRestriction&&y>=this.minPx.y+yRestriction?Math.round(dy):0;if(dx||dy){if(!this.dragging){this.dragging=true;this.events.triggerEvent("movestart");}
+this.center=null;if(dx){this.layerContainerDiv.style.left=(this.layerContainerOriginPx.x-=dx)+"px";this.minPx.x-=dx;this.maxPx.x-=dx;}
+if(dy){this.layerContainerDiv.style.top=(this.layerContainerOriginPx.y-=dy)+"px";this.minPx.y-=dy;this.maxPx.y-=dy;}
+var layer,i,len;for(i=0,len=this.layers.length;imaxResolution){if(this.fractionalZoom){zoom=this.getZoomForResolution(maxResolution);}else{for(var i=zoom|0,ii=resolutions.length;ithis.restrictedExtent.getWidth()){lonlat=new OpenLayers.LonLat(maxCenter.lon,lonlat.lat);}else if(extent.leftthis.restrictedExtent.right){lonlat=lonlat.add(this.restrictedExtent.right-
+extent.right,0);}
+if(extent.getHeight()>this.restrictedExtent.getHeight()){lonlat=new OpenLayers.LonLat(lonlat.lon,maxCenter.lat);}else if(extent.bottomthis.restrictedExtent.top){lonlat=lonlat.add(0,this.restrictedExtent.top-
+extent.top);}}}
+var zoomChanged=forceZoomChange||((this.isValidZoomLevel(zoom))&&(zoom!=this.getZoom()));var centerChanged=(this.isValidLonLat(lonlat))&&(!lonlat.equals(this.center));if(zoomChanged||centerChanged||dragging){dragging||this.events.triggerEvent("movestart");if(centerChanged){if(!zoomChanged&&this.center){this.centerLayerContainer(lonlat);}
+this.center=lonlat.clone();}
+var res=zoomChanged?this.getResolutionForZoom(zoom):this.getResolution();if(zoomChanged||this.layerContainerOrigin==null){this.layerContainerOrigin=this.getCachedCenter();var style=this.layerContainerDiv.style;style.left="0px";style.top="0px";this.layerContainerOriginPx.x=0;this.layerContainerOriginPx.y=0;var maxExtent=this.getMaxExtent({restricted:true});var maxExtentCenter=maxExtent.getCenterLonLat();var lonDelta=this.center.lon-maxExtentCenter.lon;var latDelta=maxExtentCenter.lat-this.center.lat;var extentWidth=Math.round(maxExtent.getWidth()/res);var extentHeight=Math.round(maxExtent.getHeight()/res);this.minPx={x:(this.size.w-extentWidth)/2-lonDelta/res,y:(this.size.h-extentHeight)/2-latDelta/res};this.maxPx={x:this.minPx.x+Math.round(maxExtent.getWidth()/res),y:this.minPx.y+Math.round(maxExtent.getHeight()/res)};}
+if(zoomChanged){this.zoom=zoom;this.resolution=res;}
+var bounds=this.getExtent();if(this.baseLayer.visibility){this.baseLayer.moveTo(bounds,zoomChanged,options.dragging);options.dragging||this.baseLayer.events.triggerEvent("moveend",{zoomChanged:zoomChanged});}
+bounds=this.baseLayer.getExtent();for(var i=this.layers.length-1;i>=0;--i){var layer=this.layers[i];if(layer!==this.baseLayer&&!layer.isBaseLayer){var inRange=layer.calculateInRange();if(layer.inRange!=inRange){layer.inRange=inRange;if(!inRange){layer.display(false);}
+this.events.triggerEvent("changelayer",{layer:layer,property:"visibility"});}
+if(inRange&&layer.visibility){layer.moveTo(bounds,zoomChanged,options.dragging);options.dragging||layer.events.triggerEvent("moveend",{zoomChanged:zoomChanged});}}}
+this.events.triggerEvent("move");dragging||this.events.triggerEvent("moveend");if(zoomChanged){for(var i=0,len=this.popups.length;i=0)&&(zoomLevel0){resolution=this.layers[0].getResolution();}
+return resolution;},getUnits:function(){var units=null;if(this.baseLayer!=null){units=this.baseLayer.units;}
+return units;},getScale:function(){var scale=null;if(this.baseLayer!=null){var res=this.getResolution();var units=this.baseLayer.units;scale=OpenLayers.Util.getScaleFromResolution(res,units);}
+return scale;},getZoomForExtent:function(bounds,closest){var zoom=null;if(this.baseLayer!=null){zoom=this.baseLayer.getZoomForExtent(bounds,closest);}
+return zoom;},getResolutionForZoom:function(zoom){var resolution=null;if(this.baseLayer){resolution=this.baseLayer.getResolutionForZoom(zoom);}
+return resolution;},getZoomForResolution:function(resolution,closest){var zoom=null;if(this.baseLayer!=null){zoom=this.baseLayer.getZoomForResolution(resolution,closest);}
+return zoom;},zoomTo:function(zoom){if(this.isValidZoomLevel(zoom)){this.setCenter(null,zoom);}},zoomIn:function(){this.zoomTo(this.getZoom()+1);},zoomOut:function(){this.zoomTo(this.getZoom()-1);},zoomToExtent:function(bounds,closest){if(!(bounds instanceof OpenLayers.Bounds)){bounds=new OpenLayers.Bounds(bounds);}
+var center=bounds.getCenterLonLat();if(this.baseLayer.wrapDateLine){var maxExtent=this.getMaxExtent();bounds=bounds.clone();while(bounds.right=0){this.initResolutions();if(reinitialize&&this.map.baseLayer===this){this.map.setCenter(this.map.getCenter(),this.map.getZoomForResolution(resolution),false,true);this.map.events.triggerEvent("changebaselayer",{layer:this});}
+break;}}}},onMapResize:function(){},redraw:function(){var redrawn=false;if(this.map){this.inRange=this.calculateInRange();var extent=this.getExtent();if(extent&&this.inRange&&this.visibility){var zoomChanged=true;this.moveTo(extent,zoomChanged,false);this.events.triggerEvent("moveend",{"zoomChanged":zoomChanged});redrawn=true;}}
+return redrawn;},moveTo:function(bounds,zoomChanged,dragging){var display=this.visibility;if(!this.isBaseLayer){display=display&&this.inRange;}
+this.display(display);},moveByPx:function(dx,dy){},setMap:function(map){if(this.map==null){this.map=map;this.maxExtent=this.maxExtent||this.map.maxExtent;this.minExtent=this.minExtent||this.map.minExtent;this.projection=this.projection||this.map.projection;if(typeof this.projection=="string"){this.projection=new OpenLayers.Projection(this.projection);}
+this.units=this.projection.getUnits()||this.units||this.map.units;this.initResolutions();if(!this.isBaseLayer){this.inRange=this.calculateInRange();var show=((this.visibility)&&(this.inRange));this.div.style.display=show?"":"none";}
+this.setTileSize();}},afterAdd:function(){},removeMap:function(map){},getImageSize:function(bounds){return(this.imageSize||this.tileSize);},setTileSize:function(size){var tileSize=(size)?size:((this.tileSize)?this.tileSize:this.map.getTileSize());this.tileSize=tileSize;if(this.gutter){this.imageSize=new OpenLayers.Size(tileSize.w+(2*this.gutter),tileSize.h+(2*this.gutter));}},getVisibility:function(){return this.visibility;},setVisibility:function(visibility){if(visibility!=this.visibility){this.visibility=visibility;this.display(visibility);this.redraw();if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"visibility"});}
+this.events.triggerEvent("visibilitychanged");}},display:function(display){if(display!=(this.div.style.display!="none")){this.div.style.display=(display&&this.calculateInRange())?"block":"none";}},calculateInRange:function(){var inRange=false;if(this.alwaysInRange){inRange=true;}else{if(this.map){var resolution=this.map.getResolution();inRange=((resolution>=this.minResolution)&&(resolution<=this.maxResolution));}}
+return inRange;},setIsBaseLayer:function(isBaseLayer){if(isBaseLayer!=this.isBaseLayer){this.isBaseLayer=isBaseLayer;if(this.map!=null){this.map.events.triggerEvent("changebaselayer",{layer:this});}}},initResolutions:function(){var i,len,p;var props={},alwaysInRange=true;for(i=0,len=this.RESOLUTION_PROPERTIES.length;i=resolution){highRes=res;lowZoom=i;}
+if(res<=resolution){lowRes=res;highZoom=i;break;}}
+var dRes=highRes-lowRes;if(dRes>0){zoom=lowZoom+((highRes-resolution)/dRes);}else{zoom=lowZoom;}}else{var diff;var minDiff=Number.POSITIVE_INFINITY;for(i=0,len=this.resolutions.length;iminDiff){break;}
+minDiff=diff;}else{if(this.resolutions[i]=0&&row=0;i--){newResolution=this.serverResolutions[i];newDistance=Math.abs(newResolution-resolution);if(newDistance>distance){break;}
+distance=newDistance;serverResolution=newResolution;}
+resolution=serverResolution;}
+return resolution;},getServerZoom:function(){var resolution=this.getServerResolution();return this.serverResolutions?OpenLayers.Util.indexOf(this.serverResolutions,resolution):this.map.getZoomForResolution(resolution)+(this.zoomOffset||0);},applyBackBuffer:function(resolution){if(this.backBufferTimerId!==null){this.removeBackBuffer();}
+var backBuffer=this.backBuffer;if(!backBuffer){backBuffer=this.createBackBuffer();if(!backBuffer){return;}
+this.div.insertBefore(backBuffer,this.div.firstChild);this.backBuffer=backBuffer;var topLeftTileBounds=this.grid[0][0].bounds;this.backBufferLonLat={lon:topLeftTileBounds.left,lat:topLeftTileBounds.top};this.backBufferResolution=this.gridResolution;}
+var ratio=this.backBufferResolution/resolution;var tiles=backBuffer.childNodes,tile;for(var i=tiles.length-1;i>=0;--i){tile=tiles[i];tile.style.top=((ratio*tile._i*tile._h)|0)+'px';tile.style.left=((ratio*tile._j*tile._w)|0)+'px';tile.style.width=Math.round(ratio*tile._w)+'px';tile.style.height=Math.round(ratio*tile._h)+'px';}
+var position=this.getViewPortPxFromLonLat(this.backBufferLonLat,resolution);var leftOffset=this.map.layerContainerOriginPx.x;var topOffset=this.map.layerContainerOriginPx.y;backBuffer.style.left=Math.round(position.x-leftOffset)+'px';backBuffer.style.top=Math.round(position.y-topOffset)+'px';},createBackBuffer:function(){var backBuffer;if(this.grid.length>0){backBuffer=document.createElement('div');backBuffer.id=this.div.id+'_bb';backBuffer.className='olBackBuffer';backBuffer.style.position='absolute';for(var i=0,lenI=this.grid.length;i=bounds.bottom-tilelat*this.buffer)||rowidx-tileSize.w*(buffer-1)){this.shiftColumn(true,tileSize);}else if(tlViewPort.x<-tileSize.w*buffer){this.shiftColumn(false,tileSize);}else if(tlViewPort.y>-tileSize.h*(buffer-1)){this.shiftRow(true,tileSize);}else if(tlViewPort.y<-tileSize.h*buffer){this.shiftRow(false,tileSize);}else{break;}}},shiftRow:function(prepend,tileSize){var modelRowIndex=(prepend)?0:(this.grid.length-1);var grid=this.grid;var modelRow=grid[modelRowIndex];var sign=prepend?-1:1;var deltaLat=this.getServerResolution()*-sign*this.tileSize.h;var row=(prepend)?grid.pop():grid.shift();for(var i=0,len=modelRow.length;irows){var row=this.grid.pop();for(i=0,l=row.length;icolumns){var row=this.grid[i];var tile=row.pop();this.destroyTile(tile);}}},onMapResize:function(){if(this.singleTile){this.clearGrid();this.setTileSize();}},getTileBounds:function(viewPortPx){var maxExtent=this.maxExtent;var resolution=this.getResolution();var tileMapWidth=resolution*this.tileSize.w;var tileMapHeight=resolution*this.tileSize.h;var mapPoint=this.getLonLatFromViewPortPx(viewPortPx);var tileLeft=maxExtent.left+(tileMapWidth*Math.floor((mapPoint.lon-
+maxExtent.left)/tileMapWidth));var tileBottom=maxExtent.bottom+(tileMapHeight*Math.floor((mapPoint.lat-
+maxExtent.bottom)/tileMapHeight));return new OpenLayers.Bounds(tileLeft,tileBottom,tileLeft+tileMapWidth,tileBottom+tileMapHeight);},CLASS_NAME:"OpenLayers.Layer.Grid"});OpenLayers.Layer.XYZ=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,sphericalMercator:false,zoomOffset:0,serverResolutions:null,initialize:function(name,url,options){if(options&&options.sphericalMercator||this.sphericalMercator){options=OpenLayers.Util.extend({projection:"EPSG:900913",numZoomLevels:19},options);}
+OpenLayers.Layer.Grid.prototype.initialize.apply(this,[name||this.name,url||this.url,{},options]);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.XYZ(this.name,this.url,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){var xyz=this.getXYZ(bounds);var url=this.url;if(OpenLayers.Util.isArray(url)){var s=''+xyz.x+xyz.y+xyz.z;url=this.selectUrl(s,url);}
+return OpenLayers.String.format(url,xyz);},getXYZ:function(bounds){var res=this.getServerResolution();var x=Math.round((bounds.left-this.maxExtent.left)/(res*this.tileSize.w));var y=Math.round((this.maxExtent.top-bounds.top)/(res*this.tileSize.h));var z=this.getServerZoom();if(this.wrapDateLine){var limit=Math.pow(2,z);x=((x%limit)+limit)%limit;}
+return{'x':x,'y':y,'z':z};},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.maxExtent.left,this.maxExtent.bottom);}},CLASS_NAME:"OpenLayers.Layer.XYZ"});OpenLayers.Layer.OSM=OpenLayers.Class(OpenLayers.Layer.XYZ,{name:"OpenStreetMap",url:['http://a.tile.openstreetmap.org/${z}/${x}/${y}.png','http://b.tile.openstreetmap.org/${z}/${x}/${y}.png','http://c.tile.openstreetmap.org/${z}/${x}/${y}.png'],attribution:"Data CC-By-SA by OpenStreetMap ",sphericalMercator:true,wrapDateLine:true,tileOptions:null,initialize:function(name,url,options){OpenLayers.Layer.XYZ.prototype.initialize.apply(this,arguments);this.tileOptions=OpenLayers.Util.extend({crossOriginKeyword:'anonymous'},this.options&&this.options.tileOptions);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.OSM(this.name,this.url,this.getOptions());}
+obj=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.OSM"});OpenLayers.Renderer=OpenLayers.Class({container:null,root:null,extent:null,locked:false,size:null,resolution:null,map:null,featureDx:0,initialize:function(containerID,options){this.container=OpenLayers.Util.getElement(containerID);OpenLayers.Util.extend(this,options);},destroy:function(){this.container=null;this.extent=null;this.size=null;this.resolution=null;this.map=null;},supported:function(){return false;},setExtent:function(extent,resolutionChanged){this.extent=extent.clone();if(this.map.baseLayer&&this.map.baseLayer.wrapDateLine){var ratio=extent.getWidth()/this.map.getExtent().getWidth(),extent=extent.scale(1/ratio);this.extent=extent.wrapDateLine(this.map.getMaxExtent()).scale(ratio);}
+if(resolutionChanged){this.resolution=null;}
+return true;},setSize:function(size){this.size=size.clone();this.resolution=null;},getResolution:function(){this.resolution=this.resolution||this.map.getResolution();return this.resolution;},drawFeature:function(feature,style){if(style==null){style=feature.style;}
+if(feature.geometry){var bounds=feature.geometry.getBounds();if(bounds){var worldBounds;if(this.map.baseLayer&&this.map.baseLayer.wrapDateLine){worldBounds=this.map.getMaxExtent();}
+if(!bounds.intersectsBounds(this.extent,{worldBounds:worldBounds})){style={display:"none"};}else{this.calculateFeatureDx(bounds,worldBounds);}
+var rendered=this.drawGeometry(feature.geometry,style,feature.id);if(style.display!="none"&&style.label&&rendered!==false){var location=feature.geometry.getCentroid();if(style.labelXOffset||style.labelYOffset){var xOffset=isNaN(style.labelXOffset)?0:style.labelXOffset;var yOffset=isNaN(style.labelYOffset)?0:style.labelYOffset;var res=this.getResolution();location.move(xOffset*res,yOffset*res);}
+this.drawText(feature.id,style,location);}else{this.removeText(feature.id);}
+return rendered;}}},calculateFeatureDx:function(bounds,worldBounds){this.featureDx=0;if(worldBounds){var worldWidth=worldBounds.getWidth(),rendererCenterX=(this.extent.left+this.extent.right)/2,featureCenterX=(bounds.left+bounds.right)/2,worldsAway=Math.round((featureCenterX-rendererCenterX)/worldWidth);this.featureDx=worldsAway*worldWidth;}},drawGeometry:function(geometry,style,featureId){},drawText:function(featureId,style,location){},removeText:function(featureId){},clear:function(){},getFeatureIdFromEvent:function(evt){},eraseFeatures:function(features){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+for(var i=0,len=features.length;i=16777216){this.hitOverflow=id-16777215;id=id%16777216+1;}
+var hex="000000"+id.toString(16);var len=hex.length;hex="#"+hex.substring(len-6,len);return hex;},setHitContextStyle:function(type,featureId,symbolizer,strokeScaling){var hex=this.featureIdToHex(featureId);if(type=="fill"){this.hitContext.globalAlpha=1.0;this.hitContext.fillStyle=hex;}else if(type=="stroke"){this.hitContext.globalAlpha=1.0;this.hitContext.strokeStyle=hex;if(typeof strokeScaling==="undefined"){this.hitContext.lineWidth=symbolizer.strokeWidth+2;}else{if(!isNaN(strokeScaling)){this.hitContext.lineWidth=symbolizer.strokeWidth+2.0/strokeScaling;}}}else{this.hitContext.globalAlpha=0;this.hitContext.lineWidth=1;}},drawPoint:function(geometry,style,featureId){if(style.graphic!==false){if(style.externalGraphic){this.drawExternalGraphic(geometry,style,featureId);}else if(style.graphicName&&(style.graphicName!="circle")){this.drawNamedSymbol(geometry,style,featureId);}else{var pt=this.getLocalXY(geometry);var p0=pt[0];var p1=pt[1];if(!isNaN(p0)&&!isNaN(p1)){var twoPi=Math.PI*2;var radius=style.pointRadius;if(style.fill!==false){this.setCanvasStyle("fill",style);this.canvas.beginPath();this.canvas.arc(p0,p1,radius,0,twoPi,true);this.canvas.fill();if(this.hitDetection){this.setHitContextStyle("fill",featureId,style);this.hitContext.beginPath();this.hitContext.arc(p0,p1,radius,0,twoPi,true);this.hitContext.fill();}}
+if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.canvas.beginPath();this.canvas.arc(p0,p1,radius,0,twoPi,true);this.canvas.stroke();if(this.hitDetection){this.setHitContextStyle("stroke",featureId,style);this.hitContext.beginPath();this.hitContext.arc(p0,p1,radius,0,twoPi,true);this.hitContext.stroke();}
+this.setCanvasStyle("reset");}}}}},drawLineString:function(geometry,style,featureId){style=OpenLayers.Util.applyDefaults({fill:false},style);this.drawLinearRing(geometry,style,featureId);},drawLinearRing:function(geometry,style,featureId){if(style.fill!==false){this.setCanvasStyle("fill",style);this.renderPath(this.canvas,geometry,style,featureId,"fill");if(this.hitDetection){this.setHitContextStyle("fill",featureId,style);this.renderPath(this.hitContext,geometry,style,featureId,"fill");}}
+if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.renderPath(this.canvas,geometry,style,featureId,"stroke");if(this.hitDetection){this.setHitContextStyle("stroke",featureId,style);this.renderPath(this.hitContext,geometry,style,featureId,"stroke");}}
+this.setCanvasStyle("reset");},renderPath:function(context,geometry,style,featureId,type){var components=geometry.components;var len=components.length;context.beginPath();var start=this.getLocalXY(components[0]);var x=start[0];var y=start[1];if(!isNaN(x)&&!isNaN(y)){context.moveTo(start[0],start[1]);for(var i=1;i1){middle=parseInt((leftIndex+rightIndex)/2);var placement=this.compare(this,newNode,OpenLayers.Util.getElement(this.order[middle]));if(placement>0){leftIndex=middle;}else{rightIndex=middle;}}
+this.order.splice(rightIndex,0,nodeId);this.indices[nodeId]=this.getZIndex(newNode);return this.getNextElement(rightIndex);},remove:function(node){var nodeId=node.id;var arrayIndex=OpenLayers.Util.indexOf(this.order,nodeId);if(arrayIndex>=0){this.order.splice(arrayIndex,1);delete this.indices[nodeId];if(this.order.length>0){var lastId=this.order[this.order.length-1];this.maxZIndex=this.indices[lastId];}else{this.maxZIndex=0;}}},clear:function(){this.order=[];this.indices={};this.maxZIndex=0;},exists:function(node){return(this.indices[node.id]!=null);},getZIndex:function(node){return node._style.graphicZIndex;},determineZIndex:function(node){var zIndex=node._style.graphicZIndex;if(zIndex==null){zIndex=this.maxZIndex;node._style.graphicZIndex=zIndex;}else if(zIndex>this.maxZIndex){this.maxZIndex=zIndex;}},getNextElement:function(index){var nextIndex=index+1;if(nextIndexextent.left&&world.rightextent.left&&world.left0;},CLASS_NAME:"OpenLayers.Protocol.Response"});OpenLayers.Protocol.Response.SUCCESS=1;OpenLayers.Protocol.Response.FAILURE=0;OpenLayers.Protocol.WFS=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Protocol.WFS.DEFAULTS);var cls=OpenLayers.Protocol.WFS["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported WFS version: "+options.version;}
+return new cls(options);};OpenLayers.Protocol.WFS.fromWMSLayer=function(layer,options){var typeName,featurePrefix;var param=layer.params["LAYERS"];var parts=(OpenLayers.Util.isArray(param)?param[0]:param).split(":");if(parts.length>1){featurePrefix=parts[0];}
+typeName=parts.pop();var protocolOptions={url:layer.url,featureType:typeName,featurePrefix:featurePrefix,srsName:layer.projection&&layer.projection.getCode()||layer.map&&layer.map.getProjectionObject().getCode(),version:"1.1.0"};return new OpenLayers.Protocol.WFS(OpenLayers.Util.applyDefaults(options,protocolOptions));};OpenLayers.Protocol.WFS.DEFAULTS={"version":"1.0.0"};OpenLayers.Strategy=OpenLayers.Class({layer:null,options:null,active:null,autoActivate:true,autoDestroy:true,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;this.active=false;},destroy:function(){this.deactivate();this.layer=null;this.options=null;},setLayer:function(layer){this.layer=layer;},activate:function(){if(!this.active){this.active=true;return true;}
+return false;},deactivate:function(){if(this.active){this.active=false;return true;}
+return false;},CLASS_NAME:"OpenLayers.Strategy"});OpenLayers.Strategy.BBOX=OpenLayers.Class(OpenLayers.Strategy,{bounds:null,resolution:null,ratio:2,resFactor:null,response:null,activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"moveend":this.update,"refresh":this.update,"visibilitychanged":this.update,scope:this});this.update();}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.layer.events.un({"moveend":this.update,"refresh":this.update,"visibilitychanged":this.update,scope:this});}
+return deactivated;},update:function(options){var mapBounds=this.getMapBounds();if(mapBounds!==null&&((options&&options.force)||(this.layer.visibility&&this.layer.calculateInRange()&&this.invalidBounds(mapBounds)))){this.calculateBounds(mapBounds);this.resolution=this.layer.map.getResolution();this.triggerRead(options);}},getMapBounds:function(){if(this.layer.map===null){return null;}
+var bounds=this.layer.map.getExtent();if(bounds&&!this.layer.projection.equals(this.layer.map.getProjectionObject())){bounds=bounds.clone().transform(this.layer.map.getProjectionObject(),this.layer.projection);}
+return bounds;},invalidBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();}
+var invalid=!this.bounds||!this.bounds.containsBounds(mapBounds);if(!invalid&&this.resFactor){var ratio=this.resolution/this.layer.map.getResolution();invalid=(ratio>=this.resFactor||ratio<=(1/this.resFactor));}
+return invalid;},calculateBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();}
+var center=mapBounds.getCenterLonLat();var dataWidth=mapBounds.getWidth()*this.ratio;var dataHeight=mapBounds.getHeight()*this.ratio;this.bounds=new OpenLayers.Bounds(center.lon-(dataWidth/2),center.lat-(dataHeight/2),center.lon+(dataWidth/2),center.lat+(dataHeight/2));},triggerRead:function(options){if(this.response&&!(options&&options.noAbort===true)){this.layer.protocol.abort(this.response);this.layer.events.triggerEvent("loadend");}
+this.layer.events.triggerEvent("loadstart");this.response=this.layer.protocol.read(OpenLayers.Util.applyDefaults({filter:this.createFilter(),callback:this.merge,scope:this},options));},createFilter:function(){var filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,value:this.bounds,projection:this.layer.projection});if(this.layer.filter){filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.layer.filter,filter]});}
+return filter;},merge:function(resp){this.layer.destroyFeatures();var features=resp.features;if(features&&features.length>0){var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var geom;for(var i=0,len=features.length;i-1;},handle:function(evt){if(this.feature&&!this.feature.layer){this.feature=null;}
+var type=evt.type;var handled=false;var previouslyIn=!!(this.feature);var click=(type=="click"||type=="dblclick"||type=="touchstart");this.feature=this.layer.getFeatureFromEvent(evt);if(this.feature&&!this.feature.layer){this.feature=null;}
+if(this.lastFeature&&!this.lastFeature.layer){this.lastFeature=null;}
+if(this.feature){if(type==="touchstart"){OpenLayers.Event.stop(evt);}
+var inNew=(this.feature!=this.lastFeature);if(this.geometryTypeMatches(this.feature)){if(previouslyIn&&inNew){if(this.lastFeature){this.triggerCallback(type,'out',[this.lastFeature]);}
+this.triggerCallback(type,'in',[this.feature]);}else if(!previouslyIn||click){this.triggerCallback(type,'in',[this.feature]);}
+this.lastFeature=this.feature;handled=true;}else{if(this.lastFeature&&(previouslyIn&&inNew||click)){this.triggerCallback(type,'out',[this.lastFeature]);}
+this.feature=null;}}else{if(this.lastFeature&&(previouslyIn||click)){this.triggerCallback(type,'out',[this.lastFeature]);}}
+return handled;},triggerCallback:function(type,mode,args){var key=this.EVENTMAP[type][mode];if(key){if(type=='click'&&this.up&&this.down){var dpx=Math.sqrt(Math.pow(this.up.x-this.down.x,2)+
+Math.pow(this.up.y-this.down.y,2));if(dpx<=this.clickTolerance){this.callback(key,args);}}else{this.callback(key,args);}}},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.moveLayerToTop();this.map.events.on({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.moveLayerBack();this.feature=null;this.lastFeature=null;this.down=null;this.up=null;this.touch=false;this.map.events.un({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});deactivated=true;}
+return deactivated;},handleMapEvents:function(evt){if(evt.type=="removelayer"||evt.property=="order"){this.moveLayerToTop();}},moveLayerToTop:function(){var index=Math.max(this.map.Z_INDEX_BASE['Feature']-1,this.layer.getZIndex())+1;this.layer.setZIndex(index);},moveLayerBack:function(){var index=this.layer.getZIndex()-1;if(index>=this.map.Z_INDEX_BASE['Feature']){this.layer.setZIndex(index);}else{this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer));}},CLASS_NAME:"OpenLayers.Handler.Feature"});OpenLayers.StyleMap=OpenLayers.Class({styles:null,extendDefault:true,initialize:function(style,options){this.styles={"default":new OpenLayers.Style(OpenLayers.Feature.Vector.style["default"]),"select":new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"]),"temporary":new OpenLayers.Style(OpenLayers.Feature.Vector.style["temporary"]),"delete":new OpenLayers.Style(OpenLayers.Feature.Vector.style["delete"])};if(style instanceof OpenLayers.Style){this.styles["default"]=style;this.styles["select"]=style;this.styles["temporary"]=style;this.styles["delete"]=style;}else if(typeof style=="object"){for(var key in style){if(style[key]instanceof OpenLayers.Style){this.styles[key]=style[key];}else if(typeof style[key]=="object"){this.styles[key]=new OpenLayers.Style(style[key]);}else{this.styles["default"]=new OpenLayers.Style(style);this.styles["select"]=new OpenLayers.Style(style);this.styles["temporary"]=new OpenLayers.Style(style);this.styles["delete"]=new OpenLayers.Style(style);break;}}}
+OpenLayers.Util.extend(this,options);},destroy:function(){for(var key in this.styles){this.styles[key].destroy();}
+this.styles=null;},createSymbolizer:function(feature,intent){if(!feature){feature=new OpenLayers.Feature.Vector();}
+if(!this.styles[intent]){intent="default";}
+feature.renderIntent=intent;var defaultSymbolizer={};if(this.extendDefault&&intent!="default"){defaultSymbolizer=this.styles["default"].createSymbolizer(feature);}
+return OpenLayers.Util.extend(defaultSymbolizer,this.styles[intent].createSymbolizer(feature));},addUniqueValueRules:function(renderIntent,property,symbolizers,context){var rules=[];for(var value in symbolizers){rules.push(new OpenLayers.Rule({symbolizer:symbolizers[value],context:context,filter:new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,property:property,value:value})}));}
+this.styles[renderIntent].addRules(rules);},CLASS_NAME:"OpenLayers.StyleMap"});OpenLayers.Layer.Vector=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:false,isFixed:false,features:null,filter:null,selectedFeatures:null,unrenderedFeatures:null,reportError:true,style:null,styleMap:null,strategies:null,protocol:null,renderers:['SVG','VML','Canvas'],renderer:null,rendererOptions:null,geometryType:null,drawn:false,ratio:1,initialize:function(name,options){OpenLayers.Layer.prototype.initialize.apply(this,arguments);if(!this.renderer||!this.renderer.supported()){this.assignRenderer();}
+if(!this.renderer||!this.renderer.supported()){this.renderer=null;this.displayError();}
+if(!this.styleMap){this.styleMap=new OpenLayers.StyleMap();}
+this.features=[];this.selectedFeatures=[];this.unrenderedFeatures={};if(this.strategies){for(var i=0,len=this.strategies.length;i=0;i--){if(i!=0&&features[i-1].geometry){this.renderer.locked=true;}else{this.renderer.locked=false;}
+var feature=features[i];delete this.unrenderedFeatures[feature.id];if(notify){this.events.triggerEvent("beforefeatureremoved",{feature:feature});}
+this.features=OpenLayers.Util.removeItem(this.features,feature);feature.layer=null;if(feature.geometry){this.renderer.eraseFeatures(feature);}
+if(OpenLayers.Util.indexOf(this.selectedFeatures,feature)!=-1){OpenLayers.Util.removeItem(this.selectedFeatures,feature);}
+if(notify){this.events.triggerEvent("featureremoved",{feature:feature});}}
+if(notify){this.events.triggerEvent("featuresremoved",{features:features});}},removeAllFeatures:function(options){var notify=!options||!options.silent;var features=this.features;if(notify){this.events.triggerEvent("beforefeaturesremoved",{features:features});}
+var feature;for(var i=features.length-1;i>=0;i--){feature=features[i];if(notify){this.events.triggerEvent("beforefeatureremoved",{feature:feature});}
+feature.layer=null;if(notify){this.events.triggerEvent("featureremoved",{feature:feature});}}
+this.renderer.clear();this.features=[];this.unrenderedFeatures={};this.selectedFeatures=[];if(notify){this.events.triggerEvent("featuresremoved",{features:features});}},destroyFeatures:function(features,options){var all=(features==undefined);if(all){features=this.features;}
+if(features){this.removeFeatures(features,options);for(var i=features.length-1;i>=0;i--){features[i].destroy();}}},drawFeature:function(feature,style){if(!this.drawn){return;}
+if(typeof style!="object"){if(!style&&feature.state===OpenLayers.State.DELETE){style="delete";}
+var renderIntent=style||feature.renderIntent;style=feature.style||this.style;if(!style){style=this.styleMap.createSymbolizer(feature,renderIntent);}}
+var drawn=this.renderer.drawFeature(feature,style);if(drawn===false||drawn===null){this.unrenderedFeatures[feature.id]=feature;}else{delete this.unrenderedFeatures[feature.id];}},eraseFeatures:function(features){this.renderer.eraseFeatures(features);},getFeatureFromEvent:function(evt){if(!this.renderer){throw new Error('getFeatureFromEvent called on layer with no '+'renderer. This usually means you destroyed a '+'layer, but not some handler which is associated '+'with it.');}
+var feature=null;var featureId=this.renderer.getFeatureIdFromEvent(evt);if(featureId){if(typeof featureId==="string"){feature=this.getFeatureById(featureId);}else{feature=featureId;}}
+return feature;},getFeatureBy:function(property,value){var feature=null;for(var i=0,len=this.features.length;i0)){var geometry=null;for(var i=0,len=features.length;inumExcept){feature=layer.selectedFeatures[numExcept];if(!options||options.except!=feature){this.unselect(feature);}else{++numExcept;}}}},clickFeature:function(feature){if(!this.hover){var selected=(OpenLayers.Util.indexOf(feature.layer.selectedFeatures,feature)>-1);if(selected){if(this.toggleSelect()){this.unselect(feature);}else if(!this.multipleSelect()){this.unselectAll({except:feature});}}else{if(!this.multipleSelect()){this.unselectAll({except:feature});}
+this.select(feature);}}},multipleSelect:function(){return this.multiple||(this.handlers.feature.evt&&this.handlers.feature.evt[this.multipleKey]);},toggleSelect:function(){return this.toggle||(this.handlers.feature.evt&&this.handlers.feature.evt[this.toggleKey]);},clickoutFeature:function(feature){if(!this.hover&&this.clickout){this.unselectAll();}},overFeature:function(feature){var layer=feature.layer;if(this.hover){if(this.highlightOnly){this.highlight(feature);}else if(OpenLayers.Util.indexOf(layer.selectedFeatures,feature)==-1){this.select(feature);}}},outFeature:function(feature){if(this.hover){if(this.highlightOnly){if(feature._lastHighlighter==this.id){if(feature._prevHighlighter&&feature._prevHighlighter!=this.id){delete feature._lastHighlighter;var control=this.map.getControl(feature._prevHighlighter);if(control){control.highlight(feature);}}else{this.unhighlight(feature);}}}else{this.unselect(feature);}}},highlight:function(feature){var layer=feature.layer;var cont=this.events.triggerEvent("beforefeaturehighlighted",{feature:feature});if(cont!==false){feature._prevHighlighter=feature._lastHighlighter;feature._lastHighlighter=this.id;var style=this.selectStyle||this.renderIntent;layer.drawFeature(feature,style);this.events.triggerEvent("featurehighlighted",{feature:feature});}},unhighlight:function(feature){var layer=feature.layer;if(feature._prevHighlighter==undefined){delete feature._lastHighlighter;}else if(feature._prevHighlighter==this.id){delete feature._prevHighlighter;}else{feature._lastHighlighter=feature._prevHighlighter;delete feature._prevHighlighter;}
+layer.drawFeature(feature,feature.style||feature.layer.style||"default");this.events.triggerEvent("featureunhighlighted",{feature:feature});},select:function(feature){var cont=this.onBeforeSelect.call(this.scope,feature);var layer=feature.layer;if(cont!==false){cont=layer.events.triggerEvent("beforefeatureselected",{feature:feature});if(cont!==false){layer.selectedFeatures.push(feature);this.highlight(feature);if(!this.handlers.feature.lastFeature){this.handlers.feature.lastFeature=layer.selectedFeatures[0];}
+layer.events.triggerEvent("featureselected",{feature:feature});this.onSelect.call(this.scope,feature);}}},unselect:function(feature){var layer=feature.layer;this.unhighlight(feature);OpenLayers.Util.removeItem(layer.selectedFeatures,feature);layer.events.triggerEvent("featureunselected",{feature:feature});this.onUnselect.call(this.scope,feature);},selectBox:function(position){if(position instanceof OpenLayers.Bounds){var minXY=this.map.getLonLatFromPixel({x:position.left,y:position.bottom});var maxXY=this.map.getLonLatFromPixel({x:position.right,y:position.top});var bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);if(!this.multipleSelect()){this.unselectAll();}
+var prevMultiple=this.multiple;this.multiple=true;var layers=this.layers||[this.layer];this.events.triggerEvent("boxselectionstart",{layers:layers});var layer;for(var l=0;l-1){if(bounds.toGeometry().intersects(feature.geometry)){if(OpenLayers.Util.indexOf(layer.selectedFeatures,feature)==-1){this.select(feature);}}}}}
+this.multiple=prevMultiple;this.events.triggerEvent("boxselectionend",{layers:layers});}},setMap:function(map){this.handlers.feature.setMap(map);if(this.box){this.handlers.box.setMap(map);}
+OpenLayers.Control.prototype.setMap.apply(this,arguments);},setLayer:function(layers){var isActive=this.active;this.unselectAll();this.deactivate();if(this.layers){this.layer.destroy();this.layers=null;}
+this.initLayer(layers);this.handlers.feature.layer=this.layer;if(isActive){this.activate();}},CLASS_NAME:"OpenLayers.Control.SelectFeature"});OpenLayers.Handler.Point=OpenLayers.Class(OpenLayers.Handler,{point:null,layer:null,multi:false,citeCompliant:false,mouseDown:false,stoppedDown:null,lastDown:null,lastUp:null,persist:false,stopDown:false,stopUp:false,layerOptions:null,pixelTolerance:5,touch:false,lastTouchPx:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});}
+OpenLayers.Handler.prototype.initialize.apply(this,arguments);},activate:function(){if(!OpenLayers.Handler.prototype.activate.apply(this,arguments)){return false;}
+var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True,wrapDateLine:this.citeCompliant},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);return true;},createFeature:function(pixel){var lonlat=this.layer.getLonLatFromViewPortPx(pixel);var geometry=new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);this.point=new OpenLayers.Feature.Vector(geometry);this.callback("create",[this.point.geometry,this.point]);this.point.geometry.clearBounds();this.layer.addFeatures([this.point],{silent:true});},deactivate:function(){if(!OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){return false;}
+this.cancel();if(this.layer.map!=null){this.destroyFeature(true);this.layer.destroy(false);}
+this.layer=null;this.touch=false;return true;},destroyFeature:function(force){if(this.layer&&(force||!this.persist)){this.layer.destroyFeatures();}
+this.point=null;},destroyPersistedFeature:function(){var layer=this.layer;if(layer&&layer.features.length>1){this.layer.features[0].destroy();}},finalize:function(cancel){var key=cancel?"cancel":"done";this.mouseDown=false;this.lastDown=null;this.lastUp=null;this.lastTouchPx=null;this.callback(key,[this.geometryClone()]);this.destroyFeature(cancel);},cancel:function(){this.finalize(true);},click:function(evt){OpenLayers.Event.stop(evt);return false;},dblclick:function(evt){OpenLayers.Event.stop(evt);return false;},modifyFeature:function(pixel){if(!this.point){this.createFeature(pixel);}
+var lonlat=this.layer.getLonLatFromViewPortPx(pixel);this.point.geometry.x=lonlat.lon;this.point.geometry.y=lonlat.lat;this.callback("modify",[this.point.geometry,this.point,false]);this.point.geometry.clearBounds();this.drawFeature();},drawFeature:function(){this.layer.drawFeature(this.point,this.style);},getGeometry:function(){var geometry=this.point&&this.point.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiPoint([geometry]);}
+return geometry;},geometryClone:function(){var geom=this.getGeometry();return geom&&geom.clone();},mousedown:function(evt){return this.down(evt);},touchstart:function(evt){if(!this.touch){this.touch=true;this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,mousemove:this.mousemove,click:this.click,dblclick:this.dblclick,scope:this});}
+this.lastTouchPx=evt.xy;return this.down(evt);},mousemove:function(evt){return this.move(evt);},touchmove:function(evt){this.lastTouchPx=evt.xy;return this.move(evt);},mouseup:function(evt){return this.up(evt);},touchend:function(evt){evt.xy=this.lastTouchPx;return this.up(evt);},down:function(evt){this.mouseDown=true;this.lastDown=evt.xy;if(!this.touch){this.modifyFeature(evt.xy);}
+this.stoppedDown=this.stopDown;return!this.stopDown;},move:function(evt){if(!this.touch&&(!this.mouseDown||this.stoppedDown)){this.modifyFeature(evt.xy);}
+return true;},up:function(evt){this.mouseDown=false;this.stoppedDown=this.stopDown;if(!this.checkModifiers(evt)){return true;}
+if(this.lastUp&&this.lastUp.equals(evt.xy)){return true;}
+if(this.lastDown&&this.passesTolerance(this.lastDown,evt.xy,this.pixelTolerance)){if(this.touch){this.modifyFeature(evt.xy);}
+if(this.persist){this.destroyPersistedFeature();}
+this.lastUp=evt.xy;this.finalize();return!this.stopUp;}else{return true;}},mouseout:function(evt){if(OpenLayers.Util.mouseLeft(evt,this.map.viewPortDiv)){this.stoppedDown=this.stopDown;this.mouseDown=false;}},passesTolerance:function(pixel1,pixel2,tolerance){var passes=true;if(tolerance!=null&&pixel1&&pixel2){var dist=pixel1.distanceTo(pixel2);if(dist>tolerance){passes=false;}}
+return passes;},CLASS_NAME:"OpenLayers.Handler.Point"});OpenLayers.Handler.Path=OpenLayers.Class(OpenLayers.Handler.Point,{line:null,maxVertices:null,doubleTouchTolerance:20,freehand:false,freehandToggle:'shiftKey',timerId:null,redoStack:null,createFeature:function(pixel){var lonlat=this.layer.getLonLatFromViewPortPx(pixel);var geometry=new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);this.point=new OpenLayers.Feature.Vector(geometry);this.line=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([this.point.geometry]));this.callback("create",[this.point.geometry,this.getSketch()]);this.point.geometry.clearBounds();this.layer.addFeatures([this.line,this.point],{silent:true});},destroyFeature:function(force){OpenLayers.Handler.Point.prototype.destroyFeature.call(this,force);this.line=null;},destroyPersistedFeature:function(){var layer=this.layer;if(layer&&layer.features.length>2){this.layer.features[0].destroy();}},removePoint:function(){if(this.point){this.layer.removeFeatures([this.point]);}},addPoint:function(pixel){this.layer.removeFeatures([this.point]);var lonlat=this.layer.getLonLatFromViewPortPx(pixel);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));this.line.geometry.addComponent(this.point.geometry,this.line.geometry.components.length);this.layer.addFeatures([this.point]);this.callback("point",[this.point.geometry,this.getGeometry()]);this.callback("modify",[this.point.geometry,this.getSketch()]);this.drawFeature();delete this.redoStack;},insertXY:function(x,y){this.line.geometry.addComponent(new OpenLayers.Geometry.Point(x,y),this.getCurrentPointIndex());this.drawFeature();delete this.redoStack;},insertDeltaXY:function(dx,dy){var previousIndex=this.getCurrentPointIndex()-1;var p0=this.line.geometry.components[previousIndex];if(p0&&!isNaN(p0.x)&&!isNaN(p0.y)){this.insertXY(p0.x+dx,p0.y+dy);}},insertDirectionLength:function(direction,length){direction*=Math.PI/180;var dx=length*Math.cos(direction);var dy=length*Math.sin(direction);this.insertDeltaXY(dx,dy);},insertDeflectionLength:function(deflection,length){var previousIndex=this.getCurrentPointIndex()-1;if(previousIndex>0){var p1=this.line.geometry.components[previousIndex];var p0=this.line.geometry.components[previousIndex-1];var theta=Math.atan2(p1.y-p0.y,p1.x-p0.x);this.insertDirectionLength((theta*180/Math.PI)+deflection,length);}},getCurrentPointIndex:function(){return this.line.geometry.components.length-1;},undo:function(){var geometry=this.line.geometry;var components=geometry.components;var index=this.getCurrentPointIndex()-1;var target=components[index];var undone=geometry.removeComponent(target);if(undone){if(!this.redoStack){this.redoStack=[];}
+this.redoStack.push(target);this.drawFeature();}
+return undone;},redo:function(){var target=this.redoStack&&this.redoStack.pop();if(target){this.line.geometry.addComponent(target,this.getCurrentPointIndex());this.drawFeature();}
+return!!target;},freehandMode:function(evt){return(this.freehandToggle&&evt[this.freehandToggle])?!this.freehand:this.freehand;},modifyFeature:function(pixel,drawing){if(!this.line){this.createFeature(pixel);}
+var lonlat=this.layer.getLonLatFromViewPortPx(pixel);this.point.geometry.x=lonlat.lon;this.point.geometry.y=lonlat.lat;this.callback("modify",[this.point.geometry,this.getSketch(),drawing]);this.point.geometry.clearBounds();this.drawFeature();},drawFeature:function(){this.layer.drawFeature(this.line,this.style);this.layer.drawFeature(this.point,this.style);},getSketch:function(){return this.line;},getGeometry:function(){var geometry=this.line&&this.line.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiLineString([geometry]);}
+return geometry;},touchstart:function(evt){if(this.timerId&&this.passesTolerance(this.lastTouchPx,evt.xy,this.doubleTouchTolerance)){this.finishGeometry();window.clearTimeout(this.timerId);this.timerId=null;return false;}else{if(this.timerId){window.clearTimeout(this.timerId);this.timerId=null;}
+this.timerId=window.setTimeout(OpenLayers.Function.bind(function(){this.timerId=null;},this),300);return OpenLayers.Handler.Point.prototype.touchstart.call(this,evt);}},down:function(evt){var stopDown=this.stopDown;if(this.freehandMode(evt)){stopDown=true;if(this.touch){this.modifyFeature(evt.xy,!!this.lastUp);OpenLayers.Event.stop(evt);}}
+if(!this.touch&&(!this.lastDown||!this.passesTolerance(this.lastDown,evt.xy,this.pixelTolerance))){this.modifyFeature(evt.xy,!!this.lastUp);}
+this.mouseDown=true;this.lastDown=evt.xy;this.stoppedDown=stopDown;return!stopDown;},move:function(evt){if(this.stoppedDown&&this.freehandMode(evt)){if(this.persist){this.destroyPersistedFeature();}
+if(this.maxVertices&&this.line&&this.line.geometry.components.length===this.maxVertices){this.removePoint();this.finalize();}else{this.addPoint(evt.xy);}
+return false;}
+if(!this.touch&&(!this.mouseDown||this.stoppedDown)){this.modifyFeature(evt.xy,!!this.lastUp);}
+return true;},up:function(evt){if(this.mouseDown&&(!this.lastUp||!this.lastUp.equals(evt.xy))){if(this.stoppedDown&&this.freehandMode(evt)){if(this.persist){this.destroyPersistedFeature();}
+this.removePoint();this.finalize();}else{if(this.passesTolerance(this.lastDown,evt.xy,this.pixelTolerance)){if(this.touch){this.modifyFeature(evt.xy);}
+if(this.lastUp==null&&this.persist){this.destroyPersistedFeature();}
+this.addPoint(evt.xy);this.lastUp=evt.xy;if(this.line.geometry.components.length===this.maxVertices+1){this.finishGeometry();}}}}
+this.stoppedDown=this.stopDown;this.mouseDown=false;return!this.stopUp;},finishGeometry:function(){var index=this.line.geometry.components.length-1;this.line.geometry.removeComponent(this.line.geometry.components[index]);this.removePoint();this.finalize();},dblclick:function(evt){if(!this.freehandMode(evt)){this.finishGeometry();}
+return false;},CLASS_NAME:"OpenLayers.Handler.Path"});OpenLayers.Control.Attribution=OpenLayers.Class(OpenLayers.Control,{separator:", ",template:"${layers}",destroy:function(){this.map.events.un({"removelayer":this.updateAttribution,"addlayer":this.updateAttribution,"changelayer":this.updateAttribution,"changebaselayer":this.updateAttribution,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.map.events.on({'changebaselayer':this.updateAttribution,'changelayer':this.updateAttribution,'addlayer':this.updateAttribution,'removelayer':this.updateAttribution,scope:this});this.updateAttribution();return this.div;},updateAttribution:function(){var attributions=[];if(this.map&&this.map.layers){for(var i=0,len=this.map.layers.length;ithis.nbPoints){this.points.pop();}},end:function(xy){var last,now=new Date().getTime();for(var i=0,l=this.points.length,point;ithis.delay){break;}
+last=point;}
+if(!last){return;}
+var time=new Date().getTime()-last.tick;var dist=Math.sqrt(Math.pow(xy.x-last.xy.x,2)+
+Math.pow(xy.y-last.xy.y,2));var speed=dist/time;if(speed==0||speed0){this.timeoutId=setTimeout(OpenLayers.Function.bind(this.removeTimeout,this),this.interval);}
+this.dragging=true;this.move(evt);this.callback("move",[evt.xy]);if(!this.oldOnselectstart){this.oldOnselectstart=document.onselectstart;document.onselectstart=OpenLayers.Function.False;}
+this.last=evt.xy;}
+return true;},dragend:function(evt){if(this.started){if(this.documentDrag===true&&this.documentEvents){this.adjustXY(evt);this.removeDocumentEvents();}
+var dragged=(this.start!=this.last);this.started=false;this.dragging=false;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.up(evt);this.callback("up",[evt.xy]);if(dragged){this.callback("done",[evt.xy]);}
+document.onselectstart=this.oldOnselectstart;}
+return true;},down:function(evt){},move:function(evt){},up:function(evt){},out:function(evt){},mousedown:function(evt){return this.dragstart(evt);},touchstart:function(evt){if(!this.touch){this.touch=true;this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,mousemove:this.mousemove,click:this.click,scope:this});}
+return this.dragstart(evt);},mousemove:function(evt){return this.dragmove(evt);},touchmove:function(evt){return this.dragmove(evt);},removeTimeout:function(){this.timeoutId=null;if(this.dragging){this.mousemove(this.lastMoveEvt);}},mouseup:function(evt){return this.dragend(evt);},touchend:function(evt){evt.xy=this.last;return this.dragend(evt);},mouseout:function(evt){if(this.started&&OpenLayers.Util.mouseLeft(evt,this.map.viewPortDiv)){if(this.documentDrag===true){this.addDocumentEvents();}else{var dragged=(this.start!=this.last);this.started=false;this.dragging=false;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.out(evt);this.callback("out",[]);if(dragged){this.callback("done",[evt.xy]);}
+if(document.onselectstart){document.onselectstart=this.oldOnselectstart;}}}
+return true;},click:function(evt){return(this.start==this.last);},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragging=false;activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.touch=false;this.started=false;this.dragging=false;this.start=null;this.last=null;deactivated=true;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");}
+return deactivated;},adjustXY:function(evt){var pos=OpenLayers.Util.pagePosition(this.map.viewPortDiv);evt.xy.x-=pos[0];evt.xy.y-=pos[1];},addDocumentEvents:function(){OpenLayers.Element.addClass(document.body,"olDragDown");this.documentEvents=true;OpenLayers.Event.observe(document,"mousemove",this._docMove);OpenLayers.Event.observe(document,"mouseup",this._docUp);},removeDocumentEvents:function(){OpenLayers.Element.removeClass(document.body,"olDragDown");this.documentEvents=false;OpenLayers.Event.stopObserving(document,"mousemove",this._docMove);OpenLayers.Event.stopObserving(document,"mouseup",this._docUp);},CLASS_NAME:"OpenLayers.Handler.Drag"});OpenLayers.Handler.Box=OpenLayers.Class(OpenLayers.Handler,{dragHandler:null,boxDivClassName:'olHandlerBoxZoomBox',boxOffsets:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.dragHandler=new OpenLayers.Handler.Drag(this,{down:this.startBox,move:this.moveBox,out:this.removeBox,up:this.endBox},{keyMask:this.keyMask});},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);if(this.dragHandler){this.dragHandler.destroy();this.dragHandler=null;}},setMap:function(map){OpenLayers.Handler.prototype.setMap.apply(this,arguments);if(this.dragHandler){this.dragHandler.setMap(map);}},startBox:function(xy){this.callback("start",[]);this.zoomBox=OpenLayers.Util.createDiv('zoomBox',{x:-9999,y:-9999});this.zoomBox.className=this.boxDivClassName;this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.viewPortDiv.appendChild(this.zoomBox);OpenLayers.Element.addClass(this.map.viewPortDiv,"olDrawBox");},moveBox:function(xy){var startX=this.dragHandler.start.x;var startY=this.dragHandler.start.y;var deltaX=Math.abs(startX-xy.x);var deltaY=Math.abs(startY-xy.y);var offset=this.getBoxOffsets();this.zoomBox.style.width=(deltaX+offset.width+1)+"px";this.zoomBox.style.height=(deltaY+offset.height+1)+"px";this.zoomBox.style.left=(xy.x5||Math.abs(this.dragHandler.start.y-end.y)>5){var start=this.dragHandler.start;var top=Math.min(start.y,end.y);var bottom=Math.max(start.y,end.y);var left=Math.min(start.x,end.x);var right=Math.max(start.x,end.x);result=new OpenLayers.Bounds(left,bottom,right,top);}else{result=this.dragHandler.start.clone();}
+this.removeBox();this.callback("done",[result]);},removeBox:function(){this.map.viewPortDiv.removeChild(this.zoomBox);this.zoomBox=null;this.boxOffsets=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDrawBox");},activate:function(){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragHandler.activate();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){if(this.dragHandler.deactivate()){if(this.zoomBox){this.removeBox();}}
+return true;}else{return false;}},getBoxOffsets:function(){if(!this.boxOffsets){var testDiv=document.createElement("div");testDiv.style.position="absolute";testDiv.style.border="1px solid black";testDiv.style.width="3px";document.body.appendChild(testDiv);var w3cBoxModel=testDiv.clientWidth==3;document.body.removeChild(testDiv);var left=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-left-width"));var right=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-right-width"));var top=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-top-width"));var bottom=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-bottom-width"));this.boxOffsets={left:left,right:right,top:top,bottom:bottom,width:w3cBoxModel===false?left+right:0,height:w3cBoxModel===false?top+bottom:0};}
+return this.boxOffsets;},CLASS_NAME:"OpenLayers.Handler.Box"});OpenLayers.Control.ZoomBox=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,out:false,keyMask:null,alwaysZoom:false,zoomOnClick:true,draw:function(){this.handler=new OpenLayers.Handler.Box(this,{done:this.zoomBox},{keyMask:this.keyMask});},zoomBox:function(position){if(position instanceof OpenLayers.Bounds){var bounds;if(!this.out){var minXY=this.map.getLonLatFromPixel({x:position.left,y:position.bottom});var maxXY=this.map.getLonLatFromPixel({x:position.right,y:position.top});bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);}else{var pixWidth=Math.abs(position.right-position.left);var pixHeight=Math.abs(position.top-position.bottom);var zoomFactor=Math.min((this.map.size.h/pixHeight),(this.map.size.w/pixWidth));var extent=this.map.getExtent();var center=this.map.getLonLatFromPixel(position.getCenterPixel());var xmin=center.lon-(extent.getWidth()/2)*zoomFactor;var xmax=center.lon+(extent.getWidth()/2)*zoomFactor;var ymin=center.lat-(extent.getHeight()/2)*zoomFactor;var ymax=center.lat+(extent.getHeight()/2)*zoomFactor;bounds=new OpenLayers.Bounds(xmin,ymin,xmax,ymax);}
+var lastZoom=this.map.getZoom();this.map.zoomToExtent(bounds);if(lastZoom==this.map.getZoom()&&this.alwaysZoom==true){this.map.zoomTo(lastZoom+(this.out?-1:1));}}else if(this.zoomOnClick){if(!this.out){this.map.setCenter(this.map.getLonLatFromPixel(position),this.map.getZoom()+1);}else{this.map.setCenter(this.map.getLonLatFromPixel(position),this.map.getZoom()-1);}}},CLASS_NAME:"OpenLayers.Control.ZoomBox"});OpenLayers.Control.DragPan=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,panned:false,interval:1,documentDrag:false,kinetic:null,enableKinetic:false,kineticInterval:10,draw:function(){if(this.enableKinetic){var config={interval:this.kineticInterval};if(typeof this.enableKinetic==="object"){config=OpenLayers.Util.extend(config,this.enableKinetic);}
+this.kinetic=new OpenLayers.Kinetic(config);}
+this.handler=new OpenLayers.Handler.Drag(this,{"move":this.panMap,"done":this.panMapDone,"down":this.panMapStart},{interval:this.interval,documentDrag:this.documentDrag});},panMapStart:function(){if(this.kinetic){this.kinetic.begin();}},panMap:function(xy){if(this.kinetic){this.kinetic.update(xy);}
+this.panned=true;this.map.pan(this.handler.last.x-xy.x,this.handler.last.y-xy.y,{dragging:true,animate:false});},panMapDone:function(xy){if(this.panned){var res=null;if(this.kinetic){res=this.kinetic.end(xy);}
+this.map.pan(this.handler.last.x-xy.x,this.handler.last.y-xy.y,{dragging:!!res,animate:false});if(res){var self=this;this.kinetic.move(res,function(x,y,end){self.map.pan(x,y,{dragging:!end,animate:false});});}
+this.panned=false;}},CLASS_NAME:"OpenLayers.Control.DragPan"});OpenLayers.Handler.Click=OpenLayers.Class(OpenLayers.Handler,{delay:300,single:true,'double':false,pixelTolerance:0,dblclickTolerance:13,stopSingle:false,stopDouble:false,timerId:null,touch:false,down:null,last:null,first:null,rightclickTimerId:null,touchstart:function(evt){if(!this.touch){this.unregisterMouseListeners();this.touch=true;}
+this.down=this.getEventInfo(evt);this.last=this.getEventInfo(evt);return true;},touchmove:function(evt){this.last=this.getEventInfo(evt);return true;},touchend:function(evt){if(this.down){evt.xy=this.last.xy;evt.lastTouches=this.last.touches;this.handleSingle(evt);this.down=null;}
+return true;},unregisterMouseListeners:function(){this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,click:this.click,dblclick:this.dblclick,scope:this});},mousedown:function(evt){this.down=this.getEventInfo(evt);this.last=this.getEventInfo(evt);return true;},mouseup:function(evt){var propagate=true;if(this.checkModifiers(evt)&&this.control.handleRightClicks&&OpenLayers.Event.isRightClick(evt)){propagate=this.rightclick(evt);}
+return propagate;},rightclick:function(evt){if(this.passesTolerance(evt)){if(this.rightclickTimerId!=null){this.clearTimer();this.callback('dblrightclick',[evt]);return!this.stopDouble;}else{var clickEvent=this['double']?OpenLayers.Util.extend({},evt):this.callback('rightclick',[evt]);var delayedRightCall=OpenLayers.Function.bind(this.delayedRightCall,this,clickEvent);this.rightclickTimerId=window.setTimeout(delayedRightCall,this.delay);}}
+return!this.stopSingle;},delayedRightCall:function(evt){this.rightclickTimerId=null;if(evt){this.callback('rightclick',[evt]);}},click:function(evt){if(!this.last){this.last=this.getEventInfo(evt);}
+this.handleSingle(evt);return!this.stopSingle;},dblclick:function(evt){this.handleDouble(evt);return!this.stopDouble;},handleDouble:function(evt){if(this.passesDblclickTolerance(evt)){if(this["double"]){this.callback("dblclick",[evt]);}
+this.clearTimer();}},handleSingle:function(evt){if(this.passesTolerance(evt)){if(this.timerId!=null){if(this.last.touches&&this.last.touches.length===1){if(this["double"]){OpenLayers.Event.stop(evt);}
+this.handleDouble(evt);}
+if(!this.last.touches||this.last.touches.length!==2){this.clearTimer();}}else{this.first=this.getEventInfo(evt);var clickEvent=this.single?OpenLayers.Util.extend({},evt):null;this.queuePotentialClick(clickEvent);}}},queuePotentialClick:function(evt){this.timerId=window.setTimeout(OpenLayers.Function.bind(this.delayedCall,this,evt),this.delay);},passesTolerance:function(evt){var passes=true;if(this.pixelTolerance!=null&&this.down&&this.down.xy){passes=this.pixelTolerance>=this.down.xy.distanceTo(evt.xy);if(passes&&this.touch&&this.down.touches.length===this.last.touches.length){for(var i=0,ii=this.down.touches.length;ithis.pixelTolerance){passes=false;break;}}}}
+return passes;},getTouchDistance:function(from,to){return Math.sqrt(Math.pow(from.clientX-to.clientX,2)+
+Math.pow(from.clientY-to.clientY,2));},passesDblclickTolerance:function(evt){var passes=true;if(this.down&&this.first){passes=this.down.xy.distanceTo(this.first.xy)<=this.dblclickTolerance;}
+return passes;},clearTimer:function(){if(this.timerId!=null){window.clearTimeout(this.timerId);this.timerId=null;}
+if(this.rightclickTimerId!=null){window.clearTimeout(this.rightclickTimerId);this.rightclickTimerId=null;}},delayedCall:function(evt){this.timerId=null;if(evt){this.callback("click",[evt]);}},getEventInfo:function(evt){var touches;if(evt.touches){var len=evt.touches.length;touches=new Array(len);var touch;for(var i=0;i=1.3&&!params.EXCEPTIONS){params.EXCEPTIONS="INIMAGE";}
+newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);OpenLayers.Util.applyDefaults(this.params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));if(!this.noMagic&&this.params.TRANSPARENT&&this.params.TRANSPARENT.toString().toLowerCase()=="true"){if((options==null)||(!options.isBaseLayer)){this.isBaseLayer=false;}
+if(this.params.FORMAT=="image/jpeg"){this.params.FORMAT=OpenLayers.Util.alphaHack()?"image/gif":"image/png";}}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WMS(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},reverseAxisOrder:function(){var projCode=this.projection.getCode();return parseFloat(this.params.VERSION)>=1.3&&!!(this.yx[projCode]||OpenLayers.Projection.defaults[projCode].yx);},getURL:function(bounds){bounds=this.adjustBounds(bounds);var imageSize=this.getImageSize();var newParams={};var reverseAxisOrder=this.reverseAxisOrder();newParams.BBOX=this.encodeBBOX?bounds.toBBOX(null,reverseAxisOrder):bounds.toArray(reverseAxisOrder);newParams.WIDTH=imageSize.w;newParams.HEIGHT=imageSize.h;var requestString=this.getFullRequestString(newParams);return requestString;},mergeNewParams:function(newParams){var upperParams=OpenLayers.Util.upperCaseObject(newParams);var newArguments=[upperParams];return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,newArguments);},getFullRequestString:function(newParams,altUrl){var mapProjection=this.map.getProjectionObject();var projectionCode=this.projection&&this.projection.equals(mapProjection)?this.projection.getCode():mapProjection.getCode();var value=(projectionCode=="none")?null:projectionCode;if(parseFloat(this.params.VERSION)>=1.3){this.params.CRS=value;}else{this.params.SRS=value;}
+if(typeof this.params.TRANSPARENT=="boolean"){newParams.TRANSPARENT=this.params.TRANSPARENT?"TRUE":"FALSE";}
+return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,arguments);},CLASS_NAME:"OpenLayers.Layer.WMS"});OpenLayers.Renderer.SVG=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"http://www.w3.org/2000/svg",xlinkns:"http://www.w3.org/1999/xlink",MAX_PIXEL:15000,translationParameters:null,symbolMetrics:null,initialize:function(containerID){if(!this.supported()){return;}
+OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);this.translationParameters={x:0,y:0};this.symbolMetrics={};},supported:function(){var svgFeature="http://www.w3.org/TR/SVG11/feature#";return(document.implementation&&(document.implementation.hasFeature("org.w3c.svg","1.0")||document.implementation.hasFeature(svgFeature+"SVG","1.1")||document.implementation.hasFeature(svgFeature+"BasicStructure","1.1")));},inValidRange:function(x,y,xyOnly){var left=x+(xyOnly?0:this.translationParameters.x);var top=y+(xyOnly?0:this.translationParameters.y);return(left>=-this.MAX_PIXEL&&left<=this.MAX_PIXEL&&top>=-this.MAX_PIXEL&&top<=this.MAX_PIXEL);},setExtent:function(extent,resolutionChanged){var coordSysUnchanged=OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution(),left=-extent.left/resolution,top=extent.top/resolution;if(resolutionChanged){this.left=left;this.top=top;var extentString="0 0 "+this.size.w+" "+this.size.h;this.rendererRoot.setAttributeNS(null,"viewBox",extentString);this.translate(this.xOffset,0);return true;}else{var inRange=this.translate(left-this.left+this.xOffset,top-this.top);if(!inRange){this.setExtent(extent,true);}
+return coordSysUnchanged&&inRange;}},translate:function(x,y){if(!this.inValidRange(x,y,true)){return false;}else{var transformString="";if(x||y){transformString="translate("+x+","+y+")";}
+this.root.setAttributeNS(null,"transform",transformString);this.translationParameters={x:x,y:y};return true;}},setSize:function(size){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);this.rendererRoot.setAttributeNS(null,"width",this.size.w);this.rendererRoot.setAttributeNS(null,"height",this.size.h);},getNodeType:function(geometry,style){var nodeType=null;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.externalGraphic){nodeType="image";}else if(this.isComplexSymbol(style.graphicName)){nodeType="svg";}else{nodeType="circle";}
+break;case"OpenLayers.Geometry.Rectangle":nodeType="rect";break;case"OpenLayers.Geometry.LineString":nodeType="polyline";break;case"OpenLayers.Geometry.LinearRing":nodeType="polygon";break;case"OpenLayers.Geometry.Polygon":case"OpenLayers.Geometry.Curve":nodeType="path";break;default:break;}
+return nodeType;},setStyle:function(node,style,options){style=style||node._style;options=options||node._options;var title=style.title||style.graphicTitle;if(title){node.setAttributeNS(null,"title",title);var titleNode=node.getElementsByTagName("title");if(titleNode.length>0){titleNode[0].firstChild.textContent=title;}else{var label=this.nodeFactory(null,"title");label.textContent=title;node.appendChild(label);}}
+var r=parseFloat(node.getAttributeNS(null,"r"));var widthFactor=1;var pos;if(node._geometryClass=="OpenLayers.Geometry.Point"&&r){node.style.visibility="";if(style.graphic===false){node.style.visibility="hidden";}else if(style.externalGraphic){pos=this.getPosition(node);if(style.graphicWidth&&style.graphicHeight){node.setAttributeNS(null,"preserveAspectRatio","none");}
+var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);var opacity=style.graphicOpacity||style.fillOpacity;node.setAttributeNS(null,"x",(pos.x+xOffset).toFixed());node.setAttributeNS(null,"y",(pos.y+yOffset).toFixed());node.setAttributeNS(null,"width",width);node.setAttributeNS(null,"height",height);node.setAttributeNS(this.xlinkns,"href",style.externalGraphic);node.setAttributeNS(null,"style","opacity: "+opacity);node.onclick=OpenLayers.Event.preventDefault;}else if(this.isComplexSymbol(style.graphicName)){var offset=style.pointRadius*3;var size=offset*2;var src=this.importSymbol(style.graphicName);pos=this.getPosition(node);widthFactor=this.symbolMetrics[src.id][0]*3/size;var parent=node.parentNode;var nextSibling=node.nextSibling;if(parent){parent.removeChild(node);}
+node.firstChild&&node.removeChild(node.firstChild);node.appendChild(src.firstChild.cloneNode(true));node.setAttributeNS(null,"viewBox",src.getAttributeNS(null,"viewBox"));node.setAttributeNS(null,"width",size);node.setAttributeNS(null,"height",size);node.setAttributeNS(null,"x",pos.x-offset);node.setAttributeNS(null,"y",pos.y-offset);if(nextSibling){parent.insertBefore(node,nextSibling);}else if(parent){parent.appendChild(node);}}else{node.setAttributeNS(null,"r",style.pointRadius);}
+var rotation=style.rotation;if((rotation!==undefined||node._rotation!==undefined)&&pos){node._rotation=rotation;rotation|=0;if(node.nodeName!=="svg"){node.setAttributeNS(null,"transform","rotate("+rotation+" "+pos.x+" "+
+pos.y+")");}else{var metrics=this.symbolMetrics[src.id];node.firstChild.setAttributeNS(null,"transform","rotate("
++rotation+" "
++metrics[1]+" "
++metrics[2]+")");}}}
+if(options.isFilled){node.setAttributeNS(null,"fill",style.fillColor);node.setAttributeNS(null,"fill-opacity",style.fillOpacity);}else{node.setAttributeNS(null,"fill","none");}
+if(options.isStroked){node.setAttributeNS(null,"stroke",style.strokeColor);node.setAttributeNS(null,"stroke-opacity",style.strokeOpacity);node.setAttributeNS(null,"stroke-width",style.strokeWidth*widthFactor);node.setAttributeNS(null,"stroke-linecap",style.strokeLinecap||"round");node.setAttributeNS(null,"stroke-linejoin","round");style.strokeDashstyle&&node.setAttributeNS(null,"stroke-dasharray",this.dashStyle(style,widthFactor));}else{node.setAttributeNS(null,"stroke","none");}
+if(style.pointerEvents){node.setAttributeNS(null,"pointer-events",style.pointerEvents);}
+if(style.cursor!=null){node.setAttributeNS(null,"cursor",style.cursor);}
+return node;},dashStyle:function(style,widthFactor){var w=style.strokeWidth*widthFactor;var str=style.strokeDashstyle;switch(str){case'solid':return'none';case'dot':return[1,4*w].join();case'dash':return[4*w,4*w].join();case'dashdot':return[4*w,4*w,1,4*w].join();case'longdash':return[8*w,4*w].join();case'longdashdot':return[8*w,4*w,1,4*w].join();default:return OpenLayers.String.trim(str).replace(/\s+/g,",");}},createNode:function(type,id){var node=document.createElementNS(this.xmlns,type);if(id){node.setAttributeNS(null,"id",id);}
+return node;},nodeTypeCompare:function(node,type){return(type==node.nodeName);},createRenderRoot:function(){var svg=this.nodeFactory(this.container.id+"_svgRoot","svg");svg.style.display="block";return svg;},createRoot:function(suffix){return this.nodeFactory(this.container.id+suffix,"g");},createDefs:function(){var defs=this.nodeFactory(this.container.id+"_defs","defs");this.rendererRoot.appendChild(defs);return defs;},drawPoint:function(node,geometry){return this.drawCircle(node,geometry,1);},drawCircle:function(node,geometry,radius){var resolution=this.getResolution();var x=((geometry.x-this.featureDx)/resolution+this.left);var y=(this.top-geometry.y/resolution);if(this.inValidRange(x,y)){node.setAttributeNS(null,"cx",x);node.setAttributeNS(null,"cy",y);node.setAttributeNS(null,"r",radius);return node;}else{return false;}},drawLineString:function(node,geometry){var componentsResult=this.getComponentsString(geometry.components);if(componentsResult.path){node.setAttributeNS(null,"points",componentsResult.path);return(componentsResult.complete?node:null);}else{return false;}},drawLinearRing:function(node,geometry){var componentsResult=this.getComponentsString(geometry.components);if(componentsResult.path){node.setAttributeNS(null,"points",componentsResult.path);return(componentsResult.complete?node:null);}else{return false;}},drawPolygon:function(node,geometry){var d="";var draw=true;var complete=true;var linearRingResult,path;for(var j=0,len=geometry.components.length;jnumRows){label.removeChild(label.lastChild);}
+for(var i=0;i0){if(this.getShortString(components[i-1])){strings.push(this.clipLine(components[i],components[i-1]));}}
+if(imaxX){k=(y2-y1)/(x2-x1);x2=x2<0?-maxX:maxX;y2=y1+(x2-x1)*k;}
+if(y2<-maxY||y2>maxY){k=(x2-x1)/(y2-y1);y2=y2<0?-maxY:maxY;x2=x1+(y2-y1)*k;}
+return x2+","+y2;},getShortString:function(point){var resolution=this.getResolution();var x=((point.x-this.featureDx)/resolution+this.left);var y=(this.top-point.y/resolution);if(this.inValidRange(x,y)){return x+","+y;}else{return false;}},getPosition:function(node){return({x:parseFloat(node.getAttributeNS(null,"cx")),y:parseFloat(node.getAttributeNS(null,"cy"))});},importSymbol:function(graphicName){if(!this.defs){this.defs=this.createDefs();}
+var id=this.container.id+"-"+graphicName;var existing=document.getElementById(id);if(existing!=null){return existing;}
+var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');}
+var symbolNode=this.nodeFactory(id,"symbol");var node=this.nodeFactory(null,"polygon");symbolNode.appendChild(node);var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var points=[];var x,y;for(var i=0;i1.0){this.setGeometryName(null);}},destroy:function(){if(this.options&&!this.options.format){this.format.destroy();}
+this.format=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options||{});var response=new OpenLayers.Protocol.Response({requestType:"read"});var data=OpenLayers.Format.XML.prototype.write.apply(this.format,[this.format.writeNode("wfs:GetFeature",options)]);response.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,response,options),params:options.params,headers:options.headers,data:data});return response;},setFeatureType:function(featureType){this.featureType=featureType;this.format.featureType=featureType;},setGeometryName:function(geometryName){this.geometryName=geometryName;this.format.geometryName=geometryName;},handleRead:function(response,options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options);if(options.callback){var request=response.priv;if(request.status>=200&&request.status<300){var result=this.parseResponse(request,options.readOptions);if(result&&result.success!==false){if(options.readOptions&&options.readOptions.output=="object"){OpenLayers.Util.extend(response,result);}else{response.features=result;}
+response.code=OpenLayers.Protocol.Response.SUCCESS;}else{response.code=OpenLayers.Protocol.Response.FAILURE;response.error=result;}}else{response.code=OpenLayers.Protocol.Response.FAILURE;}
+options.callback.call(options.scope,response);}},parseResponse:function(request,options){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+if(!doc||doc.length<=0){return null;}
+var result=(this.readFormat!==null)?this.readFormat.read(doc):this.format.read(doc,options);if(!this.featureNS){var format=this.readFormat||this.format;this.featureNS=format.featureNS;format.autoConfig=false;if(!this.geometryName){this.setGeometryName(format.geometryName);}}
+return result;},commit:function(features,options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options);var response=new OpenLayers.Protocol.Response({requestType:"commit",reqFeatures:features});response.priv=OpenLayers.Request.POST({url:options.url,headers:options.headers,data:this.format.write(features,options),callback:this.createCallback(this.handleCommit,response,options)});return response;},handleCommit:function(response,options){if(options.callback){var request=response.priv;var data=request.responseXML;if(!data||!data.documentElement){data=request.responseText;}
+var obj=this.format.read(data)||{};response.insertIds=obj.insertIds||[];if(obj.success){response.code=OpenLayers.Protocol.Response.SUCCESS;}else{response.code=OpenLayers.Protocol.Response.FAILURE;response.error=obj;}
+options.callback.call(options.scope,response);}},filterDelete:function(filter,options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options);var response=new OpenLayers.Protocol.Response({requestType:"commit"});var root=this.format.createElementNSPlus("wfs:Transaction",{attributes:{service:"WFS",version:this.version}});var deleteNode=this.format.createElementNSPlus("wfs:Delete",{attributes:{typeName:(options.featureNS?this.featurePrefix+":":"")+
+options.featureType}});if(options.featureNS){deleteNode.setAttribute("xmlns:"+this.featurePrefix,options.featureNS);}
+var filterNode=this.format.writeNode("ogc:Filter",filter);deleteNode.appendChild(filterNode);root.appendChild(deleteNode);var data=OpenLayers.Format.XML.prototype.write.apply(this.format,[root]);return OpenLayers.Request.POST({url:this.url,callback:options.callback||function(){},data:data});},abort:function(response){if(response){response.priv.abort();}},CLASS_NAME:"OpenLayers.Protocol.WFS.v1"});OpenLayers.ProxyHost="";if(!OpenLayers.Request){OpenLayers.Request={};}
+OpenLayers.Util.extend(OpenLayers.Request,{DEFAULT_CONFIG:{method:"GET",url:window.location.href,async:true,user:undefined,password:undefined,params:null,proxy:OpenLayers.ProxyHost,headers:{},data:null,callback:function(){},success:null,failure:null,scope:null},URL_SPLIT_REGEX:/([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/,events:new OpenLayers.Events(this),makeSameOrigin:function(url,proxy){var sameOrigin=url.indexOf("http")!==0;var urlParts=!sameOrigin&&url.match(this.URL_SPLIT_REGEX);if(urlParts){var location=window.location;sameOrigin=urlParts[1]==location.protocol&&urlParts[3]==location.hostname;var uPort=urlParts[4],lPort=location.port;if(uPort!=80&&uPort!=""||lPort!="80"&&lPort!=""){sameOrigin=sameOrigin&&uPort==lPort;}}
+if(!sameOrigin){if(proxy){if(typeof proxy=="function"){url=proxy(url);}else{url=proxy+encodeURIComponent(url);}}else{OpenLayers.Console.warn(OpenLayers.i18n("proxyNeeded"),{url:url});}}
+return url;},issue:function(config){var defaultConfig=OpenLayers.Util.extend(this.DEFAULT_CONFIG,{proxy:OpenLayers.ProxyHost});config=OpenLayers.Util.applyDefaults(config,defaultConfig);var customRequestedWithHeader=false,headerKey;for(headerKey in config.headers){if(config.headers.hasOwnProperty(headerKey)){if(headerKey.toLowerCase()==='x-requested-with'){customRequestedWithHeader=true;}}}
+if(customRequestedWithHeader===false){config.headers['X-Requested-With']='XMLHttpRequest';}
+var request=new OpenLayers.Request.XMLHttpRequest();var url=OpenLayers.Util.urlAppend(config.url,OpenLayers.Util.getParameterString(config.params||{}));url=OpenLayers.Request.makeSameOrigin(url,config.proxy);request.open(config.method,url,config.async,config.user,config.password);for(var header in config.headers){request.setRequestHeader(header,config.headers[header]);}
+var events=this.events;var self=this;request.onreadystatechange=function(){if(request.readyState==OpenLayers.Request.XMLHttpRequest.DONE){var proceed=events.triggerEvent("complete",{request:request,config:config,requestUrl:url});if(proceed!==false){self.runCallbacks({request:request,config:config,requestUrl:url});}}};if(config.async===false){request.send(config.data);}else{window.setTimeout(function(){if(request.readyState!==0){request.send(config.data);}},0);}
+return request;},runCallbacks:function(options){var request=options.request;var config=options.config;var complete=(config.scope)?OpenLayers.Function.bind(config.callback,config.scope):config.callback;var success;if(config.success){success=(config.scope)?OpenLayers.Function.bind(config.success,config.scope):config.success;}
+var failure;if(config.failure){failure=(config.scope)?OpenLayers.Function.bind(config.failure,config.scope):config.failure;}
+if(OpenLayers.Util.createUrlObject(config.url).protocol=="file:"&&request.responseText){request.status=200;}
+complete(request);if(!request.status||(request.status>=200&&request.status<300)){this.events.triggerEvent("success",options);if(success){success(request);}}
+if(request.status&&(request.status<200||request.status>=300)){this.events.triggerEvent("failure",options);if(failure){failure(request);}}},GET:function(config){config=OpenLayers.Util.extend(config,{method:"GET"});return OpenLayers.Request.issue(config);},POST:function(config){config=OpenLayers.Util.extend(config,{method:"POST"});config.headers=config.headers?config.headers:{};if(!("CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(config.headers))){config.headers["Content-Type"]="application/xml";}
+return OpenLayers.Request.issue(config);},PUT:function(config){config=OpenLayers.Util.extend(config,{method:"PUT"});config.headers=config.headers?config.headers:{};if(!("CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(config.headers))){config.headers["Content-Type"]="application/xml";}
+return OpenLayers.Request.issue(config);},DELETE:function(config){config=OpenLayers.Util.extend(config,{method:"DELETE"});return OpenLayers.Request.issue(config);},HEAD:function(config){config=OpenLayers.Util.extend(config,{method:"HEAD"});return OpenLayers.Request.issue(config);},OPTIONS:function(config){config=OpenLayers.Util.extend(config,{method:"OPTIONS"});return OpenLayers.Request.issue(config);}});(function(){var oXMLHttpRequest=window.XMLHttpRequest;var bGecko=!!window.controllers,bIE=window.document.all&&!window.opera,bIE7=bIE&&window.navigator.userAgent.match(/MSIE 7.0/);function fXMLHttpRequest(){this._object=oXMLHttpRequest&&!bIE7?new oXMLHttpRequest:new window.ActiveXObject("Microsoft.XMLHTTP");this._listeners=[];};function cXMLHttpRequest(){return new fXMLHttpRequest;};cXMLHttpRequest.prototype=fXMLHttpRequest.prototype;if(bGecko&&oXMLHttpRequest.wrapped)
+cXMLHttpRequest.wrapped=oXMLHttpRequest.wrapped;cXMLHttpRequest.UNSENT=0;cXMLHttpRequest.OPENED=1;cXMLHttpRequest.HEADERS_RECEIVED=2;cXMLHttpRequest.LOADING=3;cXMLHttpRequest.DONE=4;cXMLHttpRequest.prototype.readyState=cXMLHttpRequest.UNSENT;cXMLHttpRequest.prototype.responseText='';cXMLHttpRequest.prototype.responseXML=null;cXMLHttpRequest.prototype.status=0;cXMLHttpRequest.prototype.statusText='';cXMLHttpRequest.prototype.priority="NORMAL";cXMLHttpRequest.prototype.onreadystatechange=null;cXMLHttpRequest.onreadystatechange=null;cXMLHttpRequest.onopen=null;cXMLHttpRequest.onsend=null;cXMLHttpRequest.onabort=null;cXMLHttpRequest.prototype.open=function(sMethod,sUrl,bAsync,sUser,sPassword){delete this._headers;if(arguments.length<3)
+bAsync=true;this._async=bAsync;var oRequest=this,nState=this.readyState,fOnUnload;if(bIE&&bAsync){fOnUnload=function(){if(nState!=cXMLHttpRequest.DONE){fCleanTransport(oRequest);oRequest.abort();}};window.attachEvent("onunload",fOnUnload);}
+if(cXMLHttpRequest.onopen)
+cXMLHttpRequest.onopen.apply(this,arguments);if(arguments.length>4)
+this._object.open(sMethod,sUrl,bAsync,sUser,sPassword);else
+if(arguments.length>3)
+this._object.open(sMethod,sUrl,bAsync,sUser);else
+this._object.open(sMethod,sUrl,bAsync);this.readyState=cXMLHttpRequest.OPENED;fReadyStateChange(this);this._object.onreadystatechange=function(){if(bGecko&&!bAsync)
+return;oRequest.readyState=oRequest._object.readyState;fSynchronizeValues(oRequest);if(oRequest._aborted){oRequest.readyState=cXMLHttpRequest.UNSENT;return;}
+if(oRequest.readyState==cXMLHttpRequest.DONE){delete oRequest._data;fCleanTransport(oRequest);if(bIE&&bAsync)
+window.detachEvent("onunload",fOnUnload);}
+if(nState!=oRequest.readyState)
+fReadyStateChange(oRequest);nState=oRequest.readyState;}};function fXMLHttpRequest_send(oRequest){oRequest._object.send(oRequest._data);if(bGecko&&!oRequest._async){oRequest.readyState=cXMLHttpRequest.OPENED;fSynchronizeValues(oRequest);while(oRequest.readyStatecXMLHttpRequest.UNSENT)
+this._aborted=true;this._object.abort();fCleanTransport(this);this.readyState=cXMLHttpRequest.UNSENT;delete this._data;};cXMLHttpRequest.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders();};cXMLHttpRequest.prototype.getResponseHeader=function(sName){return this._object.getResponseHeader(sName);};cXMLHttpRequest.prototype.setRequestHeader=function(sName,sValue){if(!this._headers)
+this._headers={};this._headers[sName]=sValue;return this._object.setRequestHeader(sName,sValue);};cXMLHttpRequest.prototype.addEventListener=function(sName,fHandler,bUseCapture){for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
+if(oListener[0]==sName&&oListener[1]==fHandler&&oListener[2]==bUseCapture)
+return;this._listeners.push([sName,fHandler,bUseCapture]);};cXMLHttpRequest.prototype.removeEventListener=function(sName,fHandler,bUseCapture){for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
+if(oListener[0]==sName&&oListener[1]==fHandler&&oListener[2]==bUseCapture)
+break;if(oListener)
+this._listeners.splice(nIndex,1);};cXMLHttpRequest.prototype.dispatchEvent=function(oEvent){var oEventPseudo={'type':oEvent.type,'target':this,'currentTarget':this,'eventPhase':2,'bubbles':oEvent.bubbles,'cancelable':oEvent.cancelable,'timeStamp':oEvent.timeStamp,'stopPropagation':function(){},'preventDefault':function(){},'initEvent':function(){}};if(oEventPseudo.type=="readystatechange"&&this.onreadystatechange)
+(this.onreadystatechange.handleEvent||this.onreadystatechange).apply(this,[oEventPseudo]);for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
+if(oListener[0]==oEventPseudo.type&&!oListener[2])
+(oListener[1].handleEvent||oListener[1]).apply(this,[oEventPseudo]);};cXMLHttpRequest.prototype.toString=function(){return'['+"object"+' '+"XMLHttpRequest"+']';};cXMLHttpRequest.toString=function(){return'['+"XMLHttpRequest"+']';};function fReadyStateChange(oRequest){if(cXMLHttpRequest.onreadystatechange)
+cXMLHttpRequest.onreadystatechange.apply(oRequest);oRequest.dispatchEvent({'type':"readystatechange",'bubbles':false,'cancelable':false,'timeStamp':new Date+0});};function fGetDocument(oRequest){var oDocument=oRequest.responseXML,sResponse=oRequest.responseText;if(bIE&&sResponse&&oDocument&&!oDocument.documentElement&&oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)){oDocument=new window.ActiveXObject("Microsoft.XMLDOM");oDocument.async=false;oDocument.validateOnParse=false;oDocument.loadXML(sResponse);}
+if(oDocument)
+if((bIE&&oDocument.parseError!=0)||!oDocument.documentElement||(oDocument.documentElement&&oDocument.documentElement.tagName=="parsererror"))
+return null;return oDocument;};function fSynchronizeValues(oRequest){try{oRequest.responseText=oRequest._object.responseText;}catch(e){}
+try{oRequest.responseXML=fGetDocument(oRequest._object);}catch(e){}
+try{oRequest.status=oRequest._object.status;}catch(e){}
+try{oRequest.statusText=oRequest._object.statusText;}catch(e){}};function fCleanTransport(oRequest){oRequest._object.onreadystatechange=new window.Function;};if(!window.Function.prototype.apply){window.Function.prototype.apply=function(oRequest,oArguments){if(!oArguments)
+oArguments=[];oRequest.__func=this;oRequest.__func(oArguments[0],oArguments[1],oArguments[2],oArguments[3],oArguments[4]);delete oRequest.__func;};};if(!OpenLayers.Request){OpenLayers.Request={};}
+OpenLayers.Request.XMLHttpRequest=cXMLHttpRequest;})();OpenLayers.Raster={};OpenLayers.Raster.Grid=OpenLayers.Class({EVENT_TYPES:["update"],initialize:function(config){OpenLayers.Util.extend(this,config);this.events=new OpenLayers.Events(this,null,this.EVENT_TYPES);},getValue:function(col,row){throw new Error("getValue must be defined")},numCols:function(){throw new Error("numCols must be defined")},numRows:function(){throw new Error("numRows must be defined")},forEach:function(fn){var cols=this.numCols();var rows=this.numRows();for(var j=0;j=this.getCount()){throw new Error("Bad grid index.")}
+var composite=this;return new OpenLayers.Raster.Grid({numCols:function(){return composite.numCols();},numRows:function(){return composite.numRows();},getValue:function(col,row){return composite.getValue(col,row)[index];}});},CLASS_NAME:"OpenLayers.Raster.Composite"};})());OpenLayers.Raster.Composite.fromLayer=function(layer,options){var composite;if(layer instanceof OpenLayers.Layer.Grid){composite=OpenLayers.Raster.Composite.fromGridLayer(layer);}else if(layer instanceof OpenLayers.Layer.Vector){composite=OpenLayers.Raster.Composite.fromVectorLayer(layer,options);}else{throw new Error("Only Grid or Vector type layers can be used to create a raster");}
+return composite;};OpenLayers.Raster.Composite.fromVectorLayer=function(layer,options){var mapping=options&&options.mapping||function(feature){return[255,255,255,255]};var container=document.createElement("div");var renderer=new OpenLayers.Renderer.Canvas(container,{hitDetection:false});var canvas=renderer.root;var context=renderer.canvas;var composite=new OpenLayers.Raster.Composite({numCols:function(){return canvas.width;},numRows:function(){return canvas.height;},getCount:function(){return 4;},getValue:function(col,row){var pixelArray=getPixelArray();var cols=canvas.width;var offset=4*(col+(row*cols));return Array.prototype.slice.apply(pixelArray,[offset,offset+4]);},toDataURL:function(){return canvas.toDataURL.apply(canvas,arguments);}});var cache={};function getPixelArray(){if(!cache.pixelArray){var imageData=context.getImageData(0,0,canvas.width,canvas.height);cache.pixelArray=imageData.data;}
+return cache.pixelArray;}
+function hex(value){value=Math.max(0,Math.min(255,value));return(3840+value).toString(16).substring(1);}
+var style=new OpenLayers.Style({stroke:false,fillColor:"${getColor}",fillOpacity:"${getOpacity}"},{context:{getColor:function(feature){var rgba=mapping(feature);return"#"+
+hex(rgba[0])+
+hex(rgba[1])+
+hex(rgba[2]);},getOpacity:function(feature){var rgba=mapping(feature);return rgba[3]/255;}}});var clone=new OpenLayers.Layer.Vector(null,{styleMap:new OpenLayers.StyleMap(style),renderer:renderer});function triggerUpdate(){cache={};window.setTimeout(function(){composite.events.triggerEvent("update");},0);}
+function addFeatures(event){var features=event.features;clone.addFeatures(features,{silent:true});for(var i=0,ii=features.length;icanvas.width?cornerPixel.x+tileSize.w-canvas.width:0;var overwritey=cornerPixel.y+tileSize.h>canvas.height?cornerPixel.y+tileSize.h-canvas.height:0;if((underwritex+overwritex)0?0:cornerPixel.x;var dy=underwritey>0?0:cornerPixel.y;var dw=tileSize.w-underwritex-overwritex;var dh=tileSize.h-underwritey-overwritey;context.drawImage(img,sx,sy,sw,sh,dx,dy,dw,dh);}}}}
+composite.getValue=function(col,row){var width=canvas.width;var data8=context.getImageData(0,0,width,canvas.height).data;var accessor;var pixel=[0,0,0,0];accessor=function(col,row){var offset=(col+(row*width))<<2;pixel[3]=data8[offset+3];pixel[2]=data8[offset+2];pixel[1]=data8[offset+1];pixel[0]=data8[offset];return pixel;}
+composite.getValue=accessor;return accessor(col,row);}
+composite.events.triggerEvent("update");}}
+if(layer.map){layer.map.events.register("moveend",null,deferredUpdate);}else{layer.events.register("added",null,function(){layer.map.events.register("moveend",null,deferredUpdate);});}
+layer.events.register("loadend",null,deferredUpdate);return composite;};OpenLayers.Raster.Operation=(function(){var Grid=OpenLayers.Raster.Grid;var Composite=OpenLayers.Raster.Composite;return{create:function(fn){var op=function(){var args=Array.prototype.slice.call(arguments);var len=args.length;if(len==1){var operand=args[0];if(operand instanceof Grid){var result=new Grid({numCols:function(){return operand.numCols();},numRows:function(){return operand.numRows();},getValue:function(col,row){return fn(operand.getValue(col,row));},getCount:function(){return 1;}});operand.events.register("update",null,function(){result.events.triggerEvent("update");});return result;}else{throw new Error("Operation must be called with at least one grid.");}}else{function getFirstGrid(){var grid;for(var i=0;i1)?Composite:Grid;var grid=new Constructor({numCols:function(){return getFirstGrid().numCols();},numRows:function(){return getFirstGrid().numRows();},getValue:function(col,row){var values=new Array(len);var arg;for(var i=0;i=0;--i){candidate=features[i].geometry;if((candidate instanceof OpenLayers.Geometry.Polygon||candidate instanceof OpenLayers.Geometry.MultiPolygon)&&candidate.intersects(geometry)){polygon=features[i];this.control.layer.removeFeatures([polygon],{silent:true});this.control.layer.events.registerPriority("sketchcomplete",this,this.finalizeInteriorRing);this.control.layer.events.registerPriority("sketchmodified",this,this.enforceTopology);polygon.geometry.addComponent(this.line.geometry);this.polygon=polygon;this.drawingHole=true;break;}}}
+OpenLayers.Handler.Path.prototype.addPoint.apply(this,arguments);},getCurrentPointIndex:function(){return this.line.geometry.components.length-2;},enforceTopology:function(event){var point=event.vertex;var components=this.line.geometry.components;if(!this.polygon.geometry.intersects(point)){var last=components[components.length-3];point.x=last.x;point.y=last.y;}},finishGeometry:function(){var index=this.line.geometry.components.length-2;this.line.geometry.removeComponent(this.line.geometry.components[index]);this.removePoint();this.finalize();},finalizeInteriorRing:function(){var ring=this.line.geometry;var modified=(ring.getArea()!==0);if(modified){var rings=this.polygon.geometry.components;for(var i=rings.length-2;i>=0;--i){if(ring.intersects(rings[i])){modified=false;break;}}
+if(modified){var target;outer:for(var i=rings.length-2;i>0;--i){var points=rings[i].components;for(var j=0,jj=points.length;j= 0x0001) && (c <= 0x007F)) {
+ out += str.charAt(i);
+ } else if (c > 0x07FF) {
+ out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
+ out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
+ out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
+ } else {
+ out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
+ out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
+ }
+ }
+ return out;
+ }
+ // takes a string imgData containing the raw bytes of
+ // a jpeg image and returns [width, height]
+ // Algorithm from: http://www.64lines.com/jpeg-width-height
+ , getJpegSize = function(imgData) {
+ var width, height;
+ // Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
+ if (!imgData.charCodeAt(0) === 0xff ||
+ !imgData.charCodeAt(1) === 0xd8 ||
+ !imgData.charCodeAt(2) === 0xff ||
+ !imgData.charCodeAt(3) === 0xe0 ||
+ !imgData.charCodeAt(6) === 'J'.charCodeAt(0) ||
+ !imgData.charCodeAt(7) === 'F'.charCodeAt(0) ||
+ !imgData.charCodeAt(8) === 'I'.charCodeAt(0) ||
+ !imgData.charCodeAt(9) === 'F'.charCodeAt(0) ||
+ !imgData.charCodeAt(10) === 0x00) {
+ throw new Error('getJpegSize requires a binary jpeg file')
+ }
+ var blockLength = imgData.charCodeAt(4)*256 + imgData.charCodeAt(5);
+ var i = 4, len = imgData.length;
+ while ( i < len ) {
+ i += blockLength;
+ if (imgData.charCodeAt(i) !== 0xff) {
+ throw new Error('getJpegSize could not find the size of the image');
+ }
+ if (imgData.charCodeAt(i+1) === 0xc0) {
+ height = imgData.charCodeAt(i+5)*256 + imgData.charCodeAt(i+6);
+ width = imgData.charCodeAt(i+7)*256 + imgData.charCodeAt(i+8);
+ return [width, height];
+ } else {
+ i += 2;
+ blockLength = imgData.charCodeAt(i)*256 + imgData.charCodeAt(i+1)
+ }
+ }
+
+ }
+ // simplified (speedier) replacement for sprintf's %.2f conversion
+ , f2 = function(number){
+ return number.toFixed(2)
+ }
+ // simplified (speedier) replacement for sprintf's %.3f conversion
+ , f3 = function(number){
+ return number.toFixed(3)
+ }
+ // simplified (speedier) replacement for sprintf's %02d
+ , padd2 = function(number) {
+ var n = (number).toFixed(0)
+ if ( number < 10 ) return '0' + n
+ else return n
+ }
+ // simplified (speedier) replacement for sprintf's %02d
+ , padd10 = function(number) {
+ var n = (number).toFixed(0)
+ if (n.length < 10) return new Array( 11 - n.length ).join( '0' ) + n
+ else return n
+ }
+ , out = function(string) {
+ if(outToPages /* set by beginPage */) {
+ pages[page].push(string)
+ } else {
+ content.push(string)
+ content_length += string.length + 1 // +1 is for '\n' that will be used to join contents of content
+ }
+ }
+ , newObject = function() {
+ // Begin a new object
+ objectNumber ++
+ offsets[objectNumber] = content_length
+ out(objectNumber + ' 0 obj');
+ }
+ , putPages = function() {
+ var wPt = pageWidth * k
+ var hPt = pageHeight * k
+
+ // outToPages = false as set in endDocument(). out() writes to content.
+
+ for(n=1; n <= page; n++) {
+ newObject()
+ out('<>')
+ out('endobj')
+
+ // Page content
+ p = pages[n].join('\n')
+ newObject()
+ out('<>')
+ putStream(p)
+ out('endobj')
+ }
+ offsets[1] = content_length
+ out('1 0 obj')
+ out('<>')
+ out('endobj');
+ }
+ , putStream = function(str) {
+ out('stream')
+ out(str)
+ out('endstream')
+ }
+ , putResources = function() {
+ putFonts()
+ putImages()
+ // Resource dictionary
+ offsets[2] = content_length
+ out('2 0 obj')
+ out('<<')
+ putResourceDictionary()
+ out('>>')
+ out('endobj')
+ }
+ , putFonts = function() {
+ for (var i = 0, l=fonts.length; i < l; i++) {
+ putFont(fonts[i])
+ }
+ }
+ , putFont = function(font) {
+ newObject()
+ font.number = objectNumber
+ out('<>')
+ out('endobj')
+ }
+ , addFont = function(name, fontName, fontType, undef) {
+ var fontkey = 'F' + (fonts.length + 1).toString(10)
+
+ fonts.push({'key': fontkey, 'number': objectNumber, 'name': name, 'fontName': fontName, 'type': fontType})
+ // this is mapping structure for quick font lookup.
+ // returns the KEY of the font within fonts array.
+ if (fontmap[fontName] === undef){
+ fontmap[fontName] = {} // fontType is a var interpreted and converted to appropriate string. don't wrap in quotes.
+ }
+ fontmap[fontName][fontType] = fontkey
+ }
+ , addFonts = function() {
+ addFont('Helvetica', HELVETICA, NORMAL)
+ addFont('Helvetica-Bold', HELVETICA, BOLD)
+ addFont('Helvetica-Oblique', HELVETICA, ITALIC)
+ addFont('Helvetica-BoldOblique', HELVETICA, BOLD_ITALIC)
+ addFont('Courier', COURIER, NORMAL)
+ addFont('Courier-Bold', COURIER, BOLD)
+ addFont('Courier-Oblique', COURIER, ITALIC)
+ addFont('Courier-BoldOblique', COURIER, BOLD_ITALIC)
+ addFont('Times-Roman', TIMES, NORMAL)
+ addFont('Times-Bold', TIMES, BOLD)
+ addFont('Times-Italic', TIMES, ITALIC)
+ addFont('Times-BoldItalic', TIMES, BOLD_ITALIC)
+ }
+ , putResourceDictionary = function() {
+ out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]')
+ out('/Font <<')
+ // Do this for each font, the '1' bit is the index of the font
+ for (var i = 0; i < fonts.length; i++) {
+ out('/' + fonts[i].key + ' ' + fonts[i].number + ' 0 R')
+ }
+
+ out('>>')
+ out('/XObject <<')
+ putXobjectDict()
+ out('>>')
+ }
+ , putXobjectDict = function() {
+ for (img in images) {
+ out('/I' + images[img]['i'] + ' ' + images[img]['n'] + ' 0 R');
+ }
+ }
+ , putInfo = function() {
+ out('/Producer (jsPDF ' + version + ')')
+ if(documentProperties.title != undefined) {
+ out('/Title (' + pdfEscape(documentProperties.title) + ')')
+ }
+ if(documentProperties.subject != undefined) {
+ out('/Subject (' + pdfEscape(documentProperties.subject) + ')')
+ }
+ if(documentProperties.author != undefined) {
+ out('/Author (' + pdfEscape(documentProperties.author) + ')')
+ }
+ if(documentProperties.keywords != undefined) {
+ out('/Keywords (' + pdfEscape(documentProperties.keywords) + ')')
+ }
+ if(documentProperties.creator != undefined) {
+ out('/Creator (' + pdfEscape(documentProperties.creator) + ')')
+ }
+ var created = new Date()
+ out('/CreationDate (D:' +
+ [
+ created.getFullYear()
+ , padd2(created.getMonth() + 1)
+ , padd2(created.getDate())
+ , padd2(created.getHours())
+ , padd2(created.getMinutes())
+ , padd2(created.getSeconds())
+ ].join('')+
+ ')'
+ )
+ }
+ , putCatalog = function () {
+ out('/Type /Catalog')
+ out('/Pages 1 0 R')
+ // @TODO: Add zoom and layout modes
+ out('/OpenAction [3 0 R /FitH null]')
+ out('/PageLayout /OneColumn')
+ }
+ , putTrailer = function () {
+ out('/Size ' + (objectNumber + 1))
+ out('/Root ' + objectNumber + ' 0 R')
+ out('/Info ' + (objectNumber - 1) + ' 0 R')
+ }
+ , beginPage = function() {
+ page ++
+ // Do dimension stuff
+ outToPages = true
+ pages[page] = []
+ }
+ , _addPage = function() {
+ beginPage()
+ // Set line width
+ out(f2(lineWidth * k) + ' w')
+ // Set draw color
+ out(drawColor)
+ // resurrecting non-default line caps, joins
+ if (lineCapID !== 0) out(lineCapID.toString(10)+' J')
+ if (lineJoinID !== 0) out(lineJoinID.toString(10)+' j')
+ }
+ , getFont = function(fontName, fontType, undef) {
+ var key
+ try {
+ key = fontmap[fontName][fontType] // returns a string like 'F3' - the KEY corresponding tot he font + type combination.
+ } catch (e) {
+ key = undef
+ }
+ if (!key){
+ throw new Error("Unable to look up font label for font '"+fontName+"', '"+fontType+"'. Refer to getFontList() for available fonts.")
+ }
+ return key
+ }
+ , buildDocument = function() {
+
+ outToPages = false // switches out() to content
+ content = []
+ offsets = []
+
+ // putHeader()
+ out('%PDF-' + pdfVersion)
+
+ putPages()
+
+ putResources()
+
+ // Info
+ newObject()
+ out('<<')
+ putInfo()
+ out('>>')
+ out('endobj')
+
+ // Catalog
+ newObject()
+ out('<<')
+ putCatalog()
+ out('>>')
+ out('endobj')
+
+ // Cross-ref
+ var o = content_length
+ out('xref')
+ out('0 ' + (objectNumber + 1))
+ out('0000000000 65535 f ')
+ for (var i=1; i <= objectNumber; i++) {
+ out(padd10(offsets[i]) + ' 00000 n ')
+ }
+ // Trailer
+ out('trailer')
+ out('<<')
+ putTrailer()
+ out('>>')
+ out('startxref')
+ out(o)
+ out('%%EOF')
+
+ outToPages = true
+
+ return content.join('\n')
+ }
+ // Replace '/', '(', and ')' with pdf-safe versions
+ , pdfEscape = function(text) {
+ return text.replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)')
+ }
+ , getStyle = function(style){
+ // see Path-Painting Operators of PDF spec
+ var op = 'S'; // stroke
+ if (style === 'F') {
+ op = 'f'; // fill
+ } else if (style === 'FD' || style === 'DF') {
+ op = 'B'; // both
+ }
+ return op;
+ }
+ // Image functionality ported from pdf.js
+ , putImg = function(img, url) {
+ newObject();
+ images[url]['n'] = objectNumber;
+ out('<>');
+ }
+ if ('trns' in img && img['trns'].constructor == Array) {
+ var trns = '';
+ for ( var i = 0; i < img['trns'].length; i++) {
+ trns += (img[trns][i] + ' ' + img['trns'][i] + ' ');
+ out('/Mask [' + trns + ']');
+ }
+ }
+ if ('smask' in img) {
+ out('/SMask ' + (objectNumber + 1) + ' 0 R');
+ }
+ out('/Length ' + img['data'].length + '>>');
+ putStream(img['data']);
+ out('endobj');
+ }
+ , putImages = function() {
+ for ( var url in images ) {
+ putImg(images[url], url);
+ }
+ }
+
+ // Public API
+ , _jsPDF = {
+ /**
+ * Adds (and transfers the focus to) new page to the PDF document.
+ * @function
+ * @returns {jsPDF}
+ * @name jsPDF.addPage
+ */
+ addPage: function() {
+ _addPage()
+ return _jsPDF
+ },
+ /**
+ * Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings.
+ * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
+ * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
+ * @param {String|Array} text String or array of strings to be added to the page. Each line is shifted one line down per font, spacing settings declared before this call.
+ * @function
+ * @returns {jsPDF}
+ * @name jsPDF.text
+ */
+ text: function(x, y, text) {
+ /**
+ * Inserts something like this into PDF
+ BT
+ /F1 16 Tf % Font name + size
+ 16 TL % How many units down for next line in multiline text
+ 0 g % color
+ 28.35 813.54 Td % position
+ (line one) Tj
+ T* (line two) Tj
+ T* (line three) Tj
+ ET
+ */
+
+ // If there are any newlines in text, we assume
+ // the user wanted to print multiple lines, so break the
+ // text up into an array. If the text is already an array,
+ // we assume the user knows what they are doing.
+ if (typeof text === 'string' && text.match(/[\n\r]/)) {
+ text = text.split(/\r\n|\r|\n/g)
+ }
+
+ var newtext, str
+
+ if (typeof text === 'string') {
+ str = pdfEscape(text)
+ } else if (text instanceof Array) /* Array */{
+ // we don't want to destroy original text array, so cloning it
+ newtext = text.concat()
+ // we do array.join('text that must not be PDFescaped")
+ // thus, pdfEscape each component separately
+ for ( var i = newtext.length - 1; i !== -1 ; i--) {
+ newtext[i] = pdfEscape( newtext[i] )
+ }
+ str = newtext.join( ") Tj\nT* (" )
+ } else {
+ throw new Error('Type of text must be string or Array. "'+text+'" is not recognized.')
+ }
+ // Using "'" ("go next line and render text" mark) would save space but would complicate our rendering code, templates
+
+ // BT .. ET does NOT have default settings for Tf. You must state that explicitely every time for BT .. ET
+ // if you want text transformation matrix (+ multiline) to work reliably (which reads sizes of things from font declarations)
+ // Thus, there is NO useful, *reliable* concept of "default" font for a page.
+ // The fact that "default" (reuse font used before) font worked before in basic cases is an accident
+ // - readers dealing smartly with brokenness of jsPDF's markup.
+ out(
+ 'BT\n/' +
+ activeFontKey + ' ' + fontSize + ' Tf\n' + // font face, style, size
+ fontSize + ' TL\n' + // line spacing
+ textColor +
+ '\n' + f2(x * k) + ' ' + f2((pageHeight - y) * k) + ' Td\n(' +
+ str +
+ ') Tj\nET'
+ )
+ return _jsPDF
+ },
+ line: function(x1, y1, x2, y2) {
+ out(
+ f2(x1 * k) + ' ' + f2((pageHeight - y1) * k) + ' m ' +
+ f2(x2 * k) + ' ' + f2((pageHeight - y2) * k) + ' l S'
+ )
+ return _jsPDF
+ },
+ /**
+ * Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates.
+ * All data points in `lines` are relative to last line origin.
+ * `x`, `y` become x1,y1 for first line / curve in the set.
+ * For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point.
+ * For bezier curves you need to specify [x2,y2,x3,y3,x4,y4] - vectors to control points 1, 2, ending point. All vectors are against the start of the curve - x1,y1.
+ *
+ * @example .lines(212,110,[[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 10) // line, line, bezier curve, line
+ * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
+ * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
+ * @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves).
+ * @param {Number} scale (Defaults to [1.0,1.0]) x,y Scaling factor for all vectors. Elements can be any floating number Sub-one makes drawing smaller. Over-one grows the drawing. Negative flips the direction.
+ * @function
+ * @returns {jsPDF}
+ * @name jsPDF.text
+ */
+ lines: function(x, y, lines, scale, style) {
+ var undef
+
+ style = getStyle(style)
+ scale = scale === undef ? [1,1] : scale
+
+ // starting point
+ out(f3(x * k) + ' ' + f3((pageHeight - y) * k) + ' m ')
+
+ var scalex = scale[0]
+ , scaley = scale[1]
+ , i = 0
+ , l = lines.length
+ , leg
+ , x2, y2 // bezier only. In page default measurement "units", *after* scaling
+ , x3, y3 // bezier only. In page default measurement "units", *after* scaling
+ // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling
+ , x4 = x // last / ending point = starting point for first item.
+ , y4 = y // last / ending point = starting point for first item.
+
+ for (; i < l; i++) {
+ leg = lines[i]
+ if (leg.length === 2){
+ // simple line
+ x4 = leg[0] * scalex + x4 // here last x4 was prior ending point
+ y4 = leg[1] * scaley + y4 // here last y4 was prior ending point
+ out(f3(x4 * k) + ' ' + f3((pageHeight - y4) * k) + ' l')
+ } else {
+ // bezier curve
+ x2 = leg[0] * scalex + x4 // here last x4 is prior ending point
+ y2 = leg[1] * scaley + y4 // here last y4 is prior ending point
+ x3 = leg[2] * scalex + x4 // here last x4 is prior ending point
+ y3 = leg[3] * scaley + y4 // here last y4 is prior ending point
+ x4 = leg[4] * scalex + x4 // here last x4 was prior ending point
+ y4 = leg[5] * scaley + y4 // here last y4 was prior ending point
+ out(
+ f3(x2 * k) + ' ' +
+ f3((pageHeight - y2) * k) + ' ' +
+ f3(x3 * k) + ' ' +
+ f3((pageHeight - y3) * k) + ' ' +
+ f3(x4 * k) + ' ' +
+ f3((pageHeight - y4) * k) + ' c'
+ )
+ }
+ }
+ // stroking / filling / both the path
+ out(style)
+ return _jsPDF
+ },
+ rect: function(x, y, w, h, style) {
+ var op = getStyle(style)
+ out([
+ f2(x * k)
+ , f2((pageHeight - y) * k)
+ , f2(w * k)
+ , f2(-h * k)
+ , 're'
+ , op
+ ].join(' '))
+ return _jsPDF
+ },
+ triangle: function(x1, y1, x2, y2, x3, y3, style) {
+ this.lines(
+ x1, x2 // start of path
+ , [
+ [ x2 - x1 , y2 - y1 ] // vector to point 2
+ , [ x3 - x2 , y3 - y2 ] // vector to point 3
+ , [ x1 - x3 , y1 - y3 ] // closing vector back to point 1
+ ]
+ , [1,1]
+ , style
+ )
+ return _jsPDF;
+ },
+ ellipse: function(x, y, rx, ry, style) {
+ var op = getStyle(style)
+ , lx = 4/3*(Math.SQRT2-1)*rx
+ , ly = 4/3*(Math.SQRT2-1)*ry
+
+ out([
+ f2((x+rx)*k)
+ , f2((pageHeight-y)*k)
+ , 'm'
+ , f2((x+rx)*k)
+ , f2((pageHeight-(y-ly))*k)
+ , f2((x+lx)*k)
+ , f2((pageHeight-(y-ry))*k)
+ , f2(x*k)
+ , f2((pageHeight-(y-ry))*k)
+ , 'c'
+ ].join(' '))
+ out([
+ f2((x-lx)*k)
+ , f2((pageHeight-(y-ry))*k)
+ , f2((x-rx)*k)
+ , f2((pageHeight-(y-ly))*k)
+ , f2((x-rx)*k)
+ , f2((pageHeight-y)*k)
+ , 'c'
+ ].join(' '))
+ out([
+ f2((x-rx)*k)
+ , f2((pageHeight-(y+ly))*k)
+ , f2((x-lx)*k)
+ , f2((pageHeight-(y+ry))*k)
+ , f2(x*k)
+ , f2((pageHeight-(y+ry))*k)
+ , 'c'
+ ].join(' '))
+ out([
+ f2((x+lx)*k)
+ , f2((pageHeight-(y+ry))*k)
+ , f2((x+rx)*k)
+ , f2((pageHeight-(y+ly))*k)
+ , f2((x+rx)*k)
+ , f2((pageHeight-y)*k)
+ ,'c'
+ , op
+ ].join(' '))
+ return _jsPDF
+ },
+ circle: function(x, y, r, style) {
+ return this.ellipse(x, y, r, r, style)
+ },
+ setProperties: function(properties) {
+ documentProperties = properties
+ return _jsPDF
+ },
+ addImage: function(imageData, format, x, y, w, h) {
+ if (format.toUpperCase() !== 'JPEG') {
+ throw new Error('addImage currently only supports format \'JPEG\', not \''+format+'\'');
+ }
+ var imageIndex = Object.keys(images).length;
+
+ var dims = getJpegSize(imageData);
+ var info = {
+ w : dims[0],
+ h : dims[1],
+ cs : 'DeviceRGB',
+ bpc : 8,
+ f : 'DCTDecode',
+ i : imageIndex,
+ data : imageData
+ };
+ images[imageIndex] = info
+ if (!w && !h) {
+ w = -96;
+ h = -96;
+ }
+ if (w < 0) {
+ w = (-1) * info['w'] * 72 / w / k;
+ }
+ if (h < 0) {
+ h = (-1) * info['h'] * 72 / h / k;
+ }
+ if (w === 0) {
+ w = h * info['w'] / info['h'];
+ }
+ if (h === 0) {
+ h = w * info['h'] / info['w'];
+ }
+// out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', w * k, h
+// * k, x * k, (pageHeight - (y + h)) * k, info['i']));
+ out( 'q '+f2(w*k)+' 0 0 '+f2(h*k)+' '+
+ f2(x*k)+' '+f2((pageHeight - (y + h)) * k)+
+ ' cm /I'+info['i']+' Do Q');
+
+ return _jsPDF
+ },
+ setFontSize: function(size) {
+ fontSize = size
+ return _jsPDF
+ },
+ setFont: function(name) {
+ var _name = name.toLowerCase()
+ activeFontKey = getFont(_name, fontType)
+ // if font is not found, the above line blows up and we never go further
+ fontName = _name
+ return _jsPDF
+ },
+ setFontType: function(type) {
+ var _type = type.toLowerCase()
+ activeFontKey = getFont(fontName, _type)
+ // if font is not found, the above line blows up and we never go further
+ fontType = _type
+ return _jsPDF
+ },
+ getFontList: function(){
+ // TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
+ return {
+ HELVETICA:[NORMAL, BOLD, ITALIC, BOLD_ITALIC]
+ , TIMES:[NORMAL, BOLD, ITALIC, BOLD_ITALIC]
+ , COURIER:[NORMAL, BOLD, ITALIC, BOLD_ITALIC]
+ }
+ },
+ setLineWidth: function(width) {
+ out((width * k).toFixed(2) + ' w')
+ return _jsPDF
+ },
+ setDrawColor: function(r,g,b) {
+ var color
+ if ((r===0 && g===0 && b===0) || (typeof g === 'undefined')) {
+ color = f3(r/255) + ' G'
+ } else {
+ color = [f3(r/255), f3(g/255), f3(b/255), 'RG'].join(' ')
+ }
+ out(color)
+ return _jsPDF
+ },
+ setFillColor: function(r,g,b) {
+ var color
+ if ((r===0 && g===0 && b===0) || (typeof g === 'undefined')) {
+ color = f3(r/255) + ' g'
+ } else {
+ color = [f3(r/255), f3(g/255), f3(b/255), 'rg'].join(' ')
+ }
+ out(color)
+ return _jsPDF
+ },
+ setTextColor: function(r,g,b) {
+ if ((r===0 && g===0 && b===0) || (typeof g === 'undefined')) {
+ textColor = f3(r/255) + ' g'
+ } else {
+ textColor = [f3(r/255), f3(g/255), f3(b/255), 'rg'].join(' ')
+ }
+ return _jsPDF
+ },
+ CapJoinStyles: {
+ 0:0, 'butt':0, 'but':0, 'bevel':0
+ , 1:1, 'round': 1, 'rounded':1, 'circle':1
+ , 2:2, 'projecting':2, 'project':2, 'square':2, 'milter':2
+ },
+ setLineCap: function(style, undef) {
+ var id = this.CapJoinStyles[style]
+ if (id === undef) {
+ throw new Error("Line cap style of '"+style+"' is not recognized. See or extend .CapJoinStyles property for valid styles")
+ }
+ lineCapID = id
+ out(id.toString(10) + ' J')
+ },
+ setLineJoin: function(style, undef) {
+ var id = this.CapJoinStyles[style]
+ if (id === undef) {
+ throw new Error("Line join style of '"+style+"' is not recognized. See or extend .CapJoinStyles property for valid styles")
+ }
+ lineJoinID = id
+ out(id.toString(10) + ' j')
+ },
+ base64encode: function(data) {
+ // use native code if it's present
+ var encode = btoa || function(data) {
+ /** @preserve
+ ====================================================================
+ base64 encoder
+ MIT, GPL
+
+ version: 1109.2015
+ discuss at: http://phpjs.org/functions/base64_encode
+ + original by: Tyler Akins (http://rumkin.com)
+ + improved by: Bayron Guevara
+ + improved by: Thunder.m
+ + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ + bugfixed by: Pellentesque Malesuada
+ + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ + improved by: Rafal Kukawski (http://kukawski.pl)
+ ====================================================================
+ */
+
+ var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
+ , b64a = b64.split('')
+ , o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
+ ac = 0,
+ enc = "",
+ tmp_arr = [];
+
+ do { // pack three octets into four hexets
+ o1 = data.charCodeAt(i++);
+ o2 = data.charCodeAt(i++);
+ o3 = data.charCodeAt(i++);
+
+ bits = o1 << 16 | o2 << 8 | o3;
+
+ h1 = bits >> 18 & 0x3f;
+ h2 = bits >> 12 & 0x3f;
+ h3 = bits >> 6 & 0x3f;
+ h4 = bits & 0x3f;
+
+ // use hexets to index into b64, and append result to encoded string
+ tmp_arr[ac++] = b64a[h1] + b64a[h2] + b64a[h3] + b64a[h4];
+ } while (i < data.length);
+
+ enc = tmp_arr.join('');
+ var r = data.length % 3;
+ return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
+
+ // end of base64 encoder MIT, GPL
+ }
+
+ try {
+ return encode(data)
+ } catch(e) {
+ // INVALID_CHARACTER_ERR
+ // This is what happens if we have utf16 characters in our string.
+ // If so, we should re-encode them as utf-8 bytes.
+ if (e.code === 5) {
+ return encode(utf16to8(data))
+ } else {
+ throw e
+ }
+ }
+ },
+ output: function(type, options) {
+ var undef
+ switch (type){
+ case undef: return buildDocument()
+ case 'datauristring':
+ case 'datauristrlng':
+ return 'data:application/pdf;base64,' + this.base64encode(buildDocument())
+ case 'datauri':
+ case 'dataurl':
+ document.location.href = 'data:application/pdf;base64,' + this.base64encode(buildDocument()); break;
+ default: throw new Error('Output type "'+type+'" is not supported.')
+ }
+ // @TODO: Add different output options
+ }
+ }
+
+ /////////////////////////////////////////
+ // Initilisation if jsPDF Document object
+ /////////////////////////////////////////
+
+ if (unit == 'pt') {
+ k = 1
+ } else if(unit == 'mm') {
+ k = 72/25.4
+ } else if(unit == 'cm') {
+ k = 72/2.54
+ } else if(unit == 'in') {
+ k = 72
+ } else {
+ throw('Invalid unit: ' + unit)
+ }
+
+ // Dimensions are stored as user units and converted to points on output
+ if (format_as_string in pageFormats) {
+ pageHeight = pageFormats[format_as_string][1] / k
+ pageWidth = pageFormats[format_as_string][0] / k
+ } else {
+ try {
+ pageHeight = format[1]
+ pageWidth = format[0]
+ }
+ catch(err) {
+ throw('Invalid format: ' + format)
+ }
+ }
+
+ if (orientation === 'p' || orientation === 'portrait') {
+ orientation = 'p'
+ } else if (orientation === 'l' || orientation === 'landscape') {
+ orientation = 'l'
+ var tmp = pageWidth
+ pageWidth = pageHeight
+ pageHeight = tmp
+ } else {
+ throw('Invalid orientation: ' + orientation)
+ }
+
+ // Add the first page automatically
+ addFonts()
+ activeFontKey = getFont(fontName, fontType)
+ _addPage();
+
+ return _jsPDF
+}
diff --git a/examples/raster-array.html b/examples/raster-array.html
new file mode 100644
index 0000000000..c6a95145a8
--- /dev/null
+++ b/examples/raster-array.html
@@ -0,0 +1,47 @@
+
+
+
+ OpenLayers Raster from Array Example
+
+
+
+
+
+
+
+
+
+
+
+
+ Array as Raster Data
+
+ Raster, Grid, Array
+
+ This demo generates a raster grid from array data.
+
+
+ See the raster-array.js source for details on how this is done.
+
+
+
diff --git a/examples/raster-array.js b/examples/raster-array.js
new file mode 100644
index 0000000000..573188c064
--- /dev/null
+++ b/examples/raster-array.js
@@ -0,0 +1,59 @@
+var cols = 256;
+var rows = 4;
+
+var array = new Array(rows);
+var values = new Array(cols);
+for (var i=0; i
+
+
+ OpenLayers Raster Download Example
+
+
+
+
+
+
+
+
+
+ Download Raster
+
+ Raster, Grid, Download
+
+ This demo shows how raster data can be downloaded.
+
+
+ Download links:
+
+
+
+
+ This example creates a raster composite from a WMS layer. The data from the
+ raster composite can be used to generate download links in various different formats.
+
+ See the raster-download.js
+ source for details on how this is done.
+
+
+
+
+
diff --git a/examples/raster-download.js b/examples/raster-download.js
new file mode 100644
index 0000000000..610dbe628b
--- /dev/null
+++ b/examples/raster-download.js
@@ -0,0 +1,30 @@
+var marble = new OpenLayers.Layer.WMS(
+ "Blue Marble",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "nasa:bluemarble", format: "image/png"},
+ {tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var data = OpenLayers.Raster.Composite.fromLayer(marble);
+
+var map = new OpenLayers.Map({
+ div: "map",
+ theme: null,
+ layers: [marble],
+ center: new OpenLayers.LonLat(0, 0),
+ zoom: 1
+});
+
+var types = {
+ png: "image/png",
+ jpg: "image/jpeg",
+ gif: "image/gif"
+};
+
+for (var type in types) {
+ var link = document.getElementById(type + "-link");
+ link.onmouseover = (function(link, type) {return function() {
+ link.href = data.toDataURL(types[type]);
+ }})(link, type);
+}
+
diff --git a/examples/raster-from-vector.html b/examples/raster-from-vector.html
new file mode 100644
index 0000000000..94524a1684
--- /dev/null
+++ b/examples/raster-from-vector.html
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+ Rasterize Feature Example
+
+
+
+
+
+
+
+
+ Rasterize Feature Example
+
+
+ raster, feature
+
+
+
+ Demonstrates the rasterization of vector features.
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/raster-from-vector.js b/examples/raster-from-vector.js
new file mode 100644
index 0000000000..9ec775d0b5
--- /dev/null
+++ b/examples/raster-from-vector.js
@@ -0,0 +1,52 @@
+var marble = new OpenLayers.Layer.WMS(
+ "Blue Marble",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "nasa:bluemarble", format: "image/png"},
+ {tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var vector = new OpenLayers.Layer.Vector("Vector Features");
+
+var composite = OpenLayers.Raster.Composite.fromLayer(vector, {
+ mapping: function(feature) {
+ // return a 4 element array based on feature
+ return [255, 255, 255, 150];
+ }
+});
+
+var raster = new OpenLayers.Layer.Raster({
+ name: "Rasterized Features",
+ data: composite
+});
+
+var map = new OpenLayers.Map({
+ div: "map",
+ layers: [marble, vector, raster],
+ center: [0, 0],
+ zoom: 1
+});
+
+map.addControl(new OpenLayers.Control.LayerSwitcher());
+
+var controls = {
+ polygon: new OpenLayers.Control.DrawFeature(vector,
+ OpenLayers.Handler.Polygon),
+ drag: new OpenLayers.Control.DragFeature(vector)
+};
+
+for(var key in controls) {
+ map.addControl(controls[key]);
+}
+
+document.getElementById('noneToggle').checked = true;
+
+function toggleControl(element) {
+ for(key in controls) {
+ var control = controls[key];
+ if(element.value == key && element.checked) {
+ control.activate();
+ } else {
+ control.deactivate();
+ }
+ }
+}
diff --git a/examples/raster-grid-layer.html b/examples/raster-grid-layer.html
new file mode 100644
index 0000000000..4c2b0dbb74
--- /dev/null
+++ b/examples/raster-grid-layer.html
@@ -0,0 +1,40 @@
+
+
+
+ OpenLayers Raster Grid Layer Example
+
+
+
+
+
+
+
+
+
+ Raster Layer from Grid Data
+
+ Raster, Grid, Layer
+
+ This demo generates a raster layer based on modified data from another layer.
+
+
+
+
+ This example generates a OpenLayers.Raster.Composite
+ from a WMS layer. The composite data is a luminosity calculation
+ from a OpenLayers.Raster.Operation
that works with
+ the source RGBA data. The resulting luminosity data is displayed
+ on a second map with a OpenLayers.Layer.Raster
.
+
+
+ See the raster-grid-layer.js
+ source for details on how this is done.
+
+
+
+
diff --git a/examples/raster-grid-layer.js b/examples/raster-grid-layer.js
new file mode 100644
index 0000000000..eda8f91a8a
--- /dev/null
+++ b/examples/raster-grid-layer.js
@@ -0,0 +1,40 @@
+
+var luminance = OpenLayers.Raster.Operation.create(function(rgba) {
+ var lum = Math.min(255, 30 + (0.299 * rgba[0]) + (0.587 * rgba[1]) + (0.114 * rgba[2]));
+ return [lum, lum, lum, rgba[3]];
+});
+
+var marble = new OpenLayers.Layer.WMS(
+ "Blue Marble",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "nasa:bluemarble", format: "image/png"},
+ {tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var raster = new OpenLayers.Layer.Raster({
+ name: "Luminance",
+ data: luminance(OpenLayers.Raster.Composite.fromLayer(marble)),
+ isBaseLayer: true
+});
+
+var map = new OpenLayers.Map({
+ div: "map",
+ theme: null,
+ layers: [
+ marble
+ ],
+ center: new OpenLayers.LonLat(0, 0),
+ zoom: 1
+});
+
+var view = new OpenLayers.Map({
+ div: "view",
+ theme: null,
+ controls: [],
+ layers: [
+ raster
+ ],
+ center: new OpenLayers.LonLat(0, 0),
+ zoom: 1
+});
+
diff --git a/examples/raster-magnify.html b/examples/raster-magnify.html
new file mode 100644
index 0000000000..2be2a5dd88
--- /dev/null
+++ b/examples/raster-magnify.html
@@ -0,0 +1,38 @@
+
+
+
+
OpenLayers Raster Magnification Example
+
+
+
+
+
+
+
+
+
+
Magnify Raster
+
+ Raster, Grid, Resample
+
+
This demo shows how raster data can be resampled.
+
+
+
+ This example uses a OpenLayers.Raster.Composite
+ to resample data from a WMS layer. Move your mouse over the
+ map to change the center of the magnification lens.
+
+
+ See the raster-magnify.js
+ source for details on how this is done.
+
+
+
+
+
diff --git a/examples/raster-magnify.js b/examples/raster-magnify.js
new file mode 100644
index 0000000000..29eef6d669
--- /dev/null
+++ b/examples/raster-magnify.js
@@ -0,0 +1,70 @@
+var marble = new OpenLayers.Layer.WMS(
+ "Blue Marble",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "nasa:bluemarble", format: "image/png"},
+ {tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var data = OpenLayers.Raster.Composite.fromLayer(marble);
+
+var focus = [256, 128];
+var radius = 50;
+var magnification = 2.5;
+
+var magnified = new OpenLayers.Raster.Composite({
+ numRows: function() {
+ return data.numRows();
+ },
+ numCols: function() {
+ return data.numCols();
+ },
+ getCount: function() {
+ return data.getCount();
+ },
+ getValue: function(col, row) {
+ var dx = focus[0] - col;
+ var dy = focus[1] - row;
+ var d = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
+ var value;
+ if (d < radius) {
+ value = data.getValue(
+ Math.round(col + (dx / magnification)),
+ Math.round(row + (dy / magnification))
+ );
+ } else {
+ value = [0, 0, 0, 0];
+ }
+ return value;
+ }
+});
+
+data.events.on({
+ update: function() {
+ magnified.events.triggerEvent("update");
+ }
+});
+
+var raster = new OpenLayers.Layer.Raster({
+ name: "Magnified Blue Marble",
+ data: magnified
+});
+
+var map = new OpenLayers.Map({
+ div: "map",
+ theme: null,
+ layers: [
+ marble, raster
+ ],
+ center: new OpenLayers.LonLat(0, 0),
+ zoom: 1
+});
+
+map.events.on({
+ mousemove: function(event) {
+ if (!map.dragging) {
+ var pixel = event.xy;
+ focus = [pixel.x, pixel.y];
+ magnified.events.triggerEvent("update");
+ }
+ }
+});
diff --git a/examples/raster-mask.html b/examples/raster-mask.html
new file mode 100644
index 0000000000..01b168834b
--- /dev/null
+++ b/examples/raster-mask.html
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
OpenLayers Raster Mask
+
+
+
+
+
+
OpenLayers Raster Mask
+
+ This example demonstrates how generate a raster mask from vector data.
+
+
+ Raster, Vector, Mask
+
+
+
+ Show landcover layer.
+
+
+
+
+ Area (sq. m) Land Cover
+
+ area
+ cover
+
+
+
+
+
+ Click on the map to select a census tract. The landcover stats will be
+ displayed for the selected tracts.
+
+ See the raster-mask.js source for
+ detail on generating a mask for raster data from vector features.
+
+
+
+
+
+
diff --git a/examples/raster-mask.js b/examples/raster-mask.js
new file mode 100644
index 0000000000..82693b41e7
--- /dev/null
+++ b/examples/raster-mask.js
@@ -0,0 +1,205 @@
+var fromLayer = OpenLayers.Raster.Composite.fromLayer;
+var op = OpenLayers.Raster.Operation;
+
+var streets = new OpenLayers.Layer.XYZ(
+ "OpenStreetMap",
+ [
+ "http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile2.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile3.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile4.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png"
+ ],
+ {
+ attribution: "Tiles by
MapQuest ,
Open Street Map and contributors,
CC-BY-SA ",
+ transitionEffect: "resize"
+ }
+);
+
+var imagery = new OpenLayers.Layer.XYZ(
+ "Imagery",
+ [
+ "http://oatile1.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile2.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile3.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile4.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png"
+ ],
+ {
+ attribution: "Tiles by
MapQuest ",
+ transitionEffect: "resize"
+ }
+);
+
+
+var nlcd = new OpenLayers.Layer.WMS(
+ "Land Cover",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "usgs:nlcd", format: "image/png8"},
+ {singleTile: true, isBaseLayer: false, opacity: 0, displayInLayerSwitcher: false, tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+
+var tracts = new OpenLayers.Layer.Vector("Census Tracts", {
+ strategies: [new OpenLayers.Strategy.BBOX()],
+ projection: new OpenLayers.Projection("EPSG:900913"),
+ protocol: new OpenLayers.Protocol.WFS({
+ url: "http://demo.opengeo.org/geoserver/wfs",
+ version: "1.1.0",
+ featureNS: "http://www.usgs.gov/",
+ srsName: "EPSG:900913",
+ featureType: "tracts"
+ }),
+ styleMap: new OpenLayers.StyleMap({
+ "default": new OpenLayers.Style({
+ stroke: false,
+ fillOpacity: 0.01
+ }),
+ "select": new OpenLayers.Style({
+ fillColor: "#66ccff",
+ fillOpacity: 0.5,
+ stroke: true,
+ strokeColor: "#3399ff",
+ strokeWidth: 2
+ })
+ })
+});
+
+var select = new OpenLayers.Control.SelectFeature(tracts, {
+ autoActivate: true,
+ toggle: true,
+ multipleKey: "shiftKey"
+});
+
+var getIds = op.create(function(pixel) {
+ var id = null;
+ if (!!pixel[3]) {
+ id = (256 * 256 * pixel[2]) + ((256 * pixel[1]) + pixel[0]);
+ }
+ return [id];
+});
+
+var rasterTracts = fromLayer(tracts, {
+ mapping: function(feature) {
+ // TODO: handle this mapping in the factory
+ var id = Number(feature.fid.split(".").pop());
+ var r = id % 256;
+ var g = Math.floor(id / 256) % 256;
+ var b = Math.floor(id / (256 * 256));
+ if (b > 255) {
+ throw new Error("Id overflow");
+ }
+ return [r, g, b, 255];
+ }
+});
+
+var tractIds = getIds(rasterTracts);
+
+var map = new OpenLayers.Map({
+ div: "map",
+ projection: "EPSG:900913",
+ layers: [streets, imagery, nlcd, tracts],
+ controls: [
+ select,
+ new OpenLayers.Control.Zoom(),
+ new OpenLayers.Control.Navigation(),
+ new OpenLayers.Control.LayerSwitcher()
+ ],
+ center: [-8606289, 4714070],
+ zoom: 11
+});
+
+var classes = {
+ "255,255,255": null,
+ "0,0,0": null, // 0
+ "73,109,163": "Open Water", // 11
+ "224,204,204": "Developed, Open Space", // 21
+ "219,153,130": "Developed, Low Intensity", // 22
+ "242,0,0": "Developed, Medium Intensity", // 23
+ "170,0,0": "Developed, High Intensity", // 24
+ "181,175,163": "Barren Land (Rock/Sand/Clay)", // 31
+ "107,170,102": "Deciduous Forest", // 41
+ "28,102,51": "Evergreen Forest", // 42
+ "186,204,145": "Mixed Forest", // 43
+ "165,140,48": "Dwarf Scrub", // 51
+ "209,186,130": "Shrub/Scrub", // 52
+ "229,229,193": "Grassland/Herbaceous", // 71
+ "201,201,119": "Sedge/Herbaceous", // 72
+ "221,216,60": "Pasture/Hay", // 81
+ "173,112,40": "Cultivated Crops", // 82
+ "186,216,237": "Woody Wetlands", // 90
+ "112,163,191": "Emergent Herbaceous Wetlands" // 95
+};
+
+var getCover = op.create(function(pixel) {
+ var rgb = pixel.slice(0, 3).join(",");
+ return [classes[rgb] || rgb];
+});
+
+var landcover = getCover(fromLayer(nlcd));
+
+function generateStats() {
+ var stats = {};
+ var area = Math.pow(map.getResolution(), 2);
+ var selected = {};
+ var some = false;
+ for (var i=0, ii=tracts.selectedFeatures.length; i
+
+
+ OpenLayers Raster Operations Example
+
+
+
+
+
+
+
+
+
+
+
+
+ Raster Operations
+
+ Raster, Grid, Operation
+
+ This demo uses raster operations to manipulate layer based data.
+
+
+
+
+ reset
+
+
+ This example manipulates data in a OpenLayers.Raster.Composite
+ using a series of OpenLayers.Raster.Operation
methods.
+ RGB data from the WMS layer is translated to HSL, modified using
+ user supplied values, and translated back to RGB. The resulting
+ composite is displayed on the map with a OpenLayers.Layer.Raster
.
+
+
+ See the raster-operations.js
+ source for details on how this is done.
+
+
+
+
+
diff --git a/examples/raster-operations.js b/examples/raster-operations.js
new file mode 100644
index 0000000000..9826b5dd15
--- /dev/null
+++ b/examples/raster-operations.js
@@ -0,0 +1,134 @@
+
+// alias for operations
+var op = OpenLayers.Raster.Operation;
+
+// operation for converting rgb values to hsl values
+var rgb2hsl = op.create(function(rgb) {
+ var r = rgb[0] / 255,
+ g = rgb[1] / 255,
+ b = rgb[2] / 255;
+ var max = Math.max(r, g, b),
+ min = Math.min(r, g, b);
+ var h, s, l = (max + min) / 2;
+
+ if (max == min) {
+ h = s = 0; // achromatic
+ } else {
+ var d = max - min;
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+ switch (max) {
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
+ case g: h = (b - r) / d + 2; break;
+ case b: h = (r - g) / d + 4; break;
+ }
+ h /= 6;
+ }
+ return [h, s, l, rgb[3]];
+});
+
+// helper function for hsl2rgb operation
+function hue2rgb(p, q, t) {
+ if (t < 0) t += 1;
+ if (t > 1) t -= 1;
+ if (t < 1/6) return p + (q - p) * 6 * t;
+ if (t < 1/2) return q;
+ if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
+ return p;
+}
+
+// operation for converting hsl values to rgb values
+var hsl2rgb = op.create(function(hsl) {
+ var r, g, b;
+ var h = hsl[0],
+ s = hsl[1],
+ l = hsl[2];
+
+ if (s == 0) {
+ r = g = b = l; // achromatic
+ } else {
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ var p = 2 * l - q;
+ r = hue2rgb(p, q, h + 1/3);
+ g = hue2rgb(p, q, h);
+ b = hue2rgb(p, q, h - 1/3);
+ }
+
+ return [r * 255, g * 255, b * 255, hsl[3]];
+});
+
+var adjustments = {
+ hue: 0,
+ saturation: 0,
+ lightness: 0
+};
+
+var adjust = op.create(function(hsl, deltas) {
+ var h = (hsl[0] + deltas.hue) % 1;
+ if (h < 0) {
+ h += 1;
+ }
+ var s = Math.max(0 , Math.min(hsl[1] + deltas.saturation, 1));
+ var l = Math.max(0 , Math.min(hsl[2] + deltas.lightness, 1));
+ return [h, s, l, hsl[3]];
+});
+
+var marble = new OpenLayers.Layer.WMS(
+ "Blue Marble",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "nasa:bluemarble", format: "image/png"},
+ {tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var data = OpenLayers.Raster.Composite.fromLayer(marble);
+var adjusted = hsl2rgb(adjust(rgb2hsl(data), adjustments));
+
+var raster = new OpenLayers.Layer.Raster({
+ name: "Adjusted Blue Marble",
+ data: adjusted
+});
+
+var map = new OpenLayers.Map({
+ div: "map",
+ theme: null,
+ layers: [
+ marble, raster
+ ],
+ center: new OpenLayers.LonLat(0, 0),
+ zoom: 1
+});
+
+// add hsl sliders that modify properties of the adjustments object and update data
+$("#hue-slider").slider({
+ step: 2,
+ value: 50,
+ stop: function(event, ui) {
+ adjustments.hue = (ui.value / 100) - 0.5;
+ adjusted.events.triggerEvent("update");
+ }
+});
+$("#sat-slider").slider({
+ step: 2,
+ value: 50,
+ stop: function(event, ui) {
+ adjustments.saturation = (2 * ui.value / 100) - 1;
+ adjusted.events.triggerEvent("update");
+ }
+});
+$("#lit-slider").slider({
+ step: 2,
+ value: 50,
+ stop: function(event, ui) {
+ adjustments.lightness = (2 * ui.value / 100) - 1;
+ adjusted.events.triggerEvent("update");
+ }
+});
+$("#reset").button();
+$("#reset").click(function() {
+ $("#hue-slider").slider("value", 50);
+ adjustments.hue = 0;
+ $("#sat-slider").slider("value", 50);
+ adjustments.saturation = 0;
+ $("#lit-slider").slider("value", 50);
+ adjustments.lightness = 0;
+ adjusted.events.triggerEvent("update");
+});
diff --git a/examples/raster-pdf.html b/examples/raster-pdf.html
new file mode 100644
index 0000000000..d57c148311
--- /dev/null
+++ b/examples/raster-pdf.html
@@ -0,0 +1,42 @@
+
+
+
+ OpenLayers Raster PDF Example
+
+
+
+
+
+
+
+
+
+
+ Download PDF
+
+ Raster, PDF, Download
+
+ This demo shows how raster data can be downloaded as a PDF.
+
+
+ Title
+
+ Save
+
+
+
+ See the raster-pdf.js
+ source for details on how this is done.
+
+
+
+
+
diff --git a/examples/raster-pdf.js b/examples/raster-pdf.js
new file mode 100644
index 0000000000..2b72712261
--- /dev/null
+++ b/examples/raster-pdf.js
@@ -0,0 +1,29 @@
+var marble = new OpenLayers.Layer.WMS(
+ "Blue Marble",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "nasa:bluemarble", format: "image/png"},
+ {tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var data = OpenLayers.Raster.Composite.fromLayer(marble);
+
+var map = new OpenLayers.Map({
+ div: "map",
+ theme: null,
+ layers: [marble],
+ center: new OpenLayers.LonLat(0, 0),
+ zoom: 1
+});
+
+var link = document.getElementById("pdf-link");
+
+link.onmouseover = function() {
+ var title = document.getElementById("map-title").value;
+ var doc = new jsPDF("landscape");
+ doc.text(20, 20, title);
+
+ var imgData = data.toDataURL("image/jpeg").slice("data:image/jpeg;base64,".length);
+ doc.addImage(atob(imgData), "JPEG", 20, 30, 256, 128);
+
+ link.href = doc.output("datauristring");
+}
diff --git a/examples/raster-query.html b/examples/raster-query.html
new file mode 100644
index 0000000000..df75f0140d
--- /dev/null
+++ b/examples/raster-query.html
@@ -0,0 +1,48 @@
+
+
+
+ OpenLayers Raster Query Example
+
+
+
+
+
+
+
+
+
+ Query Grid Data
+
+ Raster, Grid, Query
+
+ This demo shows querying of raster data.
+
+
+ Landcover Type
+ none
+
+
+ Elevation
+ none
+
+
+
+ This example uses two hidden layers to pull in landcover and elevation
+ data. Raster composites are generated from these layers and queried
+ with each move of the mouse.
+
+ See the raster-query.js
+ source for details on how this is done.
+
+
+
+
+
diff --git a/examples/raster-query.js b/examples/raster-query.js
new file mode 100644
index 0000000000..449c639f11
--- /dev/null
+++ b/examples/raster-query.js
@@ -0,0 +1,136 @@
+var op = OpenLayers.Raster.Operation;
+var fromLayer = OpenLayers.Raster.Composite.fromLayer;
+
+var streets = new OpenLayers.Layer.XYZ(
+ "OpenStreetMap",
+ [
+ "http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile2.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile3.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile4.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png"
+ ],
+ {
+ attribution: "Tiles by MapQuest , Open Street Map and contributors, CC-BY-SA ",
+ transitionEffect: "resize"
+ }
+);
+
+var imagery = new OpenLayers.Layer.XYZ(
+ "Imagery",
+ [
+ "http://oatile1.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile2.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile3.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile4.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png"
+ ],
+ {
+ attribution: "Tiles by MapQuest ",
+ transitionEffect: "resize"
+ }
+);
+
+
+var ned = new OpenLayers.Layer.WMS(
+ "Elevation",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "usgs:ned", format: "image/png", transparent: true},
+ {singleTile: true, isBaseLayer: false, opacity: 0, displayInLayerSwitcher: false, tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var nlcd = new OpenLayers.Layer.WMS(
+ "Land Cover",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "usgs:nlcd", format: "image/png8", transparent: true},
+ {singleTile: true, isBaseLayer: false, opacity: 0, displayInLayerSwitcher: false, tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var map = new OpenLayers.Map({
+ div: "map",
+ projection: "EPSG:900913",
+ layers: [streets, imagery, ned, nlcd],
+ restrictedExtent: [-8732354, 4647019, -8492897, 4782306],
+ center: [-8606289, 4714070],
+ zoom: 11
+});
+
+map.addControl(new OpenLayers.Control.LayerSwitcher());
+
+/**
+ * The NED dataset is symbolized by a color ramp that maps the following
+ * elevations to corresponding RGB values. This operation is used to
+ * invert the mapping - returning elevations in meters for a pixel RGB array.
+ *
+ * -20m : 0, 0, 0
+ * 400m : 0, 0, 255
+ * 820m : 0, 255, 255
+ * 1240m : 255, 255, 255
+ *
+ * Transparent pixels are areas of no data (grid value will be NaN).
+ */
+var getElevation = op.create(function(pixel) {
+ var elevation = NaN,
+ delta = 420,
+ min = -20;
+
+ if (pixel[3] == 255) {
+ elevation = (delta * (pixel[0] + pixel[1] + pixel[2]) / 255) + min;
+ }
+ return [elevation];
+});
+
+var elevation = getElevation(fromLayer(ned));
+
+/**
+ * The NLCD dataset is symbolized according to landcover type. The mapping below
+ * links RGB values to landcover type.
+ */
+var classes = {
+ "255,255,255": null,
+ "0,0,0": null, // 0
+ "73,109,163": "Open Water", // 11
+ "224,204,204": "Developed, Open Space", // 21
+ "219,153,130": "Developed, Low Intensity", // 22
+ "242,0,0": "Developed, Medium Intensity", // 23
+ "170,0,0": "Developed, High Intensity", // 24
+ "181,175,163": "Barren Land (Rock/Sand/Clay)", // 31
+ "107,170,102": "Deciduous Forest", // 41
+ "28,102,51": "Evergreen Forest", // 42
+ "186,204,145": "Mixed Forest", // 43
+ "165,140,48": "Dwarf Scrub", // 51
+ "209,186,130": "Shrub/Scrub", // 52
+ "229,229,193": "Grassland/Herbaceous", // 71
+ "201,201,119": "Sedge/Herbaceous", // 72
+ "221,216,60": "Pasture/Hay", // 81
+ "173,112,40": "Cultivated Crops", // 82
+ "186,216,237": "Woody Wetlands", // 90
+ "112,163,191": "Emergent Herbaceous Wetlands" // 95
+};
+
+var getCover = op.create(function(pixel) {
+ var rgb = pixel.slice(0, 3).join(",");
+ return [classes[rgb]];
+});
+
+var landcover = getCover(fromLayer(nlcd));
+
+var landcoverOutput = document.getElementById("landcover");
+var elevationOutput = document.getElementById("elevation");
+
+// on every mousemove, update the landcover and elevation output
+map.events.on({
+ mousemove: function(event) {
+ if (!map.dragging) {
+ var x = Math.round(event.xy.x);
+ var y = Math.round(event.xy.y);
+ // get landcover type for mouse location
+ landcoverOutput.innerHTML = landcover.getValue(x, y) || "loading ... ";
+ // get elevation data for mouse location
+ var el = elevation.getValue(x, y);
+ if (!isNaN(el)) {
+ elevationOutput.innerHTML = Math.round(el) + " m";
+ } else {
+ elevationOutput.innerHTML = "loading ... "
+ }
+ }
+ }
+});
diff --git a/examples/raster-stats.html b/examples/raster-stats.html
new file mode 100644
index 0000000000..b259a37aef
--- /dev/null
+++ b/examples/raster-stats.html
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+ OpenLayers Raster Stats
+
+
+
+
+
+ OpenLayers Raster Stats
+
+ This example demonstrates how statistics can be generated from raster data.
+
+
+ Raster, Statistics
+
+
+
+ Show landcover layer.
+
+
+
+
+ Area (m2 ) Land Cover
+
+ area
+ cover
+
+
+
+
+
+ This example loads landcover data with a hidden WMS layer. A raster composite
+ is generated from this layer and landcover statistics are generated each time
+ the data is updated.
+
+ See the raster-stats.js source for
+ detail on generating statistics from raster data.
+
+
+
+
+
+
diff --git a/examples/raster-stats.js b/examples/raster-stats.js
new file mode 100644
index 0000000000..9ba822b4b9
--- /dev/null
+++ b/examples/raster-stats.js
@@ -0,0 +1,126 @@
+var op = OpenLayers.Raster.Operation;
+var fromLayer = OpenLayers.Raster.Composite.fromLayer;
+
+var streets = new OpenLayers.Layer.XYZ(
+ "OpenStreetMap",
+ [
+ "http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile2.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile3.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile4.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png"
+ ],
+ {
+ attribution: "Tiles by MapQuest , Open Street Map and contributors, CC-BY-SA ",
+ transitionEffect: "resize"
+ }
+);
+
+var imagery = new OpenLayers.Layer.XYZ(
+ "Imagery",
+ [
+ "http://oatile1.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile2.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile3.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile4.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png"
+ ],
+ {
+ attribution: "Tiles by MapQuest ",
+ transitionEffect: "resize"
+ }
+);
+
+
+var nlcd = new OpenLayers.Layer.WMS(
+ "Land Cover",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "usgs:nlcd", format: "image/png8"},
+ {singleTile: true, isBaseLayer: false, opacity: 0, displayInLayerSwitcher: false, tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var map = new OpenLayers.Map({
+ div: "map",
+ projection: "EPSG:900913",
+ layers: [streets, imagery, nlcd],
+ restrictedExtent: [-8732354, 4647019, -8492897, 4782306],
+ center: [-8606289, 4714070],
+ zoom: 11
+});
+
+map.addControl(new OpenLayers.Control.LayerSwitcher());
+
+/**
+ * The NLCD dataset is symbolized according to landcover type. The mapping below
+ * links RGB values to landcover type.
+ */
+var classes = {
+ "255,255,255": null,
+ "0,0,0": null, // 0
+ "73,109,163": "Open Water", // 11
+ "224,204,204": "Developed, Open Space", // 21
+ "219,153,130": "Developed, Low Intensity", // 22
+ "242,0,0": "Developed, Medium Intensity", // 23
+ "170,0,0": "Developed, High Intensity", // 24
+ "181,175,163": "Barren Land (Rock/Sand/Clay)", // 31
+ "107,170,102": "Deciduous Forest", // 41
+ "28,102,51": "Evergreen Forest", // 42
+ "186,204,145": "Mixed Forest", // 43
+ "165,140,48": "Dwarf Scrub", // 51
+ "209,186,130": "Shrub/Scrub", // 52
+ "229,229,193": "Grassland/Herbaceous", // 71
+ "201,201,119": "Sedge/Herbaceous", // 72
+ "221,216,60": "Pasture/Hay", // 81
+ "173,112,40": "Cultivated Crops", // 82
+ "186,216,237": "Woody Wetlands", // 90
+ "112,163,191": "Emergent Herbaceous Wetlands" // 95
+};
+
+var getCover = op.create(function(pixel) {
+ var rgb = pixel.slice(0, 3).join(",");
+ return [classes[rgb]];
+});
+
+var landcover = getCover(fromLayer(nlcd));
+
+var stats = {};
+function generateStats() {
+ stats = {};
+ var area = Math.pow(map.getResolution(), 2);
+ landcover.forEach(function(pixel) {
+ var cover = pixel[0];
+ if (cover) {
+ if (cover in stats) {
+ stats[cover] += area;
+ } else {
+ stats[cover] = area;
+ }
+ }
+ });
+ displayStats(stats);
+}
+
+var template = new jugl.Template("template");
+var target = document.getElementById("stats");
+function displayStats(stats) {
+ var entries = [];
+ for (var cover in stats) {
+ entries.push({
+ cover: cover,
+ area: stats[cover]
+ });
+ }
+ entries.sort(function(a, b) {return b.area - a.area});
+ target.innerHTML = "";
+ template.process({
+ context: {entries: entries},
+ clone: true,
+ parent: target
+ });
+}
+
+landcover.events.on({update: generateStats});
+
+// allow toggling of nlcd visibility
+document.getElementById("show").onclick = function() {
+ nlcd.setOpacity(this.checked ? 1 : 0);
+};
+
diff --git a/examples/raster-zonal-stats.html b/examples/raster-zonal-stats.html
new file mode 100644
index 0000000000..4eece9d02b
--- /dev/null
+++ b/examples/raster-zonal-stats.html
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+ OpenLayers Raster Zonal Stats
+
+
+
+
+
+ OpenLayers Raster Zonal Stats
+
+ This example demonstrates how statistics can be generated from raster data.
+
+
+ Raster, Statistics
+
+
+
+ Show elevation layer.
+ Show landcover layer.
+
+
+
+
+
+ Landcover Type
+ Area (sq. meters)
+
+
+ Low Elevation
+ Mid Elevation
+ High Elevation
+
+
+ landcover type
+ low area
+ mid area
+ high area
+
+
+
+
+
+
+
+
diff --git a/examples/raster-zonal-stats.js b/examples/raster-zonal-stats.js
new file mode 100644
index 0000000000..cc3ae058b6
--- /dev/null
+++ b/examples/raster-zonal-stats.js
@@ -0,0 +1,213 @@
+var op = OpenLayers.Raster.Operation;
+var fromLayer = OpenLayers.Raster.Composite.fromLayer;
+
+var streets = new OpenLayers.Layer.XYZ(
+ "OpenStreetMap",
+ [
+ "http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile2.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile3.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
+ "http://otile4.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png"
+ ],
+ {
+ attribution: "Tiles by MapQuest , Open Street Map and contributors, CC-BY-SA ",
+ transitionEffect: "resize"
+ }
+);
+
+var imagery = new OpenLayers.Layer.XYZ(
+ "Imagery",
+ [
+ "http://oatile1.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile2.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile3.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png",
+ "http://oatile4.mqcdn.com/tiles/1.0.0/sat/${z}/${x}/${y}.png"
+ ],
+ {
+ attribution: "Tiles by MapQuest ",
+ transitionEffect: "resize"
+ }
+);
+
+
+var ned = new OpenLayers.Layer.WMS(
+ "Elevation",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "usgs:ned", format: "image/png", transparent: true},
+ {singleTile: true, isBaseLayer: false, opacity: 0, displayInLayerSwitcher: false, tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var nlcd = new OpenLayers.Layer.WMS(
+ "Land Cover",
+ "http://demo.opengeo.org/geoserver/wms",
+ {layers: "usgs:nlcd", format: "image/png8", transparent: true},
+ {singleTile: true, isBaseLayer: false, opacity: 0, displayInLayerSwitcher: false, tileOptions: {crossOriginKeyword: "anonymous"}}
+);
+
+var map = new OpenLayers.Map({
+ div: "map",
+ projection: "EPSG:900913",
+ layers: [streets, imagery, ned, nlcd],
+ center: [-8690522, 4714451],
+ restrictedExtent: [-8732354, 4647019, -8492897, 4782306],
+ zoom: 11
+});
+
+/**
+ * The NED dataset is symbolized by a color ramp that maps the following
+ * elevations to corresponding RGB values. This operation is used to
+ * invert the mapping - returning elevations in meters for a pixel RGB array.
+ *
+ * -20m : 0, 0, 0
+ * 400m : 0, 0, 255
+ * 820m : 0, 255, 255
+ * 1240m : 255, 255, 255
+ *
+ * Transparent pixels are areas of no data (grid value will be NaN).
+ */
+var getElevation = op.create(function(pixel) {
+ var elevation = NaN,
+ delta = 420,
+ min = -20;
+
+ if (pixel[3] == 255) {
+ elevation = (delta * (pixel[0] + pixel[1] + pixel[2]) / 255) + min;
+ }
+ return [elevation];
+});
+
+/**
+ * This operation is used to transform an elevation grid into a grid
+ * with values representing an elevation zone.
+ *
+ * 0: e < 150m
+ * 1: 150m <= e < 400m
+ * 2: e >= 400m
+ *
+ * Areas of no data will have NaN value.
+ */
+var getZone = op.create(function(pixel) {
+ var elevation = pixel[0],
+ zone = NaN;
+ if (!isNaN(elevation)) {
+ if (elevation < 150) {
+ zone = 0;
+ } else if (elevation < 400) {
+ zone = 1;
+ } else {
+ zone = 2;
+ }
+ }
+ return [zone];
+});
+
+var zones = getZone(getElevation(fromLayer(ned)));
+
+/**
+ * The NLCD dataset is symbolized according to landcover type. The mapping below
+ * links RGB values to landcover type.
+ */
+var classes = {
+ "255,255,255": null,
+ "0,0,0": null, // 0
+ "73,109,163": "Open Water", // 11
+ "224,204,204": "Developed, Open Space", // 21
+ "219,153,130": "Developed, Low Intensity", // 22
+ "242,0,0": "Developed, Medium Intensity", // 23
+ "170,0,0": "Developed, High Intensity", // 24
+ "181,175,163": "Barren Land (Rock/Sand/Clay)", // 31
+ "107,170,102": "Deciduous Forest", // 41
+ "28,102,51": "Evergreen Forest", // 42
+ "186,204,145": "Mixed Forest", // 43
+ "165,140,48": "Dwarf Scrub", // 51
+ "209,186,130": "Shrub/Scrub", // 52
+ "229,229,193": "Grassland/Herbaceous", // 71
+ "201,201,119": "Sedge/Herbaceous", // 72
+ "221,216,60": "Pasture/Hay", // 81
+ "173,112,40": "Cultivated Crops", // 82
+ "186,216,237": "Woody Wetlands", // 90
+ "112,163,191": "Emergent Herbaceous Wetlands" // 95
+};
+
+var getCover = op.create(function(pixel) {
+ var rgb = pixel.slice(0, 3).join(",");
+ return [classes[rgb]];
+});
+
+var landcover = getCover(fromLayer(nlcd));
+
+var getZoneCover = op.create(function(zonesPixel, coverPixel) {
+ return [zonesPixel[0], coverPixel[0]];
+});
+
+var zoneCover = getZoneCover(zones, landcover);
+
+var pending = null;
+function deferredStats() {
+ if (pending != null) {
+ window.clearTimeout(pending);
+ pending = null;
+ }
+ pending = window.setTimeout(generateStats, 500);
+}
+
+function generateStats() {
+ var stats = {};
+ var area = Math.pow(map.getResolution(), 2);
+ zoneCover.forEach(function(pixel) {
+ var zone = pixel[0];
+ var cover = pixel[1];
+ if (!isNaN(zone) && cover) {
+ if (!(cover in stats)) {
+ stats[cover] = [];
+ }
+ var sums = stats[cover];
+ if (zone in sums) {
+ sums[zone] += area;
+ } else {
+ sums[zone] = area;
+ }
+ }
+ });
+ displayStats(stats);
+}
+
+var template = new jugl.Template("template");
+var target = document.getElementById("stats");
+function displayStats(stats) {
+ var entries = [];
+ for (var cover in stats) {
+ entries.push({
+ cover: cover,
+ area: stats[cover]
+ });
+ }
+ function sum(area) {
+ return (area[0] || 0) + (area[1] || 0) + (area[2] || 0);
+ }
+ entries.sort(function(a, b) {
+ return sum(b.area) - sum(a.area);
+ });
+ target.innerHTML = "";
+ template.process({
+ context: {entries: entries},
+ clone: true,
+ parent: target
+ });
+}
+
+zoneCover.events.on({update: deferredStats});
+
+map.addControl(new OpenLayers.Control.LayerSwitcher());
+
+
+// allow toggling of nlcd visibility
+document.getElementById("show-nlcd").onclick = function() {
+ nlcd.setOpacity(this.checked ? 1 : 0);
+};
+
+
+// allow toggling of nlcd visibility
+document.getElementById("show-ned").onclick = function() {
+ ned.setOpacity(this.checked ? 1 : 0);
+};
diff --git a/examples/style.css b/examples/style.css
index 237f940248..d141838d2e 100644
--- a/examples/style.css
+++ b/examples/style.css
@@ -141,3 +141,15 @@ body {
-webkit-text-size-adjust: none;
}
+/* LayerSwitcher modifications */
+.olControlLayerSwitcher .layersDiv {
+ border-radius: 10px 0 0 10px;
+ padding-bottom: 10px;
+ background: #130085; /* fallback for IE - IE6 requires background shorthand*/
+ background: rgba(0, 60, 136, 0.75);
+ filter: alpha(opacity=80);
+}
+.olControlLayerSwitcher img {
+ opacity: 0.6;
+ filter: alpha(opacity=75);
+}
diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js
index 22be4f61bd..bd4585ecc2 100644
--- a/lib/OpenLayers.js
+++ b/lib/OpenLayers.js
@@ -156,6 +156,10 @@
"OpenLayers/Marker.js",
"OpenLayers/Marker/Box.js",
"OpenLayers/Popup.js",
+ "OpenLayers/Raster.js",
+ "OpenLayers/Raster/Grid.js",
+ "OpenLayers/Raster/Composite.js",
+ "OpenLayers/Raster/Operation.js",
"OpenLayers/Tile.js",
"OpenLayers/Tile/Image.js",
"OpenLayers/Tile/Image/IFrame.js",
@@ -168,6 +172,7 @@
"OpenLayers/Layer/Google/v3.js",
"OpenLayers/Layer/HTTPRequest.js",
"OpenLayers/Layer/Grid.js",
+ "OpenLayers/Layer/Raster.js",
"OpenLayers/Layer/MapGuide.js",
"OpenLayers/Layer/MapServer.js",
"OpenLayers/Layer/KaMap.js",
diff --git a/lib/OpenLayers/Control/DragFeature.js b/lib/OpenLayers/Control/DragFeature.js
index d8fb15f9ea..5300be8db5 100644
--- a/lib/OpenLayers/Control/DragFeature.js
+++ b/lib/OpenLayers/Control/DragFeature.js
@@ -314,6 +314,7 @@ OpenLayers.Control.DragFeature = OpenLayers.Class(OpenLayers.Control, {
* came from a mouseout, this may not be in the map viewport.
*/
doneDragging: function(pixel) {
+ this.layer.events.triggerEvent("featuremodified", {feature: this.feature});
this.onComplete(this.feature, pixel);
},
diff --git a/lib/OpenLayers/Layer/Raster.js b/lib/OpenLayers/Layer/Raster.js
new file mode 100644
index 0000000000..df06d07dad
--- /dev/null
+++ b/lib/OpenLayers/Layer/Raster.js
@@ -0,0 +1,132 @@
+/**
+ * @requires OpenLayers/Layer.js
+ * @requires OpenLayers/Raster/Composite.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Raster
+ *
+ * Inherits from:
+ * -
+ */
+OpenLayers.Layer.Raster = OpenLayers.Class(OpenLayers.Layer, {
+
+ needsUpdate: false,
+
+ initialize: function(config) {
+ config = config || {};
+ var data = config.data;
+ delete config.data;
+ OpenLayers.Layer.prototype.initialize.apply(this, [config.name, config]);
+
+ this.canvas = document.createElement("canvas");
+ this.canvas.style.position = "absolute";
+ this.div.appendChild(this.canvas);
+ this.context = this.canvas.getContext("2d");
+ if (data) {
+ this.setData(data);
+ }
+
+ },
+
+ setData: function(data) {
+ this.clearData();
+ this.data = data;
+ data.events.register("update", this, this.onDataUpdate);
+ },
+
+ clearData: function() {
+ if (this.data) {
+ this.data.events.unregister("update", this, this.onDataUpdate);
+ delete this.data;
+ }
+ },
+
+ moveTo: function() {
+ this.needsUpdate = true;
+ OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
+ window.setTimeout(OpenLayers.Function.bind(this.afterMoveTo, this), 0);
+ },
+
+ afterMoveTo: function() {
+ if (this.needsUpdate) {
+ this.onDataUpdate();
+ }
+ },
+
+ onDataUpdate: function() {
+ var map = this.map;
+ if (map) {
+ var size = map.getSize();
+ var cols = this.data.numCols();
+ var rows = this.data.numRows();
+ var style = map.layerContainerDiv.style;
+ this.canvas.width = cols;
+ this.canvas.height = rows;
+ this.canvas.style.top = (-parseInt(style.top)) + "px";
+ this.canvas.style.left = (-parseInt(style.left)) + "px";
+ this.canvas.style.width = size.w + "px";
+ this.canvas.style.height = size.h + "px";
+
+ var imageData = this.context.createImageData(cols, rows);
+ var data = imageData.data;
+
+ var mutator;
+ var mutatorTest = this.data.getValue(0,0);
+ if (!mutatorTest.length) {
+ mutator = function(value, i, j) {
+ var offset = (j * cols + i) << 2;
+ data[offset + 0] = value; // red
+ data[offset + 1] = value; // green
+ data[offset + 2] = value; // blue
+ data[offset + 3] = 255; // alpha
+ }
+ } else if (mutatorTest.length == 3) {
+ mutator = function(value, i, j) {
+ var offset = (j * cols + i) << 2;
+ data[offset + 0] = value[0] // red
+ data[offset + 1] = value[1]; // green
+ data[offset + 2] = value[2]; // blue
+ data[offset + 3] = 255; // alpha
+ }
+ } else {
+ mutator = function(value, i, j) {
+ var offset = (j * cols + i) << 2;
+ data[offset + 0] = value[0] // red
+ data[offset + 1] = value[1]; // green
+ data[offset + 2] = value[2]; // blue
+ data[offset + 3] = value[3]; // alpha
+ }
+ }
+ /*
+ // The mutators below are exclusive to the implementations above.
+ // While significantly faster, the conversion of the pipeline from
+ // pixels as Uint8[] to Uint32 breaks backwards compatibility.
+ // NOTE: symetric implementation in OpenLayers.Raster.Composite
+// if (data.buffer) {
+// var dataBuffer = new ArrayBuffer(data.length);
+// var data8 = new Uint8ClampedArray(dataBuffer);
+// var data32 = new Uint32Array(dataBuffer);
+// mutator = function(value, i, j) {
+// data32[j* cols + i] = value;
+// });
+// data.set(data8);
+// } else {
+// mutator = function(value, i, j) {
+// var offset = (j * cols + i) << 2;
+// data[offset + 0] = ( value & 0xff); // red
+// data[offset + 1] = ((value >> 8 ) & 0xff); // green
+// data[offset + 2] = ((value >> 16) & 0xff); // blue
+// data[offset + 3] = ((value >>> 24)); // alpha
+// });
+// }
+ */
+ this.data.forEach(mutator);
+ this.context.putImageData(imageData, 0, 0);
+ this.needsUpdate = false;
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Layer.Raster"
+
+});
diff --git a/lib/OpenLayers/Raster.js b/lib/OpenLayers/Raster.js
new file mode 100644
index 0000000000..2c20a7f346
--- /dev/null
+++ b/lib/OpenLayers/Raster.js
@@ -0,0 +1,4 @@
+/**
+ * @requires OpenLayers/SingleFile.js
+ */
+OpenLayers.Raster = {};
\ No newline at end of file
diff --git a/lib/OpenLayers/Raster/Composite.js b/lib/OpenLayers/Raster/Composite.js
new file mode 100644
index 0000000000..e2f041bab1
--- /dev/null
+++ b/lib/OpenLayers/Raster/Composite.js
@@ -0,0 +1,342 @@
+/**
+ * @requires OpenLayers/Raster/Grid.js
+ * @requires OpenLayers/Renderer/Canvas.js
+ */
+
+OpenLayers.Raster.Composite = OpenLayers.Class(OpenLayers.Raster.Grid, (function() {
+
+ var grids;
+
+ return {
+
+ /**
+ * Constructor: OpenLayers.Raster.Composite
+ */
+ initialize: function(config) {
+ if (config.grids) {
+ grids = config.grids;
+ delete config.grids;
+ }
+ OpenLayers.Raster.Grid.prototype.initialize.apply(this, [config]);
+ if (grids) {
+ for (var i=0, ii=grids.length; i= this.getCount()) {
+ throw new Error("Bad grid index.")
+ }
+ var composite = this;
+ return new OpenLayers.Raster.Grid({
+ numCols: function() {
+ return composite.numCols();
+ },
+ numRows: function() {
+ return composite.numRows();
+ },
+ getValue: function(col, row) {
+ return composite.getValue(col, row)[index];
+ }
+ });
+ },
+
+
+ CLASS_NAME: "OpenLayers.Raster.Composite"
+ };
+
+})());
+
+OpenLayers.Raster.Composite.fromLayer = function(layer, options) {
+ var composite;
+ if (layer instanceof OpenLayers.Layer.Grid) {
+ composite = OpenLayers.Raster.Composite.fromGridLayer(layer);
+ } else if (layer instanceof OpenLayers.Layer.Vector) {
+ composite = OpenLayers.Raster.Composite.fromVectorLayer(layer, options);
+ } else {
+ throw new Error("Only Grid or Vector type layers can be used to create a raster");
+ }
+ return composite;
+};
+
+OpenLayers.Raster.Composite.fromVectorLayer = function(layer, options) {
+
+ var mapping = options && options.mapping || function(feature) {
+ return [255, 255, 255, 255]
+ };
+
+ var container = document.createElement("div");
+ var renderer = new OpenLayers.Renderer.Canvas(container, {
+ hitDetection: false
+ });
+
+ var canvas = renderer.root;
+ var context = renderer.canvas;
+
+ var composite = new OpenLayers.Raster.Composite({
+ numCols: function() {
+ return canvas.width;
+ },
+ numRows: function() {
+ return canvas.height;
+ },
+ getCount: function() {
+ return 4;
+ },
+ getValue: function(col, row) {
+ var pixelArray = getPixelArray();
+ var cols = canvas.width;
+ var offset = 4 * (col + (row * cols));
+ return Array.prototype.slice.apply(pixelArray, [offset, offset+4]);
+ },
+ toDataURL: function() {
+ return canvas.toDataURL.apply(canvas, arguments);
+ }
+ });
+
+ var cache = {};
+ function getPixelArray() {
+ if (!cache.pixelArray) {
+ var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
+ cache.pixelArray = imageData.data;
+ }
+ return cache.pixelArray;
+ }
+
+ function hex(value) {
+ value = Math.max(0, Math.min(255, value));
+ return (3840 + value).toString(16).substring(1);
+ }
+
+ var style = new OpenLayers.Style({
+ stroke: false,
+ fillColor: "${getColor}",
+ fillOpacity: "${getOpacity}"
+ }, {context: {
+ getColor: function(feature) {
+ var rgba = mapping(feature);
+ return "#" +
+ hex(rgba[0]) +
+ hex(rgba[1]) +
+ hex(rgba[2]);
+ },
+ getOpacity: function(feature) {
+ var rgba = mapping(feature);
+ return rgba[3] / 255;
+ }
+ }});
+
+ var clone = new OpenLayers.Layer.Vector(null, {
+ styleMap: new OpenLayers.StyleMap(style),
+ renderer: renderer
+ });
+
+ function triggerUpdate() {
+ cache = {};
+ window.setTimeout(function() {
+ composite.events.triggerEvent("update");
+ }, 0);
+ }
+
+ function addFeatures(event) {
+ var features = event.features;
+ clone.addFeatures(features, {silent: true});
+
+ // features can only be added to one layer
+ // work around this by reassigning to original
+ for (var i=0, ii=features.length; i canvas.width ? cornerPixel.x + tileSize.w - canvas.width : 0;
+ var overwritey = cornerPixel.y + tileSize.h > canvas.height ? cornerPixel.y + tileSize.h - canvas.height : 0;
+
+ // only draw tile if it overlaps canvas...
+ if ((underwritex + overwritex) < tileSize.w && (underwritey + overwritey) < tileSize.h) {
+
+ // adjust source and destination values based on image overlap of canvas (required for IE 9)
+ var sx = underwritex;
+ var sy = underwritey;
+ var sw = tileSize.w - underwritex - overwritex;
+ var sh = tileSize.h - underwritey - overwritey;
+ var dx = underwritex > 0 ? 0 : cornerPixel.x;
+ var dy = underwritey > 0 ? 0 : cornerPixel.y;
+ var dw = tileSize.w - underwritex - overwritex;
+ var dh = tileSize.h - underwritey - overwritey;
+
+ context.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);
+ }
+ }
+ }
+ }
+
+ // defer context.getImageData call until needed...
+ composite.getValue = function(col, row) {
+ var width = canvas.width;
+ var data8 = context.getImageData(0, 0, width, canvas.height).data;
+ var accessor;
+ // generate closure with array access optimized dependent on broswer capability
+
+ // avoiding per-call array instantiation is an important optimization.
+ // given *current* architecture this is safe.
+ var pixel = [0,0,0,0];
+ accessor = function(col, row) {
+ var offset = (col + (row * width)) << 2;
+ pixel[3] = data8[offset + 3];
+ pixel[2] = data8[offset + 2];
+ pixel[1] = data8[offset + 1];
+ pixel[0] = data8[offset];
+ return pixel;
+ }
+ /*
+ // The accessors below are exclusive to the implementation above.
+ // While significantly faster, the conversion of the pipeline from
+ // pixels as Uint8[] to Uint32 breaks backwards compatibility.
+ // NOTE: symetric implementation in OpenLayers.Layer.Raster
+ if (data8.buffer) {
+ var data32 = new Uint32Array(data8.buffer);
+ accessor = function(col, row) {
+ var offset = (col + (row * width));
+ return data32[offset];
+ }
+ } else {
+ accessor = function(col, row) {
+ var offset = (col + (row * width)) << 2;
+ return data8[offset + 3] << 24 |
+ data8[offset + 2] << 16 |
+ data8[offset + 1] << 8 |
+ data8[offset];
+ }
+ }
+ */
+ // replace current function with optimized accessor
+ composite.getValue = accessor;
+ return accessor(col, row);
+ }
+ composite.events.triggerEvent("update");
+ }
+ }
+
+ if (layer.map) {
+ layer.map.events.register("moveend", null, deferredUpdate);
+ } else {
+ layer.events.register("added", null, function() {
+ layer.map.events.register("moveend", null, deferredUpdate);
+ });
+ }
+ layer.events.register("loadend", null, deferredUpdate);
+
+ return composite;
+
+};
diff --git a/lib/OpenLayers/Raster/Grid.js b/lib/OpenLayers/Raster/Grid.js
new file mode 100644
index 0000000000..ce82ec9a58
--- /dev/null
+++ b/lib/OpenLayers/Raster/Grid.js
@@ -0,0 +1,91 @@
+/**
+ * @requires OpenLayers/Raster.js
+ * @requires OpenLayers/BaseTypes/Class.js
+ */
+
+OpenLayers.Raster.Grid = OpenLayers.Class({
+
+ /**
+ * Constant: EVENT_TYPES
+ * {Array(String)} Supported application event types. Register a listener
+ * for a particular event with the following syntax:
+ * (code)
+ * grid.events.register(type, obj, listener);
+ * (end)
+ *
+ * Listeners will be called with a reference to an event object. The
+ * properties of this event depends on exactly what happened.
+ *
+ * Raster grid event types:
+ * update - Fired when the grid's underlying data is updated.
+ */
+ EVENT_TYPES: ["update"],
+
+ /**
+ * Constructor: OpenLayers.Raster.Grid
+ */
+ initialize: function(config) {
+ OpenLayers.Util.extend(this, config);
+ this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
+ },
+
+ /**
+ * Method: getValue
+ */
+ getValue: function(col, row) {
+ throw new Error("getValue must be defined")
+ },
+ /**
+ * APIMethod: numCols
+ */
+ numCols: function() {
+ throw new Error("numCols must be defined")
+ },
+ /**
+ * APIMethod: numRows
+ */
+ numRows: function() {
+ throw new Error("numRows must be defined")
+ },
+
+ /**
+ * APIMethod: forEach
+ * Iterate through call values in the grid. The provided function
+ * will be called with each cell value.
+ *
+ * Parameters:
+ * fn - {Function}
+ */
+ forEach: function(fn) {
+ var cols = this.numCols();
+ var rows = this.numRows();
+ for (var j=0; j 1) ? Composite : Grid;
+ var grid = new Constructor({
+ numCols: function() {
+ return getFirstGrid().numCols();
+ },
+ numRows: function() {
+ return getFirstGrid().numRows();
+ },
+ getValue: function(col, row) {
+ var values = new Array(len);
+ var arg;
+ for (var i=0; i