public override void Execute(SharedObjects shared) { double longitude = GetDouble(shared.Cpu.PopValue()); double latitude = GetDouble(shared.Cpu.PopValue()); GeoCoordinates result = new GeoCoordinates(shared.Vessel, latitude, longitude); shared.Cpu.PushStack(result); }
private bool TryParseFunction(string text) { Match match; bool result; foreach(kOSExternalFunction f in executionContext.ExternalFunctions) { match = Regex.Match(text, f.regex, RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, f.regex, RegexOptions.IgnoreCase); string[] pArr = new string[f.ParameterCount]; for (var i = 0; i < f.ParameterCount; i++) { pArr[i] = ParseSubExpressionAsString(match.Groups[i + 1].Value); } Value = executionContext.CallExternalFunction(f.Name, pArr); }; EvalDlg(); return true; } } #region TRIG // Basic result = TryParseNumericFunction("SIN_(1)", text, delegate(double[] parameters) { Value = (float)Math.Sin(parameters[0] * (Math.PI / 180)); }); if (result) return true; result = TryParseNumericFunction("COS_(1)", text, delegate(double[] parameters) { Value = (float)Math.Cos(parameters[0] * (Math.PI / 180)); }); if (result) return true; result = TryParseNumericFunction("TAN_(1)", text, delegate(double[] parameters) { Value = (float)Math.Tan(parameters[0] * (Math.PI / 180)); }); if (result) return true; // Inverse result = TryParseNumericFunction("ARCSIN_(1)", text, delegate(double[] parameters) { Value = (float)(Math.Asin(parameters[0]) * (180 / Math.PI)); }); if (result) return true; result = TryParseNumericFunction("ARCCOS_(1)", text, delegate(double[] parameters) { Value = (float)(Math.Acos(parameters[0]) * (180 / Math.PI)); }); if (result) return true; result = TryParseNumericFunction("ARCTAN_(1)", text, delegate(double[] parameters) { Value = (float)Math.Atan(parameters[0] * (180 / Math.PI)); }); if (result) return true; result = TryParseNumericFunction("ARCTAN2_(2)", text, delegate(double[] parameters) { Value = (float)Math.Atan2(parameters[0] * (180 / Math.PI), parameters[1] * (180 / Math.PI)); }); if (result) return true; /* string regexSin = Utils.BuildRegex("SIN_(1)"); match = Regex.Match(text, regexSin, RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, regexSin, RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)Math.Sin(v * (Math.PI / 180)); }; EvalDlg(); return true; } string regexCos = Utils.BuildRegex("COS_(1)"); match = Regex.Match(text, regexCos, RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, regexCos, RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)Math.Cos(v * (Math.PI / 180)); }; EvalDlg(); return true; } string regexTan = Utils.BuildRegex("TAN_(1)"); match = Regex.Match(text, regexTan, RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, regexTan, RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)Math.Tan(v * (Math.PI / 180)); }; EvalDlg(); return true; } string regexASin = Utils.BuildRegex("ARCSIN_(1)"); match = Regex.Match(text, regexASin, RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, regexASin, RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)(Math.Asin(v) * (180 / Math.PI)); }; EvalDlg(); return true; } string regexACos = Utils.BuildRegex("ARCCOS_(1)"); match = Regex.Match(text, regexACos, RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, regexACos, RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)(Math.Acos(v) * (180 / Math.PI)); }; EvalDlg(); return true; } string regexATan = Utils.BuildRegex("ARCTAN_(1)"); match = Regex.Match(text, regexATan, RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, regexATan, RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)(Math.Atan(v) * (180 / Math.PI)); }; EvalDlg(); return true; } string regexATan2 = Utils.BuildRegex("ARCTAN2_(2)"); match = Regex.Match(text, regexATan2, RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, regexATan2, RegexOptions.IgnoreCase); double x = ParseSubExpressionAsDouble(match.Groups[1].Value); double y = ParseSubExpressionAsDouble(match.Groups[2].Value); Value = (float)(Math.Atan2(x, y) * (180 / Math.PI)); }; EvalDlg(); return true; }*/ #endregion #region ABS match = Regex.Match(text, "^ABS\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^ABS\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)Math.Abs(v); }; EvalDlg(); return true; } #endregion #region Geospatial match = Regex.Match(text, "^LATLNG ?\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^LATLNG ?\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double lat = ParseSubExpressionAsDouble(match.Groups[1].Value); double lng = ParseSubExpressionAsDouble(match.Groups[2].Value); Value = new GeoCoordinates(executionContext.Vessel, lat, lng); }; EvalDlg(); return true; } #endregion #region Vectors & Rotations match = Regex.Match(text, "^V\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^V\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double x = ParseSubExpressionAsDouble(match.Groups[1].Value); double y = ParseSubExpressionAsDouble(match.Groups[2].Value); double z = ParseSubExpressionAsDouble(match.Groups[3].Value); Value = new Vector(x,y,z); }; EvalDlg(); return true; } match = Regex.Match(text, "^R\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^R\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double x = ParseSubExpressionAsDouble(match.Groups[1].Value); double y = ParseSubExpressionAsDouble(match.Groups[2].Value); double z = ParseSubExpressionAsDouble(match.Groups[3].Value); Value = new Direction(new Vector3d(x, y, z), true); }; EvalDlg(); return true; } match = Regex.Match(text, "^Q\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^Q\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); float x = (float)ParseSubExpressionAsDouble(match.Groups[1].Value); float y = (float)ParseSubExpressionAsDouble(match.Groups[2].Value); float z = (float)ParseSubExpressionAsDouble(match.Groups[3].Value); float w = (float)ParseSubExpressionAsDouble(match.Groups[4].Value); Value = x + " " + y + " " + z + " " + w; }; EvalDlg(); return true; } match = Regex.Match(text, "^HEADING ?([ :@A-Za-z0-9\\.\\-\\+\\*/]+) BY ([ :@A-Za-z0-9\\.\\-\\+\\*/]+)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^HEADING ?([ :@A-Za-z0-9\\.\\-\\+\\*/]+) BY ([ :@A-Za-z0-9\\.\\-\\+\\*/]+)$", RegexOptions.IgnoreCase); float heading = (float)ParseSubExpressionAsDouble(match.Groups[1].Value); float pitch = (float)ParseSubExpressionAsDouble(match.Groups[2].Value); var q = UnityEngine.Quaternion.LookRotation(VesselUtils.GetNorthVector(executionContext.Vessel), executionContext.Vessel.upAxis); q *= UnityEngine.Quaternion.Euler(new UnityEngine.Vector3(-pitch, heading, 0)); Value = new Direction(q); }; EvalDlg(); return true; } #endregion return false; }
private bool TryParseFunction(string text) { Match match; bool result; foreach(kOSExternalFunction f in executionContext.ExternalFunctions) { match = Regex.Match(text, f.regex, RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, f.regex, RegexOptions.IgnoreCase); string[] pArr = new string[f.ParameterCount]; for (var i = 0; i < f.ParameterCount; i++) { pArr[i] = ParseSubExpressionAsString(match.Groups[i + 1].Value); } Value = executionContext.CallExternalFunction(f.Name, pArr); }; EvalDlg(); return true; } } #region TRIG // Basic result = TryParseNumericFunction("SIN_(1)", text, delegate(double[] parameters) { Value = Math.Sin(parameters[0] * (Math.PI / 180)); }); if (result) return true; result = TryParseNumericFunction("COS_(1)", text, delegate(double[] parameters) { Value = Math.Cos(parameters[0] * (Math.PI / 180)); }); if (result) return true; result = TryParseNumericFunction("TAN_(1)", text, delegate(double[] parameters) { Value = Math.Tan(parameters[0] * (Math.PI / 180)); }); if (result) return true; // Inverse result = TryParseNumericFunction("ARCSIN_(1)", text, delegate(double[] parameters) { Value = (Math.Asin(parameters[0]) * (180 / Math.PI)); }); if (result) return true; result = TryParseNumericFunction("ARCCOS_(1)", text, delegate(double[] parameters) { Value = (Math.Acos(parameters[0]) * (180 / Math.PI)); }); if (result) return true; result = TryParseNumericFunction("ARCTAN_(1)", text, delegate(double[] parameters) { Value = Math.Atan(parameters[0]) * (180 / Math.PI); }); if (result) return true; result = TryParseNumericFunction("ARCTAN2_(2)", text, delegate(double[] parameters) { Value = Math.Atan2(parameters[0], parameters[1]) * (180 / Math.PI); }); if (result) return true; #endregion #region Other Math result = TryParseNumericFunction("ABS_(1)", text, delegate(double[] parameters) { Value = Math.Abs(parameters[0]); }); if (result) return true; result = TryParseNumericFunction("FLOOR_(1)", text, delegate(double[] parameters) { Value = Math.Floor(parameters[0]); }); if (result) return true; result = TryParseNumericFunction("CEILING_(1)", text, delegate(double[] parameters) { Value = Math.Ceiling(parameters[0]); }); if (result) return true; result = TryParseNumericFunction("ROUND_(1)", text, delegate(double[] parameters) { Value = Math.Round(parameters[0]); }); if (result) return true; result = TryParseNumericFunction("SQRT_(1)", text, delegate(double[] parameters) { Value = Math.Sqrt(parameters[0]); }); if (result) return true; #endregion #region Geospatial result = TryParseNumericFunction("LATLNG_(2)", text, delegate(double[] parameters) { Value = new GeoCoordinates(executionContext.Vessel, parameters[0], parameters[1]); }); if (result) return true; #endregion #region Time result = TryParseNumericFunction("T_(1)", text, delegate(double[] parameters) { Value = new TimeSpan(parameters[0]); }); if (result) return true; #endregion #region Vectors & Rotations result = TryParseNumericFunction("V_(3)", text, delegate(double[] parameters) { Value = new Vector(parameters[0], parameters[1], parameters[2]); }); if (result) return true; result = TryParseNumericFunction("R_(3)", text, delegate(double[] parameters) { Value = new Direction(new Vector3d(parameters[0], parameters[1], parameters[2]), true); }); if (result) return true; result = TryParseNumericFunction("Q_(4)", text, delegate(double[] parameters) { Value = new Direction(new UnityEngine.Quaternion((float)parameters[0], (float)parameters[1], (float)parameters[2], (float)parameters[3])); }); if (result) return true; match = Regex.Match(text, "^HEADING ?([ :@A-Za-z0-9\\.\\-\\+\\*/]+) BY ([ :@A-Za-z0-9\\.\\-\\+\\*/]+)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^HEADING ?([ :@A-Za-z0-9\\.\\-\\+\\*/]+) BY ([ :@A-Za-z0-9\\.\\-\\+\\*/]+)$", RegexOptions.IgnoreCase); double heading = ParseSubExpressionAsDouble(match.Groups[1].Value); double pitch = ParseSubExpressionAsDouble(match.Groups[2].Value); var q = UnityEngine.Quaternion.LookRotation(VesselUtils.GetNorthVector(executionContext.Vessel), executionContext.Vessel.upAxis); q *= UnityEngine.Quaternion.Euler(new UnityEngine.Vector3((float)-pitch, (float)heading, 0)); Value = new Direction(q); }; EvalDlg(); return true; } #endregion #region Maneuver Nodes result = TryParseNumericFunction("NODE_(4)", text, delegate(double[] parameters) { Value = new Node(parameters[0], parameters[1], parameters[2], parameters[3]); }); if (result) return true; #endregion return false; }
private bool TryParseFunction(string text) { Match match; #region TRIG match = Regex.Match(text, "^SIN\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^SIN\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)Math.Sin(v * (Math.PI / 180)); }; EvalDlg(); return true; } match = Regex.Match(text, "^COS\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^COS\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)Math.Cos(v * (Math.PI / 180)); }; EvalDlg(); return true; } match = Regex.Match(text, "^TAN\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^TAN\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)Math.Tan(v * (Math.PI / 180)); }; EvalDlg(); return true; } match = Regex.Match(text, "^ARCSIN\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^ARCSIN\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = ((float)Math.Asin(v) * (180 / Math.PI)); }; EvalDlg(); return true; } match = Regex.Match(text, "^ARCCOS\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^ARCCOS\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = ((float)Math.Acos(v) * (180 / Math.PI)); }; EvalDlg(); return true; } match = Regex.Match(text, "^ARCTAN\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^ARCTAN\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = ((float)Math.Atan(v) * (180 / Math.PI)); }; EvalDlg(); return true; } match = Regex.Match(text, "^ARCTAN2\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^ARCTAN2\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double x = ParseSubExpressionAsDouble(match.Groups[1].Value); double y = ParseSubExpressionAsDouble(match.Groups[2].Value); Value = (float)(Math.Atan2(x, y) * (180 / Math.PI)); }; EvalDlg(); return true; } #endregion #region ABS match = Regex.Match(text, "^ABS\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^ABS\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double v = ParseSubExpressionAsDouble(match.Groups[1].Value); Value = (float)Math.Abs(v); }; EvalDlg(); return true; } #endregion #region Geospatial match = Regex.Match(text, "^LATLNG ?\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^LATLNG ?\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double lat = ParseSubExpressionAsDouble(match.Groups[1].Value); double lng = ParseSubExpressionAsDouble(match.Groups[2].Value); Value = new GeoCoordinates(executionContext.Vessel, lat, lng); }; EvalDlg(); return true; } #endregion #region Vectors & Rotations match = Regex.Match(text, "^V\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^V\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double x = ParseSubExpressionAsDouble(match.Groups[1].Value); double y = ParseSubExpressionAsDouble(match.Groups[2].Value); double z = ParseSubExpressionAsDouble(match.Groups[3].Value); Value = new Vector(x,y,z); }; EvalDlg(); return true; } match = Regex.Match(text, "^R\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^R\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); double x = ParseSubExpressionAsDouble(match.Groups[1].Value); double y = ParseSubExpressionAsDouble(match.Groups[2].Value); double z = ParseSubExpressionAsDouble(match.Groups[3].Value); Value = new Direction(new Vector3d(x, y, z), true); }; EvalDlg(); return true; } match = Regex.Match(text, "^Q\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^Q\\(([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+),([ :@A-Za-z0-9\\.\\-\\+\\*/]+)\\)$", RegexOptions.IgnoreCase); float x = (float)ParseSubExpressionAsDouble(match.Groups[1].Value); float y = (float)ParseSubExpressionAsDouble(match.Groups[2].Value); float z = (float)ParseSubExpressionAsDouble(match.Groups[3].Value); float w = (float)ParseSubExpressionAsDouble(match.Groups[4].Value); Value = x + " " + y + " " + z + " " + w; }; EvalDlg(); return true; } #endregion match = Regex.Match(text, "^HEADING ?([ :@A-Za-z0-9\\.\\-\\+\\*/]+) BY ([ :@A-Za-z0-9\\.\\-\\+\\*/]+)$", RegexOptions.IgnoreCase); if (match.Success) { EvalDlg = delegate() { match = Regex.Match(text, "^HEADING ?([ :@A-Za-z0-9\\.\\-\\+\\*/]+) BY ([ :@A-Za-z0-9\\.\\-\\+\\*/]+)$", RegexOptions.IgnoreCase); float heading = (float)ParseSubExpressionAsDouble(match.Groups[1].Value); float pitch = (float)ParseSubExpressionAsDouble(match.Groups[2].Value); var q = UnityEngine.Quaternion.LookRotation(VesselUtils.GetNorthVector(executionContext.Vessel), executionContext.Vessel.upAxis); q *= UnityEngine.Quaternion.Euler(new UnityEngine.Vector3(-pitch, heading, 0)); Value = new Direction(q); }; EvalDlg(); return true; } return false; }