🚧 These docs are a work in progress — content is incomplete and may change without notice.
Skip to content

Generate GeoJSON ​

Pass a control-measure kind, a list of control points, and any kind-specific options to @orbat-mapper/control-measures. It returns MIL-STD-2525 and APP-6 graphics as GeoJSON, ready for a browser, a Node service, a test, or an SVG pipeline. No map engine or canvas is required.

Install ​

sh
pnpm add @orbat-mapper/control-measures
sh
npm install @orbat-mapper/control-measures

Render a control measure ​

Call renderControlMeasure(measure, options?) with a ControlMeasure:

  • id is a stable identifier for this instance.
  • kind selects the control-measure type, such as "ambush" or "block".
  • controlPoints contains [longitude, latitude] pairs.
  • options customizes the selected kind (optional).
  • style, textAmplifiers, and properties are also optional.
ts
import { renderControlMeasure } from "@orbat-mapper/control-measures";

const render = renderControlMeasure({
  id: "ambush-1",
  kind: "ambush",
  controlPoints: [
    [-0.871, 49.369],
    [-0.861, 49.369],
    [-0.866, 49.374],
  ],
});

// `render` is a GeoJSON FeatureCollection ready for a map or other renderer.
render.features.forEach((f) => console.log(f.id, f.geometry.type));

The function is pure: it never mutates the measure, and the same input always produces the same output.

What the render contains ​

A single graphic usually produces several features, one per part: an arrow's shaft and head, a label, a fill. Each feature has:

  • id: ${measure.id}:${part}:${index}. The ID is stable across renders, so you can match parts before and after an edit. Recover the measure ID with controlMeasureIdFromFeature(feature).
  • properties.part: the part name, such as "label".
  • properties.style: the final resolved paint values (strokeColor, fillColor, strokeWidth, strokeDash, fillPattern). See Styling.
  • For labels: text, rotation (radians), textAnchor, and the screen-space offset textAnchorGap and textBaselineShift. See Labels and text amplifiers.

The full property shape is exported as FeaturePartProps.

How many points does a control measure need? ​

Each kind declares the minimum number of control points it needs and, where applicable, a maximum. Read these limits from its metadata:

ts
import {
  listControlMeasureMetadata,
  getControlMeasureMetadata,
} from "@orbat-mapper/control-measures";

// Every kind, with geometry, point requirements, options, and symbology.
const all = listControlMeasureMetadata();

const ambush = getControlMeasureMetadata("ambush");
ambush.minCoordinates; // 3
ambush.maxCoordinates; // 3
ambush.geometry; // "line"

When minCoordinates equals maxCoordinates, the kind has a fixed number of points. Otherwise, the user may add more, up to maxCoordinates if one is set. Points beyond the maximum are ignored.

The catalog presents the same metadata for every supported kind.

Find a kind from a symbol code ​

Each kind's value is its MIL-STD-2525D entity code (entity, type, and subtype digits). Use it to map a SIDC from another system to a kind:

ts
import { getControlMeasureMetadataByValue } from "@orbat-mapper/control-measures";

getControlMeasureMetadataByValue("110100")?.id; // "boundary"

It returns undefined for codes the library does not support.

Options and defaults ​

Most kinds expose options such as arrowhead size, tooth count, or fill. Start with getDefaultOptions, then override only what you need:

ts
import { getDefaultOptions, renderControlMeasure } from "@orbat-mapper/control-measures";

const options = { ...getDefaultOptions("ambush"), arrowheadLengthRatio: 0.25 };

const render = renderControlMeasure({
  id: "ambush-1",
  kind: "ambush",
  controlPoints,
  options,
});

getDefaultOptions returns a fresh copy, so you can change it freely. Options are typed per kind: OptionsByKind["ambush"] is the ambush option type, and isKind(measure, "ambush") narrows a ControlMeasure to it.

See the catalog for each kind's option names, types, and defaults. Colors and strokes are covered in Styling. Options that come in pixel/meter pairs are covered in Pixel and meter sizes.

Validation ​

Invalid input, such as too few points or non-finite coordinates, returns an empty render by default. Set validationMode for a warning or an exception:

ts
renderControlMeasure(measure, { validationMode: "warn" }); // "silent" | "warn" | "throw"

Valid points that cannot form a shape, such as two identical points, always return an empty render without a message. This is normal while a user is still placing points. See Points and validity.

Render options ​

The second argument to renderControlMeasure accepts:

OptionDescription
validationMode"silent" (default), "warn", or "throw".
graphicsStyleLowest-priority default style for this call. See Style priority.
symbolColorsDoctrinal default colors, such as the obstacle green. See Styling.

Next steps ​