@armyc2.c5isr.renderer/mil-sym-ts-web 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +57 -0
  3. package/buildNode.bat +2 -0
  4. package/buildWeb.bat +2 -0
  5. package/dist/C5Ren.d.ts +6970 -0
  6. package/dist/C5Ren.js +2 -0
  7. package/dist/C5Ren.js.map +1 -0
  8. package/dist/LICENSE +201 -0
  9. package/dist/README.md +57 -0
  10. package/dist/armyc2.c5isr.renderer-mil-sym-ts-web-2.2.0.tgz +0 -0
  11. package/dist/manifest.json +4 -0
  12. package/dist/package.json +16 -0
  13. package/index.ts +169 -0
  14. package/package.bak +50 -0
  15. package/package.json +40 -0
  16. package/package.node.json +43 -0
  17. package/package.pack.json +19 -0
  18. package/package.packWeb.json +16 -0
  19. package/package.web.json +40 -0
  20. package/src/main/ts/android/graphics/Bitmap.ts +7 -0
  21. package/src/main/ts/android/graphics/Paint.ts +26 -0
  22. package/src/main/ts/android/graphics/Path.ts +78 -0
  23. package/src/main/ts/android/graphics/PointF.ts +14 -0
  24. package/src/main/ts/android/graphics/Rect.ts +18 -0
  25. package/src/main/ts/android/graphics/RectF.ts +50 -0
  26. package/src/main/ts/android/graphics/Region.ts +36 -0
  27. package/src/main/ts/android/graphics/Typeface.ts +11 -0
  28. package/src/main/ts/armyc2/c5isr/JavaLineArray/BasicShapes.ts +99 -0
  29. package/src/main/ts/armyc2/c5isr/JavaLineArray/CChannelPoints2.ts +34 -0
  30. package/src/main/ts/armyc2/c5isr/JavaLineArray/CELineArray.ts +193 -0
  31. package/src/main/ts/armyc2/c5isr/JavaLineArray/Channels.ts +2971 -0
  32. package/src/main/ts/armyc2/c5isr/JavaLineArray/DISMSupport.ts +4008 -0
  33. package/src/main/ts/armyc2/c5isr/JavaLineArray/POINT2.ts +93 -0
  34. package/src/main/ts/armyc2/c5isr/JavaLineArray/Shape2.ts +89 -0
  35. package/src/main/ts/armyc2/c5isr/JavaLineArray/TacticalLines.ts +515 -0
  36. package/src/main/ts/armyc2/c5isr/JavaLineArray/arraysupport.ts +5403 -0
  37. package/src/main/ts/armyc2/c5isr/JavaLineArray/countsupport.ts +1084 -0
  38. package/src/main/ts/armyc2/c5isr/JavaLineArray/flot.ts +2173 -0
  39. package/src/main/ts/armyc2/c5isr/JavaLineArray/lineutility.ts +4934 -0
  40. package/src/main/ts/armyc2/c5isr/JavaLineArray/ref.ts +7 -0
  41. package/src/main/ts/armyc2/c5isr/JavaTacticalRenderer/Modifier2.ts +5601 -0
  42. package/src/main/ts/armyc2/c5isr/JavaTacticalRenderer/P1.ts +14 -0
  43. package/src/main/ts/armyc2/c5isr/JavaTacticalRenderer/TGLight.ts +648 -0
  44. package/src/main/ts/armyc2/c5isr/JavaTacticalRenderer/clsChannelUtility.ts +647 -0
  45. package/src/main/ts/armyc2/c5isr/JavaTacticalRenderer/clsMETOC.ts +2994 -0
  46. package/src/main/ts/armyc2/c5isr/JavaTacticalRenderer/clsUtility.ts +2663 -0
  47. package/src/main/ts/armyc2/c5isr/JavaTacticalRenderer/mdlGeodesic.ts +669 -0
  48. package/src/main/ts/armyc2/c5isr/RenderMultipoints/clsClipPolygon2.ts +971 -0
  49. package/src/main/ts/armyc2/c5isr/RenderMultipoints/clsClipQuad.ts +871 -0
  50. package/src/main/ts/armyc2/c5isr/RenderMultipoints/clsRenderer.ts +3507 -0
  51. package/src/main/ts/armyc2/c5isr/RenderMultipoints/clsRenderer2.ts +500 -0
  52. package/src/main/ts/armyc2/c5isr/RenderMultipoints/clsUtility.ts +1089 -0
  53. package/src/main/ts/armyc2/c5isr/RenderMultipoints/clsUtilityCPOF.ts +2656 -0
  54. package/src/main/ts/armyc2/c5isr/RenderMultipoints/clsUtilityGE.ts +1419 -0
  55. package/src/main/ts/armyc2/c5isr/data/genc.json +1407 -0
  56. package/src/main/ts/armyc2/c5isr/data/msd.json +17311 -0
  57. package/src/main/ts/armyc2/c5isr/data/mse.json +18500 -0
  58. package/src/main/ts/armyc2/c5isr/data/svgd.json +31214 -0
  59. package/src/main/ts/armyc2/c5isr/data/svge.json +30558 -0
  60. package/src/main/ts/armyc2/c5isr/graphics2d/AffineTransform.ts +10 -0
  61. package/src/main/ts/armyc2/c5isr/graphics2d/Area.ts +437 -0
  62. package/src/main/ts/armyc2/c5isr/graphics2d/BasicStroke.ts +429 -0
  63. package/src/main/ts/armyc2/c5isr/graphics2d/BasicTypes.ts +7 -0
  64. package/src/main/ts/armyc2/c5isr/graphics2d/BufferedImage.ts +35 -0
  65. package/src/main/ts/armyc2/c5isr/graphics2d/Font.ts +111 -0
  66. package/src/main/ts/armyc2/c5isr/graphics2d/FontMetrics.ts +29 -0
  67. package/src/main/ts/armyc2/c5isr/graphics2d/FontRenderContext.ts +18 -0
  68. package/src/main/ts/armyc2/c5isr/graphics2d/GeneralPath.ts +211 -0
  69. package/src/main/ts/armyc2/c5isr/graphics2d/Graphics2D.ts +80 -0
  70. package/src/main/ts/armyc2/c5isr/graphics2d/IPathIterator.ts +33 -0
  71. package/src/main/ts/armyc2/c5isr/graphics2d/ImageIO.ts +16 -0
  72. package/src/main/ts/armyc2/c5isr/graphics2d/Line2D.ts +726 -0
  73. package/src/main/ts/armyc2/c5isr/graphics2d/PathIterator.ts +141 -0
  74. package/src/main/ts/armyc2/c5isr/graphics2d/Point.ts +112 -0
  75. package/src/main/ts/armyc2/c5isr/graphics2d/Point2D.ts +261 -0
  76. package/src/main/ts/armyc2/c5isr/graphics2d/Polygon.ts +391 -0
  77. package/src/main/ts/armyc2/c5isr/graphics2d/Rectangle.ts +567 -0
  78. package/src/main/ts/armyc2/c5isr/graphics2d/Rectangle2D.ts +445 -0
  79. package/src/main/ts/armyc2/c5isr/graphics2d/Shape.ts +31 -0
  80. package/src/main/ts/armyc2/c5isr/graphics2d/Stroke.ts +18 -0
  81. package/src/main/ts/armyc2/c5isr/graphics2d/TextLayout.ts +45 -0
  82. package/src/main/ts/armyc2/c5isr/graphics2d/TexturePaint.ts +25 -0
  83. package/src/main/ts/armyc2/c5isr/renderer/IIconRenderer.ts +15 -0
  84. package/src/main/ts/armyc2/c5isr/renderer/IconRenderer.ts +22 -0
  85. package/src/main/ts/armyc2/c5isr/renderer/MilStdIconRenderer.ts +269 -0
  86. package/src/main/ts/armyc2/c5isr/renderer/ModifierRenderer.ts +9882 -0
  87. package/src/main/ts/armyc2/c5isr/renderer/PatternFillRenderer.ts +146 -0
  88. package/src/main/ts/armyc2/c5isr/renderer/SinglePointSVGRenderer.ts +1265 -0
  89. package/src/main/ts/armyc2/c5isr/renderer/shapes/arc.ts +64 -0
  90. package/src/main/ts/armyc2/c5isr/renderer/shapes/bcurve.ts +95 -0
  91. package/src/main/ts/armyc2/c5isr/renderer/shapes/ellipse.ts +93 -0
  92. package/src/main/ts/armyc2/c5isr/renderer/shapes/line.ts +114 -0
  93. package/src/main/ts/armyc2/c5isr/renderer/shapes/path.ts +555 -0
  94. package/src/main/ts/armyc2/c5isr/renderer/shapes/pathiterator.ts +62 -0
  95. package/src/main/ts/armyc2/c5isr/renderer/shapes/point.ts +120 -0
  96. package/src/main/ts/armyc2/c5isr/renderer/shapes/rectangle.ts +431 -0
  97. package/src/main/ts/armyc2/c5isr/renderer/shapes/roundedrectangle.ts +99 -0
  98. package/src/main/ts/armyc2/c5isr/renderer/shapes/types.ts +25 -0
  99. package/src/main/ts/armyc2/c5isr/renderer/shapes/utilities.ts +203 -0
  100. package/src/main/ts/armyc2/c5isr/renderer/utilities/AffiliationColors.ts +104 -0
  101. package/src/main/ts/armyc2/c5isr/renderer/utilities/Color.ts +481 -0
  102. package/src/main/ts/armyc2/c5isr/renderer/utilities/DistanceUnit.ts +40 -0
  103. package/src/main/ts/armyc2/c5isr/renderer/utilities/DrawRules.ts +1323 -0
  104. package/src/main/ts/armyc2/c5isr/renderer/utilities/EntityCode.ts +51 -0
  105. package/src/main/ts/armyc2/c5isr/renderer/utilities/ErrorLogger.ts +736 -0
  106. package/src/main/ts/armyc2/c5isr/renderer/utilities/GENCLookup.ts +106 -0
  107. package/src/main/ts/armyc2/c5isr/renderer/utilities/GeoPixelConversion3D.ts +84 -0
  108. package/src/main/ts/armyc2/c5isr/renderer/utilities/IMultiPointRenderer.ts +87 -0
  109. package/src/main/ts/armyc2/c5isr/renderer/utilities/IPointConversion.ts +34 -0
  110. package/src/main/ts/armyc2/c5isr/renderer/utilities/ImageInfo.ts +324 -0
  111. package/src/main/ts/armyc2/c5isr/renderer/utilities/LRUCache.ts +127 -0
  112. package/src/main/ts/armyc2/c5isr/renderer/utilities/LRUEntry.ts +18 -0
  113. package/src/main/ts/armyc2/c5isr/renderer/utilities/LogLevel.ts +111 -0
  114. package/src/main/ts/armyc2/c5isr/renderer/utilities/MODrawRules.ts +219 -0
  115. package/src/main/ts/armyc2/c5isr/renderer/utilities/MSInfo.ts +1008 -0
  116. package/src/main/ts/armyc2/c5isr/renderer/utilities/MSLookup.ts +882 -0
  117. package/src/main/ts/armyc2/c5isr/renderer/utilities/MilStdAttributes.ts +380 -0
  118. package/src/main/ts/armyc2/c5isr/renderer/utilities/MilStdSymbol.ts +797 -0
  119. package/src/main/ts/armyc2/c5isr/renderer/utilities/Modifiers.ts +1699 -0
  120. package/src/main/ts/armyc2/c5isr/renderer/utilities/PointConversion.ts +178 -0
  121. package/src/main/ts/armyc2/c5isr/renderer/utilities/PointConversionDummy.ts +45 -0
  122. package/src/main/ts/armyc2/c5isr/renderer/utilities/PointConverter3D.ts +126 -0
  123. package/src/main/ts/armyc2/c5isr/renderer/utilities/RectUtilities.ts +118 -0
  124. package/src/main/ts/armyc2/c5isr/renderer/utilities/RendererException.ts +11 -0
  125. package/src/main/ts/armyc2/c5isr/renderer/utilities/RendererSettings.ts +1201 -0
  126. package/src/main/ts/armyc2/c5isr/renderer/utilities/RendererUtilities.ts +591 -0
  127. package/src/main/ts/armyc2/c5isr/renderer/utilities/SVGInfo.ts +29 -0
  128. package/src/main/ts/armyc2/c5isr/renderer/utilities/SVGLookup.ts +753 -0
  129. package/src/main/ts/armyc2/c5isr/renderer/utilities/SVGSymbolInfo.ts +137 -0
  130. package/src/main/ts/armyc2/c5isr/renderer/utilities/SVGTextInfo.ts +438 -0
  131. package/src/main/ts/armyc2/c5isr/renderer/utilities/SettingsChangedEvent.ts +19 -0
  132. package/src/main/ts/armyc2/c5isr/renderer/utilities/SettingsChangedEventListener.ts +10 -0
  133. package/src/main/ts/armyc2/c5isr/renderer/utilities/SettingsEventListener.ts +5 -0
  134. package/src/main/ts/armyc2/c5isr/renderer/utilities/Shape2SVG.ts +404 -0
  135. package/src/main/ts/armyc2/c5isr/renderer/utilities/ShapeInfo.ts +525 -0
  136. package/src/main/ts/armyc2/c5isr/renderer/utilities/ShapeUtilities.ts +55 -0
  137. package/src/main/ts/armyc2/c5isr/renderer/utilities/SymbolDimensionInfo.ts +36 -0
  138. package/src/main/ts/armyc2/c5isr/renderer/utilities/SymbolID.ts +1055 -0
  139. package/src/main/ts/armyc2/c5isr/renderer/utilities/SymbolUtilities.ts +2085 -0
  140. package/src/main/ts/armyc2/c5isr/renderer/utilities/TextInfo.ts +157 -0
  141. package/src/main/ts/armyc2/c5isr/web/render/GeoPixelConversion.ts +86 -0
  142. package/src/main/ts/armyc2/c5isr/web/render/MultiPointHandler.ts +3798 -0
  143. package/src/main/ts/armyc2/c5isr/web/render/MultiPointHandlerSVG.ts +412 -0
  144. package/src/main/ts/armyc2/c5isr/web/render/PointConverter.ts +124 -0
  145. package/src/main/ts/armyc2/c5isr/web/render/SymbolModifiers.ts +26 -0
  146. package/src/main/ts/armyc2/c5isr/web/render/WebRenderer.ts +677 -0
  147. package/src/main/ts/armyc2/c5isr/web/render/utilities/JavaRendererUtilities.ts +484 -0
  148. package/src/main/ts/armyc2/c5isr/web/render/utilities/LineInfo.ts +62 -0
  149. package/src/main/ts/armyc2/c5isr/web/render/utilities/SymbolInfo.ts +46 -0
  150. package/src/main/ts/armyc2/c5isr/web/render/utilities/TextInfo.ts +51 -0
  151. package/src/main/ts/org/gavaghan/geodesy/Angle.ts +31 -0
  152. package/src/main/ts/org/gavaghan/geodesy/Ellipsoid.ts +71 -0
  153. package/src/main/ts/org/gavaghan/geodesy/GeodeticCalculator.ts +200 -0
  154. package/src/main/ts/org/gavaghan/geodesy/GeodeticCurve.ts +55 -0
  155. package/src/main/ts/org/gavaghan/geodesy/GeodeticMeasurement.ts +68 -0
  156. package/src/main/ts/org/gavaghan/geodesy/GlobalCoordinates.ts +103 -0
  157. package/src/main/ts/org/gavaghan/geodesy/GlobalPosition.ts +90 -0
  158. package/test/ExportSPImages.js +692 -0
  159. package/test/MPWW.html +556 -0
  160. package/test/MPWorker.js +318 -0
  161. package/test/SPWorker.js +233 -0
  162. package/test/SVGWW.html +363 -0
  163. package/test/singlePointTester3.html +751 -0
  164. package/tsconfig.json +54 -0
  165. package/typedoc.json +30 -0
  166. package/updateVersion.js +21 -0
  167. package/webpack.config.js +34 -0
  168. package/webpackn.config.js +28 -0
  169. package/webpackr.config.js +47 -0
  170. package/webpackw.config.js +23 -0
@@ -0,0 +1,2085 @@
1
+ import { type int, type double } from "../../graphics2d/BasicTypes";
2
+
3
+ import { Point } from "../../graphics2d/Point";
4
+ import { Rectangle2D } from "../../graphics2d/Rectangle2D"
5
+ import { TacticalLines } from "../../JavaLineArray/TacticalLines";
6
+ import { AffiliationColors } from "../../renderer/utilities/AffiliationColors"
7
+ import { Color } from "../../renderer/utilities/Color"
8
+ import { DrawRules } from "../../renderer/utilities/DrawRules"
9
+ import { ErrorLogger } from "../../renderer/utilities/ErrorLogger"
10
+ import { Modifiers } from "../../renderer/utilities/Modifiers"
11
+ import { MSInfo } from "../../renderer/utilities/MSInfo"
12
+ import { MSLookup } from "../../renderer/utilities/MSLookup"
13
+ import { RendererSettings } from "../../renderer/utilities/RendererSettings"
14
+ import { SVGLookup } from "../../renderer/utilities/SVGLookup"
15
+ import { SymbolID } from "../../renderer/utilities/SymbolID"
16
+
17
+ /**
18
+ * Has various utility functions for prcessing the symbol code.
19
+ * See {@link SymbolID} for additional functions related to parsing the symbol code.
20
+ *
21
+ */
22
+ export class SymbolUtilities {
23
+ //this regex is from: https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html
24
+ private static readonly Digits: string = "(\\p{Digit}+)";
25
+ private static readonly HexDigits: string = "(\\p{XDigit}+)";
26
+ // an exponent is 'e' or 'E' followed by an optionally
27
+ // signed decimal integer.
28
+ private static readonly Exp: string = "[eE][+-]?" + SymbolUtilities.Digits;
29
+ private static readonly fpRegex: string =
30
+ ("[\\x00-\\x20]*" + // Optional leading "whitespace"
31
+ "[+-]?(" + // Optional sign character
32
+ "NaN|" + // "NaN" string
33
+ "Infinity|" + // "Infinity" string
34
+
35
+ // A decimal floating-point string representing a finite positive
36
+ // number without a leading sign has at most five basic pieces:
37
+ // Digits . Digits ExponentPart FloatTypeSuffix
38
+ //
39
+ // Since this method allows integer-only strings as input
40
+ // in addition to strings of floating-point literals, the
41
+ // two sub-patterns below are simplifications of the grammar
42
+ // productions from section 3.10.2 of
43
+ // The Java™ Language Specification.
44
+
45
+ // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
46
+ "(((" + SymbolUtilities.Digits + "(\\.)?(" + SymbolUtilities.Digits + "?)(" + SymbolUtilities.Exp + ")?)|" +
47
+
48
+ // . Digits ExponentPart_opt FloatTypeSuffix_opt
49
+ "(\\.(" + SymbolUtilities.Digits + ")(" + SymbolUtilities.Exp + ")?)|" +
50
+
51
+ // Hexadecimal strings
52
+ "((" +
53
+ // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
54
+ "(0[xX]" + SymbolUtilities.HexDigits + "(\\.)?)|" +
55
+
56
+ // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
57
+ "(0[xX]" + SymbolUtilities.HexDigits + "?(\\.)" + SymbolUtilities.HexDigits + ")" +
58
+
59
+ ")[pP][+-]?" + SymbolUtilities.Digits + "))" +
60
+ "[fFdD]?))" +
61
+ "[\\x00-\\x20]*");// Optional trailing "whitespace"
62
+
63
+ private static readonly pIsNumber: RegExp = RegExp(SymbolUtilities.fpRegex);
64
+
65
+ /**
66
+ * Determines if a String represents a valid number
67
+ *
68
+ * @param text string
69
+ * @return "1.56" == true, "1ab" == false
70
+ */
71
+ public static isNumber(text: string): boolean {
72
+ //return SymbolUtilities.pIsNumber.test(text);
73
+ return !isNaN(parseFloat(text)) || !isNaN(parseInt(text))
74
+ }
75
+
76
+
77
+ /*private static String convert(int integer)
78
+ {
79
+ String hexAlphabet = "0123456789ABCDEF";
80
+ String foo = "gfds" + "dhs";
81
+ char char1 = hexAlphabet.charAt((integer - integer % 16)/16);
82
+ char char2 = hexAlphabet.charAt(integer % 16);
83
+ String returnVal = char1.toString() + char2.toString();
84
+ return returnVal;
85
+ }
86
+
87
+ public static String colorToHexString(Color color, Boolean withAlpha)
88
+ {
89
+ String hex = "";
90
+ if(withAlpha == false)
91
+ {
92
+ hex = "#" + convert(color.getRed()) +
93
+ convert(color.getGreen()) +
94
+ convert(color.getBlue());
95
+ }
96
+ else
97
+ {
98
+ hex = "#" + convert(color.getAlpha()) +
99
+ convert(color.getRed()) +
100
+ convert(color.getGreen()) +
101
+ convert(color.getBlue());
102
+ }
103
+ return hex;
104
+ }//*/
105
+
106
+ /*private static String convert(int integer)
107
+ {
108
+ String hexAlphabet = "0123456789ABCDEF";
109
+ String foo = "gfds" + "dhs";
110
+ char char1 = hexAlphabet.charAt((integer - integer % 16)/16);
111
+ char char2 = hexAlphabet.charAt(integer % 16);
112
+ String returnVal = char1.toString() + char2.toString();
113
+ return returnVal;
114
+ }
115
+
116
+ public static String colorToHexString(Color color, Boolean withAlpha)
117
+ {
118
+ if(color != null) {
119
+ String hex = "";
120
+ if (withAlpha == false) {
121
+ hex = "#" + convert(color.getRed()) +
122
+ convert(color.getGreen()) +
123
+ convert(color.getBlue());
124
+ } else {
125
+ hex = "#" + convert(color.getAlpha()) +
126
+ convert(color.getRed()) +
127
+ convert(color.getGreen()) +
128
+ convert(color.getBlue());
129
+ }
130
+ return hex;
131
+ }
132
+ else
133
+ return null;
134
+ }//*/
135
+
136
+
137
+ /**
138
+ * Converts a Java Date object into a properly formatted String for W or W1.
139
+ * DDHHMMSSZMONYYYY
140
+ * Field W: D = day, H = hour, M = minute, S = second, Z = Greenwich or local time, MON= month and Y = year.
141
+ * @param date {@link Date}
142
+ * @return string
143
+ */
144
+ public static getDateLabel(date: Date): string {
145
+ const monthNamesShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
146
+
147
+ let modifierString: string = "";
148
+ modifierString += String(date.getDate()).padStart(2, '0')
149
+ modifierString += String(date.getHours()).padStart(2, '0')
150
+ modifierString += String(date.getMinutes()).padStart(2, '0')
151
+ modifierString += String(date.getSeconds()).padStart(2, '0')
152
+ modifierString += SymbolUtilities.getZuluCharFromTimeZoneOffset(date);
153
+ modifierString += monthNamesShort[date.getUTCMonth()]
154
+ modifierString += date.getUTCFullYear()
155
+
156
+ return modifierString.toUpperCase();
157
+ }
158
+
159
+ /**
160
+ * Given date, return character String representing which NATO time zone
161
+ * you're in.
162
+ *
163
+ * @param time {@link Date}
164
+ * @return string
165
+ */
166
+ private static getZuluCharFromTimeZoneOffset(time: Date): string {
167
+ let tzDescription = time.getTimezoneOffset() / 60;
168
+ if (tzDescription === -1) {
169
+ return "A";
170
+ } else if (tzDescription === -2) {
171
+ return "B";
172
+ } else if (tzDescription === -3) {
173
+ return "C";
174
+ } else if (tzDescription === -4) {
175
+ return "D";
176
+ } else if (tzDescription === -5) {
177
+ return "E";
178
+ } else if (tzDescription === -6) {
179
+ return "F";
180
+ } else if (tzDescription === -7) {
181
+ return "G";
182
+ } else if (tzDescription === -8) {
183
+ return "H";
184
+ } else if (tzDescription === -9) {
185
+ return "I";
186
+ } else if (tzDescription === -10) {
187
+ return "K";
188
+ } else if (tzDescription === -11) {
189
+ return "L";
190
+ } else if (tzDescription === -12) {
191
+ return "M";
192
+ } else if (tzDescription === 1 || tzDescription === -13) {
193
+ return "N";
194
+ } else if (tzDescription === 2) {
195
+ return "O";
196
+ } else if (tzDescription === 3) {
197
+ return "P";
198
+ } else if (tzDescription === 4) {
199
+ return "Q";
200
+ } else if (tzDescription === 5) {
201
+ return "R";
202
+ } else if (tzDescription === 6) {
203
+ return "S";
204
+ } else if (tzDescription === 7) {
205
+ return "T";
206
+ } else if (tzDescription === 8) {
207
+ return "U";
208
+ } else if (tzDescription === 9) {
209
+ return "V";
210
+ } else if (tzDescription === 10) {
211
+ return "W";
212
+ } else if (tzDescription === 11) {
213
+ return "X";
214
+ } else if (tzDescription === 12) {
215
+ return "Y";
216
+ } else if (tzDescription === 0) {
217
+ return "Z";
218
+ } else {
219
+ return "-";
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Determines if a symbol, based on it's symbol ID, can have the specified modifier/amplifier.
225
+ * @param symbolID 30 Character string
226
+ * @param modifier {@link Modifiers}
227
+ * @return
228
+ */
229
+ public static hasModifier(symbolID: string, modifier: string): boolean {
230
+ let msi: MSInfo = MSLookup.getInstance().getMSLInfo(symbolID);
231
+
232
+ if (msi != null && msi.getDrawRule() !== DrawRules.DONOTDRAW) {
233
+ let mods: Array<string> = msi.getModifiers();
234
+
235
+ if (mods != null && mods.includes(modifier)) {
236
+
237
+ return true;
238
+ }
239
+
240
+ else {
241
+ if (msi.getSymbolSet() === SymbolID.SymbolSet_ControlMeasure && modifier === Modifiers.AB_FEINT_DUMMY_INDICATOR) {
242
+
243
+ return true;
244
+ }
245
+
246
+ else {
247
+
248
+ return false;
249
+ }
250
+
251
+ }
252
+
253
+ }
254
+ return false;
255
+ }
256
+
257
+ /**
258
+ * Gets Basic Symbol ID which is the Symbol Set + Entity Code
259
+ * @param id 30 Character string
260
+ * @return 8 character string (Symbol Set + Entity Code)
261
+ */
262
+ public static getBasicSymbolID(id: string): string {
263
+ if (id.length === 8) {
264
+ return id;
265
+ }
266
+ else {
267
+ if (id.startsWith("B")) {
268
+
269
+ return id;
270
+ }
271
+
272
+ else {
273
+ if (id === "octagon") {
274
+
275
+ return id;
276
+ }
277
+
278
+ else {
279
+ if (id.length >= 20 && id.length <= 30) {
280
+ let key: string = id.substring(4, 6) + id.substring(10, 16);
281
+ return key;
282
+ }
283
+ else {
284
+ if (id.length === 15) {
285
+ return SymbolUtilities.getBasicSymbolID2525C(id);
286
+ }
287
+ }
288
+
289
+ }
290
+
291
+ }
292
+
293
+ }
294
+
295
+ return id;
296
+ }
297
+
298
+ /**
299
+ * Gets the basic Symbol ID for a 2525C symbol
300
+ * S*F*GPU---*****
301
+ * G*G*GPP---****X
302
+ * @param strSymbolID 15 Character string
303
+ * @return 15 Character string
304
+ * @deprecated function will be removed
305
+ */
306
+ public static getBasicSymbolID2525C(strSymbolID: string): string {
307
+ if (strSymbolID != null && strSymbolID.length === 15) {
308
+ let res: string = "";
309
+ let scheme: string = strSymbolID.charAt(0);
310
+ if (scheme === 'G') {
311
+ res += strSymbolID.charAt(0);
312
+ res += "*";
313
+ res += strSymbolID.charAt(2);
314
+ res += "*";
315
+ res += strSymbolID.substring(4, 10);
316
+ res += "****X";
317
+ } else if (scheme !== 'W' && scheme !== 'B' && scheme !== 'P') {
318
+ res += strSymbolID.charAt(0);
319
+ res += "*";
320
+ res += strSymbolID.charAt(2);
321
+ res += "*";
322
+ res += strSymbolID.substring(4, 10);
323
+ res += "*****";
324
+ } else {
325
+ return strSymbolID;
326
+ }
327
+
328
+ return res;
329
+ }
330
+ return strSymbolID;
331
+ }
332
+
333
+ /**
334
+ * Attempts to resolve a bad symbol ID into a value that can be found in {@link MSLookup}.
335
+ * If it fails, it will return the symbol code for a invalid symbol which is displayed as
336
+ * an inverted question mark (110098000010000000000000000000)
337
+ * @param symbolID 30 character string
338
+ * @return 30 character string representing the resolved symbol ID.
339
+ */
340
+ public static reconcileSymbolID(symbolID: string): string {
341
+
342
+ let newID: string = "";
343
+ try {
344
+
345
+
346
+ let v: int = SymbolID.getVersion(symbolID);
347
+ if (v < SymbolID.Version_2525E) {
348
+
349
+ newID = SymbolID.Version_2525Dch1.toString();
350
+ }
351
+
352
+ else {
353
+
354
+ newID = SymbolID.Version_2525E.toString();
355
+ }
356
+
357
+ let c: int = SymbolID.getContext(symbolID);
358
+ if (c > 2) {
359
+
360
+ newID += SymbolID.StandardIdentity_Context_Reality.toString();
361
+ }
362
+
363
+ else {
364
+
365
+ newID += c.toString();
366
+ }
367
+
368
+ let a: int = SymbolID.getAffiliation(symbolID);
369
+ if (a > 6) {
370
+
371
+ newID += SymbolID.StandardIdentity_Affiliation_Unknown.toString();
372
+ }
373
+
374
+ else {
375
+
376
+ newID += a.toString();
377
+ }
378
+
379
+ let ss: int = SymbolID.getSymbolSet(symbolID);
380
+ switch (ss) {
381
+ case SymbolID.SymbolSet_Unknown:
382
+ case SymbolID.SymbolSet_Air:
383
+ case SymbolID.SymbolSet_AirMissile:
384
+ case SymbolID.SymbolSet_SignalsIntelligence_Air:
385
+ case SymbolID.SymbolSet_Space:
386
+ case SymbolID.SymbolSet_SpaceMissile:
387
+ case SymbolID.SymbolSet_SignalsIntelligence_Space:
388
+ case SymbolID.SymbolSet_LandUnit:
389
+ case SymbolID.SymbolSet_LandCivilianUnit_Organization:
390
+ case SymbolID.SymbolSet_LandEquipment:
391
+ case SymbolID.SymbolSet_SignalsIntelligence_Land:
392
+ case SymbolID.SymbolSet_LandInstallation:
393
+ case SymbolID.SymbolSet_DismountedIndividuals:
394
+ case SymbolID.SymbolSet_SeaSurface:
395
+ case SymbolID.SymbolSet_SignalsIntelligence_SeaSurface:
396
+ case SymbolID.SymbolSet_SeaSubsurface:
397
+ case SymbolID.SymbolSet_MineWarfare:
398
+ case SymbolID.SymbolSet_SignalsIntelligence_SeaSubsurface:
399
+ case SymbolID.SymbolSet_Activities:
400
+ case SymbolID.SymbolSet_ControlMeasure:
401
+ case SymbolID.SymbolSet_Atmospheric:
402
+ case SymbolID.SymbolSet_Oceanographic:
403
+ case SymbolID.SymbolSet_MeteorologicalSpace:
404
+ case SymbolID.SymbolSet_CyberSpace: {
405
+ newID += String(ss).padStart(2, '0');
406
+ break;
407
+ }
408
+
409
+ default: {
410
+ newID += String(SymbolID.SymbolSet_Unknown).padStart(2, '0');
411
+ }
412
+ //SymbolID.SymbolSet_Unknown.toString();
413
+ }
414
+
415
+ let s: int = SymbolID.getStatus(symbolID);
416
+ if (s > SymbolID.Status_Present_FullToCapacity) {
417
+
418
+ newID += SymbolID.Status_Present.toString();
419
+ }
420
+
421
+ else {
422
+
423
+ newID += s.toString();
424
+ }
425
+
426
+
427
+ newID += SymbolID.getHQTFD(symbolID).toString();//just add, won't get used if value bad
428
+ newID += String(SymbolID.getAmplifierDescriptor(symbolID)).padStart(2, '0');//just add, won't get used if value bad
429
+
430
+ let ec: int = SymbolID.getEntityCode(symbolID);
431
+
432
+ if (ec === 0) {
433
+
434
+ newID += "000000";
435
+ }
436
+ //root symbol for symbol set
437
+ else {
438
+ if (SVGLookup.getInstance().getSVGLInfo(SVGLookup.getMainIconID(newID + ec + "0000"), v) == null) {
439
+ //set to invalid symbol since we couldn't find it in the lookup
440
+ newID = SymbolID.setSymbolSet(newID, 98);
441
+ newID += 100000;
442
+ }
443
+ else {
444
+ newID += String(ec).padStart(6, '0');
445
+ }
446
+
447
+ }
448
+ //we found it so add the entity code
449
+
450
+ //newID += SymbolID.getMod1ID(symbolID);//just add, won't get used if value bad
451
+ //newID += SymbolID.getMod2ID(symbolID);//just add, won't get used if value bad
452
+ newID += symbolID.substring(16);//just add, won't get used if value bad
453
+ } catch (exc) {
454
+ if (exc instanceof Error) {
455
+ newID = "110098000010000000000000000000";//invalid symbol
456
+ } else {
457
+ throw exc;
458
+ }
459
+ }
460
+
461
+ return newID;
462
+ }
463
+
464
+ /**
465
+ * Gets line color used if no line color has been set. The color is specified based on the affiliation of
466
+ * the symbol and whether it is a unit or not.
467
+ * @param symbolID 30 character string
468
+ * @return
469
+ */
470
+ public static getLineColorOfAffiliation(symbolID: string): Color | null {
471
+ let retColor: Color | null = null;
472
+
473
+ let symbolSet: int = SymbolID.getSymbolSet(symbolID);
474
+ let set: int = SymbolID.getSymbolSet(symbolID);
475
+ let affiliation: int = SymbolID.getAffiliation(symbolID);
476
+ let symStd: int = SymbolID.getVersion(symbolID);
477
+ let entityCode: int = SymbolID.getEntityCode(symbolID);
478
+
479
+ try {
480
+ // We can't get the line color if there is no symbol id, since that also means there is no affiliation
481
+ if ((symbolID == null) || (symbolID === "")) {
482
+ return retColor;
483
+ }
484
+
485
+ if (symbolSet === SymbolID.SymbolSet_ControlMeasure) {
486
+ let entity: int = SymbolID.getEntity(symbolID);
487
+ let entityType: int = SymbolID.getEntityType(symbolID);
488
+ let entitySubtype: int = SymbolID.getEntitySubtype(symbolID);
489
+
490
+
491
+ if (SymbolUtilities.isGreenProtectionGraphic(entity, entityType, entitySubtype)) {
492
+ //Obstacles/Protection Graphics, some are green obstacles and we need to
493
+ //check for those.
494
+ retColor = AffiliationColors.ObstacleGreen;//new Color(0,255,0);//Color.GREEN;
495
+ }
496
+ //just do color by affiliation if no other color has been set yet.
497
+ if (retColor == null) {
498
+ switch (affiliation) {
499
+ case SymbolID.StandardIdentity_Affiliation_Friend:
500
+ case SymbolID.StandardIdentity_Affiliation_AssumedFriend: {
501
+ retColor = AffiliationColors.FriendlyGraphicLineColor;//Color.BLACK;//0x000000; // Black
502
+ break;
503
+ }
504
+
505
+ case SymbolID.StandardIdentity_Affiliation_Hostile_Faker: {
506
+ retColor = AffiliationColors.HostileGraphicLineColor;//Color.RED;//0xff0000; // Red
507
+ break;
508
+ }
509
+
510
+ case SymbolID.StandardIdentity_Affiliation_Suspect_Joker: {
511
+ if (symStd >= SymbolID.Version_2525E) {
512
+
513
+ retColor = AffiliationColors.SuspectGraphicLineColor;
514
+ }
515
+ //255,188,1
516
+ else {
517
+
518
+ retColor = AffiliationColors.HostileGraphicLineColor;
519
+ }
520
+ //Color.RED;//0xff0000; // Red
521
+ break;
522
+ }
523
+
524
+ case SymbolID.StandardIdentity_Affiliation_Neutral: {
525
+ retColor = AffiliationColors.NeutralGraphicLineColor;//Color.GREEN;//0x00ff00; // Green
526
+ break;
527
+ }
528
+
529
+ default: {
530
+ retColor = AffiliationColors.UnknownGraphicLineColor;//Color.YELLOW;//0xffff00; // Yellow
531
+ break;
532
+ }
533
+
534
+ }
535
+ }
536
+ }
537
+ else {
538
+ if (set >= 45 && set <= 47)//METOC
539
+ {
540
+ // If not black then color will be set in clsMETOC.SetMeTOCProperties()
541
+ retColor = Color.BLACK;
542
+ ;
543
+ }
544
+ else {
545
+ if (set === SymbolID.SymbolSet_MineWarfare && (RendererSettings.getInstance().getSeaMineRenderMethod() === RendererSettings.SeaMineRenderMethod_MEDAL)) {
546
+ if (!(entityCode === 110600 || entityCode === 110700)) {
547
+ switch (affiliation) {
548
+ case SymbolID.StandardIdentity_Affiliation_Friend:
549
+ case SymbolID.StandardIdentity_Affiliation_AssumedFriend: {
550
+ retColor = AffiliationColors.FriendlyUnitFillColor;//0x00ffff; // Cyan
551
+ break;
552
+ }
553
+
554
+ case SymbolID.StandardIdentity_Affiliation_Hostile_Faker: {
555
+ retColor = AffiliationColors.HostileGraphicLineColor;//Color.RED;//0xff0000; // Red
556
+ break;
557
+ }
558
+
559
+ case SymbolID.StandardIdentity_Affiliation_Suspect_Joker: {
560
+ if (symStd >= SymbolID.Version_2525E) {
561
+
562
+ retColor = AffiliationColors.SuspectGraphicLineColor;
563
+ }
564
+ //255,188,1
565
+ else {
566
+
567
+ retColor = AffiliationColors.HostileGraphicLineColor;
568
+ }
569
+ //Color.RED;//0xff0000; // Red
570
+ break;
571
+ }
572
+
573
+ case SymbolID.StandardIdentity_Affiliation_Neutral: {
574
+ retColor = AffiliationColors.NeutralUnitFillColor;//0x7fff00; // Light Green
575
+ break;
576
+ }
577
+
578
+ default: {//unknown, pending, everything else
579
+ retColor = AffiliationColors.UnknownUnitFillColor;//new Color(255,250, 205); //0xfffacd; // LemonChiffon 255 250 205
580
+ break;
581
+ }
582
+
583
+ }
584
+ }
585
+ else {
586
+ retColor = Color.BLACK;
587
+ }
588
+ }
589
+ else//everything else
590
+ {
591
+ //stopped doing check because all warfighting
592
+ //should have black for line color.
593
+ retColor = Color.BLACK;
594
+ }
595
+ }
596
+
597
+ }
598
+
599
+ } catch (e) {
600
+ if (e instanceof Error) {
601
+ // Log Error
602
+ ErrorLogger.LogException("SymbolUtilities", "getLineColorOfAffiliation", e);
603
+ //throw e;
604
+ } else {
605
+ throw e;
606
+ }
607
+ } // End catch
608
+ return retColor;
609
+ } // End get LineColorOfAffiliation
610
+
611
+ /**
612
+ * For Control Measures, returns the default color for a symbol when it differs from the
613
+ * affiliation line color. If there is no default color, returns the value from {@link getLineColorOfAffiliation()}
614
+ * @param symbolID 30 Character string
615
+ * @return
616
+ */
617
+ public static getDefaultLineColor(symbolID: string): Color | null {
618
+ try {
619
+ if (symbolID == null || symbolID === "") {
620
+ return null;
621
+ }
622
+
623
+ let symbolSet: int = SymbolID.getSymbolSet(symbolID);
624
+ let entityCode: int = SymbolID.getEntityCode(symbolID);
625
+ let version: int = SymbolID.getVersion(symbolID);
626
+
627
+ if (symbolSet === SymbolID.SymbolSet_ControlMeasure) {
628
+ if (entityCode === 200600) {
629
+ return Color.WHITE;
630
+ } else {
631
+ if (entityCode === 200700) {
632
+ return new Color(51, 136, 136);
633
+ } else {
634
+ if (entityCode === 200101) {
635
+ return new Color(255, 155, 0);
636
+ } else {
637
+ if (entityCode === 200201 || entityCode === 200202) {
638
+ return new Color(85, 119, 136);
639
+ } else {
640
+ if (version >= SymbolID.Version_2525E &&
641
+ (entityCode === 132100 || //key terrain
642
+ entityCode === 282001 || //Tower, Low
643
+ entityCode === 282002 || //Tower, High
644
+ entityCode === 282003)) { // Overhead wire
645
+ return new Color(128, 0, 128);//purple
646
+ }
647
+ }
648
+
649
+ }
650
+
651
+ }
652
+
653
+ }
654
+
655
+ }
656
+ } catch (e) {
657
+ if (e instanceof Error) {
658
+ ErrorLogger.LogException("SymbolUtilities", "getDefaultLineColor", e);
659
+ } else {
660
+ throw e;
661
+ }
662
+ }
663
+ return SymbolUtilities.getLineColorOfAffiliation(symbolID);
664
+ }
665
+
666
+ /**
667
+ * Checks if a symbol should be filled by default
668
+ *
669
+ * @param strSymbolID The 20 digit representation of the 2525D symbol
670
+ * @return true if there is a default fill
671
+ */
672
+ public static hasDefaultFill(strSymbolID: string): boolean {
673
+ let ec: int = SymbolID.getEntityCode(strSymbolID);
674
+ switch (ec) {
675
+ case 200101:
676
+ case 200201:
677
+ case 200202:
678
+ case 200600:
679
+ case 200700: {
680
+ return true;
681
+ }
682
+
683
+ default: {
684
+ return !SymbolUtilities.isTacticalGraphic(strSymbolID);
685
+ }
686
+
687
+ }
688
+ }
689
+
690
+ /**
691
+ * Determines if the symbol is a tactical graphic
692
+ *
693
+ * @param strSymbolID 30 Character string
694
+ * @return true if symbol set is 25 (control measure), or is a weather graphic
695
+ */
696
+ public static isTacticalGraphic(strSymbolID: string): boolean {
697
+ try {
698
+ let ss: int = SymbolID.getSymbolSet(strSymbolID);
699
+
700
+ if (ss === SymbolID.SymbolSet_ControlMeasure || SymbolUtilities.isWeather(strSymbolID)) {
701
+ return true;
702
+ }
703
+ } catch (e) {
704
+ if (e instanceof Error) {
705
+ ErrorLogger.LogException("SymbolUtilities", "getFillColorOfAffiliation", e);
706
+ } else {
707
+ throw e;
708
+ }
709
+ }
710
+ return false;
711
+ }
712
+
713
+ /**
714
+ * Determines if the Symbol can be rendered as a multipoint graphic and not just as an icon
715
+ * @param symbolID 30 Character string
716
+ * @return
717
+ */
718
+ public static isMultiPoint(symbolID: string): boolean {
719
+ let msi: MSInfo = MSLookup.getInstance().getMSLInfo(symbolID);
720
+ if (msi == null) {
721
+ return false;
722
+ }
723
+ let drawRule: int = msi.getDrawRule();
724
+ let ss: int = msi.getSymbolSet();
725
+ if (ss !== SymbolID.SymbolSet_ControlMeasure && ss !== SymbolID.SymbolSet_Oceanographic && ss !== SymbolID.SymbolSet_Atmospheric && ss !== SymbolID.SymbolSet_MeteorologicalSpace) {
726
+ return false;
727
+ }
728
+ else {
729
+ if (ss === SymbolID.SymbolSet_ControlMeasure) {
730
+ if (msi.getMaxPointCount() > 1) {
731
+
732
+ return true;
733
+ }
734
+
735
+ else {
736
+ if ((drawRule < DrawRules.POINT1 || drawRule > DrawRules.POINT16 || drawRule === DrawRules.POINT12) &&
737
+ drawRule !== DrawRules.DONOTDRAW && drawRule !== DrawRules.AREA22) {
738
+ return true;
739
+ }
740
+ else {
741
+
742
+ return false;
743
+ }
744
+
745
+ }
746
+
747
+ }
748
+ else {
749
+ if (ss === SymbolID.SymbolSet_Oceanographic || ss === SymbolID.SymbolSet_Atmospheric || ss === SymbolID.SymbolSet_MeteorologicalSpace) {
750
+ if (msi.getMaxPointCount() > 1) {
751
+
752
+ return true;
753
+ }
754
+
755
+ else {
756
+
757
+ return false;
758
+ }
759
+
760
+ }
761
+ }
762
+
763
+ }
764
+
765
+ return false;
766
+ }
767
+
768
+ public static isActionPoint(symbolID: string): boolean {
769
+ let msi: MSInfo = MSLookup.getInstance().getMSLInfo(symbolID);
770
+ if (msi.getDrawRule() === DrawRules.POINT1) {
771
+ let ec: int = SymbolID.getEntityCode(symbolID);
772
+ if (ec !== 131300 && ec !== 131301 && ec !== 182600 && ec !== 212800) {
773
+
774
+ return true;
775
+ }
776
+
777
+ }
778
+ return false;
779
+ }
780
+
781
+
782
+ /**
783
+ * Control Measures and Tactical Graphics that have labels but not with the Action Point layout
784
+ * @param strSymbolID 30 Character string
785
+ * @return
786
+ * @deprecated see {@link isSPWithSpecialModifierLayout(String)}
787
+ */
788
+ public static isTGSPWithSpecialModifierLayout(strSymbolID: string): boolean {
789
+ try {
790
+ let ss: int = SymbolID.getSymbolSet(strSymbolID);
791
+ let entityCode: int = SymbolID.getEntityCode(strSymbolID);
792
+ if (ss === SymbolID.SymbolSet_ControlMeasure) //|| isWeather(strSymbolID)) {
793
+ {
794
+ if (SymbolUtilities.isCBRNEvent(strSymbolID)) {
795
+
796
+ return true;
797
+ }
798
+
799
+
800
+ if (SymbolUtilities.isSonobuoy(strSymbolID)) {
801
+
802
+ return true;
803
+ }
804
+
805
+
806
+ switch (entityCode) {
807
+ case 130500: //contact point
808
+ case 130700: //decision point
809
+ case 212800: //harbor
810
+ case 131300: //point of interest
811
+ case 131800: //waypoint
812
+ case 240900: //fire support station
813
+ case 180100: //Air Control point
814
+ case 180200: //Communications Check point
815
+ case 160300: //T (target reference point)
816
+ case 240601: //ap,ap1,x,h (Point/Single Target)
817
+ case 240602: //ap (nuclear target)
818
+ case 270701: //static depiction
819
+ case 282001: //tower, low
820
+ case 282002: { //tower, high
821
+ return true;
822
+ }
823
+
824
+ default: {
825
+ return false;
826
+ }
827
+
828
+ }
829
+ }
830
+ else {
831
+ if (ss === SymbolID.SymbolSet_Atmospheric) {
832
+ switch (entityCode) {
833
+ case 162300: //Freezing Level
834
+ case 162200: //tropopause Level
835
+ case 110102: //tropopause Low
836
+ case 110202: { //tropopause High
837
+ return true;
838
+ }
839
+
840
+ default: {
841
+ return false;
842
+ }
843
+
844
+ }
845
+ }
846
+ }
847
+
848
+ } catch (e) {
849
+ if (e instanceof Error) {
850
+ ErrorLogger.LogException("SymbolUtilities", "isTGSPWithSpecialModifierLayout", e);
851
+ } else {
852
+ throw e;
853
+ }
854
+ }
855
+ return false;
856
+ }
857
+
858
+ /**
859
+ * Returns the fill color for the symbol based on its affiliation
860
+ * @param symbolID 30 Character string
861
+ * @return
862
+ */
863
+ public static getFillColorOfAffiliation(symbolID: string): Color | null {
864
+ let retColor: Color | null = null;
865
+ let entityCode: int = SymbolID.getEntityCode(symbolID);
866
+ let entity: int = SymbolID.getEntity(symbolID);
867
+ let entityType: int = SymbolID.getEntityType(symbolID);
868
+ let entitySubtype: int = SymbolID.getEntitySubtype(symbolID);
869
+
870
+ let affiliation: int = SymbolID.getAffiliation(symbolID);
871
+
872
+ try {
873
+ // We can't get the fill color if there is no symbol id, since that also means there is no affiliation
874
+ if ((symbolID == null) || (symbolID === "")) {
875
+ return null;
876
+ }
877
+ if (SymbolID.getSymbolSet(symbolID) === SymbolID.SymbolSet_ControlMeasure) {
878
+ switch (entityCode) {
879
+ case 200101: {
880
+ retColor = new Color(255, 155, 0, (.25 * 255) as int);
881
+ break;
882
+ }
883
+
884
+ case 200201:
885
+ case 200202:
886
+ case 200600: {
887
+ retColor = new Color(85, 119, 136, (.25 * 255) as int);
888
+ break;
889
+ }
890
+
891
+ case 200700: {
892
+ retColor = new Color(51, 136, 136, (.25 * 255) as int);
893
+ break;
894
+ }
895
+
896
+
897
+ default:
898
+
899
+ }
900
+ }
901
+ else {
902
+ if (SymbolID.getSymbolSet(symbolID) === SymbolID.SymbolSet_MineWarfare &&
903
+ (RendererSettings.getInstance().getSeaMineRenderMethod() === RendererSettings.SeaMineRenderMethod_MEDAL) &&
904
+ (!(entityCode === 110600 || entityCode === 110700))) {
905
+ retColor = new Color(0, 0, 0, 0);//transparent
906
+ }
907
+ }
908
+
909
+ //just do color by affiliation if no other color has been set yet
910
+ if (retColor == null) {
911
+ switch (affiliation) {
912
+ case SymbolID.StandardIdentity_Affiliation_Friend:
913
+ case SymbolID.StandardIdentity_Affiliation_AssumedFriend: {
914
+ retColor = AffiliationColors.FriendlyUnitFillColor;//0x00ffff; // Cyan
915
+ break;
916
+ }
917
+
918
+ case SymbolID.StandardIdentity_Affiliation_Hostile_Faker: {
919
+ retColor = AffiliationColors.HostileUnitFillColor;//0xfa8072; // Salmon
920
+ break;
921
+ }
922
+
923
+ case SymbolID.StandardIdentity_Affiliation_Suspect_Joker: {
924
+ if (SymbolID.getVersion(symbolID) >= SymbolID.Version_2525E) {
925
+
926
+ retColor = AffiliationColors.SuspectGraphicFillColor;
927
+ }
928
+ //255,229,153
929
+ else {
930
+
931
+ retColor = AffiliationColors.HostileGraphicFillColor;
932
+ }
933
+ //Color.RED;//0xff0000; // Red
934
+ break;
935
+ }
936
+
937
+ case SymbolID.StandardIdentity_Affiliation_Neutral: {
938
+ retColor = AffiliationColors.NeutralUnitFillColor;//0x7fff00; // Light Green
939
+ break;
940
+ }
941
+
942
+ default: {//unknown, pending, everything else
943
+ retColor = AffiliationColors.UnknownUnitFillColor;//new Color(255,250, 205); //0xfffacd; // LemonChiffon 255 250 205
944
+ break;
945
+ }
946
+
947
+ }
948
+ }
949
+ } catch (e) {
950
+ if (e instanceof Error) {
951
+ // Log Error
952
+ ErrorLogger.LogException("SymbolUtilities", "getFillColorOfAffiliation", e);
953
+ //throw e;
954
+ } else {
955
+ throw e;
956
+ }
957
+ } // End catch
958
+
959
+ return retColor;
960
+ } // End FillColorOfAffiliation
961
+
962
+ /**
963
+ *
964
+ * @param symbolID 30 Character string
965
+ * @param modifier {@link Modifiers}
966
+ * @return
967
+ * @deprecated see {@link hasModifier()}
968
+ */
969
+ public static canSymbolHaveModifier(symbolID: string, modifier: string): boolean {
970
+ return SymbolUtilities.hasModifier(symbolID, modifier);
971
+ }
972
+
973
+ /**
974
+ * Checks if the Symbol Code has FDI set.
975
+ * Does not check if the symbol can have an FDI.
976
+ * @param symbolID 30 Character string
977
+ * @return
978
+ */
979
+ public static hasFDI(symbolID: string): boolean {
980
+ let hqtfd: int = SymbolID.getHQTFD(symbolID);
981
+ if (hqtfd === SymbolID.HQTFD_FeintDummy
982
+ || hqtfd === SymbolID.HQTFD_FeintDummy_TaskForce
983
+ || hqtfd === SymbolID.HQTFD_FeintDummy_Headquarters
984
+ || hqtfd === SymbolID.HQTFD_FeintDummy_TaskForce_Headquarters) {
985
+ return true;
986
+ }
987
+ else {
988
+
989
+ return false;
990
+ }
991
+
992
+ }
993
+
994
+ /**
995
+ * Returns true if graphic is protection graphic (obstacles which render green)
996
+ * @param symbolID 30 Character string
997
+ * @return
998
+ */
999
+ public static isGreenProtectionGraphic(symbolID: string): boolean;
1000
+
1001
+ /***
1002
+ * Returns true if graphic is protection graphic (obstacles which render green)
1003
+ * Assumes control measure symbol code where SS == 25
1004
+ * @param entity
1005
+ * @param entityType
1006
+ * @param entitySubtype
1007
+ * @return
1008
+ */
1009
+ public static isGreenProtectionGraphic(entity: int, entityType: int, entitySubtype: int): boolean;
1010
+ public static isGreenProtectionGraphic(...args: unknown[]): boolean {
1011
+ switch (args.length) {
1012
+ case 1: {
1013
+ const [symbolID] = args as [string];
1014
+
1015
+
1016
+ if (SymbolID.getSymbolSet(symbolID) === SymbolID.SymbolSet_ControlMeasure) {
1017
+ return SymbolUtilities.isGreenProtectionGraphic(SymbolID.getEntity(symbolID), SymbolID.getEntityType(symbolID), SymbolID.getEntitySubtype(symbolID));
1018
+ } else {
1019
+ return false;
1020
+ }
1021
+
1022
+
1023
+ break;
1024
+ }
1025
+
1026
+ case 3: {
1027
+ const [entity, entityType, entitySubtype] = args as [int, int, int];
1028
+
1029
+
1030
+ if (entity >= 27 && entity <= 29)//Protection Areas, Points and Lines
1031
+ {
1032
+ if (entity === 27) {
1033
+ if (entityType > 0 && entityType <= 5) {
1034
+
1035
+ return true;
1036
+ }
1037
+
1038
+ else {
1039
+ if (entityType === 7 || entityType === 8 || entityType === 10 || entityType === 12) {
1040
+ return true;
1041
+ }
1042
+ else {
1043
+
1044
+ return false;
1045
+ }
1046
+
1047
+ }
1048
+
1049
+ }
1050
+ else {
1051
+ if (entity === 28) {
1052
+ if (entityType > 0 && entityType <= 7) {
1053
+
1054
+ return true;
1055
+ }
1056
+
1057
+ if (entityType === 19) {
1058
+
1059
+ return true;
1060
+ }
1061
+
1062
+ else {
1063
+
1064
+ return false;
1065
+ }
1066
+
1067
+ }
1068
+ else {
1069
+ if (entity === 29) {
1070
+ if (entityType >= 1 && entityType <= 5) {
1071
+
1072
+ return true;
1073
+ }
1074
+
1075
+ else {
1076
+
1077
+ return false;
1078
+ }
1079
+
1080
+ }
1081
+ }
1082
+
1083
+ }
1084
+
1085
+ }
1086
+ else {
1087
+ return false;
1088
+ }
1089
+ return false;
1090
+
1091
+
1092
+ break;
1093
+ }
1094
+
1095
+ default: {
1096
+ throw Error(`Invalid number of arguments`);
1097
+ }
1098
+ }
1099
+ }
1100
+
1101
+
1102
+ /**
1103
+ * Returns true if Symbol ID represents a chemical, biological, radiological or nuclear incident.
1104
+ * @param symbolID 30 Character string
1105
+ * @return
1106
+ */
1107
+ public static isCBRNEvent(symbolID: string): boolean {
1108
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1109
+ let ec: int = SymbolID.getEntityCode(symbolID);
1110
+
1111
+ if (ss === SymbolID.SymbolSet_ControlMeasure) {
1112
+ switch (ec) {
1113
+ case 281300:
1114
+ case 281400:
1115
+ case 281500:
1116
+ case 281600:
1117
+ case 281700: {
1118
+ return true;
1119
+ }
1120
+
1121
+ default:
1122
+ }
1123
+ }
1124
+ return false;
1125
+ }
1126
+
1127
+ /**
1128
+ * Returns true if Symbol ID represents a Sonobuoy.
1129
+ * @param symbolID 30 Character string
1130
+ * @return
1131
+ */
1132
+ public static isSonobuoy(symbolID: string): boolean {
1133
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1134
+ let e: int = SymbolID.getEntity(symbolID);
1135
+ let et: int = SymbolID.getEntityType(symbolID);
1136
+ if (ss === 25 && e === 21 && et === 35) {
1137
+
1138
+ return true;
1139
+ }
1140
+
1141
+ else {
1142
+
1143
+ return false;
1144
+ }
1145
+
1146
+ }
1147
+
1148
+ /**
1149
+ * Obstacles are generally required to have a green line color
1150
+ * @param symbolID 30 Character string
1151
+ * @return
1152
+ * @deprecated see {@link isGreenProtectionGraphic()}
1153
+ */
1154
+ public static isObstacle(symbolID: string): boolean {
1155
+
1156
+ if (SymbolID.getSymbolSet(symbolID) === SymbolID.SymbolSet_ControlMeasure &&
1157
+ SymbolID.getEntity(symbolID) === 27) {
1158
+ return true;
1159
+ }
1160
+ else {
1161
+
1162
+ return false;
1163
+ }
1164
+
1165
+ }
1166
+
1167
+ /**
1168
+ * Return true if symbol is from the Atmospheric, Oceanographic or Meteorological Space Symbol Sets.
1169
+ * @param symbolID 30 Character string
1170
+ * @return
1171
+ */
1172
+ public static isWeather(symbolID: string): boolean {
1173
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1174
+ if (ss >= SymbolID.SymbolSet_Atmospheric && ss <= SymbolID.SymbolSet_MeteorologicalSpace) {
1175
+
1176
+ return true;
1177
+ }
1178
+
1179
+ else {
1180
+
1181
+ return false;
1182
+ }
1183
+
1184
+ }
1185
+
1186
+ /**
1187
+ * Returns true if the symbol has the HQ staff indicated by the symbol ID
1188
+ * @param symbolID 30 Character string
1189
+ * @return
1190
+ */
1191
+ public static isHQ(symbolID: string): boolean {
1192
+ let hq: int = SymbolID.getHQTFD(symbolID);
1193
+ if (SymbolUtilities.hasModifier(symbolID, Modifiers.S_HQ_STAFF_INDICATOR) &&
1194
+ (hq === SymbolID.HQTFD_FeintDummy_Headquarters ||
1195
+ hq === SymbolID.HQTFD_Headquarters ||
1196
+ hq === SymbolID.HQTFD_FeintDummy_TaskForce_Headquarters ||
1197
+ hq === SymbolID.HQTFD_TaskForce_Headquarters)) {
1198
+
1199
+ return true;
1200
+ }
1201
+
1202
+ else {
1203
+
1204
+ return false;
1205
+ }
1206
+
1207
+ }
1208
+
1209
+ /**
1210
+ * Checks if this is a single point control measure or meteorological graphic with a unique layout.
1211
+ * Basically anything that's not an action point style graphic with modifiers
1212
+ * @param symbolID 30 Character string
1213
+ * @return
1214
+ */
1215
+ public static isSPWithSpecialModifierLayout(symbolID: string): boolean {
1216
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1217
+ let ec: int = SymbolID.getEntityCode(symbolID);
1218
+
1219
+ if (ss === SymbolID.SymbolSet_ControlMeasure) {
1220
+ switch (ec) {
1221
+ case 130500: //Control Point
1222
+ case 130700: //Decision Point
1223
+ case 131300: //Point of Interest
1224
+ case 131800: //Waypoint
1225
+ case 131900: //Airfield (AEGIS Only)
1226
+ case 132000: //Target Handover
1227
+ case 132100: //Key Terrain
1228
+ case 160300: //Target Point Reference
1229
+ case 180100: //Air Control Point
1230
+ case 180200: //Communications Check Point
1231
+ case 180600: //TACAN
1232
+ case 210300: //Defended Asset
1233
+ case 210600: //Air Detonation
1234
+ case 210800: //Impact Point
1235
+ case 211000: //Launched Torpedo
1236
+ case 212800: //Harbor
1237
+ case 213500: //Sonobuoy
1238
+ case 213501: //Ambient Noise Sonobuoy
1239
+ case 213502: //Air Transportable Communication (ATAC) (Sonobuoy)
1240
+ case 213503: //Barra (Sonobuoy)
1241
+ case 213504:
1242
+ case 213505:
1243
+ case 213506:
1244
+ case 213507:
1245
+ case 213508:
1246
+ case 213509:
1247
+ case 213510:
1248
+ case 213511:
1249
+ case 213512:
1250
+ case 213513:
1251
+ case 213514:
1252
+ case 213515:
1253
+ case 214900: //General Sea Subsurface Station
1254
+ case 215600: //General Sea Station
1255
+ case 217000: //Shore Control Station
1256
+ case 240601: //Point or Single Target
1257
+ case 240602: //Nuclear Target
1258
+ case 240900: //Fire Support Station
1259
+ case 250600: //Known Point
1260
+ case 270701: //Static Depiction
1261
+ case 282001: //Tower, Low
1262
+ case 282002: //Tower, High
1263
+ case 281300: //Chemical Event
1264
+ case 281400: //Biological Event
1265
+ case 281500: //Nuclear Event
1266
+ case 281600: //Nuclear Fallout Producing Event
1267
+ case 281700: { //Radiological Event
1268
+ return true;
1269
+ }
1270
+
1271
+ default: {
1272
+ return false;
1273
+ }
1274
+
1275
+ }
1276
+ }
1277
+ else {
1278
+ if (ss === SymbolID.SymbolSet_Atmospheric) {
1279
+ switch (ec) {
1280
+ case 162300: //Freezing Level
1281
+ case 162200: //tropopause Level
1282
+ case 110102: //tropopause low
1283
+ case 110202: { //tropopause high
1284
+ return true;
1285
+ }
1286
+
1287
+ default: {
1288
+ return false;
1289
+ }
1290
+
1291
+ }
1292
+ }
1293
+ }
1294
+
1295
+ return false;
1296
+ }
1297
+
1298
+ /**
1299
+ * Gets the anchor point for single point Control Measure as the anchor point isn't always they center of the symbol.
1300
+ * @param symbolID 30 Character string
1301
+ * @param bounds {@link Rectangle2D} representing the bound of the core symbol in the image.
1302
+ * @return representing the point in the image that is the anchor point of the symbol.
1303
+ */
1304
+ public static getCMSymbolAnchorPoint(symbolID: string, bounds: Rectangle2D): Point {
1305
+
1306
+ let centerX: double = bounds.getWidth() / 2;
1307
+ let centerY: double = bounds.getHeight() / 2;
1308
+
1309
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1310
+ let ec: int = SymbolID.getEntityCode(symbolID);
1311
+ let msi: MSInfo;
1312
+ let drawRule: int = 0;
1313
+
1314
+ //center/anchor point is always half width and half height except for control measures
1315
+ //and meteorological
1316
+ if (ss === SymbolID.SymbolSet_ControlMeasure) {
1317
+ drawRule = MSLookup.getInstance().getMSLInfo(symbolID).getDrawRule();
1318
+ switch (drawRule)//here we check the 'Y' value for the anchor point
1319
+ {
1320
+ case DrawRules.POINT1://action points //bottom center
1321
+ case DrawRules.POINT5://entry point
1322
+ case DrawRules.POINT6://ground zero
1323
+ case DrawRules.POINT7: {//missile detection point
1324
+ centerY = bounds.getHeight();
1325
+ break;
1326
+ }
1327
+
1328
+ case DrawRules.POINT4: {//drop point //almost bottom and center
1329
+ centerY = (bounds.getHeight() * 0.80);
1330
+ break;
1331
+ }
1332
+
1333
+ case DrawRules.POINT10: {//Sonobuoy //center of circle which isn't center of symbol
1334
+ centerY = (bounds.getHeight() * 0.75);
1335
+ break;
1336
+ }
1337
+
1338
+ case DrawRules.POINT13: {//booby trap //almost bottom and center
1339
+ centerY = (bounds.getHeight() * 0.74);
1340
+ break;
1341
+ }
1342
+
1343
+ case DrawRules.POINT15: {//Marine Life //center left
1344
+ centerX = 0;
1345
+ break;
1346
+ }
1347
+
1348
+ case DrawRules.POINT16: {//Tower //circle at base of tower
1349
+ centerY = (bounds.getHeight() * 0.87);
1350
+ break;
1351
+ }
1352
+
1353
+ case DrawRules.POINT2: {//Several different symbols
1354
+ if (ec === 280500) {
1355
+ //Wide Area Antitank Mine
1356
+ centerY = (bounds.getHeight() * 0.35);
1357
+ } else if (ec === 280400) {
1358
+ //Antitank Mine w/ Anti-handling Device
1359
+ centerY = (bounds.getHeight() * 0.33);
1360
+ } else if (ec === 280200) {
1361
+ //Antipersonnel Mine
1362
+ centerY = (bounds.getHeight() * 0.7);
1363
+ } else if (ec === 280201) {
1364
+ //Antipersonnel Mine with Directional Effects
1365
+ centerY = (bounds.getHeight() * 0.65);
1366
+ } else if (ec === 219000) {
1367
+ //Sea Anomaly
1368
+ centerY = (bounds.getHeight() * 0.7);
1369
+ } else if (ec === 212500) {
1370
+ //Electromagnetic - Magnetic Anomaly Detections (MAD)
1371
+ centerY = (bounds.getHeight() * 0.4);
1372
+ }
1373
+ break;
1374
+ }
1375
+
1376
+ default:
1377
+ }
1378
+
1379
+ switch (ec)
1380
+ //have to adjust center X as some graphics have integrated text outside the symbol
1381
+ {
1382
+ case 180400: { //Pickup Point (PUP)
1383
+ centerX = bounds.getWidth() * 0.3341;
1384
+ break;
1385
+ }
1386
+
1387
+ case 240900: { //Fire Support Station
1388
+ centerX = bounds.getWidth() * 0.38;
1389
+ break;
1390
+ }
1391
+
1392
+ case 280201: { //Antipersonnel Mine with Directional Effects
1393
+ centerX = bounds.getWidth() * 0.43;
1394
+ break;
1395
+ }
1396
+ }
1397
+ }
1398
+
1399
+ return new Point(Math.round(centerX), Math.round(centerY));
1400
+ }
1401
+
1402
+
1403
+ /**
1404
+ * Returns true if the symbol is an installation
1405
+ * @param symbolID 30 Character string
1406
+ * @return
1407
+ */
1408
+
1409
+ public static isInstallation(symbolID: string): boolean {
1410
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1411
+ let entity: int = SymbolID.getEntity(symbolID);
1412
+ if (ss === SymbolID.SymbolSet_LandInstallation && entity === 11) {
1413
+
1414
+ return true;
1415
+ }
1416
+
1417
+ else {
1418
+
1419
+ return false;
1420
+ }
1421
+
1422
+ }
1423
+
1424
+ /**
1425
+ * Returns true if the symbol is from an air based symbol set
1426
+ * @param symbolID 30 Character string
1427
+ * @return
1428
+ */
1429
+ public static isAir(symbolID: string): boolean {
1430
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1431
+ let entity: int = SymbolID.getEntity(symbolID);
1432
+ if (ss === SymbolID.SymbolSet_Air ||
1433
+ ss === SymbolID.SymbolSet_AirMissile ||
1434
+ ss === SymbolID.SymbolSet_SignalsIntelligence_Air) {
1435
+
1436
+ return true;
1437
+ }
1438
+
1439
+ else {
1440
+
1441
+ return false;
1442
+ }
1443
+
1444
+ }
1445
+
1446
+ /**
1447
+ * Returns true if the symbol is from a space based symbol set
1448
+ * @param symbolID 30 Character string
1449
+ * @return
1450
+ */
1451
+ public static isSpace(symbolID: string): boolean {
1452
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1453
+ let entity: int = SymbolID.getEntity(symbolID);
1454
+ if (ss === SymbolID.SymbolSet_Space ||
1455
+ ss === SymbolID.SymbolSet_SpaceMissile ||
1456
+ ss === SymbolID.SymbolSet_SignalsIntelligence_Space) {
1457
+
1458
+ return true;
1459
+ }
1460
+
1461
+ else {
1462
+
1463
+ return false;
1464
+ }
1465
+
1466
+ }
1467
+
1468
+ /**
1469
+ * Returns true if the symbol is from a land based symbol set
1470
+ * @param symbolID 30 Character string
1471
+ * @return
1472
+ */
1473
+ public static isLand(symbolID: string): boolean {
1474
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1475
+ let entity: int = SymbolID.getEntity(symbolID);
1476
+ if (ss === SymbolID.SymbolSet_LandUnit ||
1477
+ ss === SymbolID.SymbolSet_LandCivilianUnit_Organization ||
1478
+ ss === SymbolID.SymbolSet_LandEquipment ||
1479
+ ss === SymbolID.SymbolSet_LandInstallation ||
1480
+ ss === SymbolID.SymbolSet_SignalsIntelligence_Land) {
1481
+
1482
+ return true;
1483
+ }
1484
+
1485
+ else {
1486
+
1487
+ return false;
1488
+ }
1489
+
1490
+ }
1491
+
1492
+ /**
1493
+ * Returns true if the symbol ID has the task for indicator
1494
+ * @param symbolID 30 Character string
1495
+ * @return
1496
+ */
1497
+ public static isTaskForce(symbolID: string): boolean {
1498
+ let hqtfd: int = SymbolID.getHQTFD(symbolID);
1499
+ if ((hqtfd === SymbolID.HQTFD_TaskForce ||
1500
+ hqtfd === SymbolID.HQTFD_TaskForce_Headquarters ||
1501
+ hqtfd === SymbolID.HQTFD_FeintDummy_TaskForce ||
1502
+ hqtfd === SymbolID.HQTFD_FeintDummy_TaskForce_Headquarters) &&
1503
+ SymbolUtilities.canSymbolHaveModifier(symbolID, Modifiers.B_ECHELON)) {
1504
+
1505
+ return true;
1506
+ }
1507
+
1508
+ else {
1509
+
1510
+ return false;
1511
+ }
1512
+
1513
+ }
1514
+
1515
+ /**
1516
+ * Returns true if the symbol ID indicates the context is Reality
1517
+ * @param symbolID 30 Character string
1518
+ * @return
1519
+ */
1520
+ public static isReality(symbolID: string): boolean {
1521
+ let c: int = SymbolID.getContext(symbolID);
1522
+ if (c === SymbolID.StandardIdentity_Context_Reality ||
1523
+ c === 3 || c === 4) {
1524
+
1525
+ return true;
1526
+ }
1527
+
1528
+ else {
1529
+
1530
+ return false;
1531
+ }
1532
+
1533
+ }
1534
+
1535
+ /**
1536
+ * Returns true if the symbol ID indicates the context is Exercise
1537
+ * @param symbolID 30 Character string
1538
+ * @return
1539
+ */
1540
+ public static isExercise(symbolID: string): boolean {
1541
+ let c: int = SymbolID.getContext(symbolID);
1542
+ if (c === SymbolID.StandardIdentity_Context_Exercise ||
1543
+ c === 5 || c === 6) {
1544
+
1545
+ return true;
1546
+ }
1547
+
1548
+ else {
1549
+
1550
+ return false;
1551
+ }
1552
+
1553
+ }
1554
+
1555
+ /**
1556
+ * Returns true if the symbol ID indicates the context is Simulation
1557
+ * @param symbolID 30 Character string
1558
+ * @return
1559
+ */
1560
+ public static isSimulation(symbolID: string): boolean {
1561
+ let c: int = SymbolID.getContext(symbolID);
1562
+ if (c === SymbolID.StandardIdentity_Context_Simulation ||
1563
+ c === 7 || c === 8) {
1564
+
1565
+ return true;
1566
+ }
1567
+
1568
+ else {
1569
+
1570
+ return false;
1571
+ }
1572
+
1573
+ }
1574
+
1575
+
1576
+
1577
+ /**
1578
+ * Reads the Symbol ID string and returns the text that represents the echelon
1579
+ * code.
1580
+ * @param echelon from positions 9-10 in the symbol ID
1581
+ * See {@link SymbolID.getAmplifierDescriptor()}
1582
+ * @return string (23 (Army) would be "XXXX")
1583
+ */
1584
+ public static getEchelonText(echelon: int): string {
1585
+ let text: string;
1586
+ if (echelon === SymbolID.Echelon_Team_Crew) {
1587
+ text = '\u{00D8}';
1588
+ } else if (echelon === SymbolID.Echelon_Squad) {
1589
+ text = '\u{2022}';
1590
+ } else if (echelon === SymbolID.Echelon_Section) {
1591
+ text = '\u{2022}\u{2022}';
1592
+ } else if (echelon === SymbolID.Echelon_Platoon_Detachment) {
1593
+ text = '\u{2022}\u{2022}\u{2022}';
1594
+ } else if (echelon === SymbolID.Echelon_Company_Battery_Troop) {
1595
+ text = "I";
1596
+ } else if (echelon === SymbolID.Echelon_Battalion_Squadron) {
1597
+ text = "II";
1598
+ } else if (echelon === SymbolID.Echelon_Regiment_Group) {
1599
+ text = "III";
1600
+ } else if (echelon === SymbolID.Echelon_Brigade) {
1601
+ text = "X";
1602
+ } else if (echelon === SymbolID.Echelon_Division) {
1603
+ text = "XX";
1604
+ } else if (echelon === SymbolID.Echelon_Corps_MEF) {
1605
+ text = "XXX";
1606
+ } else if (echelon === SymbolID.Echelon_Army) {
1607
+ text = "XXXX";
1608
+ } else if (echelon === SymbolID.Echelon_ArmyGroup_Front) {
1609
+ text = "XXXXX";
1610
+ } else if (echelon === SymbolID.Echelon_Region_Theater) {
1611
+ text = "XXXXXX";
1612
+ } else if (echelon === SymbolID.Echelon_Region_Command) {
1613
+ text = "++";
1614
+ }
1615
+ return text;
1616
+ }
1617
+
1618
+ /**
1619
+ * Returns the Standard Identity Modifier based on the Symbol ID
1620
+ * @param symbolID 30 Character string
1621
+ * @return string
1622
+ */
1623
+ public static getStandardIdentityModifier(symbolID: string): string {
1624
+ let textChar: string;
1625
+ let si: int = SymbolID.getStandardIdentity(symbolID);
1626
+ let context: int = SymbolID.getContext(symbolID);
1627
+ let affiliation: int = SymbolID.getAffiliation(symbolID);
1628
+
1629
+ if (context === SymbolID.StandardIdentity_Context_Simulation) {
1630
+ //Simulation
1631
+ textChar = "S";
1632
+ }
1633
+
1634
+ else {
1635
+ if (context === SymbolID.StandardIdentity_Context_Exercise) {
1636
+ if (affiliation === SymbolID.StandardIdentity_Affiliation_Suspect_Joker) {
1637
+ //exercise Joker
1638
+ textChar = "J";
1639
+ } else if (affiliation === SymbolID.StandardIdentity_Affiliation_Hostile_Faker) {
1640
+ //exercise faker
1641
+ textChar = "K";
1642
+ } else if (context === SymbolID.StandardIdentity_Context_Exercise) {
1643
+ //exercise
1644
+ textChar = "X";
1645
+ }
1646
+ }
1647
+ }
1648
+
1649
+
1650
+ return textChar;
1651
+ }
1652
+
1653
+ /**
1654
+ * Returns true if the unit has a rectangle frame
1655
+ * @param symbolID 30 Character string
1656
+ * @return
1657
+ */
1658
+ public static hasRectangleFrame(symbolID: string): boolean {
1659
+ let affiliation: int = SymbolID.getAffiliation(symbolID);
1660
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1661
+ if (ss !== SymbolID.SymbolSet_ControlMeasure) {
1662
+ if (affiliation === SymbolID.StandardIdentity_Affiliation_Friend
1663
+ || affiliation === SymbolID.StandardIdentity_Affiliation_AssumedFriend
1664
+ || (SymbolID.getContext(symbolID) === SymbolID.StandardIdentity_Context_Exercise &&
1665
+ (affiliation === SymbolID.StandardIdentity_Affiliation_Hostile_Faker
1666
+ || affiliation === SymbolID.StandardIdentity_Affiliation_Suspect_Joker))) {
1667
+ return true;
1668
+ }
1669
+ else {
1670
+
1671
+ return false;
1672
+ }
1673
+
1674
+ }
1675
+ else {
1676
+
1677
+ return false;
1678
+ }
1679
+
1680
+ }
1681
+
1682
+ /**
1683
+ * Returns the height ratio for the unit specified by the symbol ID
1684
+ * Based on Figure 4 in 2525E.
1685
+ * @param symbolID 30 Character string
1686
+ * @return
1687
+ */
1688
+ public static getUnitRatioHeight(symbolID: string): double {
1689
+ let ver: int = SymbolID.getVersion(symbolID);
1690
+ let aff: int = SymbolID.getAffiliation(symbolID);
1691
+
1692
+ let rh: double = 0;
1693
+
1694
+ if (ver < SymbolID.Version_2525E) {
1695
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1696
+
1697
+ if (aff === SymbolID.StandardIdentity_Affiliation_Hostile_Faker ||
1698
+ aff === SymbolID.StandardIdentity_Affiliation_Suspect_Joker) {
1699
+ switch (ss) {
1700
+ case SymbolID.SymbolSet_LandCivilianUnit_Organization:
1701
+ case SymbolID.SymbolSet_LandUnit:
1702
+ case SymbolID.SymbolSet_LandInstallation:
1703
+ case SymbolID.SymbolSet_LandEquipment:
1704
+ case SymbolID.SymbolSet_SignalsIntelligence_Land:
1705
+ case SymbolID.SymbolSet_Activities:
1706
+ case SymbolID.SymbolSet_CyberSpace: {
1707
+ rh = 1.44;
1708
+ break;
1709
+ }
1710
+
1711
+ default: {
1712
+ rh = 1.3;
1713
+ }
1714
+
1715
+ }
1716
+ }
1717
+ else {
1718
+ if (aff === SymbolID.StandardIdentity_Affiliation_Friend ||
1719
+ aff === SymbolID.StandardIdentity_Affiliation_AssumedFriend) {
1720
+ switch (ss) {
1721
+ case SymbolID.SymbolSet_LandCivilianUnit_Organization:
1722
+ case SymbolID.SymbolSet_LandUnit:
1723
+ case SymbolID.SymbolSet_LandInstallation:
1724
+ case SymbolID.SymbolSet_SignalsIntelligence_Land:
1725
+ case SymbolID.SymbolSet_Activities:
1726
+ case SymbolID.SymbolSet_CyberSpace: {
1727
+ rh = 1;
1728
+ break;
1729
+ }
1730
+
1731
+ default: {
1732
+ rh = 1.2;
1733
+ }
1734
+
1735
+ }
1736
+ }
1737
+ else {
1738
+ if (aff === SymbolID.StandardIdentity_Affiliation_Neutral) {
1739
+ switch (ss) {
1740
+ case SymbolID.SymbolSet_LandCivilianUnit_Organization:
1741
+ case SymbolID.SymbolSet_LandUnit:
1742
+ case SymbolID.SymbolSet_LandInstallation:
1743
+ case SymbolID.SymbolSet_LandEquipment:
1744
+ case SymbolID.SymbolSet_SignalsIntelligence_Land:
1745
+ case SymbolID.SymbolSet_Activities:
1746
+ case SymbolID.SymbolSet_CyberSpace: {
1747
+ rh = 1.1;
1748
+ break;
1749
+ }
1750
+
1751
+ default: {
1752
+ rh = 1.2;
1753
+ }
1754
+
1755
+ }
1756
+ }
1757
+ else //UNKNOWN
1758
+ {
1759
+ switch (ss) {
1760
+ case SymbolID.SymbolSet_LandCivilianUnit_Organization:
1761
+ case SymbolID.SymbolSet_LandUnit:
1762
+ case SymbolID.SymbolSet_LandInstallation:
1763
+ case SymbolID.SymbolSet_LandEquipment:
1764
+ case SymbolID.SymbolSet_SignalsIntelligence_Land:
1765
+ case SymbolID.SymbolSet_Activities:
1766
+ case SymbolID.SymbolSet_CyberSpace: {
1767
+ rh = 1.44;
1768
+ break;
1769
+ }
1770
+
1771
+ default: {
1772
+ rh = 1.3;
1773
+ }
1774
+
1775
+ }
1776
+ }
1777
+ }
1778
+
1779
+ }
1780
+
1781
+ }
1782
+ else //2525E and up
1783
+ {
1784
+ let frameID: string = SVGLookup.getFrameID(symbolID);
1785
+ if (frameID.length === 6) {
1786
+
1787
+ aff = parseInt(frameID.substring(2, 3));
1788
+ }
1789
+
1790
+ else {
1791
+ //"octagon"
1792
+ return 1;
1793
+ }
1794
+
1795
+ let fs: string = (frameID.charAt(3));
1796
+
1797
+ if (aff === SymbolID.StandardIdentity_Affiliation_Hostile_Faker ||
1798
+ aff === SymbolID.StandardIdentity_Affiliation_Suspect_Joker) {
1799
+ switch (fs) {
1800
+ case SymbolID.FrameShape_LandUnit:
1801
+ case SymbolID.FrameShape_LandInstallation:
1802
+ case SymbolID.FrameShape_LandEquipment_SeaSurface:
1803
+ case SymbolID.FrameShape_Activity_Event:
1804
+ case SymbolID.FrameShape_Cyberspace: {
1805
+ rh = 1.44;
1806
+ break;
1807
+ }
1808
+
1809
+ default: {
1810
+ rh = 1.3;
1811
+ }
1812
+
1813
+ }
1814
+ }
1815
+ else {
1816
+ if (aff === SymbolID.StandardIdentity_Affiliation_Friend ||
1817
+ aff === SymbolID.StandardIdentity_Affiliation_AssumedFriend) {
1818
+ switch (fs) {
1819
+ case SymbolID.FrameShape_LandUnit:
1820
+ case SymbolID.FrameShape_LandInstallation:
1821
+ case SymbolID.FrameShape_Activity_Event:
1822
+ case SymbolID.FrameShape_Cyberspace: {
1823
+ rh = 1;
1824
+ break;
1825
+ }
1826
+
1827
+ default: {
1828
+ rh = 1.2;
1829
+ }
1830
+
1831
+ }
1832
+ }
1833
+ else {
1834
+ if (aff === SymbolID.StandardIdentity_Affiliation_Neutral) {
1835
+ switch (fs) {
1836
+ case SymbolID.FrameShape_LandUnit:
1837
+ case SymbolID.FrameShape_LandInstallation:
1838
+ case SymbolID.FrameShape_LandEquipment_SeaSurface:
1839
+ case SymbolID.FrameShape_Activity_Event:
1840
+ case SymbolID.FrameShape_Cyberspace: {
1841
+ rh = 1.1;
1842
+ break;
1843
+ }
1844
+
1845
+ default: {
1846
+ rh = 1.2;
1847
+ }
1848
+
1849
+ }
1850
+ }
1851
+ else //UNKNOWN
1852
+ {
1853
+ switch (fs) {
1854
+ case SymbolID.FrameShape_LandUnit:
1855
+ case SymbolID.FrameShape_LandInstallation:
1856
+ case SymbolID.FrameShape_LandEquipment_SeaSurface:
1857
+ case SymbolID.FrameShape_Activity_Event:
1858
+ case SymbolID.FrameShape_Cyberspace: {
1859
+ rh = 1.44;
1860
+ break;
1861
+ }
1862
+
1863
+ default: {
1864
+ rh = 1.3;
1865
+ }
1866
+
1867
+ }
1868
+ }
1869
+ }
1870
+
1871
+ }
1872
+
1873
+
1874
+
1875
+ }
1876
+
1877
+ return rh;
1878
+ }
1879
+
1880
+ /**
1881
+ * Returns the width ratio for the unit specified by the symbol ID
1882
+ * Based on Figure 4 in 2525E.
1883
+ * @param symbolID 30 Character string
1884
+ * @return
1885
+ */
1886
+ public static getUnitRatioWidth(symbolID: string): double {
1887
+ let ver: int = SymbolID.getVersion(symbolID);
1888
+ let aff: int = SymbolID.getAffiliation(symbolID);
1889
+
1890
+ let rw: double = 0;
1891
+
1892
+ if (ver < SymbolID.Version_2525E) {
1893
+ let ss: int = SymbolID.getSymbolSet(symbolID);
1894
+
1895
+ if (aff === SymbolID.StandardIdentity_Affiliation_Hostile_Faker ||
1896
+ aff === SymbolID.StandardIdentity_Affiliation_Suspect_Joker) {
1897
+ switch (ss) {
1898
+ case SymbolID.SymbolSet_LandCivilianUnit_Organization:
1899
+ case SymbolID.SymbolSet_LandUnit:
1900
+ case SymbolID.SymbolSet_LandInstallation:
1901
+ case SymbolID.SymbolSet_LandEquipment:
1902
+ case SymbolID.SymbolSet_SignalsIntelligence_Land:
1903
+ case SymbolID.SymbolSet_Activities:
1904
+ case SymbolID.SymbolSet_CyberSpace: {
1905
+ rw = 1.44;
1906
+ break;
1907
+ }
1908
+
1909
+ default: {
1910
+ rw = 1.1;
1911
+ }
1912
+
1913
+ }
1914
+ }
1915
+ else {
1916
+ if (aff === SymbolID.StandardIdentity_Affiliation_Friend ||
1917
+ aff === SymbolID.StandardIdentity_Affiliation_AssumedFriend) {
1918
+ switch (ss) {
1919
+ case SymbolID.SymbolSet_LandCivilianUnit_Organization:
1920
+ case SymbolID.SymbolSet_LandUnit:
1921
+ case SymbolID.SymbolSet_LandInstallation:
1922
+ case SymbolID.SymbolSet_SignalsIntelligence_Land:
1923
+ case SymbolID.SymbolSet_Activities:
1924
+ case SymbolID.SymbolSet_CyberSpace: {
1925
+ rw = 1.5;
1926
+ break;
1927
+ }
1928
+
1929
+ case SymbolID.SymbolSet_LandEquipment: {
1930
+ rw = 1.2;
1931
+ break;
1932
+ }
1933
+
1934
+ default: {
1935
+ rw = 1.1;
1936
+ }
1937
+
1938
+ }
1939
+ }
1940
+ else {
1941
+ if (aff === SymbolID.StandardIdentity_Affiliation_Neutral) {
1942
+ rw = 1.1;
1943
+ }
1944
+ else //UNKNOWN
1945
+ {
1946
+ switch (ss) {
1947
+ case SymbolID.SymbolSet_LandCivilianUnit_Organization:
1948
+ case SymbolID.SymbolSet_LandUnit:
1949
+ case SymbolID.SymbolSet_LandInstallation:
1950
+ case SymbolID.SymbolSet_LandEquipment:
1951
+ case SymbolID.SymbolSet_SignalsIntelligence_Land:
1952
+ case SymbolID.SymbolSet_Activities:
1953
+ case SymbolID.SymbolSet_CyberSpace: {
1954
+ rw = 1.44;
1955
+ break;
1956
+ }
1957
+
1958
+ default: {
1959
+ rw = 1.5;
1960
+ }
1961
+
1962
+ }
1963
+ }
1964
+ }
1965
+
1966
+ }
1967
+
1968
+ }
1969
+ else //2525E and above
1970
+ {
1971
+ let frameID: string = SVGLookup.getFrameID(symbolID);
1972
+ if (frameID.length === 6) {
1973
+
1974
+ aff = parseInt(frameID.substring(2, 3));
1975
+ }
1976
+
1977
+ else {
1978
+ //"octagon"
1979
+ return 1;
1980
+ }
1981
+
1982
+ let fs: string = (frameID.charAt(3));
1983
+
1984
+ if (aff === SymbolID.StandardIdentity_Affiliation_Hostile_Faker ||
1985
+ aff === SymbolID.StandardIdentity_Affiliation_Suspect_Joker) {
1986
+ switch (fs) {
1987
+ case SymbolID.FrameShape_LandUnit:
1988
+ case SymbolID.FrameShape_LandInstallation:
1989
+ case SymbolID.FrameShape_LandEquipment_SeaSurface:
1990
+ case SymbolID.FrameShape_Activity_Event:
1991
+ case SymbolID.FrameShape_Cyberspace: {
1992
+ rw = 1.44;
1993
+ break;
1994
+ }
1995
+
1996
+ default: {
1997
+ rw = 1.1;
1998
+ }
1999
+
2000
+ }
2001
+ }
2002
+ else {
2003
+ if (aff === SymbolID.StandardIdentity_Affiliation_Friend ||
2004
+ aff === SymbolID.StandardIdentity_Affiliation_AssumedFriend) {
2005
+ switch (fs) {
2006
+ case SymbolID.FrameShape_LandUnit:
2007
+ case SymbolID.FrameShape_LandInstallation:
2008
+ case SymbolID.FrameShape_Activity_Event:
2009
+ case SymbolID.FrameShape_Cyberspace: {
2010
+ rw = 1.5;
2011
+ break;
2012
+ }
2013
+
2014
+ case SymbolID.FrameShape_LandEquipment_SeaSurface: {
2015
+ rw = 1.2;
2016
+ break;
2017
+ }
2018
+
2019
+ default: {
2020
+ rw = 1.1;
2021
+ }
2022
+
2023
+ }
2024
+ }
2025
+ else {
2026
+ if (aff === SymbolID.StandardIdentity_Affiliation_Neutral) {
2027
+ rw = 1.1;
2028
+ }
2029
+ else //UNKNOWN
2030
+ {
2031
+ switch (fs) {
2032
+ case SymbolID.FrameShape_LandUnit:
2033
+ case SymbolID.FrameShape_LandInstallation:
2034
+ case SymbolID.FrameShape_LandEquipment_SeaSurface:
2035
+ case SymbolID.FrameShape_Activity_Event:
2036
+ case SymbolID.FrameShape_Cyberspace: {
2037
+ rw = 1.44;
2038
+ break;
2039
+ }
2040
+
2041
+ default: {
2042
+ rw = 1.5;
2043
+ }
2044
+
2045
+ }
2046
+ }
2047
+ }
2048
+
2049
+ }
2050
+
2051
+ }
2052
+
2053
+ return rw;
2054
+ }
2055
+
2056
+ /**
2057
+ * @param linetype the line type
2058
+ * @return true if the line is a basic shape
2059
+ */
2060
+ public static isBasicShape(linetype: int): boolean {
2061
+ switch (linetype) {
2062
+ case TacticalLines.BS_AREA:
2063
+ case TacticalLines.BS_LINE:
2064
+ case TacticalLines.BS_CROSS:
2065
+ case TacticalLines.BS_ELLIPSE:
2066
+ case TacticalLines.PBS_ELLIPSE:
2067
+ case TacticalLines.PBS_CIRCLE:
2068
+ case TacticalLines.PBS_SQUARE:
2069
+ case TacticalLines.PBS_RECTANGLE:
2070
+ case TacticalLines.BS_RECTANGLE:
2071
+ case TacticalLines.BBS_AREA:
2072
+ case TacticalLines.BBS_LINE:
2073
+ case TacticalLines.BBS_POINT:
2074
+ case TacticalLines.BBS_RECTANGLE:
2075
+ case TacticalLines.BS_BBOX: {
2076
+ return true;
2077
+ }
2078
+ default: {
2079
+ return false;
2080
+ }
2081
+ }
2082
+ }
2083
+
2084
+ }
2085
+