Bing Maps Shapes (VEShape) to WKT (Well-Known-Text) and Back using JavaScript
One of the standard methods of representing geometric shapes is by using the WKT (Well-Known-Text) standard. This is a human readable standard method of representing geometric shapes that can be used to easily pass spatial data between applications. I know GML or GeoRSS may be a little more applicable since they are based on XML, but WKT can work just fine in some cases.
If you don’t know what WKT is here are a couple links for reference:
http://geoapi.sourceforge.net/2.0/javadoc/org/opengis/referencing/doc-files/WKT.html
http://en.wikipedia.org/wiki/Well-known_text
This is also one of the things that Virtual Earth does NOT have support built in for. So I wrote a little code that simply converts VEShape objects to a WKT string representation.
The code below allows you to represent Pushpins, Polygons and Polylines as strings like the following:
POINT(-99.71000000000001 43.74999999999998) POLYGON((-99.71000000000001 46.74999999999998, -96.71000000000001 46.74999999999998, -96.71000000000001 43.74999999999998, -99.71000000000001 46.74999999999998)) LINESTRING(-99.71000000000001 40.74999999999998, -102.71000000000001 40.74999999999998, -102.71000000000001 43.74999999999998)
Here are some examples of using the conversion methods:
// Get Map Center Point var centerPoint = map.GetCenter(); // Create Pushpin VEShape and Get it's WKT representation var wktShape = VirtualEarthWKT.ShapeToWKT(new VEShape(VEShapeType.Pushpin, centerPoint)); // Create a VEShape from the WKT representation var shape = VirtualEarthWKT.ShapeFromWKT(wktShape); // Add VEShape to Map map.AddShape(shape); // Create Polygons' Location Array var polygonLocations = [ new VELatLong(centerPoint.Latitude + 3, centerPoint.Longitude), new VELatLong(centerPoint.Latitude + 3, centerPoint.Longitude + 3), new VELatLong(centerPoint.Latitude, centerPoint.Longitude + 3) ]; // Create Polygon VEShape and Get it's WKT representation wktShape = VirtualEarthWKT.ShapeToWKT(new VEShape(VEShapeType.Polygon, polygonLocations)); // Create a VEShape from the WKT representation shape = VirtualEarthWKT.ShapeFromWKT(wktShape); // Add VEShape to Map map.AddShape(shape); // Create Polylines' Location Array var polylineLocations = [ new VELatLong(centerPoint.Latitude - 3, centerPoint.Longitude), new VELatLong(centerPoint.Latitude - 3, centerPoint.Longitude - 3), new VELatLong(centerPoint.Latitude, centerPoint.Longitude - 3) ]; // Create Polyline VEShape and Get it's WKT representation wktShape = VirtualEarthWKT.ShapeToWKT(new VEShape(VEShapeType.Polyline, polylineLocations)); // Create a VEShape from the WKT representation shape = VirtualEarthWKT.ShapeFromWKT(wktShape); // Add VEShape to Map map.AddShape(shape);
Here’s the full code to the VirtualEarthWKT object that contains the static methods:
// Create the singleton object that contains the WKT (Well-Known-Text) transformation methods. var VirtualEarthWKT = new (function() { // Declare some "private" methods that will only be used internally var priv = { trimSpaces: function(str) { // Trim beginning spaces while (priv.startsWith(str, " ")) { str = str.substring(1); } // Trim ending spaces while (priv.endsWith(str, " ")) { str = str.substring(0, str.length - 1); } return str; }, startsWith: function(str, startstr) { return str.substring(0, startstr.length) == startstr; }, endsWith: function(str, endstr) { return str.substring(str.length - endstr.length) == endstr; } }; // Declare the "public" methods that will be exposed var that = { ///Converts a VEShape object to WKT (Well-Known-Text) string representation. ShapeToWKT: function(shape) { if (shape == null) { throw "VirtualEarthWKT.ShapeToWKT: 'shape' parameter can not be null."; } var wktTemplate = ""; var wktGeomPoints = ""; // Figure out the WKT Geometry Type switch (shape.GetType()) { case VEShapeType.Pushpin: wktTemplate = "POINT({points})"; break; case VEShapeType.Polygon: wktTemplate = "POLYGON(({points}))"; break; case VEShapeType.Polyline: wktTemplate = "LINESTRING({points})"; break; default: throw "VirtualEarthWKT.ShapeToWKT: VEShapeType (" + shape.GetType() + ") not supported."; break; } // Get the List of VELatLong objects represented as WKT compatible list of points var shapePoints = shape.GetPoints(); for (var i = 0; i < shapePoints.length; i++) { if (wktGeomPoints.length > 0) { wktGeomPoints += ", "; } wktGeomPoints += shapePoints[i].Longitude + " " + shapePoints[i].Latitude; } // return WKT representation of the VEShape return wktTemplate.replace("{points}", wktGeomPoints); }, ///</span> ///Converts WKT (Well-Known-Text) string representation of a point/polygon/linestring to a VEShape object. ///</summary> ShapeFromWKT: function(strWKT) { if (strWKT == null) { throw "VirtualEarthWKT.ShapeFromWKT: 'strWKT' parameter can not be null."; } if (strWKT.length == 0) { throw "VirtualEarthWKT.ShapeFromWKT: 'strWKT' parameter can not be an empty string."; } var shapeType = null; var wktPoints = null; // Get the Shape Type and list of "Longitude Latitude" location points switch (strWKT.substring(0, 5).toLowerCase()) { case "point": shapeType = VEShapeType.Pushpin; wktPoints = strWKT.substring(6, strWKT.length - 1); break; case "polyg": shapeType = VEShapeType.Polygon; wktPoints = strWKT.substring(9, strWKT.length - 2); break; case "lines": shapeType = VEShapeType.Polyline; wktPoints = strWKT.substring(11, strWKT.length - 1); break; default: throw "VirtualEarthWKT.ShapeFromWKT: Unknown WKT Geometry Type"; break; } // split out the wkt points to be seperate wktPoints = wktPoints.split(","); // Convert the WKT Points to VELatLong locations var shapePoints = new Array(); for (var i = 0; i < wktPoints.length; i++) { // Split the "Longitude Latitude" apart var loc = priv.trimSpaces(wktPoints[i]).split(" "); // Create VELatLong location shapePoints[shapePoints.length] = new VELatLong(parseFloat(loc[1]), parseFloat(loc[0])); } // Return a VEShape that represents this WKT Geometry return new VEShape(shapeType, shapePoints); } }; // Return the object that contains the "public" and "private" methods return that; })();</pre>