The Military Grid Reference System (MGRS) is the geo-coordinate standard used by NATO militaries for locating points on Earth. The MGRS is derived from the Universal Transverse Mercator (UTM) grid system and the Universal Polar Stereographic (UPS) grid system, but uses a different labeling convention.

Formatting and parsing points to/from MGRS
To format and parse a Point
Point
Point
to/from MGRS strings, use an MgrsFormat
MgrsFormat
MgrsFormat
.
MgrsFormat mgrsFormat = MgrsFormat::newBuilder()
.precision(MgrsFormatPrecision::Precision1M)
.formatType(MgrsFormatType::Mgrs)
.zoneSeparator(" ")
.coordinateSeparator(" ")
.build();
auto wgs84 = CoordinateReferenceProvider::create("EPSG:4326");
auto point = Point(wgs84.value(), {5, 45, 0});
auto stringResult = mgrsFormat.format(point);
auto parsed = mgrsFormat.parse(stringResult.value());
MgrsFormat mgrsFormat = MgrsFormat.NewBuilder()
.Precision(MgrsFormatPrecision.Precision1M)
.FormatType(MgrsFormatType.Mgrs)
.ZoneSeparator(" ")
.CoordinateSeparator(" ")
.Build();
CoordinateReference wgs84 = CoordinateReferenceProvider.Create("EPSG:4326");
Point point = GeometryFactory.CreatePoint(wgs84, 5, 45, 0);
string stringResult = mgrsFormat.Format(point);
Point parsed = mgrsFormat.Parse(stringResult);
MgrsFormat mgrsFormat = MgrsFormat.newBuilder()
.precision(MgrsFormatPrecision.Precision1M)
.formatType(MgrsFormatType.Mgrs)
.zoneSeparator(" ")
.coordinateSeparator(" ")
.build();
CoordinateReference wgs84 = CoordinateReferenceProvider.create("EPSG:4326");
Point point = GeometryFactory.createPoint(wgs84, 5, 45, 0);
String stringResult = mgrsFormat.format(point);
Point parsed = mgrsFormat.parse(stringResult);
For example, you can use this to show MGRS coordinates at the mouse location. See the Symbology sample for a demonstration.
Visualizing an MGRS grid
You can visualize the MGRS grid by using MgrsGrid
MgrsGrid
MgrsGrid
and MgrsGridLayer
MgrsGridLayer
MgrsGridLayer
.
In order of increasing complexity, you can:
-
Use the default, out-of-the-box grid styling:
MgrsGrid
MgrsGrid
MgrsGrid
with an MgrsGridLayer
MgrsGridLayer
MgrsGridLayer
to show an MGRS grid on the map
auto mgrsGridLayer = MgrsGridLayer::newBuilder().build();
map->getLayerList()->add(mgrsGridLayer);
MgrsGridLayer mgrsGridLayer = MgrsGridLayer.NewBuilder().Build();
map.LayerList.Add(mgrsGridLayer);
MgrsGridLayer mgrsGridLayer = MgrsGridLayer.newBuilder().build();
map.getLayerList().add(mgrsGridLayer);
-
Do some basic tweaks to the default styling, like changing line colors.
Color primaryColor = Color::white();
Color secondaryColor = Color::green();
Color tertiaryColor = Color::yellow();
auto primaryLabelStyle = TextStyle::newBuilder() //
.fontSize(12)
.fontName("monospace")
.textColor(primaryColor)
.haloWidth(1.0)
.haloColor(Color::black())
.build();
auto secondaryLabelStyle = TextStyle::newBuilder() //
.fontSize(14)
.fontName("monospace")
.textColor(secondaryColor)
.haloWidth(1.0)
.haloColor(Color::black())
.build();
auto tertiaryLabelStyle = TextStyle::newBuilder() //
.fontSize(16)
.fontName("monospace")
.textColor(tertiaryColor)
.haloWidth(1.0)
.haloColor(Color::black())
.build();
MgrsGrid mgrsGrid = MgrsGrid::newBuilder()
.primaryLineStyle(LineStyle::newBuilder().color(primaryColor).width(1.0).build())
.primaryLabelStyle(primaryLabelStyle)
.secondaryLineStyle(LineStyle::newBuilder().color(secondaryColor).width(2.0).build())
.secondaryLabelStyle(secondaryLabelStyle)
.tertiaryLineStyle(LineStyle::newBuilder().color(tertiaryColor).width(3.0).build())
.tertiaryLabelStyle(tertiaryLabelStyle)
.scaleMultiplier(1.5) // make the grid more coarse
.build();
auto mgrsGridLayer = MgrsGridLayer::newBuilder().grid(mgrsGrid).build();
map->getLayerList()->add(mgrsGridLayer);
Color primaryColor = Color.White;
Color secondaryColor = Color.Green;
Color tertiaryColor = Color.Blue;
TextStyle primaryLabelStyle = TextStyle.NewBuilder()
.FontName("monospace")
.FontSize(12)
.TextColor(primaryColor)
.HaloWidth(1)
.HaloColor(Color.Black)
.Build();
TextStyle secondaryLabelStyle = TextStyle.NewBuilder()
.FontName("monospace")
.FontSize(14)
.TextColor(secondaryColor)
.HaloWidth(1)
.HaloColor(Color.Black)
.Build();
TextStyle tertiaryLabelStyle = TextStyle.NewBuilder()
.FontName("monospace")
.FontSize(16)
.TextColor(tertiaryColor)
.HaloWidth(1)
.HaloColor(Color.Black)
.Build();
MgrsGrid mgrsGrid = MgrsGrid.NewBuilder()
.PrimaryLineStyle(LineStyle.NewBuilder().Color(primaryColor).Width(1.0).Build())
.PrimaryLabelStyle(primaryLabelStyle)
.SecondaryLineStyle(LineStyle.NewBuilder().Color(secondaryColor).Width(2.0).Build())
.SecondaryLabelStyle(secondaryLabelStyle)
.TertiaryLineStyle(LineStyle.NewBuilder().Color(tertiaryColor).Width(3.0).Build())
.TertiaryLabelStyle(tertiaryLabelStyle)
.ScaleMultiplier(1.5) // make the grid more coarse
.Build();
MgrsGridLayer mgrsGridLayer = MgrsGridLayer.NewBuilder().Grid(mgrsGrid).Build();
map.LayerList.Add(mgrsGridLayer);
Color primaryColor = Color.valueOf(Color.WHITE);
Color secondaryColor = Color.valueOf(Color.GREEN);
Color tertiaryColor = Color.valueOf(Color.BLUE);
TextStyle primaryLabelStyle = TextStyle.newBuilder()
.fontSize(12)
.fontName("monospace")
.textColor(primaryColor)
.haloWidth(1)
.haloColor(Color.valueOf(Color.BLACK))
.build();
TextStyle secondaryLabelStyle = TextStyle.newBuilder()
.fontSize(14)
.fontName("monospace")
.textColor(secondaryColor)
.haloWidth(1)
.haloColor(Color.valueOf(Color.BLACK))
.build();
TextStyle tertiaryLabelStyle = TextStyle.newBuilder()
.fontSize(16)
.fontName("monospace")
.textColor(tertiaryColor)
.haloWidth(1)
.haloColor(Color.valueOf(Color.BLACK))
.build();
MgrsGrid mgrsGrid = MgrsGrid.newBuilder()
.primaryLineStyle(LineStyle.newBuilder()
.color(primaryColor)
.width(1.0)
.build())
.primaryLabelStyle(primaryLabelStyle)
.secondaryLineStyle(LineStyle.newBuilder()
.color(secondaryColor)
.width(2.0)
.build())
.secondaryLabelStyle(secondaryLabelStyle)
.tertiaryLineStyle(LineStyle.newBuilder()
.color(tertiaryColor)
.width(3.0)
.build())
.tertiaryLabelStyle(tertiaryLabelStyle)
.scaleMultiplier(1.5) // make the grid more coarse
.build();
MgrsGridLayer mgrsGridLayer = MgrsGridLayer.newBuilder().grid(mgrsGrid).build();
map.getLayerList().add(mgrsGridLayer);
-
Completely customize the styling of the MGRS grid.
// Styling with completely custom scale ranges and styles
auto labelStyle = TextStyle::newBuilder() // Label style used on all levels
.fontSize(20)
.fontName("monospace")
.textColor(Color::white())
.haloColor(Color::black())
.haloWidth(1)
.build();
// Always show grid zones with thick red lines, regardless of the zoom level
MgrsGridSetting gridZoneSetting = MgrsGridSetting::newBuilder()
.level(MgrsLevel::GridZones)
.scaleRange(MapScale::maxZoomedOut(), MapScale::maxZoomedIn())
.lineStyle(LineStyle::newBuilder() // Thick red line
.color(Color::red())
.width(5.0)
.build())
.labelStyle(labelStyle)
.build();
// When zoomed in far enough, show 100km grid squares in yellow.
// Hide them when zoomed in beyond the 10km grid square scale range start
MapScale startScale100Km = MapScale::fromDenominator(3'000'000.0);
MapScale startScale10Km = MapScale::fromDenominator(750'000.0);
MgrsGridSetting square100KmSetting = MgrsGridSetting::newBuilder()
.level(MgrsLevel::Squares100Km)
.scaleRange(startScale100Km, startScale10Km)
.lineStyle(LineStyle::newBuilder() // Yellow line
.color(Color::yellow())
.width(3.0)
.build())
.labelStyle(labelStyle)
.build();
// When zoomed in beyond the 100km squares, show 10km squares in green
MgrsGridSetting square10KmSetting = MgrsGridSetting::newBuilder()
.level(MgrsLevel::Squares10Km)
.scaleRange(startScale10Km, MapScale::maxZoomedIn())
.lineStyle(LineStyle::newBuilder() // Green line
.color(Color::green())
.width(2.0)
.build())
.labelStyle(labelStyle)
.build();
// Don't show any lower MGRS levels (Squares1Km, Squares100M, Squares10M and Squares1M)
MgrsGrid mgrsGrid = MgrsGrid::newAdvancedBuilder()
.setting(gridZoneSetting) // grid zones
.setting(square100KmSetting) // 100km squares
.setting(square10KmSetting) // 10km squares
.build();
auto mgrsGridLayer = MgrsGridLayer::newBuilder().grid(mgrsGrid).build();
map->getLayerList()->add(mgrsGridLayer);
// Styling with completely custom scale ranges and styles
TextStyle labelStyle = TextStyle.NewBuilder() // Label style used on all levels
.FontSize(20)
.FontName("monospace")
.TextColor(Color.White)
.HaloColor(Color.Black)
.HaloWidth(1)
.Build();
// Always show grid zones with thick red lines, regardless of the zoom level
MgrsGridSetting gridZoneSetting = MgrsGridSetting.NewBuilder()
.Level(MgrsLevel.GridZones)
.ScaleRange(MapScale.MaxZoomedOut, MapScale.MaxZoomedIn)
.LineStyle(LineStyle.NewBuilder().Color(Color.Red).Width(5.0).Build())
.LabelStyle(labelStyle)
.Build();
// When zoomed in far enough, show 100km grid squares in yellow.
// Hide them when zoomed in beyond the 10km grid square scale range start
MapScale startScale100Km = MapScale.FromDenominator(3_000_000.0);
MapScale startScale10Km = MapScale.FromDenominator(750_000.0);
MgrsGridSetting square100KmSetting = MgrsGridSetting.NewBuilder()
.Level(MgrsLevel.Squares100Km)
.ScaleRange(startScale100Km, startScale10Km)
.LineStyle(LineStyle.NewBuilder().Color(Color.Yellow).Width(3.0).Build())
.LabelStyle(labelStyle)
.Build();
// When zoomed in beyond the 100km squares, show 10km squares in green
MgrsGridSetting square10KmSetting = MgrsGridSetting.NewBuilder()
.Level(MgrsLevel.Squares10Km)
.ScaleRange(startScale10Km, MapScale.MaxZoomedIn)
.LineStyle(LineStyle.NewBuilder().Color(Color.Green).Width(2.0).Build())
.LabelStyle(labelStyle)
.Build();
// Don't show any lower MGRS levels (Squares1Km, Squares100M, Squares10M and Squares1M)
MgrsGrid mgrsGrid = MgrsGrid.NewAdvancedBuilder()
.Setting(gridZoneSetting) // grid zones
.Setting(square100KmSetting) // 100km squares
.Setting(square10KmSetting) // 10km squares
.Build();
MgrsGridLayer mgrsGridLayer = MgrsGridLayer.NewBuilder().Grid(mgrsGrid).Build();
map.LayerList.Add(mgrsGridLayer);
// Styling with completely custom scale ranges and styles
TextStyle labelStyle = TextStyle.newBuilder() // Label style used on all levels
.fontSize(20)
.fontName("monospace")
.textColor(Color.valueOf(Color.WHITE))
.haloColor(Color.valueOf(Color.BLACK))
.haloWidth(1)
.build();
// Always show grid zones with thick red lines, regardless of the zoom level
MgrsGridSetting gridZoneSetting = MgrsGridSetting.newBuilder()
.level(MgrsLevel.GridZones)
.scaleRange(MapScale.MaxZoomedOut, MapScale.MaxZoomedIn)
.lineStyle(LineStyle.newBuilder()
.color(Color.valueOf(Color.RED))
.width(5.0)
.build())
.labelStyle(labelStyle)
.build();
// When zoomed in far enough, show 100km grid squares in yellow.
// Hide them when zoomed in beyond the 10km grid square scale range start
MapScale startScale100Km = MapScale.fromDenominator(3_000_000.0);
MapScale startScale10Km = MapScale.fromDenominator(750_000.0);
MgrsGridSetting square100KmSetting = MgrsGridSetting.newBuilder()
.level(MgrsLevel.Squares100Km)
.scaleRange(startScale100Km, startScale10Km)
.lineStyle(LineStyle.newBuilder()
.color(Color.valueOf(Color.YELLOW))
.width(3.0)
.build())
.labelStyle(labelStyle)
.build();
// When zoomed in beyond the 100km squares, show 10km squares in green
MgrsGridSetting square10KmSetting = MgrsGridSetting.newBuilder()
.level(MgrsLevel.Squares10Km)
.scaleRange(startScale10Km, MapScale.MaxZoomedIn)
.lineStyle(LineStyle.newBuilder()
.color(Color.valueOf(Color.GREEN))
.width(2.0)
.build())
.labelStyle(labelStyle)
.build();
// Don't show any lower MGRS levels (Squares1Km, Squares100M, Squares10M and Squares1M)
MgrsGrid mgrsGrid = MgrsGrid.newAdvancedBuilder()
.setting(gridZoneSetting) // grid zones
.setting(square100KmSetting) // 100km squares
.setting(square10KmSetting) // 10km squares
.build();
MgrsGridLayer mgrsGridLayer = MgrsGridLayer.newBuilder().grid(mgrsGrid).build();
map.getLayerList().add(mgrsGridLayer);
Adding an MGRS overview label to the map
When users zoom in far on the map, it’s easy for them to lose track of the grid zone or square that they’re in. To prevent that, you can show an overview label on the map. This label shows the users which grid zone and square they have reached by zooming in on the map. When you use the overview label combined with the grid labels and the mouse coordinate readout, you give the users more than one option for determining their current MGRS location.

The LuciadCPillar API gives you a utility class to generate the text for the MGRS overview label: MgrsGridTextProvider
MgrsGridTextProvider
MgrsGridTextProvider
.
It fires events whenever the overview label should change its text with a new formatted location string.
You can use this utility in a UI framework of your choice.
MgrsGridTextProvider
MgrsGridTextProvider
MgrsGridTextProvider
to the map and start listening to it.
auto textProvider = MgrsGridTextProvider(map);
textProvider.addCallback(MgrsGridTextProvider::ICallback::create([](const std::string& text) { std::cout << "New MGRS location text = " << text << "\n"; }));
// Implement ICallback
private class MyCallback : MgrsGridTextProvider.ICallback
{
public void OnTextChanged(string text)
{
Console.WriteLine("New MGRS location text = " + text);
}
}
// Create a MgrsGridTextProvider and register the callback
var textProvider = new MgrsGridTextProvider(map);
var callback = new MyCallback();
textProvider.AddCallback(callback);
MgrsGridTextProvider textProvider = new MgrsGridTextProvider(map);
textProvider.addCallback(new MgrsGridTextProvider.ICallback() {
@Override
public void onTextChanged(@NotNull String text) {
Log.d("MGRS", "New MGRS location text = " + text);
}
});