001package armyc2.c5isr.web.render.utilities; 002 003import armyc2.c5isr.renderer.utilities.MilStdAttributes; 004import armyc2.c5isr.graphics2d.Point2D; 005import armyc2.c5isr.renderer.utilities.Modifiers; 006 007import java.io.PrintWriter; 008import java.io.StringWriter; 009import java.io.Writer; 010import java.util.HashMap; 011import java.util.Locale; 012import java.util.Map; 013 014/** 015 * 016* 017 */ 018@SuppressWarnings("unused") 019public class JavaRendererUtilities { 020 021 public static final String HOSTILE_FILL_COLOR = "FFFF8080"; 022 public static final String FRIENDLY_FILL_COLOR = "FF80E0FF"; 023 public static final String NEUTRAL_FILL_COLOR = "FFAAFFAA"; 024 public static final String UNKNOWN_FILL_COLOR = "FFFFFF80"; 025 026 /** 027 * Converts ARGB string format to the Google used ABGR string format. Google 028 * reverses the blue and red positioning. 029 * 030 * @param rgbString A color string of the format AARRGGBB in hex value. 031 * @return the reverse of the input string in hex. The format should now be 032 * AABBGGRR 033 */ 034 public static String ARGBtoABGR(String rgbString) { 035 if(rgbString.length()==6) 036 { 037 String s="FF"; 038 rgbString=s.concat(rgbString); 039 } 040 041 String bgrString = rgbString.toUpperCase(Locale.US); 042 043 if(rgbString.length() == 8) 044 { 045 char[] c = rgbString.toCharArray(); 046 char temp1 = c[2]; 047 char temp2 = c[3]; 048 c[2] = c[6]; 049 c[3] = c[7]; 050 c[6] = temp1; 051 c[7] = temp2; 052 bgrString = new String(c); 053 } 054 else if(rgbString.length() == 6) 055 { 056 char[] c = rgbString.toCharArray(); 057 char temp1 = c[0]; 058 char temp2 = c[1]; 059 c[0] = c[4]; 060 c[1] = c[5]; 061 c[4] = temp1; 062 c[5] = temp2; 063 bgrString = "FF" + new String(c); 064 //bgrString = "FF" + bgrString; 065 } 066 else 067 { 068 System.err.println("JavaRendererUtilties.ARGBtoABGR(): " + "\"" + String.valueOf(rgbString) + "\" is not a 6 or 8 character String in the format of RRGGBB or AARRGGBB"); 069 } 070 071 return bgrString; 072 } 073 074 /** 075 * Returns a symbolId with just the identifiable symbol Id pieces. All 076 * variable information is returned as '*'. For example, a boundary, 077 * "GFGPGLB----KUSX" returns "G*G*GLB---****X"; 078 * 079 * @param symbolCode A 15 character symbol ID. 080 * @return The normalized SymbolCode. 081 * @deprecated 082 */ 083 public static String normalizeSymbolCode(String symbolCode) { 084 085 String newSymbolCode = symbolCode; 086 087 if (symbolCode.startsWith("G") || symbolCode.startsWith("S")) { 088 // Remove Affiliation 089 newSymbolCode = newSymbolCode.substring(0, 1) + '*' + newSymbolCode.substring(2); 090 // Remove planned/present field 091 newSymbolCode = newSymbolCode.substring(0, 3) + '*' + newSymbolCode.substring(4); 092 // Remove echelon, special code and country codes 093 newSymbolCode = newSymbolCode.substring(0, 10) + "****" + newSymbolCode.substring(14); 094 } 095 096 // If a unit replace last character with *. 097 if (symbolCode.startsWith("S")) { 098 newSymbolCode = newSymbolCode.substring(0, 14) + '*'; 099 } 100 101 return newSymbolCode; 102 } 103 104 public static void addAltModeToModifiersString(Map<String,String> attributes, String altMode) 105 { 106 if(altMode.equals("relativeToGround")) 107 attributes.put(MilStdAttributes.AltitudeMode, "AGL"); 108 else if(altMode.equals("absolute")) 109 attributes.put(MilStdAttributes.AltitudeMode, "AMSL"); 110 } 111 112 /** 113 * 114 * @param SymbolInfo something like 115 * "SymbolID?LineColor=0x000000&FillColor=0xFFFFFF&size=35" 116 */ 117 public static Map<String, String> createParameterMapFromURL(String SymbolInfo) { 118 Map<String, String> modifiers = new HashMap<String, String>(); 119 String symbolID = null; 120 String parameters = null; 121 String key = null; 122 String value = null; 123 String arrParameters[] = null; 124 String arrKeyValue[] = null; 125 String temp = null; 126 int questionIndex = SymbolInfo.lastIndexOf('?'); 127 128 try { 129 if (questionIndex == -1) { 130 symbolID = java.net.URLDecoder.decode(SymbolInfo, "UTF-8"); 131 } else { 132 symbolID = java.net.URLDecoder.decode(SymbolInfo.substring(0, questionIndex), "UTF-8"); 133 } 134 135 } catch (Exception exc) { 136 System.err.println("Error parsing SymbolID"); 137 System.err.println(exc.getMessage()); 138 } 139 140 try { //build a map for the other createMilstdSymbol function to use 141 //to build a milstd symbol. 142 if (questionIndex > 0 && (questionIndex + 1 < SymbolInfo.length())) { 143 parameters = SymbolInfo.substring(questionIndex + 1, SymbolInfo.length()); 144 arrParameters = parameters.split("&"); 145 int n = arrParameters.length; 146 //for(int i = 0; i < arrParameters.length; i++) 147 for (int i = 0; i < n; i++) { 148 arrKeyValue = arrParameters[i].split("="); 149 if (arrKeyValue.length == 2 && arrKeyValue[1] != null && arrKeyValue[1].equals("") == false) { 150 151 key = arrKeyValue[0]; 152 value = arrKeyValue[1]; 153 154 temp = java.net.URLDecoder.decode(value, "UTF-8"); 155 modifiers.put(key.toUpperCase(), temp); 156 157 //System.out.println("key: " + key + " value: " + temp); 158 } 159 } 160 } 161 } catch (Exception exc) { 162 System.err.println("Error parsing \"" + key.toUpperCase() + "\" parameter from URL"); 163 System.err.println(exc.getMessage()); 164 } 165 return modifiers; 166 } 167 168 /* 169 * Try to turn a bad code into something renderable. 170 * 171 * @param symbolID 172 * @return 173 * @deprecated use SymbolUtilties.reconcileSymbolID() 9/5/2013 174 */ 175 /*public static String ReconcileSymbolID(String symbolID) { 176 StringBuilder sb = new StringBuilder(""); 177 char codingScheme = symbolID.charAt(0); 178 179 if (symbolID.length() < 15) { 180 while (symbolID.length() < 15) { 181 symbolID += "-"; 182 } 183 } 184 if (symbolID.length() > 15) { 185 symbolID = symbolID.substring(0, 14); 186 } 187 188 if (symbolID != null && symbolID.length() == 15) { 189 if (codingScheme == 'S' || //warfighting 190 codingScheme == 'I' ||//sigint 191 codingScheme == 'O' ||//stability operation 192 codingScheme == 'E')//emergency management 193 { 194 sb.append(codingScheme); 195 196 if (SymbolUtilities.hasValidAffiliation(symbolID) == false) { 197 sb.append('U'); 198 } else { 199 sb.append(symbolID.charAt(1)); 200 } 201 202 if (SymbolUtilities.hasValidBattleDimension(symbolID) == false) { 203 sb.append('Z'); 204 sb.replace(0, 1, "S"); 205 } else { 206 sb.append(symbolID.charAt(2)); 207 } 208 209 if (SymbolUtilities.hasValidStatus(symbolID) == false) { 210 sb.append('P'); 211 } else { 212 sb.append(symbolID.charAt(3)); 213 } 214 215 sb.append("------"); 216 sb.append(symbolID.substring(10, 15)); 217 218 } else if (codingScheme == 'G')//tactical 219 { 220 sb.append(codingScheme); 221 222 if (SymbolUtilities.hasValidAffiliation(symbolID) == false) { 223 sb.append('U'); 224 } else { 225 sb.append(symbolID.charAt(1)); 226 } 227 228 sb.append('G'); 229 230 if (SymbolUtilities.hasValidStatus(symbolID) == false) { 231 sb.append('P'); 232 } else { 233 sb.append(symbolID.charAt(3)); 234 } 235 236 sb.append("GPP---");//return an action point 237 sb.append(symbolID.substring(10, 15)); 238 239 } else if (codingScheme == 'W')//weather 240 {//no default weather graphic 241 return "SUZP-----------";//unknown 242 } else//bad codingScheme 243 { 244 sb.append('S'); 245 if (SymbolUtilities.hasValidAffiliation(symbolID) == false) { 246 sb.append('U'); 247 } else { 248 sb.append(symbolID.charAt(1)); 249 } 250 251 if (SymbolUtilities.hasValidBattleDimension(symbolID) == false) { 252 sb.append('Z'); 253 } else { 254 sb.append(symbolID.charAt(2)); 255 } 256 257 if (SymbolUtilities.hasValidStatus(symbolID) == false) { 258 sb.append('P'); 259 } else { 260 sb.append(symbolID.charAt(3)); 261 } 262 263 sb.append("------"); 264 sb.append(symbolID.substring(10, 15)); 265 } 266 } else { 267 return "SUZP-----------";//unknown 268 } 269 270 return sb.toString(); 271 272 }//*/ 273 274 /** 275 * Checks symbolID and if the relevant modifiers are present 276 * 277 * @param symbolCode 278 * @param modifiers 279 * @return 280 * @deprecated 281 */ 282 public static boolean is3dSymbol(String symbolCode, Map<String,String> modifiers) { 283 boolean returnValue = false; 284 285 try { 286 String symbolId = symbolCode.substring(4, 10); 287 288 if (symbolId.equals("ACAI--") || // Airspace Coordination Area Irregular 289 symbolId.equals("ACAR--") || // Airspace Coordination Area Rectangular 290 symbolId.equals("ACAC--") || // Airspace Coordination Area Circular 291 symbolId.equals("AKPC--") || // Kill box circular 292 symbolId.equals("AKPR--") || // Kill box rectangular 293 symbolId.equals("AKPI--") || // Kill box irregular 294 symbolId.equals("ALC---") || // Air corridor 295 symbolId.equals("ALM---") || // 296 symbolId.equals("ALS---") || // SAAFR 297 symbolId.equals("ALU---") || // UAV 298 symbolId.equals("ALL---") || // Low level transit route 299 symbolId.equals("AAR---") 300 || symbolId.equals("AAF---") 301 || symbolId.equals("AAH---") 302 || symbolId.equals("AAM---") || // MEZ 303 symbolId.equals("AAML--") || // LOMEZ 304 symbolId.equals("AAMH--")) { 305 306 try { 307 if (modifiers != null) { 308 309 // These guys store array values. Put in appropriate data strucutre 310 // for MilStdSymbol. 311 if (modifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)) { 312 String[] altitudes = modifiers.get(Modifiers.X_ALTITUDE_DEPTH).split(","); 313 if (altitudes.length < 2) { 314 returnValue = false; 315 } else { 316 returnValue = true; 317 } 318 } 319 320 } 321 } catch (Exception exc) { 322 System.err.println(exc.getMessage()); 323 } 324 } 325 } catch (Exception e) { 326 System.err.println(e.getMessage()); 327 } 328 return returnValue; 329 } 330 331 /** 332 * Determines if a String represents a valid number 333 * 334 * @param text 335 * @return "1.56" == true, "1ab" == false 336 */ 337 public static boolean isNumber(String text) { 338 if (text != null && text.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")) { 339 return true; 340 } else { 341 return false; 342 } 343 } 344 345 /** 346 * Takes a throwable and puts it's stacktrace into a string. 347 * 348 * @param thrown 349 * @return 350 */ 351 public static String getStackTrace(Throwable thrown) { 352 try { 353 Writer writer = new StringWriter(); 354 PrintWriter printWriter = new PrintWriter(writer); 355 thrown.printStackTrace(printWriter); 356 return writer.toString(); 357 } catch (Exception exc) { 358 //System.out.println("JavaRendererUtilties.getStackTrace()"); 359 //return "Error - couldn't retrieve stack trace"; 360 return ""; 361 } 362 } 363 364 public static Point2D getEndPointWithAngle(Point2D ptStart, 365 //Point2D pt1, 366 //Point2D pt2, 367 double angle, 368 double distance) { 369 double newX = 0; 370 double newY = 0; 371 Point2D pt = new Point2D.Double(); 372 try { 373 //first get the angle psi between pt0 and pt1 374 double psi = 0;//Math.atan((pt1.y - pt0.y) / (pt1.x - pt0.x)); 375 //double psi = Math.atan((ptStart.getY() - ptStart.getY()) / (ptStart.getX() - (ptStart.getX()+100))); 376 //convert alpha to radians 377 double alpha1 = Math.PI * angle / 180; 378 379 //theta is the angle of extension from the x axis 380 double theta = psi + alpha1; 381 //dx is the x extension from pt2 382 double dx = distance * Math.cos(theta); 383 //dy is the y extension form pt2 384 double dy = distance * Math.sin(theta); 385 newX = ptStart.getX() + dx; 386 newY = ptStart.getY() + dy; 387 388 pt.setLocation(newX, newY); 389 } catch (Exception exc) { 390 System.out.println(exc.getMessage()); 391 exc.printStackTrace(); 392 } 393 return pt; 394 } 395 396 /** 397 * 398 * @param latitude1 399 * @param longitude1 400 * @param latitude2 401 * @param longitude2 402 * @param unitOfMeasure meters, kilometers, miles, feet, yards, nautical, 403 * nautical miles. 404 * @return 405 */ 406 public static double measureDistance(double latitude1, double longitude1, double latitude2, double longitude2, String unitOfMeasure) { 407 // latitude1,latitude2 = latitude, longitude1,longitude2 = longitude 408 //Radius is 6378.1 (km), 3963.1 (mi), 3443.9 (nm 409 410 double distance = -1, 411 rad; 412 413 String uom = unitOfMeasure.toLowerCase(); 414 415 if (uom.equals("meters")) { 416 rad = 6378137; 417 } else if (uom.equals("kilometers")) { 418 rad = 6378.137; 419 } else if (uom.equals("miles")) { 420 rad = 3963.1; 421 } else if (uom.equals("feet")) { 422 rad = 20925524.9; 423 } else if (uom.equals("yards")) { 424 rad = 6975174.98; 425 } else if (uom.equals("nautical")) { 426 rad = 3443.9; 427 } else if (uom.equals("nautical miles")) { 428 rad = 3443.9; 429 } else { 430 return -1.0; 431 } 432 433 latitude1 = latitude1 * (Math.PI / 180); 434 latitude2 = latitude2 * (Math.PI / 180); 435 longitude1 = longitude1 * (Math.PI / 180); 436 longitude2 = longitude2 * (Math.PI / 180); 437 distance = (Math.acos(Math.cos(latitude1) * Math.cos(longitude1) * Math.cos(latitude2) * Math.cos(longitude2) + Math.cos(latitude1) * Math.sin(longitude1) * Math.cos(latitude2) * Math.sin(longitude2) + Math.sin(latitude1) * Math.sin(latitude2)) * rad); 438 439 return distance; 440 } 441}