ThinkGeo.com    |     Documentation    |     Premium Support

Map Scale Bar

MapSuite 2.X provided a nice scale bar as an adornment for maps that would auto-adjust for the current zoom level, default in miles. A picture is attached here.  I see some sample code for a scale bar - did not look nearly as nice as the one that came for "free" in 2.X.  Is there any code out there for this?



Michael, 
  
 I don’t see any attached picture, could you check it? 
  
 In 3.x, we have a object ScaleBarAdornmentLayer which can display a scale bar as nice as 2.x 
  
 Once you provide the picture for it, we can give your a sample code to the same result. 
  
 Thanks 
 James

Thanks James, let me try and post the .jpg

 I attached a snapshot of the MapSuite 2.X app that included a scale bar that automatically adjusted by zoom level.  Does 4.5 offer the same?





Michael,


I attached a simple sample code to show how to display a scale bar, if you want to customize it, you can set BarBrush or MaskBrush to make it different.



Let me know if you have questions.


Thanks


James



CreateAScaleLineAdornmentLayer.zip (1.65 KB)

Thanks James, that’s the type of scale bar I’m looking for.  I’m building my application in VB.Net from the WorldMapKitDemos code base and MapSuite 4.5.  Is it possible to see a Vb.Net example or get some pointers on applying this code into WorldMapKitDemo?

I was also interested in this, so I tried running the code through 
 developerfusion.com/tools/convert/csharp-to-vb/ 
 but it ended up a big mess - the form disappeared! So, it would be helpful if ThinkGeo made a VB.Net version - this messing around with C# all the time is not a productive use of my time either.

 


Hi, Michael
You can apply the following piece of code to your application, it’s a sample built on the HowDoI sample for WorldMapKitDemo of VB.Net version:
        Private Sub FormRenderUSA_Load(ByVal sender As Object, ByVal e As EventArgs)
            Dim worldMapKitDataFolder As String = ConfigurationManager.AppSettings.[Get]("WorldMapKitDataFolder")
            worldMapKitRenderLayer = New WorldMapKitRenderLayer(worldMapKitDataFolder)
 
            Dim worldMapKitRenderLayerOverlay As New LayerOverlay()
            worldMapKitRenderLayerOverlay.Layers.Add(worldMapKitRenderLayer)
            Map.Overlays.Add(worldMapKitRenderLayerOverlay)
 
            Dim scaleBarAdronmentLayer As New ScaleBarAdornmentLayer()
            Map.AdornmentOverlay.Layers.Add("ScaleLineAdornmentLayer", scaleBarAdronmentLayer)
 
            Map.MapUnit = GeographyUnit.DecimalDegree
            Map.ExtentOverlay.ZoomPercentage = 50
            Map.CurrentExtent = worldMapKitRenderLayer.DefaultExtent
 
Map.Refresh()
        End Sub
 
 
Any further questions please let me know.
Thanks.
 
Hi, David
First of all, we have provided VB.Net sample as well, if you don't know how to get it please contact our sales, and you don’t have to apply the entire code sample James attached to your VB.Net application. In fact, just a single line of code can make the scale bar work, please have a try of this:
Map.AdornmentOverlay.Layers.Add("ScaleLineAdornmentLayer", New ScaleBarAdornmentLayer())
 
Any further questions are welcomed.
Thanks.

James



Excellent, that’s what I needed.  Adding two lines works for me!

Michael, 
  
 I am glad it’s working with you, feel free to let me know if you have more questions. 
  
 Thanks 
 James

Thanks for the reply. I can put a scale bar in with 2 lines as you said, but as always, something comes along to make it more difficult. :-)


I tried moving the scale bar to the top right instead of bottom left, but that didn't seem to work. There is an example in the Samples application but I am having trouble  getting that adapted to my system where I just want it fixed at upper right. Also having trouble finding out how to change scale to nautical miles.


'             Add a scale bar

Dim scaleBarAdornmentLayer As New ScaleBarAdornmentLayer()

staticOverlay.Layers.Add("ScaleLineAdornmentLayer", New ScaleBarAdornmentLayer())


'             Move to upper right - doesn't work - location stays in bottom left!

' scaleBarAdornmentLayer.Location = AdornmentLocation.UpperRight

'             This example from Samples does work in their application!

' currentScaleLineAdornmentLayer.Location = DirectCast(cbxScaleLineLocation.SelectedIndex, AdornmentLocation)  

'             but the following also doesn't work:

' scaleBarAdornmentLayer.Location = DirectCast(AdornmentLocation.UpperRight, AdornmentLocation)

'             stays in bottom left and gives warning "Using DirectCast operator to cast a value-type to the same type is obsolete"

' scaleBarAdornmentLayer.Location = DirectCast(3, AdornmentLocation)

'             stays in bottom left also

 


'             Change scale parameters to nautical miles.

'             What is the syntax for changing to nautical miles? 

'             Below is probably the start of how to do it, but I can't see any VB or C# examples

'             anywhere and API reference mention Dictionary

'scaleBarAdornmentLayer.DisplayUnitString


 



 


Hi, David
Sorry for inconvenience and the trouble brought by the code sample I provided in the earlier post. After going through the sample in your post, I noticed that at line 2, you add a new instance of ScaleBarAdornmentLayer to the LayerOverlay, indeed, after adding this LayerOverlay to the Map control, Map control will keep a reference of the ScaleBarAdornmentLayer instantiated at line 2, somehow, it’s NOT the one that you made announcement for at line 1, therefore, all the settings later on just took effect on the instance announced and instantiated at line 1, NOT the one add to the Map control. I’m guessing that’s because the code sample I provided misguided you, sorry for it again. Here is the code that may help you out:
Dim scaleBarAdornmentLayer As New ScaleBarAdornmentLayer()
staticOverlay.Layers.Add("ScaleLineAdornmentLayer", scaleBarAdornmentLayer)
scaleBarAdornmentLayer.Location = AdornmentLocation.UpperRight

And another suggestion is while using this ScaleLineAdornmentLayer, it’s better to add it to AdornmentOverlay of Map control. In this way, we can make sure that ScaleLineAdornmentLayer will be correctly redrawn when map is refreshed.
As for your second concern, converting the distance unit to nautical miles, for now, we only supports 4 different kinds of unit:Meter, Feet, Kilometer, Mile. We’ll add nautical miles unit to ScaleBarAdornmentLayer in future public release, and we’ve make this as an issue on our internal issue system. Thanks for your suggestion.
Further questions please let me know.
James

 



Ah, sorry - 1 too many ‘New’ in my code! 
  
 Thanks re the nautical miles code as well - I will watch out for that release. I haven’t gotten to distance measuring between my ships & my targets yet - hope those distances can also be measured in nautical miles…

David, 



We have reported this issue to our GIS gru to see what's the best way for adding this feature. We will also post it here once there is an update. 



Thanks, 



Ben



David, 
  
 We just added the nautical miles to the Map Suite from version 5.5.132.0 or later. You can get NauticalMiles by setting ScaleBarAdormentLayer.UnitFamily to ImperialWithNauticalMiles. The API name might change in the 6.0.0 final release though. Please have a try. 
  
 Thanks, 
  
 Ben

Revisiting all my old topics now that I have upgraded to version 6. API name has indeed changed in V6. My code is: 
  
 scaleBarAdornmentLayer1.UnitFamily = UnitSystem.NauticalMile 
  
 The good news is that it works - I see the scale bar in nautical miles. 
  
 The bad news is that when you zoom in and the scale bar changes from nautical miles, it changes to feet. I guess in the USA the captains might work in feet for shorter units of distance but here (Malaysia and other countries that I work in), shorter distances are measured in metres (meters in American English). Not to mention that a nautical mile is defined as 1852 metres so I am guessing nautical miles should be matched with metres rather than feet? 
 I guess it may not really be a bug but more something missing. Maybe we can have: 
  
 ScaleBarAdormentLayer.UnitFamily = ImperialWithNauticalMiles 
 ScaleBarAdormentLayer.UnitFamily = MetricWithNauticalMiles 
  
 or if imperial units are not normally used with Nautical Miles then just change the shorter distance to metres instead of feet? 
  
 Thanks, 
  
 Dave

Hi David,


Thanks for you advise, as the API UnitSystem.NauticalMile has been released, we may not change this API, but we'll consider add some new APIs, and the development team will discuss about this, so as a workaroud you can use the following code first:



    class MyAdornment : ScaleBarAdornmentLayer
    {
        protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)
        {
            //36046.862182617188 is zoom level 15's scale
            if (canvas.CurrentScale < 36046.862182617188)
            {
                UnitFamily = UnitSystem.Metric;
            }
            else
            {
                UnitFamily = UnitSystem.NauticalMile;
            }
            base.DrawCore(canvas, labelsInAllLayers);
        }
    }

    MyAdornment layer1 = new MyAdornment();
    layer1.UnitFamily = UnitSystem.NauticalMile;

Regards,


Edgar



Hi David,  
  
 We did the changes to our products following your idea that the unit is meter in deep zoom. Please get the latest version 6.0.150.0 or later to have a try. 
  
 Thanks, 
 Johnny