@orbat-mapper/control-measures 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/{index-CnRoitOO.d.mts → index-BTPCaqIB.d.mts} +112 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +83 -2
- package/dist/preview/index.d.mts +1 -1
- package/dist/preview/index.mjs +1 -1
- package/dist/{renderControlMeasure-C2er4uy_.mjs → renderControlMeasure-CU_KIPdu.mjs} +720 -109
- package/media/double-apron-fence.svg +1 -0
- package/media/double-fence.svg +1 -0
- package/media/double-strand-concertina.svg +1 -0
- package/media/high-wire-fence.svg +1 -0
- package/media/low-wire-fence.svg +1 -0
- package/media/obstacle-belt.svg +1 -0
- package/media/obstacle-free-zone.svg +1 -0
- package/media/obstacle-restricted-zone.svg +1 -0
- package/media/obstacle-zone.svg +1 -0
- package/media/single-concertina.svg +1 -0
- package/media/single-fence.svg +1 -0
- package/media/triple-strand-concertina.svg +1 -0
- package/media/wire-obstacle-unspecified.svg +1 -0
- package/package.json +1 -1
|
@@ -2621,6 +2621,408 @@ function fixedLabelLineFeatures(positions, options, textForEnd, hostileText, con
|
|
|
2621
2621
|
features
|
|
2622
2622
|
};
|
|
2623
2623
|
}
|
|
2624
|
+
function normalizeArcResolution(value) {
|
|
2625
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return 64;
|
|
2626
|
+
return Math.min(360, Math.max(4, Math.round(value)));
|
|
2627
|
+
}
|
|
2628
|
+
const ARC_RESOLUTION_PARAMS = [{
|
|
2629
|
+
key: "resolution",
|
|
2630
|
+
presentationTier: "advanced",
|
|
2631
|
+
label: "Resolution",
|
|
2632
|
+
description: "Number of segments in a full 360° sweep.",
|
|
2633
|
+
type: "number",
|
|
2634
|
+
min: 4,
|
|
2635
|
+
max: 360,
|
|
2636
|
+
step: 1
|
|
2637
|
+
}];
|
|
2638
|
+
//#endregion
|
|
2639
|
+
//#region src/generators/cm29-protection-lines/params.ts
|
|
2640
|
+
const FORTIFIED_PARAMS = [
|
|
2641
|
+
...SMOOTH_LINE_PARAMS,
|
|
2642
|
+
{
|
|
2643
|
+
key: "toothSizePixels",
|
|
2644
|
+
label: "Tooth size",
|
|
2645
|
+
description: "Side length of the square crenellations",
|
|
2646
|
+
type: "number",
|
|
2647
|
+
min: 5,
|
|
2648
|
+
max: 50,
|
|
2649
|
+
step: 1,
|
|
2650
|
+
unit: "px"
|
|
2651
|
+
},
|
|
2652
|
+
{
|
|
2653
|
+
key: "toothSize",
|
|
2654
|
+
label: "Tooth size",
|
|
2655
|
+
description: "Side length of the square crenellations",
|
|
2656
|
+
type: "number",
|
|
2657
|
+
min: 1,
|
|
2658
|
+
max: 500,
|
|
2659
|
+
step: 1,
|
|
2660
|
+
unit: "m"
|
|
2661
|
+
},
|
|
2662
|
+
LABEL_PADDING_PARAM
|
|
2663
|
+
];
|
|
2664
|
+
const ANTITANK_DITCH_PARAMS = [
|
|
2665
|
+
...SMOOTH_LINE_PARAMS,
|
|
2666
|
+
{
|
|
2667
|
+
key: "toothHeightPixels",
|
|
2668
|
+
label: "Tooth height",
|
|
2669
|
+
description: "Perpendicular depth of each triangular tooth",
|
|
2670
|
+
type: "number",
|
|
2671
|
+
min: 5,
|
|
2672
|
+
max: 50,
|
|
2673
|
+
step: 1,
|
|
2674
|
+
unit: "px"
|
|
2675
|
+
},
|
|
2676
|
+
{
|
|
2677
|
+
key: "toothHeight",
|
|
2678
|
+
label: "Tooth height",
|
|
2679
|
+
description: "Perpendicular depth of each triangular tooth",
|
|
2680
|
+
type: "number",
|
|
2681
|
+
min: 1,
|
|
2682
|
+
max: 500,
|
|
2683
|
+
step: 1,
|
|
2684
|
+
unit: "m"
|
|
2685
|
+
},
|
|
2686
|
+
{
|
|
2687
|
+
key: "toothWidthRatio",
|
|
2688
|
+
presentationTier: "advanced",
|
|
2689
|
+
label: "Tooth width ratio",
|
|
2690
|
+
description: "Tooth base span as a multiple of height",
|
|
2691
|
+
type: "number",
|
|
2692
|
+
min: .5,
|
|
2693
|
+
max: 3,
|
|
2694
|
+
step: .05,
|
|
2695
|
+
unit: "x"
|
|
2696
|
+
},
|
|
2697
|
+
LABEL_PADDING_PARAM
|
|
2698
|
+
];
|
|
2699
|
+
const ANTITANK_WALL_PARAMS = [...ANTITANK_DITCH_PARAMS, {
|
|
2700
|
+
key: "toothSpacingRatio",
|
|
2701
|
+
presentationTier: "advanced",
|
|
2702
|
+
label: "Tooth spacing ratio",
|
|
2703
|
+
description: "Gap between teeth as a multiple of base width",
|
|
2704
|
+
type: "number",
|
|
2705
|
+
min: 0,
|
|
2706
|
+
max: 3,
|
|
2707
|
+
step: .05,
|
|
2708
|
+
unit: "x"
|
|
2709
|
+
}];
|
|
2710
|
+
const WIRE_MARKER_PARAMS = [{
|
|
2711
|
+
key: "markerSize",
|
|
2712
|
+
label: "Marker size",
|
|
2713
|
+
description: "Full height of each wire marker in meters",
|
|
2714
|
+
type: "number",
|
|
2715
|
+
min: 1,
|
|
2716
|
+
max: 500,
|
|
2717
|
+
step: 1,
|
|
2718
|
+
unit: "m"
|
|
2719
|
+
}, {
|
|
2720
|
+
key: "markerSizePixels",
|
|
2721
|
+
label: "Marker size",
|
|
2722
|
+
description: "Full height of each wire marker in pixels",
|
|
2723
|
+
type: "number",
|
|
2724
|
+
min: 1,
|
|
2725
|
+
max: 50,
|
|
2726
|
+
step: 1,
|
|
2727
|
+
unit: "px"
|
|
2728
|
+
}];
|
|
2729
|
+
/** The lower bound varies per wire kind, so callers spread this and override `min`. */
|
|
2730
|
+
const WIRE_SPACING_PARAM = {
|
|
2731
|
+
key: "markerSpacingRatio",
|
|
2732
|
+
label: "Marker spacing",
|
|
2733
|
+
description: "Target distance between marker groups as a multiple of marker height",
|
|
2734
|
+
presentationTier: "advanced",
|
|
2735
|
+
type: "number",
|
|
2736
|
+
min: .8,
|
|
2737
|
+
max: 10,
|
|
2738
|
+
step: .1
|
|
2739
|
+
};
|
|
2740
|
+
//#endregion
|
|
2741
|
+
//#region src/generators/cm29-protection-lines/wire-obstacles.ts
|
|
2742
|
+
const DEFAULT_MARKER_SIZE = 100;
|
|
2743
|
+
const DEFAULT_MARKER_SIZE_PIXELS = 20;
|
|
2744
|
+
const WIRE_KINDS = {
|
|
2745
|
+
unspecified: {
|
|
2746
|
+
subtype: "Unspecified",
|
|
2747
|
+
value: "290301",
|
|
2748
|
+
description: "A wire obstacle whose fence type is unspecified.",
|
|
2749
|
+
spacing: 1.5,
|
|
2750
|
+
minSpacing: .8,
|
|
2751
|
+
concertina: false,
|
|
2752
|
+
oneSided: false,
|
|
2753
|
+
paired: false,
|
|
2754
|
+
rails: 0,
|
|
2755
|
+
railSeparation: 0,
|
|
2756
|
+
previewMarkerSize: 96
|
|
2757
|
+
},
|
|
2758
|
+
single: {
|
|
2759
|
+
subtype: "Single Fence",
|
|
2760
|
+
value: "290302",
|
|
2761
|
+
description: "A wire obstacle consisting of a single fence.",
|
|
2762
|
+
spacing: 3,
|
|
2763
|
+
minSpacing: .8,
|
|
2764
|
+
concertina: false,
|
|
2765
|
+
oneSided: false,
|
|
2766
|
+
paired: false,
|
|
2767
|
+
rails: 1,
|
|
2768
|
+
railSeparation: 0,
|
|
2769
|
+
previewMarkerSize: 115
|
|
2770
|
+
},
|
|
2771
|
+
double: {
|
|
2772
|
+
subtype: "Double Fence",
|
|
2773
|
+
value: "290303",
|
|
2774
|
+
description: "A wire obstacle consisting of a double fence.",
|
|
2775
|
+
spacing: 3.6,
|
|
2776
|
+
minSpacing: 1.6,
|
|
2777
|
+
concertina: false,
|
|
2778
|
+
oneSided: false,
|
|
2779
|
+
paired: true,
|
|
2780
|
+
rails: 1,
|
|
2781
|
+
railSeparation: 0,
|
|
2782
|
+
previewMarkerSize: 115
|
|
2783
|
+
},
|
|
2784
|
+
apron: {
|
|
2785
|
+
subtype: "Double Apron Fence",
|
|
2786
|
+
value: "290304",
|
|
2787
|
+
description: "A wire fence with an apron on each side.",
|
|
2788
|
+
spacing: 1.5,
|
|
2789
|
+
minSpacing: .8,
|
|
2790
|
+
concertina: false,
|
|
2791
|
+
oneSided: false,
|
|
2792
|
+
paired: false,
|
|
2793
|
+
rails: 1,
|
|
2794
|
+
railSeparation: 0,
|
|
2795
|
+
previewMarkerSize: 96
|
|
2796
|
+
},
|
|
2797
|
+
low: {
|
|
2798
|
+
subtype: "Low Wire Fence",
|
|
2799
|
+
value: "290305",
|
|
2800
|
+
description: "A low wire fence obstacle.",
|
|
2801
|
+
spacing: 1.5,
|
|
2802
|
+
minSpacing: .8,
|
|
2803
|
+
concertina: false,
|
|
2804
|
+
oneSided: true,
|
|
2805
|
+
paired: false,
|
|
2806
|
+
rails: 1,
|
|
2807
|
+
railSeparation: 0,
|
|
2808
|
+
previewMarkerSize: 96
|
|
2809
|
+
},
|
|
2810
|
+
high: {
|
|
2811
|
+
subtype: "High Wire Fence",
|
|
2812
|
+
value: "290306",
|
|
2813
|
+
description: "A high wire fence obstacle.",
|
|
2814
|
+
spacing: 1.5,
|
|
2815
|
+
minSpacing: .8,
|
|
2816
|
+
concertina: false,
|
|
2817
|
+
oneSided: true,
|
|
2818
|
+
paired: false,
|
|
2819
|
+
rails: 2,
|
|
2820
|
+
railSeparation: 1,
|
|
2821
|
+
previewMarkerSize: 96
|
|
2822
|
+
},
|
|
2823
|
+
concertina: {
|
|
2824
|
+
subtype: "Single Concertina",
|
|
2825
|
+
value: "290307",
|
|
2826
|
+
description: "A wire obstacle consisting of a single concertina coil.",
|
|
2827
|
+
spacing: 1.25,
|
|
2828
|
+
minSpacing: .8,
|
|
2829
|
+
concertina: true,
|
|
2830
|
+
oneSided: true,
|
|
2831
|
+
paired: false,
|
|
2832
|
+
rails: 1,
|
|
2833
|
+
railSeparation: 0,
|
|
2834
|
+
previewMarkerSize: 96
|
|
2835
|
+
},
|
|
2836
|
+
"double-concertina": {
|
|
2837
|
+
subtype: "Double Strand Concertina",
|
|
2838
|
+
value: "290308",
|
|
2839
|
+
description: "A wire obstacle consisting of double-strand concertina.",
|
|
2840
|
+
spacing: 1.25,
|
|
2841
|
+
minSpacing: .8,
|
|
2842
|
+
concertina: true,
|
|
2843
|
+
oneSided: true,
|
|
2844
|
+
paired: false,
|
|
2845
|
+
rails: 2,
|
|
2846
|
+
railSeparation: .5,
|
|
2847
|
+
previewMarkerSize: 96
|
|
2848
|
+
},
|
|
2849
|
+
"triple-concertina": {
|
|
2850
|
+
subtype: "Triple Strand Concertina",
|
|
2851
|
+
value: "290309",
|
|
2852
|
+
description: "A wire obstacle consisting of triple-strand concertina.",
|
|
2853
|
+
spacing: 1.25,
|
|
2854
|
+
minSpacing: .8,
|
|
2855
|
+
concertina: true,
|
|
2856
|
+
oneSided: true,
|
|
2857
|
+
paired: false,
|
|
2858
|
+
rails: 2,
|
|
2859
|
+
railSeparation: 1,
|
|
2860
|
+
previewMarkerSize: 96
|
|
2861
|
+
}
|
|
2862
|
+
};
|
|
2863
|
+
function createWireObstacle(positions, options, text, context, kind) {
|
|
2864
|
+
const spec = WIRE_KINDS[kind];
|
|
2865
|
+
const projected = positions.map(([x, y]) => project(x, y));
|
|
2866
|
+
const path = smoothLineVerts(projected.filter((point, index) => index === 0 || Math.hypot(point[0] - projected[index - 1][0], point[1] - projected[index - 1][1]) >= 1e-6), options, 16);
|
|
2867
|
+
const { segments, totalLength } = polylineSegments(path);
|
|
2868
|
+
if (totalLength < 1e-6) return {
|
|
2869
|
+
type: "FeatureCollection",
|
|
2870
|
+
features: []
|
|
2871
|
+
};
|
|
2872
|
+
const resolution = normalizeArcResolution(options.resolution);
|
|
2873
|
+
const size = Math.max(EPSILON, options.markerSizePixels !== void 0 && (options.metersPerPixel ?? 0) > 0 ? options.markerSizePixels * options.metersPerPixel : options.markerSize ?? DEFAULT_MARKER_SIZE);
|
|
2874
|
+
const pitch = Math.max(spec.minSpacing, options.markerSpacingRatio ?? spec.spacing) * size;
|
|
2875
|
+
const halfWidth = .4 * size;
|
|
2876
|
+
const pairOffset = spec.paired ? halfWidth : 0;
|
|
2877
|
+
const corners = [];
|
|
2878
|
+
let distance = 0;
|
|
2879
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
2880
|
+
const current = segments[i];
|
|
2881
|
+
const next = segments[i + 1];
|
|
2882
|
+
distance += current.length;
|
|
2883
|
+
const dot = current.along[0] * next.along[0] + current.along[1] * next.along[1];
|
|
2884
|
+
if (dot >= .95) continue;
|
|
2885
|
+
const turn = current.along[0] * next.along[1] - current.along[1] * next.along[0];
|
|
2886
|
+
const tangent = Math.sqrt((1 - dot) / Math.max(EPSILON, 1 + dot));
|
|
2887
|
+
const insideTangent = spec.oneSided && turn >= 0 ? 0 : tangent;
|
|
2888
|
+
const clearance = spec.concertina ? size * (insideTangent / 2 + Math.hypot(.25, insideTangent / 2)) : halfWidth + pairOffset + size * (spec.oneSided ? 1 : .5) * insideTangent;
|
|
2889
|
+
corners.push({
|
|
2890
|
+
distance,
|
|
2891
|
+
clearance: Math.max(clearance, pitch / 2)
|
|
2892
|
+
});
|
|
2893
|
+
}
|
|
2894
|
+
const inset = Math.min(totalLength / 2, halfWidth + pairOffset + (spec.rails > 0 ? .25 * size : 0));
|
|
2895
|
+
const centers = [];
|
|
2896
|
+
const spread = (start, end, count) => {
|
|
2897
|
+
for (let i = 0; i < count; i++) centers.push(count === 1 ? (start + end) / 2 : start + i * (end - start) / (count - 1));
|
|
2898
|
+
};
|
|
2899
|
+
if (corners.length === 0) spread(inset, totalLength - inset, Math.max(1, Math.round(totalLength / pitch)));
|
|
2900
|
+
else {
|
|
2901
|
+
let start = inset;
|
|
2902
|
+
for (const corner of [...corners, {
|
|
2903
|
+
distance: totalLength,
|
|
2904
|
+
clearance: inset
|
|
2905
|
+
}]) {
|
|
2906
|
+
const end = corner.distance - corner.clearance;
|
|
2907
|
+
if (end >= start) spread(start, end, Math.max(1, Math.round((end - start) / pitch) + 1));
|
|
2908
|
+
start = corner.distance + corner.clearance;
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
const coil = spec.concertina ? Array.from({ length: resolution + 1 }, (_, index) => {
|
|
2912
|
+
const angle = index / resolution * Math.PI * 2;
|
|
2913
|
+
return [.25 * size * Math.cos(angle), -size / 2 + size / 2 * Math.sin(angle)];
|
|
2914
|
+
}) : [];
|
|
2915
|
+
const markers = [];
|
|
2916
|
+
for (const center of centers) for (const offset of spec.paired ? [-pairOffset, pairOffset] : [0]) {
|
|
2917
|
+
const { point, along, perp } = pointAlongPolyline(segments, totalLength, (center + offset) / totalLength);
|
|
2918
|
+
const at = (x, y) => toPosition([point[0] + along[0] * x + perp[0] * y, point[1] + along[1] * x + perp[1] * y]);
|
|
2919
|
+
if (spec.concertina) {
|
|
2920
|
+
const loop = coil.map(([x, y]) => at(x, y));
|
|
2921
|
+
loop[loop.length - 1] = loop[0];
|
|
2922
|
+
markers.push(loop);
|
|
2923
|
+
continue;
|
|
2924
|
+
}
|
|
2925
|
+
const lift = spec.oneSided ? -size / 2 : 0;
|
|
2926
|
+
markers.push([at(-halfWidth, lift - size / 2), at(halfWidth, lift + size / 2)], [at(-halfWidth, lift + size / 2), at(halfWidth, lift - size / 2)]);
|
|
2927
|
+
}
|
|
2928
|
+
const features = [];
|
|
2929
|
+
if (spec.rails > 0) {
|
|
2930
|
+
const coordinates = [path.map(toPosition)];
|
|
2931
|
+
if (spec.rails === 2) {
|
|
2932
|
+
const { right } = offsetPolylineSides(path, path.map(() => spec.railSeparation * size));
|
|
2933
|
+
coordinates.push(right.map(toPosition));
|
|
2934
|
+
}
|
|
2935
|
+
features.push({
|
|
2936
|
+
type: "Feature",
|
|
2937
|
+
properties: { part: "wire" },
|
|
2938
|
+
geometry: {
|
|
2939
|
+
type: "MultiLineString",
|
|
2940
|
+
coordinates
|
|
2941
|
+
}
|
|
2942
|
+
});
|
|
2943
|
+
}
|
|
2944
|
+
features.push({
|
|
2945
|
+
type: "Feature",
|
|
2946
|
+
properties: { part: spec.concertina ? "loops" : "crosses" },
|
|
2947
|
+
geometry: {
|
|
2948
|
+
type: "MultiLineString",
|
|
2949
|
+
coordinates: markers
|
|
2950
|
+
}
|
|
2951
|
+
});
|
|
2952
|
+
const labels = [];
|
|
2953
|
+
pushHostileEndLabels(labels, path, text.N, options, "", context);
|
|
2954
|
+
return {
|
|
2955
|
+
type: "FeatureCollection",
|
|
2956
|
+
features: [...features, ...labels]
|
|
2957
|
+
};
|
|
2958
|
+
}
|
|
2959
|
+
function definition$1(id, name, kind) {
|
|
2960
|
+
const spec = WIRE_KINDS[kind];
|
|
2961
|
+
return defineControlMeasure({
|
|
2962
|
+
metadata: {
|
|
2963
|
+
id,
|
|
2964
|
+
name,
|
|
2965
|
+
description: spec.description,
|
|
2966
|
+
entity: "Protection Lines",
|
|
2967
|
+
entityType: "Wire Obstacles",
|
|
2968
|
+
entitySubtype: spec.subtype,
|
|
2969
|
+
value: spec.value,
|
|
2970
|
+
minCoordinates: 2,
|
|
2971
|
+
geometry: "line",
|
|
2972
|
+
geometryTypes: ["MultiLineString", "Point"],
|
|
2973
|
+
paints: {
|
|
2974
|
+
stroke: true,
|
|
2975
|
+
fill: "none",
|
|
2976
|
+
text: true
|
|
2977
|
+
},
|
|
2978
|
+
drawRule: "Line1",
|
|
2979
|
+
capturesLabelSize: true,
|
|
2980
|
+
labelGeometryUsesResolvedMetrics: ["N"],
|
|
2981
|
+
textAmplifiers: [HOSTILE_LINE_AMPLIFIER],
|
|
2982
|
+
sizePairs: [{
|
|
2983
|
+
id: "cross-size",
|
|
2984
|
+
label: "Marker size",
|
|
2985
|
+
pixels: "markerSizePixels",
|
|
2986
|
+
meters: "markerSize",
|
|
2987
|
+
defaultUnit: "m",
|
|
2988
|
+
rendering: "geometry"
|
|
2989
|
+
}],
|
|
2990
|
+
params: [
|
|
2991
|
+
...SMOOTH_LINE_PARAMS,
|
|
2992
|
+
...spec.concertina ? ARC_RESOLUTION_PARAMS : [],
|
|
2993
|
+
...WIRE_MARKER_PARAMS,
|
|
2994
|
+
{
|
|
2995
|
+
...WIRE_SPACING_PARAM,
|
|
2996
|
+
min: spec.minSpacing
|
|
2997
|
+
},
|
|
2998
|
+
LABEL_PADDING_PARAM
|
|
2999
|
+
]
|
|
3000
|
+
},
|
|
3001
|
+
generator: (positions, options = {}, text = {}, context = {}) => createWireObstacle(positions, options, text, context, kind),
|
|
3002
|
+
defaultOptions: {
|
|
3003
|
+
...spec.concertina ? { resolution: 64 } : {},
|
|
3004
|
+
markerSize: DEFAULT_MARKER_SIZE,
|
|
3005
|
+
markerSizePixels: DEFAULT_MARKER_SIZE_PIXELS,
|
|
3006
|
+
markerSpacingRatio: spec.spacing,
|
|
3007
|
+
smooth: false,
|
|
3008
|
+
smoothResolution: 16
|
|
3009
|
+
},
|
|
3010
|
+
rule: line1DrawRule,
|
|
3011
|
+
previewSample: {
|
|
3012
|
+
controlPoints: [[1, 0], [-1, 0]],
|
|
3013
|
+
options: { markerSize: spec.previewMarkerSize }
|
|
3014
|
+
}
|
|
3015
|
+
});
|
|
3016
|
+
}
|
|
3017
|
+
const WIRE_OBSTACLE_UNSPECIFIED = definition$1("wire-obstacle-unspecified", "Wire Obstacles – Unspecified", "unspecified");
|
|
3018
|
+
const SINGLE_FENCE = definition$1("single-fence", "Single Fence", "single");
|
|
3019
|
+
const DOUBLE_FENCE = definition$1("double-fence", "Double Fence", "double");
|
|
3020
|
+
const DOUBLE_APRON_FENCE = definition$1("double-apron-fence", "Double Apron Fence", "apron");
|
|
3021
|
+
const LOW_WIRE_FENCE = definition$1("low-wire-fence", "Low Wire Fence", "low");
|
|
3022
|
+
const HIGH_WIRE_FENCE = definition$1("high-wire-fence", "High Wire Fence", "high");
|
|
3023
|
+
const SINGLE_CONCERTINA = definition$1("single-concertina", "Single Concertina", "concertina");
|
|
3024
|
+
const DOUBLE_STRAND_CONCERTINA = definition$1("double-strand-concertina", "Double Strand Concertina", "double-concertina");
|
|
3025
|
+
const TRIPLE_STRAND_CONCERTINA = definition$1("triple-strand-concertina", "Triple Strand Concertina", "triple-concertina");
|
|
2624
3026
|
//#endregion
|
|
2625
3027
|
//#region src/generators/cm34-mission-tasks/shared.ts
|
|
2626
3028
|
/**
|
|
@@ -2745,8 +3147,16 @@ function createBracketSymbol(coordinates, config, context) {
|
|
|
2745
3147
|
}, createLabelFeature(rearMidpoint, config.labelText, labelRotation, config.labelOptions)]
|
|
2746
3148
|
};
|
|
2747
3149
|
}
|
|
2748
|
-
|
|
2749
|
-
|
|
3150
|
+
/** The single sized dimension every cross-symbol mission task shares. */
|
|
3151
|
+
const CROSS_TASK_SIZE_PAIR = {
|
|
3152
|
+
id: "size",
|
|
3153
|
+
label: "Size",
|
|
3154
|
+
pixels: "sizePixels",
|
|
3155
|
+
meters: "sizeMeters",
|
|
3156
|
+
defaultUnit: "px",
|
|
3157
|
+
rendering: "geometry",
|
|
3158
|
+
fallbackMeters: 1e3
|
|
3159
|
+
};
|
|
2750
3160
|
const DEFAULT_CROSS_TASK_OPTIONS = {
|
|
2751
3161
|
sizePixels: 80,
|
|
2752
3162
|
rotation: 0,
|
|
@@ -2986,6 +3396,7 @@ const DEFAULT_DEFEAT_OPTIONS = {
|
|
|
2986
3396
|
};
|
|
2987
3397
|
const DEFEAT_METADATA = {
|
|
2988
3398
|
id: "defeat",
|
|
3399
|
+
sizePairs: [CROSS_TASK_SIZE_PAIR],
|
|
2989
3400
|
name: "Defeat",
|
|
2990
3401
|
description: "Renders an enemy force unable or unwilling to achieve its objectives.",
|
|
2991
3402
|
entity: "Mission Tasks",
|
|
@@ -3032,6 +3443,7 @@ const DEFEAT = defineControlMeasure({
|
|
|
3032
3443
|
const DEFAULT_SUPPRESS_OPTIONS = DEFAULT_CROSS_TASK_OPTIONS;
|
|
3033
3444
|
const SUPPRESS_METADATA = {
|
|
3034
3445
|
id: "suppress",
|
|
3446
|
+
sizePairs: [CROSS_TASK_SIZE_PAIR],
|
|
3035
3447
|
name: "Suppress",
|
|
3036
3448
|
description: "Temporarily degrades an enemy force or weapon system below the level needed to accomplish its mission.",
|
|
3037
3449
|
entity: "Mission Tasks",
|
|
@@ -3071,6 +3483,7 @@ const SUPPRESS = defineControlMeasure({
|
|
|
3071
3483
|
const DEFAULT_NEUTRALIZE_OPTIONS = DEFAULT_CROSS_TASK_OPTIONS;
|
|
3072
3484
|
const NEUTRALIZE_METADATA = {
|
|
3073
3485
|
id: "neutralize",
|
|
3486
|
+
sizePairs: [CROSS_TASK_SIZE_PAIR],
|
|
3074
3487
|
name: "Neutralize",
|
|
3075
3488
|
description: "Renders enemy personnel or materiel incapable of interfering with an operation.",
|
|
3076
3489
|
entity: "Mission Tasks",
|
|
@@ -3110,6 +3523,7 @@ const NEUTRALIZE = defineControlMeasure({
|
|
|
3110
3523
|
const DEFAULT_DESTROY_OPTIONS = DEFAULT_CROSS_TASK_OPTIONS;
|
|
3111
3524
|
const DESTROY_METADATA = {
|
|
3112
3525
|
id: "destroy",
|
|
3526
|
+
sizePairs: [CROSS_TASK_SIZE_PAIR],
|
|
3113
3527
|
name: "Destroy",
|
|
3114
3528
|
description: "Renders an enemy force or capability physically combat-ineffective until reconstituted.",
|
|
3115
3529
|
entity: "Mission Tasks",
|
|
@@ -3155,6 +3569,15 @@ const DESTROY = defineControlMeasure({
|
|
|
3155
3569
|
* monocolor (ADR-0023). Every glyph is built from three primitives — vertical
|
|
3156
3570
|
* bars, crosses, and dots — plus the team/crew ring and command `++`.
|
|
3157
3571
|
*/
|
|
3572
|
+
/** Shared echelon dimension for every measure that stamps a unit-size amplifier. */
|
|
3573
|
+
const ECHELON_SIZE_PAIR = {
|
|
3574
|
+
id: "echelon",
|
|
3575
|
+
label: "Echelon size",
|
|
3576
|
+
pixels: "echelonSizePixels",
|
|
3577
|
+
meters: "echelonSize",
|
|
3578
|
+
defaultUnit: "m",
|
|
3579
|
+
rendering: "geometry"
|
|
3580
|
+
};
|
|
3158
3581
|
const ECHELONS = {
|
|
3159
3582
|
team: {
|
|
3160
3583
|
kind: "ring",
|
|
@@ -6216,6 +6639,7 @@ const freezeEchelonLabeledAreaAnchor = makeFreezeEchelonAnchor({
|
|
|
6216
6639
|
const DEFAULT_BASE_CAMP_OPTIONS = DEFAULT_ECHELON_LABELED_AREA_OPTIONS;
|
|
6217
6640
|
const BASE_CAMP_METADATA = {
|
|
6218
6641
|
id: "base-camp",
|
|
6642
|
+
sizePairs: [ECHELON_SIZE_PAIR],
|
|
6219
6643
|
name: "Base camp",
|
|
6220
6644
|
description: "An evolving military facility that supports military operations of a deployed unit and provides the necessary support and services for sustained operations.",
|
|
6221
6645
|
entity: "Command and Control Areas",
|
|
@@ -6275,6 +6699,7 @@ const BASE_CAMP = defineControlMeasure({
|
|
|
6275
6699
|
const DEFAULT_GUERRILLA_BASE_OPTIONS = DEFAULT_ECHELON_LABELED_AREA_OPTIONS;
|
|
6276
6700
|
const GUERRILLA_BASE_METADATA = {
|
|
6277
6701
|
id: "guerrilla-base",
|
|
6702
|
+
sizePairs: [ECHELON_SIZE_PAIR],
|
|
6278
6703
|
name: "Guerrilla base",
|
|
6279
6704
|
description: "A temporary site where guerrilla installations, headquarters, and units are located.",
|
|
6280
6705
|
entity: "Command and Control Areas",
|
|
@@ -6444,82 +6869,19 @@ const ASSEMBLY_AREA = defineControlMeasure({
|
|
|
6444
6869
|
}
|
|
6445
6870
|
});
|
|
6446
6871
|
//#endregion
|
|
6447
|
-
//#region src/generators/cm29-protection-lines/params.ts
|
|
6448
|
-
const FORTIFIED_PARAMS = [
|
|
6449
|
-
...SMOOTH_LINE_PARAMS,
|
|
6450
|
-
{
|
|
6451
|
-
key: "toothSizePixels",
|
|
6452
|
-
label: "Tooth size",
|
|
6453
|
-
description: "Side length of the square crenellations",
|
|
6454
|
-
type: "number",
|
|
6455
|
-
min: 5,
|
|
6456
|
-
max: 50,
|
|
6457
|
-
step: 1,
|
|
6458
|
-
unit: "px"
|
|
6459
|
-
},
|
|
6460
|
-
{
|
|
6461
|
-
key: "toothSize",
|
|
6462
|
-
label: "Tooth size",
|
|
6463
|
-
description: "Side length of the square crenellations",
|
|
6464
|
-
type: "number",
|
|
6465
|
-
min: 1,
|
|
6466
|
-
max: 500,
|
|
6467
|
-
step: 1,
|
|
6468
|
-
unit: "m"
|
|
6469
|
-
},
|
|
6470
|
-
LABEL_PADDING_PARAM
|
|
6471
|
-
];
|
|
6472
|
-
const ANTITANK_DITCH_PARAMS = [
|
|
6473
|
-
...SMOOTH_LINE_PARAMS,
|
|
6474
|
-
{
|
|
6475
|
-
key: "toothHeightPixels",
|
|
6476
|
-
label: "Tooth height",
|
|
6477
|
-
description: "Perpendicular depth of each triangular tooth",
|
|
6478
|
-
type: "number",
|
|
6479
|
-
min: 5,
|
|
6480
|
-
max: 50,
|
|
6481
|
-
step: 1,
|
|
6482
|
-
unit: "px"
|
|
6483
|
-
},
|
|
6484
|
-
{
|
|
6485
|
-
key: "toothHeight",
|
|
6486
|
-
label: "Tooth height",
|
|
6487
|
-
description: "Perpendicular depth of each triangular tooth",
|
|
6488
|
-
type: "number",
|
|
6489
|
-
min: 1,
|
|
6490
|
-
max: 500,
|
|
6491
|
-
step: 1,
|
|
6492
|
-
unit: "m"
|
|
6493
|
-
},
|
|
6494
|
-
{
|
|
6495
|
-
key: "toothWidthRatio",
|
|
6496
|
-
presentationTier: "advanced",
|
|
6497
|
-
label: "Tooth width ratio",
|
|
6498
|
-
description: "Tooth base span as a multiple of height",
|
|
6499
|
-
type: "number",
|
|
6500
|
-
min: .5,
|
|
6501
|
-
max: 3,
|
|
6502
|
-
step: .05,
|
|
6503
|
-
unit: "x"
|
|
6504
|
-
},
|
|
6505
|
-
LABEL_PADDING_PARAM
|
|
6506
|
-
];
|
|
6507
|
-
const ANTITANK_WALL_PARAMS = [...ANTITANK_DITCH_PARAMS, {
|
|
6508
|
-
key: "toothSpacingRatio",
|
|
6509
|
-
presentationTier: "advanced",
|
|
6510
|
-
label: "Tooth spacing ratio",
|
|
6511
|
-
description: "Gap between teeth as a multiple of base width",
|
|
6512
|
-
type: "number",
|
|
6513
|
-
min: 0,
|
|
6514
|
-
max: 3,
|
|
6515
|
-
step: .05,
|
|
6516
|
-
unit: "x"
|
|
6517
|
-
}];
|
|
6518
|
-
//#endregion
|
|
6519
6872
|
//#region src/generators/cm29-protection-lines/antitankDitch.ts
|
|
6520
6873
|
const DEFAULT_TOOTH_HEIGHT = 50;
|
|
6521
6874
|
const DEFAULT_TOOTH_HEIGHT_PIXELS = 10;
|
|
6522
6875
|
const DEFAULT_TOOTH_WIDTH_RATIO$1 = 1.15;
|
|
6876
|
+
/** Shared by both ditch variants and by the antitank wall built on the same teeth. */
|
|
6877
|
+
const TOOTH_HEIGHT_SIZE_PAIR = {
|
|
6878
|
+
id: "tooth-height",
|
|
6879
|
+
label: "Tooth height",
|
|
6880
|
+
pixels: "toothHeightPixels",
|
|
6881
|
+
meters: "toothHeight",
|
|
6882
|
+
defaultUnit: "m",
|
|
6883
|
+
rendering: "geometry"
|
|
6884
|
+
};
|
|
6523
6885
|
const DEFAULT_ANTITANK_DITCH_OPTIONS = {
|
|
6524
6886
|
toothHeight: DEFAULT_TOOTH_HEIGHT,
|
|
6525
6887
|
toothHeightPixels: DEFAULT_TOOTH_HEIGHT_PIXELS,
|
|
@@ -6529,6 +6891,7 @@ const DEFAULT_ANTITANK_DITCH_OPTIONS = {
|
|
|
6529
6891
|
};
|
|
6530
6892
|
const ANTITANK_DITCH_UNDER_CONSTRUCTION_METADATA = {
|
|
6531
6893
|
id: "antitank-ditch-under-construction",
|
|
6894
|
+
sizePairs: [TOOTH_HEIGHT_SIZE_PAIR],
|
|
6532
6895
|
name: "Ditch - Under Construction",
|
|
6533
6896
|
description: "Antitank ditch obstacle under construction.",
|
|
6534
6897
|
entity: "Protection Lines",
|
|
@@ -6551,6 +6914,7 @@ const ANTITANK_DITCH_UNDER_CONSTRUCTION_METADATA = {
|
|
|
6551
6914
|
};
|
|
6552
6915
|
const ANTITANK_DITCH_COMPLETED_METADATA = {
|
|
6553
6916
|
id: "antitank-ditch-completed",
|
|
6917
|
+
sizePairs: [TOOTH_HEIGHT_SIZE_PAIR],
|
|
6554
6918
|
name: "Ditch - Completed",
|
|
6555
6919
|
description: "Completed antitank ditch obstacle.",
|
|
6556
6920
|
entity: "Protection Lines",
|
|
@@ -6684,6 +7048,7 @@ const DEFAULT_ANTITANK_WALL_OPTIONS = {
|
|
|
6684
7048
|
};
|
|
6685
7049
|
const ANTITANK_WALL_METADATA = {
|
|
6686
7050
|
id: "antitank-wall",
|
|
7051
|
+
sizePairs: [TOOTH_HEIGHT_SIZE_PAIR],
|
|
6687
7052
|
name: "Antitank Wall",
|
|
6688
7053
|
description: "Antitank wall obstacle.",
|
|
6689
7054
|
entity: "Protection Lines",
|
|
@@ -7148,6 +7513,7 @@ const DEFAULT_BATTLE_POSITION_OPTIONS = {
|
|
|
7148
7513
|
};
|
|
7149
7514
|
const BATTLE_POSITION_METADATA = {
|
|
7150
7515
|
id: "battle-position",
|
|
7516
|
+
sizePairs: [ECHELON_SIZE_PAIR],
|
|
7151
7517
|
name: "Battle Position",
|
|
7152
7518
|
description: "A defensive location oriented on a likely enemy avenue of approach, labeled with the echelon of the occupying unit.",
|
|
7153
7519
|
entity: "Maneuver Areas",
|
|
@@ -7291,6 +7657,7 @@ const BATTLE_POSITION_PREPARED_DASH = [6, 4];
|
|
|
7291
7657
|
const DEFAULT_BATTLE_POSITION_PREPARED_OPTIONS = { ...DEFAULT_BATTLE_POSITION_OPTIONS };
|
|
7292
7658
|
const BATTLE_POSITION_PREPARED_METADATA = {
|
|
7293
7659
|
id: "battle-position-prepared",
|
|
7660
|
+
sizePairs: [ECHELON_SIZE_PAIR],
|
|
7294
7661
|
name: "Battle Position Prepared (P) but not Occupied",
|
|
7295
7662
|
description: "A battle position that has been prepared for occupation but is not yet occupied, drawn with a dashed boundary and a (P)-prefixed designation.",
|
|
7296
7663
|
entity: "Maneuver Areas",
|
|
@@ -8258,6 +8625,7 @@ const DEFAULT_BOUNDARY_OPTIONS = {
|
|
|
8258
8625
|
};
|
|
8259
8626
|
const BOUNDARY_METADATA = {
|
|
8260
8627
|
id: "boundary",
|
|
8628
|
+
sizePairs: [ECHELON_SIZE_PAIR],
|
|
8261
8629
|
name: "Boundary",
|
|
8262
8630
|
description: "Delineates the area of responsibility between two adjacent units, labeled with the echelon and the designators of the units it separates.",
|
|
8263
8631
|
entity: "Command and Control Lines",
|
|
@@ -8675,6 +9043,7 @@ const DEFAULT_GENERIC_C2_LINE_OPTIONS = {
|
|
|
8675
9043
|
};
|
|
8676
9044
|
const GENERIC_C2_LINE_METADATA = {
|
|
8677
9045
|
id: "generic-c2-line",
|
|
9046
|
+
sizePairs: [ECHELON_SIZE_PAIR],
|
|
8678
9047
|
name: "Generic command and control line",
|
|
8679
9048
|
description: "Illustrative command-and-control-style line (not part of MIL-STD-2525E) carrying optional echelon glyphs, additional-information/designation text above it, and an effective date-time-group window below it.",
|
|
8680
9049
|
entity: "Command and Control Lines",
|
|
@@ -9532,20 +9901,6 @@ function normalizeSmoothResolution(value) {
|
|
|
9532
9901
|
if (!Number.isFinite(value)) return DEFAULT_SMOOTH_RESOLUTION$3;
|
|
9533
9902
|
return Math.min(MAX_SMOOTH_RESOLUTION, Math.max(MIN_SMOOTH_RESOLUTION, Math.round(value)));
|
|
9534
9903
|
}
|
|
9535
|
-
function normalizeArcResolution(value) {
|
|
9536
|
-
if (typeof value !== "number" || !Number.isFinite(value)) return 64;
|
|
9537
|
-
return Math.min(360, Math.max(4, Math.round(value)));
|
|
9538
|
-
}
|
|
9539
|
-
const ARC_RESOLUTION_PARAMS = [{
|
|
9540
|
-
key: "resolution",
|
|
9541
|
-
presentationTier: "advanced",
|
|
9542
|
-
label: "Resolution",
|
|
9543
|
-
description: "Number of segments in a full 360° sweep.",
|
|
9544
|
-
type: "number",
|
|
9545
|
-
min: 4,
|
|
9546
|
-
max: 360,
|
|
9547
|
-
step: 1
|
|
9548
|
-
}];
|
|
9549
9904
|
//#endregion
|
|
9550
9905
|
//#region src/generators/cm99-generic-graphics/params.ts
|
|
9551
9906
|
const SMOOTH_PATH_PARAMS = [{
|
|
@@ -10006,6 +10361,14 @@ const DEFAULT_GENERIC_TEXT_OPTIONS = {
|
|
|
10006
10361
|
};
|
|
10007
10362
|
const GENERIC_TEXT_METADATA = {
|
|
10008
10363
|
id: "text",
|
|
10364
|
+
sizePairs: [{
|
|
10365
|
+
id: "size",
|
|
10366
|
+
label: "Size",
|
|
10367
|
+
pixels: "sizePixels",
|
|
10368
|
+
meters: "sizeMeters",
|
|
10369
|
+
defaultUnit: "px",
|
|
10370
|
+
rendering: "text"
|
|
10371
|
+
}],
|
|
10009
10372
|
name: "Text",
|
|
10010
10373
|
description: "A non-doctrinal free-standing text label anchored at a single point.",
|
|
10011
10374
|
entity: "Generic Graphics",
|
|
@@ -11388,7 +11751,7 @@ function createSecurityTaskSymbol(coordinates, config, options = {}) {
|
|
|
11388
11751
|
...options
|
|
11389
11752
|
};
|
|
11390
11753
|
const arrowOptions = resolveTacticalArrowOptions(resolved);
|
|
11391
|
-
const lines = [createTacticalArrow(p2, p1,
|
|
11754
|
+
const lines = [createTacticalArrow(p2, p1, arrowOptions, -1), createTacticalArrow(p3, p4, arrowOptions, 1)].flatMap((arrow) => arrow ?? []);
|
|
11392
11755
|
if (lines.length === 0) return {
|
|
11393
11756
|
type: "FeatureCollection",
|
|
11394
11757
|
features: []
|
|
@@ -11418,13 +11781,12 @@ function createSecurityTaskSymbol(coordinates, config, options = {}) {
|
|
|
11418
11781
|
};
|
|
11419
11782
|
}
|
|
11420
11783
|
/** A Search Area-style lightning shaft with a Principal Direction of Fire open head. */
|
|
11421
|
-
function createTacticalArrow(origin, tip,
|
|
11784
|
+
function createTacticalArrow(origin, tip, options, bendSide) {
|
|
11422
11785
|
const leg = vecSub(tip, origin);
|
|
11423
11786
|
const totalLegLength = vecMag(leg);
|
|
11424
11787
|
if (totalLegLength < 1e-6) return void 0;
|
|
11425
11788
|
const legDirection = vecNorm(leg);
|
|
11426
|
-
|
|
11427
|
-
if (vecDot(normal, vecSub(opposite, origin)) > 0) normal = vecScale(normal, -1);
|
|
11789
|
+
const normal = [-legDirection[1] * bendSide, legDirection[0] * bendSide];
|
|
11428
11790
|
const amplitude = totalLegLength * options.zigzagAmplitudeRatio;
|
|
11429
11791
|
const zigzagPointA = vecAdd(vecAdd(origin, vecScale(leg, options.zigzagStart)), vecScale(normal, amplitude));
|
|
11430
11792
|
const zigzagPointB = vecAdd(vecAdd(origin, vecScale(leg, options.zigzagEnd)), vecScale(normal, -amplitude));
|
|
@@ -13509,6 +13871,14 @@ const DEFAULT_FLOT_OPTIONS = {
|
|
|
13509
13871
|
};
|
|
13510
13872
|
const FLOT_METADATA = {
|
|
13511
13873
|
id: "flot",
|
|
13874
|
+
sizePairs: [{
|
|
13875
|
+
id: "radius",
|
|
13876
|
+
label: "Radius",
|
|
13877
|
+
pixels: "radiusPixels",
|
|
13878
|
+
meters: "radius",
|
|
13879
|
+
defaultUnit: "m",
|
|
13880
|
+
rendering: "geometry"
|
|
13881
|
+
}],
|
|
13512
13882
|
name: "Forward line of own troops (FLOT)",
|
|
13513
13883
|
description: "Indicates the most forward positions of friendly forces at a specific time.",
|
|
13514
13884
|
entity: "Maneuver Lines",
|
|
@@ -14679,6 +15049,15 @@ const PROBABLE_LINE_OF_DEPLOYMENT = defineControlMeasure({
|
|
|
14679
15049
|
});
|
|
14680
15050
|
//#endregion
|
|
14681
15051
|
//#region src/generators/cm29-protection-lines/fortifiedLine.ts
|
|
15052
|
+
/** Shared by the fortified line and the fortified area built from it. */
|
|
15053
|
+
const TOOTH_SIZE_SIZE_PAIR = {
|
|
15054
|
+
id: "tooth-size",
|
|
15055
|
+
label: "Tooth size",
|
|
15056
|
+
pixels: "toothSizePixels",
|
|
15057
|
+
meters: "toothSize",
|
|
15058
|
+
defaultUnit: "m",
|
|
15059
|
+
rendering: "geometry"
|
|
15060
|
+
};
|
|
14682
15061
|
const DEFAULT_TOOTH_SIZE = 50;
|
|
14683
15062
|
const DEFAULT_TOOTH_SIZE_PIXELS = 10;
|
|
14684
15063
|
const DEFAULT_SMOOTH_RESOLUTION$1 = 16;
|
|
@@ -14693,6 +15072,7 @@ const DEFAULT_FORTIFIED_LINE_OPTIONS = {
|
|
|
14693
15072
|
};
|
|
14694
15073
|
const FORTIFIED_LINE_METADATA = {
|
|
14695
15074
|
id: "fortified-line",
|
|
15075
|
+
sizePairs: [TOOTH_SIZE_SIZE_PAIR],
|
|
14696
15076
|
name: "Fortified Line",
|
|
14697
15077
|
description: "Fortified line with castellated square-wave boundary.",
|
|
14698
15078
|
entity: "Protection Lines",
|
|
@@ -14850,6 +15230,7 @@ const FORTIFIED_LINE = defineControlMeasure({
|
|
|
14850
15230
|
const DEFAULT_FORTIFIED_AREA_OPTIONS = DEFAULT_FORTIFIED_LINE_OPTIONS;
|
|
14851
15231
|
const FORTIFIED_AREA_METADATA = {
|
|
14852
15232
|
id: "fortified-area",
|
|
15233
|
+
sizePairs: [TOOTH_SIZE_SIZE_PAIR],
|
|
14853
15234
|
name: "Fortified Area",
|
|
14854
15235
|
description: "A specified geographical locality with constructed defensive works as protection against attack.",
|
|
14855
15236
|
entity: "Maneuver Areas",
|
|
@@ -16960,6 +17341,15 @@ const DEFAULT_MINEFIELD_OPTIONS = {
|
|
|
16960
17341
|
const DEFAULT_MINEFIELD_SIZE_METERS = 1e3;
|
|
16961
17342
|
const MINEFIELD_METADATA = {
|
|
16962
17343
|
id: "minefield",
|
|
17344
|
+
sizePairs: [{
|
|
17345
|
+
id: "size",
|
|
17346
|
+
label: "Size",
|
|
17347
|
+
pixels: "sizePixels",
|
|
17348
|
+
meters: "sizeMeters",
|
|
17349
|
+
defaultUnit: "px",
|
|
17350
|
+
rendering: "geometry",
|
|
17351
|
+
fallbackMeters: DEFAULT_MINEFIELD_SIZE_METERS
|
|
17352
|
+
}],
|
|
16963
17353
|
name: "Minefield",
|
|
16964
17354
|
description: "A static point symbol identifying a minefield and its mine type.",
|
|
16965
17355
|
entity: "Protection Areas",
|
|
@@ -17262,6 +17652,206 @@ const MINEFIELD = defineControlMeasure({
|
|
|
17262
17652
|
}
|
|
17263
17653
|
});
|
|
17264
17654
|
//#endregion
|
|
17655
|
+
//#region src/generators/cm27-protection-areas/obstacle-areas.ts
|
|
17656
|
+
const DEFAULT_OBSTACLE_AREA_OPTIONS = {
|
|
17657
|
+
toothSize: 50,
|
|
17658
|
+
toothSizePixels: 10,
|
|
17659
|
+
smooth: false,
|
|
17660
|
+
smoothResolution: 16
|
|
17661
|
+
};
|
|
17662
|
+
/** Preserve control-point corners and keep tooth direction independent of winding. */
|
|
17663
|
+
function toothedRing(ring, size, inward) {
|
|
17664
|
+
const side = (ringSignedArea2(ring) >= 0 ? -1 : 1) * (inward ? -1 : 1);
|
|
17665
|
+
const width = size * (inward ? 1 : .8);
|
|
17666
|
+
const pitch = size * (inward ? 2.4 : 1.6);
|
|
17667
|
+
const result = [ring[0]];
|
|
17668
|
+
for (let i = 1; i < ring.length; i++) {
|
|
17669
|
+
const a = ring[i - 1];
|
|
17670
|
+
const b = ring[i];
|
|
17671
|
+
const dx = b[0] - a[0];
|
|
17672
|
+
const dy = b[1] - a[1];
|
|
17673
|
+
const length = Math.hypot(dx, dy);
|
|
17674
|
+
if (length < 1e-6) continue;
|
|
17675
|
+
const margin = inward ? Math.min(length / 4, .75 * size) : 0;
|
|
17676
|
+
const available = length - 2 * margin;
|
|
17677
|
+
const count = Math.max(1, Math.round(available / pitch));
|
|
17678
|
+
const fittedWidth = Math.min(width, available / count);
|
|
17679
|
+
const offsets = [
|
|
17680
|
+
-fittedWidth / 2,
|
|
17681
|
+
0,
|
|
17682
|
+
fittedWidth / 2
|
|
17683
|
+
];
|
|
17684
|
+
for (let tooth = 0; tooth < count; tooth++) {
|
|
17685
|
+
const center = margin + (tooth + .5) / count * available;
|
|
17686
|
+
for (const offset of offsets) {
|
|
17687
|
+
const t = (center + offset) / length;
|
|
17688
|
+
const height = offset === 0 ? side * size : 0;
|
|
17689
|
+
result.push([a[0] + dx * t - dy / length * height, a[1] + dy * t + dx / length * height]);
|
|
17690
|
+
}
|
|
17691
|
+
}
|
|
17692
|
+
result.push(b);
|
|
17693
|
+
}
|
|
17694
|
+
result[result.length - 1] = result[0];
|
|
17695
|
+
return result;
|
|
17696
|
+
}
|
|
17697
|
+
const OBSTACLE_AREA_KINDS = {
|
|
17698
|
+
belt: {
|
|
17699
|
+
inward: false,
|
|
17700
|
+
previewToothSize: 170,
|
|
17701
|
+
description: "A brigade-level control measure within an obstacle zone that limits friendly obstacle employment and focuses the defense."
|
|
17702
|
+
},
|
|
17703
|
+
zone: {
|
|
17704
|
+
inward: false,
|
|
17705
|
+
previewToothSize: 140,
|
|
17706
|
+
description: "A division-level control measure designating land areas where subordinate units are authorized to employ tactical obstacles."
|
|
17707
|
+
},
|
|
17708
|
+
free: {
|
|
17709
|
+
inward: true,
|
|
17710
|
+
previewToothSize: 130,
|
|
17711
|
+
description: "An area designated to remain completely free of reinforcing obstacles."
|
|
17712
|
+
},
|
|
17713
|
+
restricted: {
|
|
17714
|
+
inward: true,
|
|
17715
|
+
previewToothSize: 130,
|
|
17716
|
+
description: "A control measure limiting the types or number of obstacles permitted within an area."
|
|
17717
|
+
}
|
|
17718
|
+
};
|
|
17719
|
+
function createObstacleArea(positions, options, text, context, kind) {
|
|
17720
|
+
const ring = buildClosedRing(positions, options.smooth ?? false, options.smoothResolution ?? 16, 16);
|
|
17721
|
+
const size = calculateAntitankDitchHeight({
|
|
17722
|
+
toothHeight: options.toothSize,
|
|
17723
|
+
toothHeightPixels: options.toothSizePixels,
|
|
17724
|
+
metersPerPixel: options.metersPerPixel
|
|
17725
|
+
});
|
|
17726
|
+
const { inward } = OBSTACLE_AREA_KINDS[kind];
|
|
17727
|
+
const boundary = toothedRing(options.smooth ? evenlySpacePath(ring, inward ? 8 * size : 4 * size) : ring, size, inward);
|
|
17728
|
+
const labels = [];
|
|
17729
|
+
const [cx, cy] = ringLabelAnchor(ring);
|
|
17730
|
+
const hasWindow = inward && Boolean(text.W || text.W1);
|
|
17731
|
+
const rows = Number(kind === "free") + Number(Boolean(text.T)) + Number(hasWindow);
|
|
17732
|
+
const pitch = resolveLabelOffsetMeters(options, 1.2 + Math.max(0, options.labelPadding ?? 0));
|
|
17733
|
+
let row = 0;
|
|
17734
|
+
const rowY = () => cy + ((rows - 1) / 2 - row++) * pitch;
|
|
17735
|
+
const sizeProps = labelSizeProps(options);
|
|
17736
|
+
const addLabel = (x, y, value, props = {}) => {
|
|
17737
|
+
pushLabel(labels, [x, y], value, HORIZONTAL_LABEL_ROTATION, sizeProps, props.anchor, props.field, props.key);
|
|
17738
|
+
if (props.labelPlacement === false) labels[labels.length - 1].properties.labelPlacement = false;
|
|
17739
|
+
};
|
|
17740
|
+
if (kind === "free") addLabel(cx, rowY(), "FREE", { key: "label:free" });
|
|
17741
|
+
if (text.T) addLabel(cx, rowY(), text.T, { field: "T" });
|
|
17742
|
+
if (hasWindow) {
|
|
17743
|
+
const y = rowY();
|
|
17744
|
+
if (text.W && text.W1) {
|
|
17745
|
+
const gap = resolveLabelOffsetMeters(options, 1.8);
|
|
17746
|
+
addLabel(cx - gap, y, text.W, {
|
|
17747
|
+
field: "W",
|
|
17748
|
+
anchor: "end"
|
|
17749
|
+
});
|
|
17750
|
+
addLabel(cx, y, "–", { labelPlacement: false });
|
|
17751
|
+
addLabel(cx + gap, y, text.W1, {
|
|
17752
|
+
field: "W1",
|
|
17753
|
+
anchor: "start"
|
|
17754
|
+
});
|
|
17755
|
+
} else if (text.W) addLabel(cx, y, text.W, { field: "W" });
|
|
17756
|
+
else if (text.W1) addLabel(cx, y, text.W1, { field: "W1" });
|
|
17757
|
+
}
|
|
17758
|
+
const gaps = pushAreaLabels(labels, ring, { hostile: text.N }, options, context.amplifierPlacements, {
|
|
17759
|
+
ringVerts: boundary,
|
|
17760
|
+
extraClearanceMeters: size
|
|
17761
|
+
}, context);
|
|
17762
|
+
if (kind === "restricted") for (const label of labels) label.properties.textBackground = true;
|
|
17763
|
+
return {
|
|
17764
|
+
type: "FeatureCollection",
|
|
17765
|
+
features: [...kind === "restricted" ? patternedAreaFeatures(boundary, gaps, "reverse-hatch") : [boundaryFeature(boundary, gaps)], ...labels]
|
|
17766
|
+
};
|
|
17767
|
+
}
|
|
17768
|
+
const COMMON_METADATA$1 = {
|
|
17769
|
+
entity: "Protection Areas",
|
|
17770
|
+
minCoordinates: 3,
|
|
17771
|
+
geometry: "area",
|
|
17772
|
+
geometryTypes: [
|
|
17773
|
+
"Polygon",
|
|
17774
|
+
"MultiLineString",
|
|
17775
|
+
"Point"
|
|
17776
|
+
],
|
|
17777
|
+
drawRule: "Area1",
|
|
17778
|
+
capturesLabelSize: true,
|
|
17779
|
+
labelGeometryUsesResolvedMetrics: ["N"],
|
|
17780
|
+
sizePairs: [TOOTH_SIZE_SIZE_PAIR],
|
|
17781
|
+
params: [
|
|
17782
|
+
{
|
|
17783
|
+
key: "toothSize",
|
|
17784
|
+
label: "Tooth size",
|
|
17785
|
+
description: "Boundary tooth height in meters",
|
|
17786
|
+
type: "number",
|
|
17787
|
+
min: 1,
|
|
17788
|
+
max: 500,
|
|
17789
|
+
step: 1,
|
|
17790
|
+
unit: "m"
|
|
17791
|
+
},
|
|
17792
|
+
{
|
|
17793
|
+
key: "toothSizePixels",
|
|
17794
|
+
label: "Tooth size",
|
|
17795
|
+
description: "Boundary tooth height in pixels",
|
|
17796
|
+
type: "number",
|
|
17797
|
+
min: 1,
|
|
17798
|
+
max: 50,
|
|
17799
|
+
step: 1,
|
|
17800
|
+
unit: "px"
|
|
17801
|
+
},
|
|
17802
|
+
...AREA_SMOOTH_PARAMS,
|
|
17803
|
+
AREA_LABEL_PADDING_PARAM
|
|
17804
|
+
]
|
|
17805
|
+
};
|
|
17806
|
+
function definition(id, name, value, kind) {
|
|
17807
|
+
const { inward, previewToothSize, description } = OBSTACLE_AREA_KINDS[kind];
|
|
17808
|
+
return defineControlMeasure({
|
|
17809
|
+
metadata: {
|
|
17810
|
+
...COMMON_METADATA$1,
|
|
17811
|
+
id,
|
|
17812
|
+
name,
|
|
17813
|
+
value,
|
|
17814
|
+
entityType: name,
|
|
17815
|
+
description,
|
|
17816
|
+
paints: {
|
|
17817
|
+
stroke: true,
|
|
17818
|
+
fill: kind === "restricted" ? "fixed" : "none",
|
|
17819
|
+
text: true
|
|
17820
|
+
},
|
|
17821
|
+
textAmplifiers: inward ? AREA_TEXT_AMPLIFIERS_NO_ADDITIONAL_INFO : AREA_TEXT_AMPLIFIERS_DESIGNATION_HOSTILE
|
|
17822
|
+
},
|
|
17823
|
+
generator: (positions, options = {}, text = {}, context = {}) => createObstacleArea(positions, options, text, context, kind),
|
|
17824
|
+
defaultOptions: DEFAULT_OBSTACLE_AREA_OPTIONS,
|
|
17825
|
+
rule: area1DrawRule,
|
|
17826
|
+
previewSample: {
|
|
17827
|
+
controlPoints: kind === "belt" ? [
|
|
17828
|
+
[-1, -.5],
|
|
17829
|
+
[1, -.5],
|
|
17830
|
+
[1, .5],
|
|
17831
|
+
[-1, .5]
|
|
17832
|
+
] : [
|
|
17833
|
+
[-1, -.7],
|
|
17834
|
+
[1, -.7],
|
|
17835
|
+
[.95, .25],
|
|
17836
|
+
[-1, .8]
|
|
17837
|
+
],
|
|
17838
|
+
options: {
|
|
17839
|
+
toothSize: previewToothSize,
|
|
17840
|
+
labelSize: inward ? 70 : 96
|
|
17841
|
+
},
|
|
17842
|
+
textAmplifiers: inward ? {
|
|
17843
|
+
T: "T",
|
|
17844
|
+
W: "W",
|
|
17845
|
+
W1: "W1"
|
|
17846
|
+
} : { T: "T" }
|
|
17847
|
+
}
|
|
17848
|
+
});
|
|
17849
|
+
}
|
|
17850
|
+
const OBSTACLE_BELT = definition("obstacle-belt", "Obstacle Belt", "270100", "belt");
|
|
17851
|
+
const OBSTACLE_ZONE = definition("obstacle-zone", "Obstacle Zone", "270200", "zone");
|
|
17852
|
+
const OBSTACLE_FREE_ZONE = definition("obstacle-free-zone", "Obstacle Free Zone", "270300", "free");
|
|
17853
|
+
const OBSTACLE_RESTRICTED_ZONE = definition("obstacle-restricted-zone", "Obstacle Restricted Zone", "270400", "restricted");
|
|
17854
|
+
//#endregion
|
|
17265
17855
|
//#region src/generators/cm27-protection-areas/mine-areas.ts
|
|
17266
17856
|
const DEFAULT_MINE_AREA_OPTIONS = {
|
|
17267
17857
|
mineType: "unspecified",
|
|
@@ -18278,14 +18868,12 @@ function createSearchArea(coordinates, options = {}) {
|
|
|
18278
18868
|
];
|
|
18279
18869
|
const shaftSegments = [];
|
|
18280
18870
|
const headPolygons = [];
|
|
18281
|
-
const addLeg = (origin, tip,
|
|
18871
|
+
const addLeg = (origin, tip, bendSide) => {
|
|
18282
18872
|
const v = vecSub(tip, origin);
|
|
18283
18873
|
const totalLen = vecMag(v);
|
|
18284
18874
|
if (totalLen < 1e-6) return;
|
|
18285
18875
|
const u = vecNorm(v);
|
|
18286
|
-
|
|
18287
|
-
const toOpp = vecSub(opposite, origin);
|
|
18288
|
-
if (vecDot(n, toOpp) > 0) n = vecScale(n, -1);
|
|
18876
|
+
const n = [-u[1] * bendSide, u[0] * bendSide];
|
|
18289
18877
|
const offset = totalLen * safeZigzagAmplitudeRatio;
|
|
18290
18878
|
const ptA = vecAdd(vecAdd(origin, vecScale(v, safeZigzagStart)), vecScale(n, offset));
|
|
18291
18879
|
const ptB = vecAdd(vecAdd(origin, vecScale(v, safeZigzagEnd)), vecScale(n, -offset));
|
|
@@ -18312,8 +18900,8 @@ function createSearchArea(coordinates, options = {}) {
|
|
|
18312
18900
|
tip
|
|
18313
18901
|
].map((p) => unproject(p[0], p[1]))]);
|
|
18314
18902
|
};
|
|
18315
|
-
addLeg(p1, p2,
|
|
18316
|
-
addLeg(p1, p3,
|
|
18903
|
+
addLeg(p1, p2, 1);
|
|
18904
|
+
addLeg(p1, p3, -1);
|
|
18317
18905
|
const features = [];
|
|
18318
18906
|
if (shaftSegments.length > 0) features.push({
|
|
18319
18907
|
type: "Feature",
|
|
@@ -18353,6 +18941,7 @@ const DEFAULT_SMOOTH_RESOLUTION = 16;
|
|
|
18353
18941
|
const DEFAULT_STRONG_POINT_OPTIONS = { ...DEFAULT_BATTLE_POSITION_OPTIONS };
|
|
18354
18942
|
const STRONG_POINT_METADATA = {
|
|
18355
18943
|
id: "strong-point",
|
|
18944
|
+
sizePairs: [ECHELON_SIZE_PAIR],
|
|
18356
18945
|
name: "Strong Point",
|
|
18357
18946
|
description: "A key point in a defensive position, usually strongly fortified and heavily armed, around which other positions are grouped for its protection.",
|
|
18358
18947
|
entity: "Maneuver Areas",
|
|
@@ -19033,6 +19622,10 @@ const DEFINITIONS = {
|
|
|
19033
19622
|
"no-fire-area-irregular": NO_FIRE_AREA_IRREGULAR,
|
|
19034
19623
|
"minefield-dynamic": DYNAMIC_MINEFIELD,
|
|
19035
19624
|
"mined-area": MINED_AREA,
|
|
19625
|
+
"obstacle-belt": OBSTACLE_BELT,
|
|
19626
|
+
"obstacle-zone": OBSTACLE_ZONE,
|
|
19627
|
+
"obstacle-free-zone": OBSTACLE_FREE_ZONE,
|
|
19628
|
+
"obstacle-restricted-zone": OBSTACLE_RESTRICTED_ZONE,
|
|
19036
19629
|
"pickup-zone": PICKUP_ZONE,
|
|
19037
19630
|
"assault-position": ASSAULT_POSITION,
|
|
19038
19631
|
"attack-position": ATTACK_POSITION,
|
|
@@ -19117,6 +19710,15 @@ const DEFINITIONS = {
|
|
|
19117
19710
|
"antitank-ditch-under-construction": ANTITANK_DITCH_UNDER_CONSTRUCTION,
|
|
19118
19711
|
"antitank-ditch-completed": ANTITANK_DITCH_COMPLETED,
|
|
19119
19712
|
"antitank-wall": ANTITANK_WALL,
|
|
19713
|
+
"wire-obstacle-unspecified": WIRE_OBSTACLE_UNSPECIFIED,
|
|
19714
|
+
"single-fence": SINGLE_FENCE,
|
|
19715
|
+
"double-fence": DOUBLE_FENCE,
|
|
19716
|
+
"double-apron-fence": DOUBLE_APRON_FENCE,
|
|
19717
|
+
"low-wire-fence": LOW_WIRE_FENCE,
|
|
19718
|
+
"high-wire-fence": HIGH_WIRE_FENCE,
|
|
19719
|
+
"single-concertina": SINGLE_CONCERTINA,
|
|
19720
|
+
"double-strand-concertina": DOUBLE_STRAND_CONCERTINA,
|
|
19721
|
+
"triple-strand-concertina": TRIPLE_STRAND_CONCERTINA,
|
|
19120
19722
|
"fortified-line": FORTIFIED_LINE,
|
|
19121
19723
|
"fortified-area": FORTIFIED_AREA,
|
|
19122
19724
|
"frontal-attack": FRONTAL_ATTACK,
|
|
@@ -19154,18 +19756,27 @@ const DEFINITIONS = {
|
|
|
19154
19756
|
};
|
|
19155
19757
|
/** Insertion-ordered list of every control-measure id. */
|
|
19156
19758
|
const CONTROL_MEASURE_IDS = Object.keys(DEFINITIONS);
|
|
19157
|
-
/**
|
|
19158
|
-
|
|
19159
|
-
|
|
19160
|
-
|
|
19161
|
-
|
|
19162
|
-
|
|
19163
|
-
|
|
19759
|
+
/** The shared label dimension materialized for capture-enabled definitions. */
|
|
19760
|
+
const LABEL_SIZE_PAIR = {
|
|
19761
|
+
id: "label",
|
|
19762
|
+
label: "Label size",
|
|
19763
|
+
pixels: "labelSizePixels",
|
|
19764
|
+
meters: "labelSize",
|
|
19765
|
+
defaultUnit: "px",
|
|
19766
|
+
defaultValue: 14,
|
|
19767
|
+
rendering: "text",
|
|
19768
|
+
captureOnDraw: true
|
|
19769
|
+
};
|
|
19770
|
+
/** Resolve definition-owned metadata and the shared label-capture capability. */
|
|
19771
|
+
function resolveMetadata(definition) {
|
|
19772
|
+
const sizePairs = [...definition.metadata.sizePairs ?? [], ...definition.metadata.capturesLabelSize ? [LABEL_SIZE_PAIR] : []];
|
|
19773
|
+
return {
|
|
19164
19774
|
...definition.metadata,
|
|
19165
|
-
rule: definition.rule
|
|
19166
|
-
|
|
19775
|
+
...definition.rule ? { rule: definition.rule } : {},
|
|
19776
|
+
sizePairs
|
|
19777
|
+
};
|
|
19167
19778
|
}
|
|
19168
|
-
const CONTROL_MEASURE_METADATA = Object.fromEntries(Object.entries(DEFINITIONS).map(([id, definition]) => [id,
|
|
19779
|
+
const CONTROL_MEASURE_METADATA = Object.fromEntries(Object.entries(DEFINITIONS).map(([id, definition]) => [id, resolveMetadata(definition)]));
|
|
19169
19780
|
const CONTROL_MEASURE_METADATA_LIST = Object.values(CONTROL_MEASURE_METADATA);
|
|
19170
19781
|
const CONTROL_MEASURE_METADATA_BY_VALUE = CONTROL_MEASURE_METADATA_LIST.reduce((acc, metadata) => {
|
|
19171
19782
|
acc[metadata.value] = metadata;
|
|
@@ -19538,4 +20149,4 @@ function assertNever(value) {
|
|
|
19538
20149
|
throw new Error(`Unhandled control measure kind: ${String(value)}`);
|
|
19539
20150
|
}
|
|
19540
20151
|
//#endregion
|
|
19541
|
-
export { DEFAULT_PHASE_LINE_OPTIONS as $, project as $n, DEFAULT_DIRECTION_OF_SUPPORTING_ATTACK_OPTIONS as $t, DEFAULT_SECURE_OPTIONS as A, turnDrawRule as An, DEFAULT_GENERIC_CIRCLE_OPTIONS as At, DEFAULT_FORTIFIED_LINE_OPTIONS as B, occupyDrawRule as Bn, DEFAULT_BLOCK_ARROW_OPTIONS as Bt, DEFAULT_LANDING_ZONE_OPTIONS as C, computeInitialWidthPoint as Cn, RADAR_SEARCH_DOCTRINE_FILL_COLOR as Ct, DEFAULT_WITHDRAW_OPTIONS as D, line26DrawRule as Dn, DEFAULT_GENERIC_RECTANGLE_OPTIONS as Dt, DEFAULT_WITHDRAW_UNDER_PRESSURE_OPTIONS as E, line27DrawRule as En, DEFAULT_GENERIC_SECTOR_OPTIONS as Et, DEFAULT_PENETRATE_OPTIONS as F, sectorDrawRule as Fn, DEFAULT_BLOCK_MISSION_TASK_OPTIONS as Ft, DEFAULT_LIMIT_OF_ADVANCE_OPTIONS as G, area27DrawRule as Gn, DEFAULT_ATTACK_BY_FIRE_OPTIONS as Gt, PROBABLE_LINE_OF_DEPLOYMENT_DASH as H, blockDrawRule as Hn, DEFAULT_CONTAIN_OPTIONS as Ht, DEFAULT_OCCUPY_OPTIONS as I, staticPointDrawRule as In, DEFAULT_GENERIC_C2_LINE_OPTIONS as It, DEFAULT_FORWARD_EDGE_OF_BATTLE_AREA_OPTIONS as J, getMidpointPerpendicularSignedDistance as Jn, DEFAULT_ASSEMBLY_AREA_OPTIONS as Jt, DEFAULT_BATTLE_HANDOVER_LINE_OPTIONS as K, computeDefaultMidpointPerpendicularPoint as Kn, DEFAULT_ANTITANK_WALL_OPTIONS as Kt, DEFAULT_MOVEMENT_TO_CONTACT_OPTIONS as L, point12DrawRule as Ln, DEFAULT_ENGINEER_WORK_LINE_OPTIONS as Lt, DEFAULT_RETIRE_OPTIONS as M, ambushDrawRule as Mn, DEFAULT_CANALIZE_OPTIONS as Mt, DEFAULT_RELIEF_IN_PLACE_OPTIONS as N, attackByFireDrawRule as Nn, DEFAULT_BYPASS_OPTIONS as Nt, DEFAULT_EVACUATE_OPTIONS as O, line24DrawRule as On, DEFAULT_GENERIC_POLYGON_OPTIONS as Ot, DEFAULT_REARWARD_PASSAGE_OF_LINES_OPTIONS as P, dynamicPointDrawRule as Pn, DEFAULT_BREACH_OPTIONS as Pt, DEFAULT_BRIDGEHEAD_LINE_OPTIONS as Q, haversineDistance as Qn, DEFAULT_AREA_DEFENSE_OPTIONS as Qt, DEFAULT_FRONTAL_ATTACK_OPTIONS as R, secureDrawRule as Rn, DEFAULT_LIGHT_LINE_OPTIONS as Rt, DEFAULT_MAIN_ATTACK_OPTIONS as S, calculateMetrics as Sn, DEFAULT_RADAR_SEARCH_DOCTRINE_OPTIONS as St, DEFAULT_TURN_OPTIONS as T, polyline1DrawRule as Tn, DEFAULT_GENERIC_TEXT_OPTIONS as Tt, DEFAULT_LINE_OF_DEPARTURE_CONTACT_OPTIONS as U, centerRadiusDrawRule as Un, DEFAULT_BATTLE_POSITION_OPTIONS as Ut, DEFAULT_PROBABLE_LINE_OF_DEPLOYMENT_OPTIONS as V, disruptDrawRule as Vn, DEFAULT_BLOCK_OPTIONS as Vt, DEFAULT_LINE_OF_DEPARTURE_OPTIONS as W, containDrawRule as Wn, DEFAULT_ATTACK_HELICOPTER_OPTIONS as Wt, DEFAULT_HOLDING_LINE_OPTIONS as X, snapToMidpointPerpendicular as Xn, DEFAULT_MOBILE_DEFENSE_OPTIONS as Xt, DEFAULT_RELEASE_LINE_OPTIONS as Y, pointOnMidpointPerpendicularAxis as Yn, DEFAULT_AREA_OF_OPERATIONS_OPTIONS as Yt, DEFAULT_INFILTRATION_LANE_OPTIONS as Z, createBaselineFrame as Zn, DEFAULT_ENGAGEMENT_AREA_OPTIONS as Zt, DEFAULT_PICKUP_ZONE_OPTIONS as _, DEFAULT_STROKE_DASH_CSS_PIXELS as _n, DEFAULT_SUPPORTING_ATTACK_OPTIONS as _t, DEFINITIONS as a, resolveAmplifierPlacement as an, DEFAULT_DISRUPT_OPTIONS as at, DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS as b, rectangleDrawRule as bn, DEFAULT_ISOLATE_OPTIONS as bt, getDefaultOptions as c, DEFAULT_DESTROY_OPTIONS as cn, createFollowAndAssume as ct, DEFAULT_SUPPORT_BY_FIRE_OPTIONS as d, DEFAULT_DEFEAT_OPTIONS as dn, DEFAULT_DEMONSTRATE_OPTIONS as dt, DEFAULT_DIRECTION_OF_MAIN_ATTACK_OPTIONS as en, sphericalBearing as er, DEFAULT_FLOT_OPTIONS as et, DEFAULT_RETAIN_OPTIONS as f, DEFAULT_LABEL_HEIGHT_CSS_PIXELS as fn, DEFAULT_DELAY_OPTIONS as ft, DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS as g, DEFAULT_PORTRAYAL as gn, DEFAULT_COUNTERATTACK_OPTIONS as gt, SECONDARY_DIRECTION_OF_FIRE_DASH as h, DEFAULT_LINE_JOIN as hn, DEFAULT_COUNTERATTACK_BY_FIRE_OPTIONS as ht, CONTROL_MEASURE_METADATA as i, normalizeTextAmplifiers as in,
|
|
20152
|
+
export { DEFAULT_PHASE_LINE_OPTIONS as $, project as $n, DEFAULT_DIRECTION_OF_SUPPORTING_ATTACK_OPTIONS as $t, DEFAULT_SECURE_OPTIONS as A, turnDrawRule as An, DEFAULT_GENERIC_CIRCLE_OPTIONS as At, DEFAULT_FORTIFIED_LINE_OPTIONS as B, occupyDrawRule as Bn, DEFAULT_BLOCK_ARROW_OPTIONS as Bt, DEFAULT_LANDING_ZONE_OPTIONS as C, computeInitialWidthPoint as Cn, RADAR_SEARCH_DOCTRINE_FILL_COLOR as Ct, DEFAULT_WITHDRAW_OPTIONS as D, line26DrawRule as Dn, DEFAULT_GENERIC_RECTANGLE_OPTIONS as Dt, DEFAULT_WITHDRAW_UNDER_PRESSURE_OPTIONS as E, line27DrawRule as En, DEFAULT_GENERIC_SECTOR_OPTIONS as Et, DEFAULT_PENETRATE_OPTIONS as F, sectorDrawRule as Fn, DEFAULT_BLOCK_MISSION_TASK_OPTIONS as Ft, DEFAULT_LIMIT_OF_ADVANCE_OPTIONS as G, area27DrawRule as Gn, DEFAULT_ATTACK_BY_FIRE_OPTIONS as Gt, PROBABLE_LINE_OF_DEPLOYMENT_DASH as H, blockDrawRule as Hn, DEFAULT_CONTAIN_OPTIONS as Ht, DEFAULT_OCCUPY_OPTIONS as I, staticPointDrawRule as In, DEFAULT_GENERIC_C2_LINE_OPTIONS as It, DEFAULT_FORWARD_EDGE_OF_BATTLE_AREA_OPTIONS as J, getMidpointPerpendicularSignedDistance as Jn, DEFAULT_ASSEMBLY_AREA_OPTIONS as Jt, DEFAULT_BATTLE_HANDOVER_LINE_OPTIONS as K, computeDefaultMidpointPerpendicularPoint as Kn, DEFAULT_ANTITANK_WALL_OPTIONS as Kt, DEFAULT_MOVEMENT_TO_CONTACT_OPTIONS as L, point12DrawRule as Ln, DEFAULT_ENGINEER_WORK_LINE_OPTIONS as Lt, DEFAULT_RETIRE_OPTIONS as M, ambushDrawRule as Mn, DEFAULT_CANALIZE_OPTIONS as Mt, DEFAULT_RELIEF_IN_PLACE_OPTIONS as N, attackByFireDrawRule as Nn, DEFAULT_BYPASS_OPTIONS as Nt, DEFAULT_EVACUATE_OPTIONS as O, line24DrawRule as On, DEFAULT_GENERIC_POLYGON_OPTIONS as Ot, DEFAULT_REARWARD_PASSAGE_OF_LINES_OPTIONS as P, dynamicPointDrawRule as Pn, DEFAULT_BREACH_OPTIONS as Pt, DEFAULT_BRIDGEHEAD_LINE_OPTIONS as Q, haversineDistance as Qn, DEFAULT_AREA_DEFENSE_OPTIONS as Qt, DEFAULT_FRONTAL_ATTACK_OPTIONS as R, secureDrawRule as Rn, DEFAULT_LIGHT_LINE_OPTIONS as Rt, DEFAULT_MAIN_ATTACK_OPTIONS as S, calculateMetrics as Sn, DEFAULT_RADAR_SEARCH_DOCTRINE_OPTIONS as St, DEFAULT_TURN_OPTIONS as T, polyline1DrawRule as Tn, DEFAULT_GENERIC_TEXT_OPTIONS as Tt, DEFAULT_LINE_OF_DEPARTURE_CONTACT_OPTIONS as U, centerRadiusDrawRule as Un, DEFAULT_BATTLE_POSITION_OPTIONS as Ut, DEFAULT_PROBABLE_LINE_OF_DEPLOYMENT_OPTIONS as V, disruptDrawRule as Vn, DEFAULT_BLOCK_OPTIONS as Vt, DEFAULT_LINE_OF_DEPARTURE_OPTIONS as W, containDrawRule as Wn, DEFAULT_ATTACK_HELICOPTER_OPTIONS as Wt, DEFAULT_HOLDING_LINE_OPTIONS as X, snapToMidpointPerpendicular as Xn, DEFAULT_MOBILE_DEFENSE_OPTIONS as Xt, DEFAULT_RELEASE_LINE_OPTIONS as Y, pointOnMidpointPerpendicularAxis as Yn, DEFAULT_AREA_OF_OPERATIONS_OPTIONS as Yt, DEFAULT_INFILTRATION_LANE_OPTIONS as Z, createBaselineFrame as Zn, DEFAULT_ENGAGEMENT_AREA_OPTIONS as Zt, DEFAULT_PICKUP_ZONE_OPTIONS as _, DEFAULT_STROKE_DASH_CSS_PIXELS as _n, DEFAULT_SUPPORTING_ATTACK_OPTIONS as _t, DEFINITIONS as a, resolveAmplifierPlacement as an, roundToFixed as ar, DEFAULT_DISRUPT_OPTIONS as at, DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS as b, rectangleDrawRule as bn, DEFAULT_ISOLATE_OPTIONS as bt, getDefaultOptions as c, DEFAULT_DESTROY_OPTIONS as cn, createFollowAndAssume as ct, DEFAULT_SUPPORT_BY_FIRE_OPTIONS as d, DEFAULT_DEFEAT_OPTIONS as dn, DEFAULT_DEMONSTRATE_OPTIONS as dt, DEFAULT_DIRECTION_OF_MAIN_ATTACK_OPTIONS as en, sphericalBearing as er, DEFAULT_FLOT_OPTIONS as et, DEFAULT_RETAIN_OPTIONS as f, DEFAULT_LABEL_HEIGHT_CSS_PIXELS as fn, DEFAULT_DELAY_OPTIONS as ft, DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS as g, DEFAULT_PORTRAYAL as gn, DEFAULT_COUNTERATTACK_OPTIONS as gt, SECONDARY_DIRECTION_OF_FIRE_DASH as h, DEFAULT_LINE_JOIN as hn, DEFAULT_COUNTERATTACK_BY_FIRE_OPTIONS as ht, CONTROL_MEASURE_METADATA as i, normalizeTextAmplifiers as in, isFiniteNumber as ir, DEFAULT_ENCIRCLEMENT_OPTIONS as it, DEFAULT_SCREEN_OPTIONS as j, line1DrawRule as jn, DEFAULT_CLASSIC_ARROW_OPTIONS as jt, DEFAULT_SEIZE_OPTIONS as k, line23DrawRule as kn, DEFAULT_GENERIC_LINE_OPTIONS as kt, listControlMeasureMetadata as l, DEFAULT_NEUTRALIZE_OPTIONS as ln, DEFAULT_DISRUPT_MISSION_TASK_OPTIONS as lt, DEFAULT_SECONDARY_DIRECTION_OF_FIRE_OPTIONS as m, DEFAULT_LINE_CAP as mn, DEFAULT_TACTICAL_ARROW_OPTIONS as mt, resolveStyleHints as n, TEXT_AMPLIFIER_FIELDS as nn, EPSILON as nr, DEFAULT_FIX_OPTIONS as nt, getControlMeasureMetadata as o, DEFAULT_AMBUSH_OPTIONS as on, DEFAULT_GUARD_OPTIONS as ot, DEFAULT_STRONG_POINT_OPTIONS as p, DEFAULT_LABEL_SIZE_CLAMP_CSS_PIXELS as pn, DEFAULT_COVER_OPTIONS as pt, DEFAULT_HANDOVER_LINE_OPTIONS as q, createMidpointPerpendicularDrawRule as qn, DEFAULT_ANTITANK_DITCH_OPTIONS as qt, CONTROL_MEASURE_IDS as r, canonicalTextAmplifierKey as rn, getMetersPerPixel as rr, DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS as rt, getControlMeasureMetadataByValue as s, DEFAULT_AIRBORNE_ATTACK_OPTIONS as sn, createFollowAndSupport as st, renderControlMeasure as t, DEFAULT_DIRECTION_OF_ATTACK_AVIATION_OPTIONS as tn, unproject as tr, DEFAULT_FIX_MISSION_TASK_OPTIONS as tt, DEFAULT_TURNING_MOVEMENT_OPTIONS as u, DEFAULT_SUPPRESS_OPTIONS as un, DEFAULT_DISENGAGE_OPTIONS as ut, DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS as v, DEFAULT_STROKE_WIDTH_CSS_PIXELS as vn, DEFAULT_CORDON_AND_SEARCH_OPTIONS as vt, DEFAULT_JOINT_TACTICAL_ACTION_AREA_OPTIONS as w, supportByFireDrawRule as wn, RADAR_SEARCH_DOCTRINE_STROKE_COLOR as wt, DEFAULT_MINEFIELD_OPTIONS as x, axis1DrawRule as xn, DEFAULT_CLEAR_OPTIONS as xt, DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS as y, DEFAULT_SYMBOL_COLOR as yn, DEFAULT_CORDON_AND_KNOCK_OPTIONS as yt, DEFAULT_FORTIFIED_AREA_OPTIONS as z, penetrateDrawRule as zn, DEFAULT_BOUNDARY_OPTIONS as zt };
|