Generate GeoJSON ​
@orbat-mapper/control-measures is a pure function library: give it a control-measure kind, a list of input points, and an options object, and it returns MIL-STD-2525 / APP-6 tactical graphics as plain GeoJSON Features. No map engine, no canvas, no framework — works in a browser, a Node service, a test, or an SVG pipeline like the catalog previews.
Install ​
npm install @orbat-mapper/control-measuresRender a control measure ​
renderControlMeasure(measure, options?) is the single entry point. A ControlMeasure is { id, kind, controlPoints, options? } — id is your stable identifier, kind selects the measure, and controlPoints are [lon, lat] pairs.
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 you can hand to any map.
render.features.forEach((f) => console.log(f.geometry.type));Each output feature carries a properties.part tag (which piece of the graphic it is) and a resolved properties.style. Stable feature ids follow ${id}:${part}:${index}, so you can reconcile renders across edits.
How many points does a control measure need? ​
Every kind declares a point contract — a minimum (and sometimes maximum) number of input coordinates. Below the minimum, the render is empty rather than throwing. Read the contract from the metadata:
import {
listControlMeasureMetadata,
getControlMeasureMetadata,
} from "@orbat-mapper/control-measures";
// Every measure, with geometry, point contract, params, and symbology.
const all = listControlMeasureMetadata();
const ambush = getControlMeasureMetadata("ambush");
ambush.minCoordinates; // 3
ambush.geometry; // "line"The catalog is generated from exactly this metadata. See it for the full list of kinds and their point contracts.
Options and defaults ​
Most measures expose tuning parameters (head size, tooth count, fill, …). Each kind ships defaults; fetch them with getDefaultOptions and override what you need.
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,
});Parameters per kind — keys, types, and defaults — are in the catalog. For colors and stroke, see Styling.
Validation ​
An invalid input (too few points, non-finite coordinates) yields an empty render silently by default. Pass validationMode when you'd rather be told:
renderControlMeasure(measure, { validationMode: "warn" }); // "silent" | "warn" | "throw"