Archive for the ‘Work’ Category

Using SpatialAce in WPF applications

Tuesday, April 29th, 2008

It’s been a long while since I blogged about SpatialAce. It’s even got a new name since the last time i wrote about it: Carmenta Engine. So I thought I’d write one last post about this excellent GIS map engine; this time about using it in a Windows Presentation Foundation (WPF) application.

Since Carmenta Engine is an ActiveX control, you need to use a WindowsFormsHost wrapper class. I will show a technique where we will create an intermediate WPF wrapper that will enable us to implement a few custom dependency properties that we can use for setting configurations files and view names in XAML.

Start by adding a new WPF Library project to your solution. Name the new project CarmentaEngine. Then add a new Windows Forms UserControl and name it CarmentaEngineFormsControl. Make sure that you choose a Windows Forms control, not the WPF equivalent. In this UserControl, you drop your Carmenta Engine ActiveX control and set it’s dock property to fill.

Now create a WPF UserControl in the same project and drop a WindowsFormsHost into it. Name the WPF UserControl CarmentaEngineControl. We can now add the just created Windows Forms UserControl to the WPF UserControl. Sounds a little complicated? Well, the benefit here is that we can implement dependency properties for Carmenta Engine in the WPF UserControl that we can use from XAML later.

The file CarmentaEngineControl.xaml should look something like this:

  <UserControl x:Class="CarmentaEngine.CarmentaEngineControl"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
      xmlns:code="clr-namespace:CarmentaEngine"
      Height="300" Width="300" >
      <Grid>
          <my:WindowsFormsHost Name="windowsFormsHost1">
              <code:CarmentaEngineFormsControl x:Name="carmentaEngineFormsControl"/>
          </my:WindowsFormsHost>
      </Grid>
  </UserControl>


We’d like to expose the ConfigurationFile and ViewName property of the Carmenta Engine ActiveX control as dependency properties. This is very straightforward code, the only thing to look out for is that we should not set the property values until we have both of them. Setting ViewName without a ConfigurationFile value does not make sense. Here’s the code behind from CarmentaEngineControl.xaml.cs:

  public partial class CarmentaEngineControl : UserControl {

      public static readonly DependencyProperty ConfigurationFileProperty;
      public static readonly DependencyProperty ViewNameProperty;

      private string viewName = null;
      private string path = null;

      public CarmentaEngineControl() {
          InitializeComponent();
      }

      static CarmentaEngineControl() {
          ConfigurationFileProperty = DependencyProperty.Register
              ("ConfigurationFile", typeof (string), typeof (CarmentaEngineControl),
               new FrameworkPropertyMetadata
               (null, FrameworkPropertyMetadataOptions.None, OnConfigurationFileChanged));

          ViewNameProperty = DependencyProperty.Register
              ("ViewName", typeof(string), typeof(CarmentaEngineControl),
               new FrameworkPropertyMetadata
               (null, FrameworkPropertyMetadataOptions.None, OnViewNameChanged));
      }

      private static void OnViewNameChanged
          (DependencyObject d, DependencyPropertyChangedEventArgs e) {
          CarmentaEngineControl control = d as CarmentaEngineControl;
          if (control != null) {
              control.viewName = (string) e.NewValue;
              control.InitializeEngine();
          }
      }

      private static void OnConfigurationFileChanged
          (DependencyObject d, DependencyPropertyChangedEventArgs e) {
          CarmentaEngineControl control = d as CarmentaEngineControl;
          if (control != null) {
              control.path = (string) e.NewValue;
              control.InitializeEngine();
          }
      }

      public string ConfigurationFile {
          get { return (string) GetValue(ConfigurationFileProperty); }
          set { SetValue(ConfigurationFileProperty, value); }
      }

      public string ViewName {
          get { return (string)GetValue(ViewNameProperty); }
          set { SetValue(ViewNameProperty, value); }
      }

      private void InitializeEngine() {
          if (path != null && viewName != null) {

              FileInfo fileInfo = new FileInfo(path);
              if (fileInfo.Exists) {
                  AxSpaceX spaceX = carmentaEngineFormsControl.axSpaceX1;
                  spaceX.ConfigurationFile = path;
                  spaceX.NameSpace = Path.GetFileNameWithoutExtension(path);
                  spaceX.ViewName = viewName;

                  spaceX.Tool = new RoamToolClass();
              }
          }
      }
  }


That’s basically all there is to it. Now, in your original WPF application project, reference the WPF Library project from above and add the following code to your XAML:

  <CarmentaEngine:CarmentaEngineControl
            Margin="31,0,475.75,19" Height="177" VerticalAlignment="Bottom"
            ConfigurationFile="path to configuration file"
            ViewName="the name of your view"/>


Don’t forget to reference the CarmentaEngine project in your header:

  xmlns:CarmentaEngine="clr-namespace:CarmentaEngine;assembly=CarmentaEngine"


Since last week, I no longer work at Carmenta so I can’t verify the syntax. I based the code on some notes on how I did this a few weeks ago and I hope I got all the details right. I should also say that this was my first encounter with WPF and I found the MSDN documentation to be a little terse. In other words: there might be syntax errors above and better ways to do this, but I found the technique to have a separate WPF library with custom dependency properties to be pretty powerful.

Hudson love

Wednesday, December 26th, 2007

Some time ago I tried having a separate build machine performing continuous builds every time I checked my project sources into Subversion and I was quickly hooked. It’s a very simple idea but I always found it a little hard to fully appreciate the benefits before I tried it in a real project.

While having a build machine really shines with unit tests, it has a place even when you don’t have any unit testing at all in place. Firstly, you catch those time-consuming errors not having added all files to the version control system. Breaking a build wastes time for the entire team. Secondly, you have an incentive to keep the build process sane since the system gets built all the time. Building a system really should be as simple as checking the sources out and running a single command. Performing automated builds can help simply because setting up the builds becomes troublesome otherwise!

So here’s a suggestion for you existing project that does not have any unit tests: setup a build machine that builds the project every time someone checks something in. Then create a single unit test and have it run as part of the continuous build process. That’s it. You will now know that your project can be built and that it at least passes some simple test. Moving forward, you can for example make a point of creating a unit test for all new bug reports from customers. You decide, but knowing that your project builds alone can be worth quite a lot.

There are several applications for continuous integration to choose from. Most of them seem to have been developed within the Java community, but they are capable of running much more than Java builds and JUnit tests. The first build system I tried was CruiseControl because it seemed an obvious choice at the time. It has performed very well, though I remember it was a little cumbersome to set up. Since I recently needed to set up CruiseControl from scratch I figured I might just as well try Hudson out.

For me, the major advantage of Hudson, besides the much neater interface, is the packaging and running behavior. Hudson is delivered as a WAR file that you can deploy on any Java servlet container, but it also contains Winstone, a lightweight servlet container so that you can actually run Hudson “self-hosted” by simply going:


$ java -jar hudson.war

Starting a self-hosted Hudson on a Linux box as a daemon, typically requires an System V init.d script. I can post a little information on how to write such a script and have Hudson start each time your System V machine boots if you wish; It’s not hard since Hudson will run as a single process, but a better solution might be to deploy Hudson to a servlet container, like Tomcat, JBoss or Glassfish.

A reasonable choice of servlet container for an Ubuntu box is Tomcat, simply because it is available as an Ubuntu package. Installation requires you to enable the universe and multiverse repositories. Details on how to do that can be found here. Once those repositories are enabled, you can install Tomcat and Hudson on an Ubuntu box by following these steps:

We start by installing Java and Tomcat.


# apt-get install sun-java6-jdk
# apt-get install tomcat5.5

Sun’s Java should be the default but if it is not, you can select the default Java by:


# update-alternatives --config java

Tomcat on Ubuntu comes with the security manager enabled by default and this will cause Hudson not to run. You can disable the security manager by editing the /etc/default/tomcat5.5 file.

Next we need to set the home directory for hudson. Add the following line to /etc/tomcat5.5/context.xml


<Environment name="HUDSON_HOME" value="/srv/hudson"
  type="java.lang.String" override="false"/>

As you can see, I choose /srv/hudson as the home directory. See the FHS for details on that choice. Whichever directory you choose, create the directory and set the ownership so that the tomcat55 user can use it and restart Tomcat:


# mkdir /srv/hudson
# chown tomcat55.nogroup /srv/hudson/
# /etc/init.d/tomcat restart

Now, simply deploy Hudson by copying the hudson.war file into the /var/lib/tomcat5.5/webapps/ directory. Tomcat will notice the new file and deploy it automatically. Verify that it all works by pointing your browser to http://hostname:8180/hudson/ To update Hudson simply copy the new hudson.war file to the same location, overwriting the old.

If you wish to restrict access to Hudson, add the following two lines to /etc/tomcat5.5/tomcat-users.xml:


<role rolename="admin"/>
<user username="hudson-admin" password="secret" roles="admin"/>

Restart Tomcat and enable security in the Hudson System Configuration panel. Users not logged in will still be able to access builds but cannot adjust the settings or force new builds.

Update 2008-12-28:

I just verified that the installation instructions are still valid on Ubuntu 8.10 using Tomcat 6. All you have to do is replace tomcat55 with tomcat6 above; also, the port seem to have changed from 8180 to 8080. Here’s an updated installation summary:

Install Java and Tomcat.


# apt-get install sun-java6-jdk
# apt-get install tomcat6

Configure or disable the security manager:


  # vi /etc/default/tomcat6

Set the home directory for Hudson by adding the follwowing line to /etc/tomcat6/context.xml


<Environment name="HUDSON_HOME" value="/srv/hudson"
  type="java.lang.String" override="false"/>

Create the home directory, set the permissions and restart Tomcat


# mkdir /srv/hudson
# chown tomcat6.nogroup /srv/hudson/
# /etc/init.d/tomcat6 restart

Deploy Hudson by copying the hudson.war file into the /var/lib/tomcat6/webapps/ directory. Verify that it works by pointing your browser to http://hostname:8080/hudson/

SpatialAce WMS/SOAP and SAAJ/XPath

Saturday, February 25th, 2006

When developing a Java applet to work with SpatialAce WMS, you will probably work with the SOAP web service interface of SpatialAce WMS.

As usual, there are many options on the Java client side to choose from. SAAJ/XPath is a reasonable choice for an applet since it has a small implementation (the required JARs weighs in at only 384Kb compared to well over 1Mb for Axis) and compact API.

Using SAAJ/XPath, we can connect, query the SpatialAce WMS for layers and harvest the result with less than fifty lines of code. The first thing to do is to connect to the SpatialAce server and make the request.

(more…)

Touch screen map navigation

Saturday, February 18th, 2006

This video displays a serisously cool multi-input touch screen with some equally cool software.

Notice that a few minutes into the video, the user navigates some maps. That’s how I’d like my GIS systems to work! SpatialAce already has all the navigation functionality displayed in the video. All I want is that screen!

Spreading the gospel, part II

Wednesday, August 24th, 2005

I wanted to show a little bit more about working with SpatialAce when developing an application. The last demonstration showed how to display a background map, but not how to work with the object model and API.

A distance measurement tool is a really useful thing to have in most GIS applications so I’ve coded one up, split up in two separate movie sessions. The first session shows how to make a rubber-band tool that draws a line on top of the background map. In the second session, we add calculation of the line distance.

Notice how the result of each session is a nice, re-useable class in it’s own right. The rubber-band tool and distance calculator can be used separately in other applications without any change to the code at all. As a matter of fact, this is how most GIS programming with the SpatialAce object model work: with time, you tend to build up a library of components that you share among several applications.

Demonstration 1: a rubber-band tool, implementing the ITool interface. The coding here is a little terse, but I wanted to keep the length of the session under fifteen minutes. Just ask if there’s anything that’s confusing about the code.

Demonstration 2: Distance calculation, implementing the ICustomOperator interface. This contains a little more visualization work using the SpaceLab tool.

You can find the first demonstration where I created the base application here.

SpatialAce Flash Demo

Thursday, July 14th, 2005

OK, I’ve made a Macromedia Flash demonstration movie that shows how easy it is to create a GIS application using SpatialAce. In the demo, I create a simple application in .NET/C# with support for mouse navigation and drag’n'drop of SpatialAce configuration files.

I tried to be real careful when panning and zooming the map so that the Macromedia Flash compression would have a chance of keeping up. In reality, panning and zooming is perfectly fluid with no lag or stutter.

Here’s the demo.

GIS with SpatialAce

Wednesday, June 22nd, 2005

Carmenta, the company I work for, makes the best GIS engine for
application developers on the market today: SpatialAce. It sports 2D
and 3D map rendering with un-surpassed image quailty and one of the
most impressive lists of supported map data formats. It can be used
for development of stand-alone desktop applications, web servers or
hand-held devices.

So, if you’re tasked with developing a desktop application with
support for display of geografic information, you’d simply follow
these steps to get started:

  1. Create or download a map configuration for your map data
  2. Start Visual Studio, Borland Delphi or any other ActiveX enabled
    environment
  3. Drop the SpatialAce ActiveX control onto your application form
  4. Configure the ActiveX control to use the map configuration you
    just created
  5. Write some trivial GUI glue-code for the navigation tools that
    comes bundled with SpatialAce
  6. Done!

That’s really all there is to it. You don’t need to know or care
about the nuts and bolts of GIS if you don’t want to. Image
rendering, data access, projections and datums etc are all taken care
of by the SpatialAce map engine.