Friday, July 16, 2010

Presentation AddIn for ArcGIS Desktop 10

Presentation AddIn for ArcGIS Desktop 10

About this time last year, the Applications Prototype Lab at ESRI published a presentation tool for ArcGIS 9.2/9.3.  That release is discussed here and can be downloaded from the old code gallery here.

Today, the lab released a new version of the presentation tool as an AddIn for ArcGIS 10.  This AddIn is similar to the presentation capability recently added to ArcGIS Explorer.  The AddIn can be downloaded here from the new code gallery.

The AddIn was developed in C# for .NET 3.5 and utilizes the graphics capabilities of WPF.  Full source code is provided with the code gallery download.

Thursday, July 15, 2010

Touch for ArcGIS Desktop 10

Touch for ArcGIS Desktop

Just published on the ArcGIS Resource Center is a proof-of-concept developed by the ESRI’s Applications Prototype Lab called Touch for ArcGIS Desktop. This contribution is an AddIn that adds touch navigation to ArcGlobe.  The contribution can be downloaded from here and includes the AddIn itself and full source code.  The download page includes instructions how to install and use the AddIn.

The AddIn will install on any computer running ArcGIS 10 but a warning message will appear if you do not have a Windows 7 Touch-enabled device connected.

This AddIn is based on code from the Windows 7 Multitouch .NET Interop Sample Library.

GeoTagger for ArcGIS Desktop 10

Geotagging text from an English web page  Geotagging text from an Arabic web page

Have you ever wanted to extract geographic locations from an email or web page? This is now possible with the free GeoTagger AddIn for ArcGIS Desktop 10 published by the Applications Prototype Lab. The AddIn uses MetaCarta’s public geotagging web service to extract geographic references from text. The service supports English, Russian, Spanish and Arabic.

The AddIn is available here from ESRI’s ArcGIS Resource Center.  The download page includes usage and installation instructions.  Source code is bundled with the download.

Wednesday, July 14, 2010

Dynamic Charting for ArcGIS Desktop 10

Late last year ESRI’s Applications Prototype Lab released the dynamic charting tool for ArcGIS Desktop 9.2/9.3.  This tool provided the unique ability to display dynamic pie charts during editing operations.

Today, the lab released a new version of the tool for the newly launched ArcGIS Desktop 10.  The tool features a number of improvements:

  • Ability to switch between a pie chart and a column chart,
  • Ability to pick any summary field other than area, for example, cost or mineral volume,
  • Improved performance, the charts are only updated following an editing operation such as an add or delete.  Previously updates occurred at regular time intervals.
  • The legend is now sorted alphabetically,
  • And mostly importantly, the user interface colors have been toned down.  :-)

The new tool can be downloaded from the ArcGIS Resource Center from this link.  The download includes full source code.  The tool is developed as a desktop AddIn and is written in C# using WPF and the WPF Toolkit.

Tuesday, June 29, 2010

Cloning Path Geometry in Silverlight

image

To add depth to a line rendered on a map, I experimented with the drop shadow bitmap effect. The shadow looked great but it had a heavy performance cost. As a workaround, I substituted the bitmap effect with a cloned path. Unfortunately Silverlight does not support path geometry cloning, unlike WPF, so based on a Silverlight.net forums thread I implemented a value converter that clones path geometry.

The second path below is the original street route displayed in blue above. The first path clones the blue path’s geometry and offsets it by a few pixels.

<Path Opacity="0.5"
      StrokeThickness="5"
      StrokeLineJoin="Round"
      Stroke="Gray"
      Data="{Binding ElementName=Element,
                     Path=Data,
                     Mode=OneWay,
                     Converter={StaticResource GeometryConverter}}">
    <Path.Resources>
        <local:GeometryConverter x:Key="GeometryConverter"/>
    </Path.Resources>
    <Path.RenderTransform>
        <TranslateTransform X="6" Y="6" />
    </Path.RenderTransform>
</Path>
<Path x:Name="Element"
StrokeThickness="5"
StrokeLineJoin="Round"
Stroke="Blue"/>

Below is the code for the value converter.  The code uses reflection to clone the geometry of the original path.

public class GeometryConverter : IValueConverter {
    public object Convert(object value, Type targetType,
object parameter, CultureInfo culture) { // Test for Null if (value == null) { return null; } Geometry g = value as Geometry; if (g == null) { return null; } Geometry clone = Clone(g) as Geometry; return clone; } public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture) { throw new NotImplementedException(); } private static object Clone(Object obj) { // Get all properties and clone them. PropertyInfo[] properties = obj.GetType().GetProperties(); object cloneObj = obj.GetType().GetConstructors()[0].Invoke(null); foreach (PropertyInfo property in properties) { object value = property.GetValue(obj, null); if (value != null) { if (IsPresentationFrameworkCollection(value.GetType())) { object collection = property.GetValue(obj, null); int count = (int)collection.GetType().
GetProperty("Count").GetValue(collection, null); for (int i = 0; i < count; i++) { // Get each child of the collection. object child = collection.GetType().
GetProperty("Item").
GetValue(collection, new Object[] { i }); object cloneChild = Clone(child); object cloneCollection = property.
GetValue(cloneObj, null); collection.GetType().
InvokeMember("Add",
BindingFlags.InvokeMethod,
null,
cloneCollection,
new object[] { cloneChild }); } } // If the property is a UIElement, we also need to clone it. else if (value is UIElement) { object obj2 = property.PropertyType.
GetConstructors()[0].Invoke(null); Clone(obj2); property.SetValue(cloneObj, obj2, null); } // For a normal property, its value doesn't need to be
// cloned.
So just copy its value to the new object. else if (property.CanWrite) { property.SetValue(cloneObj, value, null); } } } return cloneObj; } private static bool IsPresentationFrameworkCollection(Type type) { if (type == typeof(object)) { return false; } if (type.Name.StartsWith("PresentationFrameworkCollection")) { return true; } return IsPresentationFrameworkCollection(type.BaseType); } }