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