SharpGIS

#GIS from a .NET developer's perspective

MapServer Enterprise

Yesterday The MapServer Foundation announced the availability of the new (and free!) MapServer Enterprise sponsored by AutoDesk.
They state that it also supports .NET, which sounds like goodies for a .NET/GIS guy like me, so I definitely had to check it out.

I must admit that their ASP.NET examples shocked my completely. I can’t recall seeing that poor .NET code the last couple of years. It’s all ASP-style spaghetti-code and ridiculously poor implemented. I wouldn’t be surprised that if you rename the file-extensions to .asp, it would still run :-) Although I’m still exited by this new release, I can’t help thinking that if this is the best they can do in a .NET environment, what does the actual server-code look like?

SharpMap as a WMS server

Today I was trying to make a WMS implementation using SharpMap, and it turned out to be quite easy. I’ve implemented some helper classes in SharpMap, which I will include in the next release of SharpMap. Actually now you can create a WMS service using only a few lines of code. Here’s an example:

protected void Page_Load(object sender, EventArgs e)
{
    SharpMap.Map myMap = InitializeMap(); //Call method that sets up your map
    SharpMap.Web.Wms.WmsServer.ParseQueryString(Request.QueryString,Response,myMap);
}
And that’s it !!! (well at least besides the InitializeMap method where you set up layers etc…)

It even returns nice little XML exceptions according to the specification. I still need to do some work on the GetCapabilities request, but I think it’s more or less safe to say that SharpMap will work as an OpenGIS compliant WMS Server in the next release.

SharpMap Sourcecode and WMS support

The source code for SharpMap is now available too, as well as some feature changes. Biggest change is support for using WMS layers. I you don���t have access to vector data or a PostGreSQL database, you can still aggregate data from several WMS servers and display them in you very own map application. I’m still working on shape file and raster support.

Rendering maps using .NET

Last night I was, just for fun, fooling around with creating my own mapserver engine using native .NET and GDI+ methods, combined with a PostGreSQL/PostGIS database. Until now I got Points, Labels and Line layertypes implemented.
I didn’t expect much of the speed, but it turned out that GDI+’s drawing methods and anti-aliasing rendering combined with .NETs automatic connection pooling provided me with an ultra fast map render engine. And just by exposing LineStyles as System.Drawing.Pen you get a vast amount of options for customizing the look of the rendered output. And it even looks great! I’m all ecstatic about the result, and will probably follow this further with more geometry types and additional data-providers (shapefile, Oracle etc). I’ll post some results here later.

PocketGpsLib Class Diagram

I was looking into doing some unit testing, when I just (re)discovered a cool new feature in VS2005. You can auto-generate a class-diagram from your projects, just by right-clicking and select "Class diagram". Below is a class diagram for parts of the upcoming release of PocketGpsLib 2.0, as of today. Better get back to setting up some unit tests... :-)

PocketGpsLib v2.0 update

These last couple of days, I’ve been working a lot with the PocketGpsLib in the new Visual Studio 2005 beta 2 IDE. Working with and testing the library, I stumbled across quite a few bugs in the NMEA parser that sometimes occur, even in the old release. Pretty embarrassing considering the current 600+ downloads of the library, although it usually parses the data correctly :-)

I’ve also been redesigning the API quite a lot, and I think it’s moving toward a much slicker API. Are you also working with .NET Compact Framework 2.0 beta2, let me know if you’re interested in testing the library.

First release of SharpMap

I have decided to release my .NET Mapping engine. This is an alpha release, but it seems pretty stable. At the moment there are support for most types of vector data 
Take a look at the webpage, try it out, and contribute with ideas, bugs, comments, add-ons etc.: http://sharpmap.iter.dk

For desktop applications, there is a build-in user control that supports dynamic zoom and pan. I think it's pretty cool :-) For ASP.NET there are no user controls yet, but a HttpHandler to make life easier. Check out the FAQ.

You will need Visual Studio 2005 beta 2 to use it, as well as a PostGreSQL database with PostGIS extensions.
You can get a free Beta 2 Express Edition of Visual Studio 2005 here: http://lab.msdn.microsoft.com/express/vcsharp/default.aspx

Differential GPS using RTCM from NTRIP

This post will focus on how to get data from a NTRIP RTCM datastream. RTCM can greatly enhance the accuracy of your GPS receiver by downloading live correction data from the Internet using the NTRIP protocol. This example has been tested on Pocket PC 2002, but should work any other .NET capable OS as well.

The NTRIP data stream is basically an ordinary HTTP stream. My initial thought was just to use .NET's System.Net.WebRequest class to download the stream, but I quickly ended up with an infinite loop. The reason for this, is that the NTRIP stream never ends, and the WebRequest therefore never finishes.

Instead we have to do a bit more work ourselves. Luckily we have System.Net.Sockets to helps us out here. Lets initialize the socket, by calling a server at IP address '129.217.182.51' through port 80:

IPAddress BroadCasterIP = IPAddress.Parse("129.217.182.51");
int BroadCasterPort = 80;
 Socket sckt = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
 sckt.Blocking = true;
 sckt.Connect(new IPEndPoint(BroadCasterIP,BroadCasterPort));

The next thing we will have to do, is to send a request to the server, telling them what we want. In this case I'm requesting the datastream "FLEN0".

string msg = "GET /FLEN0 HTTP/1.1\r\n";
 msg += "User-Agent: NTRIP iter.dk\r\n";
 msg += "Accept: */*\r\nConnection: close\r\n";
 msg += "\r\n";

If the stream uses authentification, we would need to add the following, where username and password are strings containing, well... the username and password (surprise!). We need to encode the username and password to Base64 as well. A small funktion is provided for this. The request will then look like this:

string auth = ToBase64(username + ":" + password);
 string msg = "GET /FLEN0 HTTP/1.1\r\n";
 msg += "User-Agent: NTRIP iter.dk\r\n";
 msg += "Authorization: Basic " + auth + "\r\n";
 msg += "Accept: */*\r\nConnection: close\r\n";
 msg += "\r\n";
 [...]
 private string ToBase64(string str) {
   Encoding asciiEncoding = Encoding.ASCII;
   byte[] byteArray = new byte[asciiEncoding.GetByteCount(str)];
   byteArray = asciiEncoding.GetBytes(str);
   return Convert.ToBase64String(byteArray,0,byteArray.Length);
}

OK, now lets send the request:

byte[] data = System.Text.Encoding.ASCII.GetBytes(msg);
 sckt.Send(data);

Well now two things might happen. Either we start receiving the NTRIP RTCM stream, OR if we made some kind of error, we will receive a list of available data streams instead. I will not cover how to decode the data, but just show you how to pass the data on to your GPS. It's actually pretty straight forward. First of all, to receive the data, you can use the Sockets.Receive method:

byte[] returndata = new byte[256];
 sckt.Receive(returndata);

If the data returned is valid RTCM you can just throw it out to your serial port and directly on to the GPS device. Using the PocketGpsLib that is described elsewhere on this site, you would just write:

GPSHandler GPS = new GPSHandler(this); //Initialize GPS handler
//Insert code to set up the GPS here...
// [...]
if(GPS.IsPortOpen) { GPS.WriteToGPS(returndata); //Send RTCM data to GPS }

Now to make this really work, you would create a timer that with a short interval checked the socket for new data, and pass it on to the GPS device. I used an interval of 100ms, which seemed to work quite well.

When you are done using the socket, remember to close it again:

sckt.Shutdown(SocketShutdown.Both);
 sckt.Close();

Click here to view an example of how to implement the above. Note: This is not a full application. You still have to do a little work yourselves, but hopefully this should get you going.