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);
xDoc.Save(fileName);
}
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!