[fusion-commits] r1811 - in trunk: . layers/MapGuide lib lib/OpenLayers

svn_fusion at osgeo.org svn_fusion at osgeo.org
Thu Mar 5 12:50:39 EST 2009


Author: madair
Date: 2009-03-05 12:50:39 -0500 (Thu, 05 Mar 2009)
New Revision: 1811

Modified:
   trunk/config_dist.json
   trunk/layers/MapGuide/MapGuide.js
   trunk/lib/OpenLayers/OpenLayers.js
   trunk/lib/fusion.js
Log:
closes #221: add useAsyncOverlay flag to determine if the MG site implements the asynchronous version of GETDYNAMICOVERLAY API.
Also updates OpenLayers with new version of MapGUide layer

Modified: trunk/config_dist.json
===================================================================
--- trunk/config_dist.json	2009-03-05 15:54:57 UTC (rev 1810)
+++ trunk/config_dist.json	2009-03-05 17:50:39 UTC (rev 1811)
@@ -18,7 +18,9 @@
 	       with http and end with /mapguide.  If you have installed
 	       fusion inside the www directory of MapGuide, then you can
 	       leave this empty as it will be automatically calculated. */
-           "webTierUrl": ""
+           "webTierUrl": "",
+      /* for MapGuide OS version > 2.1 and MGE2010 and higher set this to true*/
+          "useAsyncOverlay": true
     },
     /* The MapServer section is required if you are installing fusion
        for MapServer. */

Modified: trunk/layers/MapGuide/MapGuide.js
===================================================================
--- trunk/layers/MapGuide/MapGuide.js	2009-03-05 15:54:57 UTC (rev 1810)
+++ trunk/layers/MapGuide/MapGuide.js	2009-03-05 17:50:39 UTC (rev 1811)
@@ -42,6 +42,7 @@
     bSelectionOn: false,
     oSelection: null,
     selectionAsOverlay: true,
+    useAsyncOverlay: false,
     defaultFormat: 'PNG',
 
     initialize: function(map, mapTag, isMapWidgetLayer) {
@@ -531,15 +532,18 @@
      * Returns an OpenLayers MapGuide layer object
      */
     createOLLayer: function(layerName, bIsBaseLayer, bSingleTile, behavior) {
-      /* prevent the useOverlay flag based on site version       */
-      if (( this.siteVersion[0] == 2 && this.siteVersion[1] < 1 ) || this.siteVersion[0] < 2) { //v2.0.0 or previous
+      /* prevent the useOverlay flag based on MapGuide config element */
+      this.useAsyncOverlay = Fusion.getConfigurationItem('mapguide', 'useAsyncOverlay');
+      if (!this.useAsyncOverlay) {          //v2.0.1 or earlier
         this.selectionAsOverlay = false;
       }
+      
       var layerOptions = {
         units: this.units,
         isBaseLayer: bIsBaseLayer,
         maxResolution: 'auto',
         useOverlay: this.selectionAsOverlay,
+        useAsyncOverlay: this.useAsyncOverlay,
         ratio: this.ratio
       };
       if ((behavior & 1) == 0 && !/WebKit/.test(navigator.userAgent)) {
@@ -572,7 +576,6 @@
           mapname: this._sMapname,
           format: this.imageFormat,
           behavior: behavior,
-          version: "2.0.0",
           clientagent: this.clientAgent
         };
         params.showLayers = this.aShowLayers.length > 0 ? this.aShowLayers.toString() : null;
@@ -594,6 +597,11 @@
           clientagent: this.clientAgent
         };
       }
+      
+      //Fix for IE6 PNG transparency
+      if (params.format && params.format.toLowerCase().indexOf('png') >= 0) {
+        layerOptions.alpha = true;
+      }
 
       //Fix for IE6 PNG transparency
       if (params.format && params.format.toLowerCase().indexOf('png') >= 0) {

Modified: trunk/lib/OpenLayers/OpenLayers.js
===================================================================
--- trunk/lib/OpenLayers/OpenLayers.js	2009-03-05 15:54:57 UTC (rev 1810)
+++ trunk/lib/OpenLayers/OpenLayers.js	2009-03-05 17:50:39 UTC (rev 1811)
@@ -224,6 +224,7 @@
             "OpenLayers/Layer/Markers.js",
             "OpenLayers/Layer/Text.js",
             "OpenLayers/Layer/WorldWind.js",
+            "OpenLayers/Layer/ArcGIS93Rest.js",
             "OpenLayers/Layer/WMS.js",
             "OpenLayers/Layer/WMS/Untiled.js",
             "OpenLayers/Layer/GeoRSS.js",
@@ -297,10 +298,15 @@
             "OpenLayers/Strategy/Cluster.js",
             "OpenLayers/Strategy/Paging.js",
             "OpenLayers/Strategy/BBOX.js",
+            "OpenLayers/Strategy/Save.js",
             "OpenLayers/Protocol.js",
             "OpenLayers/Protocol/HTTP.js",
             "OpenLayers/Protocol/SQL.js",
             "OpenLayers/Protocol/SQL/Gears.js",
+            "OpenLayers/Protocol/WFS.js",
+            "OpenLayers/Protocol/WFS/v1.js",
+            "OpenLayers/Protocol/WFS/v1_0_0.js",
+            "OpenLayers/Protocol/WFS/v1_1_0.js",
             "OpenLayers/Layer/PointTrack.js",
             "OpenLayers/Layer/GML.js",
             "OpenLayers/Style.js",
@@ -320,16 +326,22 @@
             "OpenLayers/Format/KML.js",
             "OpenLayers/Format/GeoRSS.js",
             "OpenLayers/Format/WFS.js",
+            "OpenLayers/Format/WFSDescribeFeatureType.js",
             "OpenLayers/Format/WKT.js",
             "OpenLayers/Format/OSM.js",
             "OpenLayers/Format/GPX.js",
+            "OpenLayers/Format/Filter.js",
+            "OpenLayers/Format/Filter/v1.js",
+            "OpenLayers/Format/Filter/v1_0_0.js",
+            "OpenLayers/Format/Filter/v1_1_0.js",
             "OpenLayers/Format/SLD.js",
             "OpenLayers/Format/SLD/v1.js",
             "OpenLayers/Format/SLD/v1_0_0.js",
             "OpenLayers/Format/SLD/v1.js",
-            "OpenLayers/Format/Filter.js",
-            "OpenLayers/Format/Filter/v1.js",
-            "OpenLayers/Format/Filter/v1_0_0.js",
+            "OpenLayers/Format/WFST.js",
+            "OpenLayers/Format/WFST/v1.js",
+            "OpenLayers/Format/WFST/v1_0_0.js",
+            "OpenLayers/Format/WFST/v1_1_0.js",
             "OpenLayers/Format/Text.js",
             "OpenLayers/Format/JSON.js",
             "OpenLayers/Format/GeoJSON.js",
@@ -337,6 +349,7 @@
             "OpenLayers/Format/WMC/v1.js",
             "OpenLayers/Format/WMC/v1_0_0.js",
             "OpenLayers/Format/WMC/v1_1_0.js",
+            "OpenLayers/Format/WMSGetFeatureInfo.js",
             "OpenLayers/Layer/WFS.js",
             "OpenLayers/Control/MouseToolbar.js",
             "OpenLayers/Control/NavToolbar.js",
@@ -724,7 +737,7 @@
     //
     if (!this.viewRequestID ||
         (this.map && this.viewRequestID == this.map.viewRequestID)) { 
-        this.style.backgroundColor = null;
+        this.style.backgroundColor ="transparent";
         this.style.display = "";  
     }
 };
@@ -1364,82 +1377,87 @@
 OpenLayers.INCHES_PER_UNIT["degrees"] = OpenLayers.INCHES_PER_UNIT.dd;
 OpenLayers.INCHES_PER_UNIT["nmi"] = 1852 * OpenLayers.INCHES_PER_UNIT.m;
 
-//CS-MAP units
+// Units from CS-Map
 OpenLayers.METERS_PER_INCH = 0.02540005080010160020;
-OpenLayers.INCHES_PER_UNIT["Inch"] = OpenLayers.INCHES_PER_UNIT.inches;
-OpenLayers.INCHES_PER_UNIT["Meter"] = 1.0/OpenLayers.METERS_PER_INCH;   //EPSG:9001
-OpenLayers.INCHES_PER_UNIT["Foot"] = 0.30480060960121920243/OpenLayers.METERS_PER_INCH;   //EPSG:9003
-OpenLayers.INCHES_PER_UNIT["IFoot"] = 0.30480000000000000000/OpenLayers.METERS_PER_INCH;   //EPSG:9002
-OpenLayers.INCHES_PER_UNIT["ClarkeFoot"] = 0.3047972651151/OpenLayers.METERS_PER_INCH;   //EPSG:9005
-OpenLayers.INCHES_PER_UNIT["SearsFoot"] = 0.30479947153867624624/OpenLayers.METERS_PER_INCH;   //EPSG:9041
-OpenLayers.INCHES_PER_UNIT["GoldCoastFoot"] = 0.30479971018150881758/OpenLayers.METERS_PER_INCH;   //EPSG:9094
-OpenLayers.INCHES_PER_UNIT["IInch"] = 0.02540000000000000000/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["MicroInch"] = 0.00002540000000000000/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Mil"] = 0.00000002540000000000/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Centimeter"] = 0.01000000000000000000/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Kilometer"] = 1000.00000000000000000000/OpenLayers.METERS_PER_INCH;   //EPSG:9036
-OpenLayers.INCHES_PER_UNIT["Yard"] = 0.91440182880365760731/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["SearsYard"] = 0.914398414616029/OpenLayers.METERS_PER_INCH;   //EPSG:9040
-OpenLayers.INCHES_PER_UNIT["IndianYard"] = 0.91439853074444079983/OpenLayers.METERS_PER_INCH;   //EPSG:9084
-OpenLayers.INCHES_PER_UNIT["IndianYd37"] = 0.91439523/OpenLayers.METERS_PER_INCH;   //EPSG:9085
-OpenLayers.INCHES_PER_UNIT["IndianYd62"] = 0.9143988/OpenLayers.METERS_PER_INCH;   //EPSG:9086
-OpenLayers.INCHES_PER_UNIT["IndianYd75"] = 0.9143985/OpenLayers.METERS_PER_INCH;   //EPSG:9087
-OpenLayers.INCHES_PER_UNIT["IndianFoot"] = 0.30479951/OpenLayers.METERS_PER_INCH;   //EPSG:9080
-OpenLayers.INCHES_PER_UNIT["IndianFt37"] = 0.30479841/OpenLayers.METERS_PER_INCH;   //EPSG:9081
-OpenLayers.INCHES_PER_UNIT["IndianFt62"] = 0.3047996/OpenLayers.METERS_PER_INCH;   //EPSG:9082
-OpenLayers.INCHES_PER_UNIT["IndianFt75"] = 0.3047995/OpenLayers.METERS_PER_INCH;   //EPSG:9083
-OpenLayers.INCHES_PER_UNIT["Mile"] = 1609.34721869443738887477/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["IYard"] = 0.91440000000000000000/OpenLayers.METERS_PER_INCH;   //EPSG:9096
-OpenLayers.INCHES_PER_UNIT["IMile"] = 1609.34400000000000000000/OpenLayers.METERS_PER_INCH;   //EPSG:9093
-OpenLayers.INCHES_PER_UNIT["NautM"] = 1852.00000000000000000000/OpenLayers.METERS_PER_INCH;   //EPSG:9030
-OpenLayers.INCHES_PER_UNIT["Lat-66"] = 110943.316488932731/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Lat-83"] = 110946.25736872234125/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Decimeter"] = 0.10000000000000000000/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Millimeter"] = 0.00100000000000000000/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Dekameter"] = 10.00000000000000000000/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Decameter"] = 10.00000000000000000000/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Hectometer"] = 100.00000000000000000000/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["GermanMeter"] = 1.0000135965/OpenLayers.METERS_PER_INCH;   //EPSG:9031
-OpenLayers.INCHES_PER_UNIT["CaGrid"] = 0.999738/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["ClarkeChain"] = 20.1166194976/OpenLayers.METERS_PER_INCH;   //EPSG:9038          20.11669506"
-OpenLayers.INCHES_PER_UNIT["GunterChain"] = 20.11684023368047/OpenLayers.METERS_PER_INCH;   //EPSG:9033
-OpenLayers.INCHES_PER_UNIT["BenoitChain"] = 20.116782494375872/OpenLayers.METERS_PER_INCH;   //EPSG:9062
-OpenLayers.INCHES_PER_UNIT["SearsChain"] = 20.11676512155/OpenLayers.METERS_PER_INCH;   //EPSG:9042
-OpenLayers.INCHES_PER_UNIT["ClarkeLink"] = 0.201166194976/OpenLayers.METERS_PER_INCH;   //EPSG:9039
-OpenLayers.INCHES_PER_UNIT["GunterLink"] = 0.2011684023368047/OpenLayers.METERS_PER_INCH;   //EPSG:9034
-OpenLayers.INCHES_PER_UNIT["BenoitLink"] = 0.20116782494375872/OpenLayers.METERS_PER_INCH;   //EPSG:9063
-OpenLayers.INCHES_PER_UNIT["SearsLink"] = 0.2011676512155/OpenLayers.METERS_PER_INCH;   //EPSG:9043
-OpenLayers.INCHES_PER_UNIT["Rod"] = 5.02921005842012/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["IntnlChain"] = 20.1168/OpenLayers.METERS_PER_INCH;   //EPSG:9097
-OpenLayers.INCHES_PER_UNIT["IntnlLink"] = 0.201168/OpenLayers.METERS_PER_INCH;   //EPSG:9098
-OpenLayers.INCHES_PER_UNIT["Perch"] = 5.02921005842012/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Pole"] = 5.02921005842012/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Furlong"] = 201.1684023368046/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Rood"] = 3.778266898/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["CapeFoot"] = 0.3047972615/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Brealey"] = 375.00000000000000000000/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["ModAmFt"] = 0.304812252984505969011938/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["Fathom"] = 1.8288/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["NautM-UK"] = 1853.184/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["50kilometers"] = 50000.0/OpenLayers.METERS_PER_INCH;
-OpenLayers.INCHES_PER_UNIT["150kilometers"] = 150000.0/OpenLayers.METERS_PER_INCH;
+OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT, {
+    "Inch": OpenLayers.INCHES_PER_UNIT.inches,
+    "Meter": 1.0 / OpenLayers.METERS_PER_INCH,   //EPSG:9001
+    "Foot": 0.30480060960121920243 / OpenLayers.METERS_PER_INCH,   //EPSG:9003
+    "IFoot": 0.30480000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9002
+    "ClarkeFoot": 0.3047972651151 / OpenLayers.METERS_PER_INCH,   //EPSG:9005
+    "SearsFoot": 0.30479947153867624624 / OpenLayers.METERS_PER_INCH,   //EPSG:9041
+    "GoldCoastFoot": 0.30479971018150881758 / OpenLayers.METERS_PER_INCH,   //EPSG:9094
+    "IInch": 0.02540000000000000000 / OpenLayers.METERS_PER_INCH,
+    "MicroInch": 0.00002540000000000000 / OpenLayers.METERS_PER_INCH,
+    "Mil": 0.00000002540000000000 / OpenLayers.METERS_PER_INCH,
+    "Centimeter": 0.01000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "Kilometer": 1000.00000000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9036
+    "Yard": 0.91440182880365760731 / OpenLayers.METERS_PER_INCH,
+    "SearsYard": 0.914398414616029 / OpenLayers.METERS_PER_INCH,   //EPSG:9040
+    "IndianYard": 0.91439853074444079983 / OpenLayers.METERS_PER_INCH,   //EPSG:9084
+    "IndianYd37": 0.91439523 / OpenLayers.METERS_PER_INCH,   //EPSG:9085
+    "IndianYd62": 0.9143988 / OpenLayers.METERS_PER_INCH,   //EPSG:9086
+    "IndianYd75": 0.9143985 / OpenLayers.METERS_PER_INCH,   //EPSG:9087
+    "IndianFoot": 0.30479951 / OpenLayers.METERS_PER_INCH,   //EPSG:9080
+    "IndianFt37": 0.30479841 / OpenLayers.METERS_PER_INCH,   //EPSG:9081
+    "IndianFt62": 0.3047996 / OpenLayers.METERS_PER_INCH,   //EPSG:9082
+    "IndianFt75": 0.3047995 / OpenLayers.METERS_PER_INCH,   //EPSG:9083
+    "Mile": 1609.34721869443738887477 / OpenLayers.METERS_PER_INCH,
+    "IYard": 0.91440000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9096
+    "IMile": 1609.34400000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9093
+    "NautM": 1852.00000000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9030
+    "Lat-66": 110943.316488932731 / OpenLayers.METERS_PER_INCH,
+    "Lat-83": 110946.25736872234125 / OpenLayers.METERS_PER_INCH,
+    "Decimeter": 0.10000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "Millimeter": 0.00100000000000000000 / OpenLayers.METERS_PER_INCH,
+    "Dekameter": 10.00000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "Decameter": 10.00000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "Hectometer": 100.00000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "GermanMeter": 1.0000135965 / OpenLayers.METERS_PER_INCH,   //EPSG:9031
+    "CaGrid": 0.999738 / OpenLayers.METERS_PER_INCH,
+    "ClarkeChain": 20.1166194976 / OpenLayers.METERS_PER_INCH,   //EPSG:9038
+    "GunterChain": 20.11684023368047 / OpenLayers.METERS_PER_INCH,   //EPSG:9033
+    "BenoitChain": 20.116782494375872 / OpenLayers.METERS_PER_INCH,   //EPSG:9062
+    "SearsChain": 20.11676512155 / OpenLayers.METERS_PER_INCH,   //EPSG:9042
+    "ClarkeLink": 0.201166194976 / OpenLayers.METERS_PER_INCH,   //EPSG:9039
+    "GunterLink": 0.2011684023368047 / OpenLayers.METERS_PER_INCH,   //EPSG:9034
+    "BenoitLink": 0.20116782494375872 / OpenLayers.METERS_PER_INCH,   //EPSG:9063
+    "SearsLink": 0.2011676512155 / OpenLayers.METERS_PER_INCH,   //EPSG:9043
+    "Rod": 5.02921005842012 / OpenLayers.METERS_PER_INCH,
+    "IntnlChain": 20.1168 / OpenLayers.METERS_PER_INCH,   //EPSG:9097
+    "IntnlLink": 0.201168 / OpenLayers.METERS_PER_INCH,   //EPSG:9098
+    "Perch": 5.02921005842012 / OpenLayers.METERS_PER_INCH,
+    "Pole": 5.02921005842012 / OpenLayers.METERS_PER_INCH,
+    "Furlong": 201.1684023368046 / OpenLayers.METERS_PER_INCH,
+    "Rood": 3.778266898 / OpenLayers.METERS_PER_INCH,
+    "CapeFoot": 0.3047972615 / OpenLayers.METERS_PER_INCH,
+    "Brealey": 375.00000000000000000000 / OpenLayers.METERS_PER_INCH,
+    "ModAmFt": 0.304812252984505969011938 / OpenLayers.METERS_PER_INCH,
+    "Fathom": 1.8288 / OpenLayers.METERS_PER_INCH,
+    "NautM-UK": 1853.184 / OpenLayers.METERS_PER_INCH,
+    "50kilometers": 50000.0 / OpenLayers.METERS_PER_INCH,
+    "150kilometers": 150000.0 / OpenLayers.METERS_PER_INCH
+});
+
 //unit abbreviations supported by PROJ.4
-OpenLayers.INCHES_PER_UNIT["mm"] = OpenLayers.INCHES_PER_UNIT["Meter"] / 1000.0;
-OpenLayers.INCHES_PER_UNIT["cm"] = OpenLayers.INCHES_PER_UNIT["Meter"] / 100.0;
-OpenLayers.INCHES_PER_UNIT["dm"] = OpenLayers.INCHES_PER_UNIT["Meter"] * 100.0;
-OpenLayers.INCHES_PER_UNIT["km"] = OpenLayers.INCHES_PER_UNIT["Meter"] * 1000.0;
-OpenLayers.INCHES_PER_UNIT["kmi"] = OpenLayers.INCHES_PER_UNIT["nmi"];    //International Nautical Mile
-OpenLayers.INCHES_PER_UNIT["fath"] = OpenLayers.INCHES_PER_UNIT["Fathom"]; //International Fathom
-OpenLayers.INCHES_PER_UNIT["ch"] = OpenLayers.INCHES_PER_UNIT["IntnlChain"];  //International Chain
-OpenLayers.INCHES_PER_UNIT["link"] = OpenLayers.INCHES_PER_UNIT["IntnlLink"]; //International Link
-OpenLayers.INCHES_PER_UNIT["us-in"] = OpenLayers.INCHES_PER_UNIT["inches"]; //U.S. Surveyor's Inch
-OpenLayers.INCHES_PER_UNIT["us-ft"] = OpenLayers.INCHES_PER_UNIT["Foot"];	//U.S. Surveyor's Foot
-OpenLayers.INCHES_PER_UNIT["us-yd"] = OpenLayers.INCHES_PER_UNIT["Yard"];	//U.S. Surveyor's Yard
-OpenLayers.INCHES_PER_UNIT["us-ch"] = OpenLayers.INCHES_PER_UNIT["GunterChain"]; //U.S. Surveyor's Chain
-OpenLayers.INCHES_PER_UNIT["us-mi"] = OpenLayers.INCHES_PER_UNIT["Mile"];   //U.S. Surveyor's Statute Mile
-OpenLayers.INCHES_PER_UNIT["ind-yd"] = OpenLayers.INCHES_PER_UNIT["IndianYd37"];  //Indian Yard
-OpenLayers.INCHES_PER_UNIT["ind-ft"] = OpenLayers.INCHES_PER_UNIT["IndianFt37"];  //Indian Foot
-OpenLayers.INCHES_PER_UNIT["ind-ch"] = 20.11669506/OpenLayers.METERS_PER_INCH;  //Indian Chain
+OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT, {
+    "mm": OpenLayers.INCHES_PER_UNIT["Meter"] / 1000.0,
+    "cm": OpenLayers.INCHES_PER_UNIT["Meter"] / 100.0,
+    "dm": OpenLayers.INCHES_PER_UNIT["Meter"] * 100.0,
+    "km": OpenLayers.INCHES_PER_UNIT["Meter"] * 1000.0,
+    "kmi": OpenLayers.INCHES_PER_UNIT["nmi"],    //International Nautical Mile
+    "fath": OpenLayers.INCHES_PER_UNIT["Fathom"], //International Fathom
+    "ch": OpenLayers.INCHES_PER_UNIT["IntnlChain"],  //International Chain
+    "link": OpenLayers.INCHES_PER_UNIT["IntnlLink"], //International Link
+    "us-in": OpenLayers.INCHES_PER_UNIT["inches"], //U.S. Surveyor's Inch
+    "us-ft": OpenLayers.INCHES_PER_UNIT["Foot"],	//U.S. Surveyor's Foot
+    "us-yd": OpenLayers.INCHES_PER_UNIT["Yard"],	//U.S. Surveyor's Yard
+    "us-ch": OpenLayers.INCHES_PER_UNIT["GunterChain"], //U.S. Surveyor's Chain
+    "us-mi": OpenLayers.INCHES_PER_UNIT["Mile"],   //U.S. Surveyor's Statute Mile
+    "ind-yd": OpenLayers.INCHES_PER_UNIT["IndianYd37"],  //Indian Yard
+    "ind-ft": OpenLayers.INCHES_PER_UNIT["IndianFt37"],  //Indian Foot
+    "ind-ch": 20.11669506 / OpenLayers.METERS_PER_INCH  //Indian Chain
+});
 
 /** 
  * Constant: DOTS_PER_INCH
@@ -1858,6 +1876,8 @@
  * options - {Object}
  *     displayClass - {String} Optional parameter.  A CSS class name(s) string
  *         to provide the CSS context of the rendered content.
+ *     containerElement - {DOMElement} Optional parameter. Insert the HTML to 
+ *         this node instead of the body root when calculating dimensions. 
  * 
  * Returns:
  * {OpenLayers.Size}
@@ -1872,6 +1892,9 @@
     container.style.position = "absolute";
     container.style.left = "-9999px";
         
+    var containerElement = (options && options.containerElement) 
+    	? options.containerElement : document.body;
+
     //fix a dimension, if specified.
     if (size) {
         if (size.w) {
@@ -1896,7 +1919,7 @@
     container.appendChild(content);
     
     // append container to body for rendering
-    document.body.appendChild(container);
+    containerElement.appendChild(container);
     
     // calculate scroll width of content and add corners and shadow width
     if (!w) {
@@ -1912,7 +1935,7 @@
 
     // remove elements
     container.removeChild(content);
-    document.body.removeChild(container);
+    containerElement.removeChild(container);
     
     return new OpenLayers.Size(w, h);
 };
@@ -2351,25 +2374,52 @@
         if(!context) {
             context = window;
         }
-        var tokens = template.split("${");
-        var item, last, replacement;
-        for(var i=1, len=tokens.length; i<len; i++) {
-            item = tokens[i];
-            last = item.indexOf("}"); 
-            if(last > 0) {
-                replacement = context[item.substring(0, last)];
-                if(typeof replacement == "function") {
-                    replacement = args ?
-                        replacement.apply(null, args) :
-                        replacement();
+
+        // Example matching: 
+        // str   = ${foo.bar}
+        // match = foo.bar
+        var replacer = function(str, match) {
+            var replacement;
+
+            // Loop through all subs. Example: ${a.b.c}
+            // 0 -> replacement = context[a];
+            // 1 -> replacement = context[a][b];
+            // 2 -> replacement = context[a][b][c];
+            var subs = match.split(/\.+/);
+            for (var i=0; i< subs.length; i++) {
+                if (i == 0) {
+                    replacement = context;
                 }
-                tokens[i] = replacement + item.substring(++last); 
+
+                replacement = replacement[subs[i]];
+            }
+
+            if(typeof replacement == "function") {
+                replacement = args ?
+                    replacement.apply(null, args) :
+                    replacement();
+            }
+
+            // If replacement is undefined, return the string 'undefined'.
+            // This is a workaround for a bugs in browsers not properly 
+            // dealing with non-participating groups in regular expressions:
+            // http://blog.stevenlevithan.com/archives/npcg-javascript
+            if (typeof replacement == 'undefined') {
+                return 'undefined';
             } else {
-                tokens[i] = "${" + item;
+                return replacement; 
             }
-        }
-        return tokens.join("");
+        };
+
+        return template.replace(OpenLayers.String.tokenRegEx, replacer);
     },
+
+    /**
+     * Property: OpenLayers.String.tokenRegEx
+     * Used to find tokens in a string.
+     * Examples: ${a}, ${a.b.c}, ${a-b}, ${5}
+     */
+    tokenRegEx:  /\${([\w.]+?)}/g,
     
     /**
      * Property: OpenLayers.String.numberRegEx
@@ -2394,6 +2444,18 @@
      */
     isNumeric: function(value) {
         return OpenLayers.String.numberRegEx.test(value);
+    },
+    
+    /**
+     * APIFunction: numericIf
+     * Converts a string that appears to be a numeric value into a number.
+     * 
+     * Returns
+     * {Number|String} a Number if the passed value is a number, a String
+     *     otherwise. 
+     */
+    numericIf: function(value) {
+        return OpenLayers.String.isNumeric(value) ? parseFloat(value) : value;
     }
 
 };
@@ -2745,6 +2807,8 @@
  * To create a new OpenLayers-style class with multiple inheritance, use the
  *     following syntax:
  * > var MyClass = OpenLayers.Class(Class1, Class2, prototype);
+ * Note that instanceof reflection will only reveil Class1 as superclass.
+ * Class2 ff are mixins.
  *
  */
 OpenLayers.Class = function() {
@@ -2761,9 +2825,21 @@
         }
     };
     var extended = {};
-    var parent;
+    var parent, initialize;
     for(var i=0, len=arguments.length; i<len; ++i) {
         if(typeof arguments[i] == "function") {
+            // make the class passed as the first argument the superclass
+            if(i == 0 && len > 1) {
+                // replace the initialize method with an empty function,
+                // because we do not want to create a real instance here
+                initialize = arguments[i].prototype.initialize;
+                arguments[i].prototype.initialize = function() {};
+                // the line below makes sure that the new class has a
+                // superclass
+                extended = new arguments[i];
+                // restore the original initialize method
+                arguments[i].prototype.initialize = initialize;
+            }
             // get the prototype of the superclass
             parent = arguments[i].prototype;
         } else {
@@ -5311,8 +5387,14 @@
         var preparedHTML = "<div class='" + this.contentDisplayClass+ "'>" + 
             this.contentDiv.innerHTML + 
             "<div>";
+ 
+        var containerElement = (this.map) ? this.map.layerContainerDiv
+        								  : document.body;
         var realSize = OpenLayers.Util.getRenderedDimensions(
-            preparedHTML, null, { displayClass: this.displayClass }
+            preparedHTML, null,	{
+                displayClass: this.displayClass,
+                containerElement: containerElement
+            }
         );
 
         // is the "real" size of the div is safe to display in our map?
@@ -5341,8 +5423,10 @@
                 //content is clipped in only one direction, so we need to 
                 // run getRenderedDimensions() again with a fixed dimension
                 var clippedSize = OpenLayers.Util.getRenderedDimensions(
-                    preparedHTML, fixedSize, 
-                    { displayClass: this.contentDisplayClass }
+                    preparedHTML, fixedSize, {
+                        displayClass: this.contentDisplayClass,
+                        containerElement: containerElement
+                    }
                 );
                 
                 //if the clipped size is still the same as the safeSize, 
@@ -6220,7 +6304,15 @@
         };
         
         // send request (optionally with data) and return
-        request.send(config.data);
+        // call in a timeout for asynchronous requests so the return is
+        // available before readyState == 4 for cached docs
+        if(config.async === false) {
+            request.send(config.data);
+        } else {
+            window.setTimeout(function(){
+                request.send(config.data);
+            }, 0);
+        }
         return request;
     },
     
@@ -6688,7 +6780,12 @@
 
 /**
  * Class: OpenLayers.Control.ArgParser
- * 
+ * The ArgParser control adds location bar querystring parsing functionality 
+ * to an OpenLayers Map.
+ * When added to a Map control, on a page load/refresh, the Map will 
+ * automatically take the href string and parse it for lon, lat, zoom, and 
+ * layers information. 
+ *
  * Inherits from:
  *  - <OpenLayers.Control>
  */
@@ -6716,6 +6813,7 @@
      * APIProperty: displayProjection
      * {<OpenLayers.Projection>} Requires proj4js support. 
      *     Projection used when reading the coordinates from the URL. This will
+     *
      *     reproject the map coordinates from the URL into the map's
      *     projection.
      *
@@ -6851,7 +6949,10 @@
 
 /**
  * Class: OpenLayers.Control.PanZoom
- * 
+ * The PanZoom is a visible control, composed of a
+ * <OpenLayers.Control.PanPanel> and a <OpenLayers.Control.ZoomPanel>. By
+ * default it is drawn in the upper left corner of the map.
+ *
  * Inherits from:
  *  - <OpenLayers.Control>
  */
@@ -7820,17 +7921,19 @@
         }
         
         if (!this.element.scrolls) {
-            this.element.scrolls = [];
-            this.element.scrolls[0] = (document.documentElement.scrollLeft
-                         || document.body.scrollLeft);
-            this.element.scrolls[1] = (document.documentElement.scrollTop
-                         || document.body.scrollTop);
+            this.element.scrolls = [
+                (document.documentElement.scrollLeft
+                         || document.body.scrollLeft),
+                (document.documentElement.scrollTop
+                         || document.body.scrollTop)
+            ];
         }
 
         if (!this.element.lefttop) {
-            this.element.lefttop = [];
-            this.element.lefttop[0] = (document.documentElement.clientLeft || 0);
-            this.element.lefttop[1] = (document.documentElement.clientTop || 0);
+            this.element.lefttop = [
+                (document.documentElement.clientLeft || 0),
+                (document.documentElement.clientTop  || 0)
+            ];
         }
         
         if (!this.element.offsets) {
@@ -7902,6 +8005,20 @@
     internalProjection: null,
 
     /**
+     * APIProperty: data
+     * {Object} When <keepData> is true, this is the parsed string sent to
+     *     <read>.
+     */
+    data: null,
+
+    /**
+     * APIProperty: keepData
+     * {Object} Maintain a reference (<data>) to the most recently read data.
+     *     Default is false.
+     */
+    keepData: false,
+
+    /**
      * Constructor: OpenLayers.Format
      * Instances of this class are not useful.  See one of the subclasses.
      *
@@ -7909,6 +8026,10 @@
      * options - {Object} An optional object with properties to set on the
      *           format
      *
+     * Valid options:
+     * keepData - {Boolean} If true, upon <read>, the data property will be
+     *     set to the parsed object (e.g. the json or xml object).
+     *
      * Returns:
      * An instance of OpenLayers.Format
      */
@@ -8307,8 +8428,10 @@
      *     pro4js projection object. 
      *
      * Parameters:
-     * options - {Object} An optional object with properties to set on the
-     *     format
+     * projCode - {String} A string identifying the Well Known Identifier for
+     *    the projection.
+     * options - {Object} An optional object to set additional properties
+     *     on the layer.
      *
      * Returns:
      * {<OpenLayers.Projection>} A projection object.
@@ -9412,12 +9535,19 @@
         // place it. Note that this operation is O(log(n)). If there's a
         // performance problem (when dragging, for instance) this is
         // likely where it would be.
-        var insert = this.indexer ? this.indexer.insert(node) : null;
-
-        if(insert) {
-            this.root.insertBefore(node, insert);
+        if (this.indexer) {
+            var insert = this.indexer.insert(node);
+            if (insert) {
+                this.root.insertBefore(node, insert);
+            } else {
+                this.root.appendChild(node);
+            }
         } else {
-            this.root.appendChild(node);
+            // if there's no indexer, simply append the node to root,
+            // but only if the node is a new one
+            if (node.parentNode !== this.root){ 
+                this.root.appendChild(node);
+            }
         }
         
         this.postDraw(node);
@@ -11441,8 +11571,6 @@
      *  - *move* triggered after each drag, pan, or zoom
      *  - *moveend* triggered after a drag, pan, or zoom completes
      *  - *zoomend* triggered after a zoom completes
-     *  - *popupopen* triggered after a popup opens
-     *  - *popupclose* triggered after a popup opens
      *  - *addmarker* triggered after a marker has been added
      *  - *removemarker* triggered after a marker has been removed
      *  - *clearmarkers* triggered after markers have been cleared
@@ -11738,7 +11866,7 @@
     eventListeners: null,
 
     /**
-     * Property: panMethod
+     * APIProperty: panMethod
      * {Function} The Easing function to be used for tweening.  Default is
      * OpenLayers.Easing.Expo.easeOut. Setting this to 'null' turns off
      * animated panning.
@@ -14462,7 +14590,7 @@
      * {DOMElement} The element to which we'll add the symbol definitions
      */
     createDefs: function() {
-        var defs = this.nodeFactory("ol-renderer-defs", "defs");
+        var defs = this.nodeFactory(this.container.id + "_defs", "defs");
         this.rendererRoot.appendChild(defs);
         return defs;
     },
@@ -15997,6 +16125,8 @@
                 this.backBufferTile.resolution = this.layer.getResolution();
                 this.backBufferTile.renderTile();
             }
+
+            this.backBufferTile.hide();
         }
     },
     
@@ -16289,8 +16419,10 @@
 
 /**
  * Class: OpenLayers.Control.OverviewMap
- * Create an overview map to display the extent of your main map and provide
- * additional navigation control.  Create a new overview map with the
+ * The OverMap control creates a small overview map, useful to display the 
+ * extent of a zoomed map and your main map and provide additional 
+ * navigation options to the User.  By default the overview map is drawn in
+ * the lower right corner of the main map. Create a new overview map with the
  * <OpenLayers.Control.OverviewMap> constructor.
  *
  * Inerits from:
@@ -16357,24 +16489,33 @@
     /**
      * APIProperty: minRatio
      * {Float} The ratio of the overview map resolution to the main map
-     * resolution at which to zoom farther out on the overview map.
+     *     resolution at which to zoom farther out on the overview map.
      */
     minRatio: 8,
 
     /**
      * APIProperty: maxRatio
      * {Float} The ratio of the overview map resolution to the main map
-     * resolution at which to zoom farther in on the overview map.
+     *     resolution at which to zoom farther in on the overview map.
      */
     maxRatio: 32,
     
     /**
      * APIProperty: mapOptions
      * {Object} An object containing any non-default properties to be sent to
-     * the overview map's map constructor.  These should include any non-default
-     * options that the main map was constructed with.
+     *     the overview map's map constructor.  These should include any
+     *     non-default options that the main map was constructed with.
      */
     mapOptions: null,
+
+    /**
+     * APIProperty: autoPan
+     * {Boolean} Always pan the overview map, so the extent marker remains in
+     *     the center.  Default is false.  If true, when you drag the extent
+     *     marker, the overview map will update itself so the marker returns
+     *     to the center.
+     */
+    autoPan: false,
     
     /**
      * Property: handlers
@@ -16666,7 +16807,7 @@
             this.createMap();
         }
         
-        if(!this.isSuitableOverview()) {
+        if(this.autoPan || !this.isSuitableOverview()) {
             this.updateOverview();
         }
         
@@ -17975,7 +18116,7 @@
      *
      * Parameters:
      * control - {<OpenLayers.Control>} 
-     * layers - {Array(<OpenLayers.Layer.Vector>)}
+     * layer - {<OpenLayers.Layer.Vector>}
      * callbacks - {Object} An object with a 'over' property whos value is
      *     a function to be called when the mouse is over a feature. The 
      *     callback should expect to recieve a single argument, the feature.
@@ -18088,18 +18229,32 @@
      * {Boolean} The event occurred over a relevant feature.
      */
     handle: function(evt) {
+        if(this.feature && !this.feature.layer) {
+            // feature has been destroyed
+            this.feature = null;
+        }
         var type = evt.type;
         var handled = false;
         var previouslyIn = !!(this.feature); // previously in a feature
         var click = (type == "click" || type == "dblclick");
         this.feature = this.layer.getFeatureFromEvent(evt);
-        if(this.feature && this.feature.layer) {
+        if(this.feature && !this.feature.layer) {
+            // feature has been destroyed
+            this.feature = null;
+        }
+        if(this.lastFeature && !this.lastFeature.layer) {
+            // last feature has been destroyed
+            this.lastFeature = null;
+        }
+        if(this.feature) {
             var inNew = (this.feature != this.lastFeature);
             if(this.geometryTypeMatches(this.feature)) {
                 // in to a feature
                 if(previouslyIn && inNew) {
                     // out of last feature and in to another
-                    this.triggerCallback(type, 'out', [this.lastFeature]);
+                    if(this.lastFeature) {
+                        this.triggerCallback(type, 'out', [this.lastFeature]);
+                    }
                     this.triggerCallback(type, 'in', [this.feature]);
                 } else if(!previouslyIn || click) {
                     // in feature for the first time
@@ -18109,7 +18264,7 @@
                 handled = true;
             } else {
                 // not in to a feature
-                if(previouslyIn && inNew || (click && this.lastFeature)) {
+                if(this.lastFeature && (previouslyIn && inNew || click)) {
                     // out of last feature for the first time
                     this.triggerCallback(type, 'out', [this.lastFeature]);
                 }
@@ -18121,8 +18276,7 @@
                 this.feature = null;
             }
         } else {
-            if(this.lastFeature && this.lastFeature.layer &&
-               (previouslyIn || click)) {
+            if(this.lastFeature && (previouslyIn || click)) {
                 this.triggerCallback(type, 'out', [this.lastFeature]);
             }
         }
@@ -18282,21 +18436,21 @@
 
     /**
      * APIProperty: stopMove
-     * {Boolean} Stop other listeners from being notified on mousemoves.
+     * {Boolean} - Stop other listeners from being notified on mousemoves.
      *      Default is false.
      */
     stopMove: false,
 
     /**
      * Property: px
-     * {<OpenLayers.Pixel>} The location of the last mousemove, expressed
+     * {<OpenLayers.Pixel>} - The location of the last mousemove, expressed
      *      in pixels.
      */
     px: null,
 
     /**
      * Property: timerId
-     * {Number} The id of the timer.
+     * {Number} - The id of the timer.
      */
     timerId: null,
  
@@ -18308,10 +18462,11 @@
      * control - {<OpenLayers.Control>} The control that initialized this
      *     handler.  The control is assumed to have a valid map property; that
      *     map is used in the handler's own setMap method.
-     * callbacks - {Object} An object whose properties correspond to abstracted
-     *     events or sequences of browser events.  The values for these
-     *     properties are functions defined by the control that get called by
-     *     the handler.
+     * callbacks - {Object} An object with keys corresponding to callbacks
+     *     that will be called by the handler. The callbacks should
+     *     expect to receive a single argument, the event. Callbacks for
+     *     'move', the mouse is moving, and 'pause', the mouse is pausing,
+     *     are supported.
      * options - {Object} An optional object whose properties will be set on
      *     the handler.
      */
@@ -19631,7 +19786,7 @@
         if(this.map.fractionalZoom) {
             var low = Math.floor(zoom);
             var high = Math.ceil(zoom);
-            resolution = this.resolutions[high] +
+            resolution = this.resolutions[low] -
                 ((zoom-low) * (this.resolutions[low]-this.resolutions[high]));
         } else {
             resolution = this.resolutions[Math.round(zoom)];
@@ -19679,7 +19834,7 @@
             }
             var dRes = highRes - lowRes;
             if(dRes > 0) {
-                zoom = lowZoom + ((resolution - lowRes) / dRes);
+                zoom = lowZoom + ((highRes - resolution) / dRes);
             } else {
                 zoom = lowZoom;
             }
@@ -19973,7 +20128,7 @@
 
 /**
  * Class: OpenLayers.Control.DragPan
- * DragPan control.
+ * The DragPan control pans the map with a drag of the mouse.
  *
  * Inherits from:
  *  - <OpenLayers.Control>
@@ -20100,6 +20255,15 @@
      */
     attributes: null,
 
+    /**
+     * Property: bounds
+     * {<OpenLayers.Bounds>} The box bounding that feature's geometry, that
+     *     property can be set by an <OpenLayers.Format> object when
+     *     deserializing the feature, so in most cases it represents an
+     *     information set by the server. 
+     */
+    bounds: null,
+
     /** 
      * Property: state 
      * {String} 
@@ -20350,38 +20514,33 @@
 /**
  * Constant: OpenLayers.Feature.Vector.style
  * OpenLayers features can have a number of style attributes. The 'default' 
- *     style will typically be used if no other style is specified.
+ *     style will typically be used if no other style is specified. These
+ *     styles correspond for the most part, to the styling properties defined
+ *     by the SVG standard. 
+ *     Information on fill properties: http://www.w3.org/TR/SVG/painting.html#FillProperties
+ *     Information on stroke properties: http://www.w3.org/TR/SVG/painting.html#StrokeProperties
  *
- * Default style properties:
- *
- *  - fillColor: "#ee9900",
- *  - fillOpacity: 0.4, 
- *  - hoverFillColor: "white",
- *  - hoverFillOpacity: 0.8,
- *  - strokeColor: "#ee9900",
- *  - strokeOpacity: 1,
- *  - strokeWidth: 1,
- *  - strokeLinecap: "round",  [butt | round | square]
- *  - strokeDashstyle: "solid", [dot | dash | dashdot | longdash | longdashdot | solid]
- *  - hoverStrokeColor: "red",
- *  - hoverStrokeOpacity: 1,
- *  - hoverStrokeWidth: 0.2,
- *  - pointRadius: 6,
- *  - hoverPointRadius: 1,
- *  - hoverPointUnit: "%",
- *  - pointerEvents: "visiblePainted"
- *  - cursor: ""
- *
- * Other style properties that have no default values:
- *
- *  - externalGraphic,
- *  - graphicWidth,
- *  - graphicHeight,
- *  - graphicOpacity,
- *  - graphicXOffset,
- *  - graphicYOffset,
- *  - graphicName,
- *  - display
+ * Symbolizer properties:
+ * fillColor - {String} Hex fill color.  Default is "#ee9900".
+ * fillOpacity - {Number} Fill opacity (0-1).  Default is 0.4 
+ * strokeColor - {String} Hex stroke color.  Default is "#ee9900".
+ * strokeOpacity - {Number} Stroke opacity (0-1).  Default is 1.
+ * strokeWidth - {Number} Pixel stroke width.  Default is 1.
+ * strokeLinecap - {String} Stroke cap type.  Default is "round".  [butt | round | square]
+ * strokeDashstyle - {String} Stroke dash style.  Default is "solid". [dot | dash | dashdot | longdash | longdashdot | solid]
+ * pointRadius - {Number} Pixel point radius.  Default is 6.
+ * pointerEvents - {String}  Default is "visiblePainted".
+ * cursor - {String} Default is "".
+ * externalGraphic - {String} Url to an external graphic that will be used for rendering points.
+ * graphicWidth - {Number} Pixel width for sizing an external graphic.
+ * graphicHeight - {Number} Pixel height for sizing an external graphic.
+ * graphicOpacity - {Number} Opacity (0-1) for an external graphic.
+ * graphicXOffset - {Number} Pixel offset along the positive x axis for displacing an external graphic.
+ * graphicYOffset - {Number} Pixel offset along the positive y axis for displacing an external graphic.
+ * graphicZIndex - {Number} The integer z-index value to use in rendering.
+ * graphicName - {String} Named graphic to use when rendering points.  Supported values include "circle" (default),
+ *     "square", "star", "x", "cross", "triangle".
+ * display - {String} Symbolizers will have no effect if display is set to "none".  All other values have no effect.
  */ 
 OpenLayers.Feature.Vector.style = {
     'default': {
@@ -20550,7 +20709,7 @@
 
         // depending on the box model, modify width and height to take borders
         // of the box into account
-        var box = this.getBoxCharacteristics(deltaX, deltaY);
+        var box = this.getBoxCharacteristics();
         if (box.newBoxModel) {
             if (xy.x > startX) {
                 this.zoomBox.style.width =
@@ -20621,7 +20780,17 @@
         }
     },
     
-    getBoxCharacteristics: function(dx, dy) {
+    /**
+     * Method: getCharacteristics
+     * Determines offset and box model for a box.
+     * 
+     * Returns:
+     * {Object} a hash with the following properties:
+     *     - xOffset - Corner offset in x-direction
+     *     - yOffset - Corner offset in y-direction
+     *     - newBoxModel - true for all browsers except IE in quirks mode
+     */
+    getBoxCharacteristics: function() {
         if (!this.boxCharacteristics) {
             var xOffset = parseInt(OpenLayers.Element.getStyle(this.zoomBox,
                 "border-left-width")) + parseInt(OpenLayers.Element.getStyle(
@@ -20923,6 +21092,12 @@
      */
     up: function(evt) {
         this.finalize();
+        // the mouseup method of superclass doesn't call the
+        // "done" callback if there's been no move between
+        // down and up
+        if (this.start == this.last) {
+            this.callback("done", [evt.xy]);
+        }
     },
 
     /**
@@ -22058,7 +22233,7 @@
     isBaseLayer: false,
     
     /** 
-     * Property: markers 
+     * APIProperty: markers 
      * {Array(<OpenLayers.Marker>)} internal marker list 
      */
     markers: null,
@@ -22402,7 +22577,8 @@
 
 /**
  * Class: OpenLayers.Control.DrawFeature
- * Draws features on a vector layer when active.
+ * The DrawFeature control draws point, line or polygon features on a vector
+ * layer when active.
  *
  * Inherits from:
  *  - <OpenLayers.Control>
@@ -22458,9 +22634,26 @@
         );
         
         OpenLayers.Control.prototype.initialize.apply(this, [options]);
-        this.callbacks = OpenLayers.Util.extend({done: this.drawFeature},
-                                                this.callbacks);
+        this.callbacks = OpenLayers.Util.extend(
+            {
+                done: this.drawFeature,
+                modify: function(vertex, feature) {
+                    this.layer.events.triggerEvent(
+                        "sketchmodified", {vertex: vertex, feature: feature}
+                    );
+                }
+            },
+            this.callbacks
+        );
         this.layer = layer;
+        var sketchStyle = this.layer.styleMap && this.layer.styleMap.styles.temporary;
+        if(sketchStyle) {
+            this.handlerOptions = this.handlerOptions || {};
+            this.handlerOptions.layerOptions = OpenLayers.Util.applyDefaults(
+                this.handlerOptions.layerOptions,
+                {styleMap: new OpenLayers.StyleMap({"default": sketchStyle})}
+            );
+        }
         this.handler = new handler(this, this.callbacks, this.handlerOptions);
     },
 
@@ -22469,10 +22662,15 @@
      */
     drawFeature: function(geometry) {
         var feature = new OpenLayers.Feature.Vector(geometry);
-        feature.state = OpenLayers.State.INSERT;
-        this.layer.addFeatures([feature]);
-        this.featureAdded(feature);
-        this.events.triggerEvent("featureadded",{feature : feature});
+        var proceed = this.layer.events.triggerEvent(
+            "sketchcomplete", {feature: feature}
+        );
+        if(proceed !== false) {
+            feature.state = OpenLayers.State.INSERT;
+            this.layer.addFeatures([feature]);
+            this.featureAdded(feature);
+            this.events.triggerEvent("featureadded",{feature : feature});
+        }
     },
 
     CLASS_NAME: "OpenLayers.Control.DrawFeature"
@@ -22742,6 +22940,9 @@
 
 /**
  * Class: OpenLayers.Control.ZoomBox
+ * The ZoomBox control enables zooming directly to a given extent, by drawing 
+ * a box on the map. The box is drawn by holding down shift, whilst dragging 
+ * the mouse.
  *
  * Inherits from:
  *  - <OpenLayers.Control>
@@ -23297,6 +23498,13 @@
 
             // move the ToS and branding stuff up to the pane
             // thanks a *mil* Erik for thinking of this
+            var termsOfUse = this.div.lastChild;
+            this.div.removeChild(termsOfUse);
+            this.pane.appendChild(termsOfUse);
+            termsOfUse.className = "olLayerGoogleCopyright";
+            termsOfUse.style.right = "";
+            termsOfUse.style.bottom = "";
+
             var poweredBy = this.div.lastChild;
             this.div.removeChild(poweredBy);
             this.pane.appendChild(poweredBy);
@@ -23304,13 +23512,6 @@
             poweredBy.style.left = "";
             poweredBy.style.bottom = "";
 
-            var termsOfUse = this.div.lastChild;
-            this.div.removeChild(termsOfUse);
-            this.pane.appendChild(termsOfUse);
-            termsOfUse.className = "olLayerGoogleCopyright";
-            termsOfUse.style.right = "";
-            termsOfUse.style.bottom = "";
-
         } catch (e) {
             OpenLayers.Console.error(e);
         }
@@ -24628,8 +24829,6 @@
         // don't display if there were rules but none applied
         if(rules.length > 0 && appliedRules == false) {
             style.display = "none";
-        } else {
-            style.display = "";
         }
         
         return style;
@@ -25207,6 +25406,44 @@
     },
     
     /**
+     * APIMethod: distanceTo
+     * Calculate the closest distance between two geometries.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Optional properties for configuring the distance
+     *     calculation.
+     *
+     * Valid options depend on the specific geometry type.
+     * 
+     * Returns:
+     * {Number | Object} The distance between this geometry and the target.
+     *     If details is true, the return will be an object with distance,
+     *     x0, y0, x1, and x2 properties.  The x0 and y0 properties represent
+     *     the coordinates of the closest point on this geometry. The x1 and y1
+     *     properties represent the coordinates of the closest point on the
+     *     target geometry.
+     */
+    distanceTo: function(geometry, options) {
+    },
+    
+    /**
+     * APIMethod: getVertices
+     * Return a list of all points in this geometry.
+     *
+     * Parameters:
+     * nodes - {Boolean} For lines, only return vertices that are
+     *     endpoints.  If false, for lines, only vertices that are not
+     *     endpoints will be returned.  If not provided, all vertices will
+     *     be returned.
+     *
+     * Returns:
+     * {Array} A list of all vertices in the geometry.
+     */
+    getVertices: function(nodes) {
+    },
+
+    /**
      * Method: atPoint
      * Note - This is only an approximation based on the bounds of the 
      * geometry.
@@ -25281,6 +25518,36 @@
     CLASS_NAME: "OpenLayers.Geometry"
 });
 
+/**
+ * Function: OpenLayers.Geometry.fromWKT
+ * Generate a geometry given a Well-Known Text string.
+ *
+ * Parameters:
+ * wkt - {String} A string representing the geometry in Well-Known Text.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry of the appropriate class.
+ */
+OpenLayers.Geometry.fromWKT = function(wkt) {
+    var format = arguments.callee.format;
+    if(!format) {
+        format = new OpenLayers.Format.WKT();
+        arguments.callee.format = format;
+    }
+    var geom;
+    var result = format.read(wkt);
+    if(result instanceof OpenLayers.Feature.Vector) {
+        geom = result.geometry;
+    } else if(result instanceof Array) {
+        var len = result.length;
+        var components = new Array(len);
+        for(var i=0; i<len; ++i) {
+            components[i] = result[i].geometry;
+        }
+        geom = new OpenLayers.Geometry.Collection(components);
+    }
+    return geom;
+};
     
 /**
  * Method: OpenLayers.Geometry.segmentsIntersect
@@ -25344,6 +25611,49 @@
     }
     return intersection;
 };
+
+/**
+ * Function: OpenLayers.Geometry.distanceToSegment
+ *
+ * Parameters:
+ * point - {Object} An object with x and y properties representing the
+ *     point coordinates.
+ * segment - {Object} An object with x1, y1, x2, and y2 properties
+ *     representing endpoint coordinates.
+ *
+ * Returns:
+ * {Object} An object with distance, x, and y properties.  The distance
+ *     will be the shortest distance between the input point and segment.
+ *     The x and y properties represent the coordinates along the segment
+ *     where the shortest distance meets the segment.
+ */
+OpenLayers.Geometry.distanceToSegment = function(point, segment) {
+    var x0 = point.x;
+    var y0 = point.y;
+    var x1 = segment.x1;
+    var y1 = segment.y1;
+    var x2 = segment.x2;
+    var y2 = segment.y2;
+    var dx = x2 - x1;
+    var dy = y2 - y1;
+    var along = ((dx * (x0 - x1)) + (dy * (y0 - y1))) /
+                (Math.pow(dx, 2) + Math.pow(dy, 2));
+    var x, y;
+    if(along <= 0.0) {
+        x = x1;
+        y = y1;
+    } else if(along >= 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/Layer/MapGuide.js
    ====================================================================== */
@@ -25383,12 +25693,26 @@
      * APIProperty: useOverlay
      * {Boolean} flag to indicate if the layer should be retrieved using
      * GETMAPIMAGE (default) or using GETDYNAMICOVERLAY requests.
-     * Using an overlay image is only available in MapGuide Enterprise 2010
-     * and MapGuide Open Source v2.0.3 or higher, but it allows selections
-     * to be drawn separately from the map and offers styling options
      **/
     useOverlay: false,
     
+    /** 
+     * APIProperty: useAsyncOverlay
+     * {Boolean} indicates if the MapGuide site supports the asynchronous 
+     * GETDYNAMICOVERLAY requests which is available in MapGuide Enterprise 2010
+     * and MapGuide Open Source v2.0.3 or higher. The newer versions of MG 
+     * is called asynchronously, allows selections to be drawn separately from 
+     * the map and offers styling options.
+     * 
+     * With older versions of MapGuide, set useAsyncOverlay=false.  Note that in
+     * this case a synchronous AJAX call is issued and the mapname and session
+     * parameters must be used to initialize the layer, not the mapdefinition
+     * parameter. Also note that this will issue a synchronous AJAX request 
+     * before the image request can be issued so the users browser may lock
+     * up if the MG Web tier does not respond in a timely fashion.
+     **/
+    useAsyncOverlay: true,
+    
     /**
      * Constant: TILE_PARAMS
      * {Object} Hashtable of default parameter key/value pairs for tiled layer
@@ -25419,7 +25743,7 @@
         format: 'PNG',
         locale: 'en',
         clip: '1',
-        version: '2.1.0'
+        version: '2.0.0'
     },
     
     /** 
@@ -25438,8 +25762,9 @@
      * For untiled base layers, specify either combination of 'mapName' and
      * 'session', or 'mapDefinition' and 'locale'.  
      *
-     * For untiled overlay layers (useOverlay=true), 
-     * mapName and session are required parameters for the Layer constructor.  
+     * For older versions of MapGuide and overlay layers, set useAsyncOverlay 
+     * to false and in this case mapName and session are required parameters 
+     * for the constructor.
      *
      * NOTE: MapGuide OS uses a DPI value and degrees to meters conversion 
      * factor that are different than the defaults used in OpenLayers, 
@@ -25498,6 +25823,9 @@
                            this.params,
                            this.OVERLAY_PARAMS
                            );
+            if (!this.useAsyncOverlay) {
+              this.params.version = "1.0.0";
+            }
           } else {
             OpenLayers.Util.applyDefaults(
                            this.params,
@@ -25578,8 +25906,21 @@
             setviewcenterx: center.lon,
             setviewcentery: center.lat,
             setviewscale: this.map.getScale()
+          };
+          
+          if (this.useOverlay && !this.useAsyncOverlay) {
+            //first we need to call GETVISIBLEMAPEXTENT to set the extent
+            var getVisParams = {};
+            getVisParams = OpenLayers.Util.extend(getVisParams, params);
+            getVisParams.operation = "GETVISIBLEMAPEXTENT";
+            getVisParams.version = "1.0.0";
+            getVisParams.session = this.params.session;
+            getVisParams.mapName = this.params.mapName;
+            getVisParams.format = 'text/xml';
+            url = this.getFullRequestString( getVisParams );
+            
+            OpenLayers.Request.GET({url: url, async: false});
           }
-          
           //construct the full URL
           url = this.getFullRequestString( params );
         } else {
@@ -26760,14 +27101,64 @@
      *                 will have four times the area).
      * origin - {<OpenLayers.Geometry.Point>} Point of origin for resizing
      * ratio - {Float} Optional x:y ratio for resizing.  Default ratio is 1.
+     * 
+     * Returns:
+     * {OpenLayers.Geometry} - The current geometry. 
      */
     resize: function(scale, origin, ratio) {
         for(var i=0; i<this.components.length; ++i) {
             this.components[i].resize(scale, origin, ratio);
         }
+        return this;
     },
 
     /**
+     * APIMethod: distanceTo
+     * Calculate the closest distance between two geometries.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Optional properties for configuring the distance
+     *     calculation.
+     *
+     * Valid options:
+     * details - {Boolean} Return details from the distance calculation.
+     *     Default is false.
+     * edge - {Boolean} Calculate the distance from this geometry to the
+     *     nearest edge of the target geometry.  Default is true.  If true,
+     *     calling distanceTo from a geometry that is wholly contained within
+     *     the target will result in a non-zero distance.  If false, whenever
+     *     geometries intersect, calling distanceTo will return 0.  If false,
+     *     details cannot be returned.
+     *
+     * Returns:
+     * {Number | Object} The distance between this geometry and the target.
+     *     If details is true, the return will be an object with distance,
+     *     x0, y0, x1, and y1 properties.  The x0 and y0 properties represent
+     *     the coordinates of the closest point on this geometry. The x1 and y1
+     *     properties represent the coordinates of the closest point on the
+     *     target geometry.
+     */
+    distanceTo: function(geometry, options) {
+        var edge = !(options && options.edge === false);
+        var details = edge && options && options.details;
+        var result, best;
+        var min = Number.POSITIVE_INFINITY;
+        for(var i=0, len=this.components.length; i<len; ++i) {
+            result = this.components[i].distanceTo(geometry, options);
+            distance = details ? result.distance : result;
+            if(distance < min) {
+                min = distance;
+                best = result;
+                if(min == 0) {
+                    break;
+                }
+            }
+        }
+        return best;
+    },
+
+    /**
      * APIMethod: equals
      * Tests for equivalent geometries
      *
@@ -26839,6 +27230,30 @@
         return intersect;
     },
 
+    /**
+     * APIMethod: getVertices
+     * Return a list of all points in this geometry.
+     *
+     * Parameters:
+     * nodes - {Boolean} For lines, only return vertices that are
+     *     endpoints.  If false, for lines, only vertices that are not
+     *     endpoints will be returned.  If not provided, all vertices will
+     *     be returned.
+     *
+     * Returns:
+     * {Array} A list of all vertices in the geometry.
+     */
+    getVertices: function(nodes) {
+        var vertices = [];
+        for(var i=0, len=this.components.length; i<len; ++i) {
+            Array.prototype.push.apply(
+                vertices, this.components[i].getVertices(nodes)
+            );
+        }
+        return vertices;
+    },
+
+
     CLASS_NAME: "OpenLayers.Geometry.Collection"
 });
 /* ======================================================================
@@ -26918,20 +27333,55 @@
 
     /**
      * APIMethod: distanceTo
-     * 
+     * Calculate the closest distance between two geometries.
+     *
      * Parameters:
-     * point - {<OpenLayers.Geometry.Point>} 
+     * geometry - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Optional properties for configuring the distance
+     *     calculation.
+     *
+     * Valid options:
+     * details - {Boolean} Return details from the distance calculation.
+     *     Default is false.
+     * edge - {Boolean} Calculate the distance from this geometry to the
+     *     nearest edge of the target geometry.  Default is true.  If true,
+     *     calling distanceTo from a geometry that is wholly contained within
+     *     the target will result in a non-zero distance.  If false, whenever
+     *     geometries intersect, calling distanceTo will return 0.  If false,
+     *     details cannot be returned.
+     *
+     * Returns:
+     * {Number | Object} The distance between this geometry and the target.
+     *     If details is true, the return will be an object with distance,
+     *     x0, y0, x1, and x2 properties.  The x0 and y0 properties represent
+     *     the coordinates of the closest point on this geometry. The x1 and y1
+     *     properties represent the coordinates of the closest point on the
+     *     target geometry.
      */
-    distanceTo: function(point) {
-        var distance = 0.0;
-        if ( (this.x != null) && (this.y != null) && 
-             (point != null) && (point.x != null) && (point.y != null) ) {
-             
-             var dx2 = Math.pow(this.x - point.x, 2);
-             var dy2 = Math.pow(this.y - point.y, 2);
-             distance = Math.sqrt( dx2 + dy2 );
+    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) {
+                // switch coord order since this geom is target
+                result = {
+                    x0: result.x1, y0: result.y1,
+                    x1: result.x0, y1: result.y0,
+                    distance: result.distance
+                };
+            }
         }
-        return distance;
+        return result;
     },
     
     /** 
@@ -27010,12 +27460,16 @@
      *                 distance between the point and origin.
      * origin - {<OpenLayers.Geometry.Point>} Point of origin for resizing
      * ratio - {Float} Optional x:y ratio for resizing.  Default ratio is 1.
+     * 
+     * Returns:
+     * {OpenLayers.Geometry} - The current geometry. 
      */
     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;
     },
     
     /**
@@ -27058,6 +27512,23 @@
         return this;
     },
 
+    /**
+     * APIMethod: getVertices
+     * Return a list of all points in this geometry.
+     *
+     * Parameters:
+     * nodes - {Boolean} For lines, only return vertices that are
+     *     endpoints.  If false, for lines, only vertices that are not
+     *     endpoints will be returned.  If not provided, all vertices will
+     *     be returned.
+     *
+     * Returns:
+     * {Array} A list of all vertices in the geometry.
+     */
+    getVertices: function(nodes) {
+        return [this];
+    },
+
     CLASS_NAME: "OpenLayers.Geometry.Point"
 });
 /* ======================================================================
@@ -27140,6 +27611,19 @@
      *  - *afterfeaturemodified* Triggered when a feature is finished being modified.
      *      Listeners will receive an object with a *feature* property referencing 
      *      the modified feature.
+     *  - *vertexmodified* Triggered when a vertex within any feature geometry
+     *      has been modified.  Listeners will receive an object with a
+     *      *feature* property referencing the modified feature, a *vertex*
+     *      property referencing the vertex modified (always a point geometry),
+     *      and a *pixel* property referencing the pixel location of the
+     *      modification.
+     *  - *sketchmodified* Triggered when a feature sketch bound for this layer
+     *      is modified.  Listeners will receive an object with a *vertex*
+     *      property referencing the modified vertex.
+     *  - *sketchcomplete* Triggered when a feature sketch bound for this layer
+     *      is complete.  Listeners will receive an object with a *feature*
+     *      property referencing the sketch feature.  By returning false, a
+     *      listener can stop the sketch feature from being added to the layer.
      *  - *refresh* Triggered when something wants a strategy to ask the protocol
      *      for a new set of features.
      */
@@ -27148,6 +27632,7 @@
                   "beforefeatureremoved", "featureremoved", "featuresremoved",
                   "beforefeatureselected", "featureselected", "featureunselected", 
                   "beforefeaturemodified", "featuremodified", "afterfeaturemodified",
+                  "vertexmodified", "sketchmodified", "sketchcomplete",
                   "refresh"],
 
     /**
@@ -27361,7 +27846,7 @@
      * and assigns the first one whose "supported()" function returns true.
      */    
     assignRenderer: function()  {
-        for (var i=0, len=this.renderers.length; i<this.renderers.length; i++) {
+        for (var i=0, len=this.renderers.length; i<len; i++) {
             var rendererClass = OpenLayers.Renderer[this.renderers[i]];
             if (rendererClass && rendererClass.prototype.supported()) {
                 this.renderer = new rendererClass(this.div,
@@ -27571,10 +28056,20 @@
 
     /**
      * APIMethod: removeFeatures
+     * Remove features from the layer.  This erases any drawn features and
+     *     removes them from the layer's control.  The beforefeatureremoved
+     *     and featureremoved events will be triggered for each feature.  The
+     *     featuresremoved event will be triggered after all features have
+     *     been removed.  To supress event triggering, use the silent option.
      * 
      * Parameters:
-     * features - {Array(<OpenLayers.Feature.Vector>)} 
-     * options - {Object}
+     * features - {Array(<OpenLayers.Feature.Vector>)} List of features to be
+     *     removed.
+     * options - {Object} Optional properties for changing behavior of the
+     *     removal.
+     *
+     * Valid options:
+     * silent - {Boolean} Supress event triggering.  Default is false.
      */
     removeFeatures: function(features, options) {
         if(!features || features.length === 0) {
@@ -27667,6 +28162,13 @@
      * feature's style will be used.  If the feature doesn't have a style,
      * the layer's style will be used.
      * 
+     * This function is not designed to be used when adding features to 
+     * the layer (use addFeatures instead). It is meant to be used when
+     * the style of a feature has changed, or in some other way needs to 
+     * visually updated *after* it has already been added to a layer. You
+     * must add the feature to the layer for most layer-related events to 
+     * happen.
+     *
      * Parameters: 
      * feature - {<OpenLayers.Feature.Vector>} 
      * style - {Object} Symbolizer hash or {String} renderIntent
@@ -27901,9 +28403,11 @@
 /**
  * Class: OpenLayers.Handler.Point
  * Handler to draw a point on the map.  Point is displayed on mouse down,
- * moves on mouse move, and is finished on mouse up.  The handler triggers
- * callbacks for 'done' and 'cancel'.  Create a new instance with the
- * <OpenLayers.Handler.Point> constructor.
+ *     moves on mouse move, and is finished on mouse up.  The handler triggers
+ *     callbacks for 'done', 'cancel', and 'modify'.  The modify callback is
+ *     called with each change in the sketc and will receive the latest point
+ *     drawn.  Create a new instance with the <OpenLayers.Handler.Point>
+ *     constructor.
  * 
  * Inherits from:
  *  - <OpenLayers.Handler>
@@ -27974,19 +28478,23 @@
      *
      * Parameters:
      * control - {<OpenLayers.Control>} The control that owns this handler
-     * callbacks - {Object} An object with a 'done' property whose value is a
-     *             function to be called when the point drawing is finished.
-     *             The callback should expect to recieve a single argument,
-     *             the point geometry.  If the callbacks object contains a
-     *             'cancel' property, this function will be called when the
-     *             handler is deactivated while drawing.  The cancel should
-     *             expect to receive a geometry.
+     * callbacks - {Object} An object with a properties whose values are
+     *     functions.  Various callbacks described below.
      * options - {Object} An optional object with properties to be set on the
      *           handler
+     *
+     * Named callbacks:
+     * done - Called when the point drawing is finished.  The callback will
+     *     recieve a single argument, the point geometry.
+     * modify - Called with each move of a vertex with the vertex (point)
+     *     geometry and the sketch feature.
+     * cancel - Called when the handler is deactivated while drawing.  The
+     *     cancel callback will receive a geometry.
      */
     initialize: function(control, callbacks, options) {
-        // TBD: deal with style
-        this.style = OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'], {});
+        if(!(options && options.layerOptions && options.layerOptions.styleMap)) {
+            this.style = OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'], {});
+        }
 
         OpenLayers.Handler.prototype.initialize.apply(this, arguments);
     },
@@ -28122,6 +28630,21 @@
     },
     
     /**
+     * Method: modifyFeature
+     * Modify the existing geometry given a pixel location.
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} A pixel location on the map.
+     */
+    modifyFeature: function(pixel) {
+        var lonlat = this.map.getLonLatFromPixel(pixel);
+        this.point.geometry.x = lonlat.lon;
+        this.point.geometry.y = lonlat.lat;
+        this.callback("modify", [this.point.geometry, this.point]);
+        this.point.geometry.clearBounds();
+    },
+
+    /**
      * Method: drawFeature
      * Render features on the temporary layer.
      */
@@ -28184,10 +28707,7 @@
         }
         this.lastDown = evt.xy;
         this.drawing = true;
-        var lonlat = this.map.getLonLatFromPixel(evt.xy);
-        this.point.geometry.x = lonlat.lon;
-        this.point.geometry.y = lonlat.lat;
-        this.point.geometry.clearBounds();
+        this.modifyFeature(evt.xy);
         this.drawFeature();
         return false;
     },
@@ -28205,10 +28725,7 @@
      */
     mousemove: function (evt) {
         if(this.drawing) {
-            var lonlat = this.map.getLonLatFromPixel(evt.xy);
-            this.point.geometry.x = lonlat.lon;
-            this.point.geometry.y = lonlat.lat;
-            this.point.geometry.clearBounds();
+            this.modifyFeature(evt.xy);
             this.drawFeature();
         }
         return true;
@@ -28456,6 +28973,167 @@
         return segments.sort(byX1);
     },
 
+    /**
+     * APIMethod: getVertices
+     * Return a list of all points in this geometry.
+     *
+     * Parameters:
+     * nodes - {Boolean} For lines, only return vertices that are
+     *     endpoints.  If false, for lines, only vertices that are not
+     *     endpoints will be returned.  If not provided, all vertices will
+     *     be returned.
+     *
+     * Returns:
+     * {Array} A list of all vertices in the geometry.
+     */
+    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;
+    },
+
+    /**
+     * APIMethod: distanceTo
+     * Calculate the closest distance between two geometries.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Optional properties for configuring the distance
+     *     calculation.
+     *
+     * Valid options:
+     * details - {Boolean} Return details from the distance calculation.
+     *     Default is false.
+     * edge - {Boolean} Calculate the distance from this geometry to the
+     *     nearest edge of the target geometry.  Default is true.  If true,
+     *     calling distanceTo from a geometry that is wholly contained within
+     *     the target will result in a non-zero distance.  If false, whenever
+     *     geometries intersect, calling distanceTo will return 0.  If false,
+     *     details cannot be returned.
+     *
+     * Returns:
+     * {Number | Object} The distance between this geometry and the target.
+     *     If details is true, the return will be an object with distance,
+     *     x0, y0, x1, and x2 properties.  The x0 and y0 properties represent
+     *     the coordinates of the closest point on this geometry. The x1 and y1
+     *     properties represent the coordinates of the closest point on the
+     *     target geometry.
+     */
+    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; i<len; ++i) {
+                seg = segs[i];
+                result = OpenLayers.Geometry.distanceToSegment(geometry, seg);
+                if(result.distance < min) {
+                    min = result.distance;
+                    best = result;
+                    if(min == 0) {
+                        break;
+                    }
+                } else {
+                    // if distance increases and we cross y0 to the right of x0, no need to keep looking.
+                    if(seg.x2 > x && ((y > seg.y1 && y < seg.y2) || (y < seg.y1 && y > seg.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;
+            outer: for(var i=0, len=segs0.length; i<len; ++i) {
+                seg0 = segs0[i];
+                x0 = seg0.x1;
+                y0 = seg0.y1;
+                for(var j=0; j<len1; ++j) {
+                    seg1 = segs1[j];
+                    intersection = OpenLayers.Geometry.segmentsIntersect(seg0, seg1, true);
+                    if(intersection) {
+                        min = 0;
+                        best = {
+                            distance: 0,
+                            x0: intersection.x, y0: intersection.y,
+                            x1: intersection.x, y1: intersection.y
+                        };
+                        break outer;
+                    } else {
+                        result = OpenLayers.Geometry.distanceToSegment({x: x0, y: y0}, seg1);
+                        if(result.distance < min) {
+                            min = result.distance;
+                            best = {
+                                distance: min,
+                                x0: x0, y0: y0,
+                                x1: result.x, y1: result.y
+                            };
+                        }
+                    }
+                }
+            }
+            if(!details) {
+                best = best.distance;
+            }
+            if(min !== 0) {
+                // check the final vertex in this line's sorted segments
+                if(seg0) {
+                    result = geometry.distanceTo(
+                        new OpenLayers.Geometry.Point(seg0.x2, seg0.y2),
+                        options
+                    );
+                    var dist = details ? result.distance : result;
+                    if(dist < min) {
+                        if(details) {
+                            best = {
+                                distance: min,
+                                x0: result.x1, y0: result.y1,
+                                x1: result.x0, y1: result.y0
+                            };
+                        } else {
+                            best = dist;
+                        }
+                    }
+                }
+            }
+        } else {
+            best = geometry.distanceTo(this, options);
+            // swap since target comes from this line
+            if(details) {
+                best = {
+                    distance: best.distance,
+                    x0: best.x1, y0: best.y1,
+                    x1: best.x0, y1: best.y0
+                };
+            }
+        }
+        return best;
+    },
+
     CLASS_NAME: "OpenLayers.Geometry.LineString"
 });
 /* ======================================================================
@@ -28612,11 +29290,15 @@
      *                 will have four times the area).
      * origin - {<OpenLayers.Geometry.Point>} Point of origin for resizing
      * ratio - {Float} Optional x:y ratio for resizing.  Default ratio is 1.
+     * 
+     * Returns:
+     * {OpenLayers.Geometry} - The current geometry. 
      */
     resize: function(scale, origin, ratio) {
         for(var i=0, len=this.components.length; i<len - 1; ++i) {
             this.components[i].resize(scale, origin, ratio);
         }
+        return this;
     },
     
     /**
@@ -28784,6 +29466,23 @@
         return intersect;
     },
 
+    /**
+     * APIMethod: getVertices
+     * Return a list of all points in this geometry.
+     *
+     * Parameters:
+     * nodes - {Boolean} For lines, only return vertices that are
+     *     endpoints.  If false, for lines, only vertices that are not
+     *     endpoints will be returned.  If not provided, all vertices will
+     *     be returned.
+     *
+     * Returns:
+     * {Array} A list of all vertices in the geometry.
+     */
+    getVertices: function(nodes) {
+        return (nodes === true) ? [] : this.components.slice(0, this.components.length-1);
+    },
+
     CLASS_NAME: "OpenLayers.Geometry.LinearRing"
 });
 /* ======================================================================
@@ -28840,17 +29539,20 @@
      * Create a new path hander
      *
      * Parameters:
-     * control - {<OpenLayers.Control>} 
-     * callbacks - {Object} An object with a 'done' property whos value is a
-     *     function to be called when the path drawing is finished. The 
-     *     callback should expect to recieve a single argument, the line 
-     *     string geometry. If the callbacks object contains a 'point' 
-     *     property, this function will be sent each point as they are added.  
-     *     If the callbacks object contains a 'cancel' property, this function 
-     *     will be called when the handler is deactivated while drawing. The 
-     *     cancel should expect to receive a geometry.
+     * control - {<OpenLayers.Control>} The control that owns this handler
+     * callbacks - {Object} An object with a properties whose values are
+     *     functions.  Various callbacks described below.
      * options - {Object} An optional object with properties to be set on the
      *           handler
+     *
+     * Named callbacks:
+     * done - Called when the point drawing is finished.  The callback will
+     *     recieve a single argument, the linestring geometry.
+     * point - Called as each point is added.  Receives the new point geometry.
+     * modify - Called with each move of a vertex with the vertex (point)
+     *     geometry and the sketch feature.
+     * cancel - Called when the handler is deactivated while drawing.  The
+     *     cancel callback will receive a geometry.
      */
     initialize: function(control, callbacks, options) {
         OpenLayers.Handler.Point.prototype.initialize.apply(this, arguments);
@@ -28859,12 +29561,19 @@
     /**
      * Method: createFeature
      * Add temporary geometries
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} The initial pixel location for the new
+     *     feature.
      */
-    createFeature: function() {
+    createFeature: function(pixel) {
+        var lonlat = this.control.map.getLonLatFromPixel(pixel);
+        this.point = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat)
+        );
         this.line = new OpenLayers.Feature.Vector(
-                                        new OpenLayers.Geometry.LineString());
-        this.point = new OpenLayers.Feature.Vector(
-                                        new OpenLayers.Geometry.Point());
+            new OpenLayers.Geometry.LineString([this.point.geometry])
+        );
         this.layer.addFeatures([this.line, this.point], {silent: true});
     },
         
@@ -28878,12 +29587,12 @@
     },
 
     /**
-     * Method: destroyPoint
+     * Method: removePoint
      * Destroy the temporary point.
      */
-    destroyPoint: function() {
+    removePoint: function() {
         if(this.point) {
-            this.layer.destroyFeatures([this.point]);
+            this.layer.removeFeatures([this.point]);
         }
     },
     
@@ -28891,11 +29600,22 @@
      * Method: addPoint
      * Add point to geometry.  Send the point index to override
      * the behavior of LinearRing that disregards adding duplicate points.
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} The pixel location for the new point.
      */
-    addPoint: function() {
-        this.line.geometry.addComponent(this.point.geometry.clone(),
-                                        this.line.geometry.components.length);
+    addPoint: function(pixel) {
+        this.layer.removeFeatures([this.point]);
+        var lonlat = this.control.map.getLonLatFromPixel(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.callback("point", [this.point.geometry, this.getGeometry()]);
+        this.callback("modify", [this.point.geometry, this.getSketch()]);
+        this.drawFeature();
     },
     
     /**
@@ -28913,14 +29633,20 @@
     /**
      * Method: modifyFeature
      * Modify the existing geometry given the new point
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} The updated pixel location for the latest
+     *     point.
      */
-    modifyFeature: function() {
-        var index = this.line.geometry.components.length - 1;
-        this.line.geometry.components[index].x = this.point.geometry.x;
-        this.line.geometry.components[index].y = this.point.geometry.y;
-        this.line.geometry.components[index].clearBounds();
+    modifyFeature: function(pixel) {
+        var lonlat = this.control.map.getLonLatFromPixel(pixel);
+        this.point.geometry.x = lonlat.lon;
+        this.point.geometry.y = lonlat.lat;
+        this.callback("modify", [this.point.geometry, this.getSketch()]);
+        this.point.geometry.clearBounds();
+        this.drawFeature();
     },
-    
+
     /**
      * Method: drawFeature
      * Render geometries on the temporary layer.
@@ -28931,6 +29657,17 @@
     },
 
     /**
+     * Method: getSketch
+     * Return the sketch feature.
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>}
+     */
+    getSketch: function() {
+        return this.line;
+    },
+
+    /**
      * Method: getGeometry
      * Return the sketch geometry.  If <multi> is true, this will return
      *     a multi-part geometry.
@@ -28966,18 +29703,12 @@
             if(this.persist) {
                 this.destroyFeature();
             }
-            this.createFeature();
+            this.createFeature(evt.xy);
+        } else if((this.lastUp == null) || !this.lastUp.equals(evt.xy)) {
+            this.addPoint(evt.xy);
         }
         this.mouseDown = true;
         this.lastDown = evt.xy;
-        var lonlat = this.control.map.getLonLatFromPixel(evt.xy);
-        this.point.geometry.x = lonlat.lon;
-        this.point.geometry.y = lonlat.lat;
-        this.point.geometry.clearBounds();
-        if((this.lastUp == null) || !this.lastUp.equals(evt.xy)) {
-            this.addPoint();
-        }
-        this.drawFeature();
         this.drawing = true;
         return false;
     },
@@ -28995,17 +29726,11 @@
      */
     mousemove: function (evt) {
         if(this.drawing) { 
-            var lonlat = this.map.getLonLatFromPixel(evt.xy);
-            this.point.geometry.x = lonlat.lon;
-            this.point.geometry.y = lonlat.lat;
-            this.point.geometry.clearBounds();
             if(this.mouseDown && this.freehandMode(evt)) {
-                this.addPoint();
+                this.addPoint(evt.xy);
             } else {
-                this.modifyFeature();
+                this.modifyFeature(evt.xy);
             }
-            this.drawFeature();
-            //this.callback("move", [evt.xy]);
         }
         return true;
     },
@@ -29025,13 +29750,11 @@
         this.mouseDown = false;
         if(this.drawing) {
             if(this.freehandMode(evt)) {
-                if(this.persist) {
-                    this.destroyPoint();
-                }
+                this.removePoint();
                 this.finalize();
             } else {
                 if(this.lastUp == null) {
-                   this.addPoint();
+                   this.addPoint(evt.xy);
                 }
                 this.lastUp = evt.xy;
             }
@@ -29055,9 +29778,7 @@
         if(!this.freehandMode(evt)) {
             var index = this.line.geometry.components.length - 1;
             this.line.geometry.removeComponent(this.line.geometry.components[index]);
-            if(this.persist) {
-                this.destroyPoint();
-            }
+            this.removePoint();
             this.finalize();
         }
         return false;
@@ -29227,6 +29948,47 @@
         return intersect;
     },
 
+    /**
+     * APIMethod: distanceTo
+     * Calculate the closest distance between two geometries.
+     *
+     * Parameters:
+     * geometry - {<OpenLayers.Geometry>} The target geometry.
+     * options - {Object} Optional properties for configuring the distance
+     *     calculation.
+     *
+     * Valid options:
+     * details - {Boolean} Return details from the distance calculation.
+     *     Default is false.
+     * edge - {Boolean} Calculate the distance from this geometry to the
+     *     nearest edge of the target geometry.  Default is true.  If true,
+     *     calling distanceTo from a geometry that is wholly contained within
+     *     the target will result in a non-zero distance.  If false, whenever
+     *     geometries intersect, calling distanceTo will return 0.  If false,
+     *     details cannot be returned.
+     *
+     * Returns:
+     * {Number | Object} The distance between this geometry and the target.
+     *     If details is true, the return will be an object with distance,
+     *     x0, y0, x1, and y1 properties.  The x0 and y0 properties represent
+     *     the coordinates of the closest point on this geometry. The x1 and y1
+     *     properties represent the coordinates of the closest point on the
+     *     target geometry.
+     */
+    distanceTo: function(geometry, options) {
+        var edge = !(options && options.edge === false);
+        var result;
+        // this is the case where we might not be looking for distance to edge
+        if(!edge && this.intersects(geometry)) {
+            result = 0;
+        } else {
+            result = OpenLayers.Geometry.Collection.prototype.distanceTo.apply(
+                this, [geometry, options]
+            );
+        }
+        return result;
+    },
+
     CLASS_NAME: "OpenLayers.Geometry.Polygon"
 });
 
@@ -29293,18 +30055,20 @@
      * Create a Polygon Handler.
      *
      * Parameters:
-     * control - {<OpenLayers.Control>} 
-     * callbacks - {Object} An object with a 'done' property whos value is
-     *                          a function to be called when the path drawing is
-     *                          finished. The callback should expect to recieve a
-     *                          single argument, the polygon geometry.
-     *                          If the callbacks object contains a 'point'
-     *                          property, this function will be sent each point
-     *                          as they are added.  If the callbacks object contains
-     *                          a 'cancel' property, this function will be called when
-     *                          the handler is deactivated while drawing.  The cancel
-     *                          should expect to receive a geometry.
-     * options - {Object} 
+     * control - {<OpenLayers.Control>} The control that owns this handler
+     * callbacks - {Object} An object with a properties whose values are
+     *     functions.  Various callbacks described below.
+     * options - {Object} An optional object with properties to be set on the
+     *           handler
+     *
+     * Named callbacks:
+     * done - Called when the point drawing is finished.  The callback will
+     *     recieve a single argument, the polygon geometry.
+     * point - Called as each point is added.  Receives the new point geometry.
+     * modify - Called with each move of a vertex with the vertex (point)
+     *     geometry and the sketch feature.
+     * cancel - Called when the handler is deactivated while drawing.  The
+     *     cancel callback will receive a geometry.
      */
     initialize: function(control, callbacks, options) {
         OpenLayers.Handler.Path.prototype.initialize.apply(this, arguments);
@@ -29313,15 +30077,22 @@
     /**
      * Method: createFeature
      * Add temporary geometries
+     *
+     * Parameters:
+     * pixel - {<OpenLayers.Pixel>} The initial pixel location for the new
+     *     feature.
      */
-    createFeature: function() {
+    createFeature: function(pixel) {
+        var lonlat = this.control.map.getLonLatFromPixel(pixel);
+        this.point = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat)
+        );
+        this.line = new OpenLayers.Feature.Vector(
+            new OpenLayers.Geometry.LinearRing([this.point.geometry])
+        );
         this.polygon = new OpenLayers.Feature.Vector(
-                                        new OpenLayers.Geometry.Polygon());
-        this.line = new OpenLayers.Feature.Vector(
-                                        new OpenLayers.Geometry.LinearRing());
-        this.polygon.geometry.addComponent(this.line.geometry);
-        this.point = new OpenLayers.Feature.Vector(
-                                        new OpenLayers.Geometry.Point());
+            new OpenLayers.Geometry.Polygon([this.line.geometry])
+        );
         this.layer.addFeatures([this.polygon, this.point], {silent: true});
     },
 
@@ -29335,18 +30106,6 @@
     },
 
     /**
-     * Method: modifyFeature
-     * Modify the existing geometry given the new point
-     * 
-     */
-    modifyFeature: function() {
-        var index = this.line.geometry.components.length - 2;
-        this.line.geometry.components[index].x = this.point.geometry.x;
-        this.line.geometry.components[index].y = this.point.geometry.y;
-        this.line.geometry.components[index].clearBounds();
-    },
-
-    /**
      * Method: drawFeature
      * Render geometries on the temporary layer.
      */
@@ -29356,6 +30115,17 @@
     },
     
     /**
+     * Method: getSketch
+     * Return the sketch feature.
+     *
+     * Returns:
+     * {<OpenLayers.Feature.Vector>}
+     */
+    getSketch: function() {
+        return this.polygon;
+    },
+
+    /**
      * Method: getGeometry
      * Return the sketch geometry.  If <multi> is true, this will return
      *     a multi-part geometry.
@@ -29384,9 +30154,7 @@
             // remove the penultimate point
             var index = this.line.geometry.components.length - 2;
             this.line.geometry.removeComponent(this.line.geometry.components[index]);
-            if(this.persist) {
-                this.destroyPoint();
-            }
+            this.removePoint();
             this.finalize();
         }
         return false;

Modified: trunk/lib/fusion.js
===================================================================
--- trunk/lib/fusion.js	2009-03-05 15:54:57 UTC (rev 1810)
+++ trunk/lib/fusion.js	2009-03-05 17:50:39 UTC (rev 1811)
@@ -800,7 +800,7 @@
         getFusionURL: function() {return this.fusionURL;},
     
         getConfigurationItem: function(arch, key) { 
-            if (this.configuration[arch] && this.configuration[arch][key]) { 
+            if (this.configuration[arch] && (this.configuration[arch][key]!='undefined')) { 
                 return this.configuration[arch][key]; 
             } 
             return null; 



More information about the fusion-commits mailing list