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 2104 //Process Anchor point if available 2105 if(shapeInfo.getModifierAnchor() != null) 2106 { 2107 Point2D anchorPoint = ipc.PixelsToGeo(shapeInfo.getModifierAnchor()); 2108 if(normalize) 2109 anchorPoint = NormalizeCoordToGECoord(anchorPoint); 2110 anchorPoint = new Point2D.Double(Math.round(anchorPoint.getX() * 100000000.0) / 100000000.0,Math.round(anchorPoint.getY() * 100000000.0) / 100000000.0); 2111 2112 JSONed.append(",\"anchorPoint\":{\"type\":\"Point\",\"coordinates\":["); 2113 JSONed.append(anchorPoint.getX()); 2114 JSONed.append(","); 2115 JSONed.append(anchorPoint.getY()); 2116 JSONed.append("]"); 2117 JSONed.append("}"); 2118 2119 JSONed.append(",\"anchorOffsetX\":").append(Math.round(shapeInfo.getModifierAnchorOffset().getX())); 2120 JSONed.append(",\"anchorOffsetY\":").append(Math.round(shapeInfo.getModifierAnchorOffset().getY())); 2121 } 2122 2123 JSONed.append(",\"labelOutlineColor\":\""); 2124 JSONed.append(RendererUtilities.colorToHexString(outlineColor, false)); 2125 JSONed.append("\",\"labelOutlineWidth\":"); 2126 JSONed.append("4"); 2127 JSONed.append(",\"rotation\":"); 2128 JSONed.append(angle); 2129 JSONed.append(",\"angle\":"); 2130 JSONed.append(angle); 2131 JSONed.append("},"); 2132 2133 JSONed.append("\"geometry\":{\"type\":\"Point\",\"coordinates\":["); 2134 JSONed.append(longitude); 2135 JSONed.append(","); 2136 JSONed.append(latitude); 2137 JSONed.append("]"); 2138 JSONed.append("}}"); 2139 2140 } else { 2141 return ""; 2142 } 2143 2144 return JSONed.toString(); 2145 } 2146 2147 private static String ShapeToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2148 StringBuilder JSONed = new StringBuilder(); 2149 StringBuilder properties = new StringBuilder(); 2150 StringBuilder geometry = new StringBuilder(); 2151 String geometryType = null; 2152 String sda = null; 2153 /* 2154 NOTE: Google Earth / KML colors are backwards. 2155 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2156 * */ 2157 Color lineColor = shapeInfo.getLineColor(); 2158 Color fillColor = shapeInfo.getFillColor(); 2159 2160 if (shapeInfo.getShapeType() == ShapeInfo.SHAPE_TYPE_FILL || fillColor != null || shapeInfo.getPatternFillImage() != null) { 2161 geometryType = "\"Polygon\""; 2162 } else //if(shapeInfo.getShapeType() == ShapeInfo.SHAPE_TYPE_POLYLINE) 2163 { 2164 geometryType = "\"MultiLineString\""; 2165 } 2166 2167 BasicStroke stroke = null; 2168 stroke = shapeInfo.getStroke(); 2169 int lineWidth = 4; 2170 2171 if (stroke != null) { 2172 lineWidth = (int) stroke.getLineWidth(); 2173 //lineWidth++; 2174 //System.out.println("lineWidth: " + String.valueOf(lineWidth)); 2175 } 2176 2177 //generate JSON properties for feature 2178 properties.append("\"properties\":{"); 2179 properties.append("\"label\":\"\","); 2180 if (lineColor != null) { 2181 properties.append("\"strokeColor\":\"" + RendererUtilities.colorToHexString(lineColor, false) + "\","); 2182 properties.append("\"lineOpacity\":" + String.valueOf(lineColor.getAlpha() / 255f) + ","); 2183 } 2184 if (fillColor != null) { 2185 properties.append("\"fillColor\":\"" + RendererUtilities.colorToHexString(fillColor, false) + "\","); 2186 properties.append("\"fillOpacity\":" + String.valueOf(fillColor.getAlpha() / 255f) + ","); 2187 } 2188 if (shapeInfo.getPatternFillImage() != null) { 2189 properties.append("\"fillPattern\":\"" + bitmapToString(shapeInfo.getPatternFillImage()) + "\","); 2190 } 2191 if(stroke.getDashArray() != null) 2192 { 2193 float[] arrSDA = stroke.getDashArray(); 2194 sda = "["; 2195 sda += String.valueOf(arrSDA[0]); 2196 if(arrSDA.length > 1) 2197 { 2198 for(int i = 1; i < arrSDA.length; i++) 2199 { 2200 sda = sda + ", " + String.valueOf(arrSDA[i]); 2201 } 2202 } 2203 sda += "]"; 2204 sda = "\"strokeDasharray\":" + sda + ","; 2205 properties.append(sda); 2206 } 2207 2208 int lineCap = stroke.getEndCap(); 2209 properties.append("\"lineCap\":" + lineCap + ","); 2210 2211 String strokeWidth = String.valueOf(lineWidth); 2212 properties.append("\"strokeWidth\":" + strokeWidth + ","); 2213 properties.append("\"strokeWeight\":" + strokeWidth + ""); 2214 properties.append("},"); 2215 2216 2217 properties.append("\"style\":{"); 2218 if (lineColor != null) { 2219 properties.append("\"stroke\":\"" + RendererUtilities.colorToHexString(lineColor, false) + "\","); 2220 properties.append("\"line-opacity\":" + String.valueOf(lineColor.getAlpha() / 255f) + ","); 2221 } 2222 if (fillColor != null) { 2223 properties.append("\"fill\":\"" + RendererUtilities.colorToHexString(fillColor, false) + "\","); 2224 properties.append("\"fill-opacity\":" + String.valueOf(fillColor.getAlpha() / 255f) + ","); 2225 } 2226 if(stroke.getDashArray() != null) 2227 { 2228 float[] da = stroke.getDashArray(); 2229 sda = String.valueOf(da[0]); 2230 if(da.length > 1) 2231 { 2232 for(int i = 1; i < da.length; i++) 2233 { 2234 sda = sda + " " + String.valueOf(da[i]); 2235 } 2236 } 2237 sda = "\"stroke-dasharray\":\"" + sda + "\","; 2238 properties.append(sda); 2239 sda = null; 2240 } 2241 2242 if(lineCap == BasicStroke.CAP_SQUARE) 2243 properties.append("\"stroke-linecap\":\"square\","); 2244 else if(lineCap == BasicStroke.CAP_ROUND) 2245 properties.append("\"stroke-linecap\":\"round\","); 2246 else if(lineCap == BasicStroke.CAP_BUTT) 2247 properties.append("\"stroke-linecap\":\"butt\","); 2248 2249 strokeWidth = String.valueOf(lineWidth); 2250 properties.append("\"stroke-width\":" + strokeWidth); 2251 properties.append("}"); 2252 2253 2254 //generate JSON geometry for feature 2255 geometry.append("\"geometry\":{\"type\":"); 2256 geometry.append(geometryType); 2257 geometry.append(",\"coordinates\":["); 2258 2259 ArrayList shapesArray = shapeInfo.getPolylines(); 2260 2261 for (int i = 0; i < shapesArray.size(); i++) { 2262 ArrayList pointList = (ArrayList) shapesArray.get(i); 2263 2264 normalize = normalizePoints(pointList, ipc); 2265 2266 geometry.append("["); 2267 2268 //System.out.println("Pixel Coords:"); 2269 for (int j = 0; j < pointList.size(); j++) { 2270 Point2D coord = (Point2D) pointList.get(j); 2271 Point2D geoCoord = ipc.PixelsToGeo(coord); 2272 //M. Deutch 9-27-11 2273 if (normalize) { 2274 geoCoord = NormalizeCoordToGECoord(geoCoord); 2275 } 2276 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2277 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2278 2279 //fix for fill crossing DTL 2280 if (normalize && fillColor != null) { 2281 if (longitude > 0) { 2282 longitude -= 360; 2283 } 2284 } 2285 2286 //diagnostic M. Deutch 10-18-11 2287 //set the point as geo so that the 2288 //coord.setLocation(longitude, latitude); 2289 coord = new Point2D.Double(longitude, latitude); 2290 pointList.set(j, coord); 2291 //end section 2292 2293 geometry.append("["); 2294 geometry.append(longitude); 2295 geometry.append(","); 2296 geometry.append(latitude); 2297 geometry.append("]"); 2298 2299 if (j < (pointList.size() - 1)) { 2300 geometry.append(","); 2301 } 2302 } 2303 2304 geometry.append("]"); 2305 2306 if (i < (shapesArray.size() - 1)) { 2307 geometry.append(","); 2308 } 2309 } 2310 geometry.append("]}"); 2311 2312 JSONed.append("{\"type\":\"Feature\","); 2313 JSONed.append(properties.toString()); 2314 JSONed.append(","); 2315 JSONed.append(geometry.toString()); 2316 JSONed.append("}"); 2317 2318 return JSONed.toString(); 2319 } 2320 2321 private static String ImageToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2322 2323 StringBuilder JSONed = new StringBuilder(); 2324 StringBuilder properties = new StringBuilder(); 2325 StringBuilder geometry = new StringBuilder(); 2326 2327 //AffineTransform at = shapeInfo.getAffineTransform(); 2328 //Point2D coord = (Point2D)new Point2D.Double(at.getTranslateX(), at.getTranslateY()); 2329 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2330 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 2331 Point2D geoCoord = ipc.PixelsToGeo(coord); 2332 //M. Deutch 9-27-11 2333 if (normalize) { 2334 geoCoord = NormalizeCoordToGECoord(geoCoord); 2335 } 2336 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2337 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2338 double angle = shapeInfo.getModifierAngle(); 2339 coord.setLocation(longitude, latitude); 2340 2341 //diagnostic M. Deutch 10-18-11 2342 shapeInfo.setGlyphPosition(coord); 2343 2344 Bitmap image = shapeInfo.getModifierImage(); 2345 2346 RendererSettings RS = RendererSettings.getInstance(); 2347 2348 if (image != null) { 2349 2350 JSONed.append("{\"type\":\"Feature\",\"properties\":{\"image\":\""); 2351 JSONed.append(bitmapToString(image)); 2352 JSONed.append("\",\"rotation\":"); 2353 JSONed.append(angle); 2354 JSONed.append(",\"angle\":"); 2355 JSONed.append(angle); 2356 //Process Anchor point if available 2357 if(shapeInfo.getModifierAnchor() != null) 2358 { 2359 Point2D anchorPoint = ipc.PixelsToGeo(shapeInfo.getModifierAnchor()); 2360 if(normalize) 2361 anchorPoint = NormalizeCoordToGECoord(anchorPoint); 2362 anchorPoint = new Point2D.Double(Math.round(anchorPoint.getX() * 100000000.0) / 100000000.0,Math.round(anchorPoint.getY() * 100000000.0) / 100000000.0); 2363 2364 JSONed.append(",\"anchorPoint\":{\"type\":\"Point\",\"coordinates\":["); 2365 JSONed.append(anchorPoint.getX()); 2366 JSONed.append(","); 2367 JSONed.append(anchorPoint.getY()); 2368 JSONed.append("]"); 2369 JSONed.append("}"); 2370 2371 JSONed.append(",\"anchorOffsetX\":").append(Math.round(shapeInfo.getModifierAnchorOffset().getX())); 2372 JSONed.append(",\"anchorOffsetY\":").append(Math.round(shapeInfo.getModifierAnchorOffset().getY())); 2373 } 2374 JSONed.append("},"); 2375 JSONed.append("\"geometry\":{\"type\":\"Point\",\"coordinates\":["); 2376 JSONed.append(longitude); 2377 JSONed.append(","); 2378 JSONed.append(latitude); 2379 JSONed.append("]"); 2380 JSONed.append("}}"); 2381 2382 } else { 2383 return ""; 2384 } 2385 2386 return JSONed.toString(); 2387 } 2388 2389 protected static String bitmapToString(Bitmap bitmap) { 2390 final int COMPRESSION_QUALITY = 100; 2391 String encodedImage; 2392 ByteArrayOutputStream byteArrayBitmapStream = new ByteArrayOutputStream(); 2393 bitmap.compress(Bitmap.CompressFormat.PNG, COMPRESSION_QUALITY, 2394 byteArrayBitmapStream); 2395 byte[] b = byteArrayBitmapStream.toByteArray(); 2396 encodedImage = Base64.encodeToString(b, Base64.DEFAULT); 2397 return "data:image/png;base64," + encodedImage; 2398 } 2399 2400 private static String GeoJSONize(ArrayList<ShapeInfo> shapes, ArrayList<ShapeInfo> modifiers, IPointConversion ipc, boolean normalize, Color textColor, Color textBackgroundColor) { 2401 2402 String jstr = ""; 2403 ShapeInfo tempModifier = null; 2404 StringBuilder fc = new StringBuilder();//JSON feature collection 2405 2406 fc.append("["); 2407 2408 int len = shapes.size(); 2409 for (int i = 0; i < len; i++) { 2410 2411 String shapesToAdd = ShapeToGeoJSONString(shapes.get(i), ipc, normalize); 2412 if (shapesToAdd.length() > 0) { 2413 fc.append(shapesToAdd); 2414 if (i < len - 1) { 2415 fc.append(","); 2416 } 2417 } 2418 } 2419 2420 int len2 = modifiers.size(); 2421 2422 for (int j = 0; j < len2; j++) { 2423 tempModifier = modifiers.get(j); 2424 2425 String modifiersToAdd = null; 2426 if(modifiers.get(j).getModifierImage() != null) { 2427 modifiersToAdd = ImageToGeoJSONString(tempModifier, ipc, normalize); 2428 } else { 2429 modifiersToAdd = LabelToGeoJSONString(tempModifier, ipc, normalize, textColor, textBackgroundColor); 2430 } 2431 if (modifiersToAdd.length() > 0) { 2432 if (fc.length() > 1) 2433 fc.append(","); 2434 fc.append(modifiersToAdd); 2435 } 2436 } 2437 fc.append("]"); 2438 String GeoJSON = fc.toString(); 2439 return GeoJSON; 2440 } 2441 2442 /** 2443 * 2444 * @param shapes 2445 * @param modifiers 2446 * @param ipc 2447 * @param normalize 2448 * @deprecated 2449 */ 2450 private static void MakeWWReady( 2451 ArrayList<ShapeInfo> shapes, 2452 ArrayList<ShapeInfo> modifiers, 2453 IPointConversion ipc, 2454 boolean normalize) { 2455 ShapeInfo temp = null; 2456 int len = shapes.size(); 2457 for (int i = 0; i < len; i++) { 2458 2459 temp = ShapeToWWReady(shapes.get(i), ipc, normalize); 2460 shapes.set(i, temp); 2461 2462 } 2463 2464 int len2 = modifiers.size(); 2465 ShapeInfo tempModifier = null; 2466 for (int j = 0; j < len2; j++) { 2467 2468 tempModifier = modifiers.get(j); 2469 2470 //Do we need this for World Wind? 2471 tempModifier = LabelToWWReady(tempModifier, ipc, normalize); 2472 modifiers.set(j, tempModifier); 2473 2474 } 2475 2476 } 2477 2478 static Boolean normalizePoints(ArrayList<Point2D.Double> shape, IPointConversion ipc) { 2479 ArrayList geoCoords = new ArrayList(); 2480 int n = shape.size(); 2481 //for (int j = 0; j < shape.size(); j++) 2482 for (int j = 0; j < n; j++) { 2483 Point2D coord = shape.get(j); 2484 Point2D geoCoord = ipc.PixelsToGeo(coord); 2485 geoCoord = NormalizeCoordToGECoord(geoCoord); 2486 double latitude = geoCoord.getY(); 2487 double longitude = geoCoord.getX(); 2488 Point2D pt2d = new Point2D.Double(longitude, latitude); 2489 geoCoords.add(pt2d); 2490 } 2491 Boolean normalize = crossesIDL(geoCoords); 2492 return normalize; 2493 } 2494 2495 /** 2496 * @deprecated 2497 */ 2498 private static Boolean IsOnePointSymbolCode(String symbolCode) { 2499 String basicCode = SymbolUtilities.getBasicSymbolID(symbolCode); 2500 //TODO: Revisit for basic shapes 2501 //some airspaces affected 2502 if (symbolCode.equals("CAKE-----------")) { 2503 return true; 2504 } else if (symbolCode.equals("CYLINDER-------")) { 2505 return true; 2506 } else if (symbolCode.equals("RADARC---------")) { 2507 return true; 2508 } 2509 2510 return false; 2511 } 2512 2513 private static String ShapeToKMLString(ShapeInfo shapeInfo, 2514 IPointConversion ipc, 2515 boolean normalize) { 2516 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 2517 Color lineColor = null; 2518 Color fillColor = null; 2519 String googleLineColor = null; 2520 String googleFillColor = null; 2521 BasicStroke stroke = null; 2522 int lineWidth = 4; 2523 2524 kml.append("<Placemark>"); 2525 kml.append("<Style>"); 2526 2527 lineColor = shapeInfo.getLineColor(); 2528 if (lineColor != null) { 2529 googleLineColor = Integer.toHexString(shapeInfo.getLineColor().toARGB()); 2530 2531 stroke = shapeInfo.getStroke(); 2532 2533 if (stroke != null) { 2534 lineWidth = (int) stroke.getLineWidth(); 2535 } 2536 2537 googleLineColor = JavaRendererUtilities.ARGBtoABGR(googleLineColor); 2538 2539 kml.append("<LineStyle>"); 2540 kml.append("<color>" + googleLineColor + "</color>"); 2541 kml.append("<colorMode>normal</colorMode>"); 2542 kml.append("<width>" + String.valueOf(lineWidth) + "</width>"); 2543 kml.append("</LineStyle>"); 2544 } 2545 2546 fillColor = shapeInfo.getFillColor(); 2547 Bitmap fillPattern = shapeInfo.getPatternFillImage(); 2548 if (fillColor != null || fillPattern != null) { 2549 kml.append("<PolyStyle>"); 2550 2551 if (fillColor != null) { 2552 googleFillColor = Integer.toHexString(shapeInfo.getFillColor().toARGB()); 2553 googleFillColor = JavaRendererUtilities.ARGBtoABGR(googleFillColor); 2554 kml.append("<color>" + googleFillColor + "</color>"); 2555 kml.append("<colorMode>normal</colorMode>"); 2556 } 2557 if (fillPattern != null){ 2558 kml.append("<shader>" + bitmapToString(fillPattern) + "</shader>"); 2559 } 2560 2561 kml.append("<fill>1</fill>"); 2562 if (lineColor != null) { 2563 kml.append("<outline>1</outline>"); 2564 } else { 2565 kml.append("<outline>0</outline>"); 2566 } 2567 kml.append("</PolyStyle>"); 2568 } 2569 2570 kml.append("</Style>"); 2571 2572 ArrayList shapesArray = shapeInfo.getPolylines(); 2573 int len = shapesArray.size(); 2574 kml.append("<MultiGeometry>"); 2575 2576 for (int i = 0; i < len; i++) { 2577 ArrayList shape = (ArrayList) shapesArray.get(i); 2578 normalize = normalizePoints(shape, ipc); 2579 if (lineColor != null && fillColor == null) { 2580 kml.append("<LineString>"); 2581 kml.append("<tessellate>1</tessellate>"); 2582 kml.append("<altitudeMode>clampToGround</altitudeMode>"); 2583 kml.append("<coordinates>"); 2584 int n = shape.size(); 2585 //for (int j = 0; j < shape.size(); j++) 2586 for (int j = 0; j < n; j++) { 2587 Point2D coord = (Point2D) shape.get(j); 2588 Point2D geoCoord = ipc.PixelsToGeo(coord); 2589 if (normalize) { 2590 geoCoord = NormalizeCoordToGECoord(geoCoord); 2591 } 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 kml.append(longitude); 2597 kml.append(","); 2598 kml.append(latitude); 2599 if(j<shape.size()-1) 2600 kml.append(" "); 2601 } 2602 2603 kml.append("</coordinates>"); 2604 kml.append("</LineString>"); 2605 } 2606 2607 if (fillColor != null) { 2608 2609 if (i == 0) { 2610 kml.append("<Polygon>"); 2611 } 2612 //kml.append("<outerBoundaryIs>"); 2613 if (i == 1 && len > 1) { 2614 kml.append("<innerBoundaryIs>"); 2615 } else { 2616 kml.append("<outerBoundaryIs>"); 2617 } 2618 kml.append("<LinearRing>"); 2619 kml.append("<altitudeMode>clampToGround</altitudeMode>"); 2620 kml.append("<tessellate>1</tessellate>"); 2621 kml.append("<coordinates>"); 2622 2623 int n = shape.size(); 2624 //for (int j = 0; j < shape.size(); j++) 2625 for (int j = 0; j < n; j++) { 2626 Point2D coord = (Point2D) shape.get(j); 2627 Point2D geoCoord = ipc.PixelsToGeo(coord); 2628 2629 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2630 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2631 2632 //fix for fill crossing DTL 2633 if (normalize) { 2634 if (longitude > 0) { 2635 longitude -= 360; 2636 } 2637 } 2638 2639 kml.append(longitude); 2640 kml.append(","); 2641 kml.append(latitude); 2642 if(j<shape.size()-1) 2643 kml.append(" "); 2644 } 2645 2646 kml.append("</coordinates>"); 2647 kml.append("</LinearRing>"); 2648 if (i == 1 && len > 1) { 2649 kml.append("</innerBoundaryIs>"); 2650 } else { 2651 kml.append("</outerBoundaryIs>"); 2652 } 2653 if (i == len - 1) { 2654 kml.append("</Polygon>"); 2655 } 2656 } 2657 } 2658 2659 kml.append("</MultiGeometry>"); 2660 kml.append("</Placemark>"); 2661 2662 return kml.toString(); 2663 } 2664 2665 /** 2666 * 2667 * @param shapeInfo 2668 * @param ipc 2669 * @param normalize 2670 * @return 2671 * @deprecated 2672 */ 2673 private static ShapeInfo ShapeToWWReady( 2674 ShapeInfo shapeInfo, 2675 IPointConversion ipc, 2676 boolean normalize) { 2677 2678 ArrayList shapesArray = shapeInfo.getPolylines(); 2679 int len = shapesArray.size(); 2680 2681 for (int i = 0; i < len; i++) { 2682 ArrayList shape = (ArrayList) shapesArray.get(i); 2683 2684 if (shapeInfo.getLineColor() != null) { 2685 int n = shape.size(); 2686 //for (int j = 0; j < shape.size(); j++) 2687 for (int j = 0; j < n; j++) { 2688 Point2D coord = (Point2D) shape.get(j); 2689 Point2D geoCoord = ipc.PixelsToGeo(coord); 2690 //M. Deutch 9-26-11 2691 if (normalize) { 2692 geoCoord = NormalizeCoordToGECoord(geoCoord); 2693 } 2694 2695 shape.set(j, geoCoord); 2696 2697 } 2698 2699 } 2700 2701 if (shapeInfo.getFillColor() != null) { 2702 int n = shape.size(); 2703 //for (int j = 0; j < shape.size(); j++) 2704 for (int j = 0; j < n; j++) { 2705 Point2D coord = (Point2D) shape.get(j); 2706 Point2D geoCoord = ipc.PixelsToGeo(coord); 2707 //M. Deutch 9-26-11 2708 //commenting these two lines seems to help with fill not go around the pole 2709 //if(normalize) 2710 //geoCoord=NormalizeCoordToGECoord(geoCoord); 2711 2712 shape.set(j, geoCoord); 2713 } 2714 } 2715 } 2716 2717 return shapeInfo; 2718 } 2719 2720 private static ShapeInfo LabelToWWReady(ShapeInfo shapeInfo, 2721 IPointConversion ipc, 2722 boolean normalize) { 2723 2724 try { 2725 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2726 Point2D geoCoord = ipc.PixelsToGeo(coord); 2727 //M. Deutch 9-26-11 2728 if (normalize) { 2729 geoCoord = NormalizeCoordToGECoord(geoCoord); 2730 } 2731 double latitude = geoCoord.getY(); 2732 double longitude = geoCoord.getX(); 2733 long angle = Math.round(shapeInfo.getModifierAngle()); 2734 2735 String text = shapeInfo.getModifierString(); 2736 2737 if (text != null && text.equals("") == false) { 2738 shapeInfo.setModifierPosition(geoCoord); 2739 } else { 2740 return null; 2741 } 2742 } catch (Exception exc) { 2743 System.err.println(exc.getMessage()); 2744 exc.printStackTrace(); 2745 } 2746 2747 return shapeInfo; 2748 } 2749 2750 /** 2751 * Google earth centers text on point rather than drawing from that point. 2752 * So we need to adjust the point to where the center of the text would be. 2753 * 2754 * @param modifier 2755 */ 2756 private static void AdjustModifierPointToCenter(ShapeInfo modifier) { 2757 AffineTransform at = null; 2758 try { 2759 Rectangle bounds2 = modifier.getTextLayout().getBounds(); 2760 Rectangle2D bounds = new Rectangle2D.Double(bounds2.x, bounds2.y, bounds2.width, bounds2.height); 2761 } catch (Exception exc) { 2762 System.err.println(exc.getMessage()); 2763 exc.printStackTrace(); 2764 } 2765 } 2766 2767 /** 2768 * 2769 * @param shapeInfo 2770 * @param ipc 2771 * @param geMap 2772 * @param normalize 2773 * @return 2774 * @deprecated 2775 */ 2776 private static String ShapeToJSONString(ShapeInfo shapeInfo, IPointConversion ipc, Boolean geMap, boolean normalize) { 2777 StringBuilder JSONed = new StringBuilder(); 2778 /* 2779 NOTE: Google Earth / KML colors are backwards. 2780 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2781 * */ 2782 String fillColor = null; 2783 String lineColor = null; 2784 2785 if (shapeInfo.getLineColor() != null) { 2786 lineColor = Integer.toHexString(shapeInfo.getLineColor().toARGB()); 2787 if (geMap) { 2788 lineColor = JavaRendererUtilities.ARGBtoABGR(lineColor); 2789 } 2790 2791 } 2792 if (shapeInfo.getFillColor() != null) { 2793 fillColor = Integer.toHexString(shapeInfo.getFillColor().toARGB()); 2794 if (geMap) { 2795 fillColor = JavaRendererUtilities.ARGBtoABGR(fillColor); 2796 } 2797 } 2798 2799 BasicStroke stroke = null; 2800 stroke = shapeInfo.getStroke(); 2801 int lineWidth = 4; 2802 2803 if (stroke != null) { 2804 lineWidth = (int) stroke.getLineWidth(); 2805 } 2806 2807 ArrayList shapesArray = shapeInfo.getPolylines(); 2808 int n = shapesArray.size(); 2809 //for (int i = 0; i < shapesArray.size(); i++) 2810 for (int i = 0; i < n; i++) { 2811 ArrayList shape = (ArrayList) shapesArray.get(i); 2812 2813 if (fillColor != null) { 2814 JSONed.append("{\"polygon\":["); 2815 } else { 2816 JSONed.append("{\"line\":["); 2817 } 2818 2819 int t = shape.size(); 2820 //for (int j = 0; j < shape.size(); j++) 2821 for (int j = 0; j < t; j++) { 2822 Point2D coord = (Point2D) shape.get(j); 2823 Point2D geoCoord = ipc.PixelsToGeo(coord); 2824 //M. Deutch 9-27-11 2825 if (normalize) { 2826 geoCoord = NormalizeCoordToGECoord(geoCoord); 2827 } 2828 double latitude = geoCoord.getY(); 2829 double longitude = geoCoord.getX(); 2830 2831 //diagnostic M. Deutch 10-18-11 2832 //set the point as geo so that the 2833 coord = new Point2D.Double(longitude, latitude); 2834 shape.set(j, coord); 2835 2836 JSONed.append("["); 2837 JSONed.append(longitude); 2838 JSONed.append(","); 2839 JSONed.append(latitude); 2840 JSONed.append("]"); 2841 2842 if (j < (shape.size() - 1)) { 2843 JSONed.append(","); 2844 } 2845 } 2846 2847 JSONed.append("]"); 2848 if (lineColor != null) { 2849 JSONed.append(",\"lineColor\":\""); 2850 JSONed.append(lineColor); 2851 2852 JSONed.append("\""); 2853 } 2854 if (fillColor != null) { 2855 JSONed.append(",\"fillColor\":\""); 2856 JSONed.append(fillColor); 2857 JSONed.append("\""); 2858 } 2859 2860 JSONed.append(",\"lineWidth\":\""); 2861 JSONed.append(String.valueOf(lineWidth)); 2862 JSONed.append("\""); 2863 2864 JSONed.append("}"); 2865 2866 if (i < (shapesArray.size() - 1)) { 2867 JSONed.append(","); 2868 } 2869 } 2870 2871 return JSONed.toString(); 2872 } 2873 2874 private static String LabelToKMLString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize, Color textColor) { 2875 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 2876 2877 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2878 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 2879 Point2D geoCoord = ipc.PixelsToGeo(coord); 2880 //M. Deutch 9-26-11 2881 if (normalize) { 2882 geoCoord = NormalizeCoordToGECoord(geoCoord); 2883 } 2884 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2885 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2886 long angle = Math.round(shapeInfo.getModifierAngle()); 2887 2888 String text = shapeInfo.getModifierString(); 2889 2890 String cdataStart = "<![CDATA["; 2891 String cdataEnd = "]]>"; 2892 2893 String color = Integer.toHexString(textColor.toARGB()); 2894 color = JavaRendererUtilities.ARGBtoABGR(color); 2895 float kmlScale = RendererSettings.getInstance().getKMLLabelScale(); 2896 2897 if (kmlScale > 0 && text != null && text.equals("") == false) { 2898 kml.append("<Placemark>");//("<Placemark id=\"" + id + "_lp" + i + "\">"); 2899 kml.append("<name>" + cdataStart + text + cdataEnd + "</name>"); 2900 kml.append("<Style>"); 2901 kml.append("<IconStyle>"); 2902 kml.append("<scale>" + kmlScale + "</scale>"); 2903 kml.append("<heading>" + angle + "</heading>"); 2904 kml.append("<Icon>"); 2905 kml.append("<href></href>"); 2906 kml.append("</Icon>"); 2907 kml.append("</IconStyle>"); 2908 kml.append("<LabelStyle>"); 2909 kml.append("<color>" + color + "</color>"); 2910 kml.append("<scale>" + String.valueOf(kmlScale) +"</scale>"); 2911 kml.append("</LabelStyle>"); 2912 kml.append("</Style>"); 2913 kml.append("<Point>"); 2914 kml.append("<extrude>1</extrude>"); 2915 kml.append("<altitudeMode>relativeToGround</altitudeMode>"); 2916 kml.append("<coordinates>"); 2917 kml.append(longitude); 2918 kml.append(","); 2919 kml.append(latitude); 2920 kml.append("</coordinates>"); 2921 kml.append("</Point>"); 2922 kml.append("</Placemark>"); 2923 } else { 2924 return ""; 2925 } 2926 2927 return kml.toString(); 2928 } 2929 2930 /** 2931 * 2932 * @param shapeInfo 2933 * @param ipc 2934 * @param normalize 2935 * @return 2936 * @deprecated 2937 */ 2938 private static String LabelToJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2939 StringBuilder JSONed = new StringBuilder(); 2940 /* 2941 NOTE: Google Earth / KML colors are backwards. 2942 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2943 * */ 2944 JSONed.append("{\"label\":"); 2945 2946 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2947 Point2D geoCoord = ipc.PixelsToGeo(coord); 2948 if (normalize) { 2949 geoCoord = NormalizeCoordToGECoord(geoCoord); 2950 } 2951 double latitude = geoCoord.getY(); 2952 double longitude = geoCoord.getX(); 2953 double angle = shapeInfo.getModifierAngle(); 2954 coord.setLocation(longitude, latitude); 2955 2956 shapeInfo.setGlyphPosition(coord); 2957 2958 String text = shapeInfo.getModifierString(); 2959 2960 if (text != null && text.equals("") == false) { 2961 JSONed.append("["); 2962 JSONed.append(longitude); 2963 JSONed.append(","); 2964 JSONed.append(latitude); 2965 JSONed.append("]"); 2966 2967 JSONed.append(",\"text\":\""); 2968 JSONed.append(text); 2969 JSONed.append("\""); 2970 2971 JSONed.append(",\"angle\":\""); 2972 JSONed.append(angle); 2973 JSONed.append("\"}"); 2974 } else { 2975 return ""; 2976 } 2977 2978 return JSONed.toString(); 2979 } 2980 2981 public static String canRenderMultiPoint(String symbolID, Map<String,String> modifiers, int numPoints) { 2982 try { 2983 String basicID = SymbolUtilities.getBasicSymbolID(symbolID); 2984 MSInfo info = MSLookup.getInstance().getMSLInfo(symbolID); 2985 2986 if (info == null) { 2987 if (SymbolID.getVersion(symbolID) >= SymbolID.Version_2525E) { 2988 return"Basic ID: " + basicID + " not recognized in version E (15)"; 2989 } else { 2990 return "Basic ID: " + basicID + " not recognized in version D (11)"; 2991 } 2992 } 2993 2994 int drawRule = info.getDrawRule(); 2995 2996 if (drawRule == DrawRules.DONOTDRAW) { 2997 return "Basic ID: " + basicID + " has no draw rule"; 2998 } else if (!SymbolUtilities.isMultiPoint(symbolID)) { 2999 return "Basic ID: " + basicID + " is not a multipoint symbol"; 3000 } else if (numPoints < info.getMinPointCount()) { 3001 return "Basic ID: " + basicID + " requires a minimum of " + String.valueOf(info.getMinPointCount()) + " points. " + String.valueOf(numPoints) + " are present."; 3002 } 3003 3004 //now check for required modifiers 3005 ArrayList<Double> AM = new ArrayList(); 3006 ArrayList<Double> AN = new ArrayList(); 3007 if (modifiers.containsKey(Modifiers.AM_DISTANCE)) { 3008 String[] amArray = modifiers.get(Modifiers.AM_DISTANCE).split(","); 3009 for (String str : amArray) { 3010 if (!str.equals("")) { 3011 AM.add(Double.parseDouble(str)); 3012 } 3013 } 3014 } 3015 if (modifiers.containsKey(Modifiers.AN_AZIMUTH)) { 3016 String[] anArray = modifiers.get(Modifiers.AN_AZIMUTH).split(","); 3017 for (String str : anArray) { 3018 if (!str.equals("")) { 3019 AN.add(Double.parseDouble(str)); 3020 } 3021 } 3022 } 3023 3024 return hasRequiredModifiers(symbolID, drawRule, AM, AN); 3025 } catch (Exception exc) { 3026 ErrorLogger.LogException("MultiPointHandler", "canRenderMultiPoint", exc); 3027 return "false: " + exc.getMessage(); 3028 } 3029 } 3030 3031 static private String hasRequiredModifiers(String symbolID, int drawRule, ArrayList<Double> AM, ArrayList<Double> AN) { 3032 3033 String message = symbolID; 3034 try { 3035 if (drawRule > 700) { 3036 if (drawRule == DrawRules.CIRCULAR1) 3037 { 3038 if (AM != null && AM.size() > 0) { 3039 return "true"; 3040 } else { 3041 message += " requires a modifiers object that has 1 distance/AM value."; 3042 return message; 3043 } 3044 } else if (drawRule == DrawRules.RECTANGULAR2) 3045 { 3046 if (AM != null && AM.size() >= 2 3047 && AN != null && AN.size() >= 1) { 3048 return "true"; 3049 } else { 3050 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 3051 return message; 3052 } 3053 } else if (drawRule == DrawRules.ARC1) 3054 { 3055 if (AM != null && AM.size() >= 1 3056 && AN != null && AN.size() >= 2) { 3057 return "true"; 3058 } else { 3059 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."); 3060 return message; 3061 } 3062 } else if (drawRule == DrawRules.CIRCULAR2) 3063 { 3064 if (AM != null && AM.size() > 0) { 3065 return "true"; 3066 } else { 3067 message += (" requires a modifiers object that has at least 1 distance/AM value"); 3068 return message; 3069 } 3070 } else if (drawRule == DrawRules.RECTANGULAR1) 3071 { 3072 if (AM != null && AM.size() > 0) { 3073 return "true"; 3074 } else { 3075 message += (" requires a modifiers object that has 1 distance/AM value."); 3076 return message; 3077 } 3078 } else if (drawRule == DrawRules.ELLIPSE1) 3079 { 3080 if (AM != null && AM.size() >= 2 3081 && AN != null && AN.size() >= 1) { 3082 return "true"; 3083 } else { 3084 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 3085 return message; 3086 } 3087 } 3088 else if (drawRule == DrawRules.RECTANGULAR3) 3089 { 3090 if (AM != null && AM.size() >= 1) { 3091 return "true"; 3092 } else { 3093 message += (" requires a modifiers object that has 1 distance/AM value."); 3094 return message; 3095 } 3096 } else { 3097 //should never get here 3098 return "true"; 3099 } 3100 } else if (drawRule == DrawRules.POINT17) { 3101 if (AM != null && AM.size() >= 2 3102 && AN != null && AN.size() >= 1) { 3103 return "true"; 3104 } else { 3105 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 3106 return message; 3107 } 3108 } else if (drawRule == DrawRules.POINT18) { 3109 if (AM != null && AM.size() >= 2 3110 && AN != null && AN.size() >= 2) { 3111 return "true"; 3112 } else { 3113 message += (" requires a modifiers object that has 2 distance/AM values and 2 azimuth/AN values."); 3114 return message; 3115 } 3116 } else if (drawRule == DrawRules.CORRIDOR1) { 3117 if (AM != null && AM.size() > 0) { 3118 return "true"; 3119 } else { 3120 message += (" requires a modifiers object that has 1 distance/AM value."); 3121 return message; 3122 } 3123 } else { 3124 //no required parameters 3125 return "true"; 3126 } 3127 } catch (Exception exc) { 3128 ErrorLogger.LogException("MultiPointHandler", "hasRequiredModifiers", exc); 3129 return "true"; 3130 } 3131 } 3132 3133 /** 3134 * 3135 * @param id 3136 * @param name 3137 * @param description 3138 * @param basicShapeType 3139 * @param controlPoints 3140 * @param scale 3141 * @param bbox 3142 * @param symbolModifiers 3143 * @param symbolAttributes 3144 * @return 3145 */ 3146 public static MilStdSymbol RenderBasicShapeAsMilStdSymbol(String id, 3147 String name, 3148 String description, 3149 int basicShapeType, 3150 String controlPoints, 3151 Double scale, 3152 String bbox, 3153 Map<String,String> symbolModifiers, 3154 Map<String,String> symbolAttributes) 3155 { 3156 MilStdSymbol mSymbol = null; 3157 boolean normalize = true; 3158 Double controlLat = 0.0; 3159 Double controlLong = 0.0; 3160 //String jsonContent = ""; 3161 3162 Rectangle rect = null; 3163 3164 //for symbol & line fill 3165 ArrayList<POINT2> tgPoints = null; 3166 3167 String[] coordinates = controlPoints.split(" "); 3168 ArrayList<ShapeInfo> shapes = null;//new ArrayList<ShapeInfo>(); 3169 ArrayList<ShapeInfo> modifiers = null;//new ArrayList<ShapeInfo>(); 3170 //ArrayList<Point2D> pixels = new ArrayList<Point2D>(); 3171 ArrayList<Point2D> geoCoords = new ArrayList<Point2D>(); 3172 int len = coordinates.length; 3173 3174 IPointConversion ipc = null; 3175 3176 //Deutch moved section 6-29-11 3177 Double left = 0.0; 3178 Double right = 0.0; 3179 Double top = 0.0; 3180 Double bottom = 0.0; 3181 Point2D temp = null; 3182 Point2D ptGeoUL = null; 3183 int width = 0; 3184 int height = 0; 3185 int leftX = 0; 3186 int topY = 0; 3187 int bottomY = 0; 3188 int rightX = 0; 3189 int j = 0; 3190 ArrayList<Point2D> bboxCoords = null; 3191 if (bbox != null && bbox.equals("") == false) { 3192 String[] bounds = null; 3193 if (bbox.contains(" "))//trapezoid 3194 { 3195 bboxCoords = new ArrayList<Point2D>(); 3196 double x = 0; 3197 double y = 0; 3198 String[] coords = bbox.split(" "); 3199 String[] arrCoord; 3200 for (String coord : coords) { 3201 arrCoord = coord.split(","); 3202 x = Double.valueOf(arrCoord[0]); 3203 y = Double.valueOf(arrCoord[1]); 3204 bboxCoords.add(new Point2D.Double(x, y)); 3205 } 3206 //use the upper left corner of the MBR containing geoCoords 3207 //to set the converter 3208 ptGeoUL = getGeoUL(bboxCoords); 3209 left = ptGeoUL.getX(); 3210 top = ptGeoUL.getY(); 3211 ipc = new PointConverter(left, top, scale); 3212 Point2D ptPixels = null; 3213 Point2D ptGeo = null; 3214 int n = bboxCoords.size(); 3215 //for (j = 0; j < bboxCoords.size(); j++) 3216 for (j = 0; j < n; j++) { 3217 ptGeo = bboxCoords.get(j); 3218 ptPixels = ipc.GeoToPixels(ptGeo); 3219 x = ptPixels.getX(); 3220 y = ptPixels.getY(); 3221 if (x < 20) { 3222 x = 20; 3223 } 3224 if (y < 20) { 3225 y = 20; 3226 } 3227 ptPixels.setLocation(x, y); 3228 //end section 3229 bboxCoords.set(j, (Point2D) ptPixels); 3230 } 3231 } else//rectangle 3232 { 3233 bounds = bbox.split(","); 3234 left = Double.valueOf(bounds[0]); 3235 right = Double.valueOf(bounds[2]); 3236 top = Double.valueOf(bounds[3]); 3237 bottom = Double.valueOf(bounds[1]); 3238 scale = getReasonableScale(bbox, scale); 3239 ipc = new PointConverter(left, top, scale); 3240 } 3241 3242 Point2D pt2d = null; 3243 if (bboxCoords == null) { 3244 pt2d = new Point2D.Double(left, top); 3245 temp = ipc.GeoToPixels(pt2d); 3246 3247 leftX = (int) temp.getX(); 3248 topY = (int) temp.getY(); 3249 3250 pt2d = new Point2D.Double(right, bottom); 3251 temp = ipc.GeoToPixels(pt2d); 3252 3253 bottomY = (int) temp.getY(); 3254 rightX = (int) temp.getX(); 3255 //diagnostic clipping does not work for large scales 3256// if (scale > 10e6) { 3257// //get widest point in the AOI 3258// double midLat = 0; 3259// if (bottom < 0 && top > 0) { 3260// midLat = 0; 3261// } else if (bottom < 0 && top < 0) { 3262// midLat = top; 3263// } else if (bottom > 0 && top > 0) { 3264// midLat = bottom; 3265// } 3266// 3267// temp = ipc.GeoToPixels(new Point2D.Double(right, midLat)); 3268// rightX = (int) temp.getX(); 3269// } 3270 //end section 3271 3272 width = (int) Math.abs(rightX - leftX); 3273 height = (int) Math.abs(bottomY - topY); 3274 3275 if(width==0 || height==0) 3276 rect=null; 3277 else 3278 rect = new Rectangle(leftX, topY, width, height); 3279 } 3280 } else { 3281 rect = null; 3282 } 3283 //end section 3284 3285 for (int i = 0; i < len; i++) { 3286 String[] coordPair = coordinates[i].split(","); 3287 Double latitude = Double.valueOf(coordPair[1].trim()); 3288 Double longitude = Double.valueOf(coordPair[0].trim()); 3289 geoCoords.add(new Point2D.Double(longitude, latitude)); 3290 } 3291 if (ipc == null) { 3292 Point2D ptCoordsUL = getGeoUL(geoCoords); 3293 ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale); 3294 } 3295 //if (crossesIDL(geoCoords) == true) 3296// if(Math.abs(right-left)>180) 3297// { 3298// normalize = true; 3299// ((PointConverter)ipc).set_normalize(true); 3300// } 3301// else { 3302// normalize = false; 3303// ((PointConverter)ipc).set_normalize(false); 3304// } 3305 3306 //seems to work ok at world view 3307// if (normalize) { 3308// NormalizeGECoordsToGEExtents(0, 360, geoCoords); 3309// } 3310 3311 //M. Deutch 10-3-11 3312 //must shift the rect pixels to synch with the new ipc 3313 //the old ipc was in synch with the bbox, so rect x,y was always 0,0 3314 //the new ipc synchs with the upper left of the geocoords so the boox is shifted 3315 //and therefore the clipping rectangle must shift by the delta x,y between 3316 //the upper left corner of the original bbox and the upper left corner of the geocoords 3317 ArrayList<Point2D> geoCoords2 = new ArrayList<Point2D>(); 3318 geoCoords2.add(new Point2D.Double(left, top)); 3319 geoCoords2.add(new Point2D.Double(right, bottom)); 3320 3321// if (normalize) { 3322// NormalizeGECoordsToGEExtents(0, 360, geoCoords2); 3323// } 3324 3325 //disable clipping 3326 if (crossesIDL(geoCoords) == false) { 3327 rect = null; 3328 bboxCoords = null; 3329 } 3330 3331 String symbolCode = ""; 3332 try { 3333 String fillColor = null; 3334 mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null); 3335 3336// mSymbol.setUseDashArray(true); 3337 3338 if (symbolModifiers != null || symbolAttributes != null) { 3339 populateModifiers(symbolModifiers, symbolAttributes, mSymbol); 3340 } else { 3341 mSymbol.setFillColor(null); 3342 } 3343 3344 if (mSymbol.getFillColor() != null) { 3345 Color fc = mSymbol.getFillColor(); 3346 //fillColor = Integer.toHexString(fc.getRGB()); 3347 fillColor = Integer.toHexString(fc.toARGB()); 3348 } 3349 3350 TGLight tg = clsRenderer.createTGLightFromMilStdSymbolBasicShape(mSymbol, ipc, basicShapeType); 3351 ArrayList<ShapeInfo> shapeInfos = new ArrayList(); 3352 ArrayList<ShapeInfo> modifierShapeInfos = new ArrayList(); 3353 Object clipArea; 3354 if (bboxCoords == null) { 3355 clipArea = rect; 3356 } else { 3357 clipArea = bboxCoords; 3358 } 3359 if (clsRenderer.intersectsClipArea(tg, ipc, clipArea)) { 3360 clsRenderer.render_GE(tg, shapeInfos, modifierShapeInfos, ipc, clipArea); 3361 } 3362 mSymbol.setSymbolShapes(shapeInfos); 3363 mSymbol.setModifierShapes(modifierShapeInfos); 3364 mSymbol.set_WasClipped(tg.get_WasClipped()); 3365 shapes = mSymbol.getSymbolShapes(); 3366 modifiers = mSymbol.getModifierShapes(); 3367 3368 //convert points//////////////////////////////////////////////////// 3369 ArrayList<ArrayList<Point2D>> polylines = null; 3370 ArrayList<ArrayList<Point2D>> newPolylines = null; 3371 ArrayList<Point2D> newLine = null; 3372 for (ShapeInfo shape : shapes) { 3373 polylines = shape.getPolylines(); 3374 //System.out.println("pixel polylines: " + String.valueOf(polylines)); 3375 newPolylines = ConvertPolylinePixelsToCoords(polylines, ipc, normalize); 3376 shape.setPolylines(newPolylines); 3377 } 3378 3379 for (ShapeInfo label : modifiers) { 3380 Point2D pixelCoord = label.getModifierPosition(); 3381 if (pixelCoord == null) { 3382 pixelCoord = label.getGlyphPosition(); 3383 } 3384 Point2D geoCoord = ipc.PixelsToGeo(pixelCoord); 3385 3386 if (normalize) { 3387 geoCoord = NormalizeCoordToGECoord(geoCoord); 3388 } 3389 3390 double latitude = geoCoord.getY(); 3391 double longitude = geoCoord.getX(); 3392 label.setModifierPosition(new Point2D.Double(longitude, latitude)); 3393 3394 } 3395 3396 //////////////////////////////////////////////////////////////////// 3397 mSymbol.setModifierShapes(modifiers); 3398 mSymbol.setSymbolShapes(shapes); 3399 3400 } catch (Exception exc) { 3401 System.out.println(exc.getMessage()); 3402 System.out.println("Symbol Code: " + symbolCode); 3403 exc.printStackTrace(); 3404 } 3405 3406 boolean debug = false; 3407 if (debug == true) { 3408 System.out.println("Symbol Code: " + symbolCode); 3409 System.out.println("Scale: " + scale); 3410 System.out.println("BBOX: " + bbox); 3411 if (controlPoints != null) { 3412 System.out.println("Geo Points: " + controlPoints); 3413 } 3414 if (bbox != null) { 3415 System.out.println("geo bounds: " + bbox); 3416 } 3417 if (rect != null) { 3418 System.out.println("pixel bounds: " + rect.toString()); 3419 } 3420 } 3421 3422 return mSymbol; 3423 3424 } 3425 3426 /** 3427 * 3428 * @param id - For the client to track the symbol, not related to rendering 3429 * @param name - For the client to track the symbol, not related to rendering 3430 * @param description - For the client to track the symbol, not related to rendering 3431 * @param basicShapeType 3432 * @param controlPoints 3433 * @param scale 3434 * @param bbox 3435 * @param symbolModifiers keyed using constants from 3436 * Modifiers. Pass in comma delimited String for modifiers with multiple 3437 * values like AM, AN & X 3438 * @param symbolAttributes keyed using constants from 3439 * MilStdAttributes. pass in double[] for AM, AN and X; Strings for the 3440 * rest. 3441 * @param format 3442 * @return 3443 */ 3444 public static String RenderBasicShape(String id, 3445 String name, 3446 String description, 3447 int basicShapeType, 3448 String controlPoints, 3449 Double scale, 3450 String bbox, 3451 Map<String,String> symbolModifiers, 3452 Map<String,String> symbolAttributes, 3453 int format)//, 3454 { 3455 boolean normalize = true; 3456 //Double controlLat = 0.0; 3457 //Double controlLong = 0.0; 3458 //Double metPerPix = GeoPixelConversion.metersPerPixel(scale); 3459 //String bbox2=getBoundingRectangle(controlPoints,bbox); 3460 StringBuilder jsonOutput = new StringBuilder(); 3461 String jsonContent = ""; 3462 3463 Rectangle rect = null; 3464 String[] coordinates = controlPoints.split(" "); 3465 ArrayList<ShapeInfo> shapes = new ArrayList<ShapeInfo>(); 3466 ArrayList<ShapeInfo> modifiers = new ArrayList<ShapeInfo>(); 3467 //ArrayList<Point2D> pixels = new ArrayList<Point2D>(); 3468 ArrayList<Point2D> geoCoords = new ArrayList<Point2D>(); 3469 int len = coordinates.length; 3470 //diagnostic create geoCoords here 3471 Point2D coordsUL=null; 3472 final String symbolCode = ""; 3473 3474 for (int i = 0; i < len; i++) 3475 { 3476 String[] coordPair = coordinates[i].split(","); 3477 Double latitude = Double.valueOf(coordPair[1].trim()).doubleValue(); 3478 Double longitude = Double.valueOf(coordPair[0].trim()).doubleValue(); 3479 geoCoords.add(new Point2D.Double(longitude, latitude)); 3480 } 3481 ArrayList<POINT2> tgPoints = null; 3482 IPointConversion ipc = null; 3483 3484 //Deutch moved section 6-29-11 3485 Double left = 0.0; 3486 Double right = 0.0; 3487 Double top = 0.0; 3488 Double bottom = 0.0; 3489 Point2D temp = null; 3490 Point2D ptGeoUL = null; 3491 int width = 0; 3492 int height = 0; 3493 int leftX = 0; 3494 int topY = 0; 3495 int bottomY = 0; 3496 int rightX = 0; 3497 int j = 0; 3498 ArrayList<Point2D> bboxCoords = null; 3499 if (bbox != null && bbox.equals("") == false) { 3500 String[] bounds = null; 3501 if (bbox.contains(" "))//trapezoid 3502 { 3503 bboxCoords = new ArrayList<Point2D>(); 3504 double x = 0; 3505 double y = 0; 3506 String[] coords = bbox.split(" "); 3507 String[] arrCoord; 3508 for (String coord : coords) { 3509 arrCoord = coord.split(","); 3510 x = Double.valueOf(arrCoord[0]); 3511 y = Double.valueOf(arrCoord[1]); 3512 bboxCoords.add(new Point2D.Double(x, y)); 3513 } 3514 //use the upper left corner of the MBR containing geoCoords 3515 //to set the converter 3516 ptGeoUL = getGeoUL(bboxCoords); 3517 left = ptGeoUL.getX(); 3518 top = ptGeoUL.getY(); 3519 String bbox2=getBboxFromCoords(bboxCoords); 3520 scale = getReasonableScale(bbox2, scale); 3521 ipc = new PointConverter(left, top, scale); 3522 Point2D ptPixels = null; 3523 Point2D ptGeo = null; 3524 int n = bboxCoords.size(); 3525 //for (j = 0; j < bboxCoords.size(); j++) 3526 for (j = 0; j < n; j++) { 3527 ptGeo = bboxCoords.get(j); 3528 ptPixels = ipc.GeoToPixels(ptGeo); 3529 x = ptPixels.getX(); 3530 y = ptPixels.getY(); 3531 if (x < 20) { 3532 x = 20; 3533 } 3534 if (y < 20) { 3535 y = 20; 3536 } 3537 ptPixels.setLocation(x, y); 3538 //end section 3539 bboxCoords.set(j, (Point2D) ptPixels); 3540 } 3541 } else//rectangle 3542 { 3543 bounds = bbox.split(","); 3544 left = Double.valueOf(bounds[0]); 3545 right = Double.valueOf(bounds[2]); 3546 top = Double.valueOf(bounds[3]); 3547 bottom = Double.valueOf(bounds[1]); 3548 scale = getReasonableScale(bbox, scale); 3549 ipc = new PointConverter(left, top, scale); 3550 } 3551 3552 Point2D pt2d = null; 3553 if (bboxCoords == null) { 3554 pt2d = new Point2D.Double(left, top); 3555 temp = ipc.GeoToPixels(pt2d); 3556 3557 leftX = (int) temp.getX(); 3558 topY = (int) temp.getY(); 3559 3560 pt2d = new Point2D.Double(right, bottom); 3561 temp = ipc.GeoToPixels(pt2d); 3562 3563 bottomY = (int) temp.getY(); 3564 rightX = (int) temp.getX(); 3565 3566 width = (int) Math.abs(rightX - leftX); 3567 height = (int) Math.abs(bottomY - topY); 3568 3569 rect = new Rectangle(leftX, topY, width, height); 3570 } 3571 } else { 3572 rect = null; 3573 } 3574 3575 if (ipc == null) { 3576 Point2D ptCoordsUL = getGeoUL(geoCoords); 3577 ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale); 3578 } 3579 3580 ArrayList<Point2D> geoCoords2 = new ArrayList<Point2D>(); 3581 geoCoords2.add(new Point2D.Double(left, top)); 3582 geoCoords2.add(new Point2D.Double(right, bottom)); 3583 3584// if (normalize) { 3585// NormalizeGECoordsToGEExtents(0, 360, geoCoords2); 3586// } 3587 3588 try { 3589 3590 //String fillColor = null; 3591 MilStdSymbol mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null); 3592 3593 if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG){ 3594 // Use dash array and hatch pattern fill for SVG output 3595 symbolAttributes.put(MilStdAttributes.UseDashArray, "true"); 3596 symbolAttributes.put(MilStdAttributes.UsePatternFill, "true"); 3597 } 3598 3599 if (symbolModifiers != null || symbolAttributes != null) { 3600 populateModifiers(symbolModifiers, symbolAttributes, mSymbol); 3601 } else { 3602 mSymbol.setFillColor(null); 3603 } 3604 3605 TGLight tg = clsRenderer.createTGLightFromMilStdSymbolBasicShape(mSymbol, ipc, basicShapeType); 3606 ArrayList<ShapeInfo> shapeInfos = new ArrayList(); 3607 ArrayList<ShapeInfo> modifierShapeInfos = new ArrayList(); 3608 Object clipArea; 3609 if (bboxCoords == null) { 3610 clipArea = rect; 3611 } else { 3612 clipArea = bboxCoords; 3613 } 3614 if (clsRenderer.intersectsClipArea(tg, ipc, clipArea)) { 3615 clsRenderer.render_GE(tg, shapeInfos, modifierShapeInfos, ipc, clipArea); 3616 } 3617 mSymbol.setSymbolShapes(shapeInfos); 3618 mSymbol.setModifierShapes(modifierShapeInfos); 3619 mSymbol.set_WasClipped(tg.get_WasClipped()); 3620 shapes = mSymbol.getSymbolShapes(); 3621 modifiers = mSymbol.getModifierShapes(); 3622 3623 if (format == WebRenderer.OUTPUT_FORMAT_JSON) { 3624 jsonOutput.append("{\"type\":\"symbol\","); 3625 jsonContent = JSONize(shapes, modifiers, ipc, true, normalize); 3626 jsonOutput.append(jsonContent); 3627 jsonOutput.append("}"); 3628 } else if (format == WebRenderer.OUTPUT_FORMAT_KML) { 3629 Color textColor = mSymbol.getTextColor(); 3630 if(textColor==null) 3631 textColor=mSymbol.getLineColor(); 3632 3633 jsonContent = KMLize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor, mSymbol.getWasClipped(), mSymbol.isTextScaleSensitive(), mSymbol.isSymbolScaleSensitive()); 3634 jsonOutput.append(jsonContent); 3635 } else if (format == WebRenderer.OUTPUT_FORMAT_GEOJSON) 3636 { 3637 jsonOutput.append("{\"type\":\"FeatureCollection\",\"features\":"); 3638 jsonContent = GeoJSONize(shapes, modifiers, ipc, normalize, mSymbol.getTextColor(), mSymbol.getTextBackgroundColor()); 3639 jsonOutput.append(jsonContent); 3640 3641 //moving meta data properties to the last feature with no coords as feature collection doesn't allow properties 3642 jsonOutput.replace(jsonOutput.toString().length()-1,jsonOutput.toString().length(),"" ); 3643 if (jsonContent.length() > 2) 3644 jsonOutput.append(","); 3645 jsonOutput.append("{\"type\": \"Feature\",\"geometry\": { \"type\": \"Polygon\",\"coordinates\": [ ]}"); 3646 3647 jsonOutput.append(",\"properties\":{\"id\":\""); 3648 jsonOutput.append(id); 3649 jsonOutput.append("\",\"name\":\""); 3650 jsonOutput.append(name); 3651 jsonOutput.append("\",\"description\":\""); 3652 jsonOutput.append(description); 3653 jsonOutput.append("\",\"symbolID\":\""); 3654 jsonOutput.append(symbolCode); 3655 jsonOutput.append("\",\"wasClipped\":\""); 3656 jsonOutput.append(String.valueOf(mSymbol.getWasClipped())); 3657 jsonOutput.append("\",\"textScaleSensitive\":\""); 3658 jsonOutput.append(String.valueOf(mSymbol.isTextScaleSensitive())); 3659 jsonOutput.append("\",\"symbolScaleSensitive\":\""); 3660 jsonOutput.append(String.valueOf(mSymbol.isSymbolScaleSensitive())); 3661 //jsonOutput.append("\"}}"); 3662 3663 jsonOutput.append("\"}}]}"); 3664 } else if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG) { 3665 String textColor = mSymbol.getTextColor() != null ? RendererUtilities.colorToHexString(mSymbol.getTextColor(), false) : ""; 3666 String backgroundColor = mSymbol.getTextBackgroundColor() != null ? RendererUtilities.colorToHexString(mSymbol.getTextBackgroundColor(), false) : ""; 3667 //returns an svg with a geoTL and geoBR value to use to place the canvas on the map 3668 jsonContent = MultiPointHandlerSVG.GeoSVGize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor, backgroundColor, mSymbol.get_WasClipped()); 3669 jsonOutput.append(jsonContent); 3670 } 3671 } catch (Exception exc) { 3672 String st = JavaRendererUtilities.getStackTrace(exc); 3673 jsonOutput = new StringBuilder(); 3674 jsonOutput.append("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + ": " + "- "); 3675 jsonOutput.append(exc.getMessage() + " - "); 3676 jsonOutput.append(st); 3677 jsonOutput.append("\"}"); 3678 3679 ErrorLogger.LogException("MultiPointHandler", "RenderBasicShape", exc); 3680 } 3681 3682 boolean debug = false; 3683 if (debug == true) { 3684 System.out.println("Symbol Code: " + symbolCode); 3685 System.out.println("Scale: " + scale); 3686 System.out.println("BBOX: " + bbox); 3687 if (controlPoints != null) { 3688 System.out.println("Geo Points: " + controlPoints); 3689 } 3690 if (bbox != null) { 3691 System.out.println("geo bounds: " + bbox); 3692 } 3693 if (rect != null) { 3694 System.out.println("pixel bounds: " + rect.toString()); 3695 } 3696 if (jsonOutput != null) { 3697 System.out.println(jsonOutput.toString()); 3698 } 3699 } 3700 3701 ErrorLogger.LogMessage("MultiPointHandler", "RenderBasicShape()", "exit RenderBasicShape", Level.FINER); 3702 return jsonOutput.toString(); 3703 3704 } 3705}