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