I asked a question before about whether it was possible to scale labels and I was correctly pointed to the IAnnotateLayerTransformationProperties.ReferenceScale property. What would like to know now is: does anyone have pointers on the correct algorithm to use to calculate that number (the reference scale) and the font size in order to best match the bounds of your layer and map? (I want to automate the labeling process as much as possible without asking the user questions that they probably can't answer (like me now.))
It seems reasonable that you can use loose relationships to derive FontSize or ReferenceScale, assuming you know one or the other. I say loose relationship because aesthetic fonts can have significant per-character width variation; and while font-height is more stable, there is still variation between lowercase and uppercase chars, et cetera. In other words, there's "odd slosh" here.
Nevertheless, Pixels-Per-Inch is a useful constant, and it holds a value of 72.
You can manually experiment with Reference Scale in ArcGIS using the 1:N button on the standard tool bar. Arc will output something that looks like 1:###### for any given level of zoom. For calculation purposes, drop the "1:" from that expression. For example, 1:1200 becomes simply, 1200.
Calculate vertical space a FontSize may occupy for a given ReferenceScale:
// My inputs.. // fontSize=12, fontFamily=Arial // 1200 is a 1:1200 reference scale // 72 is the pixels-per-inch constant. scaledFontHeightOnGround = ( fontSize * 72 ) / 1200; // scaledFontHeightOnGround becomes 200 feet // Most chars will be "shorter" than this, however.
By "font-height" I mean my annotations will scale, or become fitted-to, appx 200-feet on the ground. In other words, they grow as you zoom in, and they shrink as you zoom out. Most characters need about 2/3 of that space. If you had several characters in your anno (like the string "144" for example), in my case that only occupies about 350 feet of scaled width on the ground. In other words, the relationship does not apply well to annotation-width, and it gets worse as string length increases.
Knowing this, you can derive FontSize by working the problem backwards, assuming you can establish a vertical dimension, in map units, your annotations can occupy on the ground for a given ReferenceScale. Or said differently "How tall (in map units) do your annotations need to be to read them at a selected ReferenceScale?" Let's assume you're comfortable with a font-height of 300-feet.
Derive reasonable FontSize when you know both ReferenceScale and desired font-height in map units:
// My inputs.. // 300 = font-height in map units // 1200 is a 1:1200 reference scale // 72 is the pixels-per-inch constant. ( 300 / 1200 ) * 72 == aNewFontSize; // aNewFontSize becomes 18
Clearly, we can rearrange the equation again to derive a ReferenceScale if we know both an acceptable vertical dimension for font-heights, in map units :), and a FontSize.
Calculate a ReferenceScale when you have both a vertical dimension in map units and FontSize:
// My inputs.. // 300 = font-height in map units // 72 is the pixels-per-inch constant // fontSize = 18, in this case ( 300 * 72 ) / fontSize == theReferenceScale; // theReferenceScale becomes 1200
In this screenshot, at left is the 1:N button that outputs the MapScale. You can change the MapScale in that control and it will zoom in/out, respectively. At right, I'm measuring the font-height of my annotation.
Now having spilled my thoughts on this topic, I'm at a loss to derive both FontSize and ReferenceScale if you don't know one or the other. Perhaps the solution would be to put together a sample-set of RefScale and FontSize pairs, then assemble a graph and derives a trendline equation relating appropriate font sizes for given reference scales. Even better, maybe someone already has such an equation?
I'll be very interested to see what other folks contribute as answers to this question.