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