@orbat-mapper/control-measures 0.2.0-alpha.4 → 0.2.0-alpha.6
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/dist/{index-BJYbQlzo.d.mts → index-DUGzYzPy.d.mts} +114 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +17 -2
- package/dist/preview/index.d.mts +1 -1
- package/dist/preview/index.mjs +1 -1
- package/dist/{renderControlMeasure-CONa8M6M.mjs → renderControlMeasure-D5NKuws0.mjs} +426 -37
- package/package.json +1 -1
|
@@ -23,6 +23,19 @@ interface ControlMeasureDrawRule {
|
|
|
23
23
|
* `minimumUserPoints` (no early preview).
|
|
24
24
|
*/
|
|
25
25
|
readonly minimumPreviewPoints?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Opt a fixed-length draw into the standard dashed interaction guide. Fixed
|
|
28
|
+
* shapes suppress guides by default because their generator preview is
|
|
29
|
+
* normally sufficient. Use this when the guide communicates an incomplete
|
|
30
|
+
* construction state, such as Rectangle's P1-P2 baseline.
|
|
31
|
+
*/
|
|
32
|
+
readonly showGuide?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Convert raw draw points into the spine rendered by the interaction guide.
|
|
35
|
+
* Defaults to the raw points. A rule may return the first point again at the
|
|
36
|
+
* end when it needs to provide its own closed guide geometry.
|
|
37
|
+
*/
|
|
38
|
+
guidePoints?(points: readonly Position[]): Position[];
|
|
26
39
|
/**
|
|
27
40
|
* Number of trailing slots in the canonical control-point array that are
|
|
28
41
|
* NOT user-clicked spine vertices. For Axis1, this is 1 (the width handle
|
|
@@ -36,6 +49,12 @@ interface ControlMeasureDrawRule {
|
|
|
36
49
|
* Defaults to 0 (the entire array is user-clicked spine). See ADR-0008.
|
|
37
50
|
*/
|
|
38
51
|
readonly trailingFixedSlots?: number;
|
|
52
|
+
/**
|
|
53
|
+
* The user-spine points form a closed ring even though the first point is not
|
|
54
|
+
* duplicated at the end. TacticalDraw uses this to treat the last→first edge
|
|
55
|
+
* like every other edge for completion and midpoint insertion.
|
|
56
|
+
*/
|
|
57
|
+
readonly closedRing?: boolean;
|
|
39
58
|
derive(points: readonly Position[]): Position[];
|
|
40
59
|
transform(event: AnchorTransformEvent): Position[];
|
|
41
60
|
}
|
|
@@ -43,7 +62,7 @@ interface ControlMeasureDrawRule {
|
|
|
43
62
|
//#region src/metadata.d.ts
|
|
44
63
|
type ControlMeasureGeometryType = Geometry["type"];
|
|
45
64
|
type ControlMeasureGeometry = "point" | "line" | "area";
|
|
46
|
-
declare const DRAW_RULE_IDS: readonly ["Area1", "Area7", "Area8", "Area11", "Area12", "Area15", "Area21", "Axis1", "Line1", "Line3", "Line9", "Line10", "Line23", "Line24", "Line29", "Point12"];
|
|
65
|
+
declare const DRAW_RULE_IDS: readonly ["Area1", "Area7", "Area8", "Area11", "Area12", "Area15", "Area21", "Axis1", "Line1", "Line3", "Line9", "Line10", "Line23", "Line24", "Line29", "Point12", "Rectangle"];
|
|
47
66
|
type DrawRuleId = (typeof DRAW_RULE_IDS)[number];
|
|
48
67
|
interface BaseParamDescriptor {
|
|
49
68
|
key: string;
|
|
@@ -156,6 +175,18 @@ interface ControlMeasureDefinition<Id extends string, G extends ControlMeasureGe
|
|
|
156
175
|
* ADR-0025.
|
|
157
176
|
*/
|
|
158
177
|
previewSample?: PreviewSample<NonNullable<Parameters<G>[1]>>;
|
|
178
|
+
/**
|
|
179
|
+
* Pins orientation-derived defaults — options whose default value depends on
|
|
180
|
+
* the shape's current screen orientation (e.g. Battle Position's echelon
|
|
181
|
+
* anchor, which defaults to the bottom edge) — to their current concrete
|
|
182
|
+
* values. Returns an options patch to merge onto the working options, or
|
|
183
|
+
* `undefined` when there is nothing to freeze (already frozen, or nothing
|
|
184
|
+
* visible to pin). Called by edit hosts when a rotate gesture starts, so a
|
|
185
|
+
* subsequent rigid rotation of the control points preserves the rendered
|
|
186
|
+
* appearance instead of an orientation-relative default silently re-deriving
|
|
187
|
+
* against the new orientation. See ADR-0023.
|
|
188
|
+
*/
|
|
189
|
+
freezeOrientation?: (controlPoints: Position[], options: NonNullable<Parameters<G>[1]>) => Partial<NonNullable<Parameters<G>[1]>> | undefined;
|
|
159
190
|
}
|
|
160
191
|
/**
|
|
161
192
|
* A measure's representative preview input. Shared between the typed
|
|
@@ -309,6 +340,25 @@ interface BattlePositionOptions {
|
|
|
309
340
|
* @default 0
|
|
310
341
|
*/
|
|
311
342
|
echelonPosition?: number;
|
|
343
|
+
/**
|
|
344
|
+
* Absolute anchor for the echelon glyph, as a fraction of the total
|
|
345
|
+
* perimeter measured from the ring seam (the ring's first vertex), wrapped
|
|
346
|
+
* into `[0, 1)`. When omitted, the anchor is "auto": the bottom edge's
|
|
347
|
+
* midpoint (the side opposite the front), recomputed from the current
|
|
348
|
+
* geometry on every render — the long-standing default behavior.
|
|
349
|
+
* `echelonPosition` still applies on top of this anchor as a signed offset,
|
|
350
|
+
* exactly as it does against the auto anchor.
|
|
351
|
+
*
|
|
352
|
+
* Edit controllers freeze this from "auto" to a concrete fraction the
|
|
353
|
+
* moment a rotate gesture starts (see `freezeEchelonAnchor` /
|
|
354
|
+
* `freezeOrientationOptions`): the transform box rotates only the control
|
|
355
|
+
* points and re-renders, so without a pinned anchor the "bottom edge" would
|
|
356
|
+
* keep re-deriving against the rotated geometry and the glyph would jump to
|
|
357
|
+
* a different edge each time a new edge becomes lowest. Freezing the anchor
|
|
358
|
+
* first makes the rotation rigid — the glyph turns with the shape instead.
|
|
359
|
+
* See ADR-0023.
|
|
360
|
+
*/
|
|
361
|
+
echelonAnchor?: number;
|
|
312
362
|
/**
|
|
313
363
|
* Meters-per-pixel at the current zoom/latitude. Stamped by the host when the
|
|
314
364
|
* measure is screen-anchored; required to resolve `echelonSizePixels`.
|
|
@@ -613,6 +663,47 @@ declare function createBlockArrow(coordinates: Position[], options?: BlockArrowO
|
|
|
613
663
|
fill: boolean;
|
|
614
664
|
}>;
|
|
615
665
|
//#endregion
|
|
666
|
+
//#region src/generators/cm99-generic-graphics/params.d.ts
|
|
667
|
+
interface SmoothPathOptions {
|
|
668
|
+
/** Curve the rendered path through the unchanged control points. */
|
|
669
|
+
smooth?: boolean;
|
|
670
|
+
/** Number of samples per segment when smoothing is enabled. */
|
|
671
|
+
smoothResolution?: number;
|
|
672
|
+
}
|
|
673
|
+
interface FilledAreaOptions {
|
|
674
|
+
/** Fill the polygon interior; false renders only its outline. */
|
|
675
|
+
filled?: boolean;
|
|
676
|
+
}
|
|
677
|
+
//#endregion
|
|
678
|
+
//#region src/generators/cm99-generic-graphics/line.d.ts
|
|
679
|
+
type GenericLineOptions = SmoothPathOptions;
|
|
680
|
+
declare const DEFAULT_GENERIC_LINE_OPTIONS: Required<GenericLineOptions>;
|
|
681
|
+
declare function createGenericLine(coordinates: Position[], options?: GenericLineOptions): FeatureCollection<LineString>;
|
|
682
|
+
//#endregion
|
|
683
|
+
//#region src/generators/cm99-generic-graphics/polygon.d.ts
|
|
684
|
+
interface GenericPolygonOptions extends SmoothPathOptions, FilledAreaOptions {}
|
|
685
|
+
declare const DEFAULT_GENERIC_POLYGON_OPTIONS: Required<GenericPolygonOptions>;
|
|
686
|
+
declare function createGenericPolygon(coordinates: Position[], options?: GenericPolygonOptions): FeatureCollection<Polygon, {
|
|
687
|
+
part: string;
|
|
688
|
+
fill: boolean;
|
|
689
|
+
}>;
|
|
690
|
+
//#endregion
|
|
691
|
+
//#region src/generators/cm99-generic-graphics/rectangle.d.ts
|
|
692
|
+
type GenericRectangleOptions = FilledAreaOptions;
|
|
693
|
+
declare const DEFAULT_GENERIC_RECTANGLE_OPTIONS: Required<GenericRectangleOptions>;
|
|
694
|
+
declare function createGenericRectangle(coordinates: Position[], options?: GenericRectangleOptions): FeatureCollection<Polygon, {
|
|
695
|
+
part: string;
|
|
696
|
+
fill: boolean;
|
|
697
|
+
}>;
|
|
698
|
+
//#endregion
|
|
699
|
+
//#region src/generators/cm99-generic-graphics/circle.d.ts
|
|
700
|
+
type GenericCircleOptions = FilledAreaOptions;
|
|
701
|
+
declare const DEFAULT_GENERIC_CIRCLE_OPTIONS: Required<GenericCircleOptions>;
|
|
702
|
+
declare function createGenericCircle(coordinates: Position[], options?: GenericCircleOptions): FeatureCollection<Polygon, {
|
|
703
|
+
part: string;
|
|
704
|
+
fill: boolean;
|
|
705
|
+
}>;
|
|
706
|
+
//#endregion
|
|
616
707
|
//#region src/generators/cm15-maneuver-areas/airborneAttack.d.ts
|
|
617
708
|
type AirborneAttackOptions = AttackOptions;
|
|
618
709
|
declare const DEFAULT_AIRBORNE_ATTACK_OPTIONS: Required<AirborneAttackOptions>;
|
|
@@ -1265,6 +1356,10 @@ declare const DEFINITIONS: {
|
|
|
1265
1356
|
"supporting-attack": ControlMeasureDefinition<"supporting-attack", typeof createSupportingAttack>;
|
|
1266
1357
|
"classic-arrow": ControlMeasureDefinition<"classic-arrow", typeof createClassicArrow>;
|
|
1267
1358
|
"block-arrow": ControlMeasureDefinition<"block-arrow", typeof createBlockArrow>;
|
|
1359
|
+
line: ControlMeasureDefinition<"line", typeof createGenericLine>;
|
|
1360
|
+
polygon: ControlMeasureDefinition<"polygon", typeof createGenericPolygon>;
|
|
1361
|
+
rectangle: ControlMeasureDefinition<"rectangle", typeof createGenericRectangle>;
|
|
1362
|
+
circle: ControlMeasureDefinition<"circle", typeof createGenericCircle>;
|
|
1268
1363
|
"airborne-attack": ControlMeasureDefinition<"airborne-attack", typeof createAirborneAttack>;
|
|
1269
1364
|
"attack-helicopter": ControlMeasureDefinition<"attack-helicopter", typeof createAttackHelicopter>;
|
|
1270
1365
|
"support-by-fire": ControlMeasureDefinition<"support-by-fire", typeof createSupportByFire>;
|
|
@@ -1454,6 +1549,17 @@ interface RenderOptions {
|
|
|
1454
1549
|
*/
|
|
1455
1550
|
declare function renderControlMeasure<K extends ControlMeasureKind>(cm: ControlMeasure<K>, opts?: RenderOptions): ControlMeasureRender;
|
|
1456
1551
|
//#endregion
|
|
1552
|
+
//#region src/freeze-orientation.d.ts
|
|
1553
|
+
/**
|
|
1554
|
+
* Dispatches to a measure kind's `freezeOrientation` hook (see
|
|
1555
|
+
* {@link import("./define").ControlMeasureDefinition.freezeOrientation}),
|
|
1556
|
+
* pinning orientation-derived option defaults to their current concrete
|
|
1557
|
+
* values ahead of a rigid rotation of `controlPoints`. Returns `undefined`
|
|
1558
|
+
* when the kind declares no hook, or when the hook itself finds nothing to
|
|
1559
|
+
* freeze. Edit hosts call this when a rotate gesture starts (ADR-0023).
|
|
1560
|
+
*/
|
|
1561
|
+
declare function freezeOrientationOptions<K extends ControlMeasureKind>(kind: K, controlPoints: Position[], options: OptionsByKind[K] | undefined): Partial<OptionsByKind[K]> | undefined;
|
|
1562
|
+
//#endregion
|
|
1457
1563
|
//#region src/styleResolver.d.ts
|
|
1458
1564
|
/**
|
|
1459
1565
|
* Three-layer style precedence for `renderControlMeasure`.
|
|
@@ -1599,6 +1705,9 @@ declare const blockDrawRule: ControlMeasureDrawRule;
|
|
|
1599
1705
|
*/
|
|
1600
1706
|
declare const disruptDrawRule: ControlMeasureDrawRule;
|
|
1601
1707
|
//#endregion
|
|
1708
|
+
//#region src/draw-rules/area15.d.ts
|
|
1709
|
+
declare const centerRadiusDrawRule: ControlMeasureDrawRule;
|
|
1710
|
+
//#endregion
|
|
1602
1711
|
//#region src/draw-rules/point12.d.ts
|
|
1603
1712
|
/**
|
|
1604
1713
|
* Point12 anchor draw rule for the obstacle-bypass family.
|
|
@@ -1669,6 +1778,9 @@ declare const supportByFireDrawRule: ControlMeasureDrawRule;
|
|
|
1669
1778
|
//#region src/draw-rules/axis1.d.ts
|
|
1670
1779
|
declare const axis1DrawRule: ControlMeasureDrawRule;
|
|
1671
1780
|
//#endregion
|
|
1781
|
+
//#region src/draw-rules/rectangle.d.ts
|
|
1782
|
+
declare const rectangleDrawRule: ControlMeasureDrawRule;
|
|
1783
|
+
//#endregion
|
|
1672
1784
|
//#region src/generators/cm14-maneuver-lines/ambush.d.ts
|
|
1673
1785
|
/**
|
|
1674
1786
|
* Configuration options for the Ambush tactical symbol.
|
|
@@ -1710,4 +1822,4 @@ interface TacticalArrowOptions {
|
|
|
1710
1822
|
*/
|
|
1711
1823
|
declare const DEFAULT_TACTICAL_ARROW_OPTIONS: Required<TacticalArrowOptions>;
|
|
1712
1824
|
//#endregion
|
|
1713
|
-
export {
|
|
1825
|
+
export { getControlMeasureMetadata as $, DEFAULT_GENERIC_LINE_OPTIONS as $t, getMetersPerPixel as A, DEFAULT_CANALIZE_OPTIONS as At, ControlMeasureSnapshot as B, DEFAULT_ATTACK_BY_FIRE_OPTIONS as Bt, snapToMidpointPerpendicular as C, ControlMeasureDrawRule as Cn, AntitankDitchOptions as Ct, BaselineFrameOrigin as D, ClearOptions as Dt, BaselineFrameOptions as E, DelayOptions as Et, resolveStyleHints as F, BlockMissionTaskOptions as Ft, cloneControlMeasure as G, AirborneAttackOptions as Gt, StyleHints as H, SupportByFireOptions as Ht, freezeOrientationOptions as I, DEFAULT_BLOCK_MISSION_TASK_OPTIONS as It, CONTROL_MEASURE_IDS as J, GenericCircleOptions as Jt, isKind as K, DEFAULT_AIRBORNE_ATTACK_OPTIONS as Kt, RenderOptions as L, DEFAULT_FLOT_OPTIONS as Lt, SimpleStyleProps as M, DEFAULT_BYPASS_OPTIONS as Mt, SimpleStyleRender as N, BreachOptions as Nt, createBaselineFrame as O, DEFAULT_CLEAR_OPTIONS as Ot, toSimpleStyle as P, DEFAULT_BREACH_OPTIONS as Pt, OptionsByKind as Q, GenericPolygonOptions as Qt, renderControlMeasure as R, FLOTOptions as Rt, pointOnMidpointPerpendicularAxis as S, AnchorTransformEvent as Sn, DEFAULT_ANTITANK_WALL_OPTIONS as St, BaselineFrameNormal as T, DEFAULT_DELAY_OPTIONS as Tt, controlMeasureIdFromFeature as U, AttackHelicopterOptions as Ut, FeaturePartProps as V, DEFAULT_SUPPORT_BY_FIRE_OPTIONS as Vt, ControlMeasure as W, DEFAULT_ATTACK_HELICOPTER_OPTIONS as Wt, ControlMeasureId as X, GenericRectangleOptions as Xt, CONTROL_MEASURE_METADATA as Y, DEFAULT_GENERIC_RECTANGLE_OPTIONS as Yt, ControlMeasureKind as Z, DEFAULT_GENERIC_POLYGON_OPTIONS as Zt, blockDrawRule as _, StrongPointOptions as _n, DEFAULT_FORTIFIED_AREA_OPTIONS as _t, rectangleDrawRule as a, calculateMetrics as an, DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS as at, createMidpointPerpendicularDrawRule as b, ControlMeasureMetadata as bn, FortifiedLineOptions as bt, line24DrawRule as c, project as cn, ObstacleBypassEasyOptions as ct, line1DrawRule as d, EncirclementOptions as dn, DEFAULT_FIX_OPTIONS as dt, GenericLineOptions as en, getControlMeasureMetadataByValue as et, ambushDrawRule as f, DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS as fn, FixOptions as ft, disruptDrawRule as g, DEFAULT_STRONG_POINT_OPTIONS as gn, DEFAULT_BLOCK_OPTIONS as gt, centerRadiusDrawRule as h, PrincipalDirectionOfFireOptions as hn, BlockOptions as ht, DEFAULT_AMBUSH_OPTIONS as i, MainAttackOptions as in, ObstacleBypassImpossibleOptions as it, roundToFixed as j, BypassOptions as jt, EPSILON as k, CanalizeOptions as kt, line23DrawRule as l, unproject as ln, DEFAULT_TURN_OPTIONS as lt, point12DrawRule as m, DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS as mn, DisruptOptions as mt, TacticalArrowOptions as n, SupportingAttackOptions as nn, listControlMeasureMetadata as nt, axis1DrawRule as o, computeInitialWidthPoint as on, ObstacleBypassDifficultOptions as ot, attackByFireDrawRule as p, FinalProtectiveFireOptions as pn, DEFAULT_DISRUPT_OPTIONS as pt, ControlMeasureStyle as q, DEFAULT_GENERIC_CIRCLE_OPTIONS as qt, AmbushOptions as r, DEFAULT_MAIN_ATTACK_OPTIONS as rn, DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS as rt, supportByFireDrawRule as s, Point2D as sn, DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS as st, DEFAULT_TACTICAL_ARROW_OPTIONS as t, DEFAULT_SUPPORTING_ATTACK_OPTIONS as tn, getDefaultOptions as tt, turnDrawRule as u, DEFAULT_ENCIRCLEMENT_OPTIONS as un, TurnOptions as ut, MidpointPerpendicularDrawRuleOptions as v, ControlMeasureGeometry as vn, FortifiedAreaOptions as vt, BaselineFrame as w, DEFAULT_ANTITANK_DITCH_OPTIONS as wt, getMidpointPerpendicularSignedDistance as x, ParamDescriptor as xn, AntitankWallOptions as xt, computeDefaultMidpointPerpendicularPoint as y, ControlMeasureGeometryType as yn, DEFAULT_FORTIFIED_LINE_OPTIONS as yt, ControlMeasureRender as z, AttackByFireOptions as zt };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
export { type AirborneAttackOptions, type AmbushOptions, type AnchorTransformEvent, type AntitankDitchOptions, type AntitankWallOptions, type AttackByFireOptions, type AttackHelicopterOptions, type BaselineFrame, type BaselineFrameNormal, type BaselineFrameOptions, type BaselineFrameOrigin, type BlockMissionTaskOptions, type BlockOptions, type BreachOptions, type BypassOptions, CONTROL_MEASURE_IDS, CONTROL_MEASURE_METADATA, type CanalizeOptions, type ClearOptions, type ControlMeasure, type ControlMeasureDrawRule, type ControlMeasureGeometry, type ControlMeasureGeometryType, type ControlMeasureId, type ControlMeasureKind, type ControlMeasureMetadata, type ControlMeasureRender, type ControlMeasureSnapshot, type ControlMeasureStyle, DEFAULT_AIRBORNE_ATTACK_OPTIONS, DEFAULT_AMBUSH_OPTIONS, DEFAULT_ANTITANK_DITCH_OPTIONS, DEFAULT_ANTITANK_WALL_OPTIONS, DEFAULT_ATTACK_BY_FIRE_OPTIONS, DEFAULT_ATTACK_HELICOPTER_OPTIONS, DEFAULT_BLOCK_MISSION_TASK_OPTIONS, DEFAULT_BLOCK_OPTIONS, DEFAULT_BREACH_OPTIONS, DEFAULT_BYPASS_OPTIONS, DEFAULT_CANALIZE_OPTIONS, DEFAULT_CLEAR_OPTIONS, DEFAULT_DELAY_OPTIONS, DEFAULT_DISRUPT_OPTIONS, DEFAULT_ENCIRCLEMENT_OPTIONS, DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, DEFAULT_FIX_OPTIONS, DEFAULT_FLOT_OPTIONS, DEFAULT_FORTIFIED_AREA_OPTIONS, DEFAULT_FORTIFIED_LINE_OPTIONS, DEFAULT_MAIN_ATTACK_OPTIONS, DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, DEFAULT_STRONG_POINT_OPTIONS, DEFAULT_SUPPORTING_ATTACK_OPTIONS, DEFAULT_SUPPORT_BY_FIRE_OPTIONS, DEFAULT_TACTICAL_ARROW_OPTIONS, DEFAULT_TURN_OPTIONS, type DelayOptions, type DisruptOptions, EPSILON, type EncirclementOptions, type FLOTOptions, type FeaturePartProps, type FinalProtectiveFireOptions, type FixOptions, type FortifiedAreaOptions, type FortifiedLineOptions, type MainAttackOptions, type MidpointPerpendicularDrawRuleOptions, type ObstacleBypassDifficultOptions, type ObstacleBypassEasyOptions, type ObstacleBypassImpossibleOptions, type OptionsByKind, type ParamDescriptor, type Point2D, type PrincipalDirectionOfFireOptions, type RenderOptions, type SimpleStyleProps, type SimpleStyleRender, type StrongPointOptions, type StyleHints, type SupportByFireOptions, type SupportingAttackOptions, type TacticalArrowOptions, type TurnOptions, ambushDrawRule, attackByFireDrawRule, axis1DrawRule, blockDrawRule, calculateMetrics, cloneControlMeasure, computeDefaultMidpointPerpendicularPoint, computeInitialWidthPoint, controlMeasureIdFromFeature, createBaselineFrame, createMidpointPerpendicularDrawRule, disruptDrawRule, getControlMeasureMetadata, getControlMeasureMetadataByValue, getDefaultOptions, getMetersPerPixel, getMidpointPerpendicularSignedDistance, isKind, line1DrawRule, line23DrawRule, line24DrawRule, listControlMeasureMetadata, point12DrawRule, pointOnMidpointPerpendicularAxis, project, renderControlMeasure, resolveStyleHints, roundToFixed, snapToMidpointPerpendicular, supportByFireDrawRule, toSimpleStyle, turnDrawRule, unproject };
|
|
1
|
+
import { $ as getControlMeasureMetadata, $t as DEFAULT_GENERIC_LINE_OPTIONS, A as getMetersPerPixel, At as DEFAULT_CANALIZE_OPTIONS, B as ControlMeasureSnapshot, Bt as DEFAULT_ATTACK_BY_FIRE_OPTIONS, C as snapToMidpointPerpendicular, Cn as ControlMeasureDrawRule, Ct as AntitankDitchOptions, D as BaselineFrameOrigin, Dt as ClearOptions, E as BaselineFrameOptions, Et as DelayOptions, F as resolveStyleHints, Ft as BlockMissionTaskOptions, G as cloneControlMeasure, Gt as AirborneAttackOptions, H as StyleHints, Ht as SupportByFireOptions, I as freezeOrientationOptions, It as DEFAULT_BLOCK_MISSION_TASK_OPTIONS, J as CONTROL_MEASURE_IDS, Jt as GenericCircleOptions, K as isKind, Kt as DEFAULT_AIRBORNE_ATTACK_OPTIONS, L as RenderOptions, Lt as DEFAULT_FLOT_OPTIONS, M as SimpleStyleProps, Mt as DEFAULT_BYPASS_OPTIONS, N as SimpleStyleRender, Nt as BreachOptions, O as createBaselineFrame, Ot as DEFAULT_CLEAR_OPTIONS, P as toSimpleStyle, Pt as DEFAULT_BREACH_OPTIONS, Q as OptionsByKind, Qt as GenericPolygonOptions, R as renderControlMeasure, Rt as FLOTOptions, S as pointOnMidpointPerpendicularAxis, Sn as AnchorTransformEvent, St as DEFAULT_ANTITANK_WALL_OPTIONS, T as BaselineFrameNormal, Tt as DEFAULT_DELAY_OPTIONS, U as controlMeasureIdFromFeature, Ut as AttackHelicopterOptions, V as FeaturePartProps, Vt as DEFAULT_SUPPORT_BY_FIRE_OPTIONS, W as ControlMeasure, Wt as DEFAULT_ATTACK_HELICOPTER_OPTIONS, X as ControlMeasureId, Xt as GenericRectangleOptions, Y as CONTROL_MEASURE_METADATA, Yt as DEFAULT_GENERIC_RECTANGLE_OPTIONS, Z as ControlMeasureKind, Zt as DEFAULT_GENERIC_POLYGON_OPTIONS, _ as blockDrawRule, _n as StrongPointOptions, _t as DEFAULT_FORTIFIED_AREA_OPTIONS, a as rectangleDrawRule, an as calculateMetrics, at as DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, b as createMidpointPerpendicularDrawRule, bn as ControlMeasureMetadata, bt as FortifiedLineOptions, c as line24DrawRule, cn as project, ct as ObstacleBypassEasyOptions, d as line1DrawRule, dn as EncirclementOptions, dt as DEFAULT_FIX_OPTIONS, en as GenericLineOptions, et as getControlMeasureMetadataByValue, f as ambushDrawRule, fn as DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, ft as FixOptions, g as disruptDrawRule, gn as DEFAULT_STRONG_POINT_OPTIONS, gt as DEFAULT_BLOCK_OPTIONS, h as centerRadiusDrawRule, hn as PrincipalDirectionOfFireOptions, ht as BlockOptions, i as DEFAULT_AMBUSH_OPTIONS, in as MainAttackOptions, it as ObstacleBypassImpossibleOptions, j as roundToFixed, jt as BypassOptions, k as EPSILON, kt as CanalizeOptions, l as line23DrawRule, ln as unproject, lt as DEFAULT_TURN_OPTIONS, m as point12DrawRule, mn as DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, mt as DisruptOptions, n as TacticalArrowOptions, nn as SupportingAttackOptions, nt as listControlMeasureMetadata, o as axis1DrawRule, on as computeInitialWidthPoint, ot as ObstacleBypassDifficultOptions, p as attackByFireDrawRule, pn as FinalProtectiveFireOptions, pt as DEFAULT_DISRUPT_OPTIONS, q as ControlMeasureStyle, qt as DEFAULT_GENERIC_CIRCLE_OPTIONS, r as AmbushOptions, rn as DEFAULT_MAIN_ATTACK_OPTIONS, rt as DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, s as supportByFireDrawRule, sn as Point2D, st as DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, t as DEFAULT_TACTICAL_ARROW_OPTIONS, tn as DEFAULT_SUPPORTING_ATTACK_OPTIONS, tt as getDefaultOptions, u as turnDrawRule, un as DEFAULT_ENCIRCLEMENT_OPTIONS, ut as TurnOptions, v as MidpointPerpendicularDrawRuleOptions, vn as ControlMeasureGeometry, vt as FortifiedAreaOptions, w as BaselineFrame, wt as DEFAULT_ANTITANK_DITCH_OPTIONS, x as getMidpointPerpendicularSignedDistance, xn as ParamDescriptor, xt as AntitankWallOptions, y as computeDefaultMidpointPerpendicularPoint, yn as ControlMeasureGeometryType, yt as DEFAULT_FORTIFIED_LINE_OPTIONS, z as ControlMeasureRender, zt as AttackByFireOptions } from "./index-DUGzYzPy.mjs";
|
|
2
|
+
export { type AirborneAttackOptions, type AmbushOptions, type AnchorTransformEvent, type AntitankDitchOptions, type AntitankWallOptions, type AttackByFireOptions, type AttackHelicopterOptions, type BaselineFrame, type BaselineFrameNormal, type BaselineFrameOptions, type BaselineFrameOrigin, type BlockMissionTaskOptions, type BlockOptions, type BreachOptions, type BypassOptions, CONTROL_MEASURE_IDS, CONTROL_MEASURE_METADATA, type CanalizeOptions, type ClearOptions, type ControlMeasure, type ControlMeasureDrawRule, type ControlMeasureGeometry, type ControlMeasureGeometryType, type ControlMeasureId, type ControlMeasureKind, type ControlMeasureMetadata, type ControlMeasureRender, type ControlMeasureSnapshot, type ControlMeasureStyle, DEFAULT_AIRBORNE_ATTACK_OPTIONS, DEFAULT_AMBUSH_OPTIONS, DEFAULT_ANTITANK_DITCH_OPTIONS, DEFAULT_ANTITANK_WALL_OPTIONS, DEFAULT_ATTACK_BY_FIRE_OPTIONS, DEFAULT_ATTACK_HELICOPTER_OPTIONS, DEFAULT_BLOCK_MISSION_TASK_OPTIONS, DEFAULT_BLOCK_OPTIONS, DEFAULT_BREACH_OPTIONS, DEFAULT_BYPASS_OPTIONS, DEFAULT_CANALIZE_OPTIONS, DEFAULT_CLEAR_OPTIONS, DEFAULT_DELAY_OPTIONS, DEFAULT_DISRUPT_OPTIONS, DEFAULT_ENCIRCLEMENT_OPTIONS, DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, DEFAULT_FIX_OPTIONS, DEFAULT_FLOT_OPTIONS, DEFAULT_FORTIFIED_AREA_OPTIONS, DEFAULT_FORTIFIED_LINE_OPTIONS, DEFAULT_GENERIC_CIRCLE_OPTIONS, DEFAULT_GENERIC_LINE_OPTIONS, DEFAULT_GENERIC_POLYGON_OPTIONS, DEFAULT_GENERIC_RECTANGLE_OPTIONS, DEFAULT_MAIN_ATTACK_OPTIONS, DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, DEFAULT_STRONG_POINT_OPTIONS, DEFAULT_SUPPORTING_ATTACK_OPTIONS, DEFAULT_SUPPORT_BY_FIRE_OPTIONS, DEFAULT_TACTICAL_ARROW_OPTIONS, DEFAULT_TURN_OPTIONS, type DelayOptions, type DisruptOptions, EPSILON, type EncirclementOptions, type FLOTOptions, type FeaturePartProps, type FinalProtectiveFireOptions, type FixOptions, type FortifiedAreaOptions, type FortifiedLineOptions, type GenericCircleOptions, type GenericLineOptions, type GenericPolygonOptions, type GenericRectangleOptions, type MainAttackOptions, type MidpointPerpendicularDrawRuleOptions, type ObstacleBypassDifficultOptions, type ObstacleBypassEasyOptions, type ObstacleBypassImpossibleOptions, type OptionsByKind, type ParamDescriptor, type Point2D, type PrincipalDirectionOfFireOptions, type RenderOptions, type SimpleStyleProps, type SimpleStyleRender, type StrongPointOptions, type StyleHints, type SupportByFireOptions, type SupportingAttackOptions, type TacticalArrowOptions, type TurnOptions, ambushDrawRule, attackByFireDrawRule, axis1DrawRule, blockDrawRule, calculateMetrics, centerRadiusDrawRule, cloneControlMeasure, computeDefaultMidpointPerpendicularPoint, computeInitialWidthPoint, controlMeasureIdFromFeature, createBaselineFrame, createMidpointPerpendicularDrawRule, disruptDrawRule, freezeOrientationOptions, getControlMeasureMetadata, getControlMeasureMetadataByValue, getDefaultOptions, getMetersPerPixel, getMidpointPerpendicularSignedDistance, isKind, line1DrawRule, line23DrawRule, line24DrawRule, listControlMeasureMetadata, point12DrawRule, pointOnMidpointPerpendicularAxis, project, rectangleDrawRule, renderControlMeasure, resolveStyleHints, roundToFixed, snapToMidpointPerpendicular, supportByFireDrawRule, toSimpleStyle, turnDrawRule, unproject };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as point12DrawRule, A as DEFAULT_GENERIC_POLYGON_OPTIONS, B as DEFAULT_ANTITANK_WALL_OPTIONS, C as DEFAULT_FIX_OPTIONS, D as DEFAULT_DELAY_OPTIONS, E as DEFAULT_DISRUPT_OPTIONS, F as DEFAULT_BREACH_OPTIONS, G as axis1DrawRule, H as DEFAULT_AMBUSH_OPTIONS, I as DEFAULT_BLOCK_MISSION_TASK_OPTIONS, J as line23DrawRule, K as supportByFireDrawRule, L as DEFAULT_BLOCK_OPTIONS, M as DEFAULT_GENERIC_CIRCLE_OPTIONS, N as DEFAULT_CANALIZE_OPTIONS, O as DEFAULT_CLEAR_OPTIONS, P as DEFAULT_BYPASS_OPTIONS, Q as attackByFireDrawRule, R as DEFAULT_ATTACK_HELICOPTER_OPTIONS, S as DEFAULT_FLOT_OPTIONS, T as DEFAULT_ENCIRCLEMENT_OPTIONS, U as DEFAULT_AIRBORNE_ATTACK_OPTIONS, V as DEFAULT_ANTITANK_DITCH_OPTIONS, W as rectangleDrawRule, X as line1DrawRule, Y as turnDrawRule, Z as ambushDrawRule, _ as DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, a as DEFINITIONS, at as getMidpointPerpendicularSignedDistance, b as DEFAULT_FORTIFIED_AREA_OPTIONS, c as getDefaultOptions, ct as createBaselineFrame, d as DEFAULT_SUPPORTING_ATTACK_OPTIONS, dt as project, et as centerRadiusDrawRule, f as DEFAULT_SUPPORT_BY_FIRE_OPTIONS, ft as unproject, g as DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, h as DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, ht as roundToFixed, i as CONTROL_MEASURE_METADATA, it as createMidpointPerpendicularDrawRule, j as DEFAULT_GENERIC_LINE_OPTIONS, k as DEFAULT_GENERIC_RECTANGLE_OPTIONS, l as listControlMeasureMetadata, lt as calculateMetrics, m as DEFAULT_TACTICAL_ARROW_OPTIONS, mt as getMetersPerPixel, n as resolveStyleHints, nt as blockDrawRule, o as getControlMeasureMetadata, ot as pointOnMidpointPerpendicularAxis, p as DEFAULT_STRONG_POINT_OPTIONS, pt as EPSILON, q as line24DrawRule, r as CONTROL_MEASURE_IDS, rt as computeDefaultMidpointPerpendicularPoint, s as getControlMeasureMetadataByValue, st as snapToMidpointPerpendicular, t as renderControlMeasure, tt as disruptDrawRule, u as DEFAULT_TURN_OPTIONS, ut as computeInitialWidthPoint, v as DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, w as DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, x as DEFAULT_FORTIFIED_LINE_OPTIONS, y as DEFAULT_MAIN_ATTACK_OPTIONS, z as DEFAULT_ATTACK_BY_FIRE_OPTIONS } from "./renderControlMeasure-D5NKuws0.mjs";
|
|
2
|
+
//#region src/freeze-orientation.ts
|
|
3
|
+
/**
|
|
4
|
+
* Dispatches to a measure kind's `freezeOrientation` hook (see
|
|
5
|
+
* {@link import("./define").ControlMeasureDefinition.freezeOrientation}),
|
|
6
|
+
* pinning orientation-derived option defaults to their current concrete
|
|
7
|
+
* values ahead of a rigid rotation of `controlPoints`. Returns `undefined`
|
|
8
|
+
* when the kind declares no hook, or when the hook itself finds nothing to
|
|
9
|
+
* freeze. Edit hosts call this when a rotate gesture starts (ADR-0023).
|
|
10
|
+
*/
|
|
11
|
+
function freezeOrientationOptions(kind, controlPoints, options) {
|
|
12
|
+
const definition = DEFINITIONS[kind];
|
|
13
|
+
if (!definition.freezeOrientation) return void 0;
|
|
14
|
+
return definition.freezeOrientation(controlPoints, options ?? {});
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
2
17
|
//#region src/instance.ts
|
|
3
18
|
function isKind(cm, kind) {
|
|
4
19
|
return cm.kind === kind;
|
|
@@ -99,4 +114,4 @@ function toHexChannel(value) {
|
|
|
99
114
|
return Math.max(0, Math.min(255, Math.round(value))).toString(16).padStart(2, "0");
|
|
100
115
|
}
|
|
101
116
|
//#endregion
|
|
102
|
-
export { CONTROL_MEASURE_IDS, CONTROL_MEASURE_METADATA, DEFAULT_AIRBORNE_ATTACK_OPTIONS, DEFAULT_AMBUSH_OPTIONS, DEFAULT_ANTITANK_DITCH_OPTIONS, DEFAULT_ANTITANK_WALL_OPTIONS, DEFAULT_ATTACK_BY_FIRE_OPTIONS, DEFAULT_ATTACK_HELICOPTER_OPTIONS, DEFAULT_BLOCK_MISSION_TASK_OPTIONS, DEFAULT_BLOCK_OPTIONS, DEFAULT_BREACH_OPTIONS, DEFAULT_BYPASS_OPTIONS, DEFAULT_CANALIZE_OPTIONS, DEFAULT_CLEAR_OPTIONS, DEFAULT_DELAY_OPTIONS, DEFAULT_DISRUPT_OPTIONS, DEFAULT_ENCIRCLEMENT_OPTIONS, DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, DEFAULT_FIX_OPTIONS, DEFAULT_FLOT_OPTIONS, DEFAULT_FORTIFIED_AREA_OPTIONS, DEFAULT_FORTIFIED_LINE_OPTIONS, DEFAULT_MAIN_ATTACK_OPTIONS, DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, DEFAULT_STRONG_POINT_OPTIONS, DEFAULT_SUPPORTING_ATTACK_OPTIONS, DEFAULT_SUPPORT_BY_FIRE_OPTIONS, DEFAULT_TACTICAL_ARROW_OPTIONS, DEFAULT_TURN_OPTIONS, EPSILON, ambushDrawRule, attackByFireDrawRule, axis1DrawRule, blockDrawRule, calculateMetrics, cloneControlMeasure, computeDefaultMidpointPerpendicularPoint, computeInitialWidthPoint, controlMeasureIdFromFeature, createBaselineFrame, createMidpointPerpendicularDrawRule, disruptDrawRule, getControlMeasureMetadata, getControlMeasureMetadataByValue, getDefaultOptions, getMetersPerPixel, getMidpointPerpendicularSignedDistance, isKind, line1DrawRule, line23DrawRule, line24DrawRule, listControlMeasureMetadata, point12DrawRule, pointOnMidpointPerpendicularAxis, project, renderControlMeasure, resolveStyleHints, roundToFixed, snapToMidpointPerpendicular, supportByFireDrawRule, toSimpleStyle, turnDrawRule, unproject };
|
|
117
|
+
export { CONTROL_MEASURE_IDS, CONTROL_MEASURE_METADATA, DEFAULT_AIRBORNE_ATTACK_OPTIONS, DEFAULT_AMBUSH_OPTIONS, DEFAULT_ANTITANK_DITCH_OPTIONS, DEFAULT_ANTITANK_WALL_OPTIONS, DEFAULT_ATTACK_BY_FIRE_OPTIONS, DEFAULT_ATTACK_HELICOPTER_OPTIONS, DEFAULT_BLOCK_MISSION_TASK_OPTIONS, DEFAULT_BLOCK_OPTIONS, DEFAULT_BREACH_OPTIONS, DEFAULT_BYPASS_OPTIONS, DEFAULT_CANALIZE_OPTIONS, DEFAULT_CLEAR_OPTIONS, DEFAULT_DELAY_OPTIONS, DEFAULT_DISRUPT_OPTIONS, DEFAULT_ENCIRCLEMENT_OPTIONS, DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, DEFAULT_FIX_OPTIONS, DEFAULT_FLOT_OPTIONS, DEFAULT_FORTIFIED_AREA_OPTIONS, DEFAULT_FORTIFIED_LINE_OPTIONS, DEFAULT_GENERIC_CIRCLE_OPTIONS, DEFAULT_GENERIC_LINE_OPTIONS, DEFAULT_GENERIC_POLYGON_OPTIONS, DEFAULT_GENERIC_RECTANGLE_OPTIONS, DEFAULT_MAIN_ATTACK_OPTIONS, DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, DEFAULT_STRONG_POINT_OPTIONS, DEFAULT_SUPPORTING_ATTACK_OPTIONS, DEFAULT_SUPPORT_BY_FIRE_OPTIONS, DEFAULT_TACTICAL_ARROW_OPTIONS, DEFAULT_TURN_OPTIONS, EPSILON, ambushDrawRule, attackByFireDrawRule, axis1DrawRule, blockDrawRule, calculateMetrics, centerRadiusDrawRule, cloneControlMeasure, computeDefaultMidpointPerpendicularPoint, computeInitialWidthPoint, controlMeasureIdFromFeature, createBaselineFrame, createMidpointPerpendicularDrawRule, disruptDrawRule, freezeOrientationOptions, getControlMeasureMetadata, getControlMeasureMetadataByValue, getDefaultOptions, getMetersPerPixel, getMidpointPerpendicularSignedDistance, isKind, line1DrawRule, line23DrawRule, line24DrawRule, listControlMeasureMetadata, point12DrawRule, pointOnMidpointPerpendicularAxis, project, rectangleDrawRule, renderControlMeasure, resolveStyleHints, roundToFixed, snapToMidpointPerpendicular, supportByFireDrawRule, toSimpleStyle, turnDrawRule, unproject };
|
package/dist/preview/index.d.mts
CHANGED
package/dist/preview/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as DEFINITIONS, t as renderControlMeasure } from "../renderControlMeasure-
|
|
1
|
+
import { a as DEFINITIONS, t as renderControlMeasure } from "../renderControlMeasure-D5NKuws0.mjs";
|
|
2
2
|
//#region src/preview/index.ts
|
|
3
3
|
/**
|
|
4
4
|
* Unitless `previewSample` points (~`[-1, 1]`) are scaled by this degree offset
|
|
@@ -484,7 +484,7 @@ function samePosition(a, b) {
|
|
|
484
484
|
}
|
|
485
485
|
//#endregion
|
|
486
486
|
//#region src/draw-rules/area1.ts
|
|
487
|
-
function derive$
|
|
487
|
+
function derive$8(points) {
|
|
488
488
|
return clonePositions(points);
|
|
489
489
|
}
|
|
490
490
|
/**
|
|
@@ -503,9 +503,10 @@ function derive$7(points) {
|
|
|
503
503
|
const area1DrawRule = {
|
|
504
504
|
id: "area1",
|
|
505
505
|
minimumUserPoints: 3,
|
|
506
|
-
|
|
506
|
+
closedRing: true,
|
|
507
|
+
derive: derive$8,
|
|
507
508
|
transform(event) {
|
|
508
|
-
return derive$
|
|
509
|
+
return derive$8(event.next);
|
|
509
510
|
}
|
|
510
511
|
};
|
|
511
512
|
//#endregion
|
|
@@ -531,14 +532,14 @@ const disruptDrawRule = createMidpointPerpendicularDrawRule({
|
|
|
531
532
|
* that fixes both the radius and the bearing of the symbol's opening. Both
|
|
532
533
|
* points are user-clicked, so the canonical array is just the (clamped) input.
|
|
533
534
|
*/
|
|
534
|
-
function derive$
|
|
535
|
+
function derive$7(points) {
|
|
535
536
|
return clonePositions(points.slice(0, 2));
|
|
536
537
|
}
|
|
537
|
-
const
|
|
538
|
-
id: "area15:
|
|
538
|
+
const centerRadiusDrawRule = {
|
|
539
|
+
id: "area15:center-radius",
|
|
539
540
|
minimumUserPoints: 2,
|
|
540
541
|
canonicalPointCount: 2,
|
|
541
|
-
derive: derive$
|
|
542
|
+
derive: derive$7,
|
|
542
543
|
transform(event) {
|
|
543
544
|
const { previous, next, activePointIndex } = event;
|
|
544
545
|
if (activePointIndex === 0 && previous.length >= 2 && next.length >= 2) {
|
|
@@ -547,9 +548,11 @@ const isolateDrawRule = {
|
|
|
547
548
|
const origin = previous[1];
|
|
548
549
|
return [clonePosition(next[0]), [origin[0] + dx, origin[1] + dy]];
|
|
549
550
|
}
|
|
550
|
-
return derive$
|
|
551
|
+
return derive$7(next);
|
|
551
552
|
}
|
|
552
553
|
};
|
|
554
|
+
/** Backward-compatible doctrinal name for Area15's shared center-radius rule. */
|
|
555
|
+
const isolateDrawRule = centerRadiusDrawRule;
|
|
553
556
|
//#endregion
|
|
554
557
|
//#region src/draw-rules/point12.ts
|
|
555
558
|
/**
|
|
@@ -590,20 +593,20 @@ const ambushDrawRule = createMidpointPerpendicularDrawRule({
|
|
|
590
593
|
});
|
|
591
594
|
//#endregion
|
|
592
595
|
//#region src/draw-rules/line1.ts
|
|
593
|
-
function derive$
|
|
596
|
+
function derive$6(points) {
|
|
594
597
|
return clonePositions(points);
|
|
595
598
|
}
|
|
596
599
|
const line1DrawRule = {
|
|
597
600
|
id: "line1",
|
|
598
601
|
minimumUserPoints: 2,
|
|
599
|
-
derive: derive$
|
|
602
|
+
derive: derive$6,
|
|
600
603
|
transform(event) {
|
|
601
|
-
return derive$
|
|
604
|
+
return derive$6(event.next);
|
|
602
605
|
}
|
|
603
606
|
};
|
|
604
607
|
//#endregion
|
|
605
608
|
//#region src/draw-rules/line3.ts
|
|
606
|
-
function derive$
|
|
609
|
+
function derive$5(points) {
|
|
607
610
|
return clonePositions(points);
|
|
608
611
|
}
|
|
609
612
|
/**
|
|
@@ -618,23 +621,23 @@ const line3DrawRule = {
|
|
|
618
621
|
id: "line3",
|
|
619
622
|
minimumUserPoints: 3,
|
|
620
623
|
canonicalPointCount: 3,
|
|
621
|
-
derive: derive$
|
|
624
|
+
derive: derive$5,
|
|
622
625
|
transform(event) {
|
|
623
|
-
return derive$
|
|
626
|
+
return derive$5(event.next);
|
|
624
627
|
}
|
|
625
628
|
};
|
|
626
629
|
//#endregion
|
|
627
630
|
//#region src/draw-rules/line9.ts
|
|
628
|
-
function derive$
|
|
631
|
+
function derive$4(points) {
|
|
629
632
|
return clonePositions(points);
|
|
630
633
|
}
|
|
631
634
|
const line9DrawRule = {
|
|
632
635
|
id: "line9",
|
|
633
636
|
minimumUserPoints: 2,
|
|
634
637
|
canonicalPointCount: 2,
|
|
635
|
-
derive: derive$
|
|
638
|
+
derive: derive$4,
|
|
636
639
|
transform(event) {
|
|
637
|
-
return derive$
|
|
640
|
+
return derive$4(event.next);
|
|
638
641
|
}
|
|
639
642
|
};
|
|
640
643
|
//#endregion
|
|
@@ -740,7 +743,7 @@ const line24DrawRule = createMidpointPerpendicularDrawRule({
|
|
|
740
743
|
});
|
|
741
744
|
//#endregion
|
|
742
745
|
//#region src/draw-rules/area8.ts
|
|
743
|
-
function derive$
|
|
746
|
+
function derive$3(points) {
|
|
744
747
|
if (points.length < 2) return clonePositions(points);
|
|
745
748
|
if (points.length !== 2) return clonePositions(points.slice(0, 4));
|
|
746
749
|
const p1 = clonePosition(points[0]);
|
|
@@ -764,16 +767,16 @@ const supportByFireDrawRule = {
|
|
|
764
767
|
id: "area8:support-by-fire",
|
|
765
768
|
minimumUserPoints: 2,
|
|
766
769
|
canonicalPointCount: 4,
|
|
767
|
-
derive: derive$
|
|
770
|
+
derive: derive$3,
|
|
768
771
|
transform(event) {
|
|
769
772
|
const { next } = event;
|
|
770
773
|
if (next.length === 4) return clonePositions(next);
|
|
771
|
-
return derive$
|
|
774
|
+
return derive$3(next);
|
|
772
775
|
}
|
|
773
776
|
};
|
|
774
777
|
//#endregion
|
|
775
778
|
//#region src/draw-rules/axis1.ts
|
|
776
|
-
function derive$
|
|
779
|
+
function derive$2(points) {
|
|
777
780
|
if (points.length < 2) return clonePositions(points);
|
|
778
781
|
if (points.length === 2) {
|
|
779
782
|
const tip = clonePosition(points[0]);
|
|
@@ -811,10 +814,10 @@ const axis1DrawRule = {
|
|
|
811
814
|
id: "axis1",
|
|
812
815
|
minimumUserPoints: 2,
|
|
813
816
|
trailingFixedSlots: 1,
|
|
814
|
-
derive: derive$
|
|
817
|
+
derive: derive$2,
|
|
815
818
|
transform(event) {
|
|
816
819
|
const { previous, next, activePointIndex } = event;
|
|
817
|
-
if (next.length < 3 || previous.length < 3) return derive$
|
|
820
|
+
if (next.length < 3 || previous.length < 3) return derive$2(next);
|
|
818
821
|
if (!(activePointIndex === 0 || activePointIndex === 1)) return clonePositions(next);
|
|
819
822
|
const metrics = calculateMetrics(previous);
|
|
820
823
|
if (!metrics) return clonePositions(next);
|
|
@@ -825,7 +828,7 @@ const axis1DrawRule = {
|
|
|
825
828
|
};
|
|
826
829
|
//#endregion
|
|
827
830
|
//#region src/draw-rules/area21.ts
|
|
828
|
-
function derive(points) {
|
|
831
|
+
function derive$1(points) {
|
|
829
832
|
if (points.length === 2) return clonePositions([
|
|
830
833
|
points[0],
|
|
831
834
|
points[1],
|
|
@@ -838,9 +841,99 @@ const searchAreaDrawRule = {
|
|
|
838
841
|
minimumUserPoints: 3,
|
|
839
842
|
minimumPreviewPoints: 2,
|
|
840
843
|
canonicalPointCount: 3,
|
|
844
|
+
derive: derive$1,
|
|
845
|
+
transform(event) {
|
|
846
|
+
return derive$1(event.next);
|
|
847
|
+
}
|
|
848
|
+
};
|
|
849
|
+
//#endregion
|
|
850
|
+
//#region src/draw-rules/rectangle.ts
|
|
851
|
+
/**
|
|
852
|
+
* Oriented rectangle: P1 and P2 are adjacent corners and define the first
|
|
853
|
+
* edge. P3 is the next corner, constrained to the perpendicular through P2.
|
|
854
|
+
* The generator derives the fourth corner.
|
|
855
|
+
*/
|
|
856
|
+
function derive(points) {
|
|
857
|
+
if (points.length < 2) return clonePositions(points);
|
|
858
|
+
const p1 = clonePosition(points[0]);
|
|
859
|
+
const p2 = clonePosition(points[1]);
|
|
860
|
+
if (points.length === 2) return [
|
|
861
|
+
p1,
|
|
862
|
+
p2,
|
|
863
|
+
clonePosition(p2)
|
|
864
|
+
];
|
|
865
|
+
const frame = createBaselineFrame(p1, p2, {
|
|
866
|
+
origin: "p2",
|
|
867
|
+
normal: "right"
|
|
868
|
+
});
|
|
869
|
+
return [
|
|
870
|
+
p1,
|
|
871
|
+
p2,
|
|
872
|
+
frame?.pointAtNormalDistance(frame.signedNormalDistance(points[2])) ?? clonePosition(points[2])
|
|
873
|
+
];
|
|
874
|
+
}
|
|
875
|
+
function guidePoints(points) {
|
|
876
|
+
const canonical = derive(points);
|
|
877
|
+
if (canonical.length < 3) return canonical;
|
|
878
|
+
const [c1, c2, c3] = canonical;
|
|
879
|
+
if (!c1 || !c2 || !c3) return canonical;
|
|
880
|
+
if (c2[0] === c3[0] && c2[1] === c3[1]) return [c1, c2];
|
|
881
|
+
const p1 = project(c1[0], c1[1]);
|
|
882
|
+
const p2 = project(c2[0], c2[1]);
|
|
883
|
+
const p4 = vecAdd(p1, vecSub(project(c3[0], c3[1]), p2));
|
|
884
|
+
return [
|
|
885
|
+
c1,
|
|
886
|
+
c2,
|
|
887
|
+
c3,
|
|
888
|
+
unproject(p4[0], p4[1]),
|
|
889
|
+
clonePosition(c1)
|
|
890
|
+
];
|
|
891
|
+
}
|
|
892
|
+
function snapToAxis(point, origin, direction) {
|
|
893
|
+
const snapped = vecAdd(origin, vecScale(direction, vecDot(vecSub(project(point[0], point[1]), origin), direction)));
|
|
894
|
+
return unproject(snapped[0], snapped[1]);
|
|
895
|
+
}
|
|
896
|
+
const rectangleDrawRule = {
|
|
897
|
+
id: "rectangle",
|
|
898
|
+
minimumUserPoints: 3,
|
|
899
|
+
minimumPreviewPoints: 2,
|
|
900
|
+
canonicalPointCount: 3,
|
|
901
|
+
showGuide: true,
|
|
902
|
+
guidePoints,
|
|
841
903
|
derive,
|
|
842
904
|
transform(event) {
|
|
843
|
-
|
|
905
|
+
const { previous, next, activePointIndex } = event;
|
|
906
|
+
if (previous.length < 3 || next.length < 3) return derive(next);
|
|
907
|
+
const frame = createBaselineFrame(previous[0], previous[1], {
|
|
908
|
+
origin: "p2",
|
|
909
|
+
normal: "right"
|
|
910
|
+
});
|
|
911
|
+
if (!frame) return derive(next);
|
|
912
|
+
if (activePointIndex === 0) return [
|
|
913
|
+
snapToAxis(next[0], frame.p2, frame.direction),
|
|
914
|
+
clonePosition(previous[1]),
|
|
915
|
+
clonePosition(previous[2])
|
|
916
|
+
];
|
|
917
|
+
if (activePointIndex === 1) {
|
|
918
|
+
const p2 = snapToAxis(next[1], frame.p1, frame.direction);
|
|
919
|
+
const delta = vecSub(project(p2[0], p2[1]), frame.p2);
|
|
920
|
+
const projectedP3 = vecAdd(project(previous[2][0], previous[2][1]), delta);
|
|
921
|
+
const p3 = unproject(projectedP3[0], projectedP3[1]);
|
|
922
|
+
return [
|
|
923
|
+
clonePosition(previous[0]),
|
|
924
|
+
p2,
|
|
925
|
+
p3
|
|
926
|
+
];
|
|
927
|
+
}
|
|
928
|
+
if (activePointIndex === 2) {
|
|
929
|
+
const p3 = frame.pointAtNormalDistance(frame.signedNormalDistance(next[2]));
|
|
930
|
+
if (p3) return [
|
|
931
|
+
clonePosition(previous[0]),
|
|
932
|
+
clonePosition(previous[1]),
|
|
933
|
+
p3
|
|
934
|
+
];
|
|
935
|
+
}
|
|
936
|
+
return derive(next);
|
|
844
937
|
}
|
|
845
938
|
};
|
|
846
939
|
//#endregion
|
|
@@ -2330,13 +2423,21 @@ function resolveEchelonHeight(echelonSize, echelonSizePixels, metersPerPixel) {
|
|
|
2330
2423
|
if (echelonSizePixels !== void 0 && metersPerPixel !== void 0 && metersPerPixel > 0) h = echelonSizePixels * metersPerPixel;
|
|
2331
2424
|
return Math.max(EPSILON, h);
|
|
2332
2425
|
}
|
|
2426
|
+
/** Wraps `x` into `[0, 1)`, treating `x` as a fraction (matches the arc-length wrap below). */
|
|
2427
|
+
function wrap01(x) {
|
|
2428
|
+
return (x % 1 + 1) % 1;
|
|
2429
|
+
}
|
|
2333
2430
|
/**
|
|
2334
2431
|
* Places the Field B echelon glyph on the perimeter and computes its masking
|
|
2335
|
-
* gap, anchored to the bottom edge and slid by `echelonPosition`
|
|
2336
|
-
* fraction of the perimeter, wrapping at the seam).
|
|
2337
|
-
*
|
|
2432
|
+
* gap, anchored by default to the bottom edge and slid by `echelonPosition`
|
|
2433
|
+
* (a signed fraction of the perimeter, wrapping at the seam). When
|
|
2434
|
+
* `echelonAnchor` is supplied, it replaces the bottom-edge anchor with an
|
|
2435
|
+
* absolute perimeter fraction (measured from the ring seam) — see
|
|
2436
|
+
* `BattlePositionOptions.echelonAnchor` for why (ADR-0023 rotate-freeze).
|
|
2437
|
+
* Returns empty geometry when the echelon resolves to none or the ring is
|
|
2438
|
+
* degenerate.
|
|
2338
2439
|
*/
|
|
2339
|
-
function placeEchelon(perimeter, h, echelon, echelonPadding, echelonPosition) {
|
|
2440
|
+
function placeEchelon(perimeter, h, echelon, echelonPadding, echelonPosition, echelonAnchor) {
|
|
2340
2441
|
const { segs, totalLength, anchorTarget } = perimeter;
|
|
2341
2442
|
const spec = resolveEchelon(echelon);
|
|
2342
2443
|
if (!spec || segs.length === 0 || totalLength < 1e-6) return {
|
|
@@ -2344,7 +2445,7 @@ function placeEchelon(perimeter, h, echelon, echelonPadding, echelonPosition) {
|
|
|
2344
2445
|
fills: [],
|
|
2345
2446
|
gaps: []
|
|
2346
2447
|
};
|
|
2347
|
-
const target = ((anchorTarget + echelonPosition * totalLength) % totalLength + totalLength) % totalLength;
|
|
2448
|
+
const target = (((echelonAnchor !== void 0 ? wrap01(echelonAnchor) * totalLength : anchorTarget) + echelonPosition * totalLength) % totalLength + totalLength) % totalLength;
|
|
2348
2449
|
const { point, seg } = pointOnRing(segs, target);
|
|
2349
2450
|
const { strokes, fills, width } = buildEchelonGlyph(point, seg.along, seg.perp, h, spec);
|
|
2350
2451
|
const gaps = [];
|
|
@@ -2454,10 +2555,10 @@ const BATTLE_POSITION_METADATA = {
|
|
|
2454
2555
|
* @param options - {@link BattlePositionOptions}.
|
|
2455
2556
|
*/
|
|
2456
2557
|
function createBattlePosition(positions, options = {}) {
|
|
2457
|
-
const { echelon = DEFAULT_BATTLE_POSITION_OPTIONS.echelon, echelonSize = DEFAULT_BATTLE_POSITION_OPTIONS.echelonSize, echelonSizePixels, echelonPadding = DEFAULT_BATTLE_POSITION_OPTIONS.echelonPadding, echelonPosition = DEFAULT_BATTLE_POSITION_OPTIONS.echelonPosition, metersPerPixel, smooth = DEFAULT_BATTLE_POSITION_OPTIONS.smooth, smoothResolution = DEFAULT_BATTLE_POSITION_OPTIONS.smoothResolution } = options;
|
|
2558
|
+
const { echelon = DEFAULT_BATTLE_POSITION_OPTIONS.echelon, echelonSize = DEFAULT_BATTLE_POSITION_OPTIONS.echelonSize, echelonSizePixels, echelonPadding = DEFAULT_BATTLE_POSITION_OPTIONS.echelonPadding, echelonPosition = DEFAULT_BATTLE_POSITION_OPTIONS.echelonPosition, echelonAnchor, metersPerPixel, smooth = DEFAULT_BATTLE_POSITION_OPTIONS.smooth, smoothResolution = DEFAULT_BATTLE_POSITION_OPTIONS.smoothResolution } = options;
|
|
2458
2559
|
const h = resolveEchelonHeight(echelonSize, echelonSizePixels, metersPerPixel);
|
|
2459
2560
|
const verts = buildClosedRing(positions, smooth, smoothResolution, DEFAULT_SMOOTH_RESOLUTION$6);
|
|
2460
|
-
const { strokes, fills, gaps } = placeEchelon(buildAreaPerimeter(verts), h, echelon, echelonPadding, echelonPosition);
|
|
2561
|
+
const { strokes, fills, gaps } = placeEchelon(buildAreaPerimeter(verts), h, echelon, echelonPadding, echelonPosition, echelonAnchor);
|
|
2461
2562
|
const boundaryCoords = buildGappedLine(verts, gaps);
|
|
2462
2563
|
const features = [];
|
|
2463
2564
|
if (boundaryCoords.length > 0) features.push({
|
|
@@ -2492,11 +2593,29 @@ function createBattlePosition(positions, options = {}) {
|
|
|
2492
2593
|
features
|
|
2493
2594
|
};
|
|
2494
2595
|
}
|
|
2596
|
+
/**
|
|
2597
|
+
* `freezeOrientation` hook (ADR-0023) shared by Battle Position and Strong
|
|
2598
|
+
* Point: pins the echelon anchor to its current bottom-edge fraction so a
|
|
2599
|
+
* subsequent rigid rotation of `controlPoints` (e.g. the transform box's
|
|
2600
|
+
* rotate grip) does not re-derive a different "bottom edge" against the
|
|
2601
|
+
* rotated geometry. Returns `undefined` — nothing to freeze — when:
|
|
2602
|
+
* - `echelonAnchor` is already set (previously frozen or user-authored), or
|
|
2603
|
+
* - the echelon resolves to none (nothing visible to pin), or
|
|
2604
|
+
* - the ring is degenerate (no segments, or a near-zero perimeter).
|
|
2605
|
+
*/
|
|
2606
|
+
function freezeEchelonAnchor(controlPoints, options) {
|
|
2607
|
+
if (options.echelonAnchor !== void 0) return void 0;
|
|
2608
|
+
if (!resolveEchelon(options.echelon ?? DEFAULT_BATTLE_POSITION_OPTIONS.echelon)) return void 0;
|
|
2609
|
+
const perimeter = buildAreaPerimeter(buildClosedRing(controlPoints, options.smooth ?? DEFAULT_BATTLE_POSITION_OPTIONS.smooth, options.smoothResolution ?? DEFAULT_BATTLE_POSITION_OPTIONS.smoothResolution, DEFAULT_SMOOTH_RESOLUTION$6));
|
|
2610
|
+
if (perimeter.segs.length === 0 || perimeter.totalLength < 1e-6) return void 0;
|
|
2611
|
+
return { echelonAnchor: perimeter.anchorTarget / perimeter.totalLength };
|
|
2612
|
+
}
|
|
2495
2613
|
const BATTLE_POSITION = defineControlMeasure({
|
|
2496
2614
|
metadata: BATTLE_POSITION_METADATA,
|
|
2497
2615
|
generator: createBattlePosition,
|
|
2498
2616
|
defaultOptions: DEFAULT_BATTLE_POSITION_OPTIONS,
|
|
2499
2617
|
rule: area1DrawRule,
|
|
2618
|
+
freezeOrientation: freezeEchelonAnchor,
|
|
2500
2619
|
previewSample: {
|
|
2501
2620
|
controlPoints: [
|
|
2502
2621
|
[-1, -.5],
|
|
@@ -2594,7 +2713,7 @@ const BLOCK_ARROW_METADATA = {
|
|
|
2594
2713
|
id: "block-arrow",
|
|
2595
2714
|
name: "Block Arrow",
|
|
2596
2715
|
description: "Solid filled arrow with a controllable shaft width and selectable head (triangle, barbed, concave, diamond, harpoon, swallowtail, tee). Not a doctrinal symbol.",
|
|
2597
|
-
entity: "Generic
|
|
2716
|
+
entity: "Generic Graphics",
|
|
2598
2717
|
entityType: "Illustrative Arrow",
|
|
2599
2718
|
entitySubtype: "Block Arrow",
|
|
2600
2719
|
value: "990001",
|
|
@@ -3622,7 +3741,7 @@ const CLASSIC_ARROW_METADATA = {
|
|
|
3622
3741
|
id: "classic-arrow",
|
|
3623
3742
|
name: "Classic Arrow",
|
|
3624
3743
|
description: "Clean straight arrow with a selectable head (triangle, barbed, concave, diamond, harpoon, swallowtail, chevron, circle, tee, open). Not a doctrinal symbol.",
|
|
3625
|
-
entity: "Generic
|
|
3744
|
+
entity: "Generic Graphics",
|
|
3626
3745
|
entityType: "Illustrative Arrow",
|
|
3627
3746
|
entitySubtype: "Classic Arrow",
|
|
3628
3747
|
value: "990002",
|
|
@@ -3905,6 +4024,271 @@ function normalizeSmoothResolution(value) {
|
|
|
3905
4024
|
return Math.min(MAX_SMOOTH_RESOLUTION, Math.max(MIN_SMOOTH_RESOLUTION, Math.round(value)));
|
|
3906
4025
|
}
|
|
3907
4026
|
//#endregion
|
|
4027
|
+
//#region src/generators/cm99-generic-graphics/params.ts
|
|
4028
|
+
const SMOOTH_PATH_PARAMS = [{
|
|
4029
|
+
key: "smooth",
|
|
4030
|
+
label: "Smooth",
|
|
4031
|
+
description: "Curve the path through the control points.",
|
|
4032
|
+
type: "boolean"
|
|
4033
|
+
}, {
|
|
4034
|
+
key: "smoothResolution",
|
|
4035
|
+
label: "Smooth resolution",
|
|
4036
|
+
description: "Number of samples per segment when smooth mode is enabled.",
|
|
4037
|
+
type: "number",
|
|
4038
|
+
min: 2,
|
|
4039
|
+
max: 64,
|
|
4040
|
+
step: 1,
|
|
4041
|
+
visibleWhen: (opts) => Boolean(opts.smooth)
|
|
4042
|
+
}];
|
|
4043
|
+
const FILLED_AREA_PARAMS = [{
|
|
4044
|
+
key: "filled",
|
|
4045
|
+
label: "Filled",
|
|
4046
|
+
description: "Fill the interior instead of rendering an outline only.",
|
|
4047
|
+
type: "boolean"
|
|
4048
|
+
}];
|
|
4049
|
+
//#endregion
|
|
4050
|
+
//#region src/generators/cm99-generic-graphics/circle.ts
|
|
4051
|
+
const CIRCLE_SEGMENTS = 64;
|
|
4052
|
+
const DEFAULT_GENERIC_CIRCLE_OPTIONS = { filled: false };
|
|
4053
|
+
const GENERIC_CIRCLE_METADATA = {
|
|
4054
|
+
id: "circle",
|
|
4055
|
+
name: "Circle",
|
|
4056
|
+
description: "A non-doctrinal circle defined by a center and radius point.",
|
|
4057
|
+
entity: "Generic Graphics",
|
|
4058
|
+
entityType: "Basic Shape",
|
|
4059
|
+
entitySubtype: "Circle",
|
|
4060
|
+
value: "990104",
|
|
4061
|
+
minCoordinates: 2,
|
|
4062
|
+
maxCoordinates: 2,
|
|
4063
|
+
geometry: "area",
|
|
4064
|
+
geometryTypes: ["Polygon"],
|
|
4065
|
+
drawRule: "Area15",
|
|
4066
|
+
params: FILLED_AREA_PARAMS
|
|
4067
|
+
};
|
|
4068
|
+
function createGenericCircle(coordinates, options = {}) {
|
|
4069
|
+
const center = project(coordinates[0][0], coordinates[0][1]);
|
|
4070
|
+
const radiusVector = vecSub(project(coordinates[1][0], coordinates[1][1]), center);
|
|
4071
|
+
const radius = vecMag(radiusVector);
|
|
4072
|
+
if (radius < 1e-6) return {
|
|
4073
|
+
type: "FeatureCollection",
|
|
4074
|
+
features: []
|
|
4075
|
+
};
|
|
4076
|
+
const startAngle = Math.atan2(radiusVector[1], radiusVector[0]);
|
|
4077
|
+
const ring = [];
|
|
4078
|
+
for (let index = 0; index <= CIRCLE_SEGMENTS; index++) {
|
|
4079
|
+
const angle = startAngle + index / CIRCLE_SEGMENTS * Math.PI * 2;
|
|
4080
|
+
ring.push(unproject(center[0] + Math.cos(angle) * radius, center[1] + Math.sin(angle) * radius));
|
|
4081
|
+
}
|
|
4082
|
+
return {
|
|
4083
|
+
type: "FeatureCollection",
|
|
4084
|
+
features: [{
|
|
4085
|
+
type: "Feature",
|
|
4086
|
+
properties: {
|
|
4087
|
+
part: "circle",
|
|
4088
|
+
fill: options.filled ?? DEFAULT_GENERIC_CIRCLE_OPTIONS.filled
|
|
4089
|
+
},
|
|
4090
|
+
geometry: {
|
|
4091
|
+
type: "Polygon",
|
|
4092
|
+
coordinates: [ring]
|
|
4093
|
+
}
|
|
4094
|
+
}]
|
|
4095
|
+
};
|
|
4096
|
+
}
|
|
4097
|
+
const GENERIC_CIRCLE = defineControlMeasure({
|
|
4098
|
+
metadata: GENERIC_CIRCLE_METADATA,
|
|
4099
|
+
generator: createGenericCircle,
|
|
4100
|
+
defaultOptions: DEFAULT_GENERIC_CIRCLE_OPTIONS,
|
|
4101
|
+
rule: centerRadiusDrawRule,
|
|
4102
|
+
previewSample: { controlPoints: [[0, 0], [.8, 0]] }
|
|
4103
|
+
});
|
|
4104
|
+
//#endregion
|
|
4105
|
+
//#region src/generators/cm99-generic-graphics/line.ts
|
|
4106
|
+
const DEFAULT_GENERIC_LINE_OPTIONS = {
|
|
4107
|
+
smooth: false,
|
|
4108
|
+
smoothResolution: 12
|
|
4109
|
+
};
|
|
4110
|
+
const GENERIC_LINE_METADATA = {
|
|
4111
|
+
id: "line",
|
|
4112
|
+
name: "Line",
|
|
4113
|
+
description: "A non-doctrinal free polyline through two or more control points.",
|
|
4114
|
+
entity: "Generic Graphics",
|
|
4115
|
+
entityType: "Basic Shape",
|
|
4116
|
+
entitySubtype: "Line",
|
|
4117
|
+
value: "990101",
|
|
4118
|
+
minCoordinates: 2,
|
|
4119
|
+
geometry: "line",
|
|
4120
|
+
geometryTypes: ["LineString"],
|
|
4121
|
+
drawRule: "Line1",
|
|
4122
|
+
params: SMOOTH_PATH_PARAMS
|
|
4123
|
+
};
|
|
4124
|
+
function createGenericLine(coordinates, options = {}) {
|
|
4125
|
+
const projected = coordinates.map((point) => project(point[0], point[1]));
|
|
4126
|
+
if (!projected.some((point, index) => {
|
|
4127
|
+
const next = projected[index + 1];
|
|
4128
|
+
return next ? Math.hypot(next[0] - point[0], next[1] - point[1]) >= 1e-6 : false;
|
|
4129
|
+
})) return {
|
|
4130
|
+
type: "FeatureCollection",
|
|
4131
|
+
features: []
|
|
4132
|
+
};
|
|
4133
|
+
const { smooth, smoothResolution } = {
|
|
4134
|
+
...DEFAULT_GENERIC_LINE_OPTIONS,
|
|
4135
|
+
...options
|
|
4136
|
+
};
|
|
4137
|
+
const resolution = normalizeSmoothResolution$2(smoothResolution, 12);
|
|
4138
|
+
return {
|
|
4139
|
+
type: "FeatureCollection",
|
|
4140
|
+
features: [{
|
|
4141
|
+
type: "Feature",
|
|
4142
|
+
properties: { part: "line" },
|
|
4143
|
+
geometry: {
|
|
4144
|
+
type: "LineString",
|
|
4145
|
+
coordinates: (smooth ? catmullRom(projected, resolution) : projected).map((point) => unproject(point[0], point[1]))
|
|
4146
|
+
}
|
|
4147
|
+
}]
|
|
4148
|
+
};
|
|
4149
|
+
}
|
|
4150
|
+
const GENERIC_LINE = defineControlMeasure({
|
|
4151
|
+
metadata: GENERIC_LINE_METADATA,
|
|
4152
|
+
generator: createGenericLine,
|
|
4153
|
+
defaultOptions: DEFAULT_GENERIC_LINE_OPTIONS,
|
|
4154
|
+
rule: line1DrawRule,
|
|
4155
|
+
previewSample: { controlPoints: [
|
|
4156
|
+
[-1, -.4],
|
|
4157
|
+
[0, .5],
|
|
4158
|
+
[1, -.2]
|
|
4159
|
+
] }
|
|
4160
|
+
});
|
|
4161
|
+
//#endregion
|
|
4162
|
+
//#region src/generators/cm99-generic-graphics/polygon.ts
|
|
4163
|
+
const DEFAULT_GENERIC_POLYGON_OPTIONS = {
|
|
4164
|
+
smooth: false,
|
|
4165
|
+
smoothResolution: 12,
|
|
4166
|
+
filled: false
|
|
4167
|
+
};
|
|
4168
|
+
const GENERIC_POLYGON_METADATA = {
|
|
4169
|
+
id: "polygon",
|
|
4170
|
+
name: "Polygon",
|
|
4171
|
+
description: "A non-doctrinal free polygon with one outer ring.",
|
|
4172
|
+
entity: "Generic Graphics",
|
|
4173
|
+
entityType: "Basic Shape",
|
|
4174
|
+
entitySubtype: "Polygon",
|
|
4175
|
+
value: "990102",
|
|
4176
|
+
minCoordinates: 3,
|
|
4177
|
+
geometry: "area",
|
|
4178
|
+
geometryTypes: ["Polygon"],
|
|
4179
|
+
drawRule: "Area1",
|
|
4180
|
+
params: [...SMOOTH_PATH_PARAMS, ...FILLED_AREA_PARAMS]
|
|
4181
|
+
};
|
|
4182
|
+
function createGenericPolygon(coordinates, options = {}) {
|
|
4183
|
+
const projected = coordinates.map((point) => project(point[0], point[1]));
|
|
4184
|
+
const ringPoints = projected.length > 1 && vecMag(vecSub(projected[0], projected.at(-1))) < 1e-6 ? projected.slice(0, -1) : projected;
|
|
4185
|
+
if (ringPoints.length < 3) return {
|
|
4186
|
+
type: "FeatureCollection",
|
|
4187
|
+
features: []
|
|
4188
|
+
};
|
|
4189
|
+
const { smooth, smoothResolution, filled } = {
|
|
4190
|
+
...DEFAULT_GENERIC_POLYGON_OPTIONS,
|
|
4191
|
+
...options
|
|
4192
|
+
};
|
|
4193
|
+
const resolution = normalizeSmoothResolution$2(smoothResolution, 12);
|
|
4194
|
+
const ring = smooth ? closedCatmullRom(ringPoints, resolution) : [...ringPoints, ringPoints[0]];
|
|
4195
|
+
return {
|
|
4196
|
+
type: "FeatureCollection",
|
|
4197
|
+
features: [{
|
|
4198
|
+
type: "Feature",
|
|
4199
|
+
properties: {
|
|
4200
|
+
part: "polygon",
|
|
4201
|
+
fill: filled
|
|
4202
|
+
},
|
|
4203
|
+
geometry: {
|
|
4204
|
+
type: "Polygon",
|
|
4205
|
+
coordinates: [ring.map((point) => unproject(point[0], point[1]))]
|
|
4206
|
+
}
|
|
4207
|
+
}]
|
|
4208
|
+
};
|
|
4209
|
+
}
|
|
4210
|
+
const GENERIC_POLYGON = defineControlMeasure({
|
|
4211
|
+
metadata: GENERIC_POLYGON_METADATA,
|
|
4212
|
+
generator: createGenericPolygon,
|
|
4213
|
+
defaultOptions: DEFAULT_GENERIC_POLYGON_OPTIONS,
|
|
4214
|
+
rule: area1DrawRule,
|
|
4215
|
+
previewSample: { controlPoints: [
|
|
4216
|
+
[-.9, -.7],
|
|
4217
|
+
[.8, -.6],
|
|
4218
|
+
[1, .5],
|
|
4219
|
+
[-.4, .8]
|
|
4220
|
+
] }
|
|
4221
|
+
});
|
|
4222
|
+
//#endregion
|
|
4223
|
+
//#region src/generators/cm99-generic-graphics/rectangle.ts
|
|
4224
|
+
const DEFAULT_GENERIC_RECTANGLE_OPTIONS = { filled: false };
|
|
4225
|
+
const GENERIC_RECTANGLE_METADATA = {
|
|
4226
|
+
id: "rectangle",
|
|
4227
|
+
name: "Rectangle",
|
|
4228
|
+
description: "A non-doctrinal oriented rectangle defined by three adjacent corners.",
|
|
4229
|
+
entity: "Generic Graphics",
|
|
4230
|
+
entityType: "Basic Shape",
|
|
4231
|
+
entitySubtype: "Rectangle",
|
|
4232
|
+
value: "990103",
|
|
4233
|
+
minCoordinates: 3,
|
|
4234
|
+
maxCoordinates: 3,
|
|
4235
|
+
geometry: "area",
|
|
4236
|
+
geometryTypes: ["Polygon"],
|
|
4237
|
+
drawRule: "Rectangle",
|
|
4238
|
+
params: FILLED_AREA_PARAMS
|
|
4239
|
+
};
|
|
4240
|
+
function createGenericRectangle(coordinates, options = {}) {
|
|
4241
|
+
const [c1, c2, c3] = rectangleDrawRule.derive(coordinates);
|
|
4242
|
+
if (!c1 || !c2 || !c3) return {
|
|
4243
|
+
type: "FeatureCollection",
|
|
4244
|
+
features: []
|
|
4245
|
+
};
|
|
4246
|
+
const p1 = project(c1[0], c1[1]);
|
|
4247
|
+
const p2 = project(c2[0], c2[1]);
|
|
4248
|
+
const p3 = project(c3[0], c3[1]);
|
|
4249
|
+
if (Math.hypot(p2[0] - p1[0], p2[1] - p1[1]) < 1e-6) return {
|
|
4250
|
+
type: "FeatureCollection",
|
|
4251
|
+
features: []
|
|
4252
|
+
};
|
|
4253
|
+
const fill = options.filled ?? DEFAULT_GENERIC_RECTANGLE_OPTIONS.filled;
|
|
4254
|
+
if (Math.hypot(p3[0] - p2[0], p3[1] - p2[1]) < 1e-6) return {
|
|
4255
|
+
type: "FeatureCollection",
|
|
4256
|
+
features: []
|
|
4257
|
+
};
|
|
4258
|
+
const ring = [
|
|
4259
|
+
p1,
|
|
4260
|
+
p2,
|
|
4261
|
+
p3,
|
|
4262
|
+
[p1[0] + p3[0] - p2[0], p1[1] + p3[1] - p2[1]],
|
|
4263
|
+
p1
|
|
4264
|
+
].map((point) => unproject(point[0], point[1]));
|
|
4265
|
+
return {
|
|
4266
|
+
type: "FeatureCollection",
|
|
4267
|
+
features: [{
|
|
4268
|
+
type: "Feature",
|
|
4269
|
+
properties: {
|
|
4270
|
+
part: "rectangle",
|
|
4271
|
+
fill
|
|
4272
|
+
},
|
|
4273
|
+
geometry: {
|
|
4274
|
+
type: "Polygon",
|
|
4275
|
+
coordinates: [ring]
|
|
4276
|
+
}
|
|
4277
|
+
}]
|
|
4278
|
+
};
|
|
4279
|
+
}
|
|
4280
|
+
const GENERIC_RECTANGLE = defineControlMeasure({
|
|
4281
|
+
metadata: GENERIC_RECTANGLE_METADATA,
|
|
4282
|
+
generator: createGenericRectangle,
|
|
4283
|
+
defaultOptions: DEFAULT_GENERIC_RECTANGLE_OPTIONS,
|
|
4284
|
+
rule: rectangleDrawRule,
|
|
4285
|
+
previewSample: { controlPoints: [
|
|
4286
|
+
[-.9, -.55],
|
|
4287
|
+
[.9, -.55],
|
|
4288
|
+
[.9, .55]
|
|
4289
|
+
] }
|
|
4290
|
+
});
|
|
4291
|
+
//#endregion
|
|
3908
4292
|
//#region src/generators/cm34-mission-tasks/clear.ts
|
|
3909
4293
|
/**
|
|
3910
4294
|
* Default options for the CLEAR symbol.
|
|
@@ -6248,11 +6632,11 @@ function buildStrongPointTics(perimeter, gaps, h) {
|
|
|
6248
6632
|
* @param options - {@link StrongPointOptions}.
|
|
6249
6633
|
*/
|
|
6250
6634
|
function createStrongPoint(positions, options = {}) {
|
|
6251
|
-
const { echelon = DEFAULT_STRONG_POINT_OPTIONS.echelon, echelonSize = DEFAULT_STRONG_POINT_OPTIONS.echelonSize, echelonSizePixels, echelonPadding = DEFAULT_STRONG_POINT_OPTIONS.echelonPadding, echelonPosition = DEFAULT_STRONG_POINT_OPTIONS.echelonPosition, metersPerPixel, smooth = DEFAULT_STRONG_POINT_OPTIONS.smooth, smoothResolution = DEFAULT_STRONG_POINT_OPTIONS.smoothResolution } = options;
|
|
6635
|
+
const { echelon = DEFAULT_STRONG_POINT_OPTIONS.echelon, echelonSize = DEFAULT_STRONG_POINT_OPTIONS.echelonSize, echelonSizePixels, echelonPadding = DEFAULT_STRONG_POINT_OPTIONS.echelonPadding, echelonPosition = DEFAULT_STRONG_POINT_OPTIONS.echelonPosition, echelonAnchor, metersPerPixel, smooth = DEFAULT_STRONG_POINT_OPTIONS.smooth, smoothResolution = DEFAULT_STRONG_POINT_OPTIONS.smoothResolution } = options;
|
|
6252
6636
|
const h = resolveEchelonHeight(echelonSize, echelonSizePixels, metersPerPixel);
|
|
6253
6637
|
const verts = buildClosedRing(positions, smooth, smoothResolution, DEFAULT_SMOOTH_RESOLUTION);
|
|
6254
6638
|
const perimeter = buildAreaPerimeter(verts);
|
|
6255
|
-
const { strokes, fills, gaps } = placeEchelon(perimeter, h, echelon, echelonPadding, echelonPosition);
|
|
6639
|
+
const { strokes, fills, gaps } = placeEchelon(perimeter, h, echelon, echelonPadding, echelonPosition, echelonAnchor);
|
|
6256
6640
|
const boundaryCoords = buildGappedLine(verts, gaps);
|
|
6257
6641
|
const tics = buildStrongPointTics(perimeter, gaps, h);
|
|
6258
6642
|
const features = [];
|
|
@@ -6301,6 +6685,7 @@ const STRONG_POINT = defineControlMeasure({
|
|
|
6301
6685
|
generator: createStrongPoint,
|
|
6302
6686
|
defaultOptions: DEFAULT_STRONG_POINT_OPTIONS,
|
|
6303
6687
|
rule: area1DrawRule,
|
|
6688
|
+
freezeOrientation: freezeEchelonAnchor,
|
|
6304
6689
|
previewSample: {
|
|
6305
6690
|
controlPoints: [
|
|
6306
6691
|
[-1, -.5],
|
|
@@ -6654,6 +7039,10 @@ const DEFINITIONS = {
|
|
|
6654
7039
|
"supporting-attack": SUPPORTING_ATTACK,
|
|
6655
7040
|
"classic-arrow": CLASSIC_ARROW,
|
|
6656
7041
|
"block-arrow": BLOCK_ARROW,
|
|
7042
|
+
line: GENERIC_LINE,
|
|
7043
|
+
polygon: GENERIC_POLYGON,
|
|
7044
|
+
rectangle: GENERIC_RECTANGLE,
|
|
7045
|
+
circle: GENERIC_CIRCLE,
|
|
6657
7046
|
"airborne-attack": AIRBORNE_ATTACK,
|
|
6658
7047
|
"attack-helicopter": ATTACK_HELICOPTER,
|
|
6659
7048
|
"support-by-fire": SUPPORT_BY_FIRE,
|
|
@@ -6904,4 +7293,4 @@ function assertNever(value) {
|
|
|
6904
7293
|
throw new Error(`Unhandled control measure kind: ${String(value)}`);
|
|
6905
7294
|
}
|
|
6906
7295
|
//#endregion
|
|
6907
|
-
export {
|
|
7296
|
+
export { point12DrawRule as $, DEFAULT_GENERIC_POLYGON_OPTIONS as A, DEFAULT_ANTITANK_WALL_OPTIONS as B, DEFAULT_FIX_OPTIONS as C, DEFAULT_DELAY_OPTIONS as D, DEFAULT_DISRUPT_OPTIONS as E, DEFAULT_BREACH_OPTIONS as F, axis1DrawRule as G, DEFAULT_AMBUSH_OPTIONS as H, DEFAULT_BLOCK_MISSION_TASK_OPTIONS as I, line23DrawRule as J, supportByFireDrawRule as K, DEFAULT_BLOCK_OPTIONS as L, DEFAULT_GENERIC_CIRCLE_OPTIONS as M, DEFAULT_CANALIZE_OPTIONS as N, DEFAULT_CLEAR_OPTIONS as O, DEFAULT_BYPASS_OPTIONS as P, attackByFireDrawRule as Q, DEFAULT_ATTACK_HELICOPTER_OPTIONS as R, DEFAULT_FLOT_OPTIONS as S, DEFAULT_ENCIRCLEMENT_OPTIONS as T, DEFAULT_AIRBORNE_ATTACK_OPTIONS as U, DEFAULT_ANTITANK_DITCH_OPTIONS as V, rectangleDrawRule as W, line1DrawRule as X, turnDrawRule as Y, ambushDrawRule as Z, DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS as _, DEFINITIONS as a, getMidpointPerpendicularSignedDistance as at, DEFAULT_FORTIFIED_AREA_OPTIONS as b, getDefaultOptions as c, createBaselineFrame as ct, DEFAULT_SUPPORTING_ATTACK_OPTIONS as d, project as dt, centerRadiusDrawRule as et, DEFAULT_SUPPORT_BY_FIRE_OPTIONS as f, unproject as ft, DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS as g, DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS as h, roundToFixed as ht, CONTROL_MEASURE_METADATA as i, createMidpointPerpendicularDrawRule as it, DEFAULT_GENERIC_LINE_OPTIONS as j, DEFAULT_GENERIC_RECTANGLE_OPTIONS as k, listControlMeasureMetadata as l, calculateMetrics as lt, DEFAULT_TACTICAL_ARROW_OPTIONS as m, getMetersPerPixel as mt, resolveStyleHints as n, blockDrawRule as nt, getControlMeasureMetadata as o, pointOnMidpointPerpendicularAxis as ot, DEFAULT_STRONG_POINT_OPTIONS as p, EPSILON as pt, line24DrawRule as q, CONTROL_MEASURE_IDS as r, computeDefaultMidpointPerpendicularPoint as rt, getControlMeasureMetadataByValue as s, snapToMidpointPerpendicular as st, renderControlMeasure as t, disruptDrawRule as tt, DEFAULT_TURN_OPTIONS as u, computeInitialWidthPoint as ut, DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS as v, DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS as w, DEFAULT_FORTIFIED_LINE_OPTIONS as x, DEFAULT_MAIN_ATTACK_OPTIONS as y, DEFAULT_ATTACK_BY_FIRE_OPTIONS as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbat-mapper/control-measures",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.6",
|
|
4
4
|
"description": "Library for drawing tactical graphics and control measures according to MIL-STD-2525 and APP-6 standards.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Orbat Mapper",
|