SharpGIS

#GIS from a .NET developer's perspective

Internet Explorer 8 whitepapers


I was looking into some of the IE8 issues we are having, and found this great site full of Microsoft white papers on IE8.

http://code.msdn.microsoft.com/ie8whitepapers

There are a lot of nice tips and tricks, both about what to be aware of that might have broken your website in IE8, but also tips and tricks on how to optimize your code to utilize some of the new features of IE8.

Opacity NOT supported
IE8 beta 1 does not support adding semi-transparency to any object, neither by using the proprietary filter object or using the CSS3 opacity style property. However, I found this interesting comment in the CSS2.1 compliance paper:

While one of Internet Explorer 8 Beta 1 for Developers' main goals is CSS 2.1 compliance, it is also forward looking towards CSS3. […] Internet Explorer 8 hopes to implement some of the most requested CSS3 features by web developers and designers'.

'opacity' is part of CSS3, and there is a feature request for it on Microsoft connect, and has already gotten a fair amount of votes. Although everyone cannot submit bugs, everyone can vote, so go vote for this missing feature here!

See update here 

VML NOT supported
Microsoft heavily Improved Namespace Support, but I think they didn't think about where that leaves VML. Basically there is no VML support (or SVG for that matter). For GIS apps this is a must. I would prefer seeing an SVG engine instead (saves us having to make two graphics APIs), but VML will do. You can vote for it here.

Here are a couple of things I found interesting in the white papers that I post here for my own reference, but you might find them useful too:

Outline (CSS2.1 compliance paper)
Outline allows you to highlight an element without affecting its size or the layout of the rest of the web page. You can think of outline as an enhanced border that is allowed to overlap other elements without changing the layout of a page. An outline is drawn right outside the border edge, and unlike the border attribute, it won't cause the size of objects to change and move around.

Syntax is the same as with border. Example:

         <div onmouseover="this.style.outline='5px solid yellow';" onmouseout="this.style.outline='';">

or

         myElement.outline = '5px solid red';

An interesting property of ‘outline' is the ability to set the color to invert. This causes the outline to take on the color which is the inversion of the pixels it is overlapping. This guarantees that the outline is always visible, no matter what type of element (even an image) it overlaps. Here is an example of an element with color set to invert: div { outline: thick solid invert }

document.getElementById (DOM Core Improvements)
In Internet Explorer 7, this method searches for and returns the first element that has an ID attribute or name attribute that case-insensitively matches the parameter string.

In Internet Explorer 8, this method finds only elements that have ID attributes that match the given parameter value in a case-sensitive manner. (ID attributes should be interpreted as case-sensitive as per the HTML 4.01 specification).

If you tested with FireFox and do the same in both browsers, this might not be an issue for you, since FireFox is case-sensitive and doesn't use the name tag.

Selecting elements by class (Selectors API)
You can now look up elements very fast by using their class name. So if you know you are doing a lot of searching for specific elements, give them a unique class name and search for them using:

var oneElement = document.querySelector('myClassName');
var elementCollection = document.querySelectorAll('myClassName');

Search for multiple classes at once:

var elementCollection = document.querySelectorAll('myClassName1, myClassName2');

You can limit the scope of the search by using the querySelector/querySelectorAll methods on the individual elements.

Neat! This is one API I hope the other browser vendors will copy!

Switching to IE7 mode (Selectors API)
You probably already know this one, but add this metatag to the page, and everything that works with IE7, should work with IE8 (but this is cheating ;-)

<meta http-equiv="X-UA-Compatible" content="IE=7">

Looping through elements within a node (Platform Performance Improvements)
Modify any chain of lookups to cache the intermediate values, so that the final lookup is the only one made repeatedly (this one is not really new to IE8, but IE8 introduces some internal caching of nodes to improve look-up).

Bad:

function badLoop(div1) {
    for(var i=0; i < div1.parentNode.childNodes.length; i++) {
        var node = div1.parentNode.childNodes[i];
        // Do something with node.
    };
}

Better:

function betterLoop(div1) { // Cache length and array to prevent multiple lookups.
    var childLength = div1.parentNode.childNodes.length;
    var childNodes = div1.parentNode.childNodes;
    for(var i=0; i < childLength; i++) {
        var node = childNodes[i];
        // Do something with node.
     };
}

Use the nextSibling method to traverse the children of an element. For example, improve betterLoop with this (nextSibling is a new property, and this is very similar to the best practice for traversing XML nodes in .NET):

function bestLoop(div1) {
    for(var node = div1.parentNode.childNodes[0]; node != null; node = node.nextSibling) {
        // Do something with node.
    }
}

String concatenation (Platform Performance Improvements)
We were taught to use Arrays for joining strings efficiently. Now we don't have to worry about that anymore:

 Before:

var smallStrings = new Array(); // Fill array with smaller strings 
var largerString = smallStrings.join('');

After:

var smallString1 = "string1";
var smallString2 = "string2";
// String concatenation using the "+" operator
var largerString = string1 + string2;

Working with arrays (Platform Performance Improvements)
Array now comes with built-in Push and Pop methods.

var standardArray = new Array();
standardArray.push("Test String");
standardArray.pop();

More connections for broad-band users (Better AJAX Development)
So here's actually one where Microsoft breaks with the standards:

 "An increasing number of users have broadband connections, so client-side bandwidth is not always a gating factor for performance. Typically, the time required to set up a connection and send a request dominates the time spent retrieving individual objects. The limit of two connections was set by the HTTP 1.1 specification (RFC 2068). By increasing the number of concurrent connections, Internet Explorer 8 Beta 1 for Developers allows Web sites to amortize that cost and churn through the list of pending objects more quickly, leading to an increase in user-perceived download time. Internet Explorer 8 Beta 1 for Developers consequently includes logic that detects whether the connection is narrow-band or broadband and increases the number of connections per host to six if it's a high speed connection. This maximum number of connections applies to any connection to a Web server, not just to downloads."

Notes from Mix08

Virtual Earth announced during their session that they will release a Silverlight Control for embedding maps in your silverlight app. It will be interesting to see if the silverlight adds any benefit over the HTML/JS control.

Deep Zoom: This is an unmanaged part of SilverLight and not very customizable. The tilingscheme is hardcoded. You cannot create images larger than 4x4billion pixels. That's still enough for having a sub-millimeter precision image of the entire earth, so I think that should be sufficient!

The Steve Ballmer Keynote was very entertaining. It was more of a live interview than a keynote. Rumour has it that the questions he got really upset him, but he hides it very well. WATCH IT!

Other sessions worth watching:
Developing ASP.NET applications using the Model View Controller Pattern
Scott Hanselmans' presentation on WPF user controls was the best session that I attended, and also very entertaining. I talked to him today and he admitted to be nervous which was partly why he kept shooting off jokes. It turned out to be be the best presentation, so it worked out :-)

Developing Cutting Edge Web Applications With Internet Explorer 8
Lots of good tips on changes from IE7 to IE8. Espcially the part about the stuff they fixed that will break existing apps is a must read. Also a bit about new features, XDomainRequest objects, new accessibility features etc.

Creating Rich, Dynamic interfaces with Silverlight 2

 

Checking browser version in IE8

IE8 comes with an "Emulate IE7" button, which will revert the page back to run as IE7. This is great for developers who can quickly test their apps in both versions (I just wish we could have an IE6 button too!).

Furthermore you can place a tag in the page that will force IE8 to render the page as IE7 would have. However this poses a problem. Lets say you make some javascript that takes IE8 into account with version checking, but the page has this IE7-compatibility tag embedded. The JavaScript browser version check would still report v8. Instead for IE you should use 'document.documentMode' to get the version number. That means that if you set your browser to run as IE7, this would return version 7 (even though it really is 8), and if you set in quirks mode, you will be getting v5. It would be safer to adjust your javascript using this property.

I ran some few tests on the fresh IE8 beta1. It still looks pretty much like IE7. This blog runs with only one minor problem. I have a gallery page that relies on AjaxControlToolkit, and this really broke on IE8. Hopefully the AjaxControlToolkit team will quickly get all those issues fixed.

There are 4 IE8 specific sessions at the Mix conference. Keep an eye on them at the Mix Website when they come online (about 24 hours after the session):

  • BCT08 - Welcome to Internet Explorer 8  Wed March 5 at 1:30 PM to 2:45 PM
  • CT07 - Cross-Browser Layout with Internet Explorer 8  Wed March 5 at 3:00 PM to 4:15 PM
  • T21 - Integrating Your Site With Internet Explorer 8  Thursday March 6 at 8:30 AM to 9:45 AM
  • T04 - Developing Cutting Edge Web Applications With Internet Explorer 8  Friday March 7 at 8:30 AM to 9:45 AM
  • Here's a picture from the first session, showing the Acid2 test:

    IE8beta1 and Silverlight 2.0 beta 1 available

    Reporting live from the Mix08 conference in Vegas :-)

    Internet Explorer 8 beta1 and Silverlight 2.0 beta1 will be available from today !

    IE8 comes with a much improved Developer tool with full debugger and style tracing, CSS2.1 and HTML5 support. You better get testing in IE8, because your existing website might be broken in IE8 (since it now finally follows the standards).

    Silverlight will also be available for Mobile, and is supported by Nokia who will add it to their S40 and S60 series. You can already see a mobile silverlight app here: silverlight.weatherbug.com. This app was developed in less than 3 weeks and works cross-platform, cross-browser, cross-mobile, cross...

     

    My computer is too smart

    ...it just have a weird way of saying things. For instance, today it tried telling me that I shouldn't be working on a Sunday.

    When I booted up XP, this message kept popping up, and my Windows folder was empty:

    The file or directory C:\Windows is corrupt and unreadable. Please run the Chkdsk utility. 

    The funny thing is that apart from this message was constantly popping up, everything seemed to run just fine.

    I took a backup, rebooted, CHKDSK started up automatically, fixed a few links, and everything seems to run fine again. PHEW! (but I'd better get that harddrive checked)

    UPDATE: Two weeks later the harddisk crashed completely. Thank God for backups !

    New SQL Server Spatial blog

    It looks like Ed Katibah (Spatial Program Manager of SQL Server) finally started blogging.

    His first blogpost covers some interesting changes in the latest February CTP.

    There are some new methods added to the list:

    • Geometry::Filter
    • Geography::Filter
    • Geography::EnvelopeCenter
    • Geography::EnvelopeAngle
    • Geography::STDistance is no longer limited to having one of the inputs of type Point.
    • Geography::Reduce

    Unfortunately I can't try these new features today, because a bug prevents you from using SQL Server 2008 on a Leap Day and the doc on MSDN doesn't cover these new methods yet, so there's not telling how these methods really work.

    Ed's and Isaac Kunens blogs are a must-read if you plan on doing some serious SQL Server Spatial work.

    Creating OGC conformance test map in SQL Server 2008

    The Simple Features Specification v1.1.0 has a conformance test based on "Joe's Blue Lake vicinity map", which roughly looks like this:

    To create the map in Microsoft SQL Server 2008, first create the tables:

    -- Lakes
    CREATE TABLE lakes (fid INTEGER NOT NULL PRIMARY KEY,name VARCHAR(64),shore Geometry);
    -- Road Segments
    CREATE TABLE road_segments (fid INTEGER NOT NULL PRIMARY KEY,name VARCHAR(64),aliases VARCHAR(64),num_lanes INTEGER,centerline Geometry);
    -- Divided Routes
    CREATE TABLE divided_routes (fid INTEGER NOT NULL PRIMARY KEY,name VARCHAR(64),num_lanes INTEGER,centerlines Geometry);
    -- Forests
    CREATE TABLE forests (fid INTEGER NOT NULL PRIMARY KEY,name VARCHAR(64),boundary Geometry);
    -- Bridges
    CREATE TABLE bridges (fid INTEGER NOT NULL PRIMARY KEY,name VARCHAR(64),position Geometry);
    -- Streams
    CREATE TABLE streams (fid INTEGER NOT NULL PRIMARY KEY,name VARCHAR(64),centerline Geometry);
    -- Buildings
    CREATE TABLE buildings (fid INTEGER NOT NULL PRIMARY KEY,address VARCHAR(64),position Geometry,footprint Geometry);
    -- Ponds
    CREATE TABLE ponds (fid INTEGER NOT NULL PRIMARY KEY,name VARCHAR(64),type VARCHAR(64),shores Geometry);
    -- Named Places
    CREATE TABLE named_places (fid INTEGER NOT NULL PRIMARY KEY,name VARCHAR(64),boundary Geometry);
    -- Map Neatline
    CREATE TABLE map_neatlines (fid INTEGER NOT NULL PRIMARY KEY,neatline Geometry);

    Next step is to insert the rows:

    -- Lakes
    INSERT INTO lakes VALUES (101, 'BLUE LAKE',Geometry::STPolyFromText('POLYGON((52 18,66 23,73 9,48 6,52 18),(59 18,67 18,67 13,59 13,59 18))', 101));
    -- Road segments
    INSERT INTO road_segments VALUES(102, 'Route 5', NULL, 2,Geometry::STLineFromText('LINESTRING( 0 18, 10 21, 16 23, 28 26, 44 31 )' ,101));
    INSERT INTO road_segments VALUES(103, 'Route 5', 'Main Street', 4,Geometry::STLineFromText('LINESTRING( 44 31, 56 34, 70 38 )' ,101));
    INSERT INTO road_segments VALUES(104, 'Route 5', NULL, 2,Geometry::STLineFromText('LINESTRING( 70 38, 72 48 )' ,101));
    INSERT INTO road_segments VALUES(105, 'Main Street', NULL, 4,Geometry::STLineFromText('LINESTRING( 70 38, 84 42 )' ,101));
    INSERT INTO road_segments VALUES(106, 'Dirt Road by Green Forest', NULL, 1,Geometry::STLineFromText('LINESTRING( 28 26, 28 0 )',101));
    -- DividedRoutes
    INSERT INTO divided_routes VALUES(119, 'Route 75', 4,Geometry::STMLineFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))', 101));
    -- Forests
    INSERT INTO forests VALUES(109, 'Green Forest',Geometry::STMPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))', 101));
    -- Bridges
    INSERT INTO bridges VALUES(110, 'Cam Bridge', Geometry::STPointFromText('POINT( 44 31 )', 101));
    -- Streams
    INSERT INTO streams VALUES(111, 'Cam Stream',Geometry::STLineFromText('LINESTRING( 38 48, 44 41, 41 36, 44 31, 52 18 )', 101));
    INSERT INTO streams VALUES(112, NULL,Geometry::STLineFromText('LINESTRING( 76 0, 78 4, 73 9 )', 101));
    -- Buildings
    INSERT INTO buildings VALUES(113, '123 Main Street',Geometry::STPointFromText('POINT( 52 30 )', 101),Geometry::STPolyFromText('POLYGON( ( 50 31, 54 31, 54 29, 50 29, 50 31) )', 101));
    INSERT INTO buildings VALUES(114, '215 Main Street',Geometry::STPointFromText('POINT( 64 33 )', 101),Geometry::STPolyFromText('POLYGON( ( 66 34, 62 34, 62 32, 66 32, 66 34) )', 101));
    -- Ponds
    INSERT INTO ponds VALUES(120, NULL, 'Stock Pond',Geometry::STMPolyFromText('MULTIPOLYGON( ( ( 24 44, 22 42, 24 40, 24 44) ),( ( 26 44, 26 40, 28 42, 26 44) ) )', 101));
    -- Named Places
    INSERT INTO named_places VALUES(117, 'Ashton',Geometry::STPolyFromText('POLYGON( ( 62 48, 84 48, 84 30, 56 30, 56 34, 62 48) )', 101));
    INSERT INTO named_places VALUES(118, 'Goose Island',Geometry::STPolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )', 101));
    -- Map Neatlines
    INSERT INTO map_neatlines VALUES(115,Geometry::STPolyFromText('POLYGON( ( 0 0, 0 48, 84 48, 84 0, 0 0 ) )', 101));
     

    And voilá... you can now for instance run all the conformance tests, but the map is actually also a good base-map for learning the various spatial operations.

    If you use my SQL Spatial Query Tool, here's a query you can use to visualize the map:

    SELECT neatline, 'Background' as name, 'map_neatlines' as layer, 'White' as FillColor, 'Transparent' as LineColor, 1 as LineThickness FROM map_neatlines UNION ALL
    SELECT shores, name, 'ponds' as layer, 'LightBlue' as FillColor, 'Blue' as LineColor, 1 as LineThickness FROM ponds UNION ALL
    SELECT boundary, name, 'forests' as layer, 'Green' as FillColor, '#ff005500' as LineColor, 4 as LineThickness FROM Forests UNION ALL
    SELECT shore, name, 'lakes' as layer, 'Blue' as FillColor, 'Transparent' as LineColor, 2 as LineThickness FROM lakes UNION ALL
    SELECT boundary, name, 'named_places' as layer, '#00ffff99' as FillColor, 'Brown' as LineColor, 2 as LineThickness FROM named_places UNION ALL
    SELECT centerline, name, 'streams_outline' as layer, 'Blue' as FillColor, 'Blue' as LineColor, 5 as LineThickness FROM streams UNION ALL
    SELECT centerline, name, 'streams_fill' as layer, 'LightBlue' as FillColor, 'LightBlue' as LineColor, 3 as LineThickness FROM streams UNION ALL
    SELECT centerline, name, 'road_segments' as layer, 'LightGreen' as FillColor, 'Black' as LineColor, num_lanes*2 as LineThickness FROM road_segments UNION ALL
    SELECT centerlines, name, 'divided_routes' as layer, 'LightGreen' as FillColor, '#aaff0000' as LineColor, num_lanes*2 as LineThickness FROM divided_routes UNION ALL
    SELECT footprint, address, 'buildings_footprint' as layer, 'Black' as FillColor, 'Transparent' as LineColor, 1 as LineThickness FROM buildings UNION ALL
    SELECT position.STBuffer(0.5), address, 'buildings_position' as layer, 'Red' as FillColor, 'Transparent' as LineColor, 1 as LineThickness FROM buildings UNION ALL
    SELECT position.STBuffer(1), name, 'bridges' as layer, '#550000ff' as FillColor, 'Black' as LineColor, 1 as LineThickness FROM bridges

    Which will generate a map like this: 

    Download SQL queries (1.71 kb)

    Straight lines on a sphere

    There was a question in the Sql Server Spatial/Katmai forums about why a straight line on a sphere didn't "look straight".

    Katmai both have planar and spherical geometry types. The spherical type makes it easier to handle things like straight lines, distances and areas over large distances, and depending on which type you choose, you can get very different results.

    Consider traveling on a straight line from Vancouver to Frankfurt. They are both located roughly at latitude 50°N. So the line would follow latitude 50°N right? Well that's true for a planar coordinate system:

    So according to The Flat Earth Society (who actually believes the Earth is flat) the green line above shows the shortest distance between the two cities. But what we are actually seeing is an artifact of working with a planar coordinate system depicting a world that is not planar.

    Using a spheric coordinate system, we get a different result. When looking at this line in a projected coordinate system, like the Mercator projection I've used here, the line doesn't look straight (left image below). However if we look at this in a 3D view (right image), it becomes apparent that the "curved line" is actually the shortest line between the two cities.

    The difference between using the two geometry types gets really apparent when you try to find the shortest distance from New York to the line in the two coordinate systems. In the planar case, Quebec is approximately the point where the line is the closest to New York. In the spherical case, the line never gets closer to New York than from Vancouver where it started out.

    Another way that I like to think of why following a latitude is not the shortest route, is imagining two guys standing a few feet from the North Pole with the pole between them. Which way is the shortest path between them: Walking straight over the pole or following the latitude at 89.999°N around it? Now imagine how this line would look on a map.

    We can extend this further and have the two men go further and further away from each other.  If one man gets a little further south than the other, the line wouldn't pass the pole, but go by just next to the it - it still wouldn't follow the latitude. Since the North Pole is just a point we humans "made up", we can abstract it and think of a pole in the ground anywhere on Earth. The bottom line is that the North Pole and the latitudes are all imaginary, and doesn't really exist, and definitely doesn't help describing the shortest distance.

    Only at Equator would it be a good idea to follow the latitude, which is because this is the only latitude that is a great circle, and it so happens to be that any straight line between two points will describe parts of a great circle. Longitudes however are all great circles, and the line between the two men describe parts of a longitude. The reason we think that the horizontal line between Vancouver and Germany is the shortest path, is simply because we have to project the round Earth onto a flat piece of paper, and this causes all sorts of things to get distorted.

    The community works

    It looks like Microsoft listened to the community and plans on switching latitude and longitude ordering for WKT and WKB:
    http://blogs.msdn.com/isaac/archive/2007/12/27/latitude-longitude-ordering.aspx

    This change will only be for WKT and WKB. That does make some sense, since the ordering is related to the SRID which is not included in the WKT and WKB, thus making it impossible to decipher without any prior knowledge. It would still be nice if the two geometry models shared a more common interface for anything that is remotely similar, but this is a good start.

    I’m actually starting to like working with the geography type (to begin with I hated the idea of having two different although similar geometry models). It’s fun to do buffers on points and see that they don’t look circular on a projected map, because they are, well… projected. Showing the same circles on a 3D globe reveals that they are in fact perfectly circular. It makes distance queries so much easier than for instance using this approach.

    400km buffer around Copenhagen

    One thing that still bugs me about the geography datatype though… why is the linear unit type that is used for calculating area, length, buffers etc. declared as part of the SRID (which in this case is always geographic) ? This requires one to always first have to look up the linear unit in the spatial_ref_sys table for each returned row (since homogeneous SRIDs aren’t enforced on the table) and divide by the factor returned to ensure that we know the unit we get back. In my mind a linear unit should never be related to a geographic coordinate system. After all, that’s why we only define linear units in projected and geocentric coordinate systems where they makes sense.

    It would be nice if the methods either took a unit type as input (although that would break with the common interface I just wished for) or simply just always outputs the results in SI units (then it would just be a matter of multiplying with a constant well-known conversion factor later if you want to display it in for instance miles, thus separating code from presentation). Luckily most of Katmai’s SR definitions use meters as default, but you never know if someone chose to change the conversion factors in the system table so you will always have to check first.

    Shapefile to SqlServer 2008 to WPF

    I've been playing with the spatial support of SQL Server 2008 today, but quickly hit two obstacles:

    1. How do I get data into the database.
    2. How do I visualize a query (apart from the Well-Known Text output).

    Surprisingly there aren't really any good (free) tools out there yet to upload for instance shapefiles to Katmai. I pulled out some old code I had lying around and threw a small tool together that can upload a shapefile to the database either as geometry or geography. Katmai is pretty picky when it comes to the geography datatype, so make sure your shapefiles contain valid geometry and has vertices in the valid domain, or use the geometry format. You can download the tool below.

    Next obstacle was visualizing the data. Playing with the spatial queries and not beeing able to see the results on a map quickly got boring. I haven't had a chance to play much with WPF, so I thought this was a good occation to play with it. Based on this MSDN article I managed to fairly quickly make a little tool that takes a SQL query as input and outputs the results in a WPF control. At the moment it only works with polylines and polygons - Points are simply ignored (tip: use STBuffer() on points to see them). It will look for the first column that contains a SqlGeometry or SqlGeography datatype and put that on the map. The remaining columns are shown in the box to the right when you hover over the shapes with the mouse.

    The two tools are not perfect in any way (and there's no bug tracking support here :-)), but they provide a quick way to play with the spatial queries. Both tools requires Windows Authentification to access the sql server and runs on .NET 3.5. Furthermore the query tool uses the Microsoft.SqlServer.Types.dll that comes with installing Katmai (to parse the results), so for now you'll need to run it from a computer that has Katmai installed.

    Read more and download SqlSpatialTools