So I'm getting ready to cook up a tile cache, and I want to use the ESRI ArcGIS Online tile scheme so I can use their tiles for the first 10 or so zoom levels. To do this, you need to have your map's spatial reference set to WGS84, which was not a problem when I was setting up the "Road Map", but I ran into a snag with the "Hybrid" (roads + parcels + orthos) - the Ortho images did not have any spatial reference defined - which means that ArcMap could not project them. Doh!
Now - I should point out that there is likely a neat-o way to do this with some Geoprocessing Python, but I'm a .NET guy, so I used my .NET hammer to solve this.
Ive done enough with images over the years to know that the spatial reference will be stored in the .aux.xml files that share the name of the raster. But for one set of images, there were no .aux.xml files. Solution: Open all the files in ArcMap and it will create these files. Sweet.
Next up, for one raster, I manually set the correct spatial reference in ArcCatalog. Easy, but there are several hundred files, so it's not going to work as a solution. Enter System.Xml...
I then opened up the .aux.xml file (in notepad) for the raster that I manually assigned a spatial reference to, and simply copied the projection information from the <SRS> element. I then cooked up a simple loop over all the files, opened them up in an XmlDocument, injected or updated the <SRS> element, saved the file and shazam! all done. The pertinent function is below.
private void UpdateSpatialRef(string folderPath, string srs)
{
//Loop over all the xml files, open as xml doc, inject the SRS node, save
string[] fileNames = Directory.GetFiles(folderPath, "*.sid.aux.xml");
for (int i = 0; i < fileNames.Length; i++)
string fileName = fileNames[i];
//Open the file
XmlDocument xDoc = new XmlDocument();
xDoc.Load(fileName);
//find the SRS element if it's here
XmlNodeList srsNodes = xDoc.SelectNodes("//SRS");
XmlElement srsEl = xDoc.CreateElement("SRS");
srsEl.InnerText = srs;
if (srsNodes.Count > 0)
//Already set... replace
if (xDoc.DocumentElement.FirstChild.Name == "SRS")
xDoc.DocumentElement.ReplaceChild(srsEl, xDoc.DocumentElement.FirstChild);
xDoc.Save(fileName);
}//if it's somewhere else in your doc, it's likely bad & you've got other problems!
}
else
xDoc.DocumentElement.PrependChild(srsEl);
Console.WriteLine("Fixed: " + fileName);
While more over the top than may be necessary, it was quick to write and solved my problem... now to kick off the cache creation!
I'm Dave and this is my blog. I'm usually writing about .NET Software Development, ArcGIS, or Agile Practices, but other stuff does creep in from time to time. I hope you find something of use, and feel free to contact me if you have any questions. You can also check out my profile on LinkedIn
dojo.DTSAgile.com is our technology preview / demo site. As I and my team cook up cool things we post them here.
ArcDeveloper.net is a site that hosts a set of open source projects related to ArcGIS. This includes Tile Cache for .NET (TC4N) and Feature Server for .NET (FS4N). Come over and check it out!
Assembla is a free service that provides Subversion source control, wikis and work Tracking. The ArcDeveloper project is run from here. It rocks. Check them out today.
Agilistas is a LinkedIn group focused on discussing and promoting Agile practices. Everyone is welcome to join in the conversation as we evolve the process of creating software to make it more enjoyable for all involved.