OpenLayers OpenLayers

Ticket #1083: graticule_v1.patch

File graticule_v1.patch, 14.0 kB (added by madair, 11 months ago)
  • examples/graticule.html

    old new  
     1<html xmlns="http://www.w3.org/1999/xhtml"> 
     2    <head> 
     3        <title>OpenLayers Graticule Example</title> 
     4 
     5        <link rel="stylesheet" href="../theme/default/style.css" type="text/css" /> 
     6        <link rel="stylesheet" href="style.css" type="text/css" /> 
     7        <style type="text/css"> 
     8            #map { 
     9                width: 600px; 
     10                height: 300px; 
     11                border: 1px solid black; 
     12                float:left; 
     13            } 
     14            #map2 { 
     15                width: 400px; 
     16                height: 400px; 
     17                border: 1px solid black; 
     18                float:left; 
     19            } 
     20        </style> 
     21        <script src="../lib/OpenLayers.js"></script> 
     22        <script src="http://proj4js.org/lib/proj4js-combined.js"></script> 
     23        <script type="text/javascript"> 
     24            Proj4js.defs["EPSG:42304"]="+title=Atlas of Canada, LCC +proj=lcc +lat_1=49 +lat_2=77 +lat_0=49 +lon_0=-95 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs"; 
     25             
     26            var map1, map2; 
     27            function init(){ 
     28              initLonLat(); 
     29              initProjected(); 
     30            } 
     31            function initLonLat(){ 
     32                map1 = new OpenLayers.Map('map', { 
     33                    controls: [ 
     34                      new OpenLayers.Control.Graticule(), 
     35                      new OpenLayers.Control.LayerSwitcher(), 
     36                      new OpenLayers.Control.PanZoomBar(), 
     37                      new OpenLayers.Control.Navigation() 
     38                      ] 
     39                }); 
     40 
     41                var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS", 
     42                    "http://labs.metacarta.com/wms/vmap0", 
     43                    {layers: 'basic'}, {wrapDateLine: true} ); 
     44 
     45                map1.addLayers([ol_wms]); 
     46                if (!map1.getCenter()) map1.zoomToMaxExtent(); 
     47            }; 
     48             
     49            function initProjected(){ 
     50                var extent = new OpenLayers.Bounds(-2200000,-712631,3072800,3840000); 
     51                var mapOptions = { 
     52                      controls: [ 
     53                      new OpenLayers.Control.Graticule({ 
     54                          labelled: false, 
     55                          targetSize: 200 
     56                        }), 
     57                        new OpenLayers.Control.LayerSwitcher(), 
     58                        new OpenLayers.Control.PanZoomBar(), 
     59                        new OpenLayers.Control.Navigation() 
     60                      ], 
     61                      //scales: tempScales, 
     62                      maxExtent: extent, 
     63                      maxResolution: 50000, 
     64                      units: 'm', 
     65                      projection: 'EPSG:42304' 
     66                }; 
     67                map2 = new OpenLayers.Map('map2', mapOptions); 
     68 
     69                var dm_wms = new OpenLayers.Layer.WMS( "DM Solutions Demo", 
     70                  "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap", { 
     71                     layers: "bathymetry", 
     72                     format: "image/png" 
     73                  },{ 
     74                      singleTile: true 
     75                  }); 
     76 
     77                map2.addLayers([dm_wms]); 
     78                if (!map2.getCenter()) map2.zoomToExtent(extent); 
     79            } 
     80        </script> 
     81    </head> 
     82    <body onload="init()"> 
     83        <h1 id="title">Graticule Example</h1> 
     84 
     85        <div id="tags"> 
     86        </div> 
     87 
     88        <p id="shortdesc"> 
     89            Adds a Graticule control to the map to display a grid of  
     90            latitude and longitude.  
     91        </p> 
     92 
     93        <div id="map" class="smallmap"></div> 
     94        <div id="map2" class="smallmap"></div> 
     95 
     96        <div id="docs"></div> 
     97    </body> 
     98</html> 
  • lib/OpenLayers/Control/Graticule.js

    old new  
     1/* Copyright (c) 2006-2007 MetaCarta, Inc., published under a modified BSD license. 
     2 * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt  
     3 * for the full text of the license. */ 
     4 
     5/** 
     6 * @requires OpenLayers/Control.js 
     7 */ 
     8 
     9/** 
     10 * Class: OpenLayers.Control.Graticule 
     11 * The Graticule displays a grid of latitude/longitude lines reprojected on 
     12 * the map.   
     13 *  
     14 * Inherits from: 
     15 *  - <OpenLayers.Control> 
     16 *   
     17 */ 
     18OpenLayers.Control.Graticule = OpenLayers.Class(OpenLayers.Control, { 
     19 
     20    /** 
     21    * APIProperty: intervals 
     22    * {Array(Float)} A list of possible graticule widths in degrees. 
     23    */ 
     24    intervals: [ 45, 30, 20, 10, 5, 2, 1, 
     25                 0.5, 0.2, 0.1, 0.05, 0.01,  
     26                 0.005, 0.002, 0.001 ], 
     27 
     28    /** 
     29     * APIProperty: displayInLayerSwitcher 
     30     * {Boolean} Allows the Graticule control to be switched on and off.  
     31     * defaults to true. 
     32     */ 
     33    displayInLayerSwitcher: true, 
     34 
     35    /** 
     36     * APIProperty: numPoints 
     37     * {Integer} The number of points to use in each graticule line.  Higher 
     38     * numbers result in a smoother curve for projected maps  
     39     */ 
     40    numPoints: 5, 
     41 
     42    /** 
     43     * APIProperty: targetSize 
     44     * {Integer} The maximum size of the grid in pixels on the map 
     45     */ 
     46    targetSize: 200, 
     47 
     48    /** 
     49     * APIProperty: labelled 
     50     * {Boolean} Should the graticule lines be labelled?. default=false 
     51     */ 
     52    labelled: true, 
     53 
     54    /** 
     55     * Property: gratLayer 
     56     * {OpenLayers.Layer.Vector} 
     57     */ 
     58    gratLayer: null, 
     59 
     60    /** 
     61     * Constructor: OpenLayers.Control.ScaleLine 
     62     * Create a new scale line control. 
     63     *  
     64     * Parameters: 
     65     * options - {Object} An optional object whose properties will be used 
     66     *     to extend the control. 
     67     */ 
     68    initialize: function(options) { 
     69        OpenLayers.Control.prototype.initialize.apply(this, [options]);      
     70    }, 
     71 
     72    /** 
     73     * Method: draw 
     74     *  
     75     * Returns: 
     76     * {DOMElement} 
     77     */ 
     78    draw: function() { 
     79        OpenLayers.Control.prototype.draw.apply(this, arguments); 
     80        if (!this.gratLayer) { 
     81            var gratStyle = new OpenLayers.Style({ 
     82                strokeColor: "black", 
     83                strokeWidth: 1, 
     84                strokeOpacity: 1, 
     85                label: "${gridLabel}", 
     86                align: "ct" 
     87              }, { 
     88              context: { 
     89                gridLabel: function(feature) { 
     90                  return feature.attributes.labelled ? 
     91                    OpenLayers.Util.getFormattedLonLat(feature.attributes.value):''; 
     92                } 
     93              } 
     94            }); 
     95            this.gratLayer = new OpenLayers.Layer.Vector("Graticule", { 
     96              styleMap: new OpenLayers.StyleMap(gratStyle), 
     97              displayInLayerSwitcher: this.displayInLayerSwitcher 
     98            }); 
     99            this.map.addLayer(this.gratLayer); 
     100        } 
     101        this.map.events.register('moveend', this, this.update); 
     102        this.update(); 
     103        return this.div; 
     104    }, 
     105 
     106    update: function() { 
     107        //wait for the map to be initialized before proceeding 
     108        var mapBounds = this.map.getExtent(); 
     109        if (!mapBounds) { 
     110          return; 
     111        } 
     112         
     113        //clear out the old grid 
     114        this.gratLayer.destroyFeatures(); 
     115         
     116        //get the projection objects required 
     117        var llProj = new OpenLayers.Projection("EPSG:4326"); 
     118        var mapProj = this.map.getProjectionObject(); 
     119        var mapRes = this.map.getResolution(); 
     120         
     121        //get the map center in EPSG:4326 
     122        var mapCenter = this.map.getCenter(); //lon and lat here are really map x and y 
     123        var mapCenterLL = new OpenLayers.Pixel(mapCenter.lon, mapCenter.lat); 
     124        OpenLayers.Projection.transform(mapCenterLL, mapProj, llProj); 
     125         
     126        /* This block of code determines the lon/lat interval to use for the 
     127         * grid by calculating the diagonal size of one grid cell at the map 
     128         * center.  Iterates through the intervals array until the diagonal 
     129         * length is less than the targetSize option. 
     130         */ 
     131        //find lat/lon interval that results in a grid of less than the target size 
     132        var testSq = this.targetSize*mapRes; 
     133        testSq *= testSq;   //compare squares rather than doing a square root to save time 
     134        var llInterval; 
     135        for (var i=0; i<this.intervals.length; ++i) { 
     136          llInterval = this.intervals[i];   //could do this for both x and y?? 
     137          var delta = llInterval/2;   
     138          var p1 = mapCenterLL.offset(new OpenLayers.Pixel(-delta, -delta));  //test coords in EPSG:4326 space 
     139          var p2 = mapCenterLL.offset(new OpenLayers.Pixel( delta,  delta)); 
     140          OpenLayers.Projection.transform(p1, llProj, mapProj); // convert them back to map projection 
     141          OpenLayers.Projection.transform(p2, llProj, mapProj); 
     142          var distSq = (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y); 
     143          if (distSq <= testSq) { 
     144            break; 
     145          } 
     146        } 
     147        //alert(llInterval); 
     148         
     149        //round the LL center to an even number based on the interval 
     150        mapCenterLL.x = Math.floor(mapCenterLL.x/llInterval)*llInterval; 
     151        mapCenterLL.y = Math.floor(mapCenterLL.y/llInterval)*llInterval; 
     152        //TODO adjust for minutses/seconds? 
     153         
     154        /* The following 2 blocks calculate the nodes of the grid along a  
     155         * line of constant longitude (then latitiude) running through the 
     156         * center of the map until it reaches the map edge.  The calculation 
     157         * goes from the center in both directions to the edge. 
     158         */ 
     159        //get the central longitude line, increment the latitude 
     160        var iter = 0 
     161        var centerLonPoints = [mapCenterLL.clone()]; 
     162        var newPoint = mapCenterLL.clone(); 
     163        var mapXY; 
     164        do { 
     165            newPoint = newPoint.offset(new OpenLayers.Pixel(0,llInterval)); 
     166            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj); 
     167            centerLonPoints.unshift(newPoint); 
     168        } while (mapBounds.containsPixel(mapXY) && ++iter<1000); 
     169        newPoint = mapCenterLL.clone(); 
     170        do {           
     171            newPoint = newPoint.offset(new OpenLayers.Pixel(0,-llInterval)); 
     172            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj); 
     173            centerLonPoints.push(newPoint); 
     174        } while (mapBounds.containsPixel(mapXY) && ++iter<1000); 
     175         
     176        //get the central latitude line, increment the longitude 
     177        iter = 0 
     178        var centerLatPoints = [mapCenterLL.clone()]; 
     179        newPoint = mapCenterLL.clone(); 
     180        do { 
     181            newPoint = newPoint.offset(new OpenLayers.Pixel(-llInterval, 0)); 
     182            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj); 
     183            centerLatPoints.unshift(newPoint); 
     184        } while (mapBounds.containsPixel(mapXY) && ++iter<1000); 
     185        newPoint = mapCenterLL.clone(); 
     186        do {           
     187            newPoint = newPoint.offset(new OpenLayers.Pixel(llInterval, 0)); 
     188            mapXY = OpenLayers.Projection.transform(newPoint.clone(), llProj, mapProj); 
     189            centerLatPoints.push(newPoint); 
     190        } while (mapBounds.containsPixel(mapXY) && ++iter<1000); 
     191         
     192        //now generate a line for each node in the central lat and lon lines 
     193        var lines = []; 
     194        for(var i=0; i < centerLatPoints.length; ++i) { 
     195          var lon = centerLatPoints[i].x; 
     196          var pointList = []; 
     197          for (var j=0; j < centerLonPoints.length; ++j) { 
     198            //TODO: increase the granularity for curved lines here 
     199            lat = centerLonPoints[j].y; 
     200            if (lat<-90 || lat>90) {  //latitudes only valid between -90 and 90 
     201              continue; 
     202            } 
     203            pointList.push(new OpenLayers.Geometry.Point(lon,lat)); 
     204          } 
     205          var geom = new OpenLayers.Geometry.LineString(pointList); 
     206          geom.transform(llProj, mapProj); 
     207          lines.push(new OpenLayers.Feature.Vector(geom, {value: lon, labelled: this.labelled})); 
     208        } 
     209        for (var j=0; j < centerLonPoints.length; ++j) { 
     210          lat = centerLonPoints[j].y; 
     211          if (lat<-90 || lat>90) {  //latitudes only valid between -90 and 90 
     212            continue; 
     213          } 
     214          var pointList = []; 
     215          for(var i=0; i < centerLatPoints.length; ++i) { 
     216            //TODO: increase the granularity for curved lines here 
     217            var lon = centerLatPoints[i].x; 
     218            pointList.push(new OpenLayers.Geometry.Point(lon,lat)); 
     219          } 
     220          var geom = new OpenLayers.Geometry.LineString(pointList); 
     221          geom.transform(llProj, mapProj); 
     222          lines.push(new OpenLayers.Feature.Vector(geom, {value: lat, labelled: this.labelled})); 
     223        } 
     224        this.gratLayer.addFeatures(lines); 
     225    }, 
     226     
     227    CLASS_NAME: "OpenLayers.Control.Graticule" 
     228}); 
     229 
     230OpenLayers.Util.getFormattedLonLat = function(coordinate) { 
     231    var abscoordinate = Math.abs(coordinate) 
     232    var coordinatedegrees = Math.floor(abscoordinate); 
     233 
     234    var coordinateminutes = (abscoordinate - coordinatedegrees)/(1/60); 
     235    var tempcoordinateminutes = coordinateminutes; 
     236    coordinateminutes = Math.floor(coordinateminutes); 
     237    var coordinateseconds = (tempcoordinateminutes - coordinateminutes)/(1/60); 
     238    coordinateseconds =  Math.round(coordinateseconds*10); 
     239    coordinateseconds /= 10; 
     240 
     241    if( coordinatedegrees < 10 ) { 
     242      coordinatedegrees = "0" + coordinatedegrees; 
     243    } 
     244 
     245    if( coordinateminutes < 10 ) { 
     246      coordinateminutes = "0" + coordinateminutes; 
     247    } 
     248 
     249    if( coordinateseconds < 10 ) { 
     250      coordinateseconds = "0" + coordinateseconds; 
     251    } 
     252    var str = coordinatedegrees + " ";  //get degree symbol here somehow for SVG/VML labelling 
     253    str += coordinateminutes + "'"; 
     254    str += coordinateseconds + '"'; 
     255    return str; 
     256}; 
     257