Introduction

To create, visualize and edit military symbols that comply with military symbology standards, LuciadRIA offers the Defense Symbology component.

The Defense Symbology functionality comes in a @luciad/ria-milsym NPM package.

The LuciadRIA Defense Symbology component provides support for several military symbology standards, including MIL-STD 2525b, MIL-STD 2525c, APP-6A, APP-6B, and APP-6C. These standards define a symbol set that is used to plan and execute military operations in support of Command, Control, Communications, Computers, and Intelligence (C4I) functions.

milsym
Figure 1. The Military Symbols Sample demonstrates a few of the available military symbols

The MIL-STD 2525 standards were developed by the United States Department of Defense (DOD), while the APP-6 standards were developed by the North Atlantic Treaty Organization (NATO). As the APP-6 standards are partially derived from MIL-STD 2525a, they share many symbols.

The Defense Symbology component allows a LuciadRIA user to create MIL-STD 2525b, MIL-STD 2525c, APP-6A, APP-6B, and APP-6C symbols, and visualize them on a map.

To use this functionality in LuciadRIA, you also need LuciadFusion and its Defense Symbology component. Both the LuciadRIA and LuciadFusion components are required to run the symbology icon servlet included with LuciadRIA. For more information about this dependency, see Retrieving symbol icons from the Symbology Service.

Using the Symbology API

A Symbology is a set of named symbols and tactical graphics that are visualized on a map by means of icons and shapes, like polygons and polylines. In LuciadRIA, a Symbology corresponds to one of the symbology standards APP6 and MS2525. This chapter explains how to use the LuciadRIA Symbology API to:

  • Import a symbology for use.Before any symbol can be created, visualized or manipulated, you must import a Symbology into your application.Symbologies provide the metadata to work with individual symbols or groups of symbols.This is explained in Importing a symbology.

  • Visualize a domain object with a military symbol, using a symbology.military.MilitarySymbologyPainter. This is explained in Visualizing a symbol.

  • Create new symbols, as discussed in Creating a new Symbol.

  • Manipulate properties of a symbol, as discussed in Manipulating symbol properties.

Importing a symbology

To import a symbology, just import the symbology/military/<symbologyname> module. This returns a singleton instance of symbology <symbologyname>.

Program: Importing a military symbology
require([
  "luciad/symbology/military/MilitarySymbologyPainter",
  "luciad/symbology/military/MIL_STD_2525b"
], function(MilitarySymbologyPainter,
            MIL_STD_2525b) {

  var symbologyPainter = new MilitarySymbologyPainter(MIL_STD_2525b, {
    ...
  });
});

The available symbologies correspond to the five supported standards.

  • MIL_STD_2525b

  • MIL_STD_2525c

  • APP_6A

  • APP_6B

  • APP_6C

All symbology sets are represented as a hierarchical tree structure consisting of symbology nodes.

Note that it is also possible to load a symbology using the symbology/SymbologyProvider module. This module can act as an AMD plugin that takes the name of the required Symbology as a parameter. The result is a symbology instance that is passed into the module factory function. Alternatively, the SymbologyProvider.getSymbology() method can be used. This method returns a promise for the symbology. Both methods are deprecated since LuciadRIA 2018.1, however, and should no longer be used.

Using a hierarchical symbology

The symbology instance is an instance of type symbology.HierarchicalSymbology. This is because all four military symbology standards have a hierarchical tree structure, in which related symbols with similar properties are grouped under the same parent. Each symbol or group of symbols in the hierarchy are instances of type symbology.SymbologyNode.

The main purpose of the HierarchicalSymbology instance is that it provides access to all the symbols defined in the standard.

With it, you can:

  • Enumerate over all symbols, starting from the root of the symbology.

  • Use a symbol’s identifier,which is the code of the symbol, to retrieve a particular symbol.

Importing a symbology is a prerequisite for visualizing domain objects with military symbols. This is further explained in Visualizing a symbol.

Using a symbology node

Each individual symbol is an instance of symbology.SymbologyNode.

Such a SymbologyNode object has two main purposes:

  • Provide metadata, such as the symbol’s name and unique identifier

  • Create a shape with a geometry that corresponds to the symbol’s requirements. For example, a Point would be the corresponding shape for a tactical icon, a helipad for example, while a PolyLine would be the corresponding shape for a symbol indicating a barrier, a fence for example.

Creating a new Symbol contains more details about how this functionality can be used to create new features.

Visualizing a symbol

To visualize a military symbol, create a MilitarySymbologyPainter.

To visualize a symbol, the API does not place any requirements on the structure of the domain objects in the model. When constructing a MilitarySymbologyPainter, you only need to supply a set of functions that map the domain object to a meaningful value in the context of the symbol. Visualizing military symbols in LuciadRIA is thus solely the responsibility of the view components in an application.

To construct a symbol painter, you need to supply two mandatory parameters.

  • A symbology.This is a reference to a symbology standard.How to import one is explained in Importing a symbology.

  • A code function.This function must map a feature, the domain object, to the SIDC military symbol code. As a shorthand, you can also use a string which refers to the property of the feature that contains the code.

Other parameters are optional and revert to default behavior if they have not been defined.Please refer to the API documentation for a list of optional modifiers, and their possible values.

Program: Minimum code needed to create a MilitarySymbologyPainter.
var symbologyPainter = new MilitarySymbologyPainter(
    //The military standard this painter should paint.
    MIL_STD_2525b, {
      //this is shorthand for a function that returns feature.properties.code
      codeFunction: "code"
    }
);

Customizing the styling of the symbol

In practice, you may need to modify the styling of the symbol according to some properties of the military symbology specification, your own preferences, or a combination of both.

For example, Program: Setting up a symbology painter to paint bodies and labels of military icons and tactical graphics. illustrates how to paint military icon symbols and tactical graphics and apply custom symbol styling, using the MilitarySymbologyPainter and its constructor parameters.

Program: Setting up a symbology painter to paint bodies and labels of military icons and tactical graphics. (from samples/symbology/main.js)
  //The military standard this painter should paint.
  var symbologyPainter = new MilitarySymbologyPainter(symbology, {
    codeFunction: function(feature) {
      //We return the SIDC of the military symbol
      return feature.properties.code;
    },
    modifiers: function(feature) {
      //We return the modifiers in the properties of our feature.
      //These include both text modifiers and graphical modifiers, as defined
      //in the MS2525 and APP6 specifications.
      return feature.properties.modifiers;
    },
    style: function(feature) {
      //We return our style. Note that it is also possible to have feature-specific
      //styling if you choose to use the feature parameter.
      var isEditing = map.controller instanceof EditController;
      return {
        selectionColor: isEditing ? "#FF0000" : "#FF9900",
        affiliationColors: {
          "Friend": SymbologyUtil.FRIEND_COLOR,
          "Hostile": SymbologyUtil.HOSTILE_COLOR
        },
        lineWidth: 2,
        iconSize: feature.properties.iconSize ? feature.properties.iconSize : 64
      };
    },
    width: function(feature) {
      //We return the width we use for arrow-type tactical graphics.
      return feature.properties.width;
    },
    symbologyServicePath: window.location.protocol + "//" + window.location.hostname + ":8081/symbologyservice/"
  });

For simple properties, it is possible to use strings as a parameter instead of functions. This is a shorthand notation for properties that exist within the feature properties. The example below uses short-hand strings instead of functions wherever possible to achieve the same result as Program: Setting up a symbology painter to paint bodies and labels of military icons and tactical graphics..

Program: Setting up a symbology painter using the shorthand notation for retrieval of simple properties
var symbologyPainter = new MilitarySymbologyPainter(
    //The military standard this painter should paint.
    MIL_STD_2525b, {
      //this is shorthand for a function that returns feature.properties.code
      codeFunction: "code",
      //this is shorthand for a function that returns feature.properties.modifiers
      modifiers: "modifiers",
      style: function(feature) {
        return {
          selectionColor: "#FF9900",
          affiliationColors: {
            "Friend": "rgb(128, 224, 255)",
            "Hostile": "#FF8080"
          },
          lineWidth: 2,
          iconSize: 64
        };
      },
      //this is shorthand for a function that returns feature.properties.width
      width: "width",
      symbologyServicePath: "/symbologyservice/"
    }
);

Customizing the styling of a label

symbollabel
Figure 2. Symbol labels in the Military Symbols Sample

Since LuciadRIA allows you to use HTML and CSS to style labels, you can modify the labels of military symbols by overriding the CSS styling properties of the lcdSymbologyLabel CSS class.

An example is provided in the sample below.

Program: Custom CSS style for the labels of icon symbols.
/*Configuring the labels of the symbology*/
.luciad .lcdSymbologyLabel {
  font-family: Arial, monospace;
  font-weight: normal;
  color: white;
  font-size: 10px;
  text-shadow: 0 0 5px rgba(0, 0, 0, 1)
}

Movement direction arrows

LuciadRIA shows movement direction arrows for moving symbols.Ground units will have an arrow starting from a vertical stem.

movement arrows
Figure 3. Movement direction arrows for ground units (right) and other units (left)

The following modifiers affect the arrows:

  • movementDirection: a number indicating the heading of the object. Must be an azimuth: degrees, clock-wise, 0 is north.

  • speedLabel: a string expressing the movement speed, for example "17 km/h" or "11 kn". Affects the length of the arrow. Only relevant for APP-6C and MIL-STD-2525C.

The length of the arrow is determined by the existing style property iconSize in combination with the speedLabel modifier if available. The line-width of the arrow is determined by the existing style properties lineWidth. In 3D, ground units have no stem.

Supported symbols

LuciadRia can visualize all symbols in the mentioned symbologies.

Creating a new Symbol

You can use a CreateController to create a new military icon or tactical graphic, just like you would ordinarily do to create shapes in LuciadRIA.

The SymbologyNode.createTemplate() method creates a Shape that matches the nature of the military symbol.Alternatively, if you want to provide your own custom geometry for the tactical graphics, you can use the ShapeFactory.createShape() method.

Program: Setting up the method CreateController.onCreateNewObject(map,layer). illustrates the recommended way to to create a new symbol.Create a new shape, and then create a new Feature that includes the shape and the desired properties.

Program: Setting up the method CreateController.onCreateNewObject(map,layer). (from samples/symbology/CreationPanel.js)
        var symbologyCreateController = new CreateController();
        symbologyCreateController.onCreateNewObject = function(map, layer) {
          return new Feature(symbology.getSymbologyNode(code).createTemplate(layer.model.reference, 0, 0, 1.6), {
            code: code,
            symbology: symbology
          });
        };
        symbologyCreateController.onObjectCreated = function(map, layer, object) {
          //close the instructions
          that._instructionsPanel.setSymbologyNode(null);
          layer.workingSet.add(object, {}).then(function() {
            //select the created object (standard action is adding without selecting)
            map.selectObjects([
              {
                layer: layer,
                objects: [object]
              }
            ]);
          });
        };
        map.controller = symbologyCreateController;

The Feature property should at least contain a reference to the military code used to create the shape. This is necessary because the MilitarySymbologyPainter needs to retrieve the code to visualize the object properly . More details about using the MilitarySymbologyPainter can be found in Visualizing a symbol.

For more information about creating and working with a SymbologyNode, refer to Using a symbology node.

Manipulating symbol properties

In the APP6 and MS2525 standards, the visualization of a symbol depends on the type of the symbol, as well as on a variety of symbol attributes. For example, a symbol can have an affiliation such as "Friend", "Neutral", or "Hostile", or it can show the status of an action: an action is "Planned" or "Anticipated", for example.

The military symbology standard defines which modifiers are allowed for each symbol. The section Using a hierarchical symbology explains how you can import a symbology standard, and retrieve particular symbols for it. These components do not allow you to edit any properties, however.

To modify the properties of a symbol, LuciadRIA offers the symbology.military.MilitarySymbol component. This object allows you to manipulate the attributes of a symbol, and read out the code of that symbol. Program: Changing the properties of a symbol and retrieving the associated code. shows how you can create a new MilitarySymbol, modify its properties and read out the correct symbol code.

Program: Changing the properties of a symbol and retrieving the associated code. (from samples/allsymbols/main.js)
      var symbol = new MilitarySymbol(symbology, child.code);
      symbol.affiliation = activeData.affiliation;
      // APP-6C has replaced the affiliation property
      symbol.standardIdentity2 = activeData.standardIdentity2;
      var properties = {
        code: symbol.code,
        name: child.name
      };

Retrieving symbol icons from the Symbology Service

The Symbology Service is a web service that serves MS2525/APP6 icons with specified styling information. LuciadRIA needs to have access to this service. Without it, the luciad.symbology.military.MilitarySymbologyPainter does not function properly.

Setting up the symbology service

The Symbology Service is included with the LuciadFusion Defense Symbology component. If this component is present in your LuciadFusion installation, the symbology service will start automatically when you run the LuciadFusion Platform.

In the LuciadRIA military symbology sample configuration, it is assumed that the LuciadFusion Platform with the symbology service is running on the same machine as the LuciadRIA sample server. If this is not the case, a fallback icon will be rendered instead of the correct icon. If the service is running on another location than the server that is hosting your web application, you can configure the MilitarySymbologyPainter with the correct location by passing the symbologyServiceLocation constructor parameter. Program: Configuring the location of the symbology service. shows you how the location of the symbology service is configured in the Blue Forces painter in the COP sample.

Program: Configuring the location of the symbology service. (from samples/cop/themes/BlueForcesPainterMilSym.js)
function BlueForcesPainterMilSym() {
  var _this = Reflect.construct(BlueForcesPainterFallback, [], this.constructor);
  _this._symbolPainter = new MilitarySymbologyPainter(APP_6B, {
    codeFunction: function(feature) {
      return feature.properties.code;
    },
    symbologyServicePath: window.location.protocol + "//" + window.location.hostname + ":8081/symbologyservice/"
  });
  return _this;
}

You can also customize the symbology service so that it uses a specific default style, and clients can request icons with both custom and default styling. Please refer to the LuciadFusion Defense Symbology component documentation for more details on setting up and configuring the symbology service.