mirror of
https://github.com/valmojr/armatak.git
synced 2026-06-13 11:53:28 +00:00
[WIP] Adding Drawing Cursor Over Time functions
This commit is contained in:
@@ -19,6 +19,24 @@ class CfgFunctions {
|
||||
class send_marker_cot {
|
||||
file = "\armatak\armatak\addons\main\functions\api\fn_send_marker_cot.sqf";
|
||||
};
|
||||
class report_marker {
|
||||
file = "\armatak\armatak\addons\main\functions\api\fn_report_marker.sqf";
|
||||
};
|
||||
class draw_circle {
|
||||
file = "\armatak\armatak\addons\main\functions\api\fn_draw_circle.sqf";
|
||||
};
|
||||
class draw_ellipse {
|
||||
file = "\armatak\armatak\addons\main\functions\api\fn_draw_ellipse.sqf";
|
||||
};
|
||||
class draw_rectangle {
|
||||
file = "\armatak\armatak\addons\main\functions\api\fn_draw_rectangle.sqf";
|
||||
};
|
||||
class draw_polyline {
|
||||
file = "\armatak\armatak\addons\main\functions\api\fn_draw_polyline.sqf";
|
||||
};
|
||||
class draw_tactical_graphic {
|
||||
file = "\armatak\armatak\addons\main\functions\api\fn_draw_tactical_graphic.sqf";
|
||||
};
|
||||
class send_uas_platform_cot {
|
||||
file = "\armatak\armatak\addons\main\functions\api\fn_send_uas_platform_cot.sqf";
|
||||
};
|
||||
|
||||
41
addons/main/functions/api/fn_draw_circle.sqf
Normal file
41
addons/main/functions/api/fn_draw_circle.sqf
Normal file
@@ -0,0 +1,41 @@
|
||||
// function name: armatak_fnc_draw_circle
|
||||
// function author: Valmo
|
||||
// function description: Sends an ATAK Drawing Tools circle CoT.
|
||||
//
|
||||
// Arguments:
|
||||
// 0: Center position or object <ARRAY|OBJECT>
|
||||
// 1: Radius in meters <NUMBER>
|
||||
// 2: Callsign/title <STRING> (default: "ArmaTAK Circle")
|
||||
// 3: Stale time in seconds <NUMBER> (default: 86400)
|
||||
// 4: Stroke color as signed ARGB int <NUMBER> (default: -1)
|
||||
// 5: Fill color as signed ARGB int <NUMBER> (default: -1761607681)
|
||||
// 6: Stroke weight <NUMBER> (default: 3)
|
||||
//
|
||||
// Example:
|
||||
// [player, 300, "Mortar Risk Area"] call armatak_fnc_draw_circle;
|
||||
//
|
||||
// Public: Yes
|
||||
|
||||
params [
|
||||
["_center", objNull, [objNull, []]],
|
||||
["_radius", 100, [0]],
|
||||
["_callsign", "ArmaTAK Circle", [""]],
|
||||
["_staleSeconds", 86400, [0]],
|
||||
["_strokeColor", -1, [0]],
|
||||
["_fillColor", -1761607681, [0]],
|
||||
["_strokeWeight", 3, [0]]
|
||||
];
|
||||
|
||||
[
|
||||
_center,
|
||||
_radius,
|
||||
_radius,
|
||||
360,
|
||||
_callsign,
|
||||
_staleSeconds,
|
||||
_strokeColor,
|
||||
_fillColor,
|
||||
_strokeWeight,
|
||||
"",
|
||||
"u-d-c-c"
|
||||
] call armatak_fnc_draw_ellipse;
|
||||
65
addons/main/functions/api/fn_draw_ellipse.sqf
Normal file
65
addons/main/functions/api/fn_draw_ellipse.sqf
Normal file
@@ -0,0 +1,65 @@
|
||||
// function name: armatak_fnc_draw_ellipse
|
||||
// function author: Valmo
|
||||
// function description: Sends an ATAK Drawing Tools ellipse or circle CoT.
|
||||
//
|
||||
// Arguments:
|
||||
// 0: Center position or object <ARRAY|OBJECT>
|
||||
// 1: Major radius in meters <NUMBER>
|
||||
// 2: Minor radius in meters <NUMBER>
|
||||
// 3: Rotation angle in degrees <NUMBER> (default: 0)
|
||||
// 4: Callsign/title <STRING> (default: "ArmaTAK Ellipse")
|
||||
// 5: Stale time in seconds <NUMBER> (default: 86400)
|
||||
// 6: Stroke color as signed ARGB int <NUMBER> (default: -1)
|
||||
// 7: Fill color as signed ARGB int <NUMBER> (default: -1761607681)
|
||||
// 8: Stroke weight <NUMBER> (default: 3)
|
||||
// 9: MilSym SIDC for tactical overlay <STRING> (default: "")
|
||||
// 10: CoT type <STRING> (default: "u-d-c-e")
|
||||
//
|
||||
// Example:
|
||||
// [screenToWorld [0.5, 0.5], 250, 100, 45, "Support by Fire"] call armatak_fnc_draw_ellipse;
|
||||
//
|
||||
// Public: Yes
|
||||
|
||||
params [
|
||||
["_center", objNull, [objNull, []]],
|
||||
["_major", 100, [0]],
|
||||
["_minor", 50, [0]],
|
||||
["_angle", 0, [0]],
|
||||
["_callsign", "ArmaTAK Ellipse", [""]],
|
||||
["_staleSeconds", 86400, [0]],
|
||||
["_strokeColor", -1, [0]],
|
||||
["_fillColor", -1761607681, [0]],
|
||||
["_strokeWeight", 3, [0]],
|
||||
["_milsym", "", [""]],
|
||||
["_cotType", "u-d-c-e", [""]]
|
||||
];
|
||||
|
||||
private _position = if (_center isEqualType objNull) then {
|
||||
getPos _center
|
||||
} else {
|
||||
_center
|
||||
};
|
||||
|
||||
if ((count _position) < 2) exitWith {""};
|
||||
|
||||
private _altitude = _position param [2, 0, [0]];
|
||||
private _realLocation = [_position select 0, _position select 1, _altitude] call armatak_client_fnc_convertClientLocation;
|
||||
private _uuid = "armatak" callExtension ["uuid", []] select 0;
|
||||
private _payload = [
|
||||
_uuid,
|
||||
_cotType,
|
||||
_realLocation select 0,
|
||||
_realLocation select 1,
|
||||
_realLocation select 2,
|
||||
_major max 1,
|
||||
_minor max 1,
|
||||
_angle,
|
||||
_callsign,
|
||||
_staleSeconds max 1,
|
||||
_strokeColor,
|
||||
_fillColor,
|
||||
_strokeWeight max 1,
|
||||
_milsym
|
||||
];
|
||||
|
||||
"armatak" callExtension ["tcp_socket:draw:ellipse", [_payload]];
|
||||
78
addons/main/functions/api/fn_draw_polyline.sqf
Normal file
78
addons/main/functions/api/fn_draw_polyline.sqf
Normal file
@@ -0,0 +1,78 @@
|
||||
// function name: armatak_fnc_draw_polyline
|
||||
// function author: Valmo
|
||||
// function description: Sends an ATAK Drawing Tools freeform line or polygon CoT.
|
||||
//
|
||||
// Arguments:
|
||||
// 0: Positions or objects <ARRAY>
|
||||
// 1: Callsign/title <STRING> (default: "ArmaTAK Line")
|
||||
// 2: Closed polygon <BOOL> (default: false)
|
||||
// 3: Stale time in seconds <NUMBER> (default: 86400)
|
||||
// 4: Stroke color as signed ARGB int <NUMBER> (default: -1)
|
||||
// 5: Fill color as signed ARGB int <NUMBER> (default: -1761607681)
|
||||
// 6: Stroke weight <NUMBER> (default: 3)
|
||||
// 7: Stroke style <STRING> (default: "solid")
|
||||
// 8: MilSym SIDC for tactical overlay <STRING> (default: "")
|
||||
// 9: CoT type <STRING> (default: "u-d-f")
|
||||
//
|
||||
// Example:
|
||||
// [[pos player, screenToWorld [0.5, 0.5]], "Phase Line Blue"] call armatak_fnc_draw_polyline;
|
||||
//
|
||||
// Public: Yes
|
||||
|
||||
params [
|
||||
["_points", [], [[]]],
|
||||
["_callsign", "ArmaTAK Line", [""]],
|
||||
["_closed", false, [true]],
|
||||
["_staleSeconds", 86400, [0]],
|
||||
["_strokeColor", -1, [0]],
|
||||
["_fillColor", -1761607681, [0]],
|
||||
["_strokeWeight", 3, [0]],
|
||||
["_strokeStyle", "solid", [""]],
|
||||
["_milsym", "", [""]],
|
||||
["_cotType", "u-d-f", [""]]
|
||||
];
|
||||
|
||||
if ((count _points) < 2) exitWith {""};
|
||||
|
||||
private _pointStrings = [];
|
||||
private _center = [];
|
||||
|
||||
{
|
||||
private _position = if (_x isEqualType objNull) then {
|
||||
getPos _x
|
||||
} else {
|
||||
_x
|
||||
};
|
||||
|
||||
if ((count _position) >= 2) then {
|
||||
private _altitude = _position param [2, 0, [0]];
|
||||
private _realLocation = [_position select 0, _position select 1, _altitude] call armatak_client_fnc_convertClientLocation;
|
||||
_pointStrings pushBack format ["%1,%2,%3", _realLocation select 0, _realLocation select 1, _realLocation select 2];
|
||||
|
||||
if (_center isEqualTo []) then {
|
||||
_center = _realLocation;
|
||||
};
|
||||
};
|
||||
} forEach _points;
|
||||
|
||||
if ((count _pointStrings) < 2) exitWith {""};
|
||||
|
||||
private _uuid = "armatak" callExtension ["uuid", []] select 0;
|
||||
private _payload = [
|
||||
_uuid,
|
||||
_cotType,
|
||||
_center select 0,
|
||||
_center select 1,
|
||||
_center select 2,
|
||||
_pointStrings joinString ";",
|
||||
_callsign,
|
||||
_staleSeconds max 1,
|
||||
_strokeColor,
|
||||
_fillColor,
|
||||
_strokeWeight max 1,
|
||||
_strokeStyle,
|
||||
_closed,
|
||||
_milsym
|
||||
];
|
||||
|
||||
"armatak" callExtension ["tcp_socket:draw:free", [_payload]];
|
||||
89
addons/main/functions/api/fn_draw_rectangle.sqf
Normal file
89
addons/main/functions/api/fn_draw_rectangle.sqf
Normal file
@@ -0,0 +1,89 @@
|
||||
// function name: armatak_fnc_draw_rectangle
|
||||
// function author: Valmo
|
||||
// function description: Sends an ATAK Drawing Tools rectangle CoT from an Arma center, width, length, and bearing.
|
||||
//
|
||||
// Arguments:
|
||||
// 0: Center position or object <ARRAY|OBJECT>
|
||||
// 1: Width in meters <NUMBER>
|
||||
// 2: Length in meters <NUMBER>
|
||||
// 3: Bearing in degrees <NUMBER> (default: 0)
|
||||
// 4: Callsign/title <STRING> (default: "ArmaTAK Rectangle")
|
||||
// 5: Stale time in seconds <NUMBER> (default: 86400)
|
||||
// 6: Stroke color as signed ARGB int <NUMBER> (default: -1)
|
||||
// 7: Fill color as signed ARGB int <NUMBER> (default: -1761607681)
|
||||
// 8: Stroke weight <NUMBER> (default: 3)
|
||||
// 9: MilSym SIDC for tactical overlay <STRING> (default: "")
|
||||
//
|
||||
// Example:
|
||||
// [screenToWorld [0.5, 0.5], 200, 500, 30, "Engagement Area"] call armatak_fnc_draw_rectangle;
|
||||
//
|
||||
// Public: Yes
|
||||
|
||||
params [
|
||||
["_center", objNull, [objNull, []]],
|
||||
["_width", 100, [0]],
|
||||
["_length", 100, [0]],
|
||||
["_bearing", 0, [0]],
|
||||
["_callsign", "ArmaTAK Rectangle", [""]],
|
||||
["_staleSeconds", 86400, [0]],
|
||||
["_strokeColor", -1, [0]],
|
||||
["_fillColor", -1761607681, [0]],
|
||||
["_strokeWeight", 3, [0]],
|
||||
["_milsym", "", [""]]
|
||||
];
|
||||
|
||||
private _centerPos = if (_center isEqualType objNull) then {
|
||||
getPos _center
|
||||
} else {
|
||||
_center
|
||||
};
|
||||
|
||||
if ((count _centerPos) < 2) exitWith {""};
|
||||
|
||||
private _altitude = _centerPos param [2, 0, [0]];
|
||||
private _halfWidth = (_width max 1) / 2;
|
||||
private _halfLength = (_length max 1) / 2;
|
||||
private _sin = sin _bearing;
|
||||
private _cos = cos _bearing;
|
||||
private _forward = [_sin, _cos, 0];
|
||||
private _right = [_cos, -_sin, 0];
|
||||
private _offsets = [
|
||||
[(_right vectorMultiply -_halfWidth), (_forward vectorMultiply _halfLength)],
|
||||
[(_right vectorMultiply _halfWidth), (_forward vectorMultiply _halfLength)],
|
||||
[(_right vectorMultiply _halfWidth), (_forward vectorMultiply -_halfLength)],
|
||||
[(_right vectorMultiply -_halfWidth), (_forward vectorMultiply -_halfLength)]
|
||||
];
|
||||
private _points = [];
|
||||
|
||||
{
|
||||
private _offset = (_x select 0) vectorAdd (_x select 1);
|
||||
_points pushBack ([_centerPos select 0, _centerPos select 1, _altitude] vectorAdd _offset);
|
||||
} forEach _offsets;
|
||||
|
||||
private _centerReal = [_centerPos select 0, _centerPos select 1, _altitude] call armatak_client_fnc_convertClientLocation;
|
||||
private _pointStrings = [];
|
||||
|
||||
{
|
||||
private _realLocation = [_x select 0, _x select 1, _x select 2] call armatak_client_fnc_convertClientLocation;
|
||||
_pointStrings pushBack format ["%1,%2,%3", _realLocation select 0, _realLocation select 1, _realLocation select 2];
|
||||
} forEach _points;
|
||||
|
||||
private _uuid = "armatak" callExtension ["uuid", []] select 0;
|
||||
private _payload = [
|
||||
_uuid,
|
||||
"u-d-r",
|
||||
_centerReal select 0,
|
||||
_centerReal select 1,
|
||||
_centerReal select 2,
|
||||
_pointStrings joinString ";",
|
||||
_callsign,
|
||||
_staleSeconds max 1,
|
||||
_strokeColor,
|
||||
_fillColor,
|
||||
_strokeWeight max 1,
|
||||
"solid",
|
||||
false,
|
||||
_milsym
|
||||
];
|
||||
|
||||
"armatak" callExtension ["tcp_socket:draw:rectangle", [_payload]];
|
||||
75
addons/main/functions/api/fn_draw_tactical_graphic.sqf
Normal file
75
addons/main/functions/api/fn_draw_tactical_graphic.sqf
Normal file
@@ -0,0 +1,75 @@
|
||||
// function name: armatak_fnc_draw_tactical_graphic
|
||||
// function author: Valmo
|
||||
// function description: Sends an ATAK Drawing Tools shape with a MilSym tactical graphic overlay.
|
||||
//
|
||||
// Arguments:
|
||||
// 0: Positions or objects <ARRAY>
|
||||
// 1: MilSym SIDC <STRING>
|
||||
// 2: Callsign/title <STRING> (default: "ArmaTAK Tactical Graphic")
|
||||
// 3: Closed polygon <BOOL> (default: false)
|
||||
// 4: Stale time in seconds <NUMBER> (default: 86400)
|
||||
// 5: Stroke color as signed ARGB int <NUMBER> (default: -1)
|
||||
// 6: Fill color as signed ARGB int <NUMBER> (default: -1761607681)
|
||||
// 7: Stroke weight <NUMBER> (default: 3)
|
||||
//
|
||||
// Example:
|
||||
// [[pos player, screenToWorld [0.5, 0.5]], "GFGPOLAGM-----X", "Axis of Advance"] call armatak_fnc_draw_tactical_graphic;
|
||||
//
|
||||
// Public: Yes
|
||||
|
||||
params [
|
||||
["_points", [], [[]]],
|
||||
["_milsym", "", [""]],
|
||||
["_callsign", "ArmaTAK Tactical Graphic", [""]],
|
||||
["_closed", false, [true]],
|
||||
["_staleSeconds", 86400, [0]],
|
||||
["_strokeColor", -1, [0]],
|
||||
["_fillColor", -1761607681, [0]],
|
||||
["_strokeWeight", 3, [0]]
|
||||
];
|
||||
|
||||
if (_milsym isEqualTo "") exitWith {""};
|
||||
if ((count _points) < 2) exitWith {""};
|
||||
|
||||
private _pointStrings = [];
|
||||
private _center = [];
|
||||
|
||||
{
|
||||
private _position = if (_x isEqualType objNull) then {
|
||||
getPos _x
|
||||
} else {
|
||||
_x
|
||||
};
|
||||
|
||||
if ((count _position) >= 2) then {
|
||||
private _altitude = _position param [2, 0, [0]];
|
||||
private _realLocation = [_position select 0, _position select 1, _altitude] call armatak_client_fnc_convertClientLocation;
|
||||
_pointStrings pushBack format ["%1,%2,%3", _realLocation select 0, _realLocation select 1, _realLocation select 2];
|
||||
|
||||
if (_center isEqualTo []) then {
|
||||
_center = _realLocation;
|
||||
};
|
||||
};
|
||||
} forEach _points;
|
||||
|
||||
if ((count _pointStrings) < 2) exitWith {""};
|
||||
|
||||
private _uuid = "armatak" callExtension ["uuid", []] select 0;
|
||||
private _payload = [
|
||||
_uuid,
|
||||
"u-d-f",
|
||||
_center select 0,
|
||||
_center select 1,
|
||||
_center select 2,
|
||||
_pointStrings joinString ";",
|
||||
_callsign,
|
||||
_staleSeconds max 1,
|
||||
_strokeColor,
|
||||
_fillColor,
|
||||
_strokeWeight max 1,
|
||||
"solid",
|
||||
_closed,
|
||||
_milsym
|
||||
];
|
||||
|
||||
"armatak" callExtension ["tcp_socket:draw:vector", [_payload]];
|
||||
@@ -1 +1,2 @@
|
||||
pub mod circle;
|
||||
pub mod shape;
|
||||
|
||||
317
src/cot/draws/shape.rs
Normal file
317
src/cot/draws/shape.rs
Normal file
@@ -0,0 +1,317 @@
|
||||
use arma_rs::{FromArma, FromArmaError};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct DrawPoint {
|
||||
lat: f64,
|
||||
lon: f64,
|
||||
hae: f32,
|
||||
}
|
||||
|
||||
pub struct DrawEllipsePayload {
|
||||
pub uuid: String,
|
||||
pub cot_type: String,
|
||||
pub center_lat: f64,
|
||||
pub center_lon: f64,
|
||||
pub center_hae: f32,
|
||||
pub major: f64,
|
||||
pub minor: f64,
|
||||
pub angle: f32,
|
||||
pub callsign: String,
|
||||
pub stale_seconds: i64,
|
||||
pub stroke_color: i32,
|
||||
pub fill_color: i32,
|
||||
pub stroke_weight: f64,
|
||||
pub milsym: String,
|
||||
}
|
||||
|
||||
pub struct DrawLinksPayload {
|
||||
pub uuid: String,
|
||||
pub cot_type: String,
|
||||
pub center_lat: f64,
|
||||
pub center_lon: f64,
|
||||
pub center_hae: f32,
|
||||
pub points: String,
|
||||
pub callsign: String,
|
||||
pub stale_seconds: i64,
|
||||
pub stroke_color: i32,
|
||||
pub fill_color: i32,
|
||||
pub stroke_weight: f64,
|
||||
pub stroke_style: String,
|
||||
pub closed: bool,
|
||||
pub milsym: String,
|
||||
}
|
||||
|
||||
impl FromArma for DrawEllipsePayload {
|
||||
fn from_arma(data: String) -> Result<Self, FromArmaError> {
|
||||
let (
|
||||
uuid,
|
||||
cot_type,
|
||||
center_lat,
|
||||
center_lon,
|
||||
center_hae,
|
||||
major,
|
||||
minor,
|
||||
angle,
|
||||
callsign,
|
||||
stale_seconds,
|
||||
stroke_color,
|
||||
fill_color,
|
||||
stroke_weight,
|
||||
milsym,
|
||||
) = <(
|
||||
String,
|
||||
String,
|
||||
f64,
|
||||
f64,
|
||||
f32,
|
||||
f64,
|
||||
f64,
|
||||
f32,
|
||||
String,
|
||||
i64,
|
||||
i32,
|
||||
i32,
|
||||
f64,
|
||||
String,
|
||||
)>::from_arma(data)?;
|
||||
|
||||
Ok(Self {
|
||||
uuid,
|
||||
cot_type,
|
||||
center_lat,
|
||||
center_lon,
|
||||
center_hae,
|
||||
major,
|
||||
minor,
|
||||
angle,
|
||||
callsign,
|
||||
stale_seconds,
|
||||
stroke_color,
|
||||
fill_color,
|
||||
stroke_weight,
|
||||
milsym,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FromArma for DrawLinksPayload {
|
||||
fn from_arma(data: String) -> Result<Self, FromArmaError> {
|
||||
let (
|
||||
uuid,
|
||||
cot_type,
|
||||
center_lat,
|
||||
center_lon,
|
||||
center_hae,
|
||||
points,
|
||||
callsign,
|
||||
stale_seconds,
|
||||
stroke_color,
|
||||
fill_color,
|
||||
stroke_weight,
|
||||
stroke_style,
|
||||
closed,
|
||||
milsym,
|
||||
) = <(
|
||||
String,
|
||||
String,
|
||||
f64,
|
||||
f64,
|
||||
f32,
|
||||
String,
|
||||
String,
|
||||
i64,
|
||||
i32,
|
||||
i32,
|
||||
f64,
|
||||
String,
|
||||
bool,
|
||||
String,
|
||||
)>::from_arma(data)?;
|
||||
|
||||
Ok(Self {
|
||||
uuid,
|
||||
cot_type,
|
||||
center_lat,
|
||||
center_lon,
|
||||
center_hae,
|
||||
points,
|
||||
callsign,
|
||||
stale_seconds,
|
||||
stroke_color,
|
||||
fill_color,
|
||||
stroke_weight,
|
||||
stroke_style,
|
||||
closed,
|
||||
milsym,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawEllipsePayload {
|
||||
pub fn to_xml(&self, now: &str, stale: &str) -> String {
|
||||
shape_event(
|
||||
&self.uuid,
|
||||
&self.cot_type,
|
||||
self.center_lat,
|
||||
self.center_lon,
|
||||
self.center_hae,
|
||||
now,
|
||||
stale,
|
||||
&self.callsign,
|
||||
&ellipse_shape_detail(
|
||||
&self.uuid,
|
||||
self.major,
|
||||
self.minor,
|
||||
self.angle,
|
||||
self.stroke_color,
|
||||
self.fill_color,
|
||||
self.stroke_weight,
|
||||
),
|
||||
self.stroke_color,
|
||||
self.fill_color,
|
||||
self.stroke_weight,
|
||||
"solid",
|
||||
&self.milsym,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawLinksPayload {
|
||||
pub fn to_xml(&self, now: &str, stale: &str) -> String {
|
||||
let points = parse_points(&self.points);
|
||||
let shape_detail = links_detail(&points, self.closed);
|
||||
|
||||
shape_event(
|
||||
&self.uuid,
|
||||
&self.cot_type,
|
||||
self.center_lat,
|
||||
self.center_lon,
|
||||
self.center_hae,
|
||||
now,
|
||||
stale,
|
||||
&self.callsign,
|
||||
&shape_detail,
|
||||
self.stroke_color,
|
||||
self.fill_color,
|
||||
self.stroke_weight,
|
||||
&self.stroke_style,
|
||||
&self.milsym,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn shape_event(
|
||||
uid: &str,
|
||||
cot_type: &str,
|
||||
lat: f64,
|
||||
lon: f64,
|
||||
hae: f32,
|
||||
now: &str,
|
||||
stale: &str,
|
||||
callsign: &str,
|
||||
shape_detail: &str,
|
||||
stroke_color: i32,
|
||||
fill_color: i32,
|
||||
stroke_weight: f64,
|
||||
stroke_style: &str,
|
||||
milsym: &str,
|
||||
) -> String {
|
||||
let milsym_detail = if milsym.trim().is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!(r#"<__milsym id="{}" />"#, escape_attr(milsym))
|
||||
};
|
||||
|
||||
format!(
|
||||
r#"<?xml version="1.0" encoding="UTF-8" ?><event version="2.0" uid="{uid}" type="{cot_type}" time="{now}" start="{now}" stale="{stale}" how="h-e" access="Undefined"><point lat="{lat}" lon="{lon}" hae="{hae}" ce="10.9" le="9999999.0" /><detail>{shape_detail}<__shapeExtras cpvis="true" editable="true" /><contact callsign="{callsign}" /><remarks /><archive /><labels_on value="true" /><strokeColor value="{stroke_color}" /><strokeWeight value="{stroke_weight}" /><strokeStyle value="{stroke_style}" /><fillColor value="{fill_color}" /><precisionlocation altsrc="GPS" geopointsrc="GPS" />{milsym_detail}</detail></event>"#,
|
||||
uid = escape_attr(uid),
|
||||
cot_type = escape_attr(cot_type),
|
||||
now = now,
|
||||
stale = stale,
|
||||
lat = lat,
|
||||
lon = lon,
|
||||
hae = hae,
|
||||
shape_detail = shape_detail,
|
||||
callsign = escape_attr(callsign),
|
||||
stroke_color = stroke_color,
|
||||
stroke_weight = stroke_weight,
|
||||
stroke_style = escape_attr(stroke_style),
|
||||
fill_color = fill_color,
|
||||
milsym_detail = milsym_detail
|
||||
)
|
||||
}
|
||||
|
||||
fn ellipse_shape_detail(
|
||||
uid: &str,
|
||||
major: f64,
|
||||
minor: f64,
|
||||
angle: f32,
|
||||
stroke_color: i32,
|
||||
fill_color: i32,
|
||||
stroke_weight: f64,
|
||||
) -> String {
|
||||
format!(
|
||||
r#"<shape><ellipse major="{major}" minor="{minor}" angle="{angle}" /><link uid="{style_uid}" type="b-x-KmlStyle" relation="p-c"><Style><LineStyle><color>{stroke_hex}</color><width>{stroke_weight}</width></LineStyle><PolyStyle><color>{fill_hex}</color></PolyStyle></Style></link></shape>"#,
|
||||
major = major,
|
||||
minor = minor,
|
||||
angle = angle,
|
||||
style_uid = escape_attr(&format!("{}.Style", uid)),
|
||||
stroke_hex = argb_hex(stroke_color),
|
||||
stroke_weight = stroke_weight,
|
||||
fill_hex = argb_hex(fill_color)
|
||||
)
|
||||
}
|
||||
|
||||
fn links_detail(points: &[DrawPoint], closed: bool) -> String {
|
||||
let mut detail = String::new();
|
||||
|
||||
for point in points {
|
||||
detail.push_str(&link_detail(point));
|
||||
}
|
||||
|
||||
if closed {
|
||||
if let Some(first) = points.first() {
|
||||
detail.push_str(&link_detail(first));
|
||||
}
|
||||
}
|
||||
|
||||
detail
|
||||
}
|
||||
|
||||
fn link_detail(point: &DrawPoint) -> String {
|
||||
format!(
|
||||
r#"<link point="{lat},{lon},{hae}" />"#,
|
||||
lat = point.lat,
|
||||
lon = point.lon,
|
||||
hae = point.hae
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_points(raw: &str) -> Vec<DrawPoint> {
|
||||
raw.split(';')
|
||||
.filter_map(|entry| {
|
||||
let parts: Vec<_> = entry.split(',').collect();
|
||||
if parts.len() != 3 {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(DrawPoint {
|
||||
lat: parts[0].parse().ok()?,
|
||||
lon: parts[1].parse().ok()?,
|
||||
hae: parts[2].parse().ok()?,
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn argb_hex(color: i32) -> String {
|
||||
format!("{:08x}", color as u32)
|
||||
}
|
||||
|
||||
fn escape_attr(value: &str) -> String {
|
||||
value
|
||||
.replace('&', "&")
|
||||
.replace('"', """)
|
||||
.replace('<', "<")
|
||||
.replace('>', ">")
|
||||
}
|
||||
@@ -19,6 +19,16 @@ pub fn send_marker_cot(
|
||||
"Sending Marker Cursor Over Time to TCP server"
|
||||
}
|
||||
|
||||
pub fn send_report_marker_cot(
|
||||
ctx: Context,
|
||||
cursor_over_time: cot::report_marker::ReportMarkerCoTPayload,
|
||||
) -> &'static str {
|
||||
let payload = cursor_over_time.to_cot().convert_to_xml();
|
||||
send_payload(ctx, payload);
|
||||
|
||||
"Sending Report Marker Cursor Over Time to TCP server"
|
||||
}
|
||||
|
||||
pub fn send_digital_pointer_cot(
|
||||
ctx: Context,
|
||||
cursor_over_time: cot::digital_pointer::DigitalPointerPayload,
|
||||
|
||||
@@ -2,36 +2,72 @@ use arma_rs::Context;
|
||||
|
||||
use crate::{cot, tcp::send_payload};
|
||||
|
||||
fn day_stale() -> (String, String) {
|
||||
let now = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Millis, true);
|
||||
let stale = (chrono::Utc::now() + chrono::Duration::days(1))
|
||||
.to_rfc3339_opts(chrono::SecondsFormat::Millis, true);
|
||||
(now, stale)
|
||||
}
|
||||
|
||||
fn payload_stale(stale_seconds: i64) -> (String, String) {
|
||||
let now = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Millis, true);
|
||||
let stale = (chrono::Utc::now() + chrono::Duration::seconds(stale_seconds.max(1)))
|
||||
.to_rfc3339_opts(chrono::SecondsFormat::Millis, true);
|
||||
(now, stale)
|
||||
}
|
||||
|
||||
pub fn send_circle_cot(
|
||||
ctx: Context,
|
||||
circle_payload: cot::draws::circle::CircleCoTPayload,
|
||||
) -> &'static str {
|
||||
let shape_circle_cot = circle_payload.to_cot();
|
||||
let now = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Millis, true);
|
||||
let stale = (chrono::Utc::now() + chrono::Duration::days(1))
|
||||
.to_rfc3339_opts(chrono::SecondsFormat::Millis, true);
|
||||
let (now, stale) = day_stale();
|
||||
let payload = shape_circle_cot.to_xml(&now, &stale);
|
||||
send_payload(ctx, payload);
|
||||
|
||||
"Sending Circle CoT to TCP server"
|
||||
}
|
||||
|
||||
pub fn send_ellipse_cot(ctx: Context) -> &'static str {
|
||||
let _ = ctx;
|
||||
"Not implemented: send_ellipse_cot"
|
||||
pub fn send_ellipse_cot(
|
||||
ctx: Context,
|
||||
ellipse_payload: cot::draws::shape::DrawEllipsePayload,
|
||||
) -> &'static str {
|
||||
let (now, stale) = payload_stale(ellipse_payload.stale_seconds);
|
||||
let payload = ellipse_payload.to_xml(&now, &stale);
|
||||
send_payload(ctx, payload);
|
||||
|
||||
"Sending Ellipse CoT to TCP server"
|
||||
}
|
||||
|
||||
pub fn send_rectangle_cot(ctx: Context) -> &'static str {
|
||||
let _ = ctx;
|
||||
"Not implemented: send_ellipse_cot"
|
||||
pub fn send_rectangle_cot(
|
||||
ctx: Context,
|
||||
rectangle_payload: cot::draws::shape::DrawLinksPayload,
|
||||
) -> &'static str {
|
||||
let (now, stale) = payload_stale(rectangle_payload.stale_seconds);
|
||||
let payload = rectangle_payload.to_xml(&now, &stale);
|
||||
send_payload(ctx, payload);
|
||||
|
||||
"Sending Rectangle CoT to TCP server"
|
||||
}
|
||||
|
||||
pub fn send_freedraw_cot(ctx: Context) -> &'static str {
|
||||
let _ = ctx;
|
||||
"Not implemented: send_ellipse_cot"
|
||||
pub fn send_freedraw_cot(
|
||||
ctx: Context,
|
||||
freedraw_payload: cot::draws::shape::DrawLinksPayload,
|
||||
) -> &'static str {
|
||||
let (now, stale) = payload_stale(freedraw_payload.stale_seconds);
|
||||
let payload = freedraw_payload.to_xml(&now, &stale);
|
||||
send_payload(ctx, payload);
|
||||
|
||||
"Sending Free Draw CoT to TCP server"
|
||||
}
|
||||
|
||||
pub fn send_vectordraw_cot(ctx: Context) -> &'static str {
|
||||
let _ = ctx;
|
||||
"Not implemented: send_ellipse_cot"
|
||||
pub fn send_vectordraw_cot(
|
||||
ctx: Context,
|
||||
vector_payload: cot::draws::shape::DrawLinksPayload,
|
||||
) -> &'static str {
|
||||
let (now, stale) = payload_stale(vector_payload.stale_seconds);
|
||||
let payload = vector_payload.to_xml(&now, &stale);
|
||||
send_payload(ctx, payload);
|
||||
|
||||
"Sending Tactical Graphic CoT to TCP server"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user