Tuesday, December 8, 2009

Silverlight Combobox with keyboard input

Recently I had to create some comboboxes in a silverlight app that contained quite a few items. Scrolling through so many items in the list made it difficult to find what you want. I wanted the combo to respond to keyboard input such that I could press a key and have it jump to the first item in the list that started with that letter. I was kind of surprised not to find this as a standard property of the silverlight combo.

The solution I came up with uses the KeyUp event to select the appropriate item in the list. The trick is, you need to handle the KeyUp event for the Combo as well as the ItemsPanel of the combo. Once you start scrolling or interact with the list, you are interacting with the ItemsPanel of the combo, so you need to handle the events there if you want to allow keyboard input multiple times. The XAML looks like this:

<ComboBox
  Width="50"
  Height="20"
  x:Name="cboSimple"
  KeyUp="cboSimple_KeyUp" >
  <ComboBox.ItemsPanel>
    <ItemsPanelTemplate>
      <StackPanel KeyUp="cboSimple_KeyUp"/>
    </ItemsPanelTemplate>
  </ComboBox.ItemsPanel>
  <ComboBoxItem Content="A" />
  <ComboBoxItem Content="B" />
  <ComboBoxItem Content="C" />
  <ComboBoxItem Content="D" />
  <ComboBoxItem Content="E" />
</ComboBox>


Now when you handle the event you to select the item in the combo. So instead of working with the sender for the event, you will work with the combo by name. LINQ can be used for finding all the items that start with the letter selected on the keyboard.


private void cboSimple_KeyUp(object sender, KeyEventArgs e)
{
  SelectItemInCombo(cboSimple, string.Format("{0}", Convert.ToChar(e.PlatformKeyCode)));
}
private void SelectItemInCombo(ComboBox cBox, string keyLetter)
{
  IEnumerable<object> itemsWithStartcChar =
  cBox.Items.Where(c => ((ComboBoxItem)c).Content.ToString().StartsWith(keyLetter));

  if (itemsWithStartcChar.Count() > 0)
  {
    cBox.SelectedItem = itemsWithStartcChar.First();
  }
}


Notice that first I do a select so I can get a count of the items that start with the letter that was pressed. Without this you get an exception on the First function if the list is empty.

This is also a very simple list. If your combo contains more than simple strings you will need to find the string within the ComboBoxItem that you are sorting by.

Tuesday, December 1, 2009

ArcGIS Server and Virtualization

I've gotten several questions lately regarding virtualization and capacity planning with regard to ArcGIS Server. Below are my answers to some of these questions.

Q: What is ESRI’s official supportability of virtualization of ArcGIS Server?
A: ArcGIS Server is supported in a virtualized system. See: http://www.esri.com/software/arcgis/arcgisserver/common-questions.html. Go down to Standards | Interoperability | IT | Security. The third question down deals with virtualization. Basically, virtual systems are treated the same as physical systems.

Q: What versions of Microsoft Windows are supportable deployments? 32 or 64bit support?
A: The same as support for physical systems. http://wikis.esri.com/wiki/display/ag93bsr/Web+ADF+for+the+Microsoft+.NET+Framework.

Q: What kind of resources (RAM / CPU / Disk) do I need to allocate to ArcGIS Server?
A: It all depends on the services that you are using, the applications that consume those services (desktop, web/server, web/browser), and the number of users that will be interacting with the system. The book Building a GIS discusses how to use the Capacity Planning Tool that you can use to estimate capacity. You can find info on that here: http://esripress.esri.com/display/index.cfm?fuseaction=display&websiteID=141&moduleID=27. To get a more exact picture of performance and scalability you should test an application in a configuration to see how many users it will support. There is information on how to do this here: http://resources.esri.com/arcgisserver/adf/dotnet/index.cfm?fa=mediaGalleryDetails&mediaID=6D73B2DB-1422-2418-344143680A5154BA


Q: Are there any special considerations for virtual systems?

A: The one performance issue that usually plagues VM’s is disk IO. ArcGIS Server tends to do a lot of disk IO. Geoprocessing services do the most disk IO but even a simple dynamic map request involves a write to disk. So improving the performance and scalability of your disk IO will have a significant impact on system performance. For this reason, I prefer to put my ArcGIS Server, server directories on a SAN. I’m not talking about a virtual disk on a SAN, I mean the SAN is attached directly to the VM. This way, you get the fast disk IO from your SAN without the dealing with the disk IO of the virtual machine. This also makes it easier to allocate space for the machine and it makes it easy to share the same server directories between VMs.

Thursday, August 13, 2009

ArcGIS Server installed on a domain controller

Several folks have asked me if it is ok to install ArcGIS Server on a domain controller. The simple answer is no. The main reason is the GIS server uses local groups to control access and a domain controller does not allow for local groups. Another really good reason is that Microsoft says that you shouldn't use a domain controller as a server for IIS or otherwise.
See:
http://www.microsoft.com/windows/windows2000/en/server/iis/htm/core/iisckl.htm (under specifically Do not use PDC as a server)
And
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/3a0742c4-f45a-4504-a232-83dd085bcfb3.mspx?mfr=true

Tuesday, July 7, 2009

Image compression for Ortho map cache

I took a minute today to analyze how much JPEG compression is appropriate for cached map services (ArcGIS Server) that are displaying an aerial photo. With JPEG compression you can set the quality between 1 and 100. 100 is more quality but less compression. Wikipedia actually has a great example of this. All of this stuff also applies to creating a map cache for imagery. So I set up a little test to see what the difference is between JPEG 90 and JPEG 55. I used 2008 orthophotography imagery for Hamilton county Indiana. I cached the map using the Bing Maps / Google Maps tiling scheme. Then I added a scale (1:575) on the bottom to build the cache down to the resolution of the 6 inch imagery. I figure this is what most people would do to get their full raster resolution in the map cache. The cache took a little over 9 hours to create for both services (2x3.59 Ghz CPU's). The first big difference was the size:
  • JPEG 90: 32.8 GB
  • JPEG 55: 15.1 GB
So JPEG 55 is about half the size of JPEG 90. That means that it will download about twice as fast in a web browser. Of course this is only part of the overall performance of the application but still it is pretty significant. Now what about the quality?

JPEG 90 at small scale




JPEG 55 at small scale




JPEG 90 at medium scale




JPEG 55 at medium scale




JPEG 90 at large scale




JPEG 55 at large scale




For my money the decision is pretty easy. JPEG 55 is half the size and very close on quality. You should certainly test this out when building your own cache though. Also, this is assuming there is no vector data in the map. When you have vectors in your map you need to go with JPEG 90 to keep the lines crisp. Or a better option would be to seperate the vectors into their own service and draw them on top of the ortho. This way you could use PNG 8 for the vector and JPEG 55 for the raster and get the best of both worlds. You can see that google maps is even doing this with their image service.

Wednesday, July 1, 2009

ArcGIS Server and map service projection on the fly

With ArcGIS 9.3.1 and the "Analyze Map" tool on the Map Service Publishing toolbar folks are realizing that projection on the fly can have a huge impact on map service performance. This leads people to think that maybe they need to project all of their data to WGS 84 or WGS 84 Web Mercator to get the best performance in their map services. This blog discusses projection on the fly as it pertains to performance for MXD or MSD based map services.

As a general rule I don’t think you need to projecting everything to WGS84 (or whatever coordinate system you are mashing up with). Map services do perform best when there is no projection on the fly happening in the MXD / MSD. But there are two places that projection on the fly can happen: within the MXD/MSD and within the map service. When you do projection on the fly within the MXD/MSD you are doing this projection on every layer in the map on every map service request. This is a lot of work and this can have a big impact on performance. When you do projection on the fly in the map service you are projecting the resulting map. This projection happens once for the entire map per request and is therefore much faster than the MXD/MSD projection on the fly.

When you have a dynamic map service who's map is using UTM (or some other local CS), it will automatically project on the fly to other map services in your application. So if you are using a WGS 84 base map from ArcGIS Online, your dynamic UTM service will overlay just fine.

Performance tip: with dynamic services, set the projection of your map to the same projection as your data.

This map service projection on the fly, does not work with cached map services. So for those map services that you are going to cache (all base maps and some of your operational layers), you need to change the projection of the map to the projection of the other services you are going to mash up with (e.g. WGS 84 or WGS 84 web mercator). In this case you would pay the price for projecting on the fly within the MXD/MSD. This would slow down your cache creation but you would get the great performance of a cached map service on each map service request. If you are building a very large cached map service, you should probably consider extracting your data to a file geodatabase just for the cache creation. A local (to the GIS server) file geodatabase is going to give you your best performance for cache creation. When you create this copy of the data for cache creation, you can project it to the coordinate system of your map service (e.g. WGS 84). The best tool for doing this is the Extract Data Wizard. Check out “Copying a geodatabase using the Extract Data Wizard in ArcMap” here: http://webhelp.esri.com/arcgisdesktop/9.3/index.cfm?TopicName=Methods_for_copying_geodatabases

Here is info on extracting data to a different coordinate system.

http://support.esri.com/index.cfm?fa=knowledgebase.techArticles.articleShow&d=34129

The Extract Data wizard is a great tool for this because it can create a copy of your map document that uses the extracted data.

In summary, store your data in the coordinate system that makes the most sense for your data maintenance, management, and analysis. Your map services can use this data to make fast maps in any coordinate system. One final curve ball is that ArcGIS Online will be moving to WGS 84 Web Mercator later in 2009 (see the ArcGIS Online blog for more information ).