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 private 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 private 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 private 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 private 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 clsRenderer.renderWithPolylines(mSymbol, ipc, rect); 731 } else { 732 clsRenderer.renderWithPolylines(mSymbol, ipc, bboxCoords); 733 } 734 735 shapes = mSymbol.getSymbolShapes(); 736 modifiers = mSymbol.getModifierShapes(); 737 738 if (format == WebRenderer.OUTPUT_FORMAT_JSON) { 739 jsonOutput.append("{\"type\":\"symbol\","); 740 jsonContent = JSONize(shapes, modifiers, ipc, true, normalize); 741 jsonOutput.append(jsonContent); 742 jsonOutput.append("}"); 743 } else if (format == WebRenderer.OUTPUT_FORMAT_KML) { 744 Color textColor = mSymbol.getTextColor(); 745 if(textColor==null) 746 textColor=mSymbol.getLineColor(); 747 748 jsonContent = KMLize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor); 749 jsonOutput.append(jsonContent); 750 } else if (format == WebRenderer.OUTPUT_FORMAT_GEOJSON) 751 { 752 jsonOutput.append("{\"type\":\"FeatureCollection\",\"features\":"); 753 jsonContent = GeoJSONize(shapes, modifiers, ipc, normalize, mSymbol.getTextColor(), mSymbol.getTextBackgroundColor()); 754 jsonOutput.append(jsonContent); 755 756 //moving meta data properties to the last feature with no coords as feature collection doesn't allow properties 757 jsonOutput.replace(jsonOutput.toString().length()-1,jsonOutput.toString().length(),"" ); 758 if (jsonContent.length() > 2) 759 jsonOutput.append(","); 760 jsonOutput.append("{\"type\": \"Feature\",\"geometry\": { \"type\": \"Polygon\",\"coordinates\": [ ]}"); 761 762 jsonOutput.append(",\"properties\":{\"id\":\""); 763 jsonOutput.append(id); 764 jsonOutput.append("\",\"name\":\""); 765 jsonOutput.append(name); 766 jsonOutput.append("\",\"description\":\""); 767 jsonOutput.append(description); 768 jsonOutput.append("\",\"symbolID\":\""); 769 jsonOutput.append(symbolCode); 770 jsonOutput.append("\",\"wasClipped\":\""); 771 jsonOutput.append(String.valueOf(mSymbol.get_WasClipped())); 772 //jsonOutput.append("\"}}"); 773 774 jsonOutput.append("\"}}]}"); 775 } else if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG) { 776 String textColor = mSymbol.getTextColor() != null ? RendererUtilities.colorToHexString(mSymbol.getTextColor(), false) : ""; 777 String backgroundColor = mSymbol.getTextBackgroundColor() != null ? RendererUtilities.colorToHexString(mSymbol.getTextBackgroundColor(), false) : ""; 778 //returns an svg with a geoTL and geoBR value to use to place the canvas on the map 779 jsonContent = MultiPointHandlerSVG.GeoSVGize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor, backgroundColor, mSymbol.get_WasClipped()); 780 jsonOutput.append(jsonContent); 781 } 782 } catch (Exception exc) { 783 String st = JavaRendererUtilities.getStackTrace(exc); 784 jsonOutput = new StringBuilder(); 785 jsonOutput.append("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + ": " + "- "); 786 jsonOutput.append(exc.getMessage() + " - "); 787 jsonOutput.append(st); 788 jsonOutput.append("\"}"); 789 790 ErrorLogger.LogException("MultiPointHandler", "RenderSymbol", exc); 791 } 792 793 boolean debug = false; 794 if (debug == true) { 795 System.out.println("Symbol Code: " + symbolCode); 796 System.out.println("Scale: " + scale); 797 System.out.println("BBOX: " + bbox); 798 if (controlPoints != null) { 799 System.out.println("Geo Points: " + controlPoints); 800 } 801 if (tgl != null && tgl.get_Pixels() != null)//pixels != null 802 { 803 System.out.println("Pixel: " + tgl.get_Pixels().toString()); 804 } 805 if (bbox != null) { 806 System.out.println("geo bounds: " + bbox); 807 } 808 if (rect != null) { 809 System.out.println("pixel bounds: " + rect.toString()); 810 } 811 if (jsonOutput != null) { 812 System.out.println(jsonOutput.toString()); 813 } 814 } 815 816 ErrorLogger.LogMessage("MultiPointHandler", "RenderSymbol()", "exit RenderSymbol", Level.FINER); 817 return jsonOutput.toString(); 818 819 } 820 821 /** 822 * 823 * @param id 824 * @param name 825 * @param description 826 * @param symbolCode 827 * @param controlPoints 828 * @param scale 829 * @param bbox 830 * @param symbolModifiers 831 * @param symbolAttributes 832 * @return 833 */ 834 public static MilStdSymbol RenderSymbolAsMilStdSymbol(String id, 835 String name, 836 String description, 837 String symbolCode, 838 String controlPoints, 839 Double scale, 840 String bbox, 841 Map<String,String> symbolModifiers, 842 Map<String,String> symbolAttributes)//, 843 //ArrayList<ShapeInfo>shapes) 844 { 845 MilStdSymbol mSymbol = null; 846 //System.out.println("MultiPointHandler.RenderSymbol()"); 847 boolean normalize = true; 848 Double controlLat = 0.0; 849 Double controlLong = 0.0; 850 //String jsonContent = ""; 851 852 Rectangle rect = null; 853 854 //for symbol & line fill 855 ArrayList<POINT2> tgPoints = null; 856 857 String[] coordinates = controlPoints.split(" "); 858 TGLight tgl = new TGLight(); 859 ArrayList<ShapeInfo> shapes = null;//new ArrayList<ShapeInfo>(); 860 ArrayList<ShapeInfo> modifiers = null;//new ArrayList<ShapeInfo>(); 861 //ArrayList<Point2D> pixels = new ArrayList<Point2D>(); 862 ArrayList<Point2D> geoCoords = new ArrayList<Point2D>(); 863 int len = coordinates.length; 864 865 IPointConversion ipc = null; 866 867 //Deutch moved section 6-29-11 868 Double left = 0.0; 869 Double right = 0.0; 870 Double top = 0.0; 871 Double bottom = 0.0; 872 Point2D temp = null; 873 Point2D ptGeoUL = null; 874 int width = 0; 875 int height = 0; 876 int leftX = 0; 877 int topY = 0; 878 int bottomY = 0; 879 int rightX = 0; 880 int j = 0; 881 ArrayList<Point2D> bboxCoords = null; 882 if (bbox != null && bbox.equals("") == false) { 883 String[] bounds = null; 884 if (bbox.contains(" "))//trapezoid 885 { 886 bboxCoords = new ArrayList<Point2D>(); 887 double x = 0; 888 double y = 0; 889 String[] coords = bbox.split(" "); 890 String[] arrCoord; 891 for (String coord : coords) { 892 arrCoord = coord.split(","); 893 x = Double.valueOf(arrCoord[0]); 894 y = Double.valueOf(arrCoord[1]); 895 bboxCoords.add(new Point2D.Double(x, y)); 896 } 897 //use the upper left corner of the MBR containing geoCoords 898 //to set the converter 899 ptGeoUL = getGeoUL(bboxCoords); 900 left = ptGeoUL.getX(); 901 top = ptGeoUL.getY(); 902 ipc = new PointConverter(left, top, scale); 903 Point2D ptPixels = null; 904 Point2D ptGeo = null; 905 int n = bboxCoords.size(); 906 //for (j = 0; j < bboxCoords.size(); j++) 907 for (j = 0; j < n; j++) { 908 ptGeo = bboxCoords.get(j); 909 ptPixels = ipc.GeoToPixels(ptGeo); 910 x = ptPixels.getX(); 911 y = ptPixels.getY(); 912 if (x < 20) { 913 x = 20; 914 } 915 if (y < 20) { 916 y = 20; 917 } 918 ptPixels.setLocation(x, y); 919 //end section 920 bboxCoords.set(j, (Point2D) ptPixels); 921 } 922 } else//rectangle 923 { 924 bounds = bbox.split(","); 925 left = Double.valueOf(bounds[0]); 926 right = Double.valueOf(bounds[2]); 927 top = Double.valueOf(bounds[3]); 928 bottom = Double.valueOf(bounds[1]); 929 scale = getReasonableScale(bbox, scale); 930 ipc = new PointConverter(left, top, scale); 931 } 932 933 Point2D pt2d = null; 934 if (bboxCoords == null) { 935 pt2d = new Point2D.Double(left, top); 936 temp = ipc.GeoToPixels(pt2d); 937 938 leftX = (int) temp.getX(); 939 topY = (int) temp.getY(); 940 941 pt2d = new Point2D.Double(right, bottom); 942 temp = ipc.GeoToPixels(pt2d); 943 944 bottomY = (int) temp.getY(); 945 rightX = (int) temp.getX(); 946 //diagnostic clipping does not work for large scales 947// if (scale > 10e6) { 948// //get widest point in the AOI 949// double midLat = 0; 950// if (bottom < 0 && top > 0) { 951// midLat = 0; 952// } else if (bottom < 0 && top < 0) { 953// midLat = top; 954// } else if (bottom > 0 && top > 0) { 955// midLat = bottom; 956// } 957// 958// temp = ipc.GeoToPixels(new Point2D.Double(right, midLat)); 959// rightX = (int) temp.getX(); 960// } 961 //end section 962 963 width = (int) Math.abs(rightX - leftX); 964 height = (int) Math.abs(bottomY - topY); 965 966 if(width==0 || height==0) 967 rect=null; 968 else 969 rect = new Rectangle(leftX, topY, width, height); 970 } 971 } else { 972 rect = null; 973 } 974 //end section 975 976 //check for required points & parameters 977 String symbolIsValid = canRenderMultiPoint(symbolCode, symbolModifiers, len); 978 if (!symbolIsValid.equals("true")) { 979 ErrorLogger.LogMessage("MultiPointHandler", "RenderSymbolAsMilStdSymbol", symbolIsValid, Level.WARNING); 980 return mSymbol; 981 } 982 983 if (MSLookup.getInstance().getMSLInfo(symbolCode).getDrawRule() != DrawRules.AREA10) // AREA10 can support infinite points 984 len = Math.min(len, MSLookup.getInstance().getMSLInfo(symbolCode).getMaxPointCount()); 985 for (int i = 0; i < len; i++) { 986 String[] coordPair = coordinates[i].split(","); 987 Double latitude = Double.valueOf(coordPair[1].trim()); 988 Double longitude = Double.valueOf(coordPair[0].trim()); 989 geoCoords.add(new Point2D.Double(longitude, latitude)); 990 } 991 if (ipc == null) { 992 Point2D ptCoordsUL = getGeoUL(geoCoords); 993 ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale); 994 } 995 //if (crossesIDL(geoCoords) == true) 996// if(Math.abs(right-left)>180) 997// { 998// normalize = true; 999// ((PointConverter)ipc).set_normalize(true); 1000// } 1001// else { 1002// normalize = false; 1003// ((PointConverter)ipc).set_normalize(false); 1004// } 1005 1006 //seems to work ok at world view 1007// if (normalize) { 1008// NormalizeGECoordsToGEExtents(0, 360, geoCoords); 1009// } 1010 1011 //M. Deutch 10-3-11 1012 //must shift the rect pixels to synch with the new ipc 1013 //the old ipc was in synch with the bbox, so rect x,y was always 0,0 1014 //the new ipc synchs with the upper left of the geocoords so the boox is shifted 1015 //and therefore the clipping rectangle must shift by the delta x,y between 1016 //the upper left corner of the original bbox and the upper left corner of the geocoords 1017 ArrayList<Point2D> geoCoords2 = new ArrayList<Point2D>(); 1018 geoCoords2.add(new Point2D.Double(left, top)); 1019 geoCoords2.add(new Point2D.Double(right, bottom)); 1020 1021// if (normalize) { 1022// NormalizeGECoordsToGEExtents(0, 360, geoCoords2); 1023// } 1024 1025 //disable clipping 1026 if (ShouldClipSymbol(symbolCode) == false) 1027 if(crossesIDL(geoCoords)==false) 1028 { 1029 rect = null; 1030 bboxCoords=null; 1031 } 1032 tgl.set_SymbolId(symbolCode);// "GFGPSLA---****X" AMBUSH symbol code 1033 tgl.set_Pixels(null); 1034 1035 try { 1036 1037 String fillColor = null; 1038 mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null); 1039 1040// mSymbol.setUseDashArray(true); 1041 1042 if (symbolModifiers != null || symbolAttributes != null) { 1043 populateModifiers(symbolModifiers, symbolAttributes, mSymbol); 1044 } else { 1045 mSymbol.setFillColor(null); 1046 } 1047 1048 if (mSymbol.getFillColor() != null) { 1049 Color fc = mSymbol.getFillColor(); 1050 //fillColor = Integer.toHexString(fc.getRGB()); 1051 fillColor = Integer.toHexString(fc.toARGB()); 1052 } 1053 1054 if (bboxCoords == null) { 1055 clsRenderer.renderWithPolylines(mSymbol, ipc, rect); 1056 } else { 1057 clsRenderer.renderWithPolylines(mSymbol, ipc, bboxCoords); 1058 } 1059 shapes = mSymbol.getSymbolShapes(); 1060 modifiers = mSymbol.getModifierShapes(); 1061 1062 //convert points//////////////////////////////////////////////////// 1063 ArrayList<ArrayList<Point2D>> polylines = null; 1064 ArrayList<ArrayList<Point2D>> newPolylines = null; 1065 ArrayList<Point2D> newLine = null; 1066 for (ShapeInfo shape : shapes) { 1067 polylines = shape.getPolylines(); 1068 //System.out.println("pixel polylines: " + String.valueOf(polylines)); 1069 newPolylines = ConvertPolylinePixelsToCoords(polylines, ipc, normalize); 1070 shape.setPolylines(newPolylines); 1071 } 1072 1073 for (ShapeInfo label : modifiers) { 1074 Point2D pixelCoord = label.getModifierPosition(); 1075 if (pixelCoord == null) { 1076 pixelCoord = label.getGlyphPosition(); 1077 } 1078 Point2D geoCoord = ipc.PixelsToGeo(pixelCoord); 1079 1080 if (normalize) { 1081 geoCoord = NormalizeCoordToGECoord(geoCoord); 1082 } 1083 1084 double latitude = geoCoord.getY(); 1085 double longitude = geoCoord.getX(); 1086 label.setModifierPosition(new Point2D.Double(longitude, latitude)); 1087 1088 } 1089 1090 //////////////////////////////////////////////////////////////////// 1091 mSymbol.setModifierShapes(modifiers); 1092 mSymbol.setSymbolShapes(shapes); 1093 1094 } catch (Exception exc) { 1095 System.out.println(exc.getMessage()); 1096 System.out.println("Symbol Code: " + symbolCode); 1097 exc.printStackTrace(); 1098 } 1099 1100 boolean debug = false; 1101 if (debug == true) { 1102 System.out.println("Symbol Code: " + symbolCode); 1103 System.out.println("Scale: " + scale); 1104 System.out.println("BBOX: " + bbox); 1105 if (controlPoints != null) { 1106 System.out.println("Geo Points: " + controlPoints); 1107 } 1108 if (tgl != null && tgl.get_Pixels() != null)//pixels != null 1109 { 1110 //System.out.println("Pixel: " + pixels.toString()); 1111 System.out.println("Pixel: " + tgl.get_Pixels().toString()); 1112 } 1113 if (bbox != null) { 1114 System.out.println("geo bounds: " + bbox); 1115 } 1116 if (rect != null) { 1117 System.out.println("pixel bounds: " + rect.toString()); 1118 } 1119 } 1120 1121 return mSymbol; 1122 1123 } 1124 1125 private static ArrayList<ArrayList<Point2D>> ConvertPolylinePixelsToCoords(ArrayList<ArrayList<Point2D>> polylines, IPointConversion ipc, Boolean normalize) { 1126 ArrayList<ArrayList<Point2D>> newPolylines = new ArrayList<ArrayList<Point2D>>(); 1127 1128 double latitude = 0; 1129 double longitude = 0; 1130 ArrayList<Point2D> newLine = null; 1131 try { 1132 for (ArrayList<Point2D> line : polylines) { 1133 newLine = new ArrayList<Point2D>(); 1134 for (Point2D pt : line) { 1135 Point2D geoCoord = ipc.PixelsToGeo(pt); 1136 1137 if (normalize) { 1138 geoCoord = NormalizeCoordToGECoord(geoCoord); 1139 } 1140 1141 latitude = geoCoord.getY(); 1142 longitude = geoCoord.getX(); 1143 newLine.add(new Point2D.Double(longitude, latitude)); 1144 } 1145 newPolylines.add(newLine); 1146 } 1147 } catch (Exception exc) { 1148 System.out.println(exc.getMessage()); 1149 exc.printStackTrace(); 1150 } 1151 return newPolylines; 1152 } 1153 1154 /** 1155 * Multipoint Rendering on flat 2D maps 1156 * 1157 * @param id A unique ID for the symbol. only used in KML currently 1158 * @param name 1159 * @param description 1160 * @param symbolCode 1161 * @param controlPoints 1162 * @param pixelWidth pixel dimensions of the viewable map area 1163 * @param pixelHeight pixel dimensions of the viewable map area 1164 * @param bbox The viewable area of the map. Passed in the format of a 1165 * string "lowerLeftX,lowerLeftY,upperRightX,upperRightY." example: 1166 * "-50.4,23.6,-42.2,24.2" 1167 * @param symbolModifiers Modifier with multiple values should be comma 1168 * delimited 1169 * @param symbolAttributes 1170 * @param format An enumeration: 0 for KML, 1 for JSON. 1171 * @return A JSON or KML string representation of the graphic. 1172 */ 1173 public static String RenderSymbol2D(String id, 1174 String name, 1175 String description, 1176 String symbolCode, 1177 String controlPoints, 1178 int pixelWidth, 1179 int pixelHeight, 1180 String bbox, 1181 Map<String,String> symbolModifiers, 1182 Map<String,String> symbolAttributes, 1183 int format) { 1184 StringBuilder jsonOutput = new StringBuilder(); 1185 String jsonContent = ""; 1186 1187 Rectangle rect = null; 1188 1189 ArrayList<POINT2> tgPoints = null; 1190 1191 String[] coordinates = controlPoints.split(" "); 1192 TGLight tgl = new TGLight(); 1193 ArrayList<ShapeInfo> shapes = new ArrayList<ShapeInfo>(); 1194 ArrayList<ShapeInfo> modifiers = new ArrayList<ShapeInfo>(); 1195 ArrayList<Point2D> geoCoords = new ArrayList<Point2D>(); 1196 int len = coordinates.length; 1197 IPointConversion ipc = null; 1198 1199 //check for required points & parameters 1200 String symbolIsValid = canRenderMultiPoint(symbolCode, symbolModifiers, len); 1201 if (!symbolIsValid.equals("true")) { 1202 String ErrorOutput = ""; 1203 ErrorOutput += ("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + " - ID: " + id + " - "); 1204 ErrorOutput += symbolIsValid; //reason for error 1205 ErrorOutput += ("\"}"); 1206 ErrorLogger.LogMessage("MultiPointHandler", "RenderSymbol2D", symbolIsValid, Level.WARNING); 1207 return ErrorOutput; 1208 } 1209 1210 Double left = 0.0; 1211 Double right = 0.0; 1212 Double top = 0.0; 1213 Double bottom = 0.0; 1214 if (bbox != null && bbox.equals("") == false) { 1215 String[] bounds = bbox.split(","); 1216 1217 left = Double.valueOf(bounds[0]).doubleValue(); 1218 right = Double.valueOf(bounds[2]).doubleValue(); 1219 top = Double.valueOf(bounds[3]).doubleValue(); 1220 bottom = Double.valueOf(bounds[1]).doubleValue(); 1221 1222 ipc = new PointConversion(pixelWidth, pixelHeight, top, left, bottom, right); 1223 } else { 1224 System.out.println("Bad bbox value: " + bbox); 1225 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\""); 1226 return "ERROR - Bad bbox value: " + bbox; 1227 } 1228 //end section 1229 1230 //get coordinates 1231 if (MSLookup.getInstance().getMSLInfo(symbolCode).getDrawRule() != DrawRules.AREA10) // AREA10 can support infinite points 1232 len = Math.min(len, MSLookup.getInstance().getMSLInfo(symbolCode).getMaxPointCount()); 1233 for (int i = 0; i < len; i++) { 1234 String[] coordPair = coordinates[i].split(","); 1235 Double latitude = Double.valueOf(coordPair[1].trim()).doubleValue(); 1236 Double longitude = Double.valueOf(coordPair[0].trim()).doubleValue(); 1237 geoCoords.add(new Point2D.Double(longitude, latitude)); 1238 } 1239 1240 try { 1241 MilStdSymbol mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null); 1242 1243 if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG){ 1244 // Use dash array and hatch pattern fill for SVG output 1245 symbolAttributes.put(MilStdAttributes.UseDashArray, "true"); 1246 symbolAttributes.put(MilStdAttributes.UsePatternFill, "true"); 1247 } 1248 1249 if (symbolModifiers != null && symbolModifiers.equals("") == false) { 1250 populateModifiers(symbolModifiers, symbolAttributes, mSymbol); 1251 } else { 1252 mSymbol.setFillColor(null); 1253 } 1254 1255 //build clipping bounds 1256 Point2D temp = null; 1257 int leftX; 1258 int topY; 1259 int bottomY; 1260 int rightX; 1261 int width; 1262 int height; 1263 boolean normalize = false; 1264// if(Math.abs(right-left)>180) 1265// { 1266// ((PointConversion)ipc).set_normalize(true); 1267// normalize=true; 1268// } 1269// else 1270// { 1271// ((PointConversion)ipc).set_normalize(false); 1272// } 1273 if (ShouldClipSymbol(symbolCode) || crossesIDL(geoCoords)) 1274 { 1275 Point2D lt=new Point2D.Double(left,top); 1276 //temp = ipc.GeoToPixels(new Point2D.Double(left, top)); 1277 temp = ipc.GeoToPixels(lt); 1278 leftX = (int) temp.getX(); 1279 topY = (int) temp.getY(); 1280 1281 Point2D rb=new Point2D.Double(right,bottom); 1282 //temp = ipc.GeoToPixels(new Point2D.Double(right, bottom)); 1283 temp = ipc.GeoToPixels(rb); 1284 bottomY = (int) temp.getY(); 1285 rightX = (int) temp.getX(); 1286 ////////////////// 1287 1288 width = (int) Math.abs(rightX - leftX); 1289 height = (int) Math.abs(bottomY - topY); 1290 1291 rect = new Rectangle(leftX, topY, width, height); 1292 } 1293 1294 //new interface 1295 //IMultiPointRenderer mpr = MultiPointRenderer.getInstance(); 1296 clsRenderer.renderWithPolylines(mSymbol, ipc, rect); 1297 shapes = mSymbol.getSymbolShapes(); 1298 modifiers = mSymbol.getModifierShapes(); 1299 1300 //boolean normalize = false; 1301 1302 if (format == WebRenderer.OUTPUT_FORMAT_JSON) { 1303 jsonOutput.append("{\"type\":\"symbol\","); 1304 //jsonContent = JSONize(shapes, modifiers, ipc, normalize); 1305 jsonOutput.append(jsonContent); 1306 jsonOutput.append("}"); 1307 } else if (format == WebRenderer.OUTPUT_FORMAT_KML) { 1308 Color textColor = mSymbol.getTextColor(); 1309 if(textColor==null) 1310 textColor=mSymbol.getLineColor(); 1311 1312 jsonContent = KMLize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor); 1313 jsonOutput.append(jsonContent); 1314 } else if (format == WebRenderer.OUTPUT_FORMAT_GEOJSON) { 1315 jsonOutput.append("{\"type\":\"FeatureCollection\",\"features\":"); 1316 jsonContent = GeoJSONize(shapes, modifiers, ipc, normalize, mSymbol.getTextColor(), mSymbol.getTextBackgroundColor()); 1317 jsonOutput.append(jsonContent); 1318 1319 //moving meta data properties to the last feature with no coords as feature collection doesn't allow properties 1320 jsonOutput.replace(jsonOutput.toString().length()-1,jsonOutput.toString().length(),"" ); 1321 if (jsonContent.length() > 2) 1322 jsonOutput.append(","); 1323 jsonOutput.append("{\"type\": \"Feature\",\"geometry\": { \"type\": \"Polygon\",\"coordinates\": [ ]}"); 1324 1325 jsonOutput.append(",\"properties\":{\"id\":\""); 1326 jsonOutput.append(id); 1327 jsonOutput.append("\",\"name\":\""); 1328 jsonOutput.append(name); 1329 jsonOutput.append("\",\"description\":\""); 1330 jsonOutput.append(description); 1331 jsonOutput.append("\",\"symbolID\":\""); 1332 jsonOutput.append(symbolCode); 1333 jsonOutput.append("\",\"wasClipped\":\""); 1334 jsonOutput.append(String.valueOf(mSymbol.get_WasClipped())); 1335 //jsonOutput.append("\"}}"); 1336 1337 jsonOutput.append("\"}}]}"); 1338 1339 } else if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG) { 1340 String textColor = mSymbol.getTextColor() != null ? RendererUtilities.colorToHexString(mSymbol.getTextColor(), false) : ""; 1341 String backgroundColor = mSymbol.getTextBackgroundColor() != null ? RendererUtilities.colorToHexString(mSymbol.getTextBackgroundColor(), false) : ""; 1342 //returns an svg with a geoTL and geoBR value to use to place the canvas on the map 1343 jsonContent = MultiPointHandlerSVG.GeoSVGize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor, backgroundColor, mSymbol.get_WasClipped()); 1344 jsonOutput.append(jsonContent); 1345 } 1346 } catch (Exception exc) { 1347 jsonOutput = new StringBuilder(); 1348 jsonOutput.append("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + ": " + "- "); 1349 jsonOutput.append(exc.getMessage() + " - "); 1350 jsonOutput.append(ErrorLogger.getStackTrace(exc)); 1351 jsonOutput.append("\"}"); 1352 } 1353 1354 boolean debug = false; 1355 if (debug == true) { 1356 System.out.println("Symbol Code: " + symbolCode); 1357 System.out.println("BBOX: " + bbox); 1358 if (controlPoints != null) { 1359 System.out.println("Geo Points: " + controlPoints); 1360 } 1361 if (tgl != null && tgl.get_Pixels() != null)//pixels != null 1362 { 1363 //System.out.println("Pixel: " + pixels.toString()); 1364 System.out.println("Pixel: " + tgl.get_Pixels().toString()); 1365 } 1366 if (bbox != null) { 1367 System.out.println("geo bounds: " + bbox); 1368 } 1369 if (rect != null) { 1370 System.out.println("pixel bounds: " + rect.toString()); 1371 } 1372 if (jsonOutput != null) { 1373 System.out.println(jsonOutput.toString()); 1374 } 1375 } 1376 1377 return jsonOutput.toString(); 1378 1379 } 1380 1381 /** 1382 * For Mike Deutch testing 1383 * 1384 * @param id 1385 * @param name 1386 * @param description 1387 * @param symbolCode 1388 * @param controlPoints 1389 * @param pixelWidth 1390 * @param pixelHeight 1391 * @param bbox 1392 * @param symbolModifiers 1393 * @param shapes 1394 * @param modifiers 1395 * @param format 1396 * @return 1397 * @deprecated 1398 */ 1399 public static String RenderSymbol2DX(String id, 1400 String name, 1401 String description, 1402 String symbolCode, 1403 String controlPoints, 1404 int pixelWidth, 1405 int pixelHeight, 1406 String bbox, 1407 Map<String,String> symbolModifiers, 1408 Map<String,String> symbolAttributes, 1409 ArrayList<ShapeInfo> shapes, 1410 ArrayList<ShapeInfo> modifiers, 1411 int format)//, 1412 //ArrayList<ShapeInfo>shapes) 1413 { 1414 1415 StringBuilder jsonOutput = new StringBuilder(); 1416 String jsonContent = ""; 1417 1418 Rectangle rect = null; 1419 1420 String[] coordinates = controlPoints.split(" "); 1421 TGLight tgl = new TGLight(); 1422 ArrayList<Point2D> geoCoords = new ArrayList<Point2D>(); 1423 IPointConversion ipc = null; 1424 1425 Double left = 0.0; 1426 Double right = 0.0; 1427 Double top = 0.0; 1428 Double bottom = 0.0; 1429 if (bbox != null && bbox.equals("") == false) { 1430 String[] bounds = bbox.split(","); 1431 1432 left = Double.valueOf(bounds[0]).doubleValue(); 1433 right = Double.valueOf(bounds[2]).doubleValue(); 1434 top = Double.valueOf(bounds[3]).doubleValue(); 1435 bottom = Double.valueOf(bounds[1]).doubleValue(); 1436 1437 ipc = new PointConversion(pixelWidth, pixelHeight, top, left, bottom, right); 1438 } else { 1439 System.out.println("Bad bbox value: " + bbox); 1440 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\""); 1441 return "ERROR - Bad bbox value: " + bbox; 1442 } 1443 //end section 1444 1445 //get coordinates 1446 int len = coordinates.length; 1447 for (int i = 0; i < len; i++) { 1448 String[] coordPair = coordinates[i].split(","); 1449 Double latitude = Double.valueOf(coordPair[1].trim()).doubleValue(); 1450 Double longitude = Double.valueOf(coordPair[0].trim()).doubleValue(); 1451 geoCoords.add(new Point2D.Double(longitude, latitude)); 1452 } 1453 1454 try { 1455 MilStdSymbol mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null); 1456 1457 if (symbolModifiers != null && symbolModifiers.equals("") == false) { 1458 populateModifiers(symbolModifiers, symbolAttributes, mSymbol); 1459 } else { 1460 mSymbol.setFillColor(null); 1461 } 1462 1463 clsRenderer.renderWithPolylines(mSymbol, ipc, rect); 1464 shapes = mSymbol.getSymbolShapes(); 1465 modifiers = mSymbol.getModifierShapes(); 1466 1467 boolean normalize = false; 1468 1469 if (format == WebRenderer.OUTPUT_FORMAT_JSON) { 1470 jsonOutput.append("{\"type\":\"symbol\","); 1471 jsonContent = JSONize(shapes, modifiers, ipc, false, normalize); 1472 jsonOutput.append(jsonContent); 1473 jsonOutput.append("}"); 1474 } 1475 1476 } catch (Exception exc) { 1477 jsonOutput = new StringBuilder(); 1478 jsonOutput.append("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + ": " + "- "); 1479 jsonOutput.append(exc.getMessage() + " - "); 1480 jsonOutput.append("\"}"); 1481 } 1482 1483 boolean debug = true; 1484 if (debug == true) { 1485 System.out.println("Symbol Code: " + symbolCode); 1486 System.out.println("BBOX: " + bbox); 1487 if (controlPoints != null) { 1488 System.out.println("Geo Points: " + controlPoints); 1489 } 1490 if (tgl != null && tgl.get_Pixels() != null)//pixels != null 1491 { 1492 //System.out.println("Pixel: " + pixels.toString()); 1493 System.out.println("Pixel: " + tgl.get_Pixels().toString()); 1494 } 1495 if (bbox != null) { 1496 System.out.println("geo bounds: " + bbox); 1497 } 1498 if (rect != null) { 1499 System.out.println("pixel bounds: " + rect.toString()); 1500 } 1501 if (jsonOutput != null) { 1502 System.out.println(jsonOutput.toString()); 1503 } 1504 } 1505 return jsonOutput.toString(); 1506 1507 } 1508 1509 private static SymbolInfo MilStdSymbolToSymbolInfo(MilStdSymbol symbol) { 1510 SymbolInfo si = null; 1511 1512 ArrayList<TextInfo> tiList = new ArrayList<TextInfo>(); 1513 ArrayList<LineInfo> liList = new ArrayList<LineInfo>(); 1514 1515 TextInfo tiTemp = null; 1516 LineInfo liTemp = null; 1517 ShapeInfo siTemp = null; 1518 1519 ArrayList<ShapeInfo> lines = symbol.getSymbolShapes(); 1520 ArrayList<ShapeInfo> modifiers = symbol.getModifierShapes(); 1521 1522 int lineCount = lines.size(); 1523 int modifierCount = modifiers.size(); 1524 for (int i = 0; i < lineCount; i++) { 1525 siTemp = lines.get(i); 1526 if (siTemp.getPolylines() != null) { 1527 liTemp = new LineInfo(); 1528 liTemp.setFillColor(siTemp.getFillColor()); 1529 liTemp.setLineColor(siTemp.getLineColor()); 1530 liTemp.setPolylines(siTemp.getPolylines()); 1531 liTemp.setStroke(siTemp.getStroke()); 1532 liList.add(liTemp); 1533 } 1534 } 1535 1536 for (int j = 0; j < modifierCount; j++) { 1537 tiTemp = new TextInfo(); 1538 siTemp = modifiers.get(j); 1539 if (siTemp.getModifierString() != null) { 1540 tiTemp.setModifierString(siTemp.getModifierString()); 1541 tiTemp.setModifierStringPosition(siTemp.getModifierPosition()); 1542 tiTemp.setModifierStringAngle(siTemp.getModifierAngle()); 1543 tiList.add(tiTemp); 1544 } 1545 } 1546 si = new SymbolInfo(tiList, liList); 1547 return si; 1548 } 1549 1550 /** 1551 * Populates a symbol with the modifiers from a JSON string. This function 1552 * will overwrite any previously populated modifier data. 1553 * 1554 * 1555 * 1556 * @param symbol An existing MilStdSymbol 1557 * @return 1558 */ 1559 private static boolean populateModifiers(Map<String,String> saModifiers, Map<String,String> saAttributes, MilStdSymbol symbol) { 1560 Map<String,String> modifiers = new HashMap<>(); 1561 Map<String,String> attributes = new HashMap<>(); 1562 saAttributes.putAll(attributes); 1563 1564 // Stores array graphic modifiers for MilStdSymbol; 1565 ArrayList<Double> altitudes = null; 1566 ArrayList<Double> azimuths = null; 1567 ArrayList<Double> distances = null; 1568 1569 // Stores colors for symbol. 1570 String fillColor = null; 1571 String lineColor = null; 1572 String textColor = null; 1573 String textBackgroundColor = null; 1574 1575 int lineWidth = 0; 1576 String altMode = null; 1577 boolean useDashArray = symbol.getUseDashArray(); 1578 boolean usePatternFill = symbol.getUseFillPattern(); 1579 int patternFillType = 0; 1580 boolean hideOptionalLabels = false; 1581 DistanceUnit distanceUnit = null; 1582 DistanceUnit altitudeUnit = null; 1583 int pixelSize = 100; 1584 boolean keepUnitRatio = true; 1585 double patternScale = RendererSettings.getInstance().getPatternScale(); 1586 1587 try { 1588 1589 // The following attirubtes are labels. All of them 1590 // are strings and can be added on the creation of the 1591 // MilStdSymbol by adding to a Map and passing in the 1592 // modifiers parameter. 1593 if (saModifiers != null) { 1594 if (saModifiers.containsKey(Modifiers.C_QUANTITY)) { 1595 modifiers.put(Modifiers.C_QUANTITY, String.valueOf(saModifiers.get(Modifiers.C_QUANTITY))); 1596 } 1597 1598 if (saModifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) { 1599 modifiers.put(Modifiers.H_ADDITIONAL_INFO_1, String.valueOf(saModifiers.get(Modifiers.H_ADDITIONAL_INFO_1))); 1600 } 1601 1602 if (saModifiers.containsKey(Modifiers.H1_ADDITIONAL_INFO_2)) { 1603 modifiers.put(Modifiers.H1_ADDITIONAL_INFO_2, String.valueOf(saModifiers.get(Modifiers.H1_ADDITIONAL_INFO_2))); 1604 } 1605 1606 if (saModifiers.containsKey(Modifiers.H2_ADDITIONAL_INFO_3)) { 1607 modifiers.put(Modifiers.H2_ADDITIONAL_INFO_3, String.valueOf(saModifiers.get(Modifiers.H2_ADDITIONAL_INFO_3))); 1608 } 1609 1610 if (saModifiers.containsKey(Modifiers.N_HOSTILE)) { 1611 if (saModifiers.get(Modifiers.N_HOSTILE) == null) { 1612 modifiers.put(Modifiers.N_HOSTILE, ""); 1613 } else { 1614 modifiers.put(Modifiers.N_HOSTILE, String.valueOf(saModifiers.get(Modifiers.N_HOSTILE))); 1615 } 1616 } 1617 1618 if (saModifiers.containsKey(Modifiers.Q_DIRECTION_OF_MOVEMENT)) { 1619 modifiers.put(Modifiers.Q_DIRECTION_OF_MOVEMENT, String.valueOf(saModifiers.get(Modifiers.Q_DIRECTION_OF_MOVEMENT))); 1620 } 1621 1622 if (saModifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) { 1623 modifiers.put(Modifiers.T_UNIQUE_DESIGNATION_1, String.valueOf(saModifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1))); 1624 } 1625 1626 if (saModifiers.containsKey(Modifiers.T1_UNIQUE_DESIGNATION_2)) { 1627 modifiers.put(Modifiers.T1_UNIQUE_DESIGNATION_2, String.valueOf(saModifiers.get(Modifiers.T1_UNIQUE_DESIGNATION_2))); 1628 } 1629 1630 if (saModifiers.containsKey(Modifiers.V_EQUIP_TYPE)) { 1631 modifiers.put(Modifiers.V_EQUIP_TYPE, String.valueOf(saModifiers.get(Modifiers.V_EQUIP_TYPE))); 1632 } 1633 1634 if (saModifiers.containsKey(Modifiers.AS_COUNTRY)) { 1635 modifiers.put(Modifiers.AS_COUNTRY, String.valueOf(saModifiers.get(Modifiers.AS_COUNTRY))); 1636 } else if (SymbolID.getCountryCode(symbol.getSymbolID()) > 0 && !GENCLookup.getInstance().get3CharCode(SymbolID.getCountryCode(symbol.getSymbolID())).equals("")) { 1637 modifiers.put(Modifiers.AS_COUNTRY, GENCLookup.getInstance().get3CharCode(SymbolID.getCountryCode(symbol.getSymbolID()))); 1638 } 1639 1640 if (saModifiers.containsKey(Modifiers.AP_TARGET_NUMBER)) { 1641 modifiers.put(Modifiers.AP_TARGET_NUMBER, String.valueOf(saModifiers.get(Modifiers.AP_TARGET_NUMBER))); 1642 } 1643 1644 if (saModifiers.containsKey(Modifiers.W_DTG_1)) { 1645 modifiers.put(Modifiers.W_DTG_1, String.valueOf(saModifiers.get(Modifiers.W_DTG_1))); 1646 } 1647 1648 if (saModifiers.containsKey(Modifiers.W1_DTG_2)) { 1649 modifiers.put(Modifiers.W1_DTG_2, String.valueOf(saModifiers.get(Modifiers.W1_DTG_2))); 1650 } 1651 1652 if (saModifiers.containsKey(Modifiers.Y_LOCATION)) { 1653 modifiers.put(Modifiers.Y_LOCATION, String.valueOf(saModifiers.get(Modifiers.Y_LOCATION))); 1654 } 1655 1656 //Required multipoint modifier arrays 1657 if (saModifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)) { 1658 altitudes = new ArrayList<Double>(); 1659 String[] arrAltitudes = String.valueOf(saModifiers.get(Modifiers.X_ALTITUDE_DEPTH)).split(","); 1660 for (String x : arrAltitudes) { 1661 if (x.equals("") != true) { 1662 altitudes.add(Double.parseDouble(x)); 1663 } 1664 } 1665 } 1666 1667 if (saModifiers.containsKey(Modifiers.AM_DISTANCE)) { 1668 distances = new ArrayList<Double>(); 1669 String[] arrDistances = String.valueOf(saModifiers.get(Modifiers.AM_DISTANCE)).split(","); 1670 for (String am : arrDistances) { 1671 if (am.equals("") != true) { 1672 distances.add(Double.parseDouble(am)); 1673 } 1674 } 1675 } 1676 1677 if (saModifiers.containsKey(Modifiers.AN_AZIMUTH)) { 1678 azimuths = new ArrayList<Double>(); 1679 String[] arrAzimuths = String.valueOf(saModifiers.get(Modifiers.AN_AZIMUTH)).split(",");; 1680 for (String an : arrAzimuths) { 1681 if (an.equals("") != true) { 1682 azimuths.add(Double.parseDouble(an)); 1683 } 1684 } 1685 } 1686 } 1687 if (saAttributes != null) { 1688 // These properties are ints, not labels, they are colors.////////////////// 1689 if (saAttributes.containsKey(MilStdAttributes.FillColor)) { 1690 fillColor = (String) saAttributes.get(MilStdAttributes.FillColor); 1691 } 1692 1693 if (saAttributes.containsKey(MilStdAttributes.LineColor)) { 1694 lineColor = (String) saAttributes.get(MilStdAttributes.LineColor); 1695 } 1696 1697 if (saAttributes.containsKey(MilStdAttributes.LineWidth)) { 1698 lineWidth = Integer.parseInt(saAttributes.get(MilStdAttributes.LineWidth)); 1699 } 1700 1701 if (saAttributes.containsKey(MilStdAttributes.TextColor)) { 1702 textColor = (String) saAttributes.get(MilStdAttributes.TextColor); 1703 } 1704 1705 if (saAttributes.containsKey(MilStdAttributes.TextBackgroundColor)) { 1706 textBackgroundColor = (String) saAttributes.get(MilStdAttributes.TextBackgroundColor); 1707 } 1708 1709 if (saAttributes.containsKey(MilStdAttributes.AltitudeMode)) { 1710 altMode = saAttributes.get(MilStdAttributes.AltitudeMode); 1711 } 1712 1713 if (saAttributes.containsKey(MilStdAttributes.UseDashArray)) { 1714 useDashArray = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.UseDashArray)); 1715 } 1716 1717 if (saAttributes.containsKey(MilStdAttributes.UsePatternFill)) { 1718 usePatternFill = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.UsePatternFill)); 1719 } 1720 1721 if (saAttributes.containsKey(MilStdAttributes.PatternFillType)) { 1722 patternFillType = Integer.parseInt((saAttributes.get(MilStdAttributes.PatternFillType))); 1723 } 1724 1725 if (saAttributes.containsKey(MilStdAttributes.HideOptionalLabels)) { 1726 hideOptionalLabels = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.HideOptionalLabels)); 1727 } 1728 1729 if(saAttributes.containsKey(MilStdAttributes.AltitudeUnits)) { 1730 altitudeUnit = DistanceUnit.parse(saAttributes.get(MilStdAttributes.AltitudeUnits)); 1731 } 1732 1733 if(saAttributes.containsKey(MilStdAttributes.DistanceUnits)) { 1734 distanceUnit = DistanceUnit.parse(saAttributes.get(MilStdAttributes.DistanceUnits)); 1735 } 1736 1737 if(saAttributes.containsKey(MilStdAttributes.PixelSize)) { 1738 pixelSize = Integer.parseInt(saAttributes.get(MilStdAttributes.PixelSize)); 1739 symbol.setUnitSize(pixelSize); 1740 } 1741 1742 if (saAttributes.containsKey(MilStdAttributes.KeepUnitRatio)) { 1743 keepUnitRatio = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.KeepUnitRatio)); 1744 symbol.setKeepUnitRatio(keepUnitRatio); 1745 } 1746 1747 if(saAttributes.containsKey(MilStdAttributes.PatternScale)) { 1748 patternScale = Double.parseDouble(saAttributes.get(MilStdAttributes.PatternScale)); 1749 } 1750 } 1751 1752 symbol.setModifierMap(modifiers); 1753 1754 if (fillColor != null && fillColor.equals("") == false) { 1755 symbol.setFillColor(RendererUtilities.getColorFromHexString(fillColor)); 1756 } 1757 1758 if (lineColor != null && lineColor.equals("") == false) { 1759 symbol.setLineColor(RendererUtilities.getColorFromHexString(lineColor)); 1760 symbol.setTextColor(RendererUtilities.getColorFromHexString(lineColor)); 1761 } 1762 else if(symbol.getLineColor()==null) 1763 symbol.setLineColor(Color.black); 1764 1765 if (lineWidth > 0) { 1766 symbol.setLineWidth(lineWidth); 1767 } 1768 1769 if (textColor != null && textColor.equals("") == false) { 1770 symbol.setTextColor(RendererUtilities.getColorFromHexString(textColor)); 1771 } else if(symbol.getTextColor()==null) 1772 symbol.setTextColor(Color.black); 1773 1774 if (textBackgroundColor != null && textBackgroundColor.equals("") == false) { 1775 symbol.setTextBackgroundColor(RendererUtilities.getColorFromHexString(textBackgroundColor)); 1776 } 1777 1778 if (altMode != null) { 1779 symbol.setAltitudeMode(altMode); 1780 } 1781 1782 symbol.setUseDashArray(useDashArray); 1783 symbol.setUseFillPattern(usePatternFill); 1784 symbol.setHideOptionalLabels(hideOptionalLabels); 1785 symbol.setAltitudeUnit(altitudeUnit); 1786 symbol.setDistanceUnit(distanceUnit); 1787 symbol.setPatternScale(patternScale); 1788 1789 // Check grpahic modifiers variables. If we set earlier, populate 1790 // the fields, otherwise, ignore. 1791 if (altitudes != null) { 1792 symbol.setModifiers_AM_AN_X(Modifiers.X_ALTITUDE_DEPTH, altitudes); 1793 } 1794 if (distances != null) { 1795 symbol.setModifiers_AM_AN_X(Modifiers.AM_DISTANCE, distances); 1796 } 1797 1798 if (azimuths != null) { 1799 symbol.setModifiers_AM_AN_X(Modifiers.AN_AZIMUTH, azimuths); 1800 } 1801 1802 //Check if sector range fan has required min range 1803 if (SymbolUtilities.getBasicSymbolID(symbol.getSymbolID()).equals("25242200")) { 1804 if (symbol.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH) != null 1805 && symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE) != null) { 1806 int anCount = symbol.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH).size(); 1807 int amCount = symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE).size(); 1808 ArrayList<Double> am = null; 1809 if (amCount < ((anCount / 2) + 1)) { 1810 am = symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 1811 if (am.get(0) != 0.0) { 1812 am.add(0, 0.0); 1813 } 1814 } 1815 } 1816 } 1817 } catch (Exception exc2) { 1818 Log.e("MPH.populateModifiers", exc2.getMessage(), exc2); 1819 } 1820 return true; 1821 1822 } 1823 1824 private static String KMLize(String id, String name, 1825 String description, 1826 String symbolCode, 1827 ArrayList<ShapeInfo> shapes, 1828 ArrayList<ShapeInfo> modifiers, 1829 IPointConversion ipc, 1830 boolean normalize, Color textColor) { 1831 1832 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 1833 1834 ShapeInfo tempModifier = null; 1835 1836 String cdataStart = "<![CDATA["; 1837 String cdataEnd = "]]>"; 1838 1839 int len = shapes.size(); 1840 kml.append("<Folder id=\"" + id + "\">"); 1841 kml.append("<name>" + cdataStart + name + cdataEnd + "</name>"); 1842 kml.append("<visibility>1</visibility>"); 1843 for (int i = 0; i < len; i++) { 1844 1845 String shapesToAdd = ShapeToKMLString(name, description, symbolCode, shapes.get(i), ipc, normalize); 1846 kml.append(shapesToAdd); 1847 } 1848 1849 int len2 = modifiers.size(); 1850 1851 for (int j = 0; j < len2; j++) { 1852 1853 tempModifier = modifiers.get(j); 1854 1855 //if(geMap)//if using google earth 1856 //assume kml text is going to be centered 1857 //AdjustModifierPointToCenter(tempModifier); 1858 1859 String labelsToAdd = LabelToKMLString(tempModifier, ipc, normalize, textColor); 1860 kml.append(labelsToAdd); 1861 } 1862 1863 kml.append("</Folder>"); 1864 return kml.toString(); 1865 } 1866 1867 /** 1868 * 1869 * @param shapes 1870 * @param modifiers 1871 * @param ipc 1872 * @param geMap 1873 * @param normalize 1874 * @return 1875 * @deprecated Use GeoJSONize() 1876 */ 1877 private static String JSONize(ArrayList<ShapeInfo> shapes, ArrayList<ShapeInfo> modifiers, IPointConversion ipc, Boolean geMap, boolean normalize) { 1878 String polygons = ""; 1879 String lines = ""; 1880 String labels = ""; 1881 String jstr = ""; 1882 ShapeInfo tempModifier = null; 1883 1884 int len = shapes.size(); 1885 for (int i = 0; i < len; i++) { 1886 if (jstr.length() > 0) { 1887 jstr += ","; 1888 } 1889 String shapesToAdd = ShapeToJSONString(shapes.get(i), ipc, geMap, normalize); 1890 if (shapesToAdd.length() > 0) { 1891 if (shapesToAdd.startsWith("line", 2)) { 1892 if (lines.length() > 0) { 1893 lines += ","; 1894 } 1895 1896 lines += shapesToAdd; 1897 } else if (shapesToAdd.startsWith("polygon", 2)) { 1898 if (polygons.length() > 0) { 1899 polygons += ","; 1900 } 1901 1902 polygons += shapesToAdd; 1903 } 1904 } 1905 } 1906 1907 jstr += "\"polygons\": [" + polygons + "]," 1908 + "\"lines\": [" + lines + "],"; 1909 int len2 = modifiers.size(); 1910 labels = ""; 1911 for (int j = 0; j < len2; j++) { 1912 tempModifier = modifiers.get(j); 1913 if (geMap) { 1914 AdjustModifierPointToCenter(tempModifier); 1915 } 1916 String labelsToAdd = LabelToJSONString(tempModifier, ipc, normalize); 1917 if (labelsToAdd.length() > 0) { 1918 if (labels.length() > 0) { 1919 labels += ","; 1920 } 1921 1922 labels += labelsToAdd; 1923 1924 } 1925 } 1926 jstr += "\"labels\": [" + labels + "]"; 1927 return jstr; 1928 } 1929 1930 private static Color getIdealTextBackgroundColor(Color fgColor) { 1931 //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "in function", Level.SEVERE); 1932 try { 1933 //an array of three elements containing the 1934 //hue, saturation, and brightness (in that order), 1935 //of the color with the indicated red, green, and blue components/ 1936 float hsbvals[] = new float[3]; 1937 1938 if (fgColor != null) {/* 1939 Color.RGBtoHSB(fgColor.getRed(), fgColor.getGreen(), fgColor.getBlue(), hsbvals); 1940 1941 if(hsbvals != null) 1942 { 1943 //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "length: " + String.valueOf(hsbvals.length)); 1944 //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "H: " + String.valueOf(hsbvals[0]) + " S: " + String.valueOf(hsbvals[1]) + " B: " + String.valueOf(hsbvals[2]),Level.SEVERE); 1945 if(hsbvals[2] > 0.6) 1946 return Color.BLACK; 1947 else 1948 return Color.WHITE; 1949 }*/ 1950 1951 int nThreshold = RendererSettings.getInstance().getTextBackgroundAutoColorThreshold();//160; 1952 int bgDelta = (int) ((fgColor.getRed() * 0.299) + (fgColor.getGreen() * 0.587) + (fgColor.getBlue() * 0.114)); 1953 //ErrorLogger.LogMessage("bgDelta: " + String.valueOf(255-bgDelta)); 1954 //if less than threshold, black, otherwise white. 1955 //return (255 - bgDelta < nThreshold) ? Color.BLACK : Color.WHITE;//new Color(0, 0, 0, fgColor.getAlpha()) 1956 return (255 - bgDelta < nThreshold) ? new Color(0, 0, 0, fgColor.getAlpha()) : new Color(255, 255, 255, fgColor.getAlpha()); 1957 } 1958 } catch (Exception exc) { 1959 ErrorLogger.LogException("SymbolDraw", "getIdealtextBGColor", exc); 1960 } 1961 return Color.WHITE; 1962 } 1963 1964 private static String LabelToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize, Color textColor, Color textBackgroundColor) { 1965 1966 StringBuilder JSONed = new StringBuilder(); 1967 StringBuilder properties = new StringBuilder(); 1968 StringBuilder geometry = new StringBuilder(); 1969 1970 Color outlineColor = getIdealTextBackgroundColor(textColor); 1971 if(textBackgroundColor != null) 1972 outlineColor = textBackgroundColor; 1973 1974 //AffineTransform at = shapeInfo.getAffineTransform(); 1975 //Point2D coord = (Point2D)new Point2D.Double(at.getTranslateX(), at.getTranslateY()); 1976 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 1977 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 1978 Point2D geoCoord = ipc.PixelsToGeo(coord); 1979 //M. Deutch 9-27-11 1980 if (normalize) { 1981 geoCoord = NormalizeCoordToGECoord(geoCoord); 1982 } 1983 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 1984 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 1985 double angle = shapeInfo.getModifierAngle(); 1986 coord.setLocation(longitude, latitude); 1987 1988 //diagnostic M. Deutch 10-18-11 1989 shapeInfo.setGlyphPosition(coord); 1990 1991 String text = shapeInfo.getModifierString(); 1992 1993 int justify=shapeInfo.getTextJustify(); 1994 String strJustify="left"; 1995 if(justify==0) 1996 strJustify="left"; 1997 else if(justify==1) 1998 strJustify="center"; 1999 else if(justify==2) 2000 strJustify="right"; 2001 2002 2003 RendererSettings RS = RendererSettings.getInstance(); 2004 2005 if (text != null && text.equals("") == false) { 2006 2007 JSONed.append("{\"type\":\"Feature\",\"properties\":{\"label\":\""); 2008 JSONed.append(text); 2009 JSONed.append("\",\"pointRadius\":0,\"fontColor\":\""); 2010 JSONed.append(RendererUtilities.colorToHexString(textColor, false)); 2011 JSONed.append("\",\"fontSize\":\""); 2012 JSONed.append(String.valueOf(RS.getMPLabelFontSize()) + "pt\""); 2013 JSONed.append(",\"fontFamily\":\""); 2014 JSONed.append(RS.getMPLabelFontName()); 2015 JSONed.append(", sans-serif"); 2016 2017 if (RS.getMPLabelFontType() == Typeface.BOLD) { 2018 JSONed.append("\",\"fontWeight\":\"bold\""); 2019 } else { 2020 JSONed.append("\",\"fontWeight\":\"normal\""); 2021 } 2022 2023 //JSONed.append(",\"labelAlign\":\"lm\""); 2024 JSONed.append(",\"labelAlign\":\""); 2025 JSONed.append(strJustify); 2026 JSONed.append("\",\"labelBaseline\":\"alphabetic\""); 2027 JSONed.append(",\"labelXOffset\":0"); 2028 JSONed.append(",\"labelYOffset\":0"); 2029 JSONed.append(",\"labelOutlineColor\":\""); 2030 JSONed.append(RendererUtilities.colorToHexString(outlineColor, false)); 2031 JSONed.append("\",\"labelOutlineWidth\":"); 2032 JSONed.append("4"); 2033 JSONed.append(",\"rotation\":"); 2034 JSONed.append(angle); 2035 JSONed.append(",\"angle\":"); 2036 JSONed.append(angle); 2037 JSONed.append("},"); 2038 2039 JSONed.append("\"geometry\":{\"type\":\"Point\",\"coordinates\":["); 2040 JSONed.append(longitude); 2041 JSONed.append(","); 2042 JSONed.append(latitude); 2043 JSONed.append("]"); 2044 JSONed.append("}}"); 2045 2046 } else { 2047 return ""; 2048 } 2049 2050 return JSONed.toString(); 2051 } 2052 2053 private static String ShapeToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2054 StringBuilder JSONed = new StringBuilder(); 2055 StringBuilder properties = new StringBuilder(); 2056 StringBuilder geometry = new StringBuilder(); 2057 String geometryType = null; 2058 String sda = null; 2059 /* 2060 NOTE: Google Earth / KML colors are backwards. 2061 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2062 * */ 2063 Color lineColor = shapeInfo.getLineColor(); 2064 Color fillColor = shapeInfo.getFillColor(); 2065 2066 if (shapeInfo.getShapeType() == ShapeInfo.SHAPE_TYPE_FILL || fillColor != null || shapeInfo.getPatternFillImage() != null) { 2067 geometryType = "\"Polygon\""; 2068 } else //if(shapeInfo.getShapeType() == ShapeInfo.SHAPE_TYPE_POLYLINE) 2069 { 2070 geometryType = "\"MultiLineString\""; 2071 } 2072 2073 BasicStroke stroke = null; 2074 stroke = shapeInfo.getStroke(); 2075 int lineWidth = 4; 2076 2077 if (stroke != null) { 2078 lineWidth = (int) stroke.getLineWidth(); 2079 //lineWidth++; 2080 //System.out.println("lineWidth: " + String.valueOf(lineWidth)); 2081 } 2082 2083 //generate JSON properties for feature 2084 properties.append("\"properties\":{"); 2085 properties.append("\"label\":\"\","); 2086 if (lineColor != null) { 2087 properties.append("\"strokeColor\":\"" + RendererUtilities.colorToHexString(lineColor, false) + "\","); 2088 properties.append("\"lineOpacity\":" + String.valueOf(lineColor.getAlpha() / 255f) + ","); 2089 } 2090 if (fillColor != null) { 2091 properties.append("\"fillColor\":\"" + RendererUtilities.colorToHexString(fillColor, false) + "\","); 2092 properties.append("\"fillOpacity\":" + String.valueOf(fillColor.getAlpha() / 255f) + ","); 2093 } 2094 if (shapeInfo.getPatternFillImage() != null) { 2095 properties.append("\"fillPattern\":\"" + bitmapToString(shapeInfo.getPatternFillImage()) + "\","); 2096 } 2097 if(stroke.getDashArray() != null) 2098 { 2099 float[] arrSDA = stroke.getDashArray(); 2100 sda = "["; 2101 sda += String.valueOf(arrSDA[0]); 2102 if(arrSDA.length > 1) 2103 { 2104 for(int i = 1; i < arrSDA.length; i++) 2105 { 2106 sda = sda + ", " + String.valueOf(arrSDA[i]); 2107 } 2108 } 2109 sda += "]"; 2110 sda = "\"strokeDasharray\":" + sda + ","; 2111 properties.append(sda); 2112 } 2113 2114 int lineCap = stroke.getEndCap(); 2115 properties.append("\"lineCap\":" + lineCap + ","); 2116 2117 String strokeWidth = String.valueOf(lineWidth); 2118 properties.append("\"strokeWidth\":" + strokeWidth + ","); 2119 properties.append("\"strokeWeight\":" + strokeWidth + ""); 2120 properties.append("},"); 2121 2122 2123 properties.append("\"style\":{"); 2124 if (lineColor != null) { 2125 properties.append("\"stroke\":\"" + RendererUtilities.colorToHexString(lineColor, false) + "\","); 2126 properties.append("\"line-opacity\":" + String.valueOf(lineColor.getAlpha() / 255f) + ","); 2127 } 2128 if (fillColor != null) { 2129 properties.append("\"fill\":\"" + RendererUtilities.colorToHexString(fillColor, false) + "\","); 2130 properties.append("\"fill-opacity\":" + String.valueOf(fillColor.getAlpha() / 255f) + ","); 2131 } 2132 if(stroke.getDashArray() != null) 2133 { 2134 float[] da = stroke.getDashArray(); 2135 sda = String.valueOf(da[0]); 2136 if(da.length > 1) 2137 { 2138 for(int i = 1; i < da.length; i++) 2139 { 2140 sda = sda + " " + String.valueOf(da[i]); 2141 } 2142 } 2143 sda = "\"stroke-dasharray\":\"" + sda + "\","; 2144 properties.append(sda); 2145 sda = null; 2146 } 2147 2148 if(lineCap == BasicStroke.CAP_SQUARE) 2149 properties.append("\"stroke-linecap\":\"square\","); 2150 else if(lineCap == BasicStroke.CAP_ROUND) 2151 properties.append("\"stroke-linecap\":\"round\","); 2152 else if(lineCap == BasicStroke.CAP_BUTT) 2153 properties.append("\"stroke-linecap\":\"butt\","); 2154 2155 strokeWidth = String.valueOf(lineWidth); 2156 properties.append("\"stroke-width\":" + strokeWidth); 2157 properties.append("}"); 2158 2159 2160 //generate JSON geometry for feature 2161 geometry.append("\"geometry\":{\"type\":"); 2162 geometry.append(geometryType); 2163 geometry.append(",\"coordinates\":["); 2164 2165 ArrayList shapesArray = shapeInfo.getPolylines(); 2166 2167 for (int i = 0; i < shapesArray.size(); i++) { 2168 ArrayList pointList = (ArrayList) shapesArray.get(i); 2169 2170 normalize = normalizePoints(pointList, ipc); 2171 2172 geometry.append("["); 2173 2174 //System.out.println("Pixel Coords:"); 2175 for (int j = 0; j < pointList.size(); j++) { 2176 Point2D coord = (Point2D) pointList.get(j); 2177 Point2D geoCoord = ipc.PixelsToGeo(coord); 2178 //M. Deutch 9-27-11 2179 if (normalize) { 2180 geoCoord = NormalizeCoordToGECoord(geoCoord); 2181 } 2182 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2183 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2184 2185 //fix for fill crossing DTL 2186 if (normalize && fillColor != null) { 2187 if (longitude > 0) { 2188 longitude -= 360; 2189 } 2190 } 2191 2192 //diagnostic M. Deutch 10-18-11 2193 //set the point as geo so that the 2194 //coord.setLocation(longitude, latitude); 2195 coord = new Point2D.Double(longitude, latitude); 2196 pointList.set(j, coord); 2197 //end section 2198 2199 geometry.append("["); 2200 geometry.append(longitude); 2201 geometry.append(","); 2202 geometry.append(latitude); 2203 geometry.append("]"); 2204 2205 if (j < (pointList.size() - 1)) { 2206 geometry.append(","); 2207 } 2208 } 2209 2210 geometry.append("]"); 2211 2212 if (i < (shapesArray.size() - 1)) { 2213 geometry.append(","); 2214 } 2215 } 2216 geometry.append("]}"); 2217 2218 JSONed.append("{\"type\":\"Feature\","); 2219 JSONed.append(properties.toString()); 2220 JSONed.append(","); 2221 JSONed.append(geometry.toString()); 2222 JSONed.append("}"); 2223 2224 return JSONed.toString(); 2225 } 2226 2227 private static String ImageToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2228 2229 StringBuilder JSONed = new StringBuilder(); 2230 StringBuilder properties = new StringBuilder(); 2231 StringBuilder geometry = new StringBuilder(); 2232 2233 //AffineTransform at = shapeInfo.getAffineTransform(); 2234 //Point2D coord = (Point2D)new Point2D.Double(at.getTranslateX(), at.getTranslateY()); 2235 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2236 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 2237 Point2D geoCoord = ipc.PixelsToGeo(coord); 2238 //M. Deutch 9-27-11 2239 if (normalize) { 2240 geoCoord = NormalizeCoordToGECoord(geoCoord); 2241 } 2242 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2243 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2244 double angle = shapeInfo.getModifierAngle(); 2245 coord.setLocation(longitude, latitude); 2246 2247 //diagnostic M. Deutch 10-18-11 2248 shapeInfo.setGlyphPosition(coord); 2249 2250 Bitmap image = shapeInfo.getModifierImage(); 2251 2252 RendererSettings RS = RendererSettings.getInstance(); 2253 2254 if (image != null) { 2255 2256 JSONed.append("{\"type\":\"Feature\",\"properties\":{\"image\":\""); 2257 JSONed.append(bitmapToString(image)); 2258 JSONed.append("\",\"rotation\":"); 2259 JSONed.append(angle); 2260 JSONed.append(",\"angle\":"); 2261 JSONed.append(angle); 2262 JSONed.append("},"); 2263 JSONed.append("\"geometry\":{\"type\":\"Point\",\"coordinates\":["); 2264 JSONed.append(longitude); 2265 JSONed.append(","); 2266 JSONed.append(latitude); 2267 JSONed.append("]"); 2268 JSONed.append("}}"); 2269 2270 } else { 2271 return ""; 2272 } 2273 2274 return JSONed.toString(); 2275 } 2276 2277 protected static String bitmapToString(Bitmap bitmap) { 2278 final int COMPRESSION_QUALITY = 100; 2279 String encodedImage; 2280 ByteArrayOutputStream byteArrayBitmapStream = new ByteArrayOutputStream(); 2281 bitmap.compress(Bitmap.CompressFormat.PNG, COMPRESSION_QUALITY, 2282 byteArrayBitmapStream); 2283 byte[] b = byteArrayBitmapStream.toByteArray(); 2284 encodedImage = Base64.encodeToString(b, Base64.DEFAULT); 2285 return "data:image/png;base64," + encodedImage; 2286 } 2287 2288 private static String GeoJSONize(ArrayList<ShapeInfo> shapes, ArrayList<ShapeInfo> modifiers, IPointConversion ipc, boolean normalize, Color textColor, Color textBackgroundColor) { 2289 2290 String jstr = ""; 2291 ShapeInfo tempModifier = null; 2292 StringBuilder fc = new StringBuilder();//JSON feature collection 2293 2294 fc.append("["); 2295 2296 int len = shapes.size(); 2297 for (int i = 0; i < len; i++) { 2298 2299 String shapesToAdd = ShapeToGeoJSONString(shapes.get(i), ipc, normalize); 2300 if (shapesToAdd.length() > 0) { 2301 fc.append(shapesToAdd); 2302 if (i < len - 1) { 2303 fc.append(","); 2304 } 2305 } 2306 } 2307 2308 int len2 = modifiers.size(); 2309 2310 for (int j = 0; j < len2; j++) { 2311 tempModifier = modifiers.get(j); 2312 2313 String modifiersToAdd = null; 2314 if(modifiers.get(j).getModifierImage() != null) { 2315 modifiersToAdd = ImageToGeoJSONString(tempModifier, ipc, normalize); 2316 } else { 2317 modifiersToAdd = LabelToGeoJSONString(tempModifier, ipc, normalize, textColor, textBackgroundColor); 2318 } 2319 if (modifiersToAdd.length() > 0) { 2320 if (fc.length() > 1) 2321 fc.append(","); 2322 fc.append(modifiersToAdd); 2323 } 2324 } 2325 fc.append("]"); 2326 String GeoJSON = fc.toString(); 2327 return GeoJSON; 2328 } 2329 2330 /** 2331 * 2332 * @param shapes 2333 * @param modifiers 2334 * @param ipc 2335 * @param normalize 2336 * @deprecated 2337 */ 2338 private static void MakeWWReady( 2339 ArrayList<ShapeInfo> shapes, 2340 ArrayList<ShapeInfo> modifiers, 2341 IPointConversion ipc, 2342 boolean normalize) { 2343 ShapeInfo temp = null; 2344 int len = shapes.size(); 2345 for (int i = 0; i < len; i++) { 2346 2347 temp = ShapeToWWReady(shapes.get(i), ipc, normalize); 2348 shapes.set(i, temp); 2349 2350 } 2351 2352 int len2 = modifiers.size(); 2353 ShapeInfo tempModifier = null; 2354 for (int j = 0; j < len2; j++) { 2355 2356 tempModifier = modifiers.get(j); 2357 2358 //Do we need this for World Wind? 2359 tempModifier = LabelToWWReady(tempModifier, ipc, normalize); 2360 modifiers.set(j, tempModifier); 2361 2362 } 2363 2364 } 2365 2366 private static Boolean normalizePoints(ArrayList<Point2D.Double> shape, IPointConversion ipc) { 2367 ArrayList geoCoords = new ArrayList(); 2368 int n = shape.size(); 2369 //for (int j = 0; j < shape.size(); j++) 2370 for (int j = 0; j < n; j++) { 2371 Point2D coord = shape.get(j); 2372 Point2D geoCoord = ipc.PixelsToGeo(coord); 2373 geoCoord = NormalizeCoordToGECoord(geoCoord); 2374 double latitude = geoCoord.getY(); 2375 double longitude = geoCoord.getX(); 2376 Point2D pt2d = new Point2D.Double(longitude, latitude); 2377 geoCoords.add(pt2d); 2378 } 2379 Boolean normalize = crossesIDL(geoCoords); 2380 return normalize; 2381 } 2382 2383 private static Boolean IsOnePointSymbolCode(String symbolCode) { 2384 String basicCode = SymbolUtilities.getBasicSymbolID(symbolCode); 2385 //TODO: Revisit for basic shapes 2386 //some airspaces affected 2387 if (symbolCode.equals("CAKE-----------")) { 2388 return true; 2389 } else if (symbolCode.equals("CYLINDER-------")) { 2390 return true; 2391 } else if (symbolCode.equals("RADARC---------")) { 2392 return true; 2393 } 2394 2395 return false; 2396 } 2397 2398 private static String ShapeToKMLString(String name, 2399 String description, 2400 String symbolCode, 2401 ShapeInfo shapeInfo, 2402 IPointConversion ipc, 2403 boolean normalize) { 2404 2405 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 2406 2407 Color lineColor = null; 2408 Color fillColor = null; 2409 String googleLineColor = null; 2410 String googleFillColor = null; 2411 2412 //String lineStyleId = "lineColor"; 2413 2414 BasicStroke stroke = null; 2415 int lineWidth = 4; 2416 2417 symbolCode = JavaRendererUtilities.normalizeSymbolCode(symbolCode); 2418 2419 String cdataStart = "<![CDATA["; 2420 String cdataEnd = "]]>"; 2421 2422 kml.append("<Placemark>");//("<Placemark id=\"" + id + "_mg" + "\">"); 2423 kml.append("<description>" + cdataStart + "<b>" + name + "</b><br/>" + "\n" + description + cdataEnd + "</description>"); 2424 //kml.append("<Style id=\"" + lineStyleId + "\">"); 2425 kml.append("<Style>"); 2426 2427 lineColor = shapeInfo.getLineColor(); 2428 if (lineColor != null) { 2429 googleLineColor = Integer.toHexString(shapeInfo.getLineColor().toARGB()); 2430 2431 stroke = shapeInfo.getStroke(); 2432 2433 if (stroke != null) { 2434 lineWidth = (int) stroke.getLineWidth(); 2435 } 2436 2437 googleLineColor = JavaRendererUtilities.ARGBtoABGR(googleLineColor); 2438 2439 kml.append("<LineStyle>"); 2440 kml.append("<color>" + googleLineColor + "</color>"); 2441 kml.append("<colorMode>normal</colorMode>"); 2442 kml.append("<width>" + String.valueOf(lineWidth) + "</width>"); 2443 kml.append("</LineStyle>"); 2444 } 2445 2446 fillColor = shapeInfo.getFillColor(); 2447 Bitmap fillPattern = shapeInfo.getPatternFillImage(); 2448 if (fillColor != null || fillPattern != null) { 2449 kml.append("<PolyStyle>"); 2450 2451 if (fillColor != null) { 2452 googleFillColor = Integer.toHexString(shapeInfo.getFillColor().toARGB()); 2453 googleFillColor = JavaRendererUtilities.ARGBtoABGR(googleFillColor); 2454 kml.append("<color>" + googleFillColor + "</color>"); 2455 kml.append("<colorMode>normal</colorMode>"); 2456 } 2457 if (fillPattern != null){ 2458 kml.append("<shader>" + bitmapToString(fillPattern) + "</shader>"); 2459 } 2460 2461 kml.append("<fill>1</fill>"); 2462 if (lineColor != null) { 2463 kml.append("<outline>1</outline>"); 2464 } else { 2465 kml.append("<outline>0</outline>"); 2466 } 2467 kml.append("</PolyStyle>"); 2468 } 2469 2470 kml.append("</Style>"); 2471 2472 ArrayList shapesArray = shapeInfo.getPolylines(); 2473 int len = shapesArray.size(); 2474 kml.append("<MultiGeometry>"); 2475 2476 for (int i = 0; i < len; i++) { 2477 ArrayList shape = (ArrayList) shapesArray.get(i); 2478 normalize = normalizePoints(shape, ipc); 2479 if (lineColor != null && fillColor == null) { 2480 kml.append("<LineString>"); 2481 kml.append("<tessellate>1</tessellate>"); 2482 kml.append("<altitudeMode>clampToGround</altitudeMode>"); 2483 kml.append("<coordinates>"); 2484 int n = shape.size(); 2485 //for (int j = 0; j < shape.size(); j++) 2486 for (int j = 0; j < n; j++) { 2487 Point2D coord = (Point2D) shape.get(j); 2488 Point2D geoCoord = ipc.PixelsToGeo(coord); 2489 if (normalize) { 2490 geoCoord = NormalizeCoordToGECoord(geoCoord); 2491 } 2492 2493 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2494 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2495 2496 kml.append(longitude); 2497 kml.append(","); 2498 kml.append(latitude); 2499 if(j<shape.size()-1) 2500 kml.append(" "); 2501 } 2502 2503 kml.append("</coordinates>"); 2504 kml.append("</LineString>"); 2505 } 2506 2507 if (fillColor != null) { 2508 2509 if (i == 0) { 2510 kml.append("<Polygon>"); 2511 } 2512 //kml.append("<outerBoundaryIs>"); 2513 if (i == 1 && len > 1) { 2514 kml.append("<innerBoundaryIs>"); 2515 } else { 2516 kml.append("<outerBoundaryIs>"); 2517 } 2518 kml.append("<LinearRing>"); 2519 kml.append("<altitudeMode>clampToGround</altitudeMode>"); 2520 kml.append("<tessellate>1</tessellate>"); 2521 kml.append("<coordinates>"); 2522 2523 //this section is a workaround for a google earth bug. Issue 417 was closed 2524 //for linestrings but they did not fix the smae issue for fills. If Google fixes the issue 2525 //for fills then this section will need to be commented or it will induce an error. 2526 double lastLongitude = Double.MIN_VALUE; 2527 if (normalize == false && IsOnePointSymbolCode(symbolCode)) { 2528 int n = shape.size(); 2529 //for (int j = 0; j < shape.size(); j++) 2530 for (int j = 0; j < n; j++) { 2531 Point2D coord = (Point2D) shape.get(j); 2532 Point2D geoCoord = ipc.PixelsToGeo(coord); 2533 double longitude = geoCoord.getX(); 2534 if (lastLongitude != Double.MIN_VALUE) { 2535 if (Math.abs(longitude - lastLongitude) > 180d) { 2536 normalize = true; 2537 break; 2538 } 2539 } 2540 lastLongitude = longitude; 2541 } 2542 } 2543 int n = shape.size(); 2544 //for (int j = 0; j < shape.size(); j++) 2545 for (int j = 0; j < n; j++) { 2546 Point2D coord = (Point2D) shape.get(j); 2547 Point2D geoCoord = ipc.PixelsToGeo(coord); 2548 2549 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2550 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2551 2552 //fix for fill crossing DTL 2553 if (normalize) { 2554 if (longitude > 0) { 2555 longitude -= 360; 2556 } 2557 } 2558 2559 kml.append(longitude); 2560 kml.append(","); 2561 kml.append(latitude); 2562 if(j<shape.size()-1) 2563 kml.append(" "); 2564 } 2565 2566 kml.append("</coordinates>"); 2567 kml.append("</LinearRing>"); 2568 if (i == 1 && len > 1) { 2569 kml.append("</innerBoundaryIs>"); 2570 } else { 2571 kml.append("</outerBoundaryIs>"); 2572 } 2573 if (i == len - 1) { 2574 kml.append("</Polygon>"); 2575 } 2576 } 2577 } 2578 2579 kml.append("</MultiGeometry>"); 2580 kml.append("</Placemark>"); 2581 2582 return kml.toString(); 2583 } 2584 2585 /** 2586 * 2587 * @param shapeInfo 2588 * @param ipc 2589 * @param normalize 2590 * @return 2591 * @deprecated 2592 */ 2593 private static ShapeInfo ShapeToWWReady( 2594 ShapeInfo shapeInfo, 2595 IPointConversion ipc, 2596 boolean normalize) { 2597 2598 ArrayList shapesArray = shapeInfo.getPolylines(); 2599 int len = shapesArray.size(); 2600 2601 for (int i = 0; i < len; i++) { 2602 ArrayList shape = (ArrayList) shapesArray.get(i); 2603 2604 if (shapeInfo.getLineColor() != null) { 2605 int n = shape.size(); 2606 //for (int j = 0; j < shape.size(); j++) 2607 for (int j = 0; j < n; j++) { 2608 Point2D coord = (Point2D) shape.get(j); 2609 Point2D geoCoord = ipc.PixelsToGeo(coord); 2610 //M. Deutch 9-26-11 2611 if (normalize) { 2612 geoCoord = NormalizeCoordToGECoord(geoCoord); 2613 } 2614 2615 shape.set(j, geoCoord); 2616 2617 } 2618 2619 } 2620 2621 if (shapeInfo.getFillColor() != null) { 2622 int n = shape.size(); 2623 //for (int j = 0; j < shape.size(); j++) 2624 for (int j = 0; j < n; j++) { 2625 Point2D coord = (Point2D) shape.get(j); 2626 Point2D geoCoord = ipc.PixelsToGeo(coord); 2627 //M. Deutch 9-26-11 2628 //commenting these two lines seems to help with fill not go around the pole 2629 //if(normalize) 2630 //geoCoord=NormalizeCoordToGECoord(geoCoord); 2631 2632 shape.set(j, geoCoord); 2633 } 2634 } 2635 } 2636 2637 return shapeInfo; 2638 } 2639 2640 private static ShapeInfo LabelToWWReady(ShapeInfo shapeInfo, 2641 IPointConversion ipc, 2642 boolean normalize) { 2643 2644 try { 2645 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2646 Point2D geoCoord = ipc.PixelsToGeo(coord); 2647 //M. Deutch 9-26-11 2648 if (normalize) { 2649 geoCoord = NormalizeCoordToGECoord(geoCoord); 2650 } 2651 double latitude = geoCoord.getY(); 2652 double longitude = geoCoord.getX(); 2653 long angle = Math.round(shapeInfo.getModifierAngle()); 2654 2655 String text = shapeInfo.getModifierString(); 2656 2657 if (text != null && text.equals("") == false) { 2658 shapeInfo.setModifierPosition(geoCoord); 2659 } else { 2660 return null; 2661 } 2662 } catch (Exception exc) { 2663 System.err.println(exc.getMessage()); 2664 exc.printStackTrace(); 2665 } 2666 2667 return shapeInfo; 2668 } 2669 2670 /** 2671 * Google earth centers text on point rather than drawing from that point. 2672 * So we need to adjust the point to where the center of the text would be. 2673 * 2674 * @param modifier 2675 */ 2676 private static void AdjustModifierPointToCenter(ShapeInfo modifier) { 2677 AffineTransform at = null; 2678 try { 2679 Rectangle bounds2 = modifier.getTextLayout().getBounds(); 2680 Rectangle2D bounds = new Rectangle2D.Double(bounds2.x, bounds2.y, bounds2.width, bounds2.height); 2681 } catch (Exception exc) { 2682 System.err.println(exc.getMessage()); 2683 exc.printStackTrace(); 2684 } 2685 } 2686 2687 /** 2688 * 2689 * @param shapeInfo 2690 * @param ipc 2691 * @param geMap 2692 * @param normalize 2693 * @return 2694 * @deprecated 2695 */ 2696 private static String ShapeToJSONString(ShapeInfo shapeInfo, IPointConversion ipc, Boolean geMap, boolean normalize) { 2697 StringBuilder JSONed = new StringBuilder(); 2698 /* 2699 NOTE: Google Earth / KML colors are backwards. 2700 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2701 * */ 2702 String fillColor = null; 2703 String lineColor = null; 2704 2705 if (shapeInfo.getLineColor() != null) { 2706 lineColor = Integer.toHexString(shapeInfo.getLineColor().toARGB()); 2707 if (geMap) { 2708 lineColor = JavaRendererUtilities.ARGBtoABGR(lineColor); 2709 } 2710 2711 } 2712 if (shapeInfo.getFillColor() != null) { 2713 fillColor = Integer.toHexString(shapeInfo.getFillColor().toARGB()); 2714 if (geMap) { 2715 fillColor = JavaRendererUtilities.ARGBtoABGR(fillColor); 2716 } 2717 } 2718 2719 BasicStroke stroke = null; 2720 stroke = shapeInfo.getStroke(); 2721 int lineWidth = 4; 2722 2723 if (stroke != null) { 2724 lineWidth = (int) stroke.getLineWidth(); 2725 } 2726 2727 ArrayList shapesArray = shapeInfo.getPolylines(); 2728 int n = shapesArray.size(); 2729 //for (int i = 0; i < shapesArray.size(); i++) 2730 for (int i = 0; i < n; i++) { 2731 ArrayList shape = (ArrayList) shapesArray.get(i); 2732 2733 if (fillColor != null) { 2734 JSONed.append("{\"polygon\":["); 2735 } else { 2736 JSONed.append("{\"line\":["); 2737 } 2738 2739 int t = shape.size(); 2740 //for (int j = 0; j < shape.size(); j++) 2741 for (int j = 0; j < t; j++) { 2742 Point2D coord = (Point2D) shape.get(j); 2743 Point2D geoCoord = ipc.PixelsToGeo(coord); 2744 //M. Deutch 9-27-11 2745 if (normalize) { 2746 geoCoord = NormalizeCoordToGECoord(geoCoord); 2747 } 2748 double latitude = geoCoord.getY(); 2749 double longitude = geoCoord.getX(); 2750 2751 //diagnostic M. Deutch 10-18-11 2752 //set the point as geo so that the 2753 coord = new Point2D.Double(longitude, latitude); 2754 shape.set(j, coord); 2755 2756 JSONed.append("["); 2757 JSONed.append(longitude); 2758 JSONed.append(","); 2759 JSONed.append(latitude); 2760 JSONed.append("]"); 2761 2762 if (j < (shape.size() - 1)) { 2763 JSONed.append(","); 2764 } 2765 } 2766 2767 JSONed.append("]"); 2768 if (lineColor != null) { 2769 JSONed.append(",\"lineColor\":\""); 2770 JSONed.append(lineColor); 2771 2772 JSONed.append("\""); 2773 } 2774 if (fillColor != null) { 2775 JSONed.append(",\"fillColor\":\""); 2776 JSONed.append(fillColor); 2777 JSONed.append("\""); 2778 } 2779 2780 JSONed.append(",\"lineWidth\":\""); 2781 JSONed.append(String.valueOf(lineWidth)); 2782 JSONed.append("\""); 2783 2784 JSONed.append("}"); 2785 2786 if (i < (shapesArray.size() - 1)) { 2787 JSONed.append(","); 2788 } 2789 } 2790 2791 return JSONed.toString(); 2792 } 2793 2794 private static String LabelToKMLString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize, Color textColor) { 2795 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 2796 2797 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2798 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 2799 Point2D geoCoord = ipc.PixelsToGeo(coord); 2800 //M. Deutch 9-26-11 2801 if (normalize) { 2802 geoCoord = NormalizeCoordToGECoord(geoCoord); 2803 } 2804 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2805 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2806 long angle = Math.round(shapeInfo.getModifierAngle()); 2807 2808 String text = shapeInfo.getModifierString(); 2809 2810 String cdataStart = "<![CDATA["; 2811 String cdataEnd = "]]>"; 2812 2813 String color = Integer.toHexString(textColor.toARGB()); 2814 color = JavaRendererUtilities.ARGBtoABGR(color); 2815 float kmlScale = RendererSettings.getInstance().getKMLLabelScale(); 2816 2817 if (kmlScale > 0 && text != null && text.equals("") == false) { 2818 kml.append("<Placemark>");//("<Placemark id=\"" + id + "_lp" + i + "\">"); 2819 kml.append("<name>" + cdataStart + text + cdataEnd + "</name>"); 2820 kml.append("<Style>"); 2821 kml.append("<IconStyle>"); 2822 kml.append("<scale>" + kmlScale + "</scale>"); 2823 kml.append("<heading>" + angle + "</heading>"); 2824 kml.append("<Icon>"); 2825 kml.append("<href></href>"); 2826 kml.append("</Icon>"); 2827 kml.append("</IconStyle>"); 2828 kml.append("<LabelStyle>"); 2829 kml.append("<color>" + color + "</color>"); 2830 kml.append("<scale>" + String.valueOf(kmlScale) +"</scale>"); 2831 kml.append("</LabelStyle>"); 2832 kml.append("</Style>"); 2833 kml.append("<Point>"); 2834 kml.append("<extrude>1</extrude>"); 2835 kml.append("<altitudeMode>relativeToGround</altitudeMode>"); 2836 kml.append("<coordinates>"); 2837 kml.append(longitude); 2838 kml.append(","); 2839 kml.append(latitude); 2840 kml.append("</coordinates>"); 2841 kml.append("</Point>"); 2842 kml.append("</Placemark>"); 2843 } else { 2844 return ""; 2845 } 2846 2847 return kml.toString(); 2848 } 2849 2850 /** 2851 * 2852 * @param shapeInfo 2853 * @param ipc 2854 * @param normalize 2855 * @return 2856 * @deprecated 2857 */ 2858 private static String LabelToJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2859 StringBuilder JSONed = new StringBuilder(); 2860 /* 2861 NOTE: Google Earth / KML colors are backwards. 2862 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2863 * */ 2864 JSONed.append("{\"label\":"); 2865 2866 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2867 Point2D geoCoord = ipc.PixelsToGeo(coord); 2868 if (normalize) { 2869 geoCoord = NormalizeCoordToGECoord(geoCoord); 2870 } 2871 double latitude = geoCoord.getY(); 2872 double longitude = geoCoord.getX(); 2873 double angle = shapeInfo.getModifierAngle(); 2874 coord.setLocation(longitude, latitude); 2875 2876 shapeInfo.setGlyphPosition(coord); 2877 2878 String text = shapeInfo.getModifierString(); 2879 2880 if (text != null && text.equals("") == false) { 2881 JSONed.append("["); 2882 JSONed.append(longitude); 2883 JSONed.append(","); 2884 JSONed.append(latitude); 2885 JSONed.append("]"); 2886 2887 JSONed.append(",\"text\":\""); 2888 JSONed.append(text); 2889 JSONed.append("\""); 2890 2891 JSONed.append(",\"angle\":\""); 2892 JSONed.append(angle); 2893 JSONed.append("\"}"); 2894 } else { 2895 return ""; 2896 } 2897 2898 return JSONed.toString(); 2899 } 2900 2901 public static String canRenderMultiPoint(String symbolID, Map<String,String> modifiers, int numPoints) { 2902 try { 2903 String basicID = SymbolUtilities.getBasicSymbolID(symbolID); 2904 MSInfo info = MSLookup.getInstance().getMSLInfo(symbolID); 2905 2906 if (info == null) { 2907 if (SymbolID.getVersion(symbolID) >= SymbolID.Version_2525E) { 2908 return"Basic ID: " + basicID + " not recognized in version E (15)"; 2909 } else { 2910 return "Basic ID: " + basicID + " not recognized in version D (11)"; 2911 } 2912 } 2913 2914 int drawRule = info.getDrawRule(); 2915 2916 if (drawRule == DrawRules.DONOTDRAW) { 2917 return "Basic ID: " + basicID + " has no draw rule"; 2918 } else if (!SymbolUtilities.isMultiPoint(symbolID)) { 2919 return "Basic ID: " + basicID + " is not a multipoint symbol"; 2920 } else if (numPoints < info.getMinPointCount()) { 2921 return "Basic ID: " + basicID + " requires a minimum of " + String.valueOf(info.getMinPointCount()) + " points. " + String.valueOf(numPoints) + " are present."; 2922 } 2923 2924 //now check for required modifiers 2925 ArrayList<Double> AM = new ArrayList(); 2926 ArrayList<Double> AN = new ArrayList(); 2927 if (modifiers.containsKey(Modifiers.AM_DISTANCE)) { 2928 String[] amArray = modifiers.get(Modifiers.AM_DISTANCE).split(","); 2929 for (String str : amArray) { 2930 if (!str.equals("")) { 2931 AM.add(Double.parseDouble(str)); 2932 } 2933 } 2934 } 2935 if (modifiers.containsKey(Modifiers.AN_AZIMUTH)) { 2936 String[] anArray = modifiers.get(Modifiers.AN_AZIMUTH).split(","); 2937 for (String str : anArray) { 2938 if (!str.equals("")) { 2939 AN.add(Double.parseDouble(str)); 2940 } 2941 } 2942 } 2943 2944 return hasRequiredModifiers(symbolID, drawRule, AM, AN); 2945 } catch (Exception exc) { 2946 ErrorLogger.LogException("MultiPointHandler", "canRenderMultiPoint", exc); 2947 return "false: " + exc.getMessage(); 2948 } 2949 } 2950 2951 static private String hasRequiredModifiers(String symbolID, int drawRule, ArrayList<Double> AM, ArrayList<Double> AN) { 2952 2953 String message = symbolID; 2954 try { 2955 if (drawRule > 700) { 2956 if (drawRule == DrawRules.CIRCULAR1) 2957 { 2958 if (AM != null && AM.size() > 0) { 2959 return "true"; 2960 } else { 2961 message += " requires a modifiers object that has 1 distance/AM value."; 2962 return message; 2963 } 2964 } else if (drawRule == DrawRules.RECTANGULAR2) 2965 { 2966 if (AM != null && AM.size() >= 2 2967 && AN != null && AN.size() >= 1) { 2968 return "true"; 2969 } else { 2970 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 2971 return message; 2972 } 2973 } else if (drawRule == DrawRules.ARC1) 2974 { 2975 if (AM != null && AM.size() >= 1 2976 && AN != null && AN.size() >= 2) { 2977 return "true"; 2978 } else { 2979 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."); 2980 return message; 2981 } 2982 } else if (drawRule == DrawRules.CIRCULAR2) 2983 { 2984 if (AM != null && AM.size() > 0) { 2985 return "true"; 2986 } else { 2987 message += (" requires a modifiers object that has at least 1 distance/AM value"); 2988 return message; 2989 } 2990 } else if (drawRule == DrawRules.RECTANGULAR1) 2991 { 2992 if (AM != null && AM.size() > 0) { 2993 return "true"; 2994 } else { 2995 message += (" requires a modifiers object that has 1 distance/AM value."); 2996 return message; 2997 } 2998 } else if (drawRule == DrawRules.ELLIPSE1) 2999 { 3000 if (AM != null && AM.size() >= 2 3001 && AN != null && AN.size() >= 1) { 3002 return "true"; 3003 } else { 3004 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 3005 return message; 3006 } 3007 } 3008 else if (drawRule == DrawRules.RECTANGULAR3) 3009 { 3010 if (AM != null && AM.size() >= 1) { 3011 return "true"; 3012 } else { 3013 message += (" requires a modifiers object that has 1 distance/AM value."); 3014 return message; 3015 } 3016 } else { 3017 //should never get here 3018 return "true"; 3019 } 3020 } else if (drawRule == DrawRules.POINT17) { 3021 if (AM != null && AM.size() >= 2 3022 && AN != null && AN.size() >= 1) { 3023 return "true"; 3024 } else { 3025 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 3026 return message; 3027 } 3028 } else if (drawRule == DrawRules.POINT18) { 3029 if (AM != null && AM.size() >= 2 3030 && AN != null && AN.size() >= 2) { 3031 return "true"; 3032 } else { 3033 message += (" requires a modifiers object that has 2 distance/AM values and 2 azimuth/AN values."); 3034 return message; 3035 } 3036 } else if (drawRule == DrawRules.CORRIDOR1) { 3037 if (AM != null && AM.size() > 0) { 3038 return "true"; 3039 } else { 3040 message += (" requires a modifiers object that has 1 distance/AM value."); 3041 return message; 3042 } 3043 } else { 3044 //no required parameters 3045 return "true"; 3046 } 3047 } catch (Exception exc) { 3048 ErrorLogger.LogException("MultiPointHandler", "hasRequiredModifiers", exc); 3049 return "true"; 3050 } 3051 } 3052 3053 /** 3054 * 3055 * @param id 3056 * @param name 3057 * @param description 3058 * @param basicShapeType 3059 * @param controlPoints 3060 * @param scale 3061 * @param bbox 3062 * @param symbolModifiers 3063 * @param symbolAttributes 3064 * @return 3065 */ 3066 public static MilStdSymbol RenderBasicShapeAsMilStdSymbol(String id, 3067 String name, 3068 String description, 3069 int basicShapeType, 3070 String controlPoints, 3071 Double scale, 3072 String bbox, 3073 Map<String,String> symbolModifiers, 3074 Map<String,String> symbolAttributes) 3075 { 3076 MilStdSymbol mSymbol = null; 3077 boolean normalize = true; 3078 Double controlLat = 0.0; 3079 Double controlLong = 0.0; 3080 //String jsonContent = ""; 3081 3082 Rectangle rect = null; 3083 3084 //for symbol & line fill 3085 ArrayList<POINT2> tgPoints = null; 3086 3087 String[] coordinates = controlPoints.split(" "); 3088 ArrayList<ShapeInfo> shapes = null;//new ArrayList<ShapeInfo>(); 3089 ArrayList<ShapeInfo> modifiers = null;//new ArrayList<ShapeInfo>(); 3090 //ArrayList<Point2D> pixels = new ArrayList<Point2D>(); 3091 ArrayList<Point2D> geoCoords = new ArrayList<Point2D>(); 3092 int len = coordinates.length; 3093 3094 IPointConversion ipc = null; 3095 3096 //Deutch moved section 6-29-11 3097 Double left = 0.0; 3098 Double right = 0.0; 3099 Double top = 0.0; 3100 Double bottom = 0.0; 3101 Point2D temp = null; 3102 Point2D ptGeoUL = null; 3103 int width = 0; 3104 int height = 0; 3105 int leftX = 0; 3106 int topY = 0; 3107 int bottomY = 0; 3108 int rightX = 0; 3109 int j = 0; 3110 ArrayList<Point2D> bboxCoords = null; 3111 if (bbox != null && bbox.equals("") == false) { 3112 String[] bounds = null; 3113 if (bbox.contains(" "))//trapezoid 3114 { 3115 bboxCoords = new ArrayList<Point2D>(); 3116 double x = 0; 3117 double y = 0; 3118 String[] coords = bbox.split(" "); 3119 String[] arrCoord; 3120 for (String coord : coords) { 3121 arrCoord = coord.split(","); 3122 x = Double.valueOf(arrCoord[0]); 3123 y = Double.valueOf(arrCoord[1]); 3124 bboxCoords.add(new Point2D.Double(x, y)); 3125 } 3126 //use the upper left corner of the MBR containing geoCoords 3127 //to set the converter 3128 ptGeoUL = getGeoUL(bboxCoords); 3129 left = ptGeoUL.getX(); 3130 top = ptGeoUL.getY(); 3131 ipc = new PointConverter(left, top, scale); 3132 Point2D ptPixels = null; 3133 Point2D ptGeo = null; 3134 int n = bboxCoords.size(); 3135 //for (j = 0; j < bboxCoords.size(); j++) 3136 for (j = 0; j < n; j++) { 3137 ptGeo = bboxCoords.get(j); 3138 ptPixels = ipc.GeoToPixels(ptGeo); 3139 x = ptPixels.getX(); 3140 y = ptPixels.getY(); 3141 if (x < 20) { 3142 x = 20; 3143 } 3144 if (y < 20) { 3145 y = 20; 3146 } 3147 ptPixels.setLocation(x, y); 3148 //end section 3149 bboxCoords.set(j, (Point2D) ptPixels); 3150 } 3151 } else//rectangle 3152 { 3153 bounds = bbox.split(","); 3154 left = Double.valueOf(bounds[0]); 3155 right = Double.valueOf(bounds[2]); 3156 top = Double.valueOf(bounds[3]); 3157 bottom = Double.valueOf(bounds[1]); 3158 scale = getReasonableScale(bbox, scale); 3159 ipc = new PointConverter(left, top, scale); 3160 } 3161 3162 Point2D pt2d = null; 3163 if (bboxCoords == null) { 3164 pt2d = new Point2D.Double(left, top); 3165 temp = ipc.GeoToPixels(pt2d); 3166 3167 leftX = (int) temp.getX(); 3168 topY = (int) temp.getY(); 3169 3170 pt2d = new Point2D.Double(right, bottom); 3171 temp = ipc.GeoToPixels(pt2d); 3172 3173 bottomY = (int) temp.getY(); 3174 rightX = (int) temp.getX(); 3175 //diagnostic clipping does not work for large scales 3176// if (scale > 10e6) { 3177// //get widest point in the AOI 3178// double midLat = 0; 3179// if (bottom < 0 && top > 0) { 3180// midLat = 0; 3181// } else if (bottom < 0 && top < 0) { 3182// midLat = top; 3183// } else if (bottom > 0 && top > 0) { 3184// midLat = bottom; 3185// } 3186// 3187// temp = ipc.GeoToPixels(new Point2D.Double(right, midLat)); 3188// rightX = (int) temp.getX(); 3189// } 3190 //end section 3191 3192 width = (int) Math.abs(rightX - leftX); 3193 height = (int) Math.abs(bottomY - topY); 3194 3195 if(width==0 || height==0) 3196 rect=null; 3197 else 3198 rect = new Rectangle(leftX, topY, width, height); 3199 } 3200 } else { 3201 rect = null; 3202 } 3203 //end section 3204 3205 for (int i = 0; i < len; i++) { 3206 String[] coordPair = coordinates[i].split(","); 3207 Double latitude = Double.valueOf(coordPair[1].trim()); 3208 Double longitude = Double.valueOf(coordPair[0].trim()); 3209 geoCoords.add(new Point2D.Double(longitude, latitude)); 3210 } 3211 if (ipc == null) { 3212 Point2D ptCoordsUL = getGeoUL(geoCoords); 3213 ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale); 3214 } 3215 //if (crossesIDL(geoCoords) == true) 3216// if(Math.abs(right-left)>180) 3217// { 3218// normalize = true; 3219// ((PointConverter)ipc).set_normalize(true); 3220// } 3221// else { 3222// normalize = false; 3223// ((PointConverter)ipc).set_normalize(false); 3224// } 3225 3226 //seems to work ok at world view 3227// if (normalize) { 3228// NormalizeGECoordsToGEExtents(0, 360, geoCoords); 3229// } 3230 3231 //M. Deutch 10-3-11 3232 //must shift the rect pixels to synch with the new ipc 3233 //the old ipc was in synch with the bbox, so rect x,y was always 0,0 3234 //the new ipc synchs with the upper left of the geocoords so the boox is shifted 3235 //and therefore the clipping rectangle must shift by the delta x,y between 3236 //the upper left corner of the original bbox and the upper left corner of the geocoords 3237 ArrayList<Point2D> geoCoords2 = new ArrayList<Point2D>(); 3238 geoCoords2.add(new Point2D.Double(left, top)); 3239 geoCoords2.add(new Point2D.Double(right, bottom)); 3240 3241// if (normalize) { 3242// NormalizeGECoordsToGEExtents(0, 360, geoCoords2); 3243// } 3244 3245 //disable clipping 3246 if (crossesIDL(geoCoords) == false) { 3247 rect = null; 3248 bboxCoords = null; 3249 } 3250 3251 String symbolCode = ""; 3252 try { 3253 String fillColor = null; 3254 mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null); 3255 3256// mSymbol.setUseDashArray(true); 3257 3258 if (symbolModifiers != null || symbolAttributes != null) { 3259 populateModifiers(symbolModifiers, symbolAttributes, mSymbol); 3260 } else { 3261 mSymbol.setFillColor(null); 3262 } 3263 3264 if (mSymbol.getFillColor() != null) { 3265 Color fc = mSymbol.getFillColor(); 3266 //fillColor = Integer.toHexString(fc.getRGB()); 3267 fillColor = Integer.toHexString(fc.toARGB()); 3268 } 3269 3270 TGLight tg = clsRenderer.createTGLightFromMilStdSymbolBasicShape(mSymbol, ipc, basicShapeType); 3271 ArrayList<ShapeInfo> shapeInfos = new ArrayList(); 3272 ArrayList<ShapeInfo> modifierShapeInfos = new ArrayList(); 3273 Object clipArea; 3274 if (bboxCoords == null) { 3275 clipArea = rect; 3276 } else { 3277 clipArea = bboxCoords; 3278 } 3279 if (clsRenderer.intersectsClipArea(tg, ipc, clipArea)) { 3280 clsRenderer.render_GE(tg, shapeInfos, modifierShapeInfos, ipc, clipArea); 3281 } 3282 mSymbol.setSymbolShapes(shapeInfos); 3283 mSymbol.setModifierShapes(modifierShapeInfos); 3284 mSymbol.set_WasClipped(tg.get_WasClipped()); 3285 shapes = mSymbol.getSymbolShapes(); 3286 modifiers = mSymbol.getModifierShapes(); 3287 3288 //convert points//////////////////////////////////////////////////// 3289 ArrayList<ArrayList<Point2D>> polylines = null; 3290 ArrayList<ArrayList<Point2D>> newPolylines = null; 3291 ArrayList<Point2D> newLine = null; 3292 for (ShapeInfo shape : shapes) { 3293 polylines = shape.getPolylines(); 3294 //System.out.println("pixel polylines: " + String.valueOf(polylines)); 3295 newPolylines = ConvertPolylinePixelsToCoords(polylines, ipc, normalize); 3296 shape.setPolylines(newPolylines); 3297 } 3298 3299 for (ShapeInfo label : modifiers) { 3300 Point2D pixelCoord = label.getModifierPosition(); 3301 if (pixelCoord == null) { 3302 pixelCoord = label.getGlyphPosition(); 3303 } 3304 Point2D geoCoord = ipc.PixelsToGeo(pixelCoord); 3305 3306 if (normalize) { 3307 geoCoord = NormalizeCoordToGECoord(geoCoord); 3308 } 3309 3310 double latitude = geoCoord.getY(); 3311 double longitude = geoCoord.getX(); 3312 label.setModifierPosition(new Point2D.Double(longitude, latitude)); 3313 3314 } 3315 3316 //////////////////////////////////////////////////////////////////// 3317 mSymbol.setModifierShapes(modifiers); 3318 mSymbol.setSymbolShapes(shapes); 3319 3320 } catch (Exception exc) { 3321 System.out.println(exc.getMessage()); 3322 System.out.println("Symbol Code: " + symbolCode); 3323 exc.printStackTrace(); 3324 } 3325 3326 boolean debug = false; 3327 if (debug == true) { 3328 System.out.println("Symbol Code: " + symbolCode); 3329 System.out.println("Scale: " + scale); 3330 System.out.println("BBOX: " + bbox); 3331 if (controlPoints != null) { 3332 System.out.println("Geo Points: " + controlPoints); 3333 } 3334 if (bbox != null) { 3335 System.out.println("geo bounds: " + bbox); 3336 } 3337 if (rect != null) { 3338 System.out.println("pixel bounds: " + rect.toString()); 3339 } 3340 } 3341 3342 return mSymbol; 3343 3344 } 3345 3346 /** 3347 * 3348 * @param id - For the client to track the symbol, not related to rendering 3349 * @param name - For the client to track the symbol, not related to rendering 3350 * @param description - For the client to track the symbol, not related to rendering 3351 * @param basicShapeType 3352 * @param controlPoints 3353 * @param scale 3354 * @param bbox 3355 * @param symbolModifiers keyed using constants from 3356 * Modifiers. Pass in comma delimited String for modifiers with multiple 3357 * values like AM, AN & X 3358 * @param symbolAttributes keyed using constants from 3359 * MilStdAttributes. pass in double[] for AM, AN and X; Strings for the 3360 * rest. 3361 * @param format 3362 * @return 3363 */ 3364 public static String RenderBasicShape(String id, 3365 String name, 3366 String description, 3367 int basicShapeType, 3368 String controlPoints, 3369 Double scale, 3370 String bbox, 3371 Map<String,String> symbolModifiers, 3372 Map<String,String> symbolAttributes, 3373 int format)//, 3374 { 3375 boolean normalize = true; 3376 //Double controlLat = 0.0; 3377 //Double controlLong = 0.0; 3378 //Double metPerPix = GeoPixelConversion.metersPerPixel(scale); 3379 //String bbox2=getBoundingRectangle(controlPoints,bbox); 3380 StringBuilder jsonOutput = new StringBuilder(); 3381 String jsonContent = ""; 3382 3383 Rectangle rect = null; 3384 String[] coordinates = controlPoints.split(" "); 3385 ArrayList<ShapeInfo> shapes = new ArrayList<ShapeInfo>(); 3386 ArrayList<ShapeInfo> modifiers = new ArrayList<ShapeInfo>(); 3387 //ArrayList<Point2D> pixels = new ArrayList<Point2D>(); 3388 ArrayList<Point2D> geoCoords = new ArrayList<Point2D>(); 3389 int len = coordinates.length; 3390 //diagnostic create geoCoords here 3391 Point2D coordsUL=null; 3392 final String symbolCode = ""; 3393 3394 for (int i = 0; i < len; i++) 3395 { 3396 String[] coordPair = coordinates[i].split(","); 3397 Double latitude = Double.valueOf(coordPair[1].trim()).doubleValue(); 3398 Double longitude = Double.valueOf(coordPair[0].trim()).doubleValue(); 3399 geoCoords.add(new Point2D.Double(longitude, latitude)); 3400 } 3401 ArrayList<POINT2> tgPoints = null; 3402 IPointConversion ipc = null; 3403 3404 //Deutch moved section 6-29-11 3405 Double left = 0.0; 3406 Double right = 0.0; 3407 Double top = 0.0; 3408 Double bottom = 0.0; 3409 Point2D temp = null; 3410 Point2D ptGeoUL = null; 3411 int width = 0; 3412 int height = 0; 3413 int leftX = 0; 3414 int topY = 0; 3415 int bottomY = 0; 3416 int rightX = 0; 3417 int j = 0; 3418 ArrayList<Point2D> bboxCoords = null; 3419 if (bbox != null && bbox.equals("") == false) { 3420 String[] bounds = null; 3421 if (bbox.contains(" "))//trapezoid 3422 { 3423 bboxCoords = new ArrayList<Point2D>(); 3424 double x = 0; 3425 double y = 0; 3426 String[] coords = bbox.split(" "); 3427 String[] arrCoord; 3428 for (String coord : coords) { 3429 arrCoord = coord.split(","); 3430 x = Double.valueOf(arrCoord[0]); 3431 y = Double.valueOf(arrCoord[1]); 3432 bboxCoords.add(new Point2D.Double(x, y)); 3433 } 3434 //use the upper left corner of the MBR containing geoCoords 3435 //to set the converter 3436 ptGeoUL = getGeoUL(bboxCoords); 3437 left = ptGeoUL.getX(); 3438 top = ptGeoUL.getY(); 3439 String bbox2=getBboxFromCoords(bboxCoords); 3440 scale = getReasonableScale(bbox2, scale); 3441 ipc = new PointConverter(left, top, scale); 3442 Point2D ptPixels = null; 3443 Point2D ptGeo = null; 3444 int n = bboxCoords.size(); 3445 //for (j = 0; j < bboxCoords.size(); j++) 3446 for (j = 0; j < n; j++) { 3447 ptGeo = bboxCoords.get(j); 3448 ptPixels = ipc.GeoToPixels(ptGeo); 3449 x = ptPixels.getX(); 3450 y = ptPixels.getY(); 3451 if (x < 20) { 3452 x = 20; 3453 } 3454 if (y < 20) { 3455 y = 20; 3456 } 3457 ptPixels.setLocation(x, y); 3458 //end section 3459 bboxCoords.set(j, (Point2D) ptPixels); 3460 } 3461 } else//rectangle 3462 { 3463 bounds = bbox.split(","); 3464 left = Double.valueOf(bounds[0]); 3465 right = Double.valueOf(bounds[2]); 3466 top = Double.valueOf(bounds[3]); 3467 bottom = Double.valueOf(bounds[1]); 3468 scale = getReasonableScale(bbox, scale); 3469 ipc = new PointConverter(left, top, scale); 3470 } 3471 3472 Point2D pt2d = null; 3473 if (bboxCoords == null) { 3474 pt2d = new Point2D.Double(left, top); 3475 temp = ipc.GeoToPixels(pt2d); 3476 3477 leftX = (int) temp.getX(); 3478 topY = (int) temp.getY(); 3479 3480 pt2d = new Point2D.Double(right, bottom); 3481 temp = ipc.GeoToPixels(pt2d); 3482 3483 bottomY = (int) temp.getY(); 3484 rightX = (int) temp.getX(); 3485 3486 width = (int) Math.abs(rightX - leftX); 3487 height = (int) Math.abs(bottomY - topY); 3488 3489 rect = new Rectangle(leftX, topY, width, height); 3490 } 3491 } else { 3492 rect = null; 3493 } 3494 3495 if (ipc == null) { 3496 Point2D ptCoordsUL = getGeoUL(geoCoords); 3497 ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale); 3498 } 3499 3500 ArrayList<Point2D> geoCoords2 = new ArrayList<Point2D>(); 3501 geoCoords2.add(new Point2D.Double(left, top)); 3502 geoCoords2.add(new Point2D.Double(right, bottom)); 3503 3504// if (normalize) { 3505// NormalizeGECoordsToGEExtents(0, 360, geoCoords2); 3506// } 3507 3508 try { 3509 3510 //String fillColor = null; 3511 MilStdSymbol mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null); 3512 3513 if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG){ 3514 // Use dash array and hatch pattern fill for SVG output 3515 symbolAttributes.put(MilStdAttributes.UseDashArray, "true"); 3516 symbolAttributes.put(MilStdAttributes.UsePatternFill, "true"); 3517 } 3518 3519 if (symbolModifiers != null || symbolAttributes != null) { 3520 populateModifiers(symbolModifiers, symbolAttributes, mSymbol); 3521 } else { 3522 mSymbol.setFillColor(null); 3523 } 3524 3525 TGLight tg = clsRenderer.createTGLightFromMilStdSymbolBasicShape(mSymbol, ipc, basicShapeType); 3526 ArrayList<ShapeInfo> shapeInfos = new ArrayList(); 3527 ArrayList<ShapeInfo> modifierShapeInfos = new ArrayList(); 3528 Object clipArea; 3529 if (bboxCoords == null) { 3530 clipArea = rect; 3531 } else { 3532 clipArea = bboxCoords; 3533 } 3534 if (clsRenderer.intersectsClipArea(tg, ipc, clipArea)) { 3535 clsRenderer.render_GE(tg, shapeInfos, modifierShapeInfos, ipc, clipArea); 3536 } 3537 mSymbol.setSymbolShapes(shapeInfos); 3538 mSymbol.setModifierShapes(modifierShapeInfos); 3539 mSymbol.set_WasClipped(tg.get_WasClipped()); 3540 shapes = mSymbol.getSymbolShapes(); 3541 modifiers = mSymbol.getModifierShapes(); 3542 3543 if (format == WebRenderer.OUTPUT_FORMAT_JSON) { 3544 jsonOutput.append("{\"type\":\"symbol\","); 3545 jsonContent = JSONize(shapes, modifiers, ipc, true, normalize); 3546 jsonOutput.append(jsonContent); 3547 jsonOutput.append("}"); 3548 } else if (format == WebRenderer.OUTPUT_FORMAT_KML) { 3549 Color textColor = mSymbol.getTextColor(); 3550 if(textColor==null) 3551 textColor=mSymbol.getLineColor(); 3552 3553 jsonContent = KMLize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor); 3554 jsonOutput.append(jsonContent); 3555 } else if (format == WebRenderer.OUTPUT_FORMAT_GEOJSON) 3556 { 3557 jsonOutput.append("{\"type\":\"FeatureCollection\",\"features\":"); 3558 jsonContent = GeoJSONize(shapes, modifiers, ipc, normalize, mSymbol.getTextColor(), mSymbol.getTextBackgroundColor()); 3559 jsonOutput.append(jsonContent); 3560 3561 //moving meta data properties to the last feature with no coords as feature collection doesn't allow properties 3562 jsonOutput.replace(jsonOutput.toString().length()-1,jsonOutput.toString().length(),"" ); 3563 if (jsonContent.length() > 2) 3564 jsonOutput.append(","); 3565 jsonOutput.append("{\"type\": \"Feature\",\"geometry\": { \"type\": \"Polygon\",\"coordinates\": [ ]}"); 3566 3567 jsonOutput.append(",\"properties\":{\"id\":\""); 3568 jsonOutput.append(id); 3569 jsonOutput.append("\",\"name\":\""); 3570 jsonOutput.append(name); 3571 jsonOutput.append("\",\"description\":\""); 3572 jsonOutput.append(description); 3573 jsonOutput.append("\",\"symbolID\":\""); 3574 jsonOutput.append(symbolCode); 3575 jsonOutput.append("\",\"wasClipped\":\""); 3576 jsonOutput.append(String.valueOf(mSymbol.get_WasClipped())); 3577 //jsonOutput.append("\"}}"); 3578 3579 jsonOutput.append("\"}}]}"); 3580 } else if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG) { 3581 String textColor = mSymbol.getTextColor() != null ? RendererUtilities.colorToHexString(mSymbol.getTextColor(), false) : ""; 3582 String backgroundColor = mSymbol.getTextBackgroundColor() != null ? RendererUtilities.colorToHexString(mSymbol.getTextBackgroundColor(), false) : ""; 3583 //returns an svg with a geoTL and geoBR value to use to place the canvas on the map 3584 jsonContent = MultiPointHandlerSVG.GeoSVGize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor, backgroundColor, mSymbol.get_WasClipped()); 3585 jsonOutput.append(jsonContent); 3586 } 3587 } catch (Exception exc) { 3588 String st = JavaRendererUtilities.getStackTrace(exc); 3589 jsonOutput = new StringBuilder(); 3590 jsonOutput.append("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + ": " + "- "); 3591 jsonOutput.append(exc.getMessage() + " - "); 3592 jsonOutput.append(st); 3593 jsonOutput.append("\"}"); 3594 3595 ErrorLogger.LogException("MultiPointHandler", "RenderBasicShape", exc); 3596 } 3597 3598 boolean debug = false; 3599 if (debug == true) { 3600 System.out.println("Symbol Code: " + symbolCode); 3601 System.out.println("Scale: " + scale); 3602 System.out.println("BBOX: " + bbox); 3603 if (controlPoints != null) { 3604 System.out.println("Geo Points: " + controlPoints); 3605 } 3606 if (bbox != null) { 3607 System.out.println("geo bounds: " + bbox); 3608 } 3609 if (rect != null) { 3610 System.out.println("pixel bounds: " + rect.toString()); 3611 } 3612 if (jsonOutput != null) { 3613 System.out.println(jsonOutput.toString()); 3614 } 3615 } 3616 3617 ErrorLogger.LogMessage("MultiPointHandler", "RenderBasicShape()", "exit RenderBasicShape", Level.FINER); 3618 return jsonOutput.toString(); 3619 3620 } 3621}