From Cory Eicher

Monday, February 27, 2006

Cartography in GIS: It's not just assigning symbols to geometry

I saw that James just posted about Cartography and ArcMap ... actually, before I even saw it, a few colleagues emailed me to tell me that they saw it. Helpful people that they are, they knew that I'm looking for ideas for my blog. So, for this entry, I'll piggy-back a bit on James' post.

Color Brewer
First, a great online resource for cartography that everyone should know about is Color Brewer (www.colorbrewer.org). This site was created by Dr. Cindy Brewer and Dr. Mark Harrower both cartographers, and this is the place to go online if you're not sure about what colors to use on your maps... and believe me, you're not sure about what colors to use on your maps! The site can basically be used as a "map colorer", telling you which colors/schemes to use for different types of maps and data.

Evolution of cartographic facilities in GIS Software
Yes, there's some exciting new functionality coming in 9.2 for cartography. Admittedly I'm a bit biased since I knew this stuff from inside ESRI, but perhaps I'll do some more convincing for your here.

9.2 cartographic representations allow you to edit feature symbology on a feature by feature basis. Pretty powerful as you can imagine for cartographers, but also as ESRI's Paul Hardy likes to say, for people that "just want a better map". Oh, and please don't forget the database! Symbology edits are stored in the geodatabase together with the feature data. Have you been waiting for ESRI to store .lyr/.mxd information in a database? Well, this is the first step...

Is 9.2 the beginning of better cartography from a GIS software package...? Of course not. Sticking with ESRI products, I'd say that a lot started with the ArcView 1x/2x/3x packages. In my opinion, GUI-based software can, and I emphasize _can_, produce better maps. Sure, people got by with ArcPlot, but GUI-based software a) makes "trial and error" easier (although I wouldn't recommend trial and error printing to large format printers when you're footing the paper/ink bill...), and b) GUI-sofware tends to be more WYSIWYG than say, creating maps from a command line app. 9.2 cartographic representations (call 'em reps for short) extend WYSIWYG capabilities in ArcMap by providing the ability to edit symbology.

9.2 cartographic representations aren't just editable symbology, they also employ better "automated routines"... (think better symbols). With reps, your maps can have better dashed lines, you'll have more control over the placement of symbols along lines, etc... Cartographers will eat this up, probably starting at the "top". What I mean by this is, organizations that have really strict cartographic requirements will be the first set of users attracted to this functionality. But, the usefullness of reps will have their use trickle down to many, many users...

A New Editing Paradigm?
Ah yes, paradigm, the word that I, the engineer, heard but wasn't quite sure how to spell during the first weeks of my graduate education in geography. 9.2 also provides new representation editings tools. Simplifying things greatly, these tools are "illustrator-like" allowing you do do things that just aren't very easy using the standard arcmap edit tools... such as modifying multiple features at once. Cartographers need to do this all the time (think offsetting several road line segments from a creek or river) and they don't want to think about topology when they do it, at least not in the sense that this is necessary in the pre 9.2 ArcMap editing experience.

Depending on how 9.2 reps are received by the public, in my opinion, their usability could spell big changes for the data-editing experience in ArcGIS... There are rumors of a huge change to the look/feel/architecture of arcgis at the next major release (10.0?). A big change to editing could be part of this.

Understanding Cartographic Representations
Are cartographic representations hard to understand? My answer is, yes, er.. possibly. James' UC blog post suggested that reps might be hard to "get", and I know that even big ESRI customers that use ArcGIS for cartography want more detailed information about how they can best use this new technology.

The Devil is in the Data
Like a lot of other things, when you need to do a lot of something with GIS, and do it often (such as produce a lot of maps, and produce frequent updates to these maps), it helps: a) to have your data in a database -- hopefully the ESRI geodatabase ; ), b) to have well modeled data, and c) to have well defined processes for creating and updating your data.

My experience with dealing with organizations that produce a lot of maps from GIS is that, well, most of their work isn't in the cartography, it's in dealing with the data... I'd postulate that this is pretty universal, whether you're producing maps, or performing watershed analyses, it helps to have a), b), and c) in pretty good order.

Design is Important
Design will always be important in cartography. It's no secret that most cartographers would like to see better maps than what we're currently seeing. Some of us (not me certainly) are like film critics: we'll tell you what we like and what we don't like, but we probably won't be able to (or won't want to?) tell you how to get there from the start.

The evolution of tools for cartography in ArcMap offers the promise for "better maps", but everybody knows that the ArcGIS 9.x Geoprocessing tools/environment didn't immediately start producing better glaciation models or better site selection analyses... I'd say that the same goes for new 9.2 cartography tools. There's potential for better maps, but resources (online, as James mentioned) and I'd add software documention and even software defaults, are needed to help end users benefit the most from new functionality...

... after all, anyone that's worked with the ArcView 3x technology has problably seen the, well, hideous jagged lines that appear by default in ArcView legends. Not to pick on anyone, but here's an example. The problem is that that this "toppled Z" symbol is the default legend pattern in the software, and not than many people change software defaults. One consequence of this is that you can still peg an ArcView 3x map simply by the appearance of lines in the legend.

Talk to you soon,

-Cory

Wednesday, February 22, 2006

1 if ByRef, 2 if ByVal...

ArcGIS Explorer
  • ESRI has posted an FAQ here: ArcGIS Explorer FAQ
  • If you have ArcGIS 9.2 beta (I don't), then you have ArcGIS Explorer. If not, you need to wait for the public beta (March?).
  • Are you registered to attend the upcoming AAG meeting in Chicago? If you are, be sure to see ESRI's David Maguire talk about ArcGIS Explorer (Thurs March 9th): David Maguire AAG Presentation Abstract
  • If you aren't registered for the conference, but you're in the area, you could always attire yourself as a starving graduate student, pop in around 2:45, and sit near the back of the room to hear what David has to say.

Copy/Paste Code Reuse


Ah yes, who hasn't copy pasted code to get a head start. Really there's no problem with this normally, but here's something that happened to me last week, pasting some of my own code no less..

I wrote a few subroutines in ArcMap VBA just to get going. After a bit I brought this code over to VB.NET.

I had a problem bringing one of my subs over, and I didn't figure out what was wrong for a long while. Can you guess what I did?

Well, the top of my sub looked something like this:

Private Sub CalcLineStartEndID(InLayer As IGeoFeatureLayer, _

ByVal LineID As String, _

StartID As Integer, _

EndID As Integer)
And then, towards the end of my sub I did something like this:

StartID = iMinSta

EndID = iMaxSta

So, StartID and EndID are ByRef parameters that I calculate during the sub. Okay, an OO purest would slap me on the wrist, but this is what I felt like doing that day..

Anyway...the problem is, (when you paste this blindly into VB.NET before having your morning cup of coffee or green tea), you get this:

Private CalcLineStartEndID(ByVal InLayer As IGeoFeatureLayer, _

ByVal LineID As String, _

ByVal StartID As Integer, _

ByVal EndID As Integer)


That's right, by default, in VB.NET params are ByVal...so, StartID and EndID become ByVal params, but everything 'pastes in' fine, compiles fine, etc... Just, when you run/test your code, well, things don't work quite the same... Lesson learned.

Talk to you soon,


-Cory

Wednesday, February 15, 2006

How to write a layer context menu command in C#

Another technical post today, but I promise that my next post will be lighter-fare...

So, yesterday I was researching how to do something with ArcObjects, and since I'm forcing myself to eat the healthy cereal that is C#, as opposed the sugary VB.NET that I'm used to, I did everything in C#.

I was trying to figure out how to add a custom command to a standard ArcMap layer context menu (doing all of this with code of course). In other words, I wanted my command to appear when a user right clicks on a layer in the ArcMap table of contents..

This is easy to do from VBA. If you've already compiled/registered your custom C# command, you can just write a little sub like this:

Sub AddCommandToLayerContextMenus()

' custom command
Dim pCommandUID As New UID
pCommandUID.Value = "MyNamespace.MyCustomCommand"
' or use GUID
'pCommandUID.Value = "{F9B2E774-29A0-4eaa-B8E2-D26DA1F21CB2}"

' add to feature layer context menu
Dim pCmdBar As ICommandBar
Set pCmdBar = ThisDocument.CommandBars.Find _

(arcid.FeatureLayerContext_Menu)
pCmdBar.Add pCommandUID

' add to group layer context menu
Set pCmdBar = ThisDocument.CommandBars.Find _

(arcid.GroupLayer_ContextMenu)
pCmdBar.Add pCommandUID

' add to raster layer context menu
Set pCmdBar = ThisDocument.CommandBars.Find _

(arcid.RasterLayer_ContextMenu)
pCmdBar.Add pCommandUID

End Sub


But, I wanted to manage all of this from my C# code. So, I wrote a custom extension that automatically adds my command to several ArcMap layer context menus on start up.

I've documented this here: How to Add a Custom ArcObjects C# Command to a Standard ArcMap Layer Context Menu

Talk to you soon,

-Cory

www.eicher-gis.com

Saturday, February 11, 2006

Diving into C#

Outside, it's been a chilly few days here in Denver, which has given me the opportunity to ramp up some of my skills. I'm a VB guy, but recently I dove into building some ArcObjects components in C#. The experience reminded me of a long-ago, early-morning, Adirondack scout camp, "polar bear" swim. Standing before the icy black, I shivered at the thought of jumping in... but the experience was surprisingly painless, and it was over and done before I knew it.


I started by working through the ESRI C# Walkthrough: Creating a simple command for ArcMap

Since I'm using Visual Studio 2005 (.NET 2.0) and I'm also using the Visual C# Express Edition, I found a few differences from the ESRI documented steps. I figured I'd note those differences here:

Create a new class library

Steps worked fine

Reference the ESRI object libraries

I found it useful to also reference to ESRI.ArcGIS.Utility. I used this later for component category registration.


Create a zoom-in command

Steps worked fine

Add a using directive

To define my class, I modified the default .cls. By default, you'll get these directives:

using System;

using System.Collections.Generic;

using System.Text;

I found that I only need the first, and I also added this directive:

using ESRI.ArcGIS.Utility.CATIDs;


Implement the ICommand interface

ESRI Step 4 states "Right-click the ICommand interface, click Add, and then click Implement Interface"...I couldn't find this functionality. Perhaps its because I'm using the Express version...
So, I manually stubbed out my class...actually, I copy/pasted from another ESRI dev sample.

Adding code to the members of ICommand

IntPntr is defined in System, so you'll either need a directive (see above), or you'll have to fully qualify:

private System.IntPtr m_hBitmap;

Returning the ICommand::Bitmap property

Steps worked fine

Expose the ZoomIn class to COM

To reg. for COM interop, Goto Project > Properties > Build > Register for COM interop. Also, maybe this is obvious, but I had to add GuidGen.exe as an External Tool (again, I'm using the Express Version of Visual Studio). Location for me was: "C:\Program Files\Microsoft Visual Studio 8\Common7\Tools"

Adding COM category registration functions

I did this differently. Since we're using ESRI.ArcGIS.Utility.CATIDs, you can do this instead:

#region "Component Category Registration"

[ComRegisterFunction()]

static void Reg(string regKey)

{

MxCommands.Register(regKey);

}

[ComUnregisterFunction()]

static void Unreg(string regKey)

{

MxCommands.Unregister(regKey);

}

#endregion

Compiling the project, Use the command in ArcMap

In order to get a .tlb, I had to go to Project > Properties > Application > Assembly Info > and check 'Make Assembly COM-visible'

Stepping through the command with the debugger

I found that I wasn't able to do this with the Express Version of VS... but I was hungry for lunch and I didn't try to hard...

Talk to you soon,

-Cory

www.eicher-gis.com

Wednesday, February 08, 2006

Making Progress

A more accurate title for today's entry might have been 'Showing Progress'.

In writing some VB code recently, I found two things in ArcObjects that made what I was doing much easier than similar functionality in vanilla VB. Both involve providing progress feedback to the user.

Exhibit A - Showing Progress While Exporting:
To get an image or vector graphic out of ArcMap, you can use IExport. So, for example you can export from the data view to get 'just the data', or you can export from layout view to get 'the whole map', including map elements such as graphics, scale bars (not sure why you'd need more than one ; ) , etc. You probably already knew this... There's a good sample here:

(esri edn) Export Active View to JPEG Sample

What you might not have known is that there's a really easy way to show progress when exporting. If you're like me, you might not want to monkey around with creating your own logic for showing progres... So, just do this:

IExport has a property StepProgressor. This property expects an object that supports, you guessed it, IStepProgressor. More importantly, the ArcMap framework has a status bar that has a progress bar that supports this interface. So, all you need to do is get ahold of the ArcMap application thru IApplication and connect its progress bar to the export object like this.

Dim pApp as IApplication
Set pApp = Application
Set pExport.StepProgressor = pApp.StatusBar.ProgressBar


Then, go ahead with your export. Your users will see export progress in the ArcMap status bar (lower left of the ArcMap window).

Exhibit B - Showing a Wait Mouse Cursor:
ArcObjects has its own MouseCursor object. For what I was doing today, I found it to be very convenient.

Dim pMouseCursor As IMouseCursor
Set pMouseCursor = New MouseCursor
pMouseCursor.SetCursor 2 ' wait cursor (gets reset automatically at end of sub)

Talk to you soon,

-Cory

www.eicher-gis.com

Friday, February 03, 2006

How to Efficiently Extract Values from a Raster at Many Points

Today I had a conversation with myself on the ESRI ArcGIS Desktop - ArcObjects General forum.

Forum Thread

In the end, I have two conclusions:

1) Using IIdentify.Identify on a RasterLayer is a very inefficient way of extracting the raster value at an X, Y point. Better to use IRaster.Read... but make sure you pay attention to your coordinate units.

IIdentify.Identify interprets incoming x, y values as data units (I have no projection on the fly going on in my data frame)

IRaster.Read interprets incoming x, y values as pixel counts from the origin of the raster data.

2) Sometimes you can solve problems by talking to yourself.

Talk to you soon,

-Cory

www.eicher-gis.com

Thursday, February 02, 2006

Everybody's Doing It

Everbody's doing what you might ask? Well, two things. First, everyone's blogging, on everything, software, GIS, other "stuff"..., so why not me?

Second, everyone's migrating their VB ArcObjects development to .NET (everyone that hasn't already that is)... so, in this, my first post, I have some tips for you.

First, just a few sentences to introduce myself. As an independent GIS and cartography consultant I work with ArcGIS and ArcObjects mainly focusing on the desktop applications. I'm a long time VB programmer who moved to the world of VB.NET 18 or so months ago, and I'm finding it very much to my liking.

I'll start things out with a few tips for anyone that is now, or will soon be, migrating their ArcObjects development from VB6 to VB.NET. There's a lot to think about, and the points below are by no means an exhaustive, or even an orgainzed list.

1) I think that Visual Studio .NET is an improved development environment compared to VB6 and it makes me much more productive as a developer. For VB6 developers, the .NET and the .NET IDE has great features (error highlighting, code completion, "helper" libraries, etc.), and these improvements more than compensate for any initial unfamiliarity with the language syntax.

2) When migrating your In ArcObjects code, one big thing that you need to know about migrating is that some members are "non-compliant" in .NET. This is just a fancy way of saying that they "don't work" in VB.NET/C#.
So...bookmark this page:

(esri edn) Migrating .NET Code and Non OLE Compliant Members

Non-compliance is the type of thing that can really trip up a developer because the errors that result are really hard to translate, and the individual ArcObjects (as you might have guessed) aren't specifically documented with this info.

3) Now that you're in .NET, you'll need to take another look at how you deploy applications/components written in .NET. As with most any deployment, my strategy for this is to just "figure it out once and reapply the strategy over and over". Here are some general things to keep in mind. See my next point for some specific help with .NET and VBA.

a) To use your .NET component, client machines will need to have: MS .NET runtime 1.1 or 2.0. 1.1. is part of the XP install now, I'm not sure when 2.0 will be.

b) Client machines also need the ArcGIS .NET interop assemblies. These are installed from the ArcGIS Deskop install (NOT the developer toolkit install). One tricky thing is that you need the MS .NET 1.1. runtime installed BEFORE you even have an option to install the ESRI libraries.

c) Finallly, you won't use the old regsvr.exe to register COM components.Instead, there's a .NET application called regasm.exe that, well, does similar but different things.
There's some good online documentation about this from esri that'll point you in the right direction:

Short but sweet: (esri edn) Registering Components With COM

Heavier weight: (esri edn) Deploying .NET Components

4) A fact of life we'll be living with for awhile is that, well, Microsoft has moved on to .NET, but ArcGIS is still built on COM. Of course, this obviously doesn't prevent you from developing ArcGIS components in .NET, it's well documented how to do this in the esri and ms doc.
But, what about VBA? I asked myself the other day..into night. What about the library of .NET objects that I built (for converting ArcGIS "stuff" to google kml "stuff" btw). These objects _use_ arcobjects, but aren't arcobjects components. They're just, well, classes that do "stuff".

How can I use these in from ArcMap VBA for example (or from VB6, or from Catalog's VBA, etc.)

Well, I found what I would say is the most informative piece of information I've found on the internet in a long time.

Read this article: (15 seconds) COM Interop Exposed

It will tell you how to expose your .NET classes to COM, so that you can use your objects in VBA, or VB6, etc. This article is a gem, I followed the steps, and I'm now using my objects in VBA.

Talk to you soon...

-Cory

www.eicher-gis.com