001/* 002 * A class to serve JavaRendererServer 003 */ 004package armyc2.c5isr.RenderMultipoints; 005 006import android.content.Context; 007 008import java.util.ArrayList; 009import java.util.Collections; 010import java.util.HashMap; 011import java.util.Map; 012 013import armyc2.c5isr.JavaLineArray.CELineArray; 014import armyc2.c5isr.JavaLineArray.DISMSupport; 015import armyc2.c5isr.JavaLineArray.POINT2; 016import armyc2.c5isr.JavaLineArray.Shape2; 017import armyc2.c5isr.JavaLineArray.TacticalLines; 018import armyc2.c5isr.JavaLineArray.lineutility; 019import armyc2.c5isr.JavaTacticalRenderer.Modifier2; 020import armyc2.c5isr.JavaTacticalRenderer.TGLight; 021import armyc2.c5isr.JavaTacticalRenderer.mdlGeodesic; 022import armyc2.c5isr.graphics2d.BasicStroke; 023import armyc2.c5isr.graphics2d.BufferedImage; 024import armyc2.c5isr.graphics2d.Font; 025import armyc2.c5isr.graphics2d.Graphics2D; 026import armyc2.c5isr.graphics2d.Point2D; 027import armyc2.c5isr.graphics2d.Rectangle; 028import armyc2.c5isr.graphics2d.Rectangle2D; 029import armyc2.c5isr.renderer.utilities.Color; 030import armyc2.c5isr.renderer.utilities.DistanceUnit; 031import armyc2.c5isr.renderer.utilities.DrawRules; 032import armyc2.c5isr.renderer.utilities.ErrorLogger; 033import armyc2.c5isr.renderer.utilities.IPointConversion; 034import armyc2.c5isr.renderer.utilities.MSInfo; 035import armyc2.c5isr.renderer.utilities.MSLookup; 036import armyc2.c5isr.renderer.utilities.MilStdSymbol; 037import armyc2.c5isr.renderer.utilities.Modifiers; 038import armyc2.c5isr.renderer.utilities.RendererException; 039import armyc2.c5isr.renderer.utilities.RendererSettings; 040import armyc2.c5isr.renderer.utilities.ShapeInfo; 041import armyc2.c5isr.renderer.utilities.SymbolID; 042import armyc2.c5isr.renderer.utilities.SymbolUtilities; 043 044/** 045 * Rendering class 046 * 047* 048 */ 049public final class clsRenderer { 050 051 private static final String _className = "clsRenderer"; 052 053 /** 054 * Set tg geo points from the client points 055 * 056 * @param milStd 057 * @param tg 058 */ 059 private static void setClientCoords(MilStdSymbol milStd, 060 TGLight tg) { 061 try { 062 ArrayList<POINT2> latLongs = new ArrayList(); 063 int j = 0; 064 ArrayList<Point2D> coords = milStd.getCoordinates(); 065 Point2D pt2d = null; 066 POINT2 pt2 = null; 067 int n = coords.size(); 068 //for (j = 0; j < coords.size(); j++) 069 for (j = 0; j < n; j++) { 070 pt2d = coords.get(j); 071 pt2 = clsUtility.Point2DToPOINT2(pt2d); 072 latLongs.add(pt2); 073 } 074 tg.set_LatLongs(latLongs); 075 } catch (Exception exc) { 076 ErrorLogger.LogException("clsRenderer", "setClientCoords", 077 new RendererException("Failed to set geo points or pixels for " + milStd.getSymbolID(), exc)); 078 } 079 } 080 081 private static ArrayList<Point2D> getClientCoords(TGLight tg) { 082 ArrayList<Point2D> coords = null; 083 try { 084 int j = 0; 085 Point2D pt2d = null; 086 POINT2 pt2 = null; 087 coords = new ArrayList(); 088 int n = tg.LatLongs.size(); 089 //for (j = 0; j < tg.LatLongs.size(); j++) 090 for (j = 0; j < n; j++) { 091 pt2 = tg.LatLongs.get(j); 092 pt2d = new Point2D.Double(pt2.x, pt2.y); 093 coords.add(pt2d); 094 } 095 } catch (Exception exc) { 096 ErrorLogger.LogException("clsRenderer", "getClientCoords", 097 new RendererException("Failed to set geo points or pixels for " + tg.get_SymbolId(), exc)); 098 } 099 return coords; 100 } 101 102 /** 103 * Build a tactical graphic object from the client MilStdSymbol 104 * 105 * @param milStd MilstdSymbol object 106 * @param converter geographic to pixels converter 107 * @param lineType {@link armyc2.c5isr.JavaLineArray.BasicShapes} 108 * @return tactical graphic 109 */ 110 public static TGLight createTGLightFromMilStdSymbolBasicShape(MilStdSymbol milStd, 111 IPointConversion converter, 112 int lineType) { 113 TGLight tg = new TGLight(); 114 try { 115 boolean useLineInterpolation = milStd.getUseLineInterpolation(); 116 tg.set_UseLineInterpolation(useLineInterpolation); 117 tg.set_LineType(lineType); 118 String status = tg.get_Status(); 119 tg.set_VisibleModifiers(true); 120 //set tg latlongs and pixels 121 setClientCoords(milStd, tg); 122 //build tg.Pixels 123 tg.Pixels = clsUtility.LatLongToPixels(tg.LatLongs, converter); 124 //tg.set_Font(new Font("Arial", Font.PLAIN, 12)); 125 RendererSettings r = RendererSettings.getInstance(); 126 int type = r.getMPLabelFontType(); 127 String name = r.getMPLabelFontName(); 128 int sz = r.getMPLabelFontSize(); 129 Font font = new Font(name, type, sz); 130 tg.set_Font(font); 131 tg.set_FillColor(milStd.getFillColor()); 132 tg.set_LineColor(milStd.getLineColor()); 133 tg.set_LineThickness(milStd.getLineWidth()); 134 tg.set_TexturePaint(milStd.getFillStyle()); 135 tg.set_Fillstyle(milStd.getPatternFillType()); 136 tg.set_patternScale(milStd.getPatternScale()); 137 138 tg.set_IconSize(milStd.getUnitSize()); 139 tg.set_KeepUnitRatio(milStd.getKeepUnitRatio()); 140 141 tg.set_FontBackColor(Color.WHITE); 142 tg.set_TextColor(milStd.getTextColor()); 143 if (milStd.getModifier(Modifiers.W_DTG_1) != null) { 144 tg.set_DTG(milStd.getModifier(Modifiers.W_DTG_1)); 145 } 146 if (milStd.getModifier(Modifiers.W1_DTG_2) != null) { 147 tg.set_DTG1(milStd.getModifier(Modifiers.W1_DTG_2)); 148 } 149 if (milStd.getModifier(Modifiers.H_ADDITIONAL_INFO_1) != null) { 150 tg.set_H(milStd.getModifier(Modifiers.H_ADDITIONAL_INFO_1)); 151 } 152 if (milStd.getModifier(Modifiers.H1_ADDITIONAL_INFO_2) != null) { 153 tg.set_H1(milStd.getModifier(Modifiers.H1_ADDITIONAL_INFO_2)); 154 } 155 if (milStd.getModifier(Modifiers.H2_ADDITIONAL_INFO_3) != null) { 156 tg.set_H2(milStd.getModifier(Modifiers.H2_ADDITIONAL_INFO_3)); 157 } 158 if (milStd.getModifier(Modifiers.T_UNIQUE_DESIGNATION_1) != null) { 159 tg.set_Name(milStd.getModifier(Modifiers.T_UNIQUE_DESIGNATION_1)); 160 } 161 if (milStd.getModifier(Modifiers.T1_UNIQUE_DESIGNATION_2) != null) { 162 tg.set_T1(milStd.getModifier(Modifiers.T1_UNIQUE_DESIGNATION_2)); 163 } 164 if (milStd.getModifier(Modifiers.V_EQUIP_TYPE) != null) { 165 tg.set_V(milStd.getModifier(Modifiers.V_EQUIP_TYPE)); 166 } 167 if (milStd.getModifier(Modifiers.AS_COUNTRY) != null) { 168 tg.set_AS(milStd.getModifier(Modifiers.AS_COUNTRY)); 169 } 170 if (milStd.getModifier(Modifiers.AP_TARGET_NUMBER) != null) { 171 tg.set_AP(milStd.getModifier(Modifiers.AP_TARGET_NUMBER)); 172 } 173 if (milStd.getModifier(Modifiers.Y_LOCATION) != null) { 174 tg.set_Location(milStd.getModifier(Modifiers.Y_LOCATION)); 175 } 176 if (milStd.getModifier(Modifiers.N_HOSTILE) != null) { 177 tg.set_N(milStd.getModifier(Modifiers.N_HOSTILE)); 178 } 179 tg.set_UseDashArray(milStd.getUseDashArray()); 180 tg.set_UseHatchFill(milStd.getUseFillPattern()); 181 //tg.set_UsePatternFill(milStd.getUseFillPattern()); 182 tg.set_HideOptionalLabels(milStd.getHideOptionalLabels()); 183 boolean isClosedArea = armyc2.c5isr.JavaTacticalRenderer.clsUtility.isClosedPolygon(lineType); 184 185 if (isClosedArea) { 186 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(tg.Pixels); 187 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(tg.LatLongs); 188 } 189 190 String strXAlt = ""; 191 //construct the H1 and H2 modifiers for sector from the mss AM, AN, and X arraylists 192 if (lineType == TacticalLines.BS_ELLIPSE) { 193 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 194 ArrayList<Double> AN = milStd.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH); 195 //ensure array length 3 196 double r2=0; 197 double b=0; 198 if(AM.size()==1) 199 { 200 r2=AM.get(0); 201 AM.add(r2); 202 AM.add(0d); 203 } 204 else if(AM.size()==2) 205 { 206 r2=AM.get(0); 207 b=AM.get(1); 208 AM.set(1, r2); 209 AM.add(b); 210 } 211 if (AN == null) { 212 AN = new ArrayList<Double>(); 213 } 214 if (AN.size() < 1) { 215 AN.add(new Double(0)); 216 } 217 if (AM != null && AM.size() >= 2 && AN != null && AN.size() >= 1) { 218 POINT2 ptAzimuth = new POINT2(0, 0); 219 ptAzimuth.x = AN.get(0); 220 POINT2 ptCenter = tg.Pixels.get(0); 221 POINT2 pt0 = mdlGeodesic.geodesic_coordinate(tg.LatLongs.get(0), AM.get(0), 90);//semi-major axis 222 POINT2 pt1 = mdlGeodesic.geodesic_coordinate(tg.LatLongs.get(0), AM.get(1), 0);//semi-minor axis 223 Point2D pt02d = new Point2D.Double(pt0.x, pt0.y); 224 Point2D pt12d = new Point2D.Double(pt1.x, pt1.y); 225 pt02d = converter.GeoToPixels(pt02d); 226 pt12d = converter.GeoToPixels(pt12d); 227 pt0 = new POINT2(pt02d.getX(), pt02d.getY()); 228 pt1 = new POINT2(pt12d.getX(), pt12d.getY()); 229 tg.Pixels = new ArrayList<POINT2>(); 230 tg.Pixels.add(ptCenter); 231 tg.Pixels.add(pt0); 232 tg.Pixels.add(pt1); 233 tg.Pixels.add(ptAzimuth); 234 } 235 if(AM != null && AM.size()>2) 236 { 237 //use AM[2] for the buffer, so PBS_CIRCLE requires AM size 3 like PBS_ELLIPSE to use a buffer 238 double dist=AM.get(2); 239 POINT2 pt0=mdlGeodesic.geodesic_coordinate(tg.LatLongs.get(0), dist, 45); //azimuth 45 is arbitrary 240 Point2D pt02d = new Point2D.Double(tg.LatLongs.get(0).x,tg.LatLongs.get(0).y); 241 Point2D pt12d = new Point2D.Double(pt0.x, pt0.y); 242 pt02d = converter.GeoToPixels(pt02d); 243 pt12d = converter.GeoToPixels(pt12d); 244 pt0=new POINT2(pt02d.getX(),pt02d.getY()); 245 POINT2 pt1=new POINT2(pt12d.getX(),pt12d.getY()); 246 dist=lineutility.CalcDistanceDouble(pt0, pt1); 247 //arraysupport will use line style to create the buffer shape 248 tg.Pixels.get(0).style=(int)dist; 249 } 250 } 251 int j = 0; 252 if (lineType == TacticalLines.BBS_RECTANGLE || lineType == TacticalLines.BS_BBOX) { 253 double minLat = tg.LatLongs.get(0).y; 254 double maxLat = tg.LatLongs.get(0).y; 255 double minLong = tg.LatLongs.get(0).x; 256 double maxLong = tg.LatLongs.get(0).x; 257 for (j = 1; j < tg.LatLongs.size(); j++) { 258 if (tg.LatLongs.get(j).x < minLong) { 259 minLong = tg.LatLongs.get(j).x; 260 } 261 if (tg.LatLongs.get(j).x > maxLong) { 262 maxLong = tg.LatLongs.get(j).x; 263 } 264 if (tg.LatLongs.get(j).y < minLat) { 265 minLat = tg.LatLongs.get(j).y; 266 } 267 if (tg.LatLongs.get(j).y > maxLat) { 268 maxLat = tg.LatLongs.get(j).y; 269 } 270 } 271 tg.LatLongs = new ArrayList(); 272 tg.LatLongs.add(new POINT2(minLong, maxLat)); 273 tg.LatLongs.add(new POINT2(maxLong, maxLat)); 274 tg.LatLongs.add(new POINT2(maxLong, minLat)); 275 tg.LatLongs.add(new POINT2(minLong, minLat)); 276 if (lineType == TacticalLines.BS_BBOX) { 277 tg.LatLongs.add(new POINT2(minLong, maxLat)); 278 } 279 tg.Pixels = clsUtility.LatLongToPixels(tg.LatLongs, converter); 280 } 281 //these have a buffer value in meters which we'll stuff tg.H2 282 //and use the style member of tg.Pixels to stuff the buffer width in pixels 283 switch (lineType) { 284 case TacticalLines.BBS_AREA: 285 case TacticalLines.BBS_LINE: 286 case TacticalLines.BBS_RECTANGLE: 287 String H2 = null; 288 double dist = 0; 289 POINT2 pt0; 290 POINT2 pt1;//45 is arbitrary 291 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 292 if (AM != null && AM.size() > 0) { 293 H2 = AM.get(0).toString(); 294 tg.set_H2(H2); 295 } 296 if (H2 != null && !H2.isEmpty()) { 297 for (j = 0; j < tg.LatLongs.size(); j++) { 298 if (tg.LatLongs.size() > j) { 299 if (!Double.isNaN(Double.parseDouble(H2))) { 300 if (j == 0) { 301 dist = Double.parseDouble(H2); 302 pt0 = new POINT2(tg.LatLongs.get(0)); 303 pt1 = mdlGeodesic.geodesic_coordinate(pt0, dist, 45);//45 is arbitrary 304 Point2D pt02d = new Point2D.Double(pt0.x, pt0.y); 305 Point2D pt12d = new Point2D.Double(pt1.x, pt1.y); 306 pt02d = converter.GeoToPixels(pt02d); 307 pt12d = converter.GeoToPixels(pt12d); 308 pt0.x = pt02d.getX(); 309 pt0.y = pt02d.getY(); 310 pt1.x = pt12d.getX(); 311 pt1.y = pt12d.getY(); 312 dist = lineutility.CalcDistanceDouble(pt0, pt1); 313 } 314 tg.Pixels.get(j).style = Math.round((float) dist); 315 } else { 316 tg.Pixels.get(j).style = 0; 317 } 318 } 319 } 320 } 321 break; 322 default: 323 break; 324 } 325 if (lineType == TacticalLines.PBS_ELLIPSE) //geo ellipse 326 { 327 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 328 ArrayList<Double> AN = milStd.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH); 329 if (AM != null && AM.size() > 1) { 330 String strAM = AM.get(0).toString(); // major axis 331 tg.set_AM(strAM); 332 String strAM1 = AM.get(1).toString(); // minor axis 333 tg.set_AM1(strAM1); 334 } 335 if (AN != null && AN.size() > 0) { 336 String strAN = AN.get(0).toString(); // rotation 337 tg.set_AN(strAN); 338 } 339 } 340 switch (lineType) { 341 case TacticalLines.BBS_AREA: 342 case TacticalLines.BBS_LINE: 343 case TacticalLines.BBS_POINT: 344 case TacticalLines.BBS_RECTANGLE: 345 if (tg.get_FillColor() == null) { 346 tg.set_FillColor(Color.LIGHT_GRAY); 347 } 348 break; 349 default: 350 break; 351 } 352 switch (lineType) { 353 case TacticalLines.PBS_CIRCLE: 354 case TacticalLines.BBS_POINT: 355 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 356 if (AM != null && AM.size() > 0) { 357 String strAM = Double.toString(AM.get(0)); 358 //set width for rectangles or radius for circles 359 tg.set_AM(strAM); 360 } else if (lineType == TacticalLines.BBS_POINT && tg.LatLongs.size() > 1) { 361 double dist = mdlGeodesic.geodesic_distance(tg.LatLongs.get(0), tg.LatLongs.get(1), null, null); 362 String strT1 = Double.toString(dist); 363 tg.set_T1(strT1); 364 } 365 break; 366 default: 367 break; 368 } 369 if (lineType == TacticalLines.PBS_RECTANGLE || lineType == TacticalLines.PBS_SQUARE) { 370 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 371 ArrayList<Double> AN = milStd.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH); 372 if (lineType == TacticalLines.PBS_SQUARE) //for square 373 { 374 double r2=AM.get(0); 375 double b=0; 376 if(AM.size()==1) 377 { 378 AM.add(r2); 379 AM.add(b); 380 } 381 else if(AM.size()==2) 382 { 383 b=AM.get(1); 384 AM.set(1,r2); 385 AM.add(b); 386 } 387 else if(AM.size()>2) 388 AM.set(1, r2); 389 } 390 //if all these conditions are not met we do not want to set any tg modifiers 391 if (lineType == TacticalLines.PBS_SQUARE) //square 392 { 393 double am0 = AM.get(0); 394 if (AM.size() == 1) { 395 AM.add(am0); 396 } else if (AM.size() >= 2) { 397 AM.set(1, am0); 398 } 399 } 400 if (AN == null) { 401 AN = new ArrayList<>(); 402 } 403 if (AN.isEmpty()) { 404 AN.add(0d); 405 } 406 407 if (AM != null && AM.size() > 1) { 408 String strAM = Double.toString(AM.get(0)); //width 409 String strAM1 = Double.toString(AM.get(1)); //length 410 //set width and length in meters for rectangular target 411 tg.set_AM(strAM); 412 tg.set_AM1(strAM1); 413 //set attitude in degrees 414 String strAN = Double.toString(AN.get(0)); 415 tg.set_AN(strAN); 416 } 417 /* 418 if(AM.size()>2) 419 { 420 String strH1 = Double.toString(AM.get(2)); //buffer size 421 tg.set_H1(strH1); 422 } 423 */ 424 } 425 } catch (Exception exc) { 426 ErrorLogger.LogException("clsRenderer", "createTGLightFromBasicMilStdSymbol", 427 new RendererException("Failed to build multipoint TG for " + lineType, exc)); 428 } 429 return tg; 430 } 431 432 /** 433 * Create MilStdSymbol from tactical graphic 434 * 435 * @deprecated 436 * @param tg tactical graphic 437 * @param converter geographic to pixels to converter 438 * @return MilstdSymbol object 439 */ 440 public static MilStdSymbol createMilStdSymboFromTGLight(TGLight tg, IPointConversion converter) { 441 MilStdSymbol milStd = null; 442 try { 443 String symbolId = tg.get_SymbolId(); 444 int lineType = armyc2.c5isr.JavaTacticalRenderer.clsUtility.GetLinetypeFromString(symbolId); 445 String status = tg.get_Status(); 446 //build tg.Pixels 447 tg.Pixels = clsUtility.LatLongToPixels(tg.LatLongs, converter); 448 boolean isClosedArea = armyc2.c5isr.JavaTacticalRenderer.clsUtility.isClosedPolygon(lineType); 449 if (isClosedArea) { 450 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(tg.Pixels); 451 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(tg.LatLongs); 452 } 453 454 ArrayList<Point2D> coords = getClientCoords(tg); 455 tg.set_Font(new Font("Arial", Font.PLAIN, 12)); 456 Map<String,String> modifiers = new HashMap<>(); 457 modifiers.put(Modifiers.W_DTG_1, tg.get_DTG()); 458 modifiers.put(Modifiers.W1_DTG_2, tg.get_DTG1()); 459 modifiers.put(Modifiers.H_ADDITIONAL_INFO_1, tg.get_H()); 460 modifiers.put(Modifiers.H1_ADDITIONAL_INFO_2, tg.get_H1()); 461 modifiers.put(Modifiers.H2_ADDITIONAL_INFO_3, tg.get_H2()); 462 modifiers.put(Modifiers.T_UNIQUE_DESIGNATION_1, tg.get_Name()); 463 modifiers.put(Modifiers.T1_UNIQUE_DESIGNATION_2, tg.get_T1()); 464 modifiers.put(Modifiers.Y_LOCATION, tg.get_Location()); 465 modifiers.put(Modifiers.N_HOSTILE, tg.get_N()); 466 467 milStd = new MilStdSymbol(symbolId, "1", coords, modifiers); 468 milStd.setFillColor(tg.get_FillColor()); 469 milStd.setLineColor(tg.get_LineColor()); 470 milStd.setLineWidth(tg.get_LineThickness()); 471 milStd.setFillStyle(tg.get_TexturePaint()); 472 milStd.setPatternScale(tg.get_patternScale()); 473 } catch (Exception exc) { 474 ErrorLogger.LogException("clsRenderer", "createMilStdSymboFromTGLight", 475 new RendererException("Failed to set geo points or pixels for " + tg.get_SymbolId(), exc)); 476 } 477 return milStd; 478 } 479 480 /** 481 * Build a tactical graphic object from the client MilStdSymbol 482 * 483 * @param milStd MilstdSymbol object 484 * @param converter geographic to pixels converter 485 * @return tactical graphic 486 */ 487 public static TGLight createTGLightFromMilStdSymbol(MilStdSymbol milStd, 488 IPointConversion converter) { 489 TGLight tg = new TGLight(); 490 try { 491 String symbolId = milStd.getSymbolID(); 492 tg.set_SymbolId(symbolId); 493 boolean useLineInterpolation = milStd.getUseLineInterpolation(); 494 tg.set_UseLineInterpolation(useLineInterpolation); 495 int lineType = armyc2.c5isr.JavaTacticalRenderer.clsUtility.GetLinetypeFromString(symbolId); 496 tg.set_LineType(lineType); 497 String status = tg.get_Status(); 498 if (status != null && status.equals("A")) { 499 tg.set_LineStyle(1); 500 } 501 tg.set_VisibleModifiers(true); 502 //set tg latlongs and pixels 503 setClientCoords(milStd, tg); 504 //build tg.Pixels 505 tg.Pixels = clsUtility.LatLongToPixels(tg.LatLongs, converter); 506 //tg.set_Font(new Font("Arial", Font.PLAIN, 12)); 507 RendererSettings r = RendererSettings.getInstance(); 508 int type = r.getMPLabelFontType(); 509 String name = r.getMPLabelFontName(); 510 int sz = r.getMPLabelFontSize(); 511 Font font = new Font(name, type, sz); 512 tg.set_Font(font); 513 tg.set_FillColor(milStd.getFillColor()); 514 tg.set_LineColor(milStd.getLineColor()); 515 tg.set_LineThickness(milStd.getLineWidth()); 516 tg.set_TexturePaint(milStd.getFillStyle()); 517 tg.set_patternScale(milStd.getPatternScale()); 518 519 tg.set_IconSize(milStd.getUnitSize()); 520 tg.set_KeepUnitRatio(milStd.getKeepUnitRatio()); 521 522 tg.set_FontBackColor(Color.WHITE); 523 tg.set_TextColor(milStd.getTextColor()); 524 if (milStd.getModifier(Modifiers.W_DTG_1) != null) { 525 tg.set_DTG(milStd.getModifier(Modifiers.W_DTG_1)); 526 } 527 if (milStd.getModifier(Modifiers.W1_DTG_2) != null) { 528 tg.set_DTG1(milStd.getModifier(Modifiers.W1_DTG_2)); 529 } 530 if (milStd.getModifier(Modifiers.H_ADDITIONAL_INFO_1) != null) { 531 tg.set_H(milStd.getModifier(Modifiers.H_ADDITIONAL_INFO_1)); 532 } 533 if (milStd.getModifier(Modifiers.H1_ADDITIONAL_INFO_2) != null) { 534 tg.set_H1(milStd.getModifier(Modifiers.H1_ADDITIONAL_INFO_2)); 535 } 536 if (milStd.getModifier(Modifiers.H2_ADDITIONAL_INFO_3) != null) { 537 tg.set_H2(milStd.getModifier(Modifiers.H2_ADDITIONAL_INFO_3)); 538 } 539 if (milStd.getModifier(Modifiers.T_UNIQUE_DESIGNATION_1) != null) { 540 tg.set_Name(milStd.getModifier(Modifiers.T_UNIQUE_DESIGNATION_1)); 541 } 542 if (milStd.getModifier(Modifiers.T1_UNIQUE_DESIGNATION_2) != null) { 543 tg.set_T1(milStd.getModifier(Modifiers.T1_UNIQUE_DESIGNATION_2)); 544 } 545 if (milStd.getModifier(Modifiers.V_EQUIP_TYPE) != null) { 546 tg.set_V(milStd.getModifier(Modifiers.V_EQUIP_TYPE)); 547 } 548 if (milStd.getModifier(Modifiers.AS_COUNTRY) != null) { 549 tg.set_AS(milStd.getModifier(Modifiers.AS_COUNTRY)); 550 } 551 if (milStd.getModifier(Modifiers.AP_TARGET_NUMBER) != null) { 552 tg.set_AP(milStd.getModifier(Modifiers.AP_TARGET_NUMBER)); 553 } 554 if (milStd.getModifier(Modifiers.Y_LOCATION) != null) { 555 tg.set_Location(milStd.getModifier(Modifiers.Y_LOCATION)); 556 } 557 if (milStd.getModifier(Modifiers.N_HOSTILE) != null) { 558 tg.set_N(milStd.getModifier(Modifiers.N_HOSTILE)); 559 } 560 tg.set_UseDashArray(milStd.getUseDashArray()); 561 tg.set_UseHatchFill(milStd.getUseFillPattern()); 562 //tg.set_UsePatternFill(milStd.getUseFillPattern()); 563 tg.set_HideOptionalLabels(milStd.getHideOptionalLabels()); 564 boolean isClosedArea = armyc2.c5isr.JavaTacticalRenderer.clsUtility.isClosedPolygon(lineType); 565 566 if (lineType == TacticalLines.STRIKWARN) { 567 ArrayList<POINT2> poly1Pixels = new ArrayList<>(tg.Pixels.subList(0, tg.Pixels.size() / 2)); 568 ArrayList<POINT2> poly1LatLons = new ArrayList<>(tg.LatLongs.subList(0, tg.LatLongs.size() / 2)); 569 ArrayList<POINT2> poly2Pixels = new ArrayList<>(tg.Pixels.subList(tg.Pixels.size() / 2, tg.Pixels.size())); 570 ArrayList<POINT2> poly2LatLons = new ArrayList<>(tg.LatLongs.subList(tg.LatLongs.size() / 2, tg.LatLongs.size())); 571 572 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(poly1Pixels); 573 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(poly1LatLons); 574 tg.Pixels = poly1Pixels; 575 tg.LatLongs = poly1LatLons; 576 577 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(poly2Pixels); 578 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(poly2LatLons); 579 tg.Pixels.addAll(poly2Pixels); 580 tg.LatLongs.addAll(poly2LatLons); 581 } 582 else if (isClosedArea) { 583 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(tg.Pixels); 584 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(tg.LatLongs); 585 } 586 587 //implement meters to feet for altitude labels 588 String altitudeLabel = milStd.getAltitudeMode(); 589 if (altitudeLabel == null || altitudeLabel.isEmpty()) { 590 altitudeLabel = "AMSL"; 591 } 592 DistanceUnit altitudeUnit = milStd.getAltitudeUnit(); 593 if(altitudeUnit == null){ 594 altitudeUnit = DistanceUnit.FEET; 595 } 596 DistanceUnit distanceUnit = milStd.getDistanceUnit(); 597 if(distanceUnit == null){ 598 distanceUnit = DistanceUnit.METERS; 599 } 600 601 String strXAlt = ""; 602 //construct the H1 and H2 modifiers for sector from the mss AM, AN, and X arraylists 603 if (lineType == TacticalLines.RANGE_FAN_SECTOR) { 604 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 605 ArrayList<Double> AN = milStd.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH); 606 ArrayList<Double> X = milStd.getModifiers_AM_AN_X(Modifiers.X_ALTITUDE_DEPTH); 607 if (AM != null) { 608 String strAM = ""; 609 for (int j = 0; j < AM.size(); j++) { 610 strAM += Double.toString(AM.get(j)); 611 if (j < AM.size() - 1) { 612 strAM += ","; 613 } 614 } 615 tg.set_AM(strAM); 616 } 617 if (AN != null) { 618 String strAN = ""; 619 for (int j = 0; j < AN.size(); j++) { 620 strAN += AN.get(j); 621 if (j < AN.size() - 1) { 622 strAN += ","; 623 } 624 } 625 tg.set_AN(strAN); 626 } 627 if (X != null) { 628 String strX = ""; 629 for (int j = 0; j < X.size(); j++) { 630 strXAlt = createAltitudeLabel(X.get(j), altitudeUnit, altitudeLabel); 631 strX += strXAlt; 632 633 if (j < X.size() - 1) { 634 strX += ","; 635 } 636 } 637 tg.set_X(strX); 638 } 639 if (AM != null && AN != null) { 640 int numSectors = AN.size() / 2; 641 double left, right, min = 0, max = 0; 642 //construct left,right,min,max from the arraylists 643 String strLeftRightMinMax = ""; 644 for (int j = 0; j < numSectors; j++) { 645 left = AN.get(2 * j); 646 right = AN.get(2 * j + 1); 647 if (j + 1 == AM.size()) { 648 break; 649 } 650 min = AM.get(j); 651 max = AM.get(j + 1); 652 strLeftRightMinMax += Double.toString(left) + "," + Double.toString(right) + "," + Double.toString(min) + "," + Double.toString(max); 653 if (j < numSectors - 1) { 654 strLeftRightMinMax += ","; 655 } 656 657 } 658 int len = strLeftRightMinMax.length(); 659 String c = strLeftRightMinMax.substring(len - 1, len); 660 if (c.equalsIgnoreCase(",")) { 661 strLeftRightMinMax = strLeftRightMinMax.substring(0, len - 1); 662 } 663 tg.set_LRMM(strLeftRightMinMax); 664 } 665 } else if (lineType == TacticalLines.RADAR_SEARCH) { 666 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 667 ArrayList<Double> AN = milStd.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH); 668 if (AM != null) { 669 String strAM = ""; 670 for (int j = 0; j < AM.size() && j < 2; j++) { 671 strAM += Double.toString(AM.get(j)); 672 if (j < AM.size() - 1) { 673 strAM += ","; 674 } 675 } 676 tg.set_AM(strAM); 677 } 678 if (AN != null) { 679 String strAN = ""; 680 for (int j = 0; j < AN.size() && j < 2; j++) { 681 strAN += AN.get(j); 682 if (j < AN.size() - 1) { 683 strAN += ","; 684 } 685 } 686 tg.set_AN(strAN); 687 } 688 if (AM != null && AN != null) { 689 double left, right, min = 0, max = 0; 690 //construct left,right,min,max from the arraylists 691 String strLeftRightMinMax = ""; 692 left = AN.get(0); 693 right = AN.get(1); 694 min = AM.get(0); 695 max = AM.get(1); 696 strLeftRightMinMax += Double.toString(left) + "," + Double.toString(right) + "," + Double.toString(min) + "," + Double.toString(max); 697 tg.set_LRMM(strLeftRightMinMax); 698 } 699 } 700 int j = 0; 701 if (lineType == TacticalLines.LAUNCH_AREA || lineType == TacticalLines.DEFENDED_AREA_CIRCULAR || lineType == TacticalLines.SHIP_AOI_CIRCULAR) //geo ellipse 702 { 703 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 704 ArrayList<Double> AN = milStd.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH); 705 if (AM != null && AM.size() > 1) { 706 String strAM = AM.get(0).toString(); // major axis 707 tg.set_AM(strAM); 708 String strAM1 = AM.get(1).toString(); // minor axis 709 tg.set_AM1(strAM1); 710 } 711 if (AN != null && AN.size() > 0) { 712 String strAN = AN.get(0).toString(); // rotation 713 tg.set_AN(strAN); 714 } 715 } 716 switch (lineType) { 717 case TacticalLines.ROZ: 718 case TacticalLines.AARROZ: 719 case TacticalLines.UAROZ: 720 case TacticalLines.WEZ: 721 case TacticalLines.FEZ: 722 case TacticalLines.JEZ: 723 case TacticalLines.FAADZ: 724 case TacticalLines.HIDACZ: 725 case TacticalLines.MEZ: 726 case TacticalLines.LOMEZ: 727 case TacticalLines.HIMEZ: 728 case TacticalLines.ACA: 729 case TacticalLines.ACA_RECTANGULAR: 730 case TacticalLines.ACA_CIRCULAR: 731 case TacticalLines.WFZ: 732 ArrayList<Double> X = milStd.getModifiers_AM_AN_X(Modifiers.X_ALTITUDE_DEPTH); 733 if (X != null && X.size() > 0) { 734 strXAlt = createAltitudeLabel(X.get(0), altitudeUnit, altitudeLabel); 735 tg.set_X(strXAlt); 736 } 737 if (X != null && X.size() > 1) { 738 strXAlt = createAltitudeLabel(X.get(1), altitudeUnit, altitudeLabel); 739 tg.set_X1(strXAlt); 740 } 741 break; 742 case TacticalLines.SC: 743 case TacticalLines.MRR: 744 case TacticalLines.SL: 745 case TacticalLines.TC: 746 case TacticalLines.LLTR: 747 case TacticalLines.AC: 748 case TacticalLines.SAAFR: 749 POINT2 pt = tg.LatLongs.get(0); 750 Point2D pt2d0 = new Point2D.Double(pt.x, pt.y); 751 Point2D pt2d0Pixels = converter.GeoToPixels(pt2d0); 752 POINT2 pt0Pixels = new POINT2(pt2d0Pixels.getX(), pt2d0Pixels.getY()); 753 754 //get some point 10000 meters away from pt 755 //10000 should work for any scale 756 double dist = 10000; 757 POINT2 pt2 = mdlGeodesic.geodesic_coordinate(pt, dist, 0); 758 Point2D pt2d1 = new Point2D.Double(pt2.x, pt2.y); 759 Point2D pt2d1Pixels = converter.GeoToPixels(pt2d1); 760 POINT2 pt1Pixels = new POINT2(pt2d1Pixels.getX(), pt2d1Pixels.getY()); 761 //calculate pixels per meter 762 double distPixels = lineutility.CalcDistanceDouble(pt0Pixels, pt1Pixels); 763 double pixelsPerMeter = distPixels / dist; 764 765 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 766 if (AM != null) { 767 String strAM = ""; 768 for (j = 0; j < AM.size(); j++) { 769 strAM += AM.get(j).toString(); 770 if (j < AM.size() - 1) { 771 strAM += ","; 772 } 773 } 774 tg.set_AM(strAM); 775 } 776 String[] strRadii = null; 777 //get the widest value 778 //the current requirement is to use the greatest width as the default width 779 double maxWidth = 0, 780 temp = 0; 781 double maxWidthMeters = 0; 782 if (tg.get_AM() != null && tg.get_AM().isEmpty() == false) { 783 strRadii = tg.get_AM().split(","); 784 if (strRadii.length > 0) { 785 for (j = 0; j < strRadii.length; j++) { 786 if (!Double.isNaN(Double.parseDouble(strRadii[j]))) { 787 temp = Double.parseDouble(strRadii[j]); 788 if (temp > maxWidth) { 789 maxWidth = temp; 790 } 791 } 792 } 793 maxWidthMeters = maxWidth; 794 maxWidth *= pixelsPerMeter / 2; 795 796 for (j = 0; j < tg.Pixels.size(); j++) { 797 if (strRadii.length > j) { 798 if (!Double.isNaN(Double.parseDouble(strRadii[j]))) { 799 double pixels = Double.parseDouble(strRadii[j]) * pixelsPerMeter / 2; 800 tg.Pixels.get(j).style = (int) pixels; 801 tg.LatLongs.get(j).style = (int) pixels; 802 } else { 803 tg.Pixels.get(j).style = (int) maxWidth; 804 tg.LatLongs.get(j).style = (int) maxWidth; 805 } 806 } else { 807 tg.Pixels.get(j).style = (int) maxWidth; 808 tg.LatLongs.get(j).style = (int) maxWidth; 809 } 810 } 811 } 812 } 813 814 maxWidthMeters *= distanceUnit.conversionFactor; 815 maxWidthMeters *= 10.0; 816 maxWidthMeters = Math.round(maxWidthMeters); 817 int tempWidth = (int) maxWidthMeters; 818 maxWidthMeters = tempWidth / 10.0; 819 820 tg.set_AM(Double.toString(maxWidthMeters) + " " + distanceUnit.label); 821 //use X, X1 to set tg.H, tg.H1 822 X = milStd.getModifiers_AM_AN_X(Modifiers.X_ALTITUDE_DEPTH); 823 if (X != null && X.size() > 0) { 824 strXAlt = createAltitudeLabel(X.get(0), altitudeUnit, altitudeLabel); 825 tg.set_X(strXAlt); 826 } 827 if (X != null && X.size() > 1) { 828 strXAlt = createAltitudeLabel(X.get(1), altitudeUnit, altitudeLabel); 829 tg.set_X1(strXAlt); 830 } 831 break; 832 default: 833 break; 834 } 835 //circular range fans 836 if (lineType == TacticalLines.RANGE_FAN) { 837 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 838 ArrayList<Double> X = milStd.getModifiers_AM_AN_X(Modifiers.X_ALTITUDE_DEPTH); 839 String strAM = ""; 840 String strX = ""; 841 if (AM != null) { 842 // Range fan circular has a maximum of 3 circles 843 for (j = 0; j < AM.size() && j < 3; j++) { 844 strAM += Double.toString(AM.get(j)); 845 if (j < AM.size() - 1) { 846 strAM += ","; 847 } 848 849 if (X != null && j < X.size()) { 850 strXAlt = createAltitudeLabel(X.get(j), altitudeUnit, altitudeLabel); 851 strX += strXAlt; 852 if (j < X.size() - 1) { 853 strX += ","; 854 } 855 } 856 } 857 } 858 tg.set_AM(strAM); 859 tg.set_X(strX); 860 } 861 switch (lineType) { 862 case TacticalLines.PAA_RECTANGULAR: 863 case TacticalLines.RECTANGULAR_TARGET: 864 case TacticalLines.FSA_RECTANGULAR: 865 case TacticalLines.SHIP_AOI_RECTANGULAR: 866 case TacticalLines.DEFENDED_AREA_RECTANGULAR: 867 case TacticalLines.FFA_RECTANGULAR: 868 case TacticalLines.ACA_RECTANGULAR: 869 case TacticalLines.NFA_RECTANGULAR: 870 case TacticalLines.RFA_RECTANGULAR: 871 case TacticalLines.ATI_RECTANGULAR: 872 case TacticalLines.CFFZ_RECTANGULAR: 873 case TacticalLines.SENSOR_RECTANGULAR: 874 case TacticalLines.CENSOR_RECTANGULAR: 875 case TacticalLines.DA_RECTANGULAR: 876 case TacticalLines.CFZ_RECTANGULAR: 877 case TacticalLines.ZOR_RECTANGULAR: 878 case TacticalLines.TBA_RECTANGULAR: 879 case TacticalLines.TVAR_RECTANGULAR: 880 case TacticalLines.CIRCULAR: 881 case TacticalLines.BDZ: 882 case TacticalLines.FSA_CIRCULAR: 883 case TacticalLines.NOTACK: 884 case TacticalLines.ACA_CIRCULAR: 885 case TacticalLines.FFA_CIRCULAR: 886 case TacticalLines.NFA_CIRCULAR: 887 case TacticalLines.RFA_CIRCULAR: 888 case TacticalLines.PAA_CIRCULAR: 889 case TacticalLines.ATI_CIRCULAR: 890 case TacticalLines.CFFZ_CIRCULAR: 891 case TacticalLines.SENSOR_CIRCULAR: 892 case TacticalLines.CENSOR_CIRCULAR: 893 case TacticalLines.DA_CIRCULAR: 894 case TacticalLines.CFZ_CIRCULAR: 895 case TacticalLines.ZOR_CIRCULAR: 896 case TacticalLines.TBA_CIRCULAR: 897 case TacticalLines.TVAR_CIRCULAR: 898 case TacticalLines.KILLBOXBLUE_CIRCULAR: 899 case TacticalLines.KILLBOXPURPLE_CIRCULAR: 900 case TacticalLines.KILLBOXBLUE_RECTANGULAR: 901 case TacticalLines.KILLBOXPURPLE_RECTANGULAR: 902 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 903 if (AM != null && AM.size() > 0) { 904 String strAM = Double.toString(AM.get(0)); 905 //set width for rectangles or radius for circles 906 tg.set_AM(strAM); 907 } 908 break; 909 default: 910 break; 911 } 912 if (lineType == TacticalLines.RECTANGULAR || lineType == TacticalLines.CUED_ACQUISITION) { 913 ArrayList<Double> AM = milStd.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 914 ArrayList<Double> AN = milStd.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH); 915 if (AN == null) { 916 AN = new ArrayList<>(); 917 } 918 if (AN.isEmpty()) { 919 AN.add(0d); 920 } 921 922 if (AM != null && AM.size() > 1) { 923 String strAM = Double.toString(AM.get(0)); //width 924 String strAM1 = Double.toString(AM.get(1)); //length 925 //set width and length in meters for rectangular target 926 tg.set_AM(strAM); 927 tg.set_AM1(strAM1); 928 //set attitude in degrees 929 String strAN = Double.toString(AN.get(0)); 930 tg.set_AN(strAN); 931 } 932 /* 933 if(AM.size()>2) 934 { 935 String strH1 = Double.toString(AM.get(2)); //buffer size 936 tg.set_H1(strH1); 937 } 938 */ 939 } 940 } catch (Exception exc) { 941 ErrorLogger.LogException("clsRenderer", "createTGLightfromMilStdSymbol", 942 new RendererException("Failed to build multipoint TG for " + milStd.getSymbolID(), exc)); 943 } 944 return tg; 945 } 946 947 private static String createAltitudeLabel(double distance, DistanceUnit altitudeUnit, String altitudeLabel){ 948 double conversionFactor; 949 950 // if using "FL" (Flight Level) for altitudeLabel, override conversion factor to avoid potential user error with altitudeUnit 951 if (altitudeLabel.equals("FL")) { 952 conversionFactor = DistanceUnit.FLIGHT_LEVEL.conversionFactor; 953 } else { 954 conversionFactor = altitudeUnit.conversionFactor; 955 } 956 957 // Truncate the result 958 double result = distance * conversionFactor; 959 result *= 10.0; 960 result = Math.round(result); 961 int tempResult = (int) result; 962 int truncatedResult = tempResult / 10; 963 // MIL-STD-2525D says altitude/depth must be an integer 964 965 // Simplifies labels of "0 units AGL" to "GL" (Ground Level) and "0 units AMSL/BMSL" to "MSL" (Mean Sea Level) 966 // as permitted by MIL-STD-2525D 5.3.7.5.1. 967 // Also works for "0 units GL" and "0 units MSL", which are improperly labeled but can be understood to mean the same thing. 968 if (truncatedResult == 0) { 969 if (altitudeLabel.equals("AGL") || altitudeLabel.equals("GL")) { 970 return "GL"; 971 } 972 if (altitudeLabel.equals("AMSL") || altitudeLabel.equals("BMSL") || altitudeLabel.equals("MSL")) { 973 return "MSL"; 974 } 975 } 976 977 // Flight level is a special altitude displayed as "FL ###" where ### are 3 digits representing hundreds of feet. 978 if (altitudeLabel.equals("FL")) { 979 return "FL " + String.format("%03d", truncatedResult); 980 } 981 982 return truncatedResult + " " + altitudeUnit.label + " " + altitudeLabel; 983 } 984 985 /** 986 * @deprecated @param milStd 987 * @param converter 988 * @param computeChannelPt 989 * @return 990 */ 991 public static TGLight createTGLightFromMilStdSymbol(MilStdSymbol milStd, 992 IPointConversion converter, Boolean computeChannelPt) { 993 TGLight tg = new TGLight(); 994 try { 995 String symbolId = milStd.getSymbolID(); 996 tg.set_SymbolId(symbolId); 997 String status = tg.get_Status(); 998 if (status != null && status.equals("A")) { 999 //lineStyle=GraphicProperties.LINE_TYPE_DASHED; 1000 tg.set_LineStyle(1); 1001 } 1002 tg.set_VisibleModifiers(true); 1003 //set tg latlongs and pixels 1004 setClientCoords(milStd, tg); 1005 //build tg.Pixels 1006 tg.Pixels = clsUtility.LatLongToPixels(tg.LatLongs, converter); 1007 tg.set_Font(new Font("Arial", Font.PLAIN, 12)); 1008 tg.set_FillColor(milStd.getFillColor()); 1009 tg.set_LineColor(milStd.getLineColor()); 1010 tg.set_LineThickness(milStd.getLineWidth()); 1011 tg.set_TexturePaint(milStd.getFillStyle()); 1012 tg.set_patternScale(milStd.getPatternScale()); 1013 tg.set_FontBackColor(Color.WHITE); 1014 tg.set_TextColor(milStd.getTextColor()); 1015 1016// tg.set_DTG(milStd.getModifier(Modifiers.W_DTG_1)); 1017// tg.set_DTG1(milStd.getModifier(Modifiers.W1_DTG_2)); 1018// tg.set_H(milStd.getModifier(Modifiers.H_ADDITIONAL_INFO_1)); 1019// tg.set_H1(milStd.getModifier(Modifiers.H1_ADDITIONAL_INFO_2)); 1020// tg.set_H2(milStd.getModifier(Modifiers.H2_ADDITIONAL_INFO_3)); 1021// tg.set_Name(milStd.getModifier(Modifiers.T_UNIQUE_DESIGNATION_1)); 1022// tg.set_T1(milStd.getModifier(Modifiers.T1_UNIQUE_DESIGNATION_2)); 1023// tg.set_Location(milStd.getModifier(Modifiers.Y_LOCATION)); 1024// tg.set_N(Modifiers.N_HOSTILE); 1025 if (milStd.getModifier(Modifiers.W_DTG_1) != null) { 1026 tg.set_DTG(milStd.getModifier(Modifiers.W_DTG_1)); 1027 } 1028 if (milStd.getModifier(Modifiers.W1_DTG_2) != null) { 1029 tg.set_DTG1(milStd.getModifier(Modifiers.W1_DTG_2)); 1030 } 1031 if (milStd.getModifier(Modifiers.H_ADDITIONAL_INFO_1) != null) { 1032 tg.set_H(milStd.getModifier(Modifiers.H_ADDITIONAL_INFO_1)); 1033 } 1034 if (milStd.getModifier(Modifiers.H1_ADDITIONAL_INFO_2) != null) { 1035 tg.set_H1(milStd.getModifier(Modifiers.H1_ADDITIONAL_INFO_2)); 1036 } 1037 if (milStd.getModifier(Modifiers.H2_ADDITIONAL_INFO_3) != null) { 1038 tg.set_H2(milStd.getModifier(Modifiers.H2_ADDITIONAL_INFO_3)); 1039 } 1040 if (milStd.getModifier(Modifiers.T_UNIQUE_DESIGNATION_1) != null) { 1041 tg.set_Name(milStd.getModifier(Modifiers.T_UNIQUE_DESIGNATION_1)); 1042 } 1043 if (milStd.getModifier(Modifiers.T1_UNIQUE_DESIGNATION_2) != null) { 1044 tg.set_T1(milStd.getModifier(Modifiers.T1_UNIQUE_DESIGNATION_2)); 1045 } 1046 if (milStd.getModifier(Modifiers.V_EQUIP_TYPE) != null) { 1047 tg.set_V(milStd.getModifier(Modifiers.V_EQUIP_TYPE)); 1048 } 1049 if (milStd.getModifier(Modifiers.AS_COUNTRY) != null) { 1050 tg.set_AS(milStd.getModifier(Modifiers.AS_COUNTRY)); 1051 } 1052 if (milStd.getModifier(Modifiers.AP_TARGET_NUMBER) != null) { 1053 tg.set_AP(milStd.getModifier(Modifiers.AP_TARGET_NUMBER)); 1054 } 1055 if (milStd.getModifier(Modifiers.Y_LOCATION) != null) { 1056 tg.set_Location(milStd.getModifier(Modifiers.Y_LOCATION)); 1057 } 1058 if (milStd.getModifier(Modifiers.N_HOSTILE) != null) { 1059 tg.set_N(milStd.getModifier(Modifiers.N_HOSTILE)); 1060 } 1061 1062 //int lineType=CELineArray.CGetLinetypeFromString(tg.get_SymbolId()); 1063 int lineType = armyc2.c5isr.JavaTacticalRenderer.clsUtility.GetLinetypeFromString(symbolId); 1064 boolean isClosedArea = armyc2.c5isr.JavaTacticalRenderer.clsUtility.isClosedPolygon(lineType); 1065 1066 if (isClosedArea) { 1067 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(tg.Pixels); 1068 armyc2.c5isr.JavaTacticalRenderer.clsUtility.ClosePolygon(tg.LatLongs); 1069 } 1070 1071 //these channels need a channel point added 1072 if (computeChannelPt) { 1073 switch (lineType) { 1074 case TacticalLines.CATK: 1075 case TacticalLines.CATKBYFIRE: 1076 case TacticalLines.AAAAA: 1077 case TacticalLines.AIRAOA: 1078 case TacticalLines.MAIN: 1079 case TacticalLines.SPT: 1080 case TacticalLines.FRONTAL_ATTACK: 1081 case TacticalLines.TURNING_MOVEMENT: 1082 case TacticalLines.MOVEMENT_TO_CONTACT: 1083 POINT2 ptPixels = armyc2.c5isr.JavaTacticalRenderer.clsUtility.ComputeLastPoint(tg.Pixels); 1084 tg.Pixels.add(ptPixels); 1085 //Point pt = clsUtility.POINT2ToPoint(ptPixels); 1086 Point2D pt = new Point2D.Double(ptPixels.x, ptPixels.y); 1087 //in case it needs the corresponding geo point 1088 Point2D ptGeo2d = converter.PixelsToGeo(pt); 1089 POINT2 ptGeo = clsUtility.Point2DToPOINT2(ptGeo2d); 1090 tg.LatLongs.add(ptGeo); 1091 //} 1092 break; 1093 default: 1094 break; 1095 } 1096 } 1097 } catch (Exception exc) { 1098 ErrorLogger.LogException("clsRenderer", "createTGLightfromMilStdSymbol", 1099 new RendererException("Failed to build multipoint TG for " + milStd.getSymbolID(), exc)); 1100 } 1101 return tg; 1102 } 1103 1104 private static void Shape2ToShapeInfo(ArrayList<ShapeInfo> shapeInfos, ArrayList<Shape2> shapes) { 1105 try { 1106 int j = 0; 1107 Shape2 shape = null; 1108 if (shapes == null || shapeInfos == null || shapes.size() == 0) { 1109 return; 1110 } 1111 1112 for (j = 0; j < shapes.size(); j++) { 1113 shape = shapes.get(j); 1114 shapeInfos.add((ShapeInfo) shape); 1115 } 1116 } catch (Exception exc) { 1117 ErrorLogger.LogException("clsRenderer", "Shape2ToShapeInfo", 1118 new RendererException("Failed to build ShapeInfo ArrayList", exc)); 1119 } 1120 } 1121 1122 /** 1123 * Added function to handle when coords or display area spans IDL but not 1124 * both, it prevents the symbol from rendering if the bounding rectangles 1125 * don't intersect. 1126 * 1127 * @param tg 1128 * @param converter 1129 * @param clipArea 1130 * @return 1131 */ 1132 public static boolean intersectsClipArea(TGLight tg, IPointConversion converter, Object clipArea) 1133 { 1134 boolean result=false; 1135 try 1136 { 1137 if (clipArea==null || tg.LatLongs.size() < 2) 1138 return true; 1139 Rectangle2D clipBounds = null; 1140 ArrayList<Point2D> clipPoints = null; 1141 1142// if (clipArea != null) { 1143// if (clipArea.getClass().isAssignableFrom(Rectangle2D.Double.class)) { 1144// clipBounds = (Rectangle2D.Double) clipArea; 1145// } else if (clipArea.getClass().isAssignableFrom(Rectangle.class)) { 1146// clipBounds = (Rectangle2D) clipArea; 1147// } else if (clipArea.getClass().isAssignableFrom(ArrayList.class)) { 1148// clipPoints = (ArrayList<Point2D>) clipArea; 1149// } 1150// } 1151 if (clipArea != null) { 1152 if (clipArea.getClass().isAssignableFrom(Rectangle2D.Double.class)) { 1153 clipBounds = (Rectangle2D.Double) clipArea; 1154 } else if (clipArea.getClass().isAssignableFrom(Rectangle.class)) { 1155 Rectangle rectx = (Rectangle) clipArea; 1156 clipBounds = new Rectangle2D.Double(rectx.x, rectx.y, rectx.width, rectx.height); 1157 } else if (clipArea.getClass().isAssignableFrom(ArrayList.class)) { 1158 clipPoints = (ArrayList<Point2D>) clipArea; 1159 //double x0=clipPoints.get(0).getX(),y0=clipPoints.get(0).getY(); 1160 //double w=clipPoints.get(1).getX()-x0,h=clipPoints.get(3).getY()-y0; 1161 //clipBounds = new Rectangle2D.Double(x0, y0, w, h); 1162 clipBounds=clsUtility.getMBR(clipPoints); 1163 } 1164 } 1165 //assumes we are using clipBounds 1166 int j = 0; 1167 double x = clipBounds.getMinX(); 1168 double y = clipBounds.getMinY(); 1169 double width = clipBounds.getWidth(); 1170 double height = clipBounds.getHeight(); 1171 POINT2 tl = new POINT2(x, y); 1172 POINT2 br = new POINT2(x + width, y + height); 1173 tl = clsUtility.PointPixelsToLatLong(tl, converter); 1174 br = clsUtility.PointPixelsToLatLong(br, converter); 1175 //the latitude range 1176 //boolean ptInside = false, ptAbove = false, ptBelow = false; 1177 double coordsLeft = tg.LatLongs.get(0).x; 1178 double coordsRight = coordsLeft; 1179 double coordsTop=tg.LatLongs.get(0).y; 1180 double coordsBottom=coordsTop; 1181 boolean intersects=false; 1182 double minx=tg.LatLongs.get(0).x,maxx=minx,maxNegX=0; 1183 for (j = 0; j < tg.LatLongs.size(); j++) 1184 { 1185 POINT2 pt=tg.LatLongs.get(j); 1186 if (pt.x < minx) 1187 minx = pt.x; 1188 if (pt.x > maxx) 1189 maxx = pt.x; 1190 if(maxNegX==0 && pt.x<0) 1191 maxNegX=pt.x; 1192 if(maxNegX<0 && pt.x<0 && pt.x>maxNegX) 1193 maxNegX=pt.x; 1194 if (pt.y < coordsBottom) 1195 coordsBottom = pt.y; 1196 if (pt.y > coordsTop) 1197 coordsTop = pt.y; 1198 } 1199 boolean coordSpanIDL = false; 1200 if(maxx==180 || minx==-180) 1201 coordSpanIDL=true; 1202 if(maxx-minx>=180) 1203 { 1204 coordSpanIDL=true; 1205 coordsLeft=maxx; 1206 coordsRight=maxNegX; 1207 }else 1208 { 1209 coordsLeft=minx; 1210 coordsRight=maxx; 1211 } 1212 //if(canClipPoints) 1213 //{ 1214 if(br.y<=coordsBottom && coordsBottom <= tl.y) 1215 intersects=true; 1216 else if(coordsBottom<=br.y && br.y <=coordsTop) 1217 intersects=true; 1218 else 1219 return false; 1220 //} 1221 //if it gets this far then the latitude ranges intersect 1222 //re-initialize intersects for the longitude ranges 1223 intersects=false; 1224 //the longitude range 1225 //the min and max coords longitude 1226 boolean boxSpanIDL = false; 1227 //boolean coordSpanIDL = false; 1228 if(tl.x==180 || tl.x==-180 || br.x==180 || br.x==-180) 1229 boxSpanIDL=true; 1230 else if (Math.abs(br.x - tl.x) > 180) 1231 boxSpanIDL = true; 1232 1233// if (coordsRight - coordsLeft > 180) 1234// { 1235// double temp = coordsLeft; 1236// coordsLeft = coordsRight; 1237// coordsRight = temp; 1238// coordSpanIDL=true; 1239// } 1240 //boolean intersects=false; 1241 if(coordSpanIDL && boxSpanIDL) 1242 intersects=true; 1243 else if(!coordSpanIDL && !boxSpanIDL) //was && canclipPoints 1244 { 1245 if(coordsLeft<=tl.x && tl.x<=coordsRight) 1246 intersects=true; 1247 if(coordsLeft<=br.x && br.x<=coordsRight) 1248 intersects=true; 1249 if(tl.x<=coordsLeft && coordsLeft<=br.x) 1250 intersects=true; 1251 if(tl.x<=coordsRight && coordsRight<=br.x) 1252 intersects=true; 1253 } 1254 else if(!coordSpanIDL && boxSpanIDL) //box spans IDL and coords do not 1255 { 1256 if(tl.x<coordsRight && coordsRight<180) 1257 intersects=true; 1258 if(-180<coordsLeft && coordsLeft<br.x) 1259 intersects=true; 1260 } 1261 else if(coordSpanIDL && !boxSpanIDL) //coords span IDL and box does not 1262 { 1263 if(coordsLeft<br.x && br.x<180) 1264 intersects=true; 1265 if(-180<tl.x && tl.x<coordsRight) 1266 intersects=true; 1267 } 1268 return intersects; 1269 1270 } 1271 catch (Exception exc) { 1272 ErrorLogger.LogException("clsRenderer", "intersectsClipArea", 1273 new RendererException("Failed inside intersectsClipArea", exc)); 1274 } 1275 return result; 1276 } 1277 1278 /** 1279 * Adds Feint, decoy, or dummy indicator to shapes. Does not check if tactical graphic should have indicator 1280 */ 1281 private static void addFDI(TGLight tg, ArrayList<Shape2> shapes) { 1282 try { 1283 MSInfo msi = MSLookup.getInstance().getMSLInfo(tg.get_SymbolId()); 1284 final int drawRule = msi != null ? msi.getDrawRule() : -1; 1285 final int lineType = tg.get_LineType(); 1286 1287 if (lineType == TacticalLines.MAIN) { 1288 // Only Axis of Advance with arrowhead in a different location 1289 ArrayList<POINT2> points = shapes.get(1).getPoints(); 1290 POINT2 ptA = new POINT2(points.get(points.size() - 3)); 1291 POINT2 ptB = new POINT2(points.get(points.size() - 8)); 1292 POINT2 ptC = new POINT2(points.get(points.size() - 7)); 1293 shapes.add(DISMSupport.getFDIShape(tg, ptA, ptB, ptC)); 1294 } else if (drawRule == DrawRules.AXIS1 || drawRule == DrawRules.AXIS2) { 1295 // Axis of Advance symbols 1296 ArrayList<POINT2> points = shapes.get(0).getPoints(); 1297 POINT2 ptA = new POINT2(points.get(points.size() / 2 - 1)); 1298 POINT2 ptB = new POINT2(points.get(points.size() / 2)); 1299 POINT2 ptC = new POINT2(points.get(points.size() / 2 + 1)); 1300 shapes.add(DISMSupport.getFDIShape(tg, ptA, ptB, ptC)); 1301 } 1302 // Direction of attack symbols 1303 else if (lineType == TacticalLines.DIRATKAIR) { 1304 ArrayList<POINT2> points = shapes.get(2).getPoints(); 1305 POINT2 ptA = new POINT2(points.get(0)); 1306 POINT2 ptB = new POINT2(points.get(1)); 1307 POINT2 ptC = new POINT2(points.get(2)); 1308 shapes.add(DISMSupport.getFDIShape(tg, ptA, ptB, ptC)); 1309 } else if (lineType == TacticalLines.DIRATKGND) { 1310 ArrayList<POINT2> points = shapes.get(1).getPoints(); 1311 POINT2 ptA = new POINT2(points.get(7)); 1312 POINT2 ptB = new POINT2(points.get(4)); 1313 POINT2 ptC = new POINT2(points.get(9)); 1314 shapes.add(DISMSupport.getFDIShape(tg, ptA, ptB, ptC)); 1315 } else if (lineType == TacticalLines.DIRATKSPT || lineType == TacticalLines.INFILTRATION) { 1316 ArrayList<POINT2> points = shapes.get(1).getPoints(); 1317 POINT2 ptA = new POINT2(points.get(0)); 1318 POINT2 ptB = new POINT2(points.get(1)); 1319 POINT2 ptC = new POINT2(points.get(2)); 1320 shapes.add(DISMSupport.getFDIShape(tg, ptA, ptB, ptC)); 1321 } 1322 else if (lineType == TacticalLines.EXPLOIT) { 1323 ArrayList<POINT2> points = shapes.get(1).getPoints(); 1324 POINT2 ptA = new POINT2(points.get(0)); 1325 POINT2 ptB = new POINT2(points.get(1)); 1326 POINT2 ptC = new POINT2(points.get(2)); 1327 shapes.add(DISMSupport.getFDIShape(tg, ptA, ptB, ptC)); 1328 } 1329 else { 1330 // Shape has no arrow. Put on top of shape 1331 POINT2 firstPoint = shapes.get(0).getPoints().get(0); 1332 POINT2 ptUl = new POINT2(firstPoint); 1333 POINT2 ptUr = new POINT2(firstPoint); 1334 POINT2 ptLr = new POINT2(firstPoint); 1335 POINT2 ptLl = new POINT2(firstPoint); 1336 clsUtility.GetMBR(shapes, ptUl, ptUr, ptLr, ptLl); 1337 shapes.add(DISMSupport.getFDIShape(tg, ptUl, ptUr)); 1338 } 1339 } catch (Exception exc) { 1340 ErrorLogger.LogException(_className, "addFDI", new RendererException("failed inside addFDI", exc)); 1341 } 1342 } 1343 1344 /** 1345 * @param mss 1346 * @param converter 1347 * @param clipArea 1348 * @param context 1349 * @deprecated context not used 1350 */ 1351 public static void renderWithPolylines(MilStdSymbol mss, 1352 IPointConversion converter, 1353 Object clipArea, 1354 Context context) { 1355 try { 1356 TGLight tg = clsRenderer.createTGLightFromMilStdSymbol(mss, converter); 1357 ArrayList<ShapeInfo> shapeInfos = new ArrayList(); 1358 ArrayList<ShapeInfo> modifierShapeInfos = new ArrayList(); 1359 if (intersectsClipArea(tg, converter, clipArea)) { 1360 render_GE(tg, shapeInfos, modifierShapeInfos, converter, clipArea, context); 1361 } 1362 mss.setSymbolShapes(shapeInfos); 1363 mss.setModifierShapes(modifierShapeInfos); 1364 } catch (Exception exc) { 1365 ErrorLogger.LogException("clsRenderer", "renderWithPolylines", 1366 new RendererException("Failed inside renderWithPolylines", exc)); 1367 } 1368 } 1369 1370 /** 1371 * GoogleEarth renderer uses polylines for rendering 1372 * 1373 * @param mss MilStdSymbol object 1374 * @param converter the geographic to pixels coordinate converter 1375 * @param clipArea the clip bounds 1376 */ 1377 public static void renderWithPolylines(MilStdSymbol mss, 1378 IPointConversion converter, 1379 Object clipArea) { 1380 try { 1381 TGLight tg = clsRenderer.createTGLightFromMilStdSymbol(mss, converter); 1382 ArrayList<ShapeInfo> shapeInfos = new ArrayList(); 1383 ArrayList<ShapeInfo> modifierShapeInfos = new ArrayList(); 1384 if (intersectsClipArea(tg, converter, clipArea)) { 1385 render_GE(tg, shapeInfos, modifierShapeInfos, converter, clipArea); 1386 } 1387 mss.setSymbolShapes(shapeInfos); 1388 mss.setModifierShapes(modifierShapeInfos); 1389 mss.set_WasClipped(tg.get_WasClipped()); 1390 } catch (Exception exc) { 1391 ErrorLogger.LogException("clsRenderer", "renderWithPolylines", 1392 new RendererException("Failed inside renderWithPolylines", exc)); 1393 } 1394 } 1395 1396 /** 1397 * See render_GE below for comments 1398 * 1399 * @param tg 1400 * @param shapeInfos 1401 * @param modifierShapeInfos 1402 * @param converter 1403 * @param clipArea 1404 * @param context test android-gradle 1405 * @deprecated context not used 1406 */ 1407 public static void render_GE(TGLight tg, 1408 ArrayList<ShapeInfo> shapeInfos, 1409 ArrayList<ShapeInfo> modifierShapeInfos, 1410 IPointConversion converter, 1411 Object clipArea, 1412 Context context) //was Rectangle2D 1413 { 1414 render_GE(tg, shapeInfos, modifierShapeInfos, converter, clipArea); 1415 } 1416 1417 /** 1418 * Google Earth renderer: Called by mapfragment-demo This is the public 1419 * interface for Google Earth renderer assumes tg.Pixels is filled assumes 1420 * the caller instantiated the ShapeInfo arrays 1421 * 1422 * @param tg tactical graphic 1423 * @param shapeInfos symbol ShapeInfo array 1424 * @param modifierShapeInfos modifier ShapeInfo array 1425 * @param converter geographic to pixels coordinate converter 1426 * @param clipArea clipping bounds in pixels 1427 */ 1428 public static void render_GE(TGLight tg, 1429 ArrayList<ShapeInfo> shapeInfos, 1430 ArrayList<ShapeInfo> modifierShapeInfos, 1431 IPointConversion converter, 1432 Object clipArea) { 1433 try { 1434 reversePointsRevD(tg); 1435 1436 Rectangle2D clipBounds = null; 1437 CELineArray.setClient("ge"); 1438// ArrayList<POINT2> origPixels = null; 1439// ArrayList<POINT2> origLatLongs = null; 1440// if (clsUtilityGE.segmentColorsSet(tg)) { 1441// origPixels=lineutility.getDeepCopy(tg.Pixels); 1442// origLatLongs=lineutility.getDeepCopy(tg.LatLongs); 1443// } 1444 ArrayList<POINT2> origFillPixels = lineutility.getDeepCopy(tg.Pixels); 1445 1446 if (tg.get_LineType() == TacticalLines.LC) 1447 armyc2.c5isr.JavaTacticalRenderer.clsUtility.SegmentLCPoints(tg, converter); 1448 1449// boolean shiftLines = Channels.getShiftLines(); 1450// if (shiftLines) { 1451// String affiliation = tg.get_Affiliation(); 1452// Channels.setAffiliation(affiliation); 1453// } 1454 //CELineArray.setMinLength(2.5); //2-27-2013 1455 ArrayList<Point2D> clipPoints = null; 1456 if (clipArea != null) { 1457 if (clipArea.getClass().isAssignableFrom(Rectangle2D.Double.class)) { 1458 clipBounds = (Rectangle2D.Double) clipArea; 1459 } else if (clipArea.getClass().isAssignableFrom(Rectangle.class)) { 1460 Rectangle rectx = (Rectangle) clipArea; 1461 clipBounds = new Rectangle2D.Double(rectx.x, rectx.y, rectx.width, rectx.height); 1462 } else if (clipArea.getClass().isAssignableFrom(ArrayList.class)) { 1463 clipPoints = (ArrayList<Point2D>) clipArea; 1464 } 1465 } 1466 double zoomFactor = clsUtilityGE.getZoomFactor(clipBounds, clipPoints, tg.Pixels); 1467 //add sub-section to test clipArea if client passes the rectangle 1468 boolean useClipPoints = false; //currently not used 1469 if (useClipPoints == true && clipBounds != null) { 1470 double x = clipBounds.getMinX(); 1471 double y = clipBounds.getMinY(); 1472 double width = clipBounds.getWidth(); 1473 double height = clipBounds.getHeight(); 1474 clipPoints = new ArrayList(); 1475 clipPoints.add(new Point2D.Double(x, y)); 1476 clipPoints.add(new Point2D.Double(x + width, y)); 1477 clipPoints.add(new Point2D.Double(x + width, y + height)); 1478 clipPoints.add(new Point2D.Double(x, y + height)); 1479 clipPoints.add(new Point2D.Double(x, y)); 1480 clipBounds = null; 1481 } 1482 //end section 1483 1484 if (tg.get_Client() == null || tg.get_Client().isEmpty()) { 1485 tg.set_client("ge"); 1486 } 1487 1488 clsUtility.RemoveDuplicatePoints(tg); 1489 1490 int linetype = tg.get_LineType(); 1491 if (linetype < 0) { 1492 linetype = armyc2.c5isr.JavaTacticalRenderer.clsUtility.GetLinetypeFromString(tg.get_SymbolId()); 1493 //clsUtilityCPOF.SegmentGeoPoints(tg, converter); 1494 tg.set_LineType(linetype); 1495 } 1496 1497 Boolean isTextFlipped = false; 1498 ArrayList<Shape2> shapes = null; //use this to collect all the shapes 1499 clsUtilityGE.setSplineLinetype(tg); 1500 1501 clsUtilityCPOF.SegmentGeoPoints(tg, converter, zoomFactor); 1502 if (clipBounds != null || clipPoints != null) { 1503 if (clsUtilityCPOF.canClipPoints(tg)) { 1504 //check assignment 1505 if (clipBounds != null) { 1506 clsClipPolygon2.ClipPolygon(tg, clipBounds); 1507 } else if (clipPoints != null) { 1508 clsClipQuad.ClipPolygon(tg, clipPoints); 1509 } 1510 1511 clsUtilityGE.removeTrailingPoints(tg, clipArea); 1512 tg.LatLongs = clsUtility.PixelsToLatLong(tg.Pixels, converter); 1513 } 1514 } 1515 1516 //if MSR segment data set use original pixels unless tg.Pixels is empty from clipping 1517// if (origPixels != null) { 1518// if (tg.Pixels.isEmpty()) { 1519// return; 1520// } else { 1521// tg.Pixels = origPixels; 1522// tg.LatLongs = origLatLongs; 1523// clipArea = null; 1524// } 1525// } 1526 armyc2.c5isr.JavaTacticalRenderer.clsUtility.InterpolatePixels(tg); 1527 1528 tg.modifiers = new ArrayList(); 1529 BufferedImage bi = new BufferedImage(8, 8, BufferedImage.TYPE_INT_ARGB); 1530 Graphics2D g2d = bi.createGraphics(); 1531 g2d.setFont(tg.get_Font()); 1532 Modifier2.AddModifiersGeo(tg, g2d, clipArea, converter); 1533 1534 clsUtilityCPOF.FilterPoints2(tg, converter); 1535 armyc2.c5isr.JavaTacticalRenderer.clsUtility.FilterVerticalSegments(tg); 1536 clsUtility.FilterAXADPoints(tg, converter); 1537 clsUtilityCPOF.ClearPixelsStyle(tg); 1538 1539 ArrayList<Shape2> linesWithFillShapes = null; 1540 1541 ArrayList<POINT2> savePixels = tg.Pixels; 1542 tg.Pixels = origFillPixels; 1543 1544 //check assignment 1545 if (clipBounds != null) { 1546 linesWithFillShapes = clsClipPolygon2.LinesWithFill(tg, clipBounds); 1547 } else if (clipPoints != null) { 1548 linesWithFillShapes = clsClipQuad.LinesWithFill(tg, clipPoints); 1549 } else if (clipArea == null) { 1550 linesWithFillShapes = clsClipPolygon2.LinesWithFill(tg, null); 1551 } 1552 1553 tg.Pixels = savePixels; 1554 1555 ArrayList<Shape2> rangeFanFillShapes = null; 1556 //do not fill the original shapes for circular range fans 1557 int savefillStyle = tg.get_FillStyle(); 1558 if (linetype == TacticalLines.RANGE_FAN) { 1559 tg.set_Fillstyle(0); 1560 } 1561 1562 //check assignment (pass which clip object is not null) 1563 if (clipBounds != null) { 1564 shapes = clsRenderer2.GetLineArray(tg, converter, isTextFlipped, clipBounds); //takes clip object 1565 } else if (clipPoints != null) { 1566 shapes = clsRenderer2.GetLineArray(tg, converter, isTextFlipped, clipPoints); 1567 } else if (clipArea == null) { 1568 shapes = clsRenderer2.GetLineArray(tg, converter, isTextFlipped, null); 1569 } 1570 1571 // Add Feint, decoy, or dummy indicator 1572 if (shapes != null 1573 && SymbolID.getSymbolSet(tg.get_SymbolId()) == SymbolID.SymbolSet_ControlMeasure 1574 && SymbolUtilities.hasFDI(tg.get_SymbolId())) { 1575 addFDI(tg, shapes); 1576 } 1577 1578 switch (linetype) { 1579 case TacticalLines.RANGE_FAN: 1580 case TacticalLines.RANGE_FAN_SECTOR: 1581 case TacticalLines.RADAR_SEARCH: 1582 if (tg.get_FillColor() == null || tg.get_FillColor().getAlpha() < 2) { 1583 break; 1584 } 1585 TGLight tg1 = clsUtilityCPOF.GetCircularRangeFanFillTG(tg); 1586 tg1.set_Fillstyle(savefillStyle); 1587 tg1.set_SymbolId(tg.get_SymbolId()); 1588 //check assignment (pass which clip object is not null) 1589 if (clipBounds != null) { 1590 rangeFanFillShapes = clsRenderer2.GetLineArray(tg1, converter, isTextFlipped, clipBounds); 1591 } else if (clipPoints != null) { 1592 rangeFanFillShapes = clsRenderer2.GetLineArray(tg1, converter, isTextFlipped, clipPoints); 1593 } else if (clipArea == null) { 1594 rangeFanFillShapes = clsRenderer2.GetLineArray(tg1, converter, isTextFlipped, null); 1595 } 1596 1597 if (rangeFanFillShapes != null) { 1598 if (shapes == null) { 1599 System.out.println("shapes is null"); 1600 break; 1601 } else { 1602 shapes.addAll(0, rangeFanFillShapes); 1603 } 1604 1605 } 1606 break; 1607 default: 1608 clsRenderer2.getAutoshapeFillShape(tg, shapes); 1609 break; 1610 } 1611 //end section 1612 1613 //undo any fillcolor for lines with fill 1614 clsUtilityCPOF.LinesWithSeparateFill(tg.get_LineType(), shapes); 1615 clsClipPolygon2.addAbatisFill(tg, shapes); 1616 1617 //if this line is commented then the extra line in testbed goes away 1618 if (shapes != null && linesWithFillShapes != null && linesWithFillShapes.size() > 0) { 1619 shapes.addAll(0, linesWithFillShapes); 1620 } 1621 1622 if (clsUtilityCPOF.canClipPoints(tg) == false && clipBounds != null) { 1623 shapes = clsUtilityCPOF.postClipShapes(tg, shapes, clipBounds); 1624 } else if (clsUtilityCPOF.canClipPoints(tg) == false && clipPoints != null) { 1625 shapes = clsUtilityCPOF.postClipShapes(tg, shapes, clipPoints); 1626 } 1627 resolvePostClippedShapes(tg,shapes); 1628 //returns early if textSpecs are null 1629 //currently the client is ignoring these 1630 if (modifierShapeInfos != null) { 1631 ArrayList<Shape2> textSpecs = new ArrayList(); 1632 Modifier2.DisplayModifiers2(tg, g2d, textSpecs, isTextFlipped, converter); 1633 Shape2ToShapeInfo(modifierShapeInfos, textSpecs); 1634 } 1635 Shape2ToShapeInfo(shapeInfos, shapes); 1636 clsUtility.addHatchFills(tg, shapeInfos); 1637 1638 //check assignment (pass which clip object is not null) 1639 if (clipBounds != null) { 1640 clsUtilityGE.SetShapeInfosPolylines(tg, shapeInfos, clipBounds);//takes a clip object 1641 } else if (clipPoints != null) { 1642 clsUtilityGE.SetShapeInfosPolylines(tg, shapeInfos, clipPoints); 1643 } else if (clipArea == null) { 1644 clsUtilityGE.SetShapeInfosPolylines(tg, shapeInfos, null); 1645 } 1646 } catch (Exception exc) { 1647 ErrorLogger.LogException(_className, "render_GE", 1648 new RendererException("Failed inside render_GE", exc)); 1649 1650 } 1651 } 1652 /** 1653 * creates a shape for known symbols. The intent is to use client points for 1654 * the shape and is intended for use with ellipse. If hatch > 1 it creates 2 shapes 1655 * one for the hatch pattern, the second one is for the outline. 1656 * 1657 * @param milStd 1658 * @param ipc 1659 * @param clipArea 1660 * @param shapeType 1661 * @param lineColor 1662 * @param fillColor 1663 * @param hatch 1664 */ 1665 public static void render_Shape(MilStdSymbol milStd, 1666 IPointConversion ipc, 1667 Object clipArea, 1668 int shapeType, 1669 Color lineColor, 1670 Color fillColor, 1671 int hatch) { 1672 try { 1673 Rectangle2D clipBounds = null; 1674 //CELineArray.setClient("ge"); 1675 ArrayList<Point2D> clipPoints = null; 1676 1677 if (clipArea != null) { 1678 if (clipArea.getClass().isAssignableFrom(Rectangle2D.Double.class)) { 1679 clipBounds = (Rectangle2D.Double) clipArea; 1680 } else if (clipArea.getClass().isAssignableFrom(Rectangle.class)) { 1681 clipBounds = (Rectangle2D) clipArea; 1682 } else if (clipArea.getClass().isAssignableFrom(ArrayList.class)) { 1683 clipPoints = (ArrayList<Point2D>) clipArea; 1684 } 1685 } 1686 1687 //can't use following line because it resets the pixels 1688 //TGLight tg = createTGLightFromMilStdSymbol(milStd, ipc); 1689 TGLight tg = new TGLight(); 1690 tg.set_SymbolId(milStd.getSymbolID()); 1691 //tg.set_VisibleModifiers(true); 1692 //set tg latlongs and pixels 1693 setClientCoords(milStd, tg); 1694 //build tg.Pixels 1695 tg.Pixels = clsUtility.LatLongToPixels(tg.LatLongs, ipc); 1696 1697 //int fillStyle = milStd.getPatternFillType(); 1698 Shape2 shape = new Shape2(shapeType); 1699 shape.setFillColor(fillColor); 1700 if (lineColor != null) { 1701 shape.setLineColor(lineColor); 1702 shape.setStroke(new BasicStroke(milStd.getLineWidth())); 1703 } 1704 //the client has already set the coordinates for the shape 1705 POINT2 pt; 1706 for (int j = 0; j < tg.Pixels.size(); j++) { 1707 pt = tg.Pixels.get(j); 1708 if (j == 0) { 1709 shape.moveTo(pt); 1710 } else { 1711 shape.lineTo(pt); 1712 } 1713 } 1714 1715 //post clip the shape and set the polylines 1716 ArrayList<Shape2> shapes = new ArrayList(); 1717 shapes.add(shape); 1718 //post-clip the shape 1719 if (clsUtilityCPOF.canClipPoints(tg) == false && clipBounds != null) { 1720 shapes = clsUtilityCPOF.postClipShapes(tg, shapes, clipBounds); 1721 } else if (clsUtilityCPOF.canClipPoints(tg) == false && clipPoints != null) { 1722 shapes = clsUtilityCPOF.postClipShapes(tg, shapes, clipPoints); 1723 } 1724 shape=shapes.get(0); 1725 if (hatch > 1) 1726 { 1727 shape = clsUtility.buildHatchArea(tg, shape, hatch, 20); 1728 shape.setLineColor(lineColor); 1729 shape.setStroke(new BasicStroke(1)); 1730 //shapes.clear(); 1731 shapes.add(shape); 1732 } 1733 ArrayList<ShapeInfo> shapeInfos = new ArrayList(); 1734 Shape2ToShapeInfo(shapeInfos, shapes); 1735 //set the shapeInfo polylines 1736 if (clipBounds != null) { 1737 clsUtilityGE.SetShapeInfosPolylines(tg, shapeInfos, clipBounds); 1738 } else if (clipPoints != null) { 1739 clsUtilityGE.SetShapeInfosPolylines(tg, shapeInfos, clipPoints); 1740 } else if (clipArea == null) { 1741 clsUtilityGE.SetShapeInfosPolylines(tg, shapeInfos, null); 1742 } 1743 //set milStd symbol shapes 1744 if (milStd.getSymbolShapes() == null) { 1745 milStd.setSymbolShapes(shapeInfos); 1746 } else { 1747 milStd.getSymbolShapes().addAll(shapeInfos); 1748 } 1749 return; 1750 } catch (Exception exc) { 1751 ErrorLogger.LogException(_className, "render_Shape", 1752 new RendererException("Failed inside render_Shape", exc)); 1753 1754 } 1755 } 1756 1757 private static void resolvePostClippedShapes(TGLight tg, ArrayList<Shape2> shapes) { 1758 try { 1759 //resolve the PBS and BBS shape properties after the post clip, regardless whether they were clipped 1760 switch (tg.get_LineType()) { 1761 case TacticalLines.BBS_RECTANGLE: 1762 case TacticalLines.BBS_POINT: 1763 case TacticalLines.BBS_LINE: 1764 case TacticalLines.BBS_AREA: 1765 case TacticalLines.PBS_RECTANGLE: 1766 case TacticalLines.PBS_SQUARE: 1767 break; 1768 default: 1769 return; 1770 } 1771 Color fillColor = tg.get_FillColor(); 1772 shapes.get(0).setFillColor(fillColor); 1773 shapes.get(1).setFillColor(null); 1774 int fillStyle = tg.get_FillStyle(); 1775 shapes.get(0).set_Fillstyle(0); 1776 shapes.get(1).set_Fillstyle(fillStyle); 1777 return; 1778 1779 } catch (Exception exc) { 1780 ErrorLogger.LogException(_className, "resolvePostClippedShapes", 1781 new RendererException("Failed inside resolvePostClippedShapes", exc)); 1782 1783 } 1784 } 1785 1786 /** 1787 * set the clip rectangle as an arraylist or a Rectangle2D depending on the 1788 * object 1789 * 1790 * @param clipBounds 1791 * @param clipRect 1792 * @param clipArray 1793 * @return 1794 */ 1795 private static boolean setClip(Object clipBounds, Rectangle2D clipRect, ArrayList<Point2D> clipArray) { 1796 try { 1797 if (clipBounds == null) { 1798 return false; 1799 } else if (clipBounds.getClass().isAssignableFrom(Rectangle2D.Double.class)) { 1800 clipRect.setRect((Rectangle2D) clipBounds); 1801 } else if (clipBounds.getClass().isAssignableFrom(Rectangle2D.class)) { 1802 clipRect.setRect((Rectangle2D) clipBounds); 1803 } else if (clipBounds.getClass().isAssignableFrom(Rectangle.class)) { 1804 //clipRect.setRect((Rectangle2D)clipBounds); 1805 Rectangle rectx = (Rectangle) clipBounds; 1806 //clipBounds=new Rectangle2D.Double(rectx.x,rectx.y,rectx.width,rectx.height); 1807 clipRect.setRect(rectx.x, rectx.y, rectx.width, rectx.height); 1808 } else if (clipBounds.getClass().isAssignableFrom(ArrayList.class)) { 1809 clipArray.addAll((ArrayList) clipBounds); 1810 } 1811 } catch (Exception exc) { 1812 ErrorLogger.LogException(_className, "setClip", 1813 new RendererException("Failed inside setClip", exc)); 1814 1815 } 1816 return true; 1817 } 1818 1819 /** 1820 * public render function transferred from JavaLineArrayCPOF project. Use 1821 * this function to replicate CPOF renderer functionality. 1822 * 1823 * @param mss the milStdSymbol object 1824 * @param converter the geographic to pixels coordinate converter 1825 * @param clipBounds the pixels based clip bounds 1826 */ 1827 public static void render(MilStdSymbol mss, 1828 IPointConversion converter, 1829 Object clipBounds) { 1830 try { 1831 ArrayList<ShapeInfo> shapeInfos = new ArrayList(); 1832 ArrayList<ShapeInfo> modifierShapeInfos = new ArrayList(); 1833 render(mss, converter, shapeInfos, modifierShapeInfos, clipBounds); 1834 } catch (Exception exc) { 1835 ErrorLogger.LogException(_className, "render", 1836 new RendererException("render", exc)); 1837 1838 } 1839 } 1840 1841 /** 1842 * Generic tester button says Tiger or use JavaRendererSample. Generic 1843 * renderer testers: called by JavaRendererSample and TestJavaLineArray 1844 * public render function transferred from JavaLineArrayCPOF project. Use 1845 * this function to replicate CPOF renderer functionality. 1846 * 1847 * @param mss 1848 * @param converter geographic to pixels converter 1849 * @param shapeInfos ShapeInfo array 1850 * @param modifierShapeInfos modifier ShapeInfo array 1851 * @param clipBounds clip bounds 1852 */ 1853 public static void render(MilStdSymbol mss, 1854 IPointConversion converter, 1855 ArrayList<ShapeInfo> shapeInfos, 1856 ArrayList<ShapeInfo> modifierShapeInfos, 1857 Object clipBounds) { 1858 try { 1859 //boolean shiftLines = Channels.getShiftLines(); 1860 //end section 1861 1862 Rectangle2D clipRect = new Rectangle2D.Double(); 1863 ArrayList<Point2D> clipArray = new ArrayList(); 1864 setClip(clipBounds, clipRect, clipArray); 1865 1866 TGLight tg = createTGLightFromMilStdSymbol(mss, converter); 1867 reversePointsRevD(tg); 1868 CELineArray.setClient("generic"); 1869// if (shiftLines) { 1870// String affiliation = tg.get_Affiliation(); 1871// Channels.setAffiliation(affiliation); 1872// } 1873 //CELineArray.setMinLength(2.5); //2-27-2013 1874 1875 int linetype = tg.get_LineType(); 1876 //replace calls to MovePixels 1877 clsUtility.RemoveDuplicatePoints(tg); 1878 1879 BufferedImage bi = new BufferedImage(8, 8, BufferedImage.TYPE_INT_ARGB); 1880 Graphics2D g2d = bi.createGraphics(); 1881 g2d.setFont(tg.get_Font()); 1882 1883 clsUtilityCPOF.SegmentGeoPoints(tg, converter, 1); 1884 clsUtility.FilterAXADPoints(tg, converter); 1885 1886 //prevent vertical segments for oneway, twoway, alt 1887 armyc2.c5isr.JavaTacticalRenderer.clsUtility.FilterVerticalSegments(tg); 1888 boolean isChange1Area = armyc2.c5isr.JavaTacticalRenderer.clsUtility.IsChange1Area(linetype); 1889 boolean isTextFlipped = false; 1890 //for 3d change 1 symbols we do not transform the points 1891 1892 //if it is world view then we want to flip the far points about 1893 //the left and right sides to get two symbols 1894 ArrayList<POINT2> farLeftPixels = new ArrayList(); 1895 ArrayList<POINT2> farRightPixels = new ArrayList(); 1896 if (isChange1Area == false) { 1897 clsUtilityCPOF.GetFarPixels(tg, converter, farLeftPixels, farRightPixels); 1898 } 1899 1900 ArrayList<Shape2> shapesLeft = new ArrayList(); 1901 ArrayList<Shape2> shapesRight = new ArrayList(); 1902 ArrayList<Shape2> shapes = null; //use this to collect all the shapes 1903 1904 //CPOF 6.0 diagnostic 1905 ArrayList<Shape2> textSpecsLeft = null; 1906 ArrayList<Shape2> textSpecsRight = null; 1907 //Note: DisplayModifiers3 returns early if textSpecs are null 1908 textSpecsLeft = new ArrayList(); 1909 textSpecsRight = new ArrayList(); 1910 1911 if (farLeftPixels.size() > 0) { 1912 tg.Pixels = farLeftPixels; 1913 shapesLeft = clsRenderer2.GetLineArray(tg, converter, isTextFlipped, clipBounds); 1914 //CPOF 6.0 1915 //returns early if textSpecs are null 1916 Modifier2.DisplayModifiers2(tg, g2d, textSpecsLeft, isTextFlipped, null); 1917 } 1918 if (farRightPixels.size() > 0) { 1919 tg.Pixels = farRightPixels; 1920 shapesRight = clsRenderer2.GetLineArray(tg, converter, isTextFlipped, clipBounds); 1921 //CPOF 6.0 1922 //returns early if textSpecs are null 1923 Modifier2.DisplayModifiers2(tg, g2d, textSpecsRight, isTextFlipped, null); 1924 } 1925 1926 //CPOF 6.0 diagnostic 1927 ArrayList<Shape2> textSpecs = new ArrayList(); 1928 1929 if (shapesLeft.isEmpty() || shapesRight.isEmpty()) { 1930 ArrayList<Shape2> linesWithFillShapes = null; 1931 if (clipArray != null && !clipArray.isEmpty()) { 1932 linesWithFillShapes = clsClipQuad.LinesWithFill(tg, clipArray); 1933 } else if (clipRect != null && clipRect.getWidth() != 0) { 1934 linesWithFillShapes = clsClipPolygon2.LinesWithFill(tg, clipRect); 1935 } else { 1936 linesWithFillShapes = clsClipPolygon2.LinesWithFill(tg, null); 1937 } 1938 1939 //diagnostic: comment two lines if using the WW tester 1940 if (clsUtilityCPOF.canClipPoints(tg) && clipBounds != null) { 1941 if (clipArray != null && !clipArray.isEmpty()) { 1942 clsClipQuad.ClipPolygon(tg, clipArray); 1943 } else if (clipRect != null && clipRect.getWidth() != 0) { 1944 clsClipPolygon2.ClipPolygon(tg, clipRect); 1945 } 1946 1947 tg.LatLongs = clsUtility.PixelsToLatLong(tg.Pixels, converter); 1948 } 1949 1950 //diagnostic 1-28-13 1951 armyc2.c5isr.JavaTacticalRenderer.clsUtility.InterpolatePixels(tg); 1952 1953 tg.modifiers = new ArrayList(); 1954 Modifier2.AddModifiersGeo(tg, g2d, clipBounds, converter); 1955 1956 clsUtilityCPOF.FilterPoints2(tg, converter); 1957 clsUtilityCPOF.ClearPixelsStyle(tg); 1958 //add section to replace preceding line M. Deutch 11-4-2011 1959 ArrayList rangeFanFillShapes = null; 1960 //do not fill the original shapes for circular range fans 1961 int savefillStyle = tg.get_FillStyle(); 1962 if (linetype == TacticalLines.RANGE_FAN) { 1963 tg.set_Fillstyle(0); 1964 } 1965 1966 shapes = clsRenderer2.GetLineArray(tg, converter, isTextFlipped, clipBounds); 1967 1968 // Add Feint, decoy, or dummy indicator 1969 if (shapes != null 1970 && SymbolID.getSymbolSet(tg.get_SymbolId()) == SymbolID.SymbolSet_ControlMeasure 1971 && SymbolUtilities.hasFDI(tg.get_SymbolId())) { 1972 addFDI(tg, shapes); 1973 } 1974 1975 switch (linetype) { 1976 case TacticalLines.RANGE_FAN: 1977 case TacticalLines.RANGE_FAN_SECTOR: 1978 case TacticalLines.RADAR_SEARCH: 1979 if (tg.get_FillColor() == null || tg.get_FillColor().getAlpha() < 2) { 1980 break; 1981 } 1982 TGLight tg1 = clsUtilityCPOF.GetCircularRangeFanFillTG(tg); 1983 tg1.set_Fillstyle(savefillStyle); 1984 tg1.set_SymbolId(tg.get_SymbolId()); 1985 rangeFanFillShapes = clsRenderer2.GetLineArray(tg1, converter, isTextFlipped, clipBounds); 1986 1987 if (rangeFanFillShapes != null) { 1988 shapes.addAll(0, rangeFanFillShapes); 1989 } 1990 break; 1991 default: 1992 break; 1993 } 1994 1995 //undo any fillcolor for lines with fill 1996 clsUtilityCPOF.LinesWithSeparateFill(tg.get_LineType(), shapes); 1997 clsClipPolygon2.addAbatisFill(tg, shapes); 1998 1999 //if this line is commented then the extra line in testbed goes away 2000 if (shapes != null && linesWithFillShapes != null && linesWithFillShapes.size() > 0) { 2001 shapes.addAll(0, linesWithFillShapes); 2002 } 2003 2004 if (shapes != null && shapes.size() > 0) { 2005 Modifier2.DisplayModifiers2(tg, g2d, textSpecs, isTextFlipped, null); 2006 Shape2ToShapeInfo(modifierShapeInfos, textSpecs); 2007 mss.setModifierShapes(modifierShapeInfos); 2008 } 2009 } else //symbol was more than 180 degrees wide, use left and right symbols 2010 { 2011 shapes = shapesLeft; 2012 shapes.addAll(shapesRight); 2013 2014 if (textSpecs != null) { 2015 textSpecs.addAll(textSpecsLeft); 2016 textSpecs.addAll(textSpecsRight); 2017 } 2018 } 2019 //post-clip the points if the tg could not be pre-clipped 2020 if (clsUtilityCPOF.canClipPoints(tg) == false && clipBounds != null) { 2021 shapes = clsUtilityCPOF.postClipShapes(tg, shapes, clipBounds); 2022 } 2023 2024 Shape2ToShapeInfo(shapeInfos, shapes); 2025 clsUtility.addHatchFills(tg, shapeInfos); 2026 mss.setSymbolShapes(shapeInfos); 2027 } catch (Exception exc) { 2028 ErrorLogger.LogException(_className, "render", 2029 new RendererException("Failed inside render", exc)); 2030 2031 } 2032 } 2033 2034 public static int getCMLineType(int version, int entityCode) { 2035 // Check if line type is specific to a version 2036 if (version >= SymbolID.Version_2525Ech1) { 2037 switch (entityCode) { 2038 // Added in 2525Ech1 2039 case 152600: 2040 return TacticalLines.AREA_DEFENSE; 2041 case 152700: 2042 return TacticalLines.FRONTAL_ATTACK; 2043 case 152900: 2044 return TacticalLines.TURNING_MOVEMENT; 2045 case 152800: 2046 return TacticalLines.MOBILE_DEFENSE; 2047 case 242800: 2048 return TacticalLines.KILL_ZONE; 2049 case 342900: 2050 return TacticalLines.MOVEMENT_TO_CONTACT; 2051 case 343100: 2052 return TacticalLines.EXPLOIT; 2053 case 343300: 2054 return TacticalLines.DEMONSTRATE; 2055 case 343500: 2056 return TacticalLines.ENVELOPMENT; 2057 case 343800: 2058 return TacticalLines.INFILTRATION; 2059 case 344000: 2060 return TacticalLines.PURSUIT; 2061 case 344400: 2062 return TacticalLines.DISENGAGE; 2063 case 344500: 2064 return TacticalLines.EVACUATE; 2065 case 344700: 2066 return TacticalLines.TURN; 2067 // Updated in 2525Ech1 2068 case 172000: 2069 return TacticalLines.WFZ; 2070 // Removed in 2525Ech1 2071 case 240804: 2072 return -1; 2073 } 2074 } 2075 if (version >= SymbolID.Version_2525E) { 2076 switch (entityCode) { 2077 // Added in 2525E 2078 case 110400: 2079 return TacticalLines.GENERIC_LINE; 2080 case 120700: 2081 return TacticalLines.GENERIC_AREA; 2082 case 141800: 2083 return TacticalLines.HOL; 2084 case 141900: 2085 return TacticalLines.BHL; 2086 case 310800: 2087 return TacticalLines.CSA; 2088 case 330500: 2089 return TacticalLines.ROUTE; 2090 case 330501: 2091 return TacticalLines.ROUTE_ONEWAY; 2092 case 330502: 2093 return TacticalLines.ROUTE_ALT; 2094 case 344100: 2095 return TacticalLines.FPOL; 2096 case 344200: 2097 return TacticalLines.RPOL; 2098 // Updated in 2525E 2099 case 120500: 2100 return TacticalLines.BASE_CAMP; 2101 case 120600: 2102 return TacticalLines.GUERILLA_BASE; 2103 case 151000: 2104 return TacticalLines.FORT; 2105 case 260400: 2106 return TacticalLines.BCL; 2107 case 310100: 2108 return TacticalLines.DHA; 2109 // Updated in 2525Ech1 2110 case 172000: 2111 return TacticalLines.WFZ_REVD; 2112 } 2113 } else { // 2525Dchange 1 and older 2114 switch (entityCode) { 2115 // Updated in 2525E 2116 case 120500: 2117 return TacticalLines.BASE_CAMP_REVD; 2118 case 120600: 2119 return TacticalLines.GUERILLA_BASE_REVD; 2120 case 151000: 2121 return TacticalLines.FORT_REVD; 2122 case 260400: 2123 return TacticalLines.BCL_REVD; 2124 case 310100: 2125 return TacticalLines.DHA_REVD; 2126 // Removed in 2525E 2127 case 150300: 2128 return TacticalLines.ASSY; 2129 case 241601: 2130 return TacticalLines.SENSOR; 2131 case 241602: 2132 return TacticalLines.SENSOR_RECTANGULAR; 2133 case 241603: 2134 return TacticalLines.SENSOR_CIRCULAR; 2135 // Updated in 2525Ech1 2136 case 172000: 2137 return TacticalLines.WFZ_REVD; 2138 } 2139 } 2140 // Line type isn't specific to a version or doesn't exist 2141 switch (entityCode) { 2142 case 200101: 2143 return TacticalLines.LAUNCH_AREA; 2144 case 200201: 2145 return TacticalLines.DEFENDED_AREA_CIRCULAR; 2146 case 200202: 2147 return TacticalLines.DEFENDED_AREA_RECTANGULAR; 2148 case 120100: 2149 return TacticalLines.AO; 2150 case 120200: 2151 return TacticalLines.NAI; 2152 case 120300: 2153 return TacticalLines.TAI; 2154 case 120400: 2155 return TacticalLines.AIRFIELD; 2156 case 151401: 2157 return TacticalLines.AIRAOA; 2158 case 151402: 2159 return TacticalLines.AAAAA; 2160 case 151403: 2161 return TacticalLines.MAIN; 2162 case 151404: 2163 return TacticalLines.SPT; 2164 case 110100: 2165 return TacticalLines.BOUNDARY; 2166 case 110200: 2167 return TacticalLines.LL; 2168 case 110300: 2169 return TacticalLines.EWL; 2170 case 140100: 2171 return TacticalLines.FLOT; 2172 case 140200: 2173 return TacticalLines.LC; 2174 case 140300: 2175 return TacticalLines.PL; 2176 case 140400: 2177 return TacticalLines.FEBA; 2178 case 140500: 2179 return TacticalLines.PDF; 2180 case 140601: 2181 return TacticalLines.DIRATKAIR; 2182 case 140602: 2183 return TacticalLines.DIRATKGND; 2184 case 140603: 2185 return TacticalLines.DIRATKSPT; 2186 case 140700: 2187 return TacticalLines.FCL; 2188 case 140800: 2189 return TacticalLines.IL; 2190 case 140900: 2191 return TacticalLines.LOA; 2192 case 141000: 2193 return TacticalLines.LOD; 2194 case 141100: 2195 return TacticalLines.LDLC; 2196 case 141200: 2197 return TacticalLines.PLD; 2198 case 150200: 2199 return TacticalLines.ASSY; 2200 case 150100: 2201 return TacticalLines.GENERAL; 2202 case 150501: 2203 return TacticalLines.JTAA; 2204 case 150502: 2205 return TacticalLines.SAA; 2206 case 150503: 2207 return TacticalLines.SGAA; 2208 case 150600: //dz no eny 2209 return TacticalLines.DZ; 2210 case 150700: //ez no eny 2211 return TacticalLines.EZ; 2212 case 150800: //lz no eny 2213 return TacticalLines.LZ; 2214 case 150900: //pz no eny 2215 return TacticalLines.PZ; 2216 case 151100: 2217 return TacticalLines.LAA; 2218 case 151200: 2219 return TacticalLines.BATTLE; 2220 case 151202: 2221 return TacticalLines.PNO; 2222 case 151204: 2223 return TacticalLines.CONTAIN; 2224 case 151205: 2225 return TacticalLines.RETAIN; 2226 case 151300: 2227 return TacticalLines.EA; 2228 case 151203: 2229 return TacticalLines.STRONG; 2230 case 151500: 2231 return TacticalLines.ASSAULT; 2232 case 151600: 2233 return TacticalLines.ATKPOS; 2234 case 151700: 2235 return TacticalLines.OBJ; 2236 case 151800: 2237 return TacticalLines.ENCIRCLE; 2238 case 151900: 2239 return TacticalLines.PEN; 2240 case 152000: 2241 return TacticalLines.ATKBYFIRE; 2242 case 152100: 2243 return TacticalLines.SPTBYFIRE; 2244 case 152200: 2245 return TacticalLines.SARA; 2246 case 141300: 2247 return TacticalLines.AIRHEAD; 2248 case 141400: 2249 return TacticalLines.BRDGHD; 2250 case 141500: 2251 return TacticalLines.HOLD; 2252 case 141600: 2253 return TacticalLines.RELEASE; 2254 case 141700: 2255 return TacticalLines.AMBUSH; 2256 case 170100: 2257 return TacticalLines.AC; 2258 case 170200: 2259 return TacticalLines.LLTR; 2260 case 170300: 2261 return TacticalLines.MRR; 2262 case 170400: 2263 return TacticalLines.SL; 2264 case 170500: 2265 return TacticalLines.SAAFR; 2266 case 170600: 2267 return TacticalLines.TC; 2268 case 170700: 2269 return TacticalLines.SC; 2270 case 170800: 2271 return TacticalLines.BDZ; 2272 case 170900: 2273 return TacticalLines.HIDACZ; 2274 case 171000: 2275 return TacticalLines.ROZ; 2276 case 171100: 2277 return TacticalLines.AARROZ; 2278 case 171200: 2279 return TacticalLines.UAROZ; 2280 case 171300: 2281 return TacticalLines.WEZ; 2282 case 171400: 2283 return TacticalLines.FEZ; 2284 case 171500: 2285 return TacticalLines.JEZ; 2286 case 171600: 2287 return TacticalLines.MEZ; 2288 case 171700: 2289 return TacticalLines.LOMEZ; 2290 case 171800: 2291 return TacticalLines.HIMEZ; 2292 case 171900: 2293 return TacticalLines.FAADZ; 2294 case 200401: 2295 return TacticalLines.SHIP_AOI_CIRCULAR; 2296 case 240804: 2297 return TacticalLines.RECTANGULAR_TARGET; 2298 case 220100: 2299 return TacticalLines.BEARING; 2300 case 220101: 2301 return TacticalLines.ELECTRO; 2302 case 220102: //EW //new label 2303 return TacticalLines.BEARING_EW; 2304 case 220103: 2305 return TacticalLines.ACOUSTIC; 2306 case 220104: 2307 return TacticalLines.ACOUSTIC_AMB; 2308 case 220105: 2309 return TacticalLines.TORPEDO; 2310 case 220106: 2311 return TacticalLines.OPTICAL; 2312 case 218400: 2313 return TacticalLines.NAVIGATION; 2314 case 220107: //Jammer //new label 2315 return TacticalLines.BEARING_J; 2316 case 220108: //RDF //new label 2317 return TacticalLines.BEARING_RDF; 2318 case 240101: 2319 return TacticalLines.ACA; 2320 case 240102: 2321 return TacticalLines.ACA_RECTANGULAR; 2322 case 240103: 2323 return TacticalLines.ACA_CIRCULAR; 2324 2325 case 240201: 2326 return TacticalLines.FFA; 2327 case 240202: 2328 return TacticalLines.FFA_RECTANGULAR; 2329 case 240203: 2330 return TacticalLines.FFA_CIRCULAR; 2331 2332 case 240301: 2333 return TacticalLines.NFA; 2334 case 240302: 2335 return TacticalLines.NFA_RECTANGULAR; 2336 case 240303: 2337 return TacticalLines.NFA_CIRCULAR; 2338 2339 case 240401: 2340 return TacticalLines.RFA; 2341 case 240402: 2342 return TacticalLines.RFA_RECTANGULAR; 2343 case 240403: 2344 return TacticalLines.RFA_CIRCULAR; 2345 case 240503: 2346 return TacticalLines.PAA; 2347 case 240501: 2348 return TacticalLines.PAA_RECTANGULAR; 2349 case 240502: 2350 return TacticalLines.PAA_CIRCULAR; 2351 case 260100: 2352 return TacticalLines.FSCL; 2353 case 300100: 2354 return TacticalLines.ICL; 2355 case 190100: 2356 return TacticalLines.IFF_OFF; 2357 case 190200: 2358 return TacticalLines.IFF_ON; 2359 case 260200: 2360 return TacticalLines.CFL; 2361 case 260300: 2362 return TacticalLines.NFL; 2363 case 260500: 2364 return TacticalLines.RFL; 2365 case 260600: 2366 return TacticalLines.MFP; 2367 case 240701: 2368 return TacticalLines.LINTGT; 2369 case 240702: 2370 return TacticalLines.LINTGTS; 2371 case 240703: 2372 return TacticalLines.FPF; 2373 case 240801: 2374 return TacticalLines.AT; 2375 case 240802: 2376 return TacticalLines.RECTANGULAR; 2377 case 240803: 2378 return TacticalLines.CIRCULAR; 2379 case 240805: 2380 return TacticalLines.SERIES; 2381 case 240806: 2382 return TacticalLines.SMOKE; 2383 case 240808: 2384 return TacticalLines.BOMB; 2385 case 241001: 2386 return TacticalLines.FSA; 2387 case 241002: 2388 return TacticalLines.FSA_RECTANGULAR; 2389 case 200402: 2390 return TacticalLines.SHIP_AOI_RECTANGULAR; 2391 case 200600: 2392 return TacticalLines.CUED_ACQUISITION; 2393 case 200700: 2394 return TacticalLines.RADAR_SEARCH; 2395 case 241003: 2396 return TacticalLines.FSA_CIRCULAR; 2397 case 200300: 2398 return TacticalLines.NOTACK; 2399 case 241101: 2400 return TacticalLines.ATI; 2401 case 241102: 2402 return TacticalLines.ATI_RECTANGULAR; 2403 case 241103: 2404 return TacticalLines.ATI_CIRCULAR; 2405 case 241201: 2406 return TacticalLines.CFFZ; 2407 case 241202: 2408 return TacticalLines.CFFZ_RECTANGULAR; 2409 case 241203: 2410 return TacticalLines.CFFZ_CIRCULAR; 2411 case 241301: 2412 return TacticalLines.CENSOR; 2413 case 241302: 2414 return TacticalLines.CENSOR_RECTANGULAR; 2415 case 241303: 2416 return TacticalLines.CENSOR_CIRCULAR; 2417 case 241401: 2418 return TacticalLines.CFZ; 2419 case 241402: 2420 return TacticalLines.CFZ_RECTANGULAR; 2421 case 241403: 2422 return TacticalLines.CFZ_CIRCULAR; 2423 case 241501: 2424 return TacticalLines.DA; 2425 case 241502: 2426 return TacticalLines.DA_RECTANGULAR; 2427 case 241503: 2428 return TacticalLines.DA_CIRCULAR; 2429 case 241701: 2430 return TacticalLines.TBA; 2431 case 241702: 2432 return TacticalLines.TBA_RECTANGULAR; 2433 case 241703: 2434 return TacticalLines.TBA_CIRCULAR; 2435 case 241801: 2436 return TacticalLines.TVAR; 2437 case 241802: 2438 return TacticalLines.TVAR_RECTANGULAR; 2439 case 241803: 2440 return TacticalLines.TVAR_CIRCULAR; 2441 case 241901: 2442 return TacticalLines.ZOR; 2443 case 241902: 2444 return TacticalLines.ZOR_RECTANGULAR; 2445 case 241903: 2446 return TacticalLines.ZOR_CIRCULAR; 2447 case 242000: 2448 return TacticalLines.TGMF; 2449 case 242100: 2450 return TacticalLines.RANGE_FAN; 2451 case 242200: 2452 return TacticalLines.RANGE_FAN_SECTOR; 2453 case 242301: 2454 return TacticalLines.KILLBOXBLUE; 2455 case 242302: 2456 return TacticalLines.KILLBOXBLUE_RECTANGULAR; 2457 case 242303: 2458 return TacticalLines.KILLBOXBLUE_CIRCULAR; 2459 case 242304: 2460 return TacticalLines.KILLBOXPURPLE; 2461 case 242305: 2462 return TacticalLines.KILLBOXPURPLE_RECTANGULAR; 2463 case 242306: 2464 return TacticalLines.KILLBOXPURPLE_CIRCULAR; 2465 case 270100: 2466 case 270200: 2467 return TacticalLines.ZONE; 2468 case 270300: 2469 return TacticalLines.OBSFAREA; 2470 case 270400: 2471 return TacticalLines.OBSAREA; 2472 case 270501: 2473 return TacticalLines.MNFLDBLK; 2474 case 270502: 2475 return TacticalLines.MNFLDDIS; 2476 case 270503: 2477 return TacticalLines.MNFLDFIX; 2478 case 270504: 2479 return TacticalLines.TURN_REVD; 2480 case 270601: 2481 return TacticalLines.EASY; 2482 case 270602: 2483 return TacticalLines.BYDIF; 2484 case 270603: 2485 return TacticalLines.BYIMP; 2486 case 271100: 2487 return TacticalLines.GAP; 2488 case 271201: 2489 return TacticalLines.PLANNED; 2490 case 271202: 2491 return TacticalLines.ESR1; 2492 case 271203: 2493 return TacticalLines.ESR2; 2494 case 271204: 2495 return TacticalLines.ROADBLK; 2496 case 280100: 2497 return TacticalLines.ABATIS; 2498 case 290100: 2499 return TacticalLines.LINE; 2500 case 290201: 2501 return TacticalLines.ATDITCH; 2502 case 290202: 2503 return TacticalLines.ATDITCHC; 2504 case 290203: 2505 return TacticalLines.ATDITCHM; 2506 case 290204: 2507 return TacticalLines.ATWALL; 2508 case 290301: 2509 return TacticalLines.UNSP; 2510 case 290302: 2511 return TacticalLines.SFENCE; 2512 case 290303: 2513 return TacticalLines.DFENCE; 2514 case 290304: 2515 return TacticalLines.DOUBLEA; 2516 case 290305: 2517 return TacticalLines.LWFENCE; 2518 case 290306: 2519 return TacticalLines.HWFENCE; 2520 case 290307: 2521 return TacticalLines.SINGLEC; 2522 case 290308: 2523 return TacticalLines.DOUBLEC; 2524 case 290309: 2525 return TacticalLines.TRIPLE; 2526 case 290600: 2527 return TacticalLines.MFLANE; 2528 case 270707: 2529 return TacticalLines.DEPICT; 2530 case 270800: 2531 return TacticalLines.MINED; 2532 case 270801: 2533 return TacticalLines.FENCED; 2534 case 290101: 2535 return TacticalLines.MINE_LINE; 2536 case 271000: 2537 return TacticalLines.UXO; 2538 case 271700: 2539 return TacticalLines.BIO; 2540 case 271800: 2541 return TacticalLines.CHEM; 2542 case 271900: 2543 return TacticalLines.NUC; 2544 case 272000: 2545 return TacticalLines.RAD; 2546 case 290400: 2547 return TacticalLines.CLUSTER; 2548 case 290500: 2549 return TacticalLines.TRIP; 2550 case 282003: 2551 return TacticalLines.OVERHEAD_WIRE; 2552 case 271300: 2553 return TacticalLines.ASLTXING; 2554 case 271500: 2555 return TacticalLines.FORDSITE; 2556 case 271600: 2557 return TacticalLines.FORDIF; 2558 case 290700: 2559 return TacticalLines.FERRY; 2560 case 290800: 2561 return TacticalLines.RAFT; 2562 case 290900: 2563 return TacticalLines.FORTL; 2564 case 291000: 2565 return TacticalLines.FOXHOLE; 2566 case 272100: 2567 return TacticalLines.MSDZ; 2568 case 272200: 2569 return TacticalLines.DRCL; 2570 2571 case 310200: 2572 return TacticalLines.EPW; 2573 case 310300: 2574 return TacticalLines.FARP; 2575 case 310400: 2576 return TacticalLines.RHA; 2577 case 310500: 2578 return TacticalLines.RSA; 2579 case 310600: 2580 return TacticalLines.BSA; 2581 case 310700: 2582 return TacticalLines.DSA; 2583 case 330100: 2584 return TacticalLines.CONVOY; 2585 case 330200: 2586 return TacticalLines.HCONVOY; 2587 case 330300: 2588 return TacticalLines.MSR; 2589 case 330301: 2590 return TacticalLines.MSR_ONEWAY; 2591 case 330401: 2592 return TacticalLines.ASR_ONEWAY; 2593 case 330302: 2594 return TacticalLines.MSR_TWOWAY; 2595 case 330402: 2596 return TacticalLines.ASR_TWOWAY; 2597 case 330303: 2598 return TacticalLines.MSR_ALT; 2599 case 330403: 2600 return TacticalLines.ASR_ALT; 2601 2602 case 330400: 2603 return TacticalLines.ASR; 2604 2605 case 340100: 2606 return TacticalLines.BLOCK; 2607 case 340200: 2608 return TacticalLines.BREACH; 2609 case 340300: 2610 return TacticalLines.BYPASS; 2611 case 340400: 2612 return TacticalLines.CANALIZE; 2613 case 340500: 2614 return TacticalLines.CLEAR; 2615 case 340600: 2616 return TacticalLines.CATK; 2617 case 340700: 2618 return TacticalLines.CATKBYFIRE; 2619 2620 case 340800: 2621 return TacticalLines.DELAY; 2622 case 341000: 2623 return TacticalLines.DISRUPT; 2624 case 341100: 2625 return TacticalLines.FIX; 2626 case 341200: 2627 return TacticalLines.FOLLA; 2628 case 341300: 2629 return TacticalLines.FOLSP; 2630 case 341500: 2631 return TacticalLines.ISOLATE; 2632 case 341700: 2633 return TacticalLines.OCCUPY; 2634 case 341800: 2635 return TacticalLines.PENETRATE; 2636 case 341900: 2637 return TacticalLines.RIP; 2638 case 342000: 2639 return TacticalLines.RETIRE; 2640 case 342100: 2641 return TacticalLines.SECURE; 2642 case 342201: 2643 return TacticalLines.COVER; 2644 case 342202: 2645 return TacticalLines.GUARD; 2646 case 342203: 2647 return TacticalLines.SCREEN; 2648 case 342300: 2649 return TacticalLines.SEIZE; 2650 case 342400: 2651 return TacticalLines.WITHDRAW; 2652 case 342500: 2653 return TacticalLines.WDRAWUP; 2654 case 342600: 2655 return TacticalLines.CORDONKNOCK; 2656 case 342700: 2657 return TacticalLines.CORDONSEARCH; 2658 case 272101: 2659 return TacticalLines.STRIKWARN; 2660 default: 2661 break; 2662 } 2663 return -1; 2664 } 2665 2666 /** 2667 * Some symbol's points are reversed when moving from 2525C to 2525D. This method should be called at the start of each render. 2668 * 2669 * It's a simpler fix to reverse the points order at start than to reverse order when rendering. 2670 * 2671 * Note: Make sure to only call once to not reverse reversed points 2672 * @param tg 2673 */ 2674 private static void reversePointsRevD(TGLight tg) { 2675 try { 2676 if (tg.get_SymbolId().length() < 20 || SymbolID.getSymbolSet(tg.get_SymbolId()) != 25) { 2677 return; 2678 } 2679 switch (tg.get_LineType()) { 2680 case TacticalLines.UNSP: 2681 case TacticalLines.LWFENCE: 2682 case TacticalLines.HWFENCE: 2683 case TacticalLines.SINGLEC: 2684 case TacticalLines.DOUBLEC: 2685 case TacticalLines.TRIPLE: 2686 case TacticalLines.LINE: 2687 if (tg.Pixels != null) { 2688 Collections.reverse(tg.Pixels); 2689 } 2690 if (tg.LatLongs != null) { 2691 Collections.reverse(tg.LatLongs); 2692 } 2693 break; 2694 case TacticalLines.CLUSTER: 2695 if (SymbolID.getVersion(tg.get_SymbolId()) < SymbolID.Version_2525E) { 2696 if (tg.Pixels != null) { 2697 Collections.reverse(tg.Pixels); 2698 } 2699 if (tg.LatLongs != null) { 2700 Collections.reverse(tg.LatLongs); 2701 } 2702 } 2703 break; 2704 default: 2705 break; 2706 } 2707 } catch (Exception exc) { 2708 ErrorLogger.LogException("clsRenderer", "reversePointsRevD", 2709 new RendererException("Failed inside reversePointsRevD", exc)); 2710 } 2711 } 2712}