Could not load file or assembly

So, I changed jobs recently* and have been mostly brushing off my C# skills to write ArcGIS Addins. This has been largely frustrating, as Esri and Microsoft have joined forces to make things as difficult as possible. For example:

 

 

This error message was particularly annoying, as it is fairly ambiguous. The full text isn’t much more enlightening:

Could not load file or assembly xxxx or one of its dependencies. The system cannot find the file specified. C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\TeamTest\Microsoft.TeamTest.targets

If only there was a way for the system to tell my which dependency it was having a problem with. Never mind, I’ll go through them all one by one and get there eventually.

For the record, the culprit was ESRI.ArcGIS.Desktop.AddIns, and the solution is to change the CopyLocal flag to true. Makes sense that if the file isn’t copied locally, it can’t be found.

The question is, why was CopyLocal set to false in the first place? I’m sure it was true last time I looked. Not only that, but this bug has come back a few times. At least I know what the fix is this time. I still didn’t know why that flag kept changing, even though I’ve done many searches.

Finally today, I worked out what was going on – the CopyLocal flag is reset every time you update the file Config.esriaddinx. Why should it do this? Who knows, but at least I know the solution now, and I’ve written it down, so when I start searching for the answer in three months time, I’ll find it!

*Actually four months ago, but geologically speaking, that’s just a blink of an eye.

Advertisements

Labelling related features

There hasn’t been much GIS on this blog recently, so I’m going to talk about an interesting problem I saw recently. A user was trying to add some road labels to a map, but wanted the label to show the name of the next town along the road, much like the John Ogilby strip maps below: “to Thorp”, etc.

Ogilby 1675  Ogilby Garstang-Carlisle

The house style he was working with showed districts, roads and cities, but only a single district of interest was shown at one time. No features were visible outside this district polygon. I tried to achieve the effect he was after, and I think I managed, although the method isn’t completely straightforward. I’m going to go through the required steps here, using one of my US datasets. Obviously, you’ll need to change some of the layer and attribute names if you want to follow the example with your own data.

Open Arcmap and add the data to the map. In my case, a point layer (Cities), a line layer (USHigh), and a polygon layer (States).We only need to show a single state of interest, so right-click States in the Table of Contents (TOC) > Properties > Definition Query tab and enter the query: Name = ‘Indiana’.

My data is showing too many cities, so I’ll thin them out in the same way, using a definition query to only show features with a population greater than 100,000.

Image 1

Now the highways need to be clipped so only the features within Indiana are showing. Open the Clip Geoprocessing (GP) tool and run with the following inputs:

Input:USHigh
Clip: States
Output:USHigh_Indiana

Image 2

It gets a bit tricky here, as Maplex can only place labels at the beginning or the end of a line. Unfortunately, some of the lines will need labels at the beginning and some at the end, depending upon which direction they were digitised. You may be lucky and find that all the features were digitised starting at the centre of the state and moving towards the boundary (or vice versa), but it’s not very likely. Open the Label Manager and set the Label Field for USHigh_Indiana to OBJECTID, Label position should be Centered curved, and the properties in the Offset dialog should look like this to push the label off the end of the line:

Offset properties

It is also a good idea to go to the Label Density tab, uncheck Connect features, and make sure the combo is set to One label per feature. It’s likely that some roads will point to the same city, so we don’t want Maplex to “helpfully” connect up those features and remove some labels

Image 3

As you can see, some of the labels are placed at the end of the line features, outside the state boundary, but some are at the other end of the line, inside the state. These latter labels will need to be placed differently, using the After end of line option. Create two new label classes on the USHigh_Indiana layer, called Start and End, and change the label offset to After end of line for the End label class.  Then create SQL queries for each class to select the correct features (Label Manager > SQL Query button). Now you should have one label coming off the end of each highway.

Image 4

Now we need to relate each highway feature to the nearest city. We don’t want to consider the cities within Indiana, so we need to create a selection layer that only contains cities outside the state. There are two ways of doing this: select all then remove the features within the state, or select the features within the state, then switch the selection. I’m going to use the second method.

Go to Selection > Select by location. Selection method = select features from, Target layer = Cities, Source layer = States, Spatial selection method = intersect the source feature layer. Click OK.

Right-click Cities in the TOC > selection > switch selection

Right-click Cities in the TOC> selection > create layer from selected features

Now we can run the Near GP tool with the following inputs:

Input features: USHigh_Indiana
Near features: Cities selection

This creates a field called NEAR_FID on each highway feature, which can be used to create a join to the Cities layer.

Right-click USHigh_Indiana in the TOC > Properties > Joins & Relates tab > Joins > Add… 1. Layer join field = NEAR_FID, 2. Table = Cities selection, 3. Table join field = OBJECTID.

Now we can change the label field to Cities.CITY_NAME, or even better, a label expression of: “To “ & Cities.CITY_NAME. Also, the SQL queries will need to be updated so OBJECTID becomes USHigh_Indiana.OBJECTID. I find it easier to copy the whole query, paste into a text editor, such as Notepad++, do a find and replace, then copy and paste it back into the query window, rather than editing each clause in the query. [Note: some dialogs in Arcmap do have find and replace functionality, e.g. the Convert Labels to Annotation dialog. It’s not documented, but you can click on the Annotation Feature Class column and press ctrl-H to quickly change part of the class name for every layer at once.]

Image 5

This should give us the result we’re after, but something is not right. If you look at the western border of the state, the two higways that point to Springfield are actually labelled “To Cincinatti”, and the highway to the south is labelled “To Nashville-Davidson”, when it should be St. Louis. The problem is that the Near tool finds the nearest feature  to any part of the input feature – the eastern end of the highway is closer to Cincinatti than the western end is to Springfield.

To get round this, we could shorten the feature, so only the end near the border is used. To isolate part of the highway near the state boundary, we need to create a clip shape of the inner edge. First run the Feature to line GP tool with States as the input feature, then run the Buffer GP tool with a distance of 0.25 Degrees. Now Clip USHigh_Indiana, calling the output layer USHigh_Indiana_Labels. The state border (red), buffer (yellow), and clipped highways (green) are shown here.

Image 6

Rerun the steps above, using the USHigh_Indiana_Labels layer. Change the symbology to have no colour – we’ll leave the USHigh_Indiana layer on to show the location of the highways within the state (but make sure you turn off the labels for this layer).

Image 7

Now the highway labels are showing correctly, we need to declutter the map by removing the outside cities. Create another selection layer of just the cities within Indiana and label this instead. To copy the symbology from the Cities layer, go to Layer properties > Symbology tab > Import… and to copy the label properties over, go to the Label manager > right-click on Default label class of Cities layer > Copy parameters > right-click on Default label class of selection layer > Paste.

Image 8

As the highway labels are offset from the state boundary, you might get better results by clipping the portion of the highway that is immediately outside the state instead. I’ve done this here and left the longer highways showing, which may fit better with some house styles.

Image 9

So, in this blog post, I’ve shown how to label one feature layer using the attributes of nearby features from a different layer. Though the final setup needs to be done by hand, most of the steps in this process can be automated, using model builder or Python scripts. Maybe I should describe how to do that in a later post, though.