@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,3798 @@
1
+ import { POINT2 } from "../../JavaLineArray/POINT2";
2
+ import { TGLight } from "../../JavaTacticalRenderer/TGLight";
3
+ import { clsRenderer } from "../../RenderMultipoints/clsRenderer";
4
+ import { AffineTransform } from "../../graphics2d/AffineTransform";
5
+ import { BasicStroke } from "../../graphics2d/BasicStroke";
6
+ import { Font } from "../../graphics2d/Font";
7
+ import { Point2D } from "../../graphics2d/Point2D";
8
+ import { Rectangle } from "../../graphics2d/Rectangle";
9
+ import { Rectangle2D } from "../../graphics2d/Rectangle2D";
10
+ import { Color } from "../../renderer/utilities/Color";
11
+ import { DistanceUnit } from "../../renderer/utilities/DistanceUnit";
12
+ import { DrawRules } from "../../renderer/utilities/DrawRules";
13
+ import { ErrorLogger } from "../../renderer/utilities/ErrorLogger";
14
+ import { GENCLookup } from "../../renderer/utilities/GENCLookup";
15
+ import { IPointConversion } from "../../renderer/utilities/IPointConversion";
16
+ import { LogLevel } from "../../renderer/utilities/LogLevel";
17
+ import { MSInfo } from "../../renderer/utilities/MSInfo";
18
+ import { MSLookup } from "../../renderer/utilities/MSLookup";
19
+ import { MilStdAttributes } from "../../renderer/utilities/MilStdAttributes";
20
+ import { MilStdSymbol } from "../../renderer/utilities/MilStdSymbol";
21
+ import { Modifiers } from "../../renderer/utilities/Modifiers";
22
+ import { PointConversion } from "../../renderer/utilities/PointConversion";
23
+ import { RendererSettings } from "../../renderer/utilities/RendererSettings";
24
+ import { RendererUtilities } from "../../renderer/utilities/RendererUtilities";
25
+ import { ShapeInfo } from "../../renderer/utilities/ShapeInfo";
26
+ import { SymbolID } from "../../renderer/utilities/SymbolID";
27
+ import { SymbolUtilities } from "../../renderer/utilities/SymbolUtilities";
28
+ import { GeoPixelConversion } from "./GeoPixelConversion";
29
+ import { PointConverter } from "./PointConverter";
30
+ import { JavaRendererUtilities } from "./utilities/JavaRendererUtilities";
31
+ import { LineInfo } from "./utilities/LineInfo";
32
+ import { SymbolInfo } from "./utilities/SymbolInfo";
33
+ import { TextInfo } from "./utilities/TextInfo";
34
+ import { mdlGeodesic } from "../../JavaTacticalRenderer/mdlGeodesic";
35
+ import { MultiPointHandlerSVG } from "./MultiPointHandlerSVG";
36
+ import { WebRenderer } from "./WebRenderer";
37
+
38
+ import { type int, type double } from "../../graphics2d/BasicTypes";
39
+
40
+ export class MultiPointHandler {
41
+ private static readonly _maxPixelWidth: int = 1920;
42
+ private static readonly _minPixelWidth: int = 720;
43
+
44
+
45
+
46
+ /**
47
+ * GE has the unusual distinction of being an application with coordinates
48
+ * outside its own extents. It appears to only be a problem when lines cross
49
+ * the IDL
50
+ *
51
+ * @param pts2d the client points
52
+ */
53
+ public static NormalizeGECoordsToGEExtents(leftLongitude: double,
54
+ rightLongitude: double,
55
+ pts2d: Array<Point2D>): void {
56
+ try {
57
+ let j: int = 0;
58
+ let x: double = 0;
59
+ let y: double = 0;
60
+ let pt2d: Point2D;
61
+ let n: int = pts2d.length;
62
+ //for (j = 0; j < pts2d.length; j++)
63
+ for (j = 0; j < n; j++) {
64
+ pt2d = pts2d[j];
65
+ x = pt2d.getX();
66
+ y = pt2d.getY();
67
+ while (x < leftLongitude) {
68
+ x += 360;
69
+ }
70
+ while (x > rightLongitude) {
71
+ x -= 360;
72
+ }
73
+
74
+ pt2d = new Point2D(x, y);
75
+ pts2d[j] = pt2d;
76
+ }
77
+ } catch (exc) {
78
+ if (exc instanceof Error) {
79
+ } else {
80
+ throw exc;
81
+ }
82
+ }
83
+ }
84
+
85
+ /**
86
+ * GE recognizes coordinates in the range of -180 to +180
87
+ *
88
+ * @param pt2d
89
+ * @return
90
+ */
91
+ static NormalizeCoordToGECoord(pt2d: Point2D): Point2D {
92
+ let ptGeo: Point2D;
93
+ try {
94
+ let x: double = pt2d.getX();
95
+ let y: double = pt2d.getY();
96
+ while (x < -180) {
97
+ x += 360;
98
+ }
99
+ while (x > 180) {
100
+ x -= 360;
101
+ }
102
+
103
+ ptGeo = new Point2D(x, y);
104
+ } catch (exc) {
105
+ if (exc instanceof Error) {
106
+ } else {
107
+ throw exc;
108
+ }
109
+ }
110
+ return ptGeo;
111
+ }
112
+
113
+ /**
114
+ * We have to ensure the bounding rectangle at least includes the symbol or
115
+ * there are problems rendering, especially when the symbol crosses the IDL
116
+ *
117
+ * @param controlPoints the client symbol anchor points
118
+ * @param bbox the original bounding box
119
+ * @return the modified bounding box
120
+ */
121
+ private static getBoundingRectangle(controlPoints: string,
122
+ bbox: string): string {
123
+ let bbox2: string = "";
124
+ try {
125
+ //first get the minimum bounding rect for the geo coords
126
+ let left: number = 0.0;
127
+ let right: number = 0.0;
128
+ let top: number = 0.0;
129
+ let bottom: number = 0.0;
130
+
131
+ let coordinates: string[] = controlPoints.split(" ");
132
+ let len: int = coordinates.length;
133
+ let i: int = 0;
134
+ left = Number.MAX_VALUE;
135
+ right = -Number.MAX_VALUE;
136
+ top = -Number.MAX_VALUE;
137
+ bottom = Number.MAX_VALUE;
138
+ for (i = 0; i < len; i++) {
139
+ let coordPair: string[] = coordinates[i].split(",");
140
+ let latitude: number = parseFloat(coordPair[1].trim());
141
+ let longitude: number = parseFloat(coordPair[0].trim());
142
+ if (longitude < left) {
143
+ left = longitude;
144
+ }
145
+ if (longitude > right) {
146
+ right = longitude;
147
+ }
148
+ if (latitude > top) {
149
+ top = latitude;
150
+ }
151
+ if (latitude < bottom) {
152
+ bottom = latitude;
153
+ }
154
+ }
155
+ bbox2 = left.toString() + "," + bottom.toString() + "," + right.toString() + "," + top.toString();
156
+ } catch (ex) {
157
+ if (ex instanceof Error) {
158
+ console.log("Failed to create bounding rectangle in MultiPointHandler.getBoundingRect");
159
+ } else {
160
+ throw ex;
161
+ }
162
+ }
163
+ return bbox2;
164
+ }
165
+
166
+ /**
167
+ * need to use the symbol to get the upper left control point in order to
168
+ * produce a valid PointConverter
169
+ *
170
+ * @param geoCoords
171
+ * @return
172
+ */
173
+ private static getControlPoint(geoCoords: Array<Point2D>): Point2D {
174
+ let pt2d: Point2D;
175
+ try {
176
+ let left: double = Number.MAX_VALUE;
177
+ let right: double = -Number.MAX_VALUE;
178
+ let top: double = -Number.MAX_VALUE;
179
+ let bottom: double = Number.MAX_VALUE;
180
+ let ptTemp: Point2D;
181
+ let n: int = geoCoords.length;
182
+ //for (int j = 0; j < geoCoords.length; j++)
183
+ for (let j: int = 0; j < n; j++) {
184
+ ptTemp = geoCoords[j];
185
+ if (ptTemp.getX() < left) {
186
+ left = ptTemp.getX();
187
+ }
188
+ if (ptTemp.getX() > right) {
189
+ right = ptTemp.getX();
190
+ }
191
+ if (ptTemp.getY() > top) {
192
+ top = ptTemp.getY();
193
+ }
194
+ if (ptTemp.getY() < bottom) {
195
+ bottom = ptTemp.getY();
196
+ }
197
+ }
198
+ pt2d = new Point2D(left, top);
199
+ } catch (ex) {
200
+ if (ex instanceof Error) {
201
+ console.log("Failed to create control point in MultiPointHandler.getControlPoint");
202
+ } else {
203
+ throw ex;
204
+ }
205
+ }
206
+ return pt2d;
207
+ }
208
+
209
+ /**
210
+ * Assumes a reference in which the north pole is on top.
211
+ *
212
+ * @param geoCoords the geographic coordinates
213
+ * @return the upper left corner of the MBR containing the geographic
214
+ * coordinates
215
+ */
216
+ private static getGeoUL(geoCoords: Array<Point2D>): Point2D {
217
+ let ptGeo: Point2D;
218
+ try {
219
+ let j: int = 0;
220
+ let pt: Point2D;
221
+ let left: double = geoCoords[0].getX();
222
+ let top: double = geoCoords[0].getY();
223
+ let right: double = geoCoords[0].getX();
224
+ let bottom: double = geoCoords[0].getY();
225
+ let n: int = geoCoords.length;
226
+ //for (j = 1; j < geoCoords.length; j++)
227
+ for (j = 1; j < n; j++) {
228
+ pt = geoCoords[j];
229
+ if (pt.getX() < left) {
230
+ left = pt.getX();
231
+ }
232
+ if (pt.getX() > right) {
233
+ right = pt.getX();
234
+ }
235
+ if (pt.getY() > top) {
236
+ top = pt.getY();
237
+ }
238
+ if (pt.getY() < bottom) {
239
+ bottom = pt.getY();
240
+ }
241
+ }
242
+ //if geoCoords crosses the IDL
243
+ if (right - left > 180) {
244
+ //There must be at least one x value on either side of +/-180. Also, there is at least
245
+ //one positive value to the left of +/-180 and negative x value to the right of +/-180.
246
+ //We are using the orientation with the north pole on top so we can keep
247
+ //the existing value for top. Then the left value will be the least positive x value
248
+ //left = geoCoords[0].getX();
249
+ left = 180;
250
+ //for (j = 1; j < geoCoords.length; j++)
251
+ n = geoCoords.length;
252
+ for (j = 0; j < n; j++) {
253
+ pt = geoCoords[j];
254
+ if (pt.getX() > 0 && pt.getX() < left) {
255
+ left = pt.getX();
256
+ }
257
+ }
258
+ }
259
+ ptGeo = new Point2D(left, top);
260
+ } catch (ex) {
261
+ if (ex instanceof Error) {
262
+ console.log("Failed to create control point in MultiPointHandler.getControlPoint");
263
+ } else {
264
+ throw ex;
265
+ }
266
+ }
267
+ return ptGeo;
268
+ }
269
+ private static getBboxFromCoords(geoCoords: Array<Point2D>): string {
270
+ //var ptGeo = null;
271
+ let bbox: string;
272
+ try {
273
+ let j: int = 0;
274
+ let pt: Point2D;
275
+ let left: double = geoCoords[0].getX();
276
+ let top: double = geoCoords[0].getY();
277
+ let right: double = geoCoords[0].getX();
278
+ let bottom: double = geoCoords[0].getY();
279
+ for (j = 1; j < geoCoords.length; j++) {
280
+ pt = geoCoords[j];
281
+ if (pt.getX() < left) {
282
+ left = pt.getX();
283
+ }
284
+ if (pt.getX() > right) {
285
+ right = pt.getX();
286
+ }
287
+ if (pt.getY() > top) {
288
+ top = pt.getY();
289
+ }
290
+ if (pt.getY() < bottom) {
291
+ bottom = pt.getY();
292
+ }
293
+ }
294
+ //if geoCoords crosses the IDL
295
+ if (right - left > 180) {
296
+ //There must be at least one x value on either side of +/-180. Also, there is at least
297
+ //one positive value to the left of +/-180 and negative x value to the right of +/-180.
298
+ //We are using the orientation with the north pole on top so we can keep
299
+ //the existing value for top. Then the left value will be the least positive x value
300
+ //left = geoCoords[0].x;
301
+ left = 180;
302
+ right = -180;
303
+ for (j = 0; j < geoCoords.length; j++) {
304
+ pt = geoCoords[j];
305
+ if (pt.getX() > 0 && pt.getX() < left) {
306
+ left = pt.getX();
307
+ }
308
+ if (pt.getX() < 0 && pt.getX() > right) {
309
+ right = pt.getX();
310
+ }
311
+ }
312
+ }
313
+ //ptGeo = new Point2D(left, top);
314
+ bbox = left.toString() + "," + bottom.toString() + "," + right.toString() + "," + top.toString();
315
+ } catch (ex) {
316
+ if (ex instanceof Error) {
317
+ console.log("Failed to create control point in MultiPointHandler.getBboxFromCoords");
318
+ } else {
319
+ throw ex;
320
+ }
321
+ }
322
+ //return ptGeo;
323
+ return bbox;
324
+ }
325
+
326
+ private static crossesIDL(geoCoords: Array<Point2D>): boolean {
327
+ let result: boolean = false;
328
+ let pt2d: Point2D = MultiPointHandler.getControlPoint(geoCoords);
329
+ let left: double = pt2d.getX();
330
+ let ptTemp: Point2D;
331
+ let n: int = geoCoords.length;
332
+ //for (int j = 0; j < geoCoords.length; j++)
333
+ for (let j: int = 0; j < n; j++) {
334
+ ptTemp = geoCoords[j];
335
+ if (Math.abs(ptTemp.getX() - left) > 180) {
336
+ return true;
337
+ }
338
+ }
339
+ return result;
340
+ }
341
+
342
+ /**
343
+ * Checks if a symbol is one with decorated lines which puts a strain on
344
+ * google earth when rendering like FLOT. These complicated lines should be
345
+ * clipped when possible.
346
+ *
347
+ * @param symbolID
348
+ * @return
349
+ */
350
+ public static ShouldClipSymbol(symbolID: string): boolean {
351
+ //TODO: need to reevaluate this function to make sure we clip the right symbols.
352
+ let status: int = SymbolID.getStatus(symbolID);
353
+
354
+ if (SymbolUtilities.isTacticalGraphic(symbolID) && status === SymbolID.Status_Planned_Anticipated_Suspect) {
355
+ return true;
356
+ }
357
+
358
+ if (SymbolUtilities.isWeather(symbolID)) {
359
+ return true;
360
+ }
361
+
362
+ let id: int = parseInt(SymbolUtilities.getBasicSymbolID(symbolID));
363
+ //TODO: needs to be reworked
364
+ if (id === 25341100 || //Task Fix
365
+ id === 25260200 || //CFL
366
+ id === 25110100 || //Boundary
367
+ id === 25110200 || //Light Line (LL)
368
+ id === 25110300 || //Engineer Work Line (EWL)
369
+ id === 25140100 || //FLOT
370
+ id === 25140200 || //Line of contact is now just two flots, but APP6 still has it as a separate symbol
371
+ id === 25151000 || //Fortified Area
372
+ id === 25151100 || //Limited Access Area
373
+ id === 25172000 || //Weapons Free Zone
374
+ id === 25151202 || //Battle Position/Prepared but not Occupied
375
+ id === 25151203 || //Strong Point
376
+ id === 25141200 || //Probable Line of Deployment (PLD)
377
+ id === 25270800 || //Mined Area
378
+ id === 25270801 || //Mined Area, Fenced
379
+ id === 25170100 || //Air Corridor
380
+ id === 25170200 || //Low Level Transit Route (LLTR)
381
+ id === 25170300 || //Minimum-Risk Route (MRR)
382
+ id === 25170400 || //Safe Lane (SL)
383
+ id === 25170500 || //Standard Use ARmy Aircraft Flight Route (SAAFR)
384
+ id === 25170600 || //Transit Corridors (TC)
385
+ id === 25170700 || //Special Corridor (SC)
386
+
387
+ id === 25270100 || //Obstacle Belt
388
+ id === 25270200 || //Obstacle Zone
389
+ id === 25270300 || //Obstacle Free Zone
390
+ id === 25270400 || //Obstacle Restricted Zone
391
+
392
+ id === 25290100 || //Obstacle Line
393
+ id === 25290201 || //Antitank Ditch - Under Construction
394
+ id === 25290202 || //Antitank Ditch - Completed
395
+ id === 25290203 || //Antitank Ditch Reinforced, with Antitank Mines
396
+ id === 25290204 || //Antitank Wall
397
+ id === 25290301 || //Unspecified
398
+ id === 25290302 || //Single Fence
399
+ id === 25290303 || //Double Fence
400
+ id === 25290304 || //Double Apron Fence
401
+ id === 25290305 || //Low Wire Fence
402
+ id === 25290306 || //High Wire Fence
403
+ id === 25290307 || //Single Concertina
404
+ id === 25290308 || //Double Strand Concertina
405
+ id === 25290309 || //Triple Strand Concertina
406
+
407
+ id === 25341100 || //Obstacles Effect Fix now Mission Tasks Fix
408
+ id === 25290400 || //Mine Cluster
409
+ id === 25282003 || //Aviation / Overhead Wire
410
+ id === 25270602 || //Bypass Difficult
411
+ id === 25271500 || //Ford Easy
412
+ id === 25271600 || //Ford Difficult
413
+
414
+ id === 25290900 || //Fortified Line
415
+
416
+ id === 25271700 || //Biological Contaminated Area
417
+ id === 25271800 || //Chemical Contaminated Area
418
+ id === 25271900 || //Nuclear Contaminated Area
419
+ id === 25272000 || //Radiological Contaminated Area
420
+
421
+ id === 25240301 || //No Fire Area (NFA) - Irregular
422
+ id === 25240302 || //No Fire Area (NFA) - Rectangular
423
+ id === 25240303 || //No Fire Area (NFA) - Circular
424
+
425
+
426
+ id === 25240701 || //Linear Target
427
+ id === 25240702 || //Linear Smoke Target
428
+ id === 25240703 || //Final Protective Fire (FPF)
429
+ id === 25151800 || //Encirclement
430
+
431
+ id === 25330300 || //MSR
432
+ id === 25330301 || //MSR / One Way Traffic
433
+ id === 25330302 || //MSR / Two Way Traffic
434
+ id === 25330303 || //MSR / Alternating Traffic
435
+
436
+ id === 25330400 || //ASR
437
+ id === 25330401 || //ASR / One Way Traffic
438
+ id === 25330402 || //ASR / Two Way Traffic
439
+ id === 25330403 || //AMSR / Alternating Traffic
440
+
441
+ id === 25151205 || //Retain
442
+ id === 25341500 || //Isolate
443
+
444
+ id === 25340600 || //counterattack.
445
+ id === 25340700 || //counterattack by fire.
446
+ //id == G*G*PA----****X || //AoA for Feint - appears to be gone in 2525D
447
+ id === 25271200 || //Blown Bridges Planned
448
+ id === 25271202 || //Blown Bridges Explosives, State of Readiness 1 (Safe)
449
+ id === 25341200) // Follow and Assume
450
+ {
451
+ return true;
452
+ } else {
453
+ return false;
454
+ }
455
+ }
456
+
457
+ /**
458
+ * Assumes bbox is of form left,bottom,right,top and it is currently only
459
+ * using the width to calculate a reasonable scale. If the original scale is
460
+ * within the max and min range it returns the original scale.
461
+ *
462
+ * @param bbox
463
+ * @param origScale
464
+ * @return
465
+ */
466
+ private static getReasonableScale(bbox: string, origScale: double): double {
467
+ try {
468
+ let bounds: string[] = bbox.split(",");
469
+ let left: double = parseFloat(bounds[0]);
470
+ let right: double = parseFloat(bounds[2]);
471
+ let top: double = parseFloat(bounds[3]);
472
+ let bottom: double = parseFloat(bounds[1]);
473
+
474
+ let ul: POINT2 = new POINT2(left, top);
475
+ let ur: POINT2 = new POINT2(right, top);
476
+
477
+ let widthInMeters: double = 0;
478
+ if ((left === -180 && right === 180) || (left === 180 && right === -180)) {
479
+
480
+ widthInMeters = 40075017 / 2;
481
+ }
482
+ // Earth's circumference / 2
483
+ else {
484
+
485
+ widthInMeters = mdlGeodesic.geodesic_distance(ul, ur, null, null);
486
+ }
487
+
488
+
489
+ let minScale: double = widthInMeters / (MultiPointHandler._maxPixelWidth as double / RendererSettings.getInstance().getDeviceDPI() / GeoPixelConversion.INCHES_PER_METER);
490
+ if (origScale < minScale) {
491
+ return minScale;
492
+ }
493
+
494
+ let maxScale: double = widthInMeters / (MultiPointHandler._minPixelWidth as double / RendererSettings.getInstance().getDeviceDPI() / GeoPixelConversion.INCHES_PER_METER);
495
+ if (origScale > maxScale) {
496
+ return maxScale;
497
+ }
498
+ } catch (ignored) {
499
+ }
500
+ return origScale;
501
+ }
502
+
503
+ /**
504
+ *
505
+ * @param id
506
+ * @param name
507
+ * @param description
508
+ * @param symbolCode
509
+ * @param controlPoints
510
+ * @param scale
511
+ * @param bbox
512
+ * @param symbolModifiers {@link Map}, keyed using constants from
513
+ * Modifiers. Pass in comma delimited String for modifiers with multiple
514
+ * values like AM, AN &amp; X
515
+ * @param symbolAttributes {@link Map}, keyed using constants from
516
+ * MilStdAttributes. pass in double[] for AM, AN and X; Strings for the
517
+ * rest.
518
+ * @param format
519
+ * @return
520
+ */
521
+ public static RenderSymbol(id: string,
522
+ name: string,
523
+ description: string,
524
+ symbolCode: string,
525
+ controlPoints: string,
526
+ scale: number,
527
+ bbox: string,
528
+ symbolModifiers: Map<string, string>,
529
+ symbolAttributes: Map<string, string>,
530
+ format: int): string//,
531
+ {
532
+ //console.log("MultiPointHandler.RenderSymbol()");
533
+ let normalize: boolean = true;
534
+ //Double controlLat = 0.0;
535
+ //Double controlLong = 0.0;
536
+ //Double metPerPix = GeoPixelConversion.metersPerPixel(scale);
537
+ //String bbox2=getBoundingRectangle(controlPoints,bbox);
538
+ let jsonOutput: string = "";
539
+ let jsonContent: string = "";
540
+
541
+ let rect: Rectangle;
542
+ let coordinates: string[] = controlPoints.split(" ");
543
+ let tgl: TGLight = new TGLight();
544
+ let shapes: Array<ShapeInfo> = new Array<ShapeInfo>();
545
+ let modifiers: Array<ShapeInfo> = new Array<ShapeInfo>();
546
+ //ArrayList<Point2D> pixels = new ArrayList<Point2D>();
547
+ let geoCoords: Array<Point2D> = new Array<Point2D>();
548
+ let len: int = coordinates.length;
549
+ //diagnostic create geoCoords here
550
+ let coordsUL: Point2D = null;
551
+
552
+ let symbolIsValid: string = MultiPointHandler.canRenderMultiPoint(symbolCode, symbolModifiers, len);
553
+ if (symbolIsValid !== "true") {
554
+ let ErrorOutput: string = "";
555
+ ErrorOutput += ("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + " - ID: " + id + " - ");
556
+ ErrorOutput += symbolIsValid; //reason for error
557
+ ErrorOutput += ("\"}");
558
+ ErrorLogger.LogMessage("MultiPointHandler", "RenderSymbol", symbolIsValid, LogLevel.FINE);
559
+ return ErrorOutput;
560
+ }
561
+
562
+ if (MSLookup.getInstance().getMSLInfo(symbolCode).getDrawRule() != DrawRules.AREA10) // AREA10 can support infinite points
563
+ len = Math.min(len, MSLookup.getInstance().getMSLInfo(symbolCode).getMaxPointCount());
564
+ for (let i: int = 0; i < len; i++) {
565
+ let coordPair: string[] = coordinates[i].split(",");
566
+ let latitude: number = parseFloat(coordPair[1].trim());
567
+ let longitude: number = parseFloat(coordPair[0].trim());
568
+ geoCoords.push(new Point2D(longitude, latitude));
569
+ }
570
+ let tgPoints: Array<POINT2>;
571
+ let ipc: IPointConversion;
572
+
573
+ //Deutch moved section 6-29-11
574
+ let left: number = 0.0;
575
+ let right: number = 0.0;
576
+ let top: number = 0.0;
577
+ let bottom: number = 0.0;
578
+ let temp: Point2D;
579
+ let ptGeoUL: Point2D;
580
+ let width: int = 0;
581
+ let height: int = 0;
582
+ let leftX: int = 0;
583
+ let topY: int = 0;
584
+ let bottomY: int = 0;
585
+ let rightX: int = 0;
586
+ let j: int = 0;
587
+ let bboxCoords: Array<Point2D>;
588
+ if (bbox != null && bbox !== "") {
589
+ let bounds: string[];
590
+ if (bbox.includes(" "))//trapezoid
591
+ {
592
+ bboxCoords = new Array<Point2D>();
593
+ let x: double = 0;
594
+ let y: double = 0;
595
+ let coords: string[] = bbox.split(" ");
596
+ let arrCoord: string[];
597
+ for (let coord of coords) {
598
+ arrCoord = coord.split(",");
599
+ x = parseFloat(arrCoord[0]);
600
+ y = parseFloat(arrCoord[1]);
601
+ bboxCoords.push(new Point2D(x, y));
602
+ }
603
+ //use the upper left corner of the MBR containing geoCoords
604
+ //to set the converter
605
+ ptGeoUL = MultiPointHandler.getGeoUL(bboxCoords);
606
+ left = ptGeoUL.getX();
607
+ top = ptGeoUL.getY();
608
+ let bbox2: string = MultiPointHandler.getBboxFromCoords(bboxCoords);
609
+ scale = MultiPointHandler.getReasonableScale(bbox2, scale);
610
+ ipc = new PointConverter(left, top, scale);
611
+ let ptPixels: Point2D;
612
+ let ptGeo: Point2D;
613
+ let n: int = bboxCoords.length;
614
+ //for (j = 0; j < bboxCoords.length; j++)
615
+ for (j = 0; j < n; j++) {
616
+ ptGeo = bboxCoords[j];
617
+ ptPixels = ipc.GeoToPixels(ptGeo);
618
+ x = ptPixels.getX();
619
+ y = ptPixels.getY();
620
+ if (x < 20) {
621
+ x = 20;
622
+ }
623
+ if (y < 20) {
624
+ y = 20;
625
+ }
626
+ ptPixels.setLocation(x, y);
627
+ //end section
628
+ bboxCoords[j] = ptPixels;
629
+ }
630
+ } else//rectangle
631
+ {
632
+ bounds = bbox.split(",");
633
+ left = parseFloat(bounds[0]);
634
+ right = parseFloat(bounds[2]);
635
+ top = parseFloat(bounds[3]);
636
+ bottom = parseFloat(bounds[1]);
637
+ scale = MultiPointHandler.getReasonableScale(bbox, scale);
638
+ ipc = new PointConverter(left, top, scale);
639
+ }
640
+
641
+ let pt2d: Point2D;
642
+ if (bboxCoords == null) {
643
+ pt2d = new Point2D(left, top);
644
+ temp = ipc.GeoToPixels(pt2d);
645
+
646
+ leftX = temp.getX() as int;
647
+ topY = temp.getY() as int;
648
+
649
+ pt2d = new Point2D(right, bottom);
650
+ temp = ipc.GeoToPixels(pt2d);
651
+
652
+ bottomY = temp.getY() as int;
653
+ rightX = temp.getX() as int;
654
+ //diagnostic clipping does not work at large scales
655
+ // if(scale>10e6)
656
+ // {
657
+ // //diagnostic replace above by using a new ipc based on the coordinates MBR
658
+ // coordsUL=getGeoUL(geoCoords);
659
+ // temp = ipc.GeoToPixels(coordsUL);
660
+ // left=coordsUL.getX();
661
+ // top=coordsUL.getY();
662
+ // //shift the ipc to coordsUL origin so that conversions will be more accurate for large scales.
663
+ // ipc = new PointConverter(left, top, scale);
664
+ // //shift the rect to compenstate for the shifted ipc so that we can maintain the original clipping area.
665
+ // leftX -= (int)temp.getX();
666
+ // rightX -= (int)temp.getX();
667
+ // topY -= (int)temp.getY();
668
+ // bottomY -= (int)temp.getY();
669
+ // //end diagnostic
670
+ // }
671
+ //end section
672
+
673
+ width = Math.abs(rightX - leftX) as int;
674
+ height = Math.abs(bottomY - topY) as int;
675
+
676
+ rect = new Rectangle(leftX, topY, width, height);
677
+ }
678
+ } else {
679
+ rect = null;
680
+ }
681
+ //end section
682
+
683
+ // for (int i = 0; i < len; i++) {
684
+ // String[] coordPair = coordinates[i].split(",");
685
+ // Double latitude = Double.valueOf(coordPair[1].trim());
686
+ // Double longitude = Double.valueOf(coordPair[0].trim());
687
+ // geoCoords.push(new Point2D(longitude, latitude));
688
+ // }
689
+ if (ipc == null) {
690
+ let ptCoordsUL: Point2D = MultiPointHandler.getGeoUL(geoCoords);
691
+ ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale);
692
+ }
693
+ //if (crossesIDL(geoCoords) == true)
694
+ // if(Math.abs(right-left)>180)
695
+ // {
696
+ // normalize = true;
697
+ // ((PointConverter)ipc).set_normalize(true);
698
+ // }
699
+ // else {
700
+ // normalize = false;
701
+ // ((PointConverter)ipc).set_normalize(false);
702
+ // }
703
+
704
+ //seems to work ok at world view
705
+ // if (normalize) {
706
+ // NormalizeGECoordsToGEExtents(0, 360, geoCoords);
707
+ // }
708
+
709
+ //M. Deutch 10-3-11
710
+ //must shift the rect pixels to synch with the new ipc
711
+ //the old ipc was in synch with the bbox, so rect x,y was always 0,0
712
+ //the new ipc synchs with the upper left of the geocoords so the boox is shifted
713
+ //and therefore the clipping rectangle must shift by the delta x,y between
714
+ //the upper left corner of the original bbox and the upper left corner of the geocoords
715
+ let geoCoords2: Array<Point2D> = new Array<Point2D>();
716
+ geoCoords2.push(new Point2D(left, top));
717
+ geoCoords2.push(new Point2D(right, bottom));
718
+
719
+ // if (normalize) {
720
+ // NormalizeGECoordsToGEExtents(0, 360, geoCoords2);
721
+ // }
722
+
723
+ //disable clipping
724
+ if (MultiPointHandler.ShouldClipSymbol(symbolCode) === false) {
725
+
726
+ if (MultiPointHandler.crossesIDL(geoCoords) === false) {
727
+ rect = null;
728
+ bboxCoords = null;
729
+ }
730
+ }
731
+
732
+
733
+ tgl.set_SymbolId(symbolCode);// "GFGPSLA---****X" AMBUSH symbol code
734
+ tgl.set_Pixels(null);
735
+
736
+ try {
737
+
738
+ //String fillColor = null;
739
+ let mSymbol: MilStdSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null);
740
+
741
+ if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG) {
742
+ // Use dash array and hatch pattern fill for SVG output
743
+ symbolAttributes.set(MilStdAttributes.UseDashArray, 'true')
744
+ symbolAttributes.set(MilStdAttributes.UsePatternFill, "true")
745
+ }
746
+
747
+ if (symbolModifiers != null || symbolAttributes != null) {
748
+ MultiPointHandler.populateModifiers(symbolModifiers, symbolAttributes, mSymbol);
749
+ } else {
750
+ mSymbol.setFillColor(null);
751
+ }
752
+
753
+ if (bboxCoords == null) {
754
+ clsRenderer.renderWithPolylines(mSymbol, ipc, rect);
755
+ } else {
756
+ clsRenderer.renderWithPolylines(mSymbol, ipc, bboxCoords);
757
+ }
758
+
759
+ shapes = mSymbol.getSymbolShapes();
760
+ modifiers = mSymbol.getModifierShapes();
761
+
762
+ if (format === WebRenderer.OUTPUT_FORMAT_JSON) {
763
+ jsonOutput += ("{\"type\":\"symbol\",");
764
+ jsonContent = MultiPointHandler.JSONize(shapes, modifiers, ipc, true, normalize);
765
+ jsonOutput += (jsonContent);
766
+ jsonOutput += ("}");
767
+ } else if (format === WebRenderer.OUTPUT_FORMAT_KML) {
768
+ var textColor = mSymbol.getTextColor();
769
+ if(textColor==null)
770
+ textColor=mSymbol.getLineColor();
771
+
772
+ jsonContent = MultiPointHandler.KMLize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor);
773
+ jsonOutput += jsonContent;
774
+ } else if (format === WebRenderer.OUTPUT_FORMAT_GEOJSON) {
775
+ /*
776
+ jsonOutput += ("{\"type\":\"FeatureCollection\",\"features\":");
777
+ jsonContent = GeoJSONize(shapes, modifiers, ipc, normalize, mSymbol.getTextColor(), mSymbol.getTextBackgroundColor());
778
+ jsonOutput += (jsonContent);
779
+ jsonOutput += (",\"properties\":{\"id\":\"");
780
+ jsonOutput += (id);
781
+ jsonOutput += ("\",\"name\":\"");
782
+ jsonOutput += (name);
783
+ jsonOutput += ("\",\"description\":\"");
784
+ jsonOutput += (description);
785
+ jsonOutput += ("\",\"symbolID\":\"");
786
+ jsonOutput += (symbolCode);
787
+ jsonOutput += ("\",\"wasClipped\":\"");
788
+ jsonOutput += (mSymbol.get_WasClipped()).toString();
789
+ jsonOutput += ("\"}}"); */
790
+
791
+ jsonOutput += ("{\"type\":\"FeatureCollection\",\"features\":");
792
+ jsonContent = MultiPointHandler.GeoJSONize(shapes, modifiers, ipc, normalize, mSymbol.getTextColor(), mSymbol.getTextBackgroundColor());
793
+ jsonOutput += (jsonContent);
794
+
795
+ //moving meta data properties to the last feature with no coords as feature collection doesn't allow properties
796
+ jsonOutput = jsonOutput.slice(0, -1);
797
+ jsonOutput += (",{\"type\": \"Feature\",\"geometry\": { \"type\": \"Polygon\",\"coordinates\": [ ]}");
798
+
799
+ jsonOutput += (",\"properties\":{\"id\":\"");
800
+ jsonOutput += (id);
801
+ jsonOutput += ("\",\"name\":\"");
802
+ jsonOutput += (name);
803
+ jsonOutput += ("\",\"description\":\"");
804
+ jsonOutput += (description);
805
+ jsonOutput += ("\",\"symbolID\":\"");
806
+ jsonOutput += (symbolCode);
807
+ jsonOutput += ("\",\"wasClipped\":\"");
808
+ jsonOutput += (mSymbol.get_WasClipped()).toString();
809
+ //jsonOutput += ("\"}}");
810
+
811
+ jsonOutput += ("\"}}]}");
812
+ } else if (format === WebRenderer.OUTPUT_FORMAT_GEOSVG) {
813
+ let textColor = mSymbol.getTextColor() ? mSymbol.getTextColor().toHexString(false) : "";
814
+ let backgroundColor = mSymbol.getTextBackgroundColor() ? mSymbol.getTextBackgroundColor().toHexString(false) : "";
815
+ //returns an svg with a geoTL and geoBR value to use to place the canvas on the map
816
+ jsonOutput = MultiPointHandlerSVG.GeoSVGize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor, backgroundColor, mSymbol.get_WasClipped());
817
+ }
818
+ } catch (exc) {
819
+ if (exc instanceof Error) {
820
+ let st: string = JavaRendererUtilities.getStackTrace(exc);
821
+ jsonOutput = "";
822
+ jsonOutput += ("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + ": " + "- ");
823
+ jsonOutput += (exc.message + " - ");
824
+ jsonOutput += (st);
825
+ jsonOutput += ("\"}");
826
+
827
+ ErrorLogger.LogException("MultiPointHandler", "RenderSymbol", exc);
828
+ } else {
829
+ throw exc;
830
+ }
831
+ }
832
+
833
+ /*
834
+ let debug: boolean = false;
835
+ if (debug === true) {
836
+ console.log("Symbol Code: " + symbolCode);
837
+ console.log("Scale: " + scale);
838
+ console.log("BBOX: " + bbox);
839
+ if (controlPoints != null) {
840
+ console.log("Geo Points: " + controlPoints);
841
+ }
842
+ if (tgl != null && tgl.get_Pixels() != null)//pixels != null
843
+ {
844
+ console.log("Pixel: " + tgl.get_Pixels().toString());
845
+ }
846
+ if (bbox != null) {
847
+ console.log("geo bounds: " + bbox);
848
+ }
849
+ if (rect != null) {
850
+ console.log("pixel bounds: " + rect.toString());
851
+ }
852
+ if (jsonOutput != null) {
853
+ console.log(jsonOutput.toString());
854
+ }
855
+ }
856
+ */
857
+
858
+ ErrorLogger.LogMessage("MultiPointHandler", "RenderSymbol()", "exit RenderSymbol", LogLevel.FINER);
859
+ return jsonOutput.toString();
860
+
861
+ }
862
+
863
+ /**
864
+ *
865
+ * @param id
866
+ * @param name
867
+ * @param description
868
+ * @param symbolCode
869
+ * @param controlPoints
870
+ * @param scale
871
+ * @param bbox
872
+ * @param symbolModifiers
873
+ * @param symbolAttributes
874
+ * @return
875
+ */
876
+ public static RenderSymbolAsMilStdSymbol(id: string,
877
+ name: string,
878
+ description: string,
879
+ symbolCode: string,
880
+ controlPoints: string,
881
+ scale: number,
882
+ bbox: string,
883
+ symbolModifiers: Map<string, string>,
884
+ symbolAttributes: Map<string, string>): MilStdSymbol//,
885
+ //ArrayList<ShapeInfo>shapes)
886
+ {
887
+ let mSymbol: MilStdSymbol;
888
+ //console.log("MultiPointHandler.RenderSymbol()");
889
+ let normalize: boolean = true;
890
+ let controlLat: number = 0.0;
891
+ let controlLong: number = 0.0;
892
+ //String jsonContent = "";
893
+
894
+ let rect: Rectangle;
895
+
896
+ //for symbol & line fill
897
+ let tgPoints: Array<POINT2>;
898
+
899
+ let coordinates: string[] = controlPoints.split(" ");
900
+ let tgl: TGLight = new TGLight();
901
+ let shapes: Array<ShapeInfo>;//new ArrayList<ShapeInfo>();
902
+ let modifiers: Array<ShapeInfo>;//new ArrayList<ShapeInfo>();
903
+ //ArrayList<Point2D> pixels = new ArrayList<Point2D>();
904
+ let geoCoords: Array<Point2D> = new Array<Point2D>();
905
+ let len: int = coordinates.length;
906
+
907
+ let ipc: IPointConversion;
908
+
909
+ //Deutch moved section 6-29-11
910
+ let left: number = 0.0;
911
+ let right: number = 0.0;
912
+ let top: number = 0.0;
913
+ let bottom: number = 0.0;
914
+ let temp: Point2D;
915
+ let ptGeoUL: Point2D;
916
+ let width: int = 0;
917
+ let height: int = 0;
918
+ let leftX: int = 0;
919
+ let topY: int = 0;
920
+ let bottomY: int = 0;
921
+ let rightX: int = 0;
922
+ let j: int = 0;
923
+ let bboxCoords: Array<Point2D>;
924
+ if (bbox != null && bbox !== "") {
925
+ let bounds: string[];
926
+ if (bbox.includes(" "))//trapezoid
927
+ {
928
+ bboxCoords = new Array<Point2D>();
929
+ let x: double = 0;
930
+ let y: double = 0;
931
+ let coords: string[] = bbox.split(" ");
932
+ let arrCoord: string[];
933
+ for (let coord of coords) {
934
+ arrCoord = coord.split(",");
935
+ x = parseFloat(arrCoord[0]);
936
+ y = parseFloat(arrCoord[1]);
937
+ bboxCoords.push(new Point2D(x, y));
938
+ }
939
+ //use the upper left corner of the MBR containing geoCoords
940
+ //to set the converter
941
+ ptGeoUL = MultiPointHandler.getGeoUL(bboxCoords);
942
+ left = ptGeoUL.getX();
943
+ top = ptGeoUL.getY();
944
+ ipc = new PointConverter(left, top, scale);
945
+ let ptPixels: Point2D;
946
+ let ptGeo: Point2D;
947
+ let n: int = bboxCoords.length;
948
+ //for (j = 0; j < bboxCoords.length; j++)
949
+ for (j = 0; j < n; j++) {
950
+ ptGeo = bboxCoords[j];
951
+ ptPixels = ipc.GeoToPixels(ptGeo);
952
+ x = ptPixels.getX();
953
+ y = ptPixels.getY();
954
+ if (x < 20) {
955
+ x = 20;
956
+ }
957
+ if (y < 20) {
958
+ y = 20;
959
+ }
960
+ ptPixels.setLocation(x, y);
961
+ //end section
962
+ bboxCoords[j] = ptPixels;
963
+ }
964
+ } else//rectangle
965
+ {
966
+ bounds = bbox.split(",");
967
+ left = parseFloat(bounds[0]);
968
+ right = parseFloat(bounds[2]);
969
+ top = parseFloat(bounds[3]);
970
+ bottom = parseFloat(bounds[1]);
971
+ scale = MultiPointHandler.getReasonableScale(bbox, scale);
972
+ ipc = new PointConverter(left, top, scale);
973
+ }
974
+
975
+ let pt2d: Point2D;
976
+ if (bboxCoords == null) {
977
+ pt2d = new Point2D(left, top);
978
+ temp = ipc.GeoToPixels(pt2d);
979
+
980
+ leftX = temp.getX() as int;
981
+ topY = temp.getY() as int;
982
+
983
+ pt2d = new Point2D(right, bottom);
984
+ temp = ipc.GeoToPixels(pt2d);
985
+
986
+ bottomY = temp.getY() as int;
987
+ rightX = temp.getX() as int;
988
+ //diagnostic clipping does not work for large scales
989
+ // if (scale > 10e6) {
990
+ // //get widest point in the AOI
991
+ // double midLat = 0;
992
+ // if (bottom < 0 && top > 0) {
993
+ // midLat = 0;
994
+ // } else if (bottom < 0 && top < 0) {
995
+ // midLat = top;
996
+ // } else if (bottom > 0 && top > 0) {
997
+ // midLat = bottom;
998
+ // }
999
+ //
1000
+ // temp = ipc.GeoToPixels(new Point2D(right, midLat));
1001
+ // rightX = (int) temp.getX();
1002
+ // }
1003
+ //end section
1004
+
1005
+ width = Math.abs(rightX - leftX) as int;
1006
+ height = Math.abs(bottomY - topY) as int;
1007
+
1008
+ if (width === 0 || height === 0) {
1009
+
1010
+ rect = null;
1011
+ }
1012
+
1013
+ else {
1014
+
1015
+ rect = new Rectangle(leftX, topY, width, height);
1016
+ }
1017
+
1018
+ }
1019
+ } else {
1020
+ rect = null;
1021
+ }
1022
+ //end section
1023
+
1024
+ //check for required points & parameters
1025
+ let symbolIsValid: string = MultiPointHandler.canRenderMultiPoint(symbolCode, symbolModifiers, len);
1026
+ if (symbolIsValid !== "true") {
1027
+ ErrorLogger.LogMessage("MultiPointHandler", "RenderSymbolAsMilStdSymbol", symbolIsValid, LogLevel.WARNING);
1028
+ return mSymbol;
1029
+ }
1030
+
1031
+ if (MSLookup.getInstance().getMSLInfo(symbolCode).getDrawRule() != DrawRules.AREA10) // AREA10 can support infinite points
1032
+ len = Math.min(len, MSLookup.getInstance().getMSLInfo(symbolCode).getMaxPointCount());
1033
+ for (let i: int = 0; i < len; i++) {
1034
+ let coordPair: string[] = coordinates[i].split(",");
1035
+ let latitude: number = parseFloat(coordPair[1].trim());
1036
+ let longitude: number = parseFloat(coordPair[0].trim());
1037
+ geoCoords.push(new Point2D(longitude, latitude));
1038
+ }
1039
+ if (ipc == null) {
1040
+ let ptCoordsUL: Point2D = MultiPointHandler.getGeoUL(geoCoords);
1041
+ ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale);
1042
+ }
1043
+ //if (crossesIDL(geoCoords) == true)
1044
+ // if(Math.abs(right-left)>180)
1045
+ // {
1046
+ // normalize = true;
1047
+ // ((PointConverter)ipc).set_normalize(true);
1048
+ // }
1049
+ // else {
1050
+ // normalize = false;
1051
+ // ((PointConverter)ipc).set_normalize(false);
1052
+ // }
1053
+
1054
+ //seems to work ok at world view
1055
+ // if (normalize) {
1056
+ // NormalizeGECoordsToGEExtents(0, 360, geoCoords);
1057
+ // }
1058
+
1059
+ //M. Deutch 10-3-11
1060
+ //must shift the rect pixels to synch with the new ipc
1061
+ //the old ipc was in synch with the bbox, so rect x,y was always 0,0
1062
+ //the new ipc synchs with the upper left of the geocoords so the boox is shifted
1063
+ //and therefore the clipping rectangle must shift by the delta x,y between
1064
+ //the upper left corner of the original bbox and the upper left corner of the geocoords
1065
+ let geoCoords2: Array<Point2D> = new Array<Point2D>();
1066
+ geoCoords2.push(new Point2D(left, top));
1067
+ geoCoords2.push(new Point2D(right, bottom));
1068
+
1069
+ // if (normalize) {
1070
+ // NormalizeGECoordsToGEExtents(0, 360, geoCoords2);
1071
+ // }
1072
+
1073
+ //disable clipping
1074
+ if (MultiPointHandler.ShouldClipSymbol(symbolCode) === false) {
1075
+
1076
+ if (MultiPointHandler.crossesIDL(geoCoords) === false) {
1077
+ rect = null;
1078
+ bboxCoords = null;
1079
+ }
1080
+ }
1081
+
1082
+ tgl.set_SymbolId(symbolCode);// "GFGPSLA---****X" AMBUSH symbol code
1083
+ tgl.set_Pixels(null);
1084
+
1085
+ try {
1086
+
1087
+ let fillColor: string;
1088
+ mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null);
1089
+
1090
+ // mSymbol.setUseDashArray(true);
1091
+
1092
+ if (symbolModifiers != null || symbolAttributes != null) {
1093
+ MultiPointHandler.populateModifiers(symbolModifiers, symbolAttributes, mSymbol);
1094
+ } else {
1095
+ mSymbol.setFillColor(null);
1096
+ }
1097
+
1098
+ if (mSymbol.getFillColor() != null) {
1099
+ let fc: Color = mSymbol.getFillColor();
1100
+ fillColor = RendererUtilities.colorToHexString(fc, false);
1101
+
1102
+ }
1103
+
1104
+ if (bboxCoords == null) {
1105
+ clsRenderer.renderWithPolylines(mSymbol, ipc, rect);
1106
+ } else {
1107
+ clsRenderer.renderWithPolylines(mSymbol, ipc, bboxCoords);
1108
+ }
1109
+
1110
+ shapes = mSymbol.getSymbolShapes();
1111
+ modifiers = mSymbol.getModifierShapes();
1112
+
1113
+ //convert points////////////////////////////////////////////////////
1114
+ let polylines: Array<Array<Point2D>>;
1115
+ let newPolylines: Array<Array<Point2D>>;
1116
+ let newLine: Array<Point2D>;
1117
+ for (let shape of shapes) {
1118
+ polylines = shape.getPolylines();
1119
+ //console.log("pixel polylines: " + polylines.toString());
1120
+ newPolylines = MultiPointHandler.ConvertPolylinePixelsToCoords(polylines, ipc, normalize);
1121
+ shape.setPolylines(newPolylines);
1122
+ }
1123
+
1124
+ for (let label of modifiers) {
1125
+ let pixelCoord: Point2D = label.getModifierPosition();
1126
+ if (pixelCoord == null) {
1127
+ pixelCoord = label.getGlyphPosition();
1128
+ }
1129
+ let geoCoord: Point2D = ipc.PixelsToGeo(pixelCoord);
1130
+
1131
+ if (normalize) {
1132
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
1133
+ }
1134
+
1135
+ let latitude: double = geoCoord.getY();
1136
+ let longitude: double = geoCoord.getX();
1137
+ label.setModifierPosition(new Point2D(longitude, latitude));
1138
+
1139
+ }
1140
+
1141
+ ////////////////////////////////////////////////////////////////////
1142
+ mSymbol.setModifierShapes(modifiers);
1143
+ mSymbol.setSymbolShapes(shapes);
1144
+
1145
+ } catch (exc) {
1146
+ if (exc instanceof Error) {
1147
+ console.log(exc.message);
1148
+ console.log("Symbol Code: " + symbolCode);
1149
+ console.log(exc.stack);
1150
+ } else {
1151
+ throw exc;
1152
+ }
1153
+ }
1154
+
1155
+ /*
1156
+ let debug: boolean = false;
1157
+ if (debug === true) {
1158
+ console.log("Symbol Code: " + symbolCode);
1159
+ console.log("Scale: " + scale);
1160
+ console.log("BBOX: " + bbox);
1161
+ if (controlPoints != null) {
1162
+ console.log("Geo Points: " + controlPoints);
1163
+ }
1164
+ if (tgl != null && tgl.get_Pixels() != null)//pixels != null
1165
+ {
1166
+ //console.log("Pixel: " + pixels.toString());
1167
+ console.log("Pixel: " + tgl.get_Pixels().toString());
1168
+ }
1169
+ if (bbox != null) {
1170
+ console.log("geo bounds: " + bbox);
1171
+ }
1172
+ if (rect != null) {
1173
+ console.log("pixel bounds: " + rect.toString());
1174
+ }
1175
+ }
1176
+ */
1177
+
1178
+ return mSymbol;
1179
+
1180
+ }
1181
+
1182
+ private static ConvertPolylinePixelsToCoords(polylines: Array<Array<Point2D>>, ipc: IPointConversion, normalize: boolean): Array<Array<Point2D>> {
1183
+ let newPolylines: Array<Array<Point2D>> = new Array<Array<Point2D>>();
1184
+
1185
+ let latitude: double = 0;
1186
+ let longitude: double = 0;
1187
+ let newLine: Array<Point2D>;
1188
+ try {
1189
+ for (let line of polylines) {
1190
+ newLine = new Array<Point2D>();
1191
+ for (let pt of line) {
1192
+ let geoCoord: Point2D = ipc.PixelsToGeo(pt);
1193
+
1194
+ if (normalize) {
1195
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
1196
+ }
1197
+
1198
+ latitude = geoCoord.getY();
1199
+ longitude = geoCoord.getX();
1200
+ newLine.push(new Point2D(longitude, latitude));
1201
+ }
1202
+ newPolylines.push(newLine);
1203
+ }
1204
+ } catch (exc) {
1205
+ if (exc instanceof Error) {
1206
+ console.log(exc.message);
1207
+ console.log(exc.stack);
1208
+ } else {
1209
+ throw exc;
1210
+ }
1211
+ }
1212
+ return newPolylines;
1213
+ }
1214
+
1215
+ /**
1216
+ * Multipoint Rendering on flat 2D maps
1217
+ *
1218
+ * @param id A unique ID for the symbol. only used in KML currently
1219
+ * @param name
1220
+ * @param description
1221
+ * @param symbolCode
1222
+ * @param controlPoints
1223
+ * @param pixelWidth pixel dimensions of the viewable map area
1224
+ * @param pixelHeight pixel dimensions of the viewable map area
1225
+ * @param bbox The viewable area of the map. Passed in the format of a
1226
+ * string "lowerLeftX,lowerLeftY,upperRightX,upperRightY." example:
1227
+ * "-50.4,23.6,-42.2,24.2"
1228
+ * @param symbolModifiers Modifier with multiple values should be comma
1229
+ * delimited
1230
+ * @param symbolAttributes
1231
+ * @param format An enumeration: 0 for KML, 1 for JSON.
1232
+ * @return A JSON or KML string representation of the graphic.
1233
+ */
1234
+ public static RenderSymbol2D(id: string,
1235
+ name: string,
1236
+ description: string,
1237
+ symbolCode: string,
1238
+ controlPoints: string,
1239
+ pixelWidth: int,
1240
+ pixelHeight: int,
1241
+ bbox: string,
1242
+ symbolModifiers: Map<string, string>,
1243
+ symbolAttributes: Map<string, string>,
1244
+ format: int): string {
1245
+ let jsonOutput: string = "";
1246
+ let jsonContent: string = "";
1247
+
1248
+ let rect: Rectangle;
1249
+
1250
+ let tgPoints: Array<POINT2>;
1251
+
1252
+ let coordinates: string[] = controlPoints.split(" ");
1253
+ let tgl: TGLight = new TGLight();
1254
+ let shapes: Array<ShapeInfo> = new Array<ShapeInfo>();
1255
+ let modifiers: Array<ShapeInfo> = new Array<ShapeInfo>();
1256
+ let geoCoords: Array<Point2D> = new Array<Point2D>();
1257
+ let len: int = coordinates.length;
1258
+ let ipc: IPointConversion;
1259
+
1260
+ //check for required points & parameters
1261
+ let symbolIsValid: string = MultiPointHandler.canRenderMultiPoint(symbolCode, symbolModifiers, len);
1262
+ if (symbolIsValid !== "true") {
1263
+ let ErrorOutput: string = "";
1264
+ ErrorOutput += ("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + " - ID: " + id + " - ");
1265
+ ErrorOutput += symbolIsValid; //reason for error
1266
+ ErrorOutput += ("\"}");
1267
+ ErrorLogger.LogMessage("MultiPointHandler", "RenderSymbol2D", symbolIsValid, LogLevel.FINE);
1268
+ return ErrorOutput;
1269
+ }
1270
+
1271
+ let left: number = 0.0;
1272
+ let right: number = 0.0;
1273
+ let top: number = 0.0;
1274
+ let bottom: number = 0.0;
1275
+ if (bbox != null && bbox !== "") {
1276
+ let bounds: string[] = bbox.split(",");
1277
+
1278
+ left = parseFloat(bounds[0]);
1279
+ right = parseFloat(bounds[2]);
1280
+ top = parseFloat(bounds[3]);
1281
+ bottom = parseFloat(bounds[1]);
1282
+
1283
+ ipc = new PointConversion(pixelWidth, pixelHeight, top, left, bottom, right);
1284
+ } else {
1285
+ console.log("Bad bbox value: " + bbox);
1286
+ console.log("bbox is viewable area of the map. Passed in the format of a string \"lowerLeftX,lowerLeftY,upperRightX,upperRightY.\" example: \"-50.4,23.6,-42.2,24.2\"");
1287
+ return "ERROR - Bad bbox value: " + bbox;
1288
+ }
1289
+ //end section
1290
+
1291
+ //get coordinates
1292
+ if (MSLookup.getInstance().getMSLInfo(symbolCode).getDrawRule() != DrawRules.AREA10) // AREA10 can support infinite points
1293
+ len = Math.min(len, MSLookup.getInstance().getMSLInfo(symbolCode).getMaxPointCount());
1294
+ for (let i: int = 0; i < len; i++) {
1295
+ let coordPair: string[] = coordinates[i].split(",");
1296
+ let latitude: number = parseFloat(coordPair[1].trim());
1297
+ let longitude: number = parseFloat(coordPair[0].trim());
1298
+ geoCoords.push(new Point2D(longitude, latitude));
1299
+ }
1300
+
1301
+ try {
1302
+ let mSymbol: MilStdSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null);
1303
+
1304
+ if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG) {
1305
+ // Use dash array and hatch pattern fill for SVG output
1306
+ symbolAttributes.set(MilStdAttributes.UseDashArray, 'true')
1307
+ symbolAttributes.set(MilStdAttributes.UsePatternFill, "true")
1308
+ }
1309
+
1310
+ if (symbolModifiers != null && symbolModifiers.size !== 0) {
1311
+ MultiPointHandler.populateModifiers(symbolModifiers, symbolAttributes, mSymbol);
1312
+ } else {
1313
+ mSymbol.setFillColor(null);
1314
+ }
1315
+
1316
+ //build clipping bounds
1317
+ let temp: Point2D;
1318
+ let leftX: int = 0;
1319
+ let topY: int = 0;
1320
+ let bottomY: int = 0;
1321
+ let rightX: int = 0;
1322
+ let width: int = 0;
1323
+ let height: int = 0;
1324
+ let normalize: boolean = false;
1325
+ // if(Math.abs(right-left)>180)
1326
+ // {
1327
+ // ((PointConversion)ipc).set_normalize(true);
1328
+ // normalize=true;
1329
+ // }
1330
+ // else
1331
+ // {
1332
+ // ((PointConversion)ipc).set_normalize(false);
1333
+ // }
1334
+ if (MultiPointHandler.ShouldClipSymbol(symbolCode) || MultiPointHandler.crossesIDL(geoCoords)) {
1335
+ let lt: Point2D = new Point2D(left, top);
1336
+ //temp = ipc.GeoToPixels(new Point2D(left, top));
1337
+ temp = ipc.GeoToPixels(lt);
1338
+ leftX = temp.getX() as int;
1339
+ topY = temp.getY() as int;
1340
+
1341
+ let rb: Point2D = new Point2D(right, bottom);
1342
+ //temp = ipc.GeoToPixels(new Point2D(right, bottom));
1343
+ temp = ipc.GeoToPixels(rb);
1344
+ bottomY = temp.getY() as int;
1345
+ rightX = temp.getX() as int;
1346
+ //////////////////
1347
+
1348
+ width = Math.abs(rightX - leftX) as int;
1349
+ height = Math.abs(bottomY - topY) as int;
1350
+
1351
+ rect = new Rectangle(leftX, topY, width, height);
1352
+ }
1353
+
1354
+ //new interface
1355
+ //IMultiPointRenderer mpr = MultiPointRenderer.getInstance();
1356
+ clsRenderer.renderWithPolylines(mSymbol, ipc, rect);
1357
+ shapes = mSymbol.getSymbolShapes();
1358
+ modifiers = mSymbol.getModifierShapes();
1359
+
1360
+ //boolean normalize = false;
1361
+
1362
+ if (format === WebRenderer.OUTPUT_FORMAT_JSON) {
1363
+ jsonOutput += ("{\"type\":\"symbol\",");
1364
+ //jsonContent = JSONize(shapes, modifiers, ipc, normalize);
1365
+ jsonOutput += (jsonContent);
1366
+ jsonOutput += ("}");
1367
+ } else if (format === WebRenderer.OUTPUT_FORMAT_KML) {
1368
+ var textColor = mSymbol.getTextColor();
1369
+ if(textColor==null)
1370
+ textColor=mSymbol.getLineColor();
1371
+
1372
+ jsonContent = MultiPointHandler.KMLize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor);
1373
+ jsonOutput += jsonContent;
1374
+ } else if (format === WebRenderer.OUTPUT_FORMAT_GEOJSON) {
1375
+ jsonOutput += ("{\"type\":\"FeatureCollection\",\"features\":");
1376
+ jsonContent = MultiPointHandler.GeoJSONize(shapes, modifiers, ipc, normalize, mSymbol.getTextColor(), mSymbol.getTextBackgroundColor());
1377
+ jsonOutput += (jsonContent);
1378
+
1379
+ //moving meta data properties to the last feature with no coords as feature collection doesn't allow properties
1380
+ jsonOutput = jsonOutput.slice(0, -1);
1381
+ jsonOutput += (",{\"type\": \"Feature\",\"geometry\": { \"type\": \"Polygon\",\"coordinates\": [ ]}");
1382
+
1383
+ jsonOutput += (",\"properties\":{\"id\":\"");
1384
+ jsonOutput += (id);
1385
+ jsonOutput += ("\",\"name\":\"");
1386
+ jsonOutput += (name);
1387
+ jsonOutput += ("\",\"description\":\"");
1388
+ jsonOutput += (description);
1389
+ jsonOutput += ("\",\"symbolID\":\"");
1390
+ jsonOutput += (symbolCode);
1391
+ jsonOutput += ("\",\"wasClipped\":\"");
1392
+ jsonOutput += (mSymbol.get_WasClipped()).toString();
1393
+ //jsonOutput += ("\"}}");
1394
+
1395
+ jsonOutput += ("\"}}]}");
1396
+
1397
+ } else if (format === WebRenderer.OUTPUT_FORMAT_GEOSVG) {
1398
+ let textColor = mSymbol.getTextColor() ? mSymbol.getTextColor().toHexString(false) : "";
1399
+ let backgroundColor = mSymbol.getTextBackgroundColor() ? mSymbol.getTextBackgroundColor().toHexString(false) : "";
1400
+ //returns an svg with a geoTL and geoBR value to use to place the canvas on the map
1401
+ jsonOutput = MultiPointHandlerSVG.GeoSVGize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor, backgroundColor, mSymbol.get_WasClipped());
1402
+ }
1403
+ } catch (exc) {
1404
+ if (exc instanceof Error) {
1405
+ jsonOutput = "";
1406
+ jsonOutput += ("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + ": " + "- ");
1407
+ jsonOutput += (exc.message + " - ");
1408
+ jsonOutput += (ErrorLogger.getStackTrace(exc));
1409
+ jsonOutput += ("\"}");
1410
+ } else {
1411
+ throw exc;
1412
+ }
1413
+ }
1414
+
1415
+ /*
1416
+ let debug: boolean = false;
1417
+ if (debug === true) {
1418
+ console.log("Symbol Code: " + symbolCode);
1419
+ console.log("BBOX: " + bbox);
1420
+ if (controlPoints != null) {
1421
+ console.log("Geo Points: " + controlPoints);
1422
+ }
1423
+ if (tgl != null && tgl.get_Pixels() != null)//pixels != null
1424
+ {
1425
+ //console.log("Pixel: " + pixels.toString());
1426
+ console.log("Pixel: " + tgl.get_Pixels().toString());
1427
+ }
1428
+ if (bbox != null) {
1429
+ console.log("geo bounds: " + bbox);
1430
+ }
1431
+ if (rect != null) {
1432
+ console.log("pixel bounds: " + rect.toString());
1433
+ }
1434
+ if (jsonOutput != null) {
1435
+ console.log(jsonOutput.toString());
1436
+ }
1437
+ }
1438
+ */
1439
+
1440
+ return jsonOutput.toString();
1441
+
1442
+ }
1443
+
1444
+ /**
1445
+ * For Mike Deutch testing
1446
+ *
1447
+ * @param id
1448
+ * @param name
1449
+ * @param description
1450
+ * @param symbolCode
1451
+ * @param controlPoints
1452
+ * @param pixelWidth
1453
+ * @param pixelHeight
1454
+ * @param bbox
1455
+ * @param symbolModifiers
1456
+ * @param shapes
1457
+ * @param modifiers
1458
+ * @param format
1459
+ * @return
1460
+ * @deprecated
1461
+ */
1462
+ public static RenderSymbol2DX(id: string,
1463
+ name: string,
1464
+ description: string,
1465
+ symbolCode: string,
1466
+ controlPoints: string,
1467
+ pixelWidth: int,
1468
+ pixelHeight: int,
1469
+ bbox: string,
1470
+ symbolModifiers: Map<string, string>,
1471
+ symbolAttributes: Map<string, string>,
1472
+ shapes: Array<ShapeInfo>,
1473
+ modifiers: Array<ShapeInfo>,
1474
+ format: int): string//,
1475
+ //ArrayList<ShapeInfo>shapes)
1476
+ {
1477
+
1478
+ let jsonOutput: string = "";
1479
+ let jsonContent: string = "";
1480
+
1481
+ let rect: Rectangle;
1482
+
1483
+ let coordinates: string[] = controlPoints.split(" ");
1484
+ let tgl: TGLight = new TGLight();
1485
+ let geoCoords: Array<Point2D> = new Array<Point2D>();
1486
+ let ipc: IPointConversion;
1487
+
1488
+ let left: number = 0.0;
1489
+ let right: number = 0.0;
1490
+ let top: number = 0.0;
1491
+ let bottom: number = 0.0;
1492
+ if (bbox != null && bbox !== "") {
1493
+ let bounds: string[] = bbox.split(",");
1494
+
1495
+ left = parseFloat(bounds[0]);
1496
+ right = parseFloat(bounds[2]);
1497
+ top = parseFloat(bounds[3]);
1498
+ bottom = parseFloat(bounds[1]);
1499
+
1500
+ ipc = new PointConversion(pixelWidth, pixelHeight, top, left, bottom, right);
1501
+ } else {
1502
+ console.log("Bad bbox value: " + bbox);
1503
+ console.log("bbox is viewable area of the map. Passed in the format of a string \"lowerLeftX,lowerLeftY,upperRightX,upperRightY.\" example: \"-50.4,23.6,-42.2,24.2\"");
1504
+ return "ERROR - Bad bbox value: " + bbox;
1505
+ }
1506
+ //end section
1507
+
1508
+ //get coordinates
1509
+ let len: int = coordinates.length;
1510
+ for (let i: int = 0; i < len; i++) {
1511
+ let coordPair: string[] = coordinates[i].split(",");
1512
+ let latitude: number = parseFloat(coordPair[1].trim());
1513
+ let longitude: number = parseFloat(coordPair[0].trim());
1514
+ geoCoords.push(new Point2D(longitude, latitude));
1515
+ }
1516
+
1517
+ try {
1518
+ let mSymbol: MilStdSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null);
1519
+
1520
+ if (symbolModifiers != null && symbolModifiers.size !== 0) {
1521
+ MultiPointHandler.populateModifiers(symbolModifiers, symbolAttributes, mSymbol);
1522
+ } else {
1523
+ mSymbol.setFillColor(null);
1524
+ }
1525
+
1526
+ clsRenderer.renderWithPolylines(mSymbol, ipc, rect);
1527
+ shapes = mSymbol.getSymbolShapes();
1528
+ modifiers = mSymbol.getModifierShapes();
1529
+
1530
+ let normalize: boolean = false;
1531
+
1532
+ if (format === WebRenderer.OUTPUT_FORMAT_JSON) {
1533
+ jsonOutput += ("{\"type\":\"symbol\",");
1534
+ jsonContent = MultiPointHandler.JSONize(shapes, modifiers, ipc, false, normalize);
1535
+ jsonOutput += (jsonContent);
1536
+ jsonOutput += ("}");
1537
+ }
1538
+ } catch (exc) {
1539
+ if (exc instanceof Error) {
1540
+ jsonOutput = "";
1541
+ jsonOutput += ("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + ": " + "- ");
1542
+ jsonOutput += (exc.message + " - ");
1543
+ jsonOutput += ("\"}");
1544
+ } else {
1545
+ throw exc;
1546
+ }
1547
+ }
1548
+
1549
+ let debug: boolean = true;
1550
+ if (debug === true) {
1551
+ console.log("Symbol Code: " + symbolCode);
1552
+ console.log("BBOX: " + bbox);
1553
+ if (controlPoints != null) {
1554
+ console.log("Geo Points: " + controlPoints);
1555
+ }
1556
+ if (tgl != null && tgl.get_Pixels() != null)//pixels != null
1557
+ {
1558
+ //console.log("Pixel: " + pixels.toString());
1559
+ console.log("Pixel: " + tgl.get_Pixels().toString());
1560
+ }
1561
+ if (bbox != null) {
1562
+ console.log("geo bounds: " + bbox);
1563
+ }
1564
+ if (rect != null) {
1565
+ console.log("pixel bounds: " + rect.toString());
1566
+ }
1567
+ if (jsonOutput != null) {
1568
+ console.log(jsonOutput.toString());
1569
+ }
1570
+ }
1571
+ return jsonOutput.toString();
1572
+
1573
+ }
1574
+
1575
+ private static MilStdSymbolToSymbolInfo(symbol: MilStdSymbol): SymbolInfo {
1576
+ let si: SymbolInfo;
1577
+
1578
+ let tiList: Array<TextInfo> = new Array<TextInfo>();
1579
+ let liList: Array<LineInfo> = new Array<LineInfo>();
1580
+
1581
+ let tiTemp: TextInfo;
1582
+ let liTemp: LineInfo;
1583
+ let siTemp: ShapeInfo;
1584
+
1585
+ let lines: Array<ShapeInfo> = symbol.getSymbolShapes();
1586
+ let modifiers: Array<ShapeInfo> = symbol.getModifierShapes();
1587
+
1588
+ let lineCount: int = lines.length;
1589
+ let modifierCount: int = modifiers.length;
1590
+ for (let i: int = 0; i < lineCount; i++) {
1591
+ siTemp = lines[i];
1592
+ if (siTemp.getPolylines() != null) {
1593
+ liTemp = new LineInfo();
1594
+ liTemp.setFillColor(siTemp.getFillColor());
1595
+ liTemp.setLineColor(siTemp.getLineColor());
1596
+ liTemp.setPolylines(siTemp.getPolylines());
1597
+ liTemp.setStroke(siTemp.getStroke());
1598
+ liList.push(liTemp);
1599
+ }
1600
+ }
1601
+
1602
+ for (let j: int = 0; j < modifierCount; j++) {
1603
+ tiTemp = new TextInfo();
1604
+ siTemp = modifiers[j];
1605
+ if (siTemp.getModifierString() != null) {
1606
+ tiTemp.setModifierString(siTemp.getModifierString());
1607
+ tiTemp.setModifierStringPosition(siTemp.getModifierPosition());
1608
+ tiTemp.setModifierStringAngle(siTemp.getModifierAngle());
1609
+ tiList.push(tiTemp);
1610
+ }
1611
+ }
1612
+ si = new SymbolInfo(tiList, liList);
1613
+ return si;
1614
+ }
1615
+
1616
+ /**
1617
+ * Populates a symbol with the modifiers from a JSON string. This function
1618
+ * will overwrite any previously populated modifier data.
1619
+ *
1620
+ *
1621
+ *
1622
+ * @param symbol An existing MilStdSymbol
1623
+ * @return
1624
+ */
1625
+ private static populateModifiers(saModifiers: Map<string, string>, saAttributes: Map<string, string>, symbol: MilStdSymbol): boolean {
1626
+ let modifiers: Map<string, string> = new Map();
1627
+ let attributes: Map<string, string> = saAttributes;
1628
+
1629
+ // Stores array graphic modifiers for MilStdSymbol;
1630
+ let altitudes: Array<number> = null;
1631
+ let azimuths: Array<number> = null;
1632
+ let distances: Array<number> = null;
1633
+
1634
+ // Stores colors for symbol.
1635
+ let fillColor: string = null;
1636
+ let lineColor: string = null;
1637
+ let textColor: string = null;
1638
+ let textBackgroundColor: string = null;
1639
+
1640
+ let lineWidth: int = 0;
1641
+ let altMode: string = "";
1642
+ let useDashArray: boolean = symbol.getUseDashArray();
1643
+ let usePatternFill: boolean = symbol.getUseFillPattern();
1644
+ let patternFillType: int = 0;
1645
+ let hideOptionalLabels: boolean = false;
1646
+ let distanceUnit: DistanceUnit;
1647
+ let altitudeUnit: DistanceUnit;
1648
+ let pixelSize: int = 50;
1649
+ let keepUnitRatio: boolean = true;
1650
+ let patternScale: double = RendererSettings.getInstance().getPatternScale();
1651
+
1652
+ try {
1653
+
1654
+ // The following attirubtes are labels. All of them
1655
+ // are strings and can be added on the creation of the
1656
+ // MilStdSymbol by adding to a Map and passing in the
1657
+ // modifiers parameter.
1658
+ if (saModifiers != null) {
1659
+ if (saModifiers.has(Modifiers.C_QUANTITY)) {
1660
+ modifiers.set(Modifiers.C_QUANTITY, saModifiers.get(Modifiers.C_QUANTITY));
1661
+ }
1662
+
1663
+ if (saModifiers.has(Modifiers.H_ADDITIONAL_INFO_1)) {
1664
+ modifiers.set(Modifiers.H_ADDITIONAL_INFO_1, saModifiers.get(Modifiers.H_ADDITIONAL_INFO_1));
1665
+ }
1666
+
1667
+ if (saModifiers.has(Modifiers.H1_ADDITIONAL_INFO_2)) {
1668
+ modifiers.set(Modifiers.H1_ADDITIONAL_INFO_2, saModifiers.get(Modifiers.H1_ADDITIONAL_INFO_2));
1669
+ }
1670
+
1671
+ if (saModifiers.has(Modifiers.H2_ADDITIONAL_INFO_3)) {
1672
+ modifiers.set(Modifiers.H2_ADDITIONAL_INFO_3, saModifiers.get(Modifiers.H2_ADDITIONAL_INFO_3));
1673
+ }
1674
+
1675
+ if (saModifiers.has(Modifiers.N_HOSTILE)) {
1676
+ if (saModifiers.get(Modifiers.N_HOSTILE) == null) {
1677
+ modifiers.set(Modifiers.N_HOSTILE, "");
1678
+ } else {
1679
+ modifiers.set(Modifiers.N_HOSTILE, saModifiers.get(Modifiers.N_HOSTILE));
1680
+ }
1681
+ }
1682
+
1683
+ if (saModifiers.has(Modifiers.Q_DIRECTION_OF_MOVEMENT)) {
1684
+ modifiers.set(Modifiers.Q_DIRECTION_OF_MOVEMENT, saModifiers.get(Modifiers.Q_DIRECTION_OF_MOVEMENT));
1685
+ }
1686
+
1687
+ if (saModifiers.has(Modifiers.T_UNIQUE_DESIGNATION_1)) {
1688
+ modifiers.set(Modifiers.T_UNIQUE_DESIGNATION_1, saModifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1));
1689
+ }
1690
+
1691
+ if (saModifiers.has(Modifiers.T1_UNIQUE_DESIGNATION_2)) {
1692
+ modifiers.set(Modifiers.T1_UNIQUE_DESIGNATION_2, saModifiers.get(Modifiers.T1_UNIQUE_DESIGNATION_2));
1693
+ }
1694
+
1695
+ if (saModifiers.has(Modifiers.V_EQUIP_TYPE)) {
1696
+ modifiers.set(Modifiers.V_EQUIP_TYPE, saModifiers.get(Modifiers.V_EQUIP_TYPE));
1697
+ }
1698
+
1699
+ if (saModifiers.has(Modifiers.AS_COUNTRY)) {
1700
+ modifiers.set(Modifiers.AS_COUNTRY, saModifiers.get(Modifiers.AS_COUNTRY));
1701
+ } else {
1702
+ if (SymbolID.getCountryCode(symbol.getSymbolID()) > 0 && GENCLookup.getInstance().get3CharCode(SymbolID.getCountryCode(symbol.getSymbolID())) !== "") {
1703
+ modifiers.set(Modifiers.AS_COUNTRY, GENCLookup.getInstance().get3CharCode(SymbolID.getCountryCode(symbol.getSymbolID())));
1704
+ }
1705
+ }
1706
+
1707
+
1708
+ if (saModifiers.has(Modifiers.AP_TARGET_NUMBER)) {
1709
+ modifiers.set(Modifiers.AP_TARGET_NUMBER, saModifiers.get(Modifiers.AP_TARGET_NUMBER));
1710
+ }
1711
+
1712
+ if (saModifiers.has(Modifiers.W_DTG_1)) {
1713
+ modifiers.set(Modifiers.W_DTG_1, saModifiers.get(Modifiers.W_DTG_1));
1714
+ }
1715
+
1716
+ if (saModifiers.has(Modifiers.W1_DTG_2)) {
1717
+ modifiers.set(Modifiers.W1_DTG_2, saModifiers.get(Modifiers.W1_DTG_2));
1718
+ }
1719
+
1720
+ if (saModifiers.has(Modifiers.Y_LOCATION)) {
1721
+ modifiers.set(Modifiers.Y_LOCATION, saModifiers.get(Modifiers.Y_LOCATION));
1722
+ }
1723
+
1724
+ //Required multipoint modifier arrays
1725
+ if (saModifiers.has(Modifiers.X_ALTITUDE_DEPTH)) {
1726
+ altitudes = new Array<number>();
1727
+ let arrAltitudes: string[] = saModifiers.get(Modifiers.X_ALTITUDE_DEPTH).split(",");
1728
+ for (let x of arrAltitudes) {
1729
+ if (x !== "") {
1730
+ altitudes.push(parseFloat(x));
1731
+ }
1732
+ }
1733
+ }
1734
+
1735
+ if (saModifiers.has(Modifiers.AM_DISTANCE)) {
1736
+ distances = new Array<number>();
1737
+ let arrDistances: string[] = saModifiers.get(Modifiers.AM_DISTANCE).split(",");
1738
+ for (let am of arrDistances) {
1739
+ if (am !== "") {
1740
+ distances.push(parseFloat(am));
1741
+ }
1742
+ }
1743
+ }
1744
+
1745
+ if (saModifiers.has(Modifiers.AN_AZIMUTH)) {
1746
+ azimuths = new Array<number>();
1747
+ let arrAzimuths: string[] = saModifiers.get(Modifiers.AN_AZIMUTH).split(",");
1748
+ for (let an of arrAzimuths) {
1749
+ if (an !== "") {
1750
+ azimuths.push(parseFloat(an));
1751
+ }
1752
+ }
1753
+ }
1754
+ }
1755
+ if (saAttributes != null) {
1756
+ // These properties are ints, not labels, they are colors.//////////////////
1757
+ if (saAttributes.has(MilStdAttributes.FillColor)) {
1758
+ fillColor = String(saAttributes.get(MilStdAttributes.FillColor));
1759
+ }
1760
+
1761
+ if (saAttributes.has(MilStdAttributes.LineColor)) {
1762
+ lineColor = String(saAttributes.get(MilStdAttributes.LineColor));
1763
+ }
1764
+
1765
+ if (saAttributes.has(MilStdAttributes.LineWidth)) {
1766
+ lineWidth = parseInt(saAttributes.get(MilStdAttributes.LineWidth));
1767
+ }
1768
+
1769
+ if (saAttributes.has(MilStdAttributes.TextColor)) {
1770
+ textColor = String(saAttributes.get(MilStdAttributes.TextColor));
1771
+ }
1772
+
1773
+ if (saAttributes.has(MilStdAttributes.TextBackgroundColor)) {
1774
+ textBackgroundColor = String(saAttributes.get(MilStdAttributes.TextBackgroundColor));
1775
+ }
1776
+
1777
+ if (saAttributes.has(MilStdAttributes.AltitudeMode)) {
1778
+ altMode = saAttributes.get(MilStdAttributes.AltitudeMode);
1779
+ }
1780
+
1781
+ if (saAttributes.has(MilStdAttributes.UseDashArray)) {
1782
+ useDashArray = saAttributes.get(MilStdAttributes.UseDashArray).toLowerCase() === 'true';
1783
+ }
1784
+
1785
+ if (saAttributes.has(MilStdAttributes.UsePatternFill)) {
1786
+ usePatternFill = saAttributes.get(MilStdAttributes.UsePatternFill).toLowerCase() === 'true';
1787
+ }
1788
+
1789
+ if (saAttributes.has(MilStdAttributes.PatternFillType)) {
1790
+ patternFillType = parseInt((saAttributes.get(MilStdAttributes.PatternFillType)));
1791
+ }
1792
+
1793
+ if (saAttributes.has(MilStdAttributes.HideOptionalLabels)) {
1794
+ hideOptionalLabels = saAttributes.get(MilStdAttributes.HideOptionalLabels).toLowerCase() === 'true';
1795
+ }
1796
+
1797
+ if (saAttributes.has(MilStdAttributes.AltitudeUnits)) {
1798
+ altitudeUnit = DistanceUnit.parse(saAttributes.get(MilStdAttributes.AltitudeUnits));
1799
+ }
1800
+
1801
+ if (saAttributes.has(MilStdAttributes.DistanceUnits)) {
1802
+ distanceUnit = DistanceUnit.parse(saAttributes.get(MilStdAttributes.DistanceUnits));
1803
+ }
1804
+
1805
+ if (saAttributes.has(MilStdAttributes.PixelSize)) {
1806
+ pixelSize = parseInt(saAttributes.get(MilStdAttributes.PixelSize));
1807
+ symbol.setUnitSize(pixelSize);
1808
+ }
1809
+
1810
+ if (saAttributes.has(MilStdAttributes.KeepUnitRatio)) {
1811
+ keepUnitRatio = saAttributes.get(MilStdAttributes.KeepUnitRatio).toLowerCase() === 'true';
1812
+ symbol.setKeepUnitRatio(keepUnitRatio);
1813
+ }
1814
+
1815
+ if(saAttributes.has(MilStdAttributes.PatternScale)) {
1816
+ patternScale = parseFloat(saAttributes.get(MilStdAttributes.PatternScale));
1817
+ }
1818
+ }
1819
+
1820
+ symbol.setModifierMap(modifiers);
1821
+
1822
+ if (fillColor != null && fillColor !== "") {
1823
+ symbol.setFillColor(RendererUtilities.getColorFromHexString(fillColor));
1824
+ }
1825
+
1826
+ if (lineColor != null && lineColor !== "") {
1827
+ symbol.setLineColor(RendererUtilities.getColorFromHexString(lineColor));
1828
+ symbol.setTextColor(RendererUtilities.getColorFromHexString(lineColor));
1829
+ }
1830
+ else {
1831
+ if (symbol.getLineColor() == null) {
1832
+
1833
+ symbol.setLineColor(Color.black);
1834
+ }
1835
+
1836
+ }
1837
+
1838
+
1839
+ if (lineWidth > 0) {
1840
+ symbol.setLineWidth(lineWidth);
1841
+ }
1842
+
1843
+ if (textColor != null && textColor !== "") {
1844
+ symbol.setTextColor(RendererUtilities.getColorFromHexString(textColor));
1845
+ } else {
1846
+ if (symbol.getTextColor() == null) {
1847
+
1848
+ symbol.setTextColor(Color.black);
1849
+ }
1850
+
1851
+ }
1852
+
1853
+
1854
+ if (textBackgroundColor != null && textBackgroundColor !== "") {
1855
+ symbol.setTextBackgroundColor(RendererUtilities.getColorFromHexString(textBackgroundColor));
1856
+ }
1857
+
1858
+ if (altMode != null) {
1859
+ symbol.setAltitudeMode(altMode);
1860
+ }
1861
+
1862
+ symbol.setUseDashArray(useDashArray);
1863
+ symbol.setUseFillPattern(usePatternFill);
1864
+ symbol.setHideOptionalLabels(hideOptionalLabels);
1865
+ symbol.setAltitudeUnit(altitudeUnit);
1866
+ symbol.setDistanceUnit(distanceUnit);
1867
+ symbol.setPatternScale(patternScale);
1868
+
1869
+ // Check grpahic modifiers variables. If we set earlier, populate
1870
+ // the fields, otherwise, ignore.
1871
+ if (altitudes != null) {
1872
+ symbol.setModifiers_AM_AN_X(Modifiers.X_ALTITUDE_DEPTH, altitudes);
1873
+ }
1874
+ if (distances != null) {
1875
+ symbol.setModifiers_AM_AN_X(Modifiers.AM_DISTANCE, distances);
1876
+ }
1877
+
1878
+ if (azimuths != null) {
1879
+ symbol.setModifiers_AM_AN_X(Modifiers.AN_AZIMUTH, azimuths);
1880
+ }
1881
+
1882
+ //Check if sector range fan has required min range
1883
+ if (SymbolUtilities.getBasicSymbolID(symbol.getSymbolID()) === "25242200") {
1884
+ if (symbol.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH) != null
1885
+ && symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE) != null) {
1886
+ let anCount: int = symbol.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH).length;
1887
+ let amCount: int = symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE).length;
1888
+ let am: Array<number>;
1889
+ if (amCount < ((anCount / 2) + 1)) {
1890
+ am = symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE);
1891
+ if (am[0] !== 0.0) {
1892
+ am.splice(0, 0, 0.0);
1893
+ }
1894
+ }
1895
+ }
1896
+ }
1897
+ } catch (exc2) {
1898
+ if (exc2 instanceof Error) {
1899
+ ErrorLogger.LogException("MPH.populateModifiers", "PopulateModifiers", exc2);
1900
+ } else {
1901
+ throw exc2;
1902
+ }
1903
+ }
1904
+ return true;
1905
+
1906
+ }
1907
+
1908
+ private static KMLize(id: string, name: string,
1909
+ description: string,
1910
+ symbolCode: string,
1911
+ shapes: Array<ShapeInfo>,
1912
+ modifiers: Array<ShapeInfo>,
1913
+ ipc: IPointConversion,
1914
+ normalize: boolean, textColor: Color): string {
1915
+
1916
+ let kml: string = "";
1917
+
1918
+ let tempModifier: ShapeInfo;
1919
+
1920
+ let cdataStart: string = "<![CDATA[";
1921
+ let cdataEnd: string = "]]>";
1922
+
1923
+ let len: int = shapes.length;
1924
+ kml += ("<Folder id=\"" + id + "\">");
1925
+ kml += ("<name>" + cdataStart + name + cdataEnd + "</name>");
1926
+ kml += ("<visibility>1</visibility>");
1927
+ for (let i: int = 0; i < len; i++) {
1928
+
1929
+ let shapesToAdd: string = MultiPointHandler.ShapeToKMLString(name, description, symbolCode, shapes[i], ipc, normalize);
1930
+ kml += (shapesToAdd);
1931
+ }
1932
+
1933
+ let len2: int = modifiers.length;
1934
+
1935
+ for (let j: int = 0; j < len2; j++) {
1936
+
1937
+ tempModifier = modifiers[j];
1938
+
1939
+ //if(geMap)//if using google earth
1940
+ //assume kml text is going to be centered
1941
+ //AdjustModifierPointToCenter(tempModifier);
1942
+
1943
+ let labelsToAdd: string = MultiPointHandler.LabelToKMLString(tempModifier, ipc, normalize, textColor);
1944
+ kml += (labelsToAdd);
1945
+ }
1946
+
1947
+ kml += ("</Folder>");
1948
+ return kml.toString();
1949
+ }
1950
+
1951
+ /**
1952
+ *
1953
+ * @param shapes
1954
+ * @param modifiers
1955
+ * @param ipc
1956
+ * @param geMap
1957
+ * @param normalize
1958
+ * @return
1959
+ * @deprecated Use GeoJSONize()
1960
+ */
1961
+ private static JSONize(shapes: Array<ShapeInfo>, modifiers: Array<ShapeInfo>, ipc: IPointConversion, geMap: boolean, normalize: boolean): string {
1962
+ let polygons: string = "";
1963
+ let lines: string = "";
1964
+ let labels: string = "";
1965
+ let jstr: string = "";
1966
+ let tempModifier: ShapeInfo;
1967
+
1968
+ let len: int = shapes.length;
1969
+ for (let i: int = 0; i < len; i++) {
1970
+ if (jstr.length > 0) {
1971
+ jstr += ",";
1972
+ }
1973
+ let shapesToAdd: string = MultiPointHandler.ShapeToJSONString(shapes[i], ipc, geMap, normalize);
1974
+ if (shapesToAdd.length > 0) {
1975
+ if (shapesToAdd.startsWith("line", 2)) {
1976
+ if (lines.length > 0) {
1977
+ lines += ",";
1978
+ }
1979
+
1980
+ lines += shapesToAdd;
1981
+ } else {
1982
+ if (shapesToAdd.startsWith("polygon", 2)) {
1983
+ if (polygons.length > 0) {
1984
+ polygons += ",";
1985
+ }
1986
+
1987
+ polygons += shapesToAdd;
1988
+ }
1989
+ }
1990
+
1991
+ }
1992
+ }
1993
+
1994
+ jstr += "\"polygons\": [" + polygons + "],"
1995
+ + "\"lines\": [" + lines + "],";
1996
+ let len2: int = modifiers.length;
1997
+ labels = "";
1998
+ for (let j: int = 0; j < len2; j++) {
1999
+ tempModifier = modifiers[j];
2000
+ if (geMap) {
2001
+ MultiPointHandler.AdjustModifierPointToCenter(tempModifier);
2002
+ }
2003
+ let labelsToAdd: string = MultiPointHandler.LabelToJSONString(tempModifier, ipc, normalize);
2004
+ if (labelsToAdd.length > 0) {
2005
+ if (labels.length > 0) {
2006
+ labels += ",";
2007
+ }
2008
+
2009
+ labels += labelsToAdd;
2010
+
2011
+ }
2012
+ }
2013
+ jstr += "\"labels\": [" + labels + "]";
2014
+ return jstr;
2015
+ }
2016
+
2017
+ private static getIdealTextBackgroundColor(fgColor: Color): Color {
2018
+ //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "in function", Level.SEVERE);
2019
+ try {
2020
+ //an array of three elements containing the
2021
+ //hue, saturation, and brightness (in that order),
2022
+ //of the color with the indicated red, green, and blue components/
2023
+ let hsbvals: double[] = new Array<number>(3);
2024
+
2025
+ if (fgColor != null) {/*
2026
+ Color.RGBtoHSB(fgColor.getRed(), fgColor.getGreen(), fgColor.getBlue(), hsbvals);
2027
+
2028
+ if(hsbvals != null)
2029
+ {
2030
+ //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "length: " + hsbvals.length.toString());
2031
+ //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "H: " + String.valueOf(hsbvals[0]) + " S: " + String.valueOf(hsbvals[1]) + " B: " + String.valueOf(hsbvals[2]),Level.SEVERE);
2032
+ if(hsbvals[2] > 0.6)
2033
+ return Color.BLACK;
2034
+ else
2035
+ return Color.WHITE;
2036
+ }*/
2037
+
2038
+ let nThreshold: int = RendererSettings.getInstance().getTextBackgroundAutoColorThreshold();//160;
2039
+ let bgDelta: int = Math.trunc((fgColor.getRed() * 0.299) + (fgColor.getGreen() * 0.587) + (fgColor.getBlue() * 0.114));
2040
+ //ErrorLogger.LogMessage("bgDelta: " + String.valueOf(255-bgDelta));
2041
+ //if less than threshold, black, otherwise white.
2042
+ //return (255 - bgDelta < nThreshold) ? Color.BLACK : Color.WHITE;//new Color(0, 0, 0, fgColor.getAlpha())
2043
+ return (255 - bgDelta < nThreshold) ? new Color(0, 0, 0, fgColor.getAlpha()) : new Color(255, 255, 255, fgColor.getAlpha());
2044
+ }
2045
+ } catch (exc) {
2046
+ if (exc instanceof Error) {
2047
+ ErrorLogger.LogException("SymbolDraw", "getIdealtextBGColor", exc);
2048
+ } else {
2049
+ throw exc;
2050
+ }
2051
+ }
2052
+ return Color.WHITE;
2053
+ }
2054
+
2055
+ private static LabelToGeoJSONString(shapeInfo: ShapeInfo, ipc: IPointConversion, normalize: boolean, textColor: Color, textBackgroundColor: Color): string {
2056
+
2057
+ let JSONed: string = "";
2058
+ let properties: string = "";
2059
+ let geometry: string = "";
2060
+
2061
+ let outlineColor: Color = MultiPointHandler.getIdealTextBackgroundColor(textColor);
2062
+ if (textBackgroundColor != null) {
2063
+ outlineColor = textBackgroundColor;
2064
+ }
2065
+
2066
+ //AffineTransform at = shapeInfo.getAffineTransform();
2067
+ //Point2D coord = (Point2D)new Point2D(at.getTranslateX(), at.getTranslateY());
2068
+ //Point2D coord = (Point2D) new Point2D(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY());
2069
+ let coord: Point2D = new Point2D(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()) as Point2D;
2070
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2071
+ //M. Deutch 9-27-11
2072
+ if (normalize) {
2073
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
2074
+ }
2075
+ let latitude: double = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0;
2076
+ let longitude: double = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0;
2077
+ let angle: double = shapeInfo.getModifierAngle();
2078
+ coord.setLocation(longitude, latitude);
2079
+
2080
+ //diagnostic M. Deutch 10-18-11
2081
+ shapeInfo.setGlyphPosition(coord);
2082
+
2083
+ let text: string = shapeInfo.getModifierString();
2084
+
2085
+ let justify: int = shapeInfo.getTextJustify();
2086
+ let strJustify: string = "left";
2087
+ if (justify === 0) {
2088
+ strJustify = "left";
2089
+ } else {
2090
+ if (justify === 1) {
2091
+ strJustify = "center";
2092
+ } else {
2093
+ if (justify === 2) {
2094
+ strJustify = "right";
2095
+ }
2096
+ }
2097
+
2098
+ }
2099
+
2100
+
2101
+ let RS: RendererSettings = RendererSettings.getInstance();
2102
+
2103
+ if (text != null && text !== "") {
2104
+
2105
+ JSONed += ("{\"type\":\"Feature\",\"properties\":{\"label\":\"");
2106
+ JSONed += (text);
2107
+ JSONed += ("\",\"pointRadius\":0,\"fontColor\":\"");
2108
+ JSONed += (RendererUtilities.colorToHexString(textColor, false));
2109
+ JSONed += ("\",\"fontSize\":\"");
2110
+ JSONed += (RS.getMPLabelFont().getSize().toString() + "pt\"");
2111
+ JSONed += (",\"fontFamily\":\"");
2112
+ JSONed += (RS.getMPLabelFont().getName());
2113
+ JSONed += (", sans-serif");
2114
+
2115
+ if (RS.getMPLabelFont().getType() === Font.BOLD) {
2116
+ JSONed += ("\",\"fontWeight\":\"bold\"");
2117
+ } else {
2118
+ JSONed += ("\",\"fontWeight\":\"normal\"");
2119
+ }
2120
+
2121
+ //JSONed += (",\"labelAlign\":\"lm\"");
2122
+ JSONed += (",\"labelAlign\":\"");
2123
+ JSONed += (strJustify);
2124
+ JSONed += ("\",\"labelBaseline\":\"alphabetic");
2125
+ JSONed += ("\",\"labelXOffset\":0");
2126
+ JSONed += (",\"labelYOffset\":0");
2127
+ JSONed += (",\"labelOutlineColor\":\"");
2128
+ JSONed += (RendererUtilities.colorToHexString(outlineColor, false));
2129
+ JSONed += ("\",\"labelOutlineWidth\":");
2130
+ JSONed += ("4");
2131
+ JSONed += (",\"rotation\":");
2132
+ JSONed += (angle);
2133
+ JSONed += (",\"angle\":");
2134
+ JSONed += (angle);
2135
+ JSONed += ("},");
2136
+
2137
+ JSONed += ("\"geometry\":{\"type\":\"Point\",\"coordinates\":[");
2138
+ JSONed += (longitude);
2139
+ JSONed += (",");
2140
+ JSONed += (latitude);
2141
+ JSONed += ("]");
2142
+ JSONed += ("}}");
2143
+
2144
+ } else {
2145
+ return "";
2146
+ }
2147
+
2148
+ return JSONed.toString();
2149
+ }
2150
+
2151
+ private static ShapeToGeoJSONString(shapeInfo: ShapeInfo, ipc: IPointConversion, normalize: boolean): string {
2152
+ let JSONed: string = "";
2153
+ let properties: string = "";
2154
+ let geometry: string = "";
2155
+ let geometryType: string;
2156
+ let sda: string;
2157
+ /*
2158
+ NOTE: Google Earth / KML colors are backwards.
2159
+ They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world
2160
+ * */
2161
+ let lineColor: Color = shapeInfo.getLineColor();
2162
+ let fillColor: Color = shapeInfo.getFillColor();
2163
+
2164
+ if (shapeInfo.getShapeType() === ShapeInfo.SHAPE_TYPE_FILL || fillColor != null || shapeInfo.getPatternFillImage() != null) {
2165
+ geometryType = "\"Polygon\"";
2166
+ } else //if(shapeInfo.getShapeType() == ShapeInfo.SHAPE_TYPE_POLYLINE)
2167
+ {
2168
+ geometryType = "\"MultiLineString\"";
2169
+ }
2170
+
2171
+ let stroke: BasicStroke;
2172
+ stroke = shapeInfo.getStroke();
2173
+ let lineWidth: int = 4;
2174
+
2175
+ if (stroke != null) {
2176
+ lineWidth = Math.trunc(stroke.getLineWidth());
2177
+ //lineWidth++;
2178
+ //console.log("lineWidth: " + lineWidth.toString());
2179
+ }
2180
+
2181
+ //generate JSON properties for feature
2182
+ properties += ("\"properties\":{");
2183
+ properties += ("\"label\":\"\",");
2184
+ if (lineColor != null) {
2185
+ properties += ("\"strokeColor\":\"" + RendererUtilities.colorToHexString(lineColor, false) + "\",");
2186
+ properties += ("\"lineOpacity\":" + (lineColor.getAlpha() / 255).toString() + ",");
2187
+ }
2188
+ if (fillColor != null) {
2189
+ properties += ("\"fillColor\":\"" + RendererUtilities.colorToHexString(fillColor, false) + "\",");
2190
+ properties += ("\"fillOpacity\":" + (fillColor.getAlpha() / 255).toString() + ",");
2191
+ }
2192
+ if (shapeInfo.getPatternFillImage() != null) {
2193
+ properties += ("\"fillPattern\":\"" + shapeInfo.getPatternFillImage() + "\",");
2194
+ }
2195
+ if (stroke.getDashArray() != null) {
2196
+ sda = "\"strokeDasharray\":[" + stroke.getDashArray().toString() + "],";
2197
+ properties += (sda);
2198
+ }
2199
+
2200
+
2201
+ let lineCap: int = stroke.getEndCap();
2202
+ properties += ("\"lineCap\":" + lineCap + ",");
2203
+
2204
+ let strokeWidth: string = lineWidth.toString();
2205
+ properties += ("\"strokeWidth\":" + strokeWidth + ",");
2206
+ properties += ("\"strokeWeight\":" + strokeWidth + "");
2207
+ properties += ("},");
2208
+
2209
+
2210
+ properties += ("\"style\":{");
2211
+ if (lineColor != null) {
2212
+ properties += ("\"stroke\":\"" + RendererUtilities.colorToHexString(lineColor, false) + "\",");
2213
+ properties += ("\"line-opacity\":" + (lineColor.getAlpha() / 255).toString() + ",");
2214
+ }
2215
+ if (fillColor != null) {
2216
+ properties += ("\"fill\":\"" + RendererUtilities.colorToHexString(fillColor, false) + "\",");
2217
+ properties += ("\"fill-opacity\":" + (fillColor.getAlpha() / 255).toString() + ",");
2218
+ }
2219
+ if (stroke.getDashArray() != null) {
2220
+ let da: number[] = stroke.getDashArray();
2221
+ sda = da[0].toString();
2222
+ if (da.length > 1) {
2223
+ for (let i: int = 1; i < da.length; i++) {
2224
+ sda = sda + " " + da[i].toString();
2225
+ }
2226
+ }
2227
+ sda = "\"stroke-dasharray\":\"" + sda + "\",";
2228
+ properties += (sda);
2229
+ sda = null;
2230
+ }
2231
+
2232
+ if (lineCap === BasicStroke.CAP_SQUARE) {
2233
+
2234
+ properties += ("\"stroke-linecap\":\"square\",");
2235
+ }
2236
+
2237
+ else {
2238
+ if (lineCap === BasicStroke.CAP_ROUND) {
2239
+
2240
+ properties += ("\"stroke-linecap\":\"round\",");
2241
+ }
2242
+
2243
+ else {
2244
+ if (lineCap === BasicStroke.CAP_BUTT) {
2245
+
2246
+ properties += ("\"stroke-linecap\":\"butt\",");
2247
+ }
2248
+
2249
+ }
2250
+
2251
+ }
2252
+
2253
+
2254
+ strokeWidth = lineWidth.toString();
2255
+ properties += ("\"stroke-width\":" + strokeWidth);
2256
+ properties += ("}");
2257
+
2258
+
2259
+ //generate JSON geometry for feature
2260
+ geometry += ("\"geometry\":{\"type\":");
2261
+ geometry += (geometryType);
2262
+ geometry += (",\"coordinates\":[");
2263
+
2264
+ let shapesArray: Point2D[][] = shapeInfo.getPolylines();
2265
+
2266
+ for (let i: int = 0; i < shapesArray.length; i++) {
2267
+ let pointList: Point2D[] = shapesArray[i];
2268
+
2269
+ normalize = MultiPointHandler.normalizePoints(pointList, ipc);
2270
+
2271
+ geometry += ("[");
2272
+
2273
+ //console.log("Pixel Coords:");
2274
+ for (let j: int = 0; j < pointList.length; j++) {
2275
+ let coord: Point2D = pointList[j] as Point2D;
2276
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2277
+ //M. Deutch 9-27-11
2278
+ if (normalize) {
2279
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
2280
+ }
2281
+ let latitude: double = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0;
2282
+ let longitude: double = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0;
2283
+
2284
+ //fix for fill crossing DTL
2285
+ if (normalize && fillColor != null) {
2286
+ if (longitude > 0) {
2287
+ longitude -= 360;
2288
+ }
2289
+ }
2290
+
2291
+ //diagnostic M. Deutch 10-18-11
2292
+ //set the point as geo so that the
2293
+ //coord.setLocation(longitude, latitude);
2294
+ coord = new Point2D(longitude, latitude);
2295
+ pointList[j] = coord;
2296
+ //end section
2297
+
2298
+ geometry += ("[");
2299
+ geometry += (longitude);
2300
+ geometry += (",");
2301
+ geometry += (latitude);
2302
+ geometry += ("]");
2303
+
2304
+ if (j < (pointList.length - 1)) {
2305
+ geometry += (",");
2306
+ }
2307
+ }
2308
+
2309
+ geometry += ("]");
2310
+
2311
+ if (i < (shapesArray.length - 1)) {
2312
+ geometry += (",");
2313
+ }
2314
+ }
2315
+ geometry += ("]}");
2316
+
2317
+ JSONed += ("{\"type\":\"Feature\",");
2318
+ JSONed += (properties.toString());
2319
+ JSONed += (",");
2320
+ JSONed += (geometry.toString());
2321
+ JSONed += ("}");
2322
+
2323
+ return JSONed.toString();
2324
+ }
2325
+
2326
+ private static ImageToGeoJSONString(shapeInfo: ShapeInfo, ipc: IPointConversion, normalize: boolean): string {
2327
+
2328
+ let JSONed: string = "";
2329
+ let properties: string = "";
2330
+ let geometry: string = "";
2331
+
2332
+ //AffineTransform at = shapeInfo.getAffineTransform();
2333
+ //Point2D coord = (Point2D)new Point2D(at.getTranslateX(), at.getTranslateY());
2334
+ //Point2D coord = (Point2D) new Point2D(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY());
2335
+ let coord: Point2D = new Point2D(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()) as Point2D;
2336
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2337
+ //M. Deutch 9-27-11
2338
+ if (normalize) {
2339
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
2340
+ }
2341
+ let latitude: double = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0;
2342
+ let longitude: double = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0;
2343
+ let angle: double = shapeInfo.getModifierAngle();
2344
+ coord.setLocation(longitude, latitude);
2345
+
2346
+ //diagnostic M. Deutch 10-18-11
2347
+ shapeInfo.setGlyphPosition(coord);
2348
+
2349
+ let image: string = shapeInfo.getModifierImage();
2350
+
2351
+ let RS: RendererSettings = RendererSettings.getInstance();
2352
+
2353
+ if (image != null) {
2354
+
2355
+ JSONed += ("{\"type\":\"Feature\",\"properties\":{\"image\":\"");
2356
+ JSONed += (image);
2357
+ JSONed += ("\",\"rotation\":");
2358
+ JSONed += (angle);
2359
+ JSONed += (",\"angle\":");
2360
+ JSONed += (angle);
2361
+ JSONed += ("},");
2362
+ JSONed += ("\"geometry\":{\"type\":\"Point\",\"coordinates\":[");
2363
+ JSONed += (longitude);
2364
+ JSONed += (",");
2365
+ JSONed += (latitude);
2366
+ JSONed += ("]");
2367
+ JSONed += ("}}");
2368
+
2369
+ } else {
2370
+ return "";
2371
+ }
2372
+
2373
+ return JSONed.toString();
2374
+ }
2375
+
2376
+ private static GeoJSONize(shapes: Array<ShapeInfo>, modifiers: Array<ShapeInfo>, ipc: IPointConversion, normalize: boolean, textColor: Color, textBackgroundColor: Color): string {
2377
+
2378
+ let jstr: string = "";
2379
+ let tempModifier: ShapeInfo;
2380
+ let fc: string = "";//JSON feature collection
2381
+
2382
+ fc += ("[");
2383
+
2384
+ let len: int = shapes.length;
2385
+ for (let i: int = 0; i < len; i++)
2386
+ {
2387
+
2388
+ let shapesToAdd: string = null;
2389
+ let tempShape:ShapeInfo = shapes[i];
2390
+ if(tempShape != null && tempShape !== undefined)
2391
+ shapesToAdd = MultiPointHandler.ShapeToGeoJSONString(tempShape, ipc, normalize);
2392
+ if (shapesToAdd != null && shapesToAdd.length > 0) {
2393
+ fc += (shapesToAdd);
2394
+ }
2395
+ if (shapesToAdd != null && i < len - 1) {
2396
+ fc += (",");
2397
+ }
2398
+ }
2399
+
2400
+ let len2: int = modifiers.length;
2401
+
2402
+ for (let j: int = 0; j < len2; j++) {
2403
+ tempModifier = modifiers[j];
2404
+
2405
+ let modifiersToAdd: string;
2406
+ if (modifiers[j].getModifierImage() != null) {
2407
+ modifiersToAdd = MultiPointHandler.ImageToGeoJSONString(tempModifier, ipc, normalize);
2408
+ } else {
2409
+ modifiersToAdd = MultiPointHandler.LabelToGeoJSONString(tempModifier, ipc, normalize, textColor, textBackgroundColor);
2410
+ }
2411
+ if (modifiersToAdd.length > 0) {
2412
+ fc += (",");
2413
+ fc += (modifiersToAdd);
2414
+ }
2415
+ }
2416
+ fc += ("]");
2417
+ let GeoJSON: string = fc.toString();
2418
+ return GeoJSON;
2419
+ }
2420
+
2421
+ /**
2422
+ *
2423
+ * @param shapes
2424
+ * @param modifiers
2425
+ * @param ipc
2426
+ * @param normalize
2427
+ * @deprecated
2428
+ */
2429
+ private static MakeWWReady(
2430
+ shapes: Array<ShapeInfo>,
2431
+ modifiers: Array<ShapeInfo>,
2432
+ ipc: IPointConversion,
2433
+ normalize: boolean): void {
2434
+ let temp: ShapeInfo;
2435
+ let len: int = shapes.length;
2436
+ for (let i: int = 0; i < len; i++) {
2437
+
2438
+ temp = MultiPointHandler.ShapeToWWReady(shapes[i], ipc, normalize);
2439
+ shapes[i] = temp;
2440
+
2441
+ }
2442
+
2443
+ let len2: int = modifiers.length;
2444
+ let tempModifier: ShapeInfo;
2445
+ for (let j: int = 0; j < len2; j++) {
2446
+
2447
+ tempModifier = modifiers[j];
2448
+
2449
+ //Do we need this for World Wind?
2450
+ tempModifier = MultiPointHandler.LabelToWWReady(tempModifier, ipc, normalize);
2451
+ modifiers[j] = tempModifier;
2452
+
2453
+ }
2454
+
2455
+ }
2456
+
2457
+ private static normalizePoints(shape: Array<Point2D>, ipc: IPointConversion): boolean {
2458
+ let geoCoords: Point2D[] = new Array();
2459
+ let n: int = shape.length;
2460
+ //for (int j = 0; j < shape.length; j++)
2461
+ for (let j: int = 0; j < n; j++) {
2462
+ let coord: Point2D = shape[j];
2463
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2464
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
2465
+ let latitude: double = geoCoord.getY();
2466
+ let longitude: double = geoCoord.getX();
2467
+ let pt2d: Point2D = new Point2D(longitude, latitude);
2468
+ geoCoords.push(pt2d);
2469
+ }
2470
+ let normalize: boolean = MultiPointHandler.crossesIDL(geoCoords);
2471
+ return normalize;
2472
+ }
2473
+
2474
+ private static IsOnePointSymbolCode(symbolCode: string): boolean {
2475
+ let basicCode: string = SymbolUtilities.getBasicSymbolID(symbolCode);
2476
+ //TODO: Revisit for basic shapes
2477
+ //some airspaces affected
2478
+ if (symbolCode === "CAKE-----------") {
2479
+ return true;
2480
+ } else {
2481
+ if (symbolCode === "CYLINDER-------") {
2482
+ return true;
2483
+ } else {
2484
+ if (symbolCode === "RADARC---------") {
2485
+ return true;
2486
+ }
2487
+ }
2488
+
2489
+ }
2490
+
2491
+
2492
+ return false;
2493
+ }
2494
+
2495
+ private static ShapeToKMLString(name: string,
2496
+ description: string,
2497
+ symbolCode: string,
2498
+ shapeInfo: ShapeInfo,
2499
+ ipc: IPointConversion,
2500
+ normalize: boolean): string {
2501
+
2502
+ let kml: string = "";
2503
+
2504
+ let lineColor: Color;
2505
+ let fillColor: Color;
2506
+ let googleLineColor: string;
2507
+ let googleFillColor: string;
2508
+
2509
+ //String lineStyleId = "lineColor";
2510
+
2511
+ let stroke: BasicStroke;
2512
+ let lineWidth: int = 4;
2513
+
2514
+ symbolCode = JavaRendererUtilities.normalizeSymbolCode(symbolCode);
2515
+
2516
+ let cdataStart: string = "<![CDATA[";
2517
+ let cdataEnd: string = "]]>";
2518
+
2519
+ kml += ("<Placemark>");//("<Placemark id=\"" + id + "_mg" + "\">");
2520
+ kml += ("<description>" + cdataStart + "<b>" + name + "</b><br/>" + "\n" + description + cdataEnd + "</description>");
2521
+ //kml += ("<Style id=\"" + lineStyleId + "\">");
2522
+ kml += ("<Style>");
2523
+
2524
+ lineColor = shapeInfo.getLineColor();
2525
+ if (lineColor != null) {
2526
+ googleLineColor = RendererUtilities.colorToHexString(shapeInfo.getLineColor(), false).substring(1);
2527
+
2528
+ stroke = shapeInfo.getStroke();
2529
+
2530
+ if (stroke != null) {
2531
+ lineWidth = stroke.getLineWidth() as int;
2532
+ }
2533
+
2534
+ googleLineColor = JavaRendererUtilities.ARGBtoABGR(googleLineColor);
2535
+
2536
+ kml += ("<LineStyle>");
2537
+ kml += ("<color>" + googleLineColor + "</color>");
2538
+ kml += ("<colorMode>normal</colorMode>");
2539
+ kml += ("<width>" + lineWidth.toString() + "</width>");
2540
+ kml += ("</LineStyle>");
2541
+ }
2542
+
2543
+ fillColor = shapeInfo.getFillColor();
2544
+ let fillPattern: string = shapeInfo.getPatternFillImage();
2545
+ if (fillColor != null || fillPattern != null) {
2546
+ kml += ("<PolyStyle>");
2547
+
2548
+ if (fillColor != null) {
2549
+ googleFillColor = RendererUtilities.colorToHexString(shapeInfo.getFillColor(), false).substring(1);
2550
+ googleFillColor = JavaRendererUtilities.ARGBtoABGR(googleFillColor);
2551
+ kml += ("<color>" + googleFillColor + "</color>");
2552
+ kml += ("<colorMode>normal</colorMode>");
2553
+ }
2554
+ if (fillPattern != null) {
2555
+ kml += ("<shader>" + fillPattern + "</shader>");
2556
+ }
2557
+
2558
+ kml += ("<fill>1</fill>");
2559
+ if (lineColor != null) {
2560
+ kml += ("<outline>1</outline>");
2561
+ } else {
2562
+ kml += ("<outline>0</outline>");
2563
+ }
2564
+ kml += ("</PolyStyle>");
2565
+ }
2566
+
2567
+ kml += ("</Style>");
2568
+
2569
+ let shapesArray: Point2D[][] = shapeInfo.getPolylines();
2570
+ let len: int = shapesArray.length;
2571
+ kml += ("<MultiGeometry>");
2572
+
2573
+ for (let i: int = 0; i < len; i++) {
2574
+ let shape: Point2D[] = shapesArray[i];
2575
+ normalize = MultiPointHandler.normalizePoints(shape, ipc);
2576
+ if (lineColor != null && fillColor == null) {
2577
+ kml += ("<LineString>");
2578
+ kml += ("<tessellate>1</tessellate>");
2579
+ kml += ("<altitudeMode>clampToGround</altitudeMode>");
2580
+ kml += ("<coordinates>");
2581
+ let n: int = shape.length;
2582
+ //for (int j = 0; j < shape.length; j++)
2583
+ for (let j: int = 0; j < n; j++) {
2584
+ let coord: Point2D = shape[j] as Point2D;
2585
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2586
+ if (normalize) {
2587
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
2588
+ }
2589
+
2590
+ let latitude: double = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0;
2591
+ let longitude: double = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0;
2592
+
2593
+ kml += (longitude);
2594
+ kml += (",");
2595
+ kml += (latitude);
2596
+ if (j < shape.length - 1) {
2597
+
2598
+ kml += (" ");
2599
+ }
2600
+
2601
+ }
2602
+
2603
+ kml += ("</coordinates>");
2604
+ kml += ("</LineString>");
2605
+ }
2606
+
2607
+ if (fillColor != null) {
2608
+
2609
+ if (i === 0) {
2610
+ kml += ("<Polygon>");
2611
+ }
2612
+ //kml += ("<outerBoundaryIs>");
2613
+ if (i === 1 && len > 1) {
2614
+ kml += ("<innerBoundaryIs>");
2615
+ } else {
2616
+ kml += ("<outerBoundaryIs>");
2617
+ }
2618
+ kml += ("<LinearRing>");
2619
+ kml += ("<altitudeMode>clampToGround</altitudeMode>");
2620
+ kml += ("<tessellate>1</tessellate>");
2621
+ kml += ("<coordinates>");
2622
+
2623
+ //this section is a workaround for a google earth bug. Issue 417 was closed
2624
+ //for linestrings but they did not fix the smae issue for fills. If Google fixes the issue
2625
+ //for fills then this section will need to be commented or it will induce an error.
2626
+ let lastLongitude: double = Number.MIN_VALUE;
2627
+ if (normalize === false && MultiPointHandler.IsOnePointSymbolCode(symbolCode)) {
2628
+ let n: int = shape.length;
2629
+ //for (int j = 0; j < shape.length; j++)
2630
+ for (let j: int = 0; j < n; j++) {
2631
+ let coord: Point2D = shape[j] as Point2D;
2632
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2633
+ let longitude: double = geoCoord.getX();
2634
+ if (lastLongitude !== Number.MIN_VALUE) {
2635
+ if (Math.abs(longitude - lastLongitude) > 180) {
2636
+ normalize = true;
2637
+ break;
2638
+ }
2639
+ }
2640
+ lastLongitude = longitude;
2641
+ }
2642
+ }
2643
+ let n: int = shape.length;
2644
+ //for (int j = 0; j < shape.length; j++)
2645
+ for (let j: int = 0; j < n; j++) {
2646
+ let coord: Point2D = shape[j] as Point2D;
2647
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2648
+
2649
+ let latitude: double = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0;
2650
+ let longitude: double = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0;
2651
+
2652
+ //fix for fill crossing DTL
2653
+ if (normalize) {
2654
+ if (longitude > 0) {
2655
+ longitude -= 360;
2656
+ }
2657
+ }
2658
+
2659
+ kml += (longitude);
2660
+ kml += (",");
2661
+ kml += (latitude);
2662
+ if (j < shape.length - 1) {
2663
+
2664
+ kml += (" ");
2665
+ }
2666
+
2667
+ }
2668
+
2669
+ kml += ("</coordinates>");
2670
+ kml += ("</LinearRing>");
2671
+ if (i === 1 && len > 1) {
2672
+ kml += ("</innerBoundaryIs>");
2673
+ } else {
2674
+ kml += ("</outerBoundaryIs>");
2675
+ }
2676
+ if (i === len - 1) {
2677
+ kml += ("</Polygon>");
2678
+ }
2679
+ }
2680
+ }
2681
+
2682
+ kml += ("</MultiGeometry>");
2683
+ kml += ("</Placemark>");
2684
+
2685
+ return kml.toString();
2686
+ }
2687
+
2688
+ /**
2689
+ *
2690
+ * @param shapeInfo
2691
+ * @param ipc
2692
+ * @param normalize
2693
+ * @return
2694
+ * @deprecated
2695
+ */
2696
+ private static ShapeToWWReady(
2697
+ shapeInfo: ShapeInfo,
2698
+ ipc: IPointConversion,
2699
+ normalize: boolean): ShapeInfo {
2700
+
2701
+ let shapesArray: Point2D[][] = shapeInfo.getPolylines();
2702
+ let len: int = shapesArray.length;
2703
+
2704
+ for (let i: int = 0; i < len; i++) {
2705
+ let shape: Point2D[] = shapesArray[i];
2706
+
2707
+ if (shapeInfo.getLineColor() != null) {
2708
+ let n: int = shape.length;
2709
+ //for (int j = 0; j < shape.length; j++)
2710
+ for (let j: int = 0; j < n; j++) {
2711
+ let coord: Point2D = shape[j] as Point2D;
2712
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2713
+ //M. Deutch 9-26-11
2714
+ if (normalize) {
2715
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
2716
+ }
2717
+
2718
+ shape[j] = geoCoord;
2719
+
2720
+ }
2721
+
2722
+ }
2723
+
2724
+ if (shapeInfo.getFillColor() != null) {
2725
+ let n: int = shape.length;
2726
+ //for (int j = 0; j < shape.length; j++)
2727
+ for (let j: int = 0; j < n; j++) {
2728
+ let coord: Point2D = shape[j] as Point2D;
2729
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2730
+ //M. Deutch 9-26-11
2731
+ //commenting these two lines seems to help with fill not go around the pole
2732
+ //if(normalize)
2733
+ //geoCoord=NormalizeCoordToGECoord(geoCoord);
2734
+
2735
+ shape[j] = geoCoord;
2736
+ }
2737
+ }
2738
+ }
2739
+
2740
+ return shapeInfo;
2741
+ }
2742
+
2743
+ private static LabelToWWReady(shapeInfo: ShapeInfo,
2744
+ ipc: IPointConversion,
2745
+ normalize: boolean): ShapeInfo | null {
2746
+
2747
+ try {
2748
+ let coord: Point2D = new Point2D(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()) as Point2D;
2749
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2750
+ //M. Deutch 9-26-11
2751
+ if (normalize) {
2752
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
2753
+ }
2754
+ let latitude: double = geoCoord.getY();
2755
+ let longitude: double = geoCoord.getX();
2756
+ let angle: number = Math.round(shapeInfo.getModifierAngle());
2757
+
2758
+ let text: string = shapeInfo.getModifierString();
2759
+
2760
+ if (text != null && text !== "") {
2761
+ shapeInfo.setModifierPosition(geoCoord);
2762
+ } else {
2763
+ return null;
2764
+ }
2765
+ } catch (exc) {
2766
+ if (exc instanceof Error) {
2767
+ console.error(exc.message);
2768
+ console.log(exc.stack);
2769
+ } else {
2770
+ throw exc;
2771
+ }
2772
+ }
2773
+
2774
+ return shapeInfo;
2775
+ }
2776
+
2777
+ /**
2778
+ * Google earth centers text on point rather than drawing from that point.
2779
+ * So we need to adjust the point to where the center of the text would be.
2780
+ *
2781
+ * @param modifier
2782
+ */
2783
+ private static AdjustModifierPointToCenter(modifier: ShapeInfo): void {
2784
+ let at: AffineTransform;
2785
+ try {
2786
+ let bounds2: Rectangle = modifier.getTextLayout().getBounds();
2787
+ let bounds: Rectangle2D = new Rectangle2D(bounds2.getX(), bounds2.getY(), bounds2.getWidth(), bounds2.getHeight());
2788
+ } catch (exc) {
2789
+ if (exc instanceof Error) {
2790
+ console.error(exc.message);
2791
+ console.log(exc.stack);
2792
+ } else {
2793
+ throw exc;
2794
+ }
2795
+ }
2796
+ }
2797
+
2798
+ /**
2799
+ *
2800
+ * @param shapeInfo
2801
+ * @param ipc
2802
+ * @param geMap
2803
+ * @param normalize
2804
+ * @return
2805
+ * @deprecated
2806
+ */
2807
+ private static ShapeToJSONString(shapeInfo: ShapeInfo, ipc: IPointConversion, geMap: boolean, normalize: boolean): string {
2808
+ let JSONed: string = "";
2809
+ /*
2810
+ NOTE: Google Earth / KML colors are backwards.
2811
+ They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world
2812
+ * */
2813
+ let fillColor: string;
2814
+ let lineColor: string;
2815
+
2816
+ if (shapeInfo.getLineColor() != null) {
2817
+ lineColor = RendererUtilities.colorToHexString(shapeInfo.getLineColor(), false).substring(1);
2818
+ if (geMap) {
2819
+ lineColor = JavaRendererUtilities.ARGBtoABGR(lineColor);
2820
+ }
2821
+
2822
+ }
2823
+ if (shapeInfo.getFillColor() != null) {
2824
+ fillColor = RendererUtilities.colorToHexString(shapeInfo.getFillColor(), false).substring(1);
2825
+ if (geMap) {
2826
+ fillColor = JavaRendererUtilities.ARGBtoABGR(fillColor);
2827
+ }
2828
+ }
2829
+
2830
+ let stroke: BasicStroke;
2831
+ stroke = shapeInfo.getStroke();
2832
+ let lineWidth: int = 4;
2833
+
2834
+ if (stroke != null) {
2835
+ lineWidth = stroke.getLineWidth() as int;
2836
+ }
2837
+
2838
+ let shapesArray: Point2D[][] = shapeInfo.getPolylines();
2839
+ let n: int = shapesArray.length;
2840
+ //for (int i = 0; i < shapesArray.length; i++)
2841
+ for (let i: int = 0; i < n; i++) {
2842
+ let shape: Point2D[] = shapesArray[i];
2843
+
2844
+ if (fillColor != null) {
2845
+ JSONed += ("{\"polygon\":[");
2846
+ } else {
2847
+ JSONed += ("{\"line\":[");
2848
+ }
2849
+
2850
+ let t: int = shape.length;
2851
+ //for (int j = 0; j < shape.length; j++)
2852
+ for (let j: int = 0; j < t; j++) {
2853
+ let coord: Point2D = shape[j] as Point2D;
2854
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2855
+ //M. Deutch 9-27-11
2856
+ if (normalize) {
2857
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
2858
+ }
2859
+ let latitude: double = geoCoord.getY();
2860
+ let longitude: double = geoCoord.getX();
2861
+
2862
+ //diagnostic M. Deutch 10-18-11
2863
+ //set the point as geo so that the
2864
+ coord = new Point2D(longitude, latitude);
2865
+ shape[j] = coord;
2866
+
2867
+ JSONed += ("[");
2868
+ JSONed += (longitude);
2869
+ JSONed += (",");
2870
+ JSONed += (latitude);
2871
+ JSONed += ("]");
2872
+
2873
+ if (j < (shape.length - 1)) {
2874
+ JSONed += (",");
2875
+ }
2876
+ }
2877
+
2878
+ JSONed += ("]");
2879
+ if (lineColor != null) {
2880
+ JSONed += (",\"lineColor\":\"");
2881
+ JSONed += (lineColor);
2882
+
2883
+ JSONed += ("\"");
2884
+ }
2885
+ if (fillColor != null) {
2886
+ JSONed += (",\"fillColor\":\"");
2887
+ JSONed += (fillColor);
2888
+ JSONed += ("\"");
2889
+ }
2890
+
2891
+ JSONed += (",\"lineWidth\":\"");
2892
+ JSONed += (lineWidth.toString());
2893
+ JSONed += ("\"");
2894
+
2895
+ JSONed += ("}");
2896
+
2897
+ if (i < (shapesArray.length - 1)) {
2898
+ JSONed += (",");
2899
+ }
2900
+ }
2901
+
2902
+ return JSONed.toString();
2903
+ }
2904
+
2905
+ private static LabelToKMLString(shapeInfo: ShapeInfo, ipc: IPointConversion, normalize: boolean, textColor: Color): string {
2906
+ let kml: string = "";
2907
+
2908
+ //Point2D coord = (Point2D) new Point2D(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY());
2909
+ let coord: Point2D = new Point2D(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()) as Point2D;
2910
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2911
+ //M. Deutch 9-26-11
2912
+ if (normalize) {
2913
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
2914
+ }
2915
+ let latitude: double = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0;
2916
+ let longitude: double = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0;
2917
+ let angle: number = Math.round(shapeInfo.getModifierAngle());
2918
+
2919
+ let text: string = shapeInfo.getModifierString();
2920
+
2921
+ let cdataStart: string = "<![CDATA[";
2922
+ let cdataEnd: string = "]]>";
2923
+
2924
+ let color: string = RendererUtilities.colorToHexString(textColor, false).substring(1);
2925
+ color = JavaRendererUtilities.ARGBtoABGR(color);
2926
+ let kmlScale: double = RendererSettings.getInstance().getKMLLabelScale();
2927
+
2928
+ if (kmlScale > 0 && text != null && text !== "") {
2929
+ kml += ("<Placemark>");//("<Placemark id=\"" + id + "_lp" + i + "\">");
2930
+ kml += ("<name>" + cdataStart + text + cdataEnd + "</name>");
2931
+ kml += ("<Style>");
2932
+ kml += ("<IconStyle>");
2933
+ kml += ("<scale>" + kmlScale + "</scale>");
2934
+ kml += ("<heading>" + angle + "</heading>");
2935
+ kml += ("<Icon>");
2936
+ kml += ("<href></href>");
2937
+ kml += ("</Icon>");
2938
+ kml += ("</IconStyle>");
2939
+ kml += ("<LabelStyle>");
2940
+ kml += ("<color>" + color + "</color>");
2941
+ kml += ("<scale>" + kmlScale.toString() + "</scale>");
2942
+ kml += ("</LabelStyle>");
2943
+ kml += ("</Style>");
2944
+ kml += ("<Point>");
2945
+ kml += ("<extrude>1</extrude>");
2946
+ kml += ("<altitudeMode>relativeToGround</altitudeMode>");
2947
+ kml += ("<coordinates>");
2948
+ kml += (longitude);
2949
+ kml += (",");
2950
+ kml += (latitude);
2951
+ kml += ("</coordinates>");
2952
+ kml += ("</Point>");
2953
+ kml += ("</Placemark>");
2954
+ } else {
2955
+ return "";
2956
+ }
2957
+
2958
+ return kml.toString();
2959
+ }
2960
+
2961
+ /**
2962
+ *
2963
+ * @param shapeInfo
2964
+ * @param ipc
2965
+ * @param normalize
2966
+ * @return
2967
+ * @deprecated
2968
+ */
2969
+ private static LabelToJSONString(shapeInfo: ShapeInfo, ipc: IPointConversion, normalize: boolean): string {
2970
+ let JSONed: string = "";
2971
+ /*
2972
+ NOTE: Google Earth / KML colors are backwards.
2973
+ They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world
2974
+ * */
2975
+ JSONed += ("{\"label\":");
2976
+
2977
+ let coord: Point2D = new Point2D(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()) as Point2D;
2978
+ let geoCoord: Point2D = ipc.PixelsToGeo(coord);
2979
+ if (normalize) {
2980
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
2981
+ }
2982
+ let latitude: double = geoCoord.getY();
2983
+ let longitude: double = geoCoord.getX();
2984
+ let angle: double = shapeInfo.getModifierAngle();
2985
+ coord.setLocation(longitude, latitude);
2986
+
2987
+ shapeInfo.setGlyphPosition(coord);
2988
+
2989
+ let text: string = shapeInfo.getModifierString();
2990
+
2991
+ if (text != null && text !== "") {
2992
+ JSONed += ("[");
2993
+ JSONed += (longitude);
2994
+ JSONed += (",");
2995
+ JSONed += (latitude);
2996
+ JSONed += ("]");
2997
+
2998
+ JSONed += (",\"text\":\"");
2999
+ JSONed += (text);
3000
+ JSONed += ("\"");
3001
+
3002
+ JSONed += (",\"angle\":\"");
3003
+ JSONed += (angle);
3004
+ JSONed += ("\"}");
3005
+ } else {
3006
+ return "";
3007
+ }
3008
+
3009
+ return JSONed.toString();
3010
+ }
3011
+
3012
+ public static canRenderMultiPoint(symbolID: string, modifiers: Map<string, string>, numPoints: int): string {
3013
+ try {
3014
+ let basicID: string = SymbolUtilities.getBasicSymbolID(symbolID);
3015
+ let info: MSInfo = MSLookup.getInstance().getMSLInfo(symbolID);
3016
+
3017
+ if (info == null) {
3018
+ if (SymbolID.getVersion(symbolID) === SymbolID.Version_2525E) {
3019
+ return "Basic ID: " + basicID + " not recognized in version E (13)";
3020
+ } else {
3021
+ return "Basic ID: " + basicID + " not recognized in version D (11)";
3022
+ }
3023
+ }
3024
+
3025
+ let drawRule: int = info.getDrawRule();
3026
+
3027
+ if (drawRule === DrawRules.DONOTDRAW) {
3028
+ return "Basic ID: " + basicID + " has no draw rule";
3029
+ } else if (!SymbolUtilities.isMultiPoint(symbolID)) {
3030
+ return "Basic ID: " + basicID + " is not a multipoint symbol";
3031
+ } else if (numPoints < info.getMinPointCount()) {
3032
+ return "Basic ID: " + basicID + " requires a minimum of " + info.getMinPointCount().toString() + " points. " + numPoints.toString() + " are present.";
3033
+ }
3034
+
3035
+ //now check for required modifiers
3036
+ let AM: Array<number> = new Array();
3037
+ let AN: Array<number> = new Array();
3038
+ if (modifiers.has(Modifiers.AM_DISTANCE)) {
3039
+ let amArray: string[] = modifiers.get(Modifiers.AM_DISTANCE).split(",");
3040
+ for (let str of amArray) {
3041
+ if (str !== "") {
3042
+ AM.push(parseFloat(str));
3043
+ }
3044
+ }
3045
+ }
3046
+ if (modifiers.has(Modifiers.AN_AZIMUTH)) {
3047
+ let anArray: string[] = modifiers.get(Modifiers.AN_AZIMUTH).split(",");
3048
+ for (let str of anArray) {
3049
+ if (str !== "") {
3050
+ AN.push(parseFloat(str));
3051
+ }
3052
+ }
3053
+ }
3054
+
3055
+ return MultiPointHandler.hasRequiredModifiers(symbolID, drawRule, AM, AN);
3056
+ } catch (exc) {
3057
+ if (exc instanceof Error) {
3058
+ ErrorLogger.LogException("MultiPointHandler", "canRenderMultiPoint", exc);
3059
+ return "false: " + exc.message;
3060
+ } else {
3061
+ throw exc;
3062
+ }
3063
+ }
3064
+ }
3065
+
3066
+ private static hasRequiredModifiers(symbolID: string, drawRule: int, AM: Array<number>, AN: Array<number>): string {
3067
+
3068
+ let message: string = symbolID;
3069
+ try {
3070
+ if (drawRule > 700) {
3071
+ if (drawRule === DrawRules.CIRCULAR1) {
3072
+ if (AM != null && AM.length > 0) {
3073
+ return "true";
3074
+ } else {
3075
+ message += " requires a modifiers object that has 1 distance/AM value.";
3076
+ return message;
3077
+ }
3078
+ } else {
3079
+ if (drawRule === DrawRules.RECTANGULAR2) {
3080
+ if (AM != null && AM.length >= 2
3081
+ && AN != null && AN.length >= 1) {
3082
+ return "true";
3083
+ } else {
3084
+ message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value.");
3085
+ return message;
3086
+ }
3087
+ } else {
3088
+ if (drawRule === DrawRules.ARC1) {
3089
+ if (AM != null && AM.length >= 1
3090
+ && AN != null && AN.length >= 2) {
3091
+ return "true";
3092
+ } else {
3093
+ message += (" requires a modifiers object that has 2 distance/AM values and 2 azimuth/AN values per sector. The first sector can have just one AM value although it is recommended to always use 2 values for each sector.");
3094
+ return message;
3095
+ }
3096
+ } else {
3097
+ if (drawRule === DrawRules.CIRCULAR2) {
3098
+ if (AM != null && AM.length > 0) {
3099
+ return "true";
3100
+ } else {
3101
+ message += (" requires a modifiers object that has at least 1 distance/AM value");
3102
+ return message;
3103
+ }
3104
+ } else {
3105
+ if (drawRule === DrawRules.RECTANGULAR1) {
3106
+ if (AM != null && AM.length > 0) {
3107
+ return "true";
3108
+ } else {
3109
+ message += (" requires a modifiers object that has 1 distance/AM value.");
3110
+ return message;
3111
+ }
3112
+ } else {
3113
+ if (drawRule === DrawRules.ELLIPSE1) {
3114
+ if (AM != null && AM.length >= 2
3115
+ && AN != null && AN.length >= 1) {
3116
+ return "true";
3117
+ } else {
3118
+ message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value.");
3119
+ return message;
3120
+ }
3121
+ }
3122
+ else {
3123
+ if (drawRule === DrawRules.RECTANGULAR3) {
3124
+ if (AM != null && AM.length >= 1) {
3125
+ return "true";
3126
+ } else {
3127
+ message += (" requires a modifiers object that has 1 distance/AM value.");
3128
+ return message;
3129
+ }
3130
+ } else {
3131
+ //should never get here
3132
+ return "true";
3133
+ }
3134
+ }
3135
+
3136
+ }
3137
+
3138
+ }
3139
+
3140
+ }
3141
+
3142
+ }
3143
+
3144
+ }
3145
+
3146
+ } else {
3147
+ if (drawRule === DrawRules.POINT17) {
3148
+ if (AM != null && AM.length >= 2
3149
+ && AN != null && AN.length >= 1) {
3150
+ return "true";
3151
+ } else {
3152
+ message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value.");
3153
+ return message;
3154
+ }
3155
+ } else {
3156
+ if (drawRule === DrawRules.POINT18) {
3157
+ if (AM != null && AM.length >= 2
3158
+ && AN != null && AN.length >= 2) {
3159
+ return "true";
3160
+ } else {
3161
+ message += (" requires a modifiers object that has 2 distance/AM values and 2 azimuth/AN values.");
3162
+ return message;
3163
+ }
3164
+ } else {
3165
+ if (drawRule === DrawRules.CORRIDOR1) {
3166
+ if (AM != null && AM.length > 0) {
3167
+ return "true";
3168
+ } else {
3169
+ message += (" requires a modifiers object that has 1 distance/AM value.");
3170
+ return message;
3171
+ }
3172
+ } else {
3173
+ //no required parameters
3174
+ return "true";
3175
+ }
3176
+ }
3177
+
3178
+ }
3179
+
3180
+ }
3181
+
3182
+ } catch (exc) {
3183
+ if (exc instanceof Error) {
3184
+ ErrorLogger.LogException("MultiPointHandler", "hasRequiredModifiers", exc);
3185
+ return "true";
3186
+ } else {
3187
+ throw exc;
3188
+ }
3189
+ }
3190
+ }
3191
+
3192
+ /**
3193
+ *
3194
+ * @param id
3195
+ * @param name
3196
+ * @param description
3197
+ * @param basicShapeType
3198
+ * @param controlPoints
3199
+ * @param scale
3200
+ * @param bbox
3201
+ * @param symbolModifiers
3202
+ * @param symbolAttributes
3203
+ * @return
3204
+ */
3205
+ public static RenderBasicShapeAsMilStdSymbol(id: string,
3206
+ name: string,
3207
+ description: string,
3208
+ basicShapeType: int,
3209
+ controlPoints: string,
3210
+ scale: number,
3211
+ bbox: string,
3212
+ symbolModifiers: Map<string, string>,
3213
+ symbolAttributes: Map<string, string>): MilStdSymbol
3214
+ {
3215
+ let mSymbol: MilStdSymbol;
3216
+ let normalize: boolean = true;
3217
+ let controlLat: number = 0.0;
3218
+ let controlLong: number = 0.0;
3219
+ //String jsonContent = "";
3220
+
3221
+ let rect: Rectangle;
3222
+
3223
+ //for symbol & line fill
3224
+ let tgPoints: Array<POINT2>;
3225
+
3226
+ let coordinates: string[] = controlPoints.split(" ");
3227
+ let shapes: Array<ShapeInfo>;//new ArrayList<ShapeInfo>();
3228
+ let modifiers: Array<ShapeInfo>;//new ArrayList<ShapeInfo>();
3229
+ //ArrayList<Point2D> pixels = new ArrayList<Point2D>();
3230
+ let geoCoords: Array<Point2D> = new Array<Point2D>();
3231
+ let len: int = coordinates.length;
3232
+
3233
+ let ipc: IPointConversion;
3234
+
3235
+ //Deutch moved section 6-29-11
3236
+ let left: number = 0.0;
3237
+ let right: number = 0.0;
3238
+ let top: number = 0.0;
3239
+ let bottom: number = 0.0;
3240
+ let temp: Point2D;
3241
+ let ptGeoUL: Point2D;
3242
+ let width: int = 0;
3243
+ let height: int = 0;
3244
+ let leftX: int = 0;
3245
+ let topY: int = 0;
3246
+ let bottomY: int = 0;
3247
+ let rightX: int = 0;
3248
+ let j: int = 0;
3249
+ let bboxCoords: Array<Point2D>;
3250
+ if (bbox != null && bbox !== "") {
3251
+ let bounds: string[];
3252
+ if (bbox.includes(" "))//trapezoid
3253
+ {
3254
+ bboxCoords = new Array<Point2D>();
3255
+ let x: double = 0;
3256
+ let y: double = 0;
3257
+ let coords: string[] = bbox.split(" ");
3258
+ let arrCoord: string[];
3259
+ for (let coord of coords) {
3260
+ arrCoord = coord.split(",");
3261
+ x = parseFloat(arrCoord[0]);
3262
+ y = parseFloat(arrCoord[1]);
3263
+ bboxCoords.push(new Point2D(x, y));
3264
+ }
3265
+ //use the upper left corner of the MBR containing geoCoords
3266
+ //to set the converter
3267
+ ptGeoUL = MultiPointHandler.getGeoUL(bboxCoords);
3268
+ left = ptGeoUL.getX();
3269
+ top = ptGeoUL.getY();
3270
+ ipc = new PointConverter(left, top, scale);
3271
+ let ptPixels: Point2D;
3272
+ let ptGeo: Point2D;
3273
+ let n: int = bboxCoords.length;
3274
+ //for (j = 0; j < bboxCoords.length; j++)
3275
+ for (j = 0; j < n; j++) {
3276
+ ptGeo = bboxCoords[j];
3277
+ ptPixels = ipc.GeoToPixels(ptGeo);
3278
+ x = ptPixels.getX();
3279
+ y = ptPixels.getY();
3280
+ if (x < 20) {
3281
+ x = 20;
3282
+ }
3283
+ if (y < 20) {
3284
+ y = 20;
3285
+ }
3286
+ ptPixels.setLocation(x, y);
3287
+ //end section
3288
+ bboxCoords[j] = ptPixels;
3289
+ }
3290
+ } else//rectangle
3291
+ {
3292
+ bounds = bbox.split(",");
3293
+ left = parseFloat(bounds[0]);
3294
+ right = parseFloat(bounds[2]);
3295
+ top = parseFloat(bounds[3]);
3296
+ bottom = parseFloat(bounds[1]);
3297
+ scale = MultiPointHandler.getReasonableScale(bbox, scale);
3298
+ ipc = new PointConverter(left, top, scale);
3299
+ }
3300
+
3301
+ let pt2d: Point2D;
3302
+ if (bboxCoords == null) {
3303
+ pt2d = new Point2D(left, top);
3304
+ temp = ipc.GeoToPixels(pt2d);
3305
+
3306
+ leftX = temp.getX() as int;
3307
+ topY = temp.getY() as int;
3308
+
3309
+ pt2d = new Point2D(right, bottom);
3310
+ temp = ipc.GeoToPixels(pt2d);
3311
+
3312
+ bottomY = temp.getY() as int;
3313
+ rightX = temp.getX() as int;
3314
+ //diagnostic clipping does not work for large scales
3315
+ // if (scale > 10e6) {
3316
+ // //get widest point in the AOI
3317
+ // double midLat = 0;
3318
+ // if (bottom < 0 && top > 0) {
3319
+ // midLat = 0;
3320
+ // } else if (bottom < 0 && top < 0) {
3321
+ // midLat = top;
3322
+ // } else if (bottom > 0 && top > 0) {
3323
+ // midLat = bottom;
3324
+ // }
3325
+ //
3326
+ // temp = ipc.GeoToPixels(new Point2D(right, midLat));
3327
+ // rightX = (int) temp.getX();
3328
+ // }
3329
+ //end section
3330
+
3331
+ width = Math.abs(rightX - leftX) as int;
3332
+ height = Math.abs(bottomY - topY) as int;
3333
+
3334
+ if (width === 0 || height === 0) {
3335
+
3336
+ rect = null;
3337
+ }
3338
+
3339
+ else {
3340
+
3341
+ rect = new Rectangle(leftX, topY, width, height);
3342
+ }
3343
+
3344
+ }
3345
+ } else {
3346
+ rect = null;
3347
+ }
3348
+ //end section
3349
+
3350
+ for (let i: int = 0; i < len; i++) {
3351
+ let coordPair: string[] = coordinates[i].split(",");
3352
+ let latitude: number = parseFloat(coordPair[1].trim());
3353
+ let longitude: number = parseFloat(coordPair[0].trim());
3354
+ geoCoords.push(new Point2D(longitude, latitude));
3355
+ }
3356
+ if (ipc == null) {
3357
+ let ptCoordsUL: Point2D = MultiPointHandler.getGeoUL(geoCoords);
3358
+ ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale);
3359
+ }
3360
+ //if (crossesIDL(geoCoords) == true)
3361
+ // if(Math.abs(right-left)>180)
3362
+ // {
3363
+ // normalize = true;
3364
+ // ((PointConverter)ipc).set_normalize(true);
3365
+ // }
3366
+ // else {
3367
+ // normalize = false;
3368
+ // ((PointConverter)ipc).set_normalize(false);
3369
+ // }
3370
+
3371
+ //seems to work ok at world view
3372
+ // if (normalize) {
3373
+ // NormalizeGECoordsToGEExtents(0, 360, geoCoords);
3374
+ // }
3375
+
3376
+ //M. Deutch 10-3-11
3377
+ //must shift the rect pixels to synch with the new ipc
3378
+ //the old ipc was in synch with the bbox, so rect x,y was always 0,0
3379
+ //the new ipc synchs with the upper left of the geocoords so the boox is shifted
3380
+ //and therefore the clipping rectangle must shift by the delta x,y between
3381
+ //the upper left corner of the original bbox and the upper left corner of the geocoords
3382
+ let geoCoords2: Array<Point2D> = new Array<Point2D>();
3383
+ geoCoords2.push(new Point2D(left, top));
3384
+ geoCoords2.push(new Point2D(right, bottom));
3385
+
3386
+ // if (normalize) {
3387
+ // NormalizeGECoordsToGEExtents(0, 360, geoCoords2);
3388
+ // }
3389
+
3390
+ //disable clipping
3391
+ if (MultiPointHandler.crossesIDL(geoCoords) === false) {
3392
+ rect = null;
3393
+ bboxCoords = null;
3394
+ }
3395
+
3396
+ let symbolCode = "";
3397
+ try {
3398
+ let fillColor: string;
3399
+ mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null);
3400
+
3401
+ // mSymbol.setUseDashArray(true);
3402
+
3403
+ if (symbolModifiers != null || symbolAttributes != null) {
3404
+ MultiPointHandler.populateModifiers(symbolModifiers, symbolAttributes, mSymbol);
3405
+ } else {
3406
+ mSymbol.setFillColor(null);
3407
+ }
3408
+
3409
+ if (mSymbol.getFillColor() != null) {
3410
+ let fc: Color = mSymbol.getFillColor();
3411
+ fillColor = RendererUtilities.colorToHexString(fc, false);
3412
+
3413
+ }
3414
+
3415
+ let tg: TGLight = clsRenderer.createTGLightFromMilStdSymbolBasicShape(mSymbol, ipc, basicShapeType);
3416
+ let shapeInfos: Array<ShapeInfo> = [];
3417
+ let modifierShapeInfos: Array<ShapeInfo> = [];
3418
+ let clipArea: Point2D[] | Rectangle | Rectangle2D;
3419
+ if (bboxCoords == null) {
3420
+ clipArea = rect;
3421
+ } else {
3422
+ clipArea = bboxCoords;
3423
+ }
3424
+ if (clsRenderer.intersectsClipArea(tg, ipc, clipArea)) {
3425
+ clsRenderer.render_GE(tg, shapeInfos, modifierShapeInfos, ipc, clipArea);
3426
+ }
3427
+ mSymbol.setSymbolShapes(shapeInfos);
3428
+ mSymbol.setModifierShapes(modifierShapeInfos);
3429
+ mSymbol.set_WasClipped(tg.get_WasClipped());
3430
+ shapes = mSymbol.getSymbolShapes();
3431
+ modifiers = mSymbol.getModifierShapes();
3432
+
3433
+ //convert points////////////////////////////////////////////////////
3434
+ let polylines: Array<Array<Point2D>>;
3435
+ let newPolylines: Array<Array<Point2D>>;
3436
+ let newLine: Array<Point2D>;
3437
+ for (let shape of shapes) {
3438
+ polylines = shape.getPolylines();
3439
+ //console.log("pixel polylines: " + polylines.toString());
3440
+ newPolylines = MultiPointHandler.ConvertPolylinePixelsToCoords(polylines, ipc, normalize);
3441
+ shape.setPolylines(newPolylines);
3442
+ }
3443
+
3444
+ for (let label of modifiers) {
3445
+ let pixelCoord: Point2D = label.getModifierPosition();
3446
+ if (pixelCoord == null) {
3447
+ pixelCoord = label.getGlyphPosition();
3448
+ }
3449
+ let geoCoord: Point2D = ipc.PixelsToGeo(pixelCoord);
3450
+
3451
+ if (normalize) {
3452
+ geoCoord = MultiPointHandler.NormalizeCoordToGECoord(geoCoord);
3453
+ }
3454
+
3455
+ let latitude: double = geoCoord.getY();
3456
+ let longitude: double = geoCoord.getX();
3457
+ label.setModifierPosition(new Point2D(longitude, latitude));
3458
+
3459
+ }
3460
+
3461
+ ////////////////////////////////////////////////////////////////////
3462
+ mSymbol.setModifierShapes(modifiers);
3463
+ mSymbol.setSymbolShapes(shapes);
3464
+
3465
+ } catch (exc) {
3466
+ if (exc instanceof Error) {
3467
+ console.log(exc.message);
3468
+ console.log("Symbol Code: " + symbolCode);
3469
+ console.log(exc.stack);
3470
+ } else {
3471
+ throw exc;
3472
+ }
3473
+ }
3474
+
3475
+ /*
3476
+ let debug: boolean = false;
3477
+ if (debug === true) {
3478
+ console.log("Symbol Code: " + symbolCode);
3479
+ console.log("Scale: " + scale);
3480
+ console.log("BBOX: " + bbox);
3481
+ if (controlPoints != null) {
3482
+ console.log("Geo Points: " + controlPoints);
3483
+ }
3484
+ if (tgl != null && tgl.get_Pixels() != null)//pixels != null
3485
+ {
3486
+ //console.log("Pixel: " + pixels.toString());
3487
+ console.log("Pixel: " + tgl.get_Pixels().toString());
3488
+ }
3489
+ if (bbox != null) {
3490
+ console.log("geo bounds: " + bbox);
3491
+ }
3492
+ if (rect != null) {
3493
+ console.log("pixel bounds: " + rect.toString());
3494
+ }
3495
+ }
3496
+ */
3497
+
3498
+ return mSymbol;
3499
+
3500
+ }
3501
+
3502
+ /**
3503
+ *
3504
+ * @param id
3505
+ * @param name
3506
+ * @param description
3507
+ * @param basicShapeType
3508
+ * @param controlPoints
3509
+ * @param scale
3510
+ * @param bbox
3511
+ * @param symbolModifiers {@link Map}, keyed using constants from
3512
+ * Modifiers. Pass in comma delimited String for modifiers with multiple
3513
+ * values like AM, AN &amp; X
3514
+ * @param symbolAttributes {@link Map}, keyed using constants from
3515
+ * MilStdAttributes. pass in double[] for AM, AN and X; Strings for the
3516
+ * rest.
3517
+ * @param format
3518
+ * @return
3519
+ */
3520
+ public static RenderBasicShape(id: string,
3521
+ name: string,
3522
+ description: string,
3523
+ basicShapeType: int,
3524
+ controlPoints: string,
3525
+ scale: number,
3526
+ bbox: string,
3527
+ symbolModifiers: Map<string, string>,
3528
+ symbolAttributes: Map<string, string>,
3529
+ format: int): string
3530
+ {
3531
+ let normalize: boolean = true;
3532
+ //Double controlLat = 0.0;
3533
+ //Double controlLong = 0.0;
3534
+ //Double metPerPix = GeoPixelConversion.metersPerPixel(scale);
3535
+ //String bbox2=getBoundingRectangle(controlPoints,bbox);
3536
+ let jsonOutput: string = "";
3537
+ let jsonContent: string = "";
3538
+
3539
+ let rect: Rectangle;
3540
+ let coordinates: string[] = controlPoints.split(" ");
3541
+ let shapes: Array<ShapeInfo> = new Array<ShapeInfo>();
3542
+ let modifiers: Array<ShapeInfo> = new Array<ShapeInfo>();
3543
+ //ArrayList<Point2D> pixels = new ArrayList<Point2D>();
3544
+ let geoCoords: Array<Point2D> = new Array<Point2D>();
3545
+ let len: int = coordinates.length;
3546
+ //diagnostic create geoCoords here
3547
+ let coordsUL: Point2D = null;
3548
+ const symbolCode = "";
3549
+
3550
+ for (let i: int = 0; i < len; i++) {
3551
+ let coordPair: string[] = coordinates[i].split(",");
3552
+ let latitude: number = parseFloat(coordPair[1].trim());
3553
+ let longitude: number = parseFloat(coordPair[0].trim());
3554
+ geoCoords.push(new Point2D(longitude, latitude));
3555
+ }
3556
+ let tgPoints: Array<POINT2>;
3557
+ let ipc: IPointConversion;
3558
+
3559
+ //Deutch moved section 6-29-11
3560
+ let left: number = 0.0;
3561
+ let right: number = 0.0;
3562
+ let top: number = 0.0;
3563
+ let bottom: number = 0.0;
3564
+ let temp: Point2D;
3565
+ let ptGeoUL: Point2D;
3566
+ let width: int = 0;
3567
+ let height: int = 0;
3568
+ let leftX: int = 0;
3569
+ let topY: int = 0;
3570
+ let bottomY: int = 0;
3571
+ let rightX: int = 0;
3572
+ let j: int = 0;
3573
+ let bboxCoords: Array<Point2D>;
3574
+ if (bbox != null && bbox !== "") {
3575
+ let bounds: string[];
3576
+ if (bbox.includes(" "))//trapezoid
3577
+ {
3578
+ bboxCoords = new Array<Point2D>();
3579
+ let x: double = 0;
3580
+ let y: double = 0;
3581
+ let coords: string[] = bbox.split(" ");
3582
+ let arrCoord: string[];
3583
+ for (let coord of coords) {
3584
+ arrCoord = coord.split(",");
3585
+ x = parseFloat(arrCoord[0]);
3586
+ y = parseFloat(arrCoord[1]);
3587
+ bboxCoords.push(new Point2D(x, y));
3588
+ }
3589
+ //use the upper left corner of the MBR containing geoCoords
3590
+ //to set the converter
3591
+ ptGeoUL = MultiPointHandler.getGeoUL(bboxCoords);
3592
+ left = ptGeoUL.getX();
3593
+ top = ptGeoUL.getY();
3594
+ let bbox2: string = MultiPointHandler.getBboxFromCoords(bboxCoords);
3595
+ scale = MultiPointHandler.getReasonableScale(bbox2, scale);
3596
+ ipc = new PointConverter(left, top, scale);
3597
+ let ptPixels: Point2D;
3598
+ let ptGeo: Point2D;
3599
+ let n: int = bboxCoords.length;
3600
+ //for (j = 0; j < bboxCoords.length; j++)
3601
+ for (j = 0; j < n; j++) {
3602
+ ptGeo = bboxCoords[j];
3603
+ ptPixels = ipc.GeoToPixels(ptGeo);
3604
+ x = ptPixels.getX();
3605
+ y = ptPixels.getY();
3606
+ if (x < 20) {
3607
+ x = 20;
3608
+ }
3609
+ if (y < 20) {
3610
+ y = 20;
3611
+ }
3612
+ ptPixels.setLocation(x, y);
3613
+ //end section
3614
+ bboxCoords[j] = ptPixels;
3615
+ }
3616
+ } else//rectangle
3617
+ {
3618
+ bounds = bbox.split(",");
3619
+ left = parseFloat(bounds[0]);
3620
+ right = parseFloat(bounds[2]);
3621
+ top = parseFloat(bounds[3]);
3622
+ bottom = parseFloat(bounds[1]);
3623
+ scale = MultiPointHandler.getReasonableScale(bbox, scale);
3624
+ ipc = new PointConverter(left, top, scale);
3625
+ }
3626
+
3627
+ let pt2d: Point2D;
3628
+ if (bboxCoords == null) {
3629
+ pt2d = new Point2D(left, top);
3630
+ temp = ipc.GeoToPixels(pt2d);
3631
+
3632
+ leftX = temp.getX() as int;
3633
+ topY = temp.getY() as int;
3634
+
3635
+ pt2d = new Point2D(right, bottom);
3636
+ temp = ipc.GeoToPixels(pt2d);
3637
+
3638
+ bottomY = temp.getY() as int;
3639
+ rightX = temp.getX() as int;
3640
+
3641
+ width = Math.abs(rightX - leftX) as int;
3642
+ height = Math.abs(bottomY - topY) as int;
3643
+
3644
+ rect = new Rectangle(leftX, topY, width, height);
3645
+ }
3646
+ } else {
3647
+ rect = null;
3648
+ }
3649
+
3650
+ if (ipc == null) {
3651
+ let ptCoordsUL: Point2D = MultiPointHandler.getGeoUL(geoCoords);
3652
+ ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale);
3653
+ }
3654
+
3655
+ let geoCoords2: Array<Point2D> = new Array<Point2D>();
3656
+ geoCoords2.push(new Point2D(left, top));
3657
+ geoCoords2.push(new Point2D(right, bottom));
3658
+
3659
+ // if (normalize) {
3660
+ // NormalizeGECoordsToGEExtents(0, 360, geoCoords2);
3661
+ // }
3662
+
3663
+ try {
3664
+
3665
+ //String fillColor = null;
3666
+ let mSymbol: MilStdSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null);
3667
+
3668
+ if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG) {
3669
+ // Use dash array and hatch pattern fill for SVG output
3670
+ symbolAttributes.set(MilStdAttributes.UseDashArray, 'true')
3671
+ symbolAttributes.set(MilStdAttributes.UsePatternFill, "true")
3672
+ }
3673
+
3674
+ if (symbolModifiers != null || symbolAttributes != null) {
3675
+ MultiPointHandler.populateModifiers(symbolModifiers, symbolAttributes, mSymbol);
3676
+ } else {
3677
+ mSymbol.setFillColor(null);
3678
+ }
3679
+
3680
+ let tg: TGLight = clsRenderer.createTGLightFromMilStdSymbolBasicShape(mSymbol, ipc, basicShapeType);
3681
+ let shapeInfos: Array<ShapeInfo> = [];
3682
+ let modifierShapeInfos: Array<ShapeInfo> = [];
3683
+ let clipArea: Point2D[] | Rectangle | Rectangle2D;
3684
+ if (bboxCoords == null) {
3685
+ clipArea = rect;
3686
+ } else {
3687
+ clipArea = bboxCoords;
3688
+ }
3689
+ if (clsRenderer.intersectsClipArea(tg, ipc, clipArea)) {
3690
+ clsRenderer.render_GE(tg, shapeInfos, modifierShapeInfos, ipc, clipArea);
3691
+ }
3692
+ mSymbol.setSymbolShapes(shapeInfos);
3693
+ mSymbol.setModifierShapes(modifierShapeInfos);
3694
+ mSymbol.set_WasClipped(tg.get_WasClipped());
3695
+ shapes = mSymbol.getSymbolShapes();
3696
+ modifiers = mSymbol.getModifierShapes();
3697
+
3698
+ if (format === WebRenderer.OUTPUT_FORMAT_JSON) {
3699
+ jsonOutput += ("{\"type\":\"symbol\",");
3700
+ jsonContent = MultiPointHandler.JSONize(shapes, modifiers, ipc, true, normalize);
3701
+ jsonOutput += (jsonContent);
3702
+ jsonOutput += ("}");
3703
+ } else if (format === WebRenderer.OUTPUT_FORMAT_KML) {
3704
+ var textColor = mSymbol.getTextColor();
3705
+ if(textColor==null)
3706
+ textColor=mSymbol.getLineColor();
3707
+
3708
+ jsonContent = MultiPointHandler.KMLize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor);
3709
+ jsonOutput += jsonContent;
3710
+ } else if (format === WebRenderer.OUTPUT_FORMAT_GEOJSON) {
3711
+ /*
3712
+ jsonOutput += ("{\"type\":\"FeatureCollection\",\"features\":");
3713
+ jsonContent = GeoJSONize(shapes, modifiers, ipc, normalize, mSymbol.getTextColor(), mSymbol.getTextBackgroundColor());
3714
+ jsonOutput += (jsonContent);
3715
+ jsonOutput += (",\"properties\":{\"id\":\"");
3716
+ jsonOutput += (id);
3717
+ jsonOutput += ("\",\"name\":\"");
3718
+ jsonOutput += (name);
3719
+ jsonOutput += ("\",\"description\":\"");
3720
+ jsonOutput += (description);
3721
+ jsonOutput += ("\",\"symbolID\":\"");
3722
+ jsonOutput += (symbolCode);
3723
+ jsonOutput += ("\",\"wasClipped\":\"");
3724
+ jsonOutput += (mSymbol.get_WasClipped()).toString();
3725
+ jsonOutput += ("\"}}"); */
3726
+
3727
+ jsonOutput += ("{\"type\":\"FeatureCollection\",\"features\":");
3728
+ jsonContent = MultiPointHandler.GeoJSONize(shapes, modifiers, ipc, normalize, mSymbol.getTextColor(), mSymbol.getTextBackgroundColor());
3729
+ jsonOutput += (jsonContent);
3730
+
3731
+ //moving meta data properties to the last feature with no coords as feature collection doesn't allow properties
3732
+ jsonOutput = jsonOutput.slice(0, -1);
3733
+ jsonOutput += (",{\"type\": \"Feature\",\"geometry\": { \"type\": \"Polygon\",\"coordinates\": [ ]}");
3734
+
3735
+ jsonOutput += (",\"properties\":{\"id\":\"");
3736
+ jsonOutput += (id);
3737
+ jsonOutput += ("\",\"name\":\"");
3738
+ jsonOutput += (name);
3739
+ jsonOutput += ("\",\"description\":\"");
3740
+ jsonOutput += (description);
3741
+ jsonOutput += ("\",\"symbolID\":\"");
3742
+ jsonOutput += (symbolCode);
3743
+ jsonOutput += ("\",\"wasClipped\":\"");
3744
+ jsonOutput += (mSymbol.get_WasClipped()).toString();
3745
+ //jsonOutput += ("\"}}");
3746
+
3747
+ jsonOutput += ("\"}}]}");
3748
+ } else if (format === WebRenderer.OUTPUT_FORMAT_GEOSVG) {
3749
+ let textColor = mSymbol.getTextColor() ? mSymbol.getTextColor().toHexString(false) : "";
3750
+ let backgroundColor = mSymbol.getTextBackgroundColor() ? mSymbol.getTextBackgroundColor().toHexString(false) : "";
3751
+ //returns an svg with a geoTL and geoBR value to use to place the canvas on the map
3752
+ jsonOutput = MultiPointHandlerSVG.GeoSVGize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor, backgroundColor, mSymbol.get_WasClipped());
3753
+ }
3754
+ } catch (exc) {
3755
+ if (exc instanceof Error) {
3756
+ let st: string = JavaRendererUtilities.getStackTrace(exc);
3757
+ jsonOutput = "";
3758
+ jsonOutput += ("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + ": " + "- ");
3759
+ jsonOutput += (exc.message + " - ");
3760
+ jsonOutput += (st);
3761
+ jsonOutput += ("\"}");
3762
+
3763
+ ErrorLogger.LogException("MultiPointHandler", "RenderBasicSymbol", exc);
3764
+ } else {
3765
+ throw exc;
3766
+ }
3767
+ }
3768
+
3769
+ /*
3770
+ let debug: boolean = false;
3771
+ if (debug === true) {
3772
+ console.log("Symbol Code: " + symbolCode);
3773
+ console.log("Scale: " + scale);
3774
+ console.log("BBOX: " + bbox);
3775
+ if (controlPoints != null) {
3776
+ console.log("Geo Points: " + controlPoints);
3777
+ }
3778
+ if (tgl != null && tgl.get_Pixels() != null)//pixels != null
3779
+ {
3780
+ console.log("Pixel: " + tgl.get_Pixels().toString());
3781
+ }
3782
+ if (bbox != null) {
3783
+ console.log("geo bounds: " + bbox);
3784
+ }
3785
+ if (rect != null) {
3786
+ console.log("pixel bounds: " + rect.toString());
3787
+ }
3788
+ if (jsonOutput != null) {
3789
+ console.log(jsonOutput.toString());
3790
+ }
3791
+ }
3792
+ */
3793
+
3794
+ ErrorLogger.LogMessage("MultiPointHandler", "RenderBasicShape()", "exit RenderBasicShape", LogLevel.FINER);
3795
+ return jsonOutput.toString();
3796
+
3797
+ }
3798
+ }