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 useLinePattern = symbol.getUseLinePattern(); 1648 boolean usePatternFill = symbol.getUseFillPattern(); 1649 int patternFillType = 0; 1650 boolean hideOptionalLabels = false; 1651 DistanceUnit distanceUnit = null; 1652 DistanceUnit altitudeUnit = null; 1653 int pixelSize = 100; 1654 boolean keepUnitRatio = true; 1655 double patternScale = RendererSettings.getInstance().getPatternScale(); 1656 1657 try { 1658 1659 // The following attirubtes are labels. All of them 1660 // are strings and can be added on the creation of the 1661 // MilStdSymbol by adding to a Map and passing in the 1662 // modifiers parameter. 1663 if (saModifiers != null) { 1664 if (saModifiers.containsKey(Modifiers.C_QUANTITY)) { 1665 modifiers.put(Modifiers.C_QUANTITY, String.valueOf(saModifiers.get(Modifiers.C_QUANTITY))); 1666 } 1667 1668 if (saModifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) { 1669 modifiers.put(Modifiers.H_ADDITIONAL_INFO_1, String.valueOf(saModifiers.get(Modifiers.H_ADDITIONAL_INFO_1))); 1670 } 1671 1672 if (saModifiers.containsKey(Modifiers.H1_ADDITIONAL_INFO_2)) { 1673 modifiers.put(Modifiers.H1_ADDITIONAL_INFO_2, String.valueOf(saModifiers.get(Modifiers.H1_ADDITIONAL_INFO_2))); 1674 } 1675 1676 if (saModifiers.containsKey(Modifiers.H2_ADDITIONAL_INFO_3)) { 1677 modifiers.put(Modifiers.H2_ADDITIONAL_INFO_3, String.valueOf(saModifiers.get(Modifiers.H2_ADDITIONAL_INFO_3))); 1678 } 1679 1680 if (saModifiers.containsKey(Modifiers.N_HOSTILE)) { 1681 if (saModifiers.get(Modifiers.N_HOSTILE) == null) { 1682 modifiers.put(Modifiers.N_HOSTILE, ""); 1683 } else { 1684 modifiers.put(Modifiers.N_HOSTILE, String.valueOf(saModifiers.get(Modifiers.N_HOSTILE))); 1685 } 1686 } 1687 1688 if (saModifiers.containsKey(Modifiers.Q_DIRECTION_OF_MOVEMENT)) { 1689 modifiers.put(Modifiers.Q_DIRECTION_OF_MOVEMENT, String.valueOf(saModifiers.get(Modifiers.Q_DIRECTION_OF_MOVEMENT))); 1690 } 1691 1692 if (saModifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) { 1693 modifiers.put(Modifiers.T_UNIQUE_DESIGNATION_1, String.valueOf(saModifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1))); 1694 } 1695 1696 if (saModifiers.containsKey(Modifiers.T1_UNIQUE_DESIGNATION_2)) { 1697 modifiers.put(Modifiers.T1_UNIQUE_DESIGNATION_2, String.valueOf(saModifiers.get(Modifiers.T1_UNIQUE_DESIGNATION_2))); 1698 } 1699 1700 if (saModifiers.containsKey(Modifiers.V_EQUIP_TYPE)) { 1701 modifiers.put(Modifiers.V_EQUIP_TYPE, String.valueOf(saModifiers.get(Modifiers.V_EQUIP_TYPE))); 1702 } 1703 1704 if (saModifiers.containsKey(Modifiers.AS_COUNTRY)) { 1705 modifiers.put(Modifiers.AS_COUNTRY, String.valueOf(saModifiers.get(Modifiers.AS_COUNTRY))); 1706 } else if (SymbolID.getCountryCode(symbol.getSymbolID()) > 0 && !GENCLookup.getInstance().get3CharCode(SymbolID.getCountryCode(symbol.getSymbolID())).equals("")) { 1707 modifiers.put(Modifiers.AS_COUNTRY, GENCLookup.getInstance().get3CharCode(SymbolID.getCountryCode(symbol.getSymbolID()))); 1708 } 1709 1710 if (saModifiers.containsKey(Modifiers.AP_TARGET_NUMBER)) { 1711 modifiers.put(Modifiers.AP_TARGET_NUMBER, String.valueOf(saModifiers.get(Modifiers.AP_TARGET_NUMBER))); 1712 } 1713 1714 if (saModifiers.containsKey(Modifiers.W_DTG_1)) { 1715 modifiers.put(Modifiers.W_DTG_1, String.valueOf(saModifiers.get(Modifiers.W_DTG_1))); 1716 } 1717 1718 if (saModifiers.containsKey(Modifiers.W1_DTG_2)) { 1719 modifiers.put(Modifiers.W1_DTG_2, String.valueOf(saModifiers.get(Modifiers.W1_DTG_2))); 1720 } 1721 1722 if (saModifiers.containsKey(Modifiers.Y_LOCATION)) { 1723 modifiers.put(Modifiers.Y_LOCATION, String.valueOf(saModifiers.get(Modifiers.Y_LOCATION))); 1724 } 1725 1726 //Required multipoint modifier arrays 1727 if (saModifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)) { 1728 altitudes = new ArrayList<Double>(); 1729 String[] arrAltitudes = String.valueOf(saModifiers.get(Modifiers.X_ALTITUDE_DEPTH)).split(","); 1730 for (String x : arrAltitudes) { 1731 if (x.equals("") != true) { 1732 altitudes.add(Double.parseDouble(x)); 1733 } 1734 } 1735 } 1736 1737 if (saModifiers.containsKey(Modifiers.AM_DISTANCE)) { 1738 distances = new ArrayList<Double>(); 1739 String[] arrDistances = String.valueOf(saModifiers.get(Modifiers.AM_DISTANCE)).split(","); 1740 for (String am : arrDistances) { 1741 if (am.equals("") != true) { 1742 distances.add(Double.parseDouble(am)); 1743 } 1744 } 1745 } 1746 1747 if (saModifiers.containsKey(Modifiers.AN_AZIMUTH)) { 1748 azimuths = new ArrayList<Double>(); 1749 String[] arrAzimuths = String.valueOf(saModifiers.get(Modifiers.AN_AZIMUTH)).split(",");; 1750 for (String an : arrAzimuths) { 1751 if (an.equals("") != true) { 1752 azimuths.add(Double.parseDouble(an)); 1753 } 1754 } 1755 } 1756 } 1757 if (saAttributes != null) { 1758 // These properties are ints, not labels, they are colors.////////////////// 1759 if (saAttributes.containsKey(MilStdAttributes.FillColor)) { 1760 fillColor = (String) saAttributes.get(MilStdAttributes.FillColor); 1761 } 1762 1763 if (saAttributes.containsKey(MilStdAttributes.LineColor)) { 1764 lineColor = (String) saAttributes.get(MilStdAttributes.LineColor); 1765 } 1766 1767 if (saAttributes.containsKey(MilStdAttributes.LineWidth)) { 1768 lineWidth = Integer.parseInt(saAttributes.get(MilStdAttributes.LineWidth)); 1769 } 1770 1771 if (saAttributes.containsKey(MilStdAttributes.TextColor)) { 1772 textColor = (String) saAttributes.get(MilStdAttributes.TextColor); 1773 } 1774 1775 if (saAttributes.containsKey(MilStdAttributes.TextBackgroundColor)) { 1776 textBackgroundColor = (String) saAttributes.get(MilStdAttributes.TextBackgroundColor); 1777 } 1778 1779 if (saAttributes.containsKey(MilStdAttributes.AltitudeMode)) { 1780 altMode = saAttributes.get(MilStdAttributes.AltitudeMode); 1781 } 1782 1783 if (saAttributes.containsKey(MilStdAttributes.UseDashArray)) { 1784 useDashArray = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.UseDashArray)); 1785 } 1786 1787 if (saAttributes.containsKey(MilStdAttributes.UseLinePattern)) { 1788 useLinePattern = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.UseLinePattern)); 1789 } 1790 1791 if (saAttributes.containsKey(MilStdAttributes.UsePatternFill)) { 1792 usePatternFill = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.UsePatternFill)); 1793 } 1794 1795 if (saAttributes.containsKey(MilStdAttributes.PatternFillType)) { 1796 patternFillType = Integer.parseInt((saAttributes.get(MilStdAttributes.PatternFillType))); 1797 } 1798 1799 if (saAttributes.containsKey(MilStdAttributes.HideOptionalLabels)) { 1800 hideOptionalLabels = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.HideOptionalLabels)); 1801 } 1802 1803 if(saAttributes.containsKey(MilStdAttributes.AltitudeUnits)) { 1804 altitudeUnit = DistanceUnit.parse(saAttributes.get(MilStdAttributes.AltitudeUnits)); 1805 } 1806 1807 if(saAttributes.containsKey(MilStdAttributes.DistanceUnits)) { 1808 distanceUnit = DistanceUnit.parse(saAttributes.get(MilStdAttributes.DistanceUnits)); 1809 } 1810 1811 if(saAttributes.containsKey(MilStdAttributes.PixelSize)) { 1812 pixelSize = Integer.parseInt(saAttributes.get(MilStdAttributes.PixelSize)); 1813 symbol.setUnitSize(pixelSize); 1814 } 1815 1816 if (saAttributes.containsKey(MilStdAttributes.KeepUnitRatio)) { 1817 keepUnitRatio = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.KeepUnitRatio)); 1818 symbol.setKeepUnitRatio(keepUnitRatio); 1819 } 1820 1821 if(saAttributes.containsKey(MilStdAttributes.PatternScale)) { 1822 patternScale = Double.parseDouble(saAttributes.get(MilStdAttributes.PatternScale)); 1823 } 1824 } 1825 1826 symbol.setModifierMap(modifiers); 1827 1828 if (fillColor != null && fillColor.equals("") == false) { 1829 symbol.setFillColor(RendererUtilities.getColorFromHexString(fillColor)); 1830 } 1831 1832 if (lineColor != null && lineColor.equals("") == false) { 1833 symbol.setLineColor(RendererUtilities.getColorFromHexString(lineColor)); 1834 symbol.setTextColor(RendererUtilities.getColorFromHexString(lineColor)); 1835 } 1836 else if(symbol.getLineColor()==null) 1837 symbol.setLineColor(Color.black); 1838 1839 if (lineWidth > 0) { 1840 symbol.setLineWidth(lineWidth); 1841 } 1842 1843 if (textColor != null && textColor.equals("") == false) { 1844 symbol.setTextColor(RendererUtilities.getColorFromHexString(textColor)); 1845 } else if(symbol.getTextColor()==null) 1846 symbol.setTextColor(Color.black); 1847 1848 if (textBackgroundColor != null && textBackgroundColor.equals("") == false) { 1849 symbol.setTextBackgroundColor(RendererUtilities.getColorFromHexString(textBackgroundColor)); 1850 } 1851 1852 if (altMode != null) { 1853 symbol.setAltitudeMode(altMode); 1854 } 1855 1856 symbol.setUseDashArray(useDashArray); 1857 symbol.setUseLinePattern(useLinePattern); 1858 symbol.setUseFillPattern(usePatternFill); 1859 symbol.setHideOptionalLabels(hideOptionalLabels); 1860 symbol.setAltitudeUnit(altitudeUnit); 1861 symbol.setDistanceUnit(distanceUnit); 1862 symbol.setPatternScale(patternScale); 1863 1864 // Check grpahic modifiers variables. If we set earlier, populate 1865 // the fields, otherwise, ignore. 1866 if (altitudes != null) { 1867 symbol.setModifiers_AM_AN_X(Modifiers.X_ALTITUDE_DEPTH, altitudes); 1868 } 1869 if (distances != null) { 1870 symbol.setModifiers_AM_AN_X(Modifiers.AM_DISTANCE, distances); 1871 } 1872 1873 if (azimuths != null) { 1874 symbol.setModifiers_AM_AN_X(Modifiers.AN_AZIMUTH, azimuths); 1875 } 1876 1877 //Check if sector range fan has required min range 1878 if (SymbolUtilities.getBasicSymbolID(symbol.getSymbolID()).equals("25242200")) { 1879 if (symbol.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH) != null 1880 && symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE) != null) { 1881 int anCount = symbol.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH).size(); 1882 int amCount = symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE).size(); 1883 ArrayList<Double> am = null; 1884 if (amCount < ((anCount / 2) + 1)) { 1885 am = symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 1886 if (am.get(0) != 0.0) { 1887 am.add(0, 0.0); 1888 } 1889 } 1890 } 1891 } 1892 } catch (Exception exc2) { 1893 Log.e("MPH.populateModifiers", exc2.getMessage(), exc2); 1894 } 1895 return true; 1896 1897 } 1898 1899 private static String KMLize(String id, 1900 String name, 1901 String description, 1902 String symbolCode, 1903 ArrayList<ShapeInfo> shapes, 1904 ArrayList<ShapeInfo> modifiers, 1905 IPointConversion ipc, 1906 boolean normalize, 1907 Color textColor, 1908 boolean wasClipped, 1909 int textScaleSensitive, 1910 int symbolScaleSensitive) { 1911 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 1912 ShapeInfo tempModifier = null; 1913 String cdataStart = "<![CDATA["; 1914 String cdataEnd = "]]>"; 1915 int len = shapes.size(); 1916 kml.append("<Folder id=\"").append(id).append("\">"); 1917 kml.append("<name>").append(cdataStart).append(name).append(cdataEnd).append("</name>"); 1918 kml.append("<visibility>1</visibility>"); 1919 kml.append("<description>").append(cdataStart).append(description).append(cdataEnd).append("</description>"); 1920 kml.append("<ExtendedData>"); 1921 kml.append("<Data name=\"symbolID\"><value>").append(symbolCode).append("</value></Data>"); 1922 kml.append("<Data name=\"wasClipped\"><value>").append(wasClipped).append("</value></Data>"); 1923 kml.append("<Data name=\"textScaleSensitive\"><value>").append(textScaleSensitive).append("</value></Data>"); 1924 kml.append("<Data name=\"symbolScaleSensitive\"><value>").append(symbolScaleSensitive).append("</value></Data>"); 1925 kml.append("</ExtendedData>"); 1926 for (int i = 0; i < len; i++) { 1927 String shapesToAdd = ShapeToKMLString(shapes.get(i), ipc, normalize); 1928 kml.append(shapesToAdd); 1929 } 1930 1931 int len2 = modifiers.size(); 1932 1933 for (int j = 0; j < len2; j++) { 1934 1935 tempModifier = modifiers.get(j); 1936 1937 //if(geMap)//if using google earth 1938 //assume kml text is going to be centered 1939 //AdjustModifierPointToCenter(tempModifier); 1940 1941 String labelsToAdd = LabelToKMLString(tempModifier, ipc, normalize, textColor); 1942 kml.append(labelsToAdd); 1943 } 1944 1945 kml.append("</Folder>"); 1946 return kml.toString(); 1947 } 1948 1949 /** 1950 * 1951 * @param shapes 1952 * @param modifiers 1953 * @param ipc 1954 * @param geMap 1955 * @param normalize 1956 * @return 1957 * @deprecated Use GeoJSONize() 1958 */ 1959 private static String JSONize(ArrayList<ShapeInfo> shapes, ArrayList<ShapeInfo> modifiers, IPointConversion ipc, Boolean geMap, boolean normalize) { 1960 String polygons = ""; 1961 String lines = ""; 1962 String labels = ""; 1963 String jstr = ""; 1964 ShapeInfo tempModifier = null; 1965 1966 int len = shapes.size(); 1967 for (int i = 0; i < len; i++) { 1968 if (jstr.length() > 0) { 1969 jstr += ","; 1970 } 1971 String shapesToAdd = ShapeToJSONString(shapes.get(i), ipc, geMap, normalize); 1972 if (shapesToAdd.length() > 0) { 1973 if (shapesToAdd.startsWith("line", 2)) { 1974 if (lines.length() > 0) { 1975 lines += ","; 1976 } 1977 1978 lines += shapesToAdd; 1979 } else if (shapesToAdd.startsWith("polygon", 2)) { 1980 if (polygons.length() > 0) { 1981 polygons += ","; 1982 } 1983 1984 polygons += shapesToAdd; 1985 } 1986 } 1987 } 1988 1989 jstr += "\"polygons\": [" + polygons + "]," 1990 + "\"lines\": [" + lines + "],"; 1991 int len2 = modifiers.size(); 1992 labels = ""; 1993 for (int j = 0; j < len2; j++) { 1994 tempModifier = modifiers.get(j); 1995 if (geMap) { 1996 AdjustModifierPointToCenter(tempModifier); 1997 } 1998 String labelsToAdd = LabelToJSONString(tempModifier, ipc, normalize); 1999 if (labelsToAdd.length() > 0) { 2000 if (labels.length() > 0) { 2001 labels += ","; 2002 } 2003 2004 labels += labelsToAdd; 2005 2006 } 2007 } 2008 jstr += "\"labels\": [" + labels + "]"; 2009 return jstr; 2010 } 2011 2012 static Color getIdealTextBackgroundColor(Color fgColor) { 2013 //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "in function", Level.SEVERE); 2014 try { 2015 //an array of three elements containing the 2016 //hue, saturation, and brightness (in that order), 2017 //of the color with the indicated red, green, and blue components/ 2018 float hsbvals[] = new float[3]; 2019 2020 if (fgColor != null) {/* 2021 Color.RGBtoHSB(fgColor.getRed(), fgColor.getGreen(), fgColor.getBlue(), hsbvals); 2022 2023 if(hsbvals != null) 2024 { 2025 //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "length: " + String.valueOf(hsbvals.length)); 2026 //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "H: " + String.valueOf(hsbvals[0]) + " S: " + String.valueOf(hsbvals[1]) + " B: " + String.valueOf(hsbvals[2]),Level.SEVERE); 2027 if(hsbvals[2] > 0.6) 2028 return Color.BLACK; 2029 else 2030 return Color.WHITE; 2031 }*/ 2032 2033 int nThreshold = RendererSettings.getInstance().getTextBackgroundAutoColorThreshold();//160; 2034 int bgDelta = (int) ((fgColor.getRed() * 0.299) + (fgColor.getGreen() * 0.587) + (fgColor.getBlue() * 0.114)); 2035 //ErrorLogger.LogMessage("bgDelta: " + String.valueOf(255-bgDelta)); 2036 //if less than threshold, black, otherwise white. 2037 //return (255 - bgDelta < nThreshold) ? Color.BLACK : Color.WHITE;//new Color(0, 0, 0, fgColor.getAlpha()) 2038 return (255 - bgDelta < nThreshold) ? new Color(0, 0, 0, fgColor.getAlpha()) : new Color(255, 255, 255, fgColor.getAlpha()); 2039 } 2040 } catch (Exception exc) { 2041 ErrorLogger.LogException("MultiPointHandler", "getIdealTextBackgroundColor", exc); 2042 } 2043 return Color.WHITE; 2044 } 2045 2046 private static String LabelToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize, Color textColor, Color textBackgroundColor) { 2047 2048 StringBuilder JSONed = new StringBuilder(); 2049 StringBuilder properties = new StringBuilder(); 2050 StringBuilder geometry = new StringBuilder(); 2051 2052 Color outlineColor = getIdealTextBackgroundColor(textColor); 2053 if(textBackgroundColor != null) 2054 outlineColor = textBackgroundColor; 2055 2056 //AffineTransform at = shapeInfo.getAffineTransform(); 2057 //Point2D coord = (Point2D)new Point2D.Double(at.getTranslateX(), at.getTranslateY()); 2058 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2059 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 2060 Point2D geoCoord = ipc.PixelsToGeo(coord); 2061 //M. Deutch 9-27-11 2062 if (normalize) { 2063 geoCoord = NormalizeCoordToGECoord(geoCoord); 2064 } 2065 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2066 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2067 double angle = shapeInfo.getModifierAngle(); 2068 coord.setLocation(longitude, latitude); 2069 2070 //diagnostic M. Deutch 10-18-11 2071 shapeInfo.setGlyphPosition(coord); 2072 2073 String text = shapeInfo.getModifierString(); 2074 2075 int justify=shapeInfo.getTextJustify(); 2076 String strJustify="left"; 2077 if(justify==0) 2078 strJustify="left"; 2079 else if(justify==1) 2080 strJustify="center"; 2081 else if(justify==2) 2082 strJustify="right"; 2083 2084 2085 RendererSettings RS = RendererSettings.getInstance(); 2086 2087 if (text != null && text.equals("") == false) { 2088 2089 JSONed.append("{\"type\":\"Feature\",\"properties\":{\"label\":\""); 2090 JSONed.append(text); 2091 JSONed.append("\",\"pointRadius\":0,\"fontColor\":\""); 2092 JSONed.append(RendererUtilities.colorToHexString(textColor, false)); 2093 JSONed.append("\",\"fontSize\":\""); 2094 JSONed.append(String.valueOf(RS.getMPLabelFontSize()) + "pt\""); 2095 JSONed.append(",\"fontFamily\":\""); 2096 JSONed.append(RS.getMPLabelFontName()); 2097 JSONed.append(", sans-serif"); 2098 2099 if (RS.getMPLabelFontType() == Typeface.BOLD) { 2100 JSONed.append("\",\"fontWeight\":\"bold\""); 2101 } else { 2102 JSONed.append("\",\"fontWeight\":\"normal\""); 2103 } 2104 2105 //JSONed.append(",\"labelAlign\":\"lm\""); 2106 JSONed.append(",\"labelAlign\":\""); 2107 JSONed.append(strJustify); 2108 JSONed.append("\",\"labelBaseline\":\"alphabetic\""); 2109 2110 //Process Anchor point if available 2111 if(shapeInfo.getModifierAnchor() != null) 2112 { 2113 Point2D anchorPoint = ipc.PixelsToGeo(shapeInfo.getModifierAnchor()); 2114 if(normalize) 2115 anchorPoint = NormalizeCoordToGECoord(anchorPoint); 2116 anchorPoint = new Point2D.Double(Math.round(anchorPoint.getX() * 100000000.0) / 100000000.0,Math.round(anchorPoint.getY() * 100000000.0) / 100000000.0); 2117 2118 JSONed.append(",\"anchorPoint\":{\"type\":\"Point\",\"coordinates\":["); 2119 JSONed.append(anchorPoint.getX()); 2120 JSONed.append(","); 2121 JSONed.append(anchorPoint.getY()); 2122 JSONed.append("]"); 2123 JSONed.append("}"); 2124 2125 JSONed.append(",\"anchorOffsetX\":").append(Math.round(shapeInfo.getModifierAnchorOffset().getX())); 2126 JSONed.append(",\"anchorOffsetY\":").append(Math.round(shapeInfo.getModifierAnchorOffset().getY())); 2127 } 2128 2129 JSONed.append(",\"labelOutlineColor\":\""); 2130 JSONed.append(RendererUtilities.colorToHexString(outlineColor, false)); 2131 JSONed.append("\",\"labelOutlineWidth\":"); 2132 JSONed.append("4"); 2133 JSONed.append(",\"rotation\":"); 2134 JSONed.append(angle); 2135 JSONed.append(",\"angle\":"); 2136 JSONed.append(angle); 2137 JSONed.append("},"); 2138 2139 JSONed.append("\"geometry\":{\"type\":\"Point\",\"coordinates\":["); 2140 JSONed.append(longitude); 2141 JSONed.append(","); 2142 JSONed.append(latitude); 2143 JSONed.append("]"); 2144 JSONed.append("}}"); 2145 2146 } else { 2147 return ""; 2148 } 2149 2150 return JSONed.toString(); 2151 } 2152 2153 private static String ShapeToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2154 StringBuilder JSONed = new StringBuilder(); 2155 StringBuilder properties = new StringBuilder(); 2156 StringBuilder geometry = new StringBuilder(); 2157 String geometryType = null; 2158 String sda = null; 2159 /* 2160 NOTE: Google Earth / KML colors are backwards. 2161 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2162 * */ 2163 Color lineColor = shapeInfo.getLineColor(); 2164 Color fillColor = shapeInfo.getFillColor(); 2165 2166 if (shapeInfo.getShapeType() == ShapeInfo.SHAPE_TYPE_FILL || fillColor != null || shapeInfo.getPatternFillImage() != null) { 2167 geometryType = "\"Polygon\""; 2168 } else //if(shapeInfo.getShapeType() == ShapeInfo.SHAPE_TYPE_POLYLINE) 2169 { 2170 geometryType = "\"MultiLineString\""; 2171 } 2172 2173 BasicStroke stroke = null; 2174 stroke = shapeInfo.getStroke(); 2175 int lineWidth = 4; 2176 2177 if (stroke != null) { 2178 lineWidth = (int) stroke.getLineWidth(); 2179 //lineWidth++; 2180 //System.out.println("lineWidth: " + String.valueOf(lineWidth)); 2181 } 2182 2183 //generate JSON properties for feature 2184 properties.append("\"properties\":{"); 2185 properties.append("\"label\":\"\","); 2186 if (lineColor != null) { 2187 properties.append("\"strokeColor\":\"" + RendererUtilities.colorToHexString(lineColor, false) + "\","); 2188 properties.append("\"lineOpacity\":" + String.valueOf(lineColor.getAlpha() / 255f) + ","); 2189 } 2190 if (fillColor != null) { 2191 properties.append("\"fillColor\":\"" + RendererUtilities.colorToHexString(fillColor, false) + "\","); 2192 properties.append("\"fillOpacity\":" + String.valueOf(fillColor.getAlpha() / 255f) + ","); 2193 } 2194 if (shapeInfo.getPatternFillImage() != null) { 2195 properties.append("\"fillPattern\":\"" + bitmapToString(shapeInfo.getPatternFillImage()) + "\","); 2196 } 2197 if(stroke.getDashArray() != null) 2198 { 2199 float[] arrSDA = stroke.getDashArray(); 2200 sda = "["; 2201 sda += String.valueOf(arrSDA[0]); 2202 if(arrSDA.length > 1) 2203 { 2204 for(int i = 1; i < arrSDA.length; i++) 2205 { 2206 sda = sda + ", " + String.valueOf(arrSDA[i]); 2207 } 2208 } 2209 sda += "]"; 2210 sda = "\"strokeDasharray\":" + sda + ","; 2211 properties.append(sda); 2212 } 2213 2214 int lineCap = stroke.getEndCap(); 2215 properties.append("\"lineCap\":" + lineCap + ","); 2216 2217 String strokeWidth = String.valueOf(lineWidth); 2218 properties.append("\"strokeWidth\":" + strokeWidth + ","); 2219 properties.append("\"strokeWeight\":" + strokeWidth + ""); 2220 properties.append("},"); 2221 2222 2223 properties.append("\"style\":{"); 2224 if (lineColor != null) { 2225 properties.append("\"stroke\":\"" + RendererUtilities.colorToHexString(lineColor, false) + "\","); 2226 properties.append("\"line-opacity\":" + String.valueOf(lineColor.getAlpha() / 255f) + ","); 2227 } 2228 if (fillColor != null) { 2229 properties.append("\"fill\":\"" + RendererUtilities.colorToHexString(fillColor, false) + "\","); 2230 properties.append("\"fill-opacity\":" + String.valueOf(fillColor.getAlpha() / 255f) + ","); 2231 } 2232 if(stroke.getDashArray() != null) 2233 { 2234 float[] da = stroke.getDashArray(); 2235 sda = String.valueOf(da[0]); 2236 if(da.length > 1) 2237 { 2238 for(int i = 1; i < da.length; i++) 2239 { 2240 sda = sda + " " + String.valueOf(da[i]); 2241 } 2242 } 2243 sda = "\"stroke-dasharray\":\"" + sda + "\","; 2244 properties.append(sda); 2245 sda = null; 2246 } 2247 2248 if(lineCap == BasicStroke.CAP_SQUARE) 2249 properties.append("\"stroke-linecap\":\"square\","); 2250 else if(lineCap == BasicStroke.CAP_ROUND) 2251 properties.append("\"stroke-linecap\":\"round\","); 2252 else if(lineCap == BasicStroke.CAP_BUTT) 2253 properties.append("\"stroke-linecap\":\"butt\","); 2254 2255 strokeWidth = String.valueOf(lineWidth); 2256 properties.append("\"stroke-width\":" + strokeWidth); 2257 properties.append("}"); 2258 2259 2260 //generate JSON geometry for feature 2261 geometry.append("\"geometry\":{\"type\":"); 2262 geometry.append(geometryType); 2263 geometry.append(",\"coordinates\":["); 2264 2265 ArrayList shapesArray = shapeInfo.getPolylines(); 2266 2267 for (int i = 0; i < shapesArray.size(); i++) { 2268 ArrayList pointList = (ArrayList) shapesArray.get(i); 2269 2270 normalize = normalizePoints(pointList, ipc); 2271 2272 geometry.append("["); 2273 2274 //System.out.println("Pixel Coords:"); 2275 for (int j = 0; j < pointList.size(); j++) { 2276 Point2D coord = (Point2D) pointList.get(j); 2277 Point2D geoCoord = ipc.PixelsToGeo(coord); 2278 //M. Deutch 9-27-11 2279 if (normalize) { 2280 geoCoord = NormalizeCoordToGECoord(geoCoord); 2281 } 2282 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2283 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2284 2285 //fix for fill crossing DTL 2286 if (normalize && fillColor != null) { 2287 if (longitude > 0) { 2288 longitude -= 360; 2289 } 2290 } 2291 2292 //diagnostic M. Deutch 10-18-11 2293 //set the point as geo so that the 2294 //coord.setLocation(longitude, latitude); 2295 coord = new Point2D.Double(longitude, latitude); 2296 pointList.set(j, coord); 2297 //end section 2298 2299 geometry.append("["); 2300 geometry.append(longitude); 2301 geometry.append(","); 2302 geometry.append(latitude); 2303 geometry.append("]"); 2304 2305 if (j < (pointList.size() - 1)) { 2306 geometry.append(","); 2307 } 2308 } 2309 2310 geometry.append("]"); 2311 2312 if (i < (shapesArray.size() - 1)) { 2313 geometry.append(","); 2314 } 2315 } 2316 geometry.append("]}"); 2317 2318 JSONed.append("{\"type\":\"Feature\","); 2319 JSONed.append(properties.toString()); 2320 JSONed.append(","); 2321 JSONed.append(geometry.toString()); 2322 JSONed.append("}"); 2323 2324 return JSONed.toString(); 2325 } 2326 2327 private static String ImageToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2328 2329 StringBuilder JSONed = new StringBuilder(); 2330 StringBuilder properties = new StringBuilder(); 2331 StringBuilder geometry = new StringBuilder(); 2332 2333 //AffineTransform at = shapeInfo.getAffineTransform(); 2334 //Point2D coord = (Point2D)new Point2D.Double(at.getTranslateX(), at.getTranslateY()); 2335 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2336 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 2337 Point2D geoCoord = ipc.PixelsToGeo(coord); 2338 //M. Deutch 9-27-11 2339 if (normalize) { 2340 geoCoord = NormalizeCoordToGECoord(geoCoord); 2341 } 2342 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2343 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2344 double angle = shapeInfo.getModifierAngle(); 2345 coord.setLocation(longitude, latitude); 2346 2347 //diagnostic M. Deutch 10-18-11 2348 shapeInfo.setGlyphPosition(coord); 2349 2350 Bitmap image = shapeInfo.getModifierImage(); 2351 2352 RendererSettings RS = RendererSettings.getInstance(); 2353 2354 if (image != null) { 2355 2356 JSONed.append("{\"type\":\"Feature\",\"properties\":{\"image\":\""); 2357 JSONed.append(bitmapToString(image)); 2358 JSONed.append("\",\"rotation\":"); 2359 JSONed.append(angle); 2360 JSONed.append(",\"angle\":"); 2361 JSONed.append(angle); 2362 //Process Anchor point if available 2363 if(shapeInfo.getModifierAnchor() != null) 2364 { 2365 Point2D anchorPoint = ipc.PixelsToGeo(shapeInfo.getModifierAnchor()); 2366 if(normalize) 2367 anchorPoint = NormalizeCoordToGECoord(anchorPoint); 2368 anchorPoint = new Point2D.Double(Math.round(anchorPoint.getX() * 100000000.0) / 100000000.0,Math.round(anchorPoint.getY() * 100000000.0) / 100000000.0); 2369 2370 JSONed.append(",\"anchorPoint\":{\"type\":\"Point\",\"coordinates\":["); 2371 JSONed.append(anchorPoint.getX()); 2372 JSONed.append(","); 2373 JSONed.append(anchorPoint.getY()); 2374 JSONed.append("]"); 2375 JSONed.append("}"); 2376 2377 JSONed.append(",\"anchorOffsetX\":").append(Math.round(shapeInfo.getModifierAnchorOffset().getX())); 2378 JSONed.append(",\"anchorOffsetY\":").append(Math.round(shapeInfo.getModifierAnchorOffset().getY())); 2379 } 2380 JSONed.append("},"); 2381 JSONed.append("\"geometry\":{\"type\":\"Point\",\"coordinates\":["); 2382 JSONed.append(longitude); 2383 JSONed.append(","); 2384 JSONed.append(latitude); 2385 JSONed.append("]"); 2386 JSONed.append("}}"); 2387 2388 } else { 2389 return ""; 2390 } 2391 2392 return JSONed.toString(); 2393 } 2394 2395 protected static String bitmapToString(Bitmap bitmap) { 2396 final int COMPRESSION_QUALITY = 100; 2397 String encodedImage; 2398 ByteArrayOutputStream byteArrayBitmapStream = new ByteArrayOutputStream(); 2399 bitmap.compress(Bitmap.CompressFormat.PNG, COMPRESSION_QUALITY, 2400 byteArrayBitmapStream); 2401 byte[] b = byteArrayBitmapStream.toByteArray(); 2402 encodedImage = Base64.encodeToString(b, Base64.DEFAULT); 2403 return "data:image/png;base64," + encodedImage; 2404 } 2405 2406 private static String GeoJSONize(ArrayList<ShapeInfo> shapes, ArrayList<ShapeInfo> modifiers, IPointConversion ipc, boolean normalize, Color textColor, Color textBackgroundColor) { 2407 2408 String jstr = ""; 2409 ShapeInfo tempModifier = null; 2410 StringBuilder fc = new StringBuilder();//JSON feature collection 2411 2412 fc.append("["); 2413 2414 int len = shapes.size(); 2415 for (int i = 0; i < len; i++) { 2416 2417 String shapesToAdd = ShapeToGeoJSONString(shapes.get(i), ipc, normalize); 2418 if (shapesToAdd.length() > 0) { 2419 fc.append(shapesToAdd); 2420 if (i < len - 1) { 2421 fc.append(","); 2422 } 2423 } 2424 } 2425 2426 int len2 = modifiers.size(); 2427 2428 for (int j = 0; j < len2; j++) { 2429 tempModifier = modifiers.get(j); 2430 2431 String modifiersToAdd = null; 2432 if(modifiers.get(j).getModifierImage() != null) { 2433 modifiersToAdd = ImageToGeoJSONString(tempModifier, ipc, normalize); 2434 } else { 2435 modifiersToAdd = LabelToGeoJSONString(tempModifier, ipc, normalize, textColor, textBackgroundColor); 2436 } 2437 if (modifiersToAdd.length() > 0) { 2438 if (fc.length() > 1) 2439 fc.append(","); 2440 fc.append(modifiersToAdd); 2441 } 2442 } 2443 fc.append("]"); 2444 String GeoJSON = fc.toString(); 2445 return GeoJSON; 2446 } 2447 2448 /** 2449 * 2450 * @param shapes 2451 * @param modifiers 2452 * @param ipc 2453 * @param normalize 2454 * @deprecated 2455 */ 2456 private static void MakeWWReady( 2457 ArrayList<ShapeInfo> shapes, 2458 ArrayList<ShapeInfo> modifiers, 2459 IPointConversion ipc, 2460 boolean normalize) { 2461 ShapeInfo temp = null; 2462 int len = shapes.size(); 2463 for (int i = 0; i < len; i++) { 2464 2465 temp = ShapeToWWReady(shapes.get(i), ipc, normalize); 2466 shapes.set(i, temp); 2467 2468 } 2469 2470 int len2 = modifiers.size(); 2471 ShapeInfo tempModifier = null; 2472 for (int j = 0; j < len2; j++) { 2473 2474 tempModifier = modifiers.get(j); 2475 2476 //Do we need this for World Wind? 2477 tempModifier = LabelToWWReady(tempModifier, ipc, normalize); 2478 modifiers.set(j, tempModifier); 2479 2480 } 2481 2482 } 2483 2484 static Boolean normalizePoints(ArrayList<Point2D.Double> shape, IPointConversion ipc) { 2485 ArrayList geoCoords = new ArrayList(); 2486 int n = shape.size(); 2487 //for (int j = 0; j < shape.size(); j++) 2488 for (int j = 0; j < n; j++) { 2489 Point2D coord = shape.get(j); 2490 Point2D geoCoord = ipc.PixelsToGeo(coord); 2491 geoCoord = NormalizeCoordToGECoord(geoCoord); 2492 double latitude = geoCoord.getY(); 2493 double longitude = geoCoord.getX(); 2494 Point2D pt2d = new Point2D.Double(longitude, latitude); 2495 geoCoords.add(pt2d); 2496 } 2497 Boolean normalize = crossesIDL(geoCoords); 2498 return normalize; 2499 } 2500 2501 /** 2502 * @deprecated 2503 */ 2504 private static Boolean IsOnePointSymbolCode(String symbolCode) { 2505 String basicCode = SymbolUtilities.getBasicSymbolID(symbolCode); 2506 //TODO: Revisit for basic shapes 2507 //some airspaces affected 2508 if (symbolCode.equals("CAKE-----------")) { 2509 return true; 2510 } else if (symbolCode.equals("CYLINDER-------")) { 2511 return true; 2512 } else if (symbolCode.equals("RADARC---------")) { 2513 return true; 2514 } 2515 2516 return false; 2517 } 2518 2519 private static String ShapeToKMLString(ShapeInfo shapeInfo, 2520 IPointConversion ipc, 2521 boolean normalize) { 2522 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 2523 Color lineColor = null; 2524 Color fillColor = null; 2525 String googleLineColor = null; 2526 String googleFillColor = null; 2527 BasicStroke stroke = null; 2528 int lineWidth = 4; 2529 2530 kml.append("<Placemark>"); 2531 kml.append("<Style>"); 2532 2533 lineColor = shapeInfo.getLineColor(); 2534 if (lineColor != null) { 2535 googleLineColor = Integer.toHexString(shapeInfo.getLineColor().toARGB()); 2536 2537 stroke = shapeInfo.getStroke(); 2538 2539 if (stroke != null) { 2540 lineWidth = (int) stroke.getLineWidth(); 2541 } 2542 2543 googleLineColor = JavaRendererUtilities.ARGBtoABGR(googleLineColor); 2544 2545 kml.append("<LineStyle>"); 2546 kml.append("<color>" + googleLineColor + "</color>"); 2547 kml.append("<colorMode>normal</colorMode>"); 2548 kml.append("<width>" + String.valueOf(lineWidth) + "</width>"); 2549 kml.append("</LineStyle>"); 2550 } 2551 2552 fillColor = shapeInfo.getFillColor(); 2553 Bitmap fillPattern = shapeInfo.getPatternFillImage(); 2554 if (fillColor != null || fillPattern != null) { 2555 kml.append("<PolyStyle>"); 2556 2557 if (fillColor != null) { 2558 googleFillColor = Integer.toHexString(shapeInfo.getFillColor().toARGB()); 2559 googleFillColor = JavaRendererUtilities.ARGBtoABGR(googleFillColor); 2560 kml.append("<color>" + googleFillColor + "</color>"); 2561 kml.append("<colorMode>normal</colorMode>"); 2562 } 2563 if (fillPattern != null){ 2564 kml.append("<shader>" + bitmapToString(fillPattern) + "</shader>"); 2565 } 2566 2567 kml.append("<fill>1</fill>"); 2568 if (lineColor != null) { 2569 kml.append("<outline>1</outline>"); 2570 } else { 2571 kml.append("<outline>0</outline>"); 2572 } 2573 kml.append("</PolyStyle>"); 2574 } 2575 2576 kml.append("</Style>"); 2577 2578 ArrayList shapesArray = shapeInfo.getPolylines(); 2579 int len = shapesArray.size(); 2580 kml.append("<MultiGeometry>"); 2581 2582 for (int i = 0; i < len; i++) { 2583 ArrayList shape = (ArrayList) shapesArray.get(i); 2584 normalize = normalizePoints(shape, ipc); 2585 if (lineColor != null && fillColor == null) { 2586 kml.append("<LineString>"); 2587 kml.append("<tessellate>1</tessellate>"); 2588 kml.append("<altitudeMode>clampToGround</altitudeMode>"); 2589 kml.append("<coordinates>"); 2590 int n = shape.size(); 2591 //for (int j = 0; j < shape.size(); j++) 2592 for (int j = 0; j < n; j++) { 2593 Point2D coord = (Point2D) shape.get(j); 2594 Point2D geoCoord = ipc.PixelsToGeo(coord); 2595 if (normalize) { 2596 geoCoord = NormalizeCoordToGECoord(geoCoord); 2597 } 2598 2599 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2600 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2601 2602 kml.append(longitude); 2603 kml.append(","); 2604 kml.append(latitude); 2605 if(j<shape.size()-1) 2606 kml.append(" "); 2607 } 2608 2609 kml.append("</coordinates>"); 2610 kml.append("</LineString>"); 2611 } 2612 2613 if (fillColor != null) { 2614 2615 if (i == 0) { 2616 kml.append("<Polygon>"); 2617 } 2618 //kml.append("<outerBoundaryIs>"); 2619 if (i == 1 && len > 1) { 2620 kml.append("<innerBoundaryIs>"); 2621 } else { 2622 kml.append("<outerBoundaryIs>"); 2623 } 2624 kml.append("<LinearRing>"); 2625 kml.append("<altitudeMode>clampToGround</altitudeMode>"); 2626 kml.append("<tessellate>1</tessellate>"); 2627 kml.append("<coordinates>"); 2628 2629 int n = shape.size(); 2630 //for (int j = 0; j < shape.size(); j++) 2631 for (int j = 0; j < n; j++) { 2632 Point2D coord = (Point2D) shape.get(j); 2633 Point2D geoCoord = ipc.PixelsToGeo(coord); 2634 2635 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2636 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2637 2638 //fix for fill crossing DTL 2639 if (normalize) { 2640 if (longitude > 0) { 2641 longitude -= 360; 2642 } 2643 } 2644 2645 kml.append(longitude); 2646 kml.append(","); 2647 kml.append(latitude); 2648 if(j<shape.size()-1) 2649 kml.append(" "); 2650 } 2651 2652 kml.append("</coordinates>"); 2653 kml.append("</LinearRing>"); 2654 if (i == 1 && len > 1) { 2655 kml.append("</innerBoundaryIs>"); 2656 } else { 2657 kml.append("</outerBoundaryIs>"); 2658 } 2659 if (i == len - 1) { 2660 kml.append("</Polygon>"); 2661 } 2662 } 2663 } 2664 2665 kml.append("</MultiGeometry>"); 2666 kml.append("</Placemark>"); 2667 2668 return kml.toString(); 2669 } 2670 2671 /** 2672 * 2673 * @param shapeInfo 2674 * @param ipc 2675 * @param normalize 2676 * @return 2677 * @deprecated 2678 */ 2679 private static ShapeInfo ShapeToWWReady( 2680 ShapeInfo shapeInfo, 2681 IPointConversion ipc, 2682 boolean normalize) { 2683 2684 ArrayList shapesArray = shapeInfo.getPolylines(); 2685 int len = shapesArray.size(); 2686 2687 for (int i = 0; i < len; i++) { 2688 ArrayList shape = (ArrayList) shapesArray.get(i); 2689 2690 if (shapeInfo.getLineColor() != null) { 2691 int n = shape.size(); 2692 //for (int j = 0; j < shape.size(); j++) 2693 for (int j = 0; j < n; j++) { 2694 Point2D coord = (Point2D) shape.get(j); 2695 Point2D geoCoord = ipc.PixelsToGeo(coord); 2696 //M. Deutch 9-26-11 2697 if (normalize) { 2698 geoCoord = NormalizeCoordToGECoord(geoCoord); 2699 } 2700 2701 shape.set(j, geoCoord); 2702 2703 } 2704 2705 } 2706 2707 if (shapeInfo.getFillColor() != null) { 2708 int n = shape.size(); 2709 //for (int j = 0; j < shape.size(); j++) 2710 for (int j = 0; j < n; j++) { 2711 Point2D coord = (Point2D) shape.get(j); 2712 Point2D geoCoord = ipc.PixelsToGeo(coord); 2713 //M. Deutch 9-26-11 2714 //commenting these two lines seems to help with fill not go around the pole 2715 //if(normalize) 2716 //geoCoord=NormalizeCoordToGECoord(geoCoord); 2717 2718 shape.set(j, geoCoord); 2719 } 2720 } 2721 } 2722 2723 return shapeInfo; 2724 } 2725 2726 private static ShapeInfo LabelToWWReady(ShapeInfo shapeInfo, 2727 IPointConversion ipc, 2728 boolean normalize) { 2729 2730 try { 2731 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2732 Point2D geoCoord = ipc.PixelsToGeo(coord); 2733 //M. Deutch 9-26-11 2734 if (normalize) { 2735 geoCoord = NormalizeCoordToGECoord(geoCoord); 2736 } 2737 double latitude = geoCoord.getY(); 2738 double longitude = geoCoord.getX(); 2739 long angle = Math.round(shapeInfo.getModifierAngle()); 2740 2741 String text = shapeInfo.getModifierString(); 2742 2743 if (text != null && text.equals("") == false) { 2744 shapeInfo.setModifierPosition(geoCoord); 2745 } else { 2746 return null; 2747 } 2748 } catch (Exception exc) { 2749 System.err.println(exc.getMessage()); 2750 exc.printStackTrace(); 2751 } 2752 2753 return shapeInfo; 2754 } 2755 2756 /** 2757 * Google earth centers text on point rather than drawing from that point. 2758 * So we need to adjust the point to where the center of the text would be. 2759 * 2760 * @param modifier 2761 */ 2762 private static void AdjustModifierPointToCenter(ShapeInfo modifier) { 2763 AffineTransform at = null; 2764 try { 2765 Rectangle bounds2 = modifier.getTextLayout().getBounds(); 2766 Rectangle2D bounds = new Rectangle2D.Double(bounds2.x, bounds2.y, bounds2.width, bounds2.height); 2767 } catch (Exception exc) { 2768 System.err.println(exc.getMessage()); 2769 exc.printStackTrace(); 2770 } 2771 } 2772 2773 /** 2774 * 2775 * @param shapeInfo 2776 * @param ipc 2777 * @param geMap 2778 * @param normalize 2779 * @return 2780 * @deprecated 2781 */ 2782 private static String ShapeToJSONString(ShapeInfo shapeInfo, IPointConversion ipc, Boolean geMap, boolean normalize) { 2783 StringBuilder JSONed = new StringBuilder(); 2784 /* 2785 NOTE: Google Earth / KML colors are backwards. 2786 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2787 * */ 2788 String fillColor = null; 2789 String lineColor = null; 2790 2791 if (shapeInfo.getLineColor() != null) { 2792 lineColor = Integer.toHexString(shapeInfo.getLineColor().toARGB()); 2793 if (geMap) { 2794 lineColor = JavaRendererUtilities.ARGBtoABGR(lineColor); 2795 } 2796 2797 } 2798 if (shapeInfo.getFillColor() != null) { 2799 fillColor = Integer.toHexString(shapeInfo.getFillColor().toARGB()); 2800 if (geMap) { 2801 fillColor = JavaRendererUtilities.ARGBtoABGR(fillColor); 2802 } 2803 } 2804 2805 BasicStroke stroke = null; 2806 stroke = shapeInfo.getStroke(); 2807 int lineWidth = 4; 2808 2809 if (stroke != null) { 2810 lineWidth = (int) stroke.getLineWidth(); 2811 } 2812 2813 ArrayList shapesArray = shapeInfo.getPolylines(); 2814 int n = shapesArray.size(); 2815 //for (int i = 0; i < shapesArray.size(); i++) 2816 for (int i = 0; i < n; i++) { 2817 ArrayList shape = (ArrayList) shapesArray.get(i); 2818 2819 if (fillColor != null) { 2820 JSONed.append("{\"polygon\":["); 2821 } else { 2822 JSONed.append("{\"line\":["); 2823 } 2824 2825 int t = shape.size(); 2826 //for (int j = 0; j < shape.size(); j++) 2827 for (int j = 0; j < t; j++) { 2828 Point2D coord = (Point2D) shape.get(j); 2829 Point2D geoCoord = ipc.PixelsToGeo(coord); 2830 //M. Deutch 9-27-11 2831 if (normalize) { 2832 geoCoord = NormalizeCoordToGECoord(geoCoord); 2833 } 2834 double latitude = geoCoord.getY(); 2835 double longitude = geoCoord.getX(); 2836 2837 //diagnostic M. Deutch 10-18-11 2838 //set the point as geo so that the 2839 coord = new Point2D.Double(longitude, latitude); 2840 shape.set(j, coord); 2841 2842 JSONed.append("["); 2843 JSONed.append(longitude); 2844 JSONed.append(","); 2845 JSONed.append(latitude); 2846 JSONed.append("]"); 2847 2848 if (j < (shape.size() - 1)) { 2849 JSONed.append(","); 2850 } 2851 } 2852 2853 JSONed.append("]"); 2854 if (lineColor != null) { 2855 JSONed.append(",\"lineColor\":\""); 2856 JSONed.append(lineColor); 2857 2858 JSONed.append("\""); 2859 } 2860 if (fillColor != null) { 2861 JSONed.append(",\"fillColor\":\""); 2862 JSONed.append(fillColor); 2863 JSONed.append("\""); 2864 } 2865 2866 JSONed.append(",\"lineWidth\":\""); 2867 JSONed.append(String.valueOf(lineWidth)); 2868 JSONed.append("\""); 2869 2870 JSONed.append("}"); 2871 2872 if (i < (shapesArray.size() - 1)) { 2873 JSONed.append(","); 2874 } 2875 } 2876 2877 return JSONed.toString(); 2878 } 2879 2880 private static String LabelToKMLString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize, Color textColor) { 2881 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 2882 2883 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2884 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 2885 Point2D geoCoord = ipc.PixelsToGeo(coord); 2886 //M. Deutch 9-26-11 2887 if (normalize) { 2888 geoCoord = NormalizeCoordToGECoord(geoCoord); 2889 } 2890 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2891 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2892 long angle = Math.round(shapeInfo.getModifierAngle()); 2893 2894 String text = shapeInfo.getModifierString(); 2895 2896 String cdataStart = "<![CDATA["; 2897 String cdataEnd = "]]>"; 2898 2899 String color = Integer.toHexString(textColor.toARGB()); 2900 color = JavaRendererUtilities.ARGBtoABGR(color); 2901 float kmlScale = RendererSettings.getInstance().getKMLLabelScale(); 2902 2903 if (kmlScale > 0 && text != null && text.equals("") == false) { 2904 kml.append("<Placemark>");//("<Placemark id=\"" + id + "_lp" + i + "\">"); 2905 kml.append("<name>" + cdataStart + text + cdataEnd + "</name>"); 2906 kml.append("<Style>"); 2907 kml.append("<IconStyle>"); 2908 kml.append("<scale>" + kmlScale + "</scale>"); 2909 kml.append("<heading>" + angle + "</heading>"); 2910 kml.append("<Icon>"); 2911 kml.append("<href></href>"); 2912 kml.append("</Icon>"); 2913 kml.append("</IconStyle>"); 2914 kml.append("<LabelStyle>"); 2915 kml.append("<color>" + color + "</color>"); 2916 kml.append("<scale>" + String.valueOf(kmlScale) +"</scale>"); 2917 kml.append("</LabelStyle>"); 2918 kml.append("</Style>"); 2919 kml.append("<Point>"); 2920 kml.append("<extrude>1</extrude>"); 2921 kml.append("<altitudeMode>relativeToGround</altitudeMode>"); 2922 kml.append("<coordinates>"); 2923 kml.append(longitude); 2924 kml.append(","); 2925 kml.append(latitude); 2926 kml.append("</coordinates>"); 2927 kml.append("</Point>"); 2928 kml.append("</Placemark>"); 2929 } else { 2930 return ""; 2931 } 2932 2933 return kml.toString(); 2934 } 2935 2936 /** 2937 * 2938 * @param shapeInfo 2939 * @param ipc 2940 * @param normalize 2941 * @return 2942 * @deprecated 2943 */ 2944 private static String LabelToJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2945 StringBuilder JSONed = new StringBuilder(); 2946 /* 2947 NOTE: Google Earth / KML colors are backwards. 2948 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2949 * */ 2950 JSONed.append("{\"label\":"); 2951 2952 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2953 Point2D geoCoord = ipc.PixelsToGeo(coord); 2954 if (normalize) { 2955 geoCoord = NormalizeCoordToGECoord(geoCoord); 2956 } 2957 double latitude = geoCoord.getY(); 2958 double longitude = geoCoord.getX(); 2959 double angle = shapeInfo.getModifierAngle(); 2960 coord.setLocation(longitude, latitude); 2961 2962 shapeInfo.setGlyphPosition(coord); 2963 2964 String text = shapeInfo.getModifierString(); 2965 2966 if (text != null && text.equals("") == false) { 2967 JSONed.append("["); 2968 JSONed.append(longitude); 2969 JSONed.append(","); 2970 JSONed.append(latitude); 2971 JSONed.append("]"); 2972 2973 JSONed.append(",\"text\":\""); 2974 JSONed.append(text); 2975 JSONed.append("\""); 2976 2977 JSONed.append(",\"angle\":\""); 2978 JSONed.append(angle); 2979 JSONed.append("\"}"); 2980 } else { 2981 return ""; 2982 } 2983 2984 return JSONed.toString(); 2985 } 2986 2987 public static String canRenderMultiPoint(String symbolID, Map<String,String> modifiers, int numPoints) { 2988 try { 2989 String basicID = SymbolUtilities.getBasicSymbolID(symbolID); 2990 MSInfo info = MSLookup.getInstance().getMSLInfo(symbolID); 2991 2992 if (info == null) { 2993 if (SymbolID.getVersion(symbolID) >= SymbolID.Version_2525E) { 2994 return"Basic ID: " + basicID + " not recognized in version E (15)"; 2995 } else { 2996 return "Basic ID: " + basicID + " not recognized in version D (11)"; 2997 } 2998 } 2999 3000 int drawRule = info.getDrawRule(); 3001 3002 if (drawRule == DrawRules.DONOTDRAW) { 3003 return "Basic ID: " + basicID + " has no draw rule"; 3004 } else if (!SymbolUtilities.isMultiPoint(symbolID)) { 3005 return "Basic ID: " + basicID + " is not a multipoint symbol"; 3006 } else if (numPoints < info.getMinPointCount()) { 3007 return "Basic ID: " + basicID + " requires a minimum of " + String.valueOf(info.getMinPointCount()) + " points. " + String.valueOf(numPoints) + " are present."; 3008 } 3009 3010 //now check for required modifiers 3011 ArrayList<Double> AM = new ArrayList(); 3012 ArrayList<Double> AN = new ArrayList(); 3013 if (modifiers.containsKey(Modifiers.AM_DISTANCE)) { 3014 String[] amArray = modifiers.get(Modifiers.AM_DISTANCE).split(","); 3015 for (String str : amArray) { 3016 if (!str.equals("")) { 3017 AM.add(Double.parseDouble(str)); 3018 } 3019 } 3020 } 3021 if (modifiers.containsKey(Modifiers.AN_AZIMUTH)) { 3022 String[] anArray = modifiers.get(Modifiers.AN_AZIMUTH).split(","); 3023 for (String str : anArray) { 3024 if (!str.equals("")) { 3025 AN.add(Double.parseDouble(str)); 3026 } 3027 } 3028 } 3029 3030 return hasRequiredModifiers(symbolID, drawRule, AM, AN); 3031 } catch (Exception exc) { 3032 ErrorLogger.LogException("MultiPointHandler", "canRenderMultiPoint", exc); 3033 return "false: " + exc.getMessage(); 3034 } 3035 } 3036 3037 static private String hasRequiredModifiers(String symbolID, int drawRule, ArrayList<Double> AM, ArrayList<Double> AN) { 3038 3039 String message = symbolID; 3040 try { 3041 if (drawRule > 700) { 3042 if (drawRule == DrawRules.CIRCULAR1) 3043 { 3044 if (AM != null && AM.size() > 0) { 3045 return "true"; 3046 } else { 3047 message += " requires a modifiers object that has 1 distance/AM value."; 3048 return message; 3049 } 3050 } else if (drawRule == DrawRules.RECTANGULAR2) 3051 { 3052 if (AM != null && AM.size() >= 2 3053 && AN != null && AN.size() >= 1) { 3054 return "true"; 3055 } else { 3056 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 3057 return message; 3058 } 3059 } else if (drawRule == DrawRules.ARC1) 3060 { 3061 if (AM != null && AM.size() >= 1 3062 && AN != null && AN.size() >= 2) { 3063 return "true"; 3064 } else { 3065 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."); 3066 return message; 3067 } 3068 } else if (drawRule == DrawRules.CIRCULAR2) 3069 { 3070 if (AM != null && AM.size() > 0) { 3071 return "true"; 3072 } else { 3073 message += (" requires a modifiers object that has at least 1 distance/AM value"); 3074 return message; 3075 } 3076 } else if (drawRule == DrawRules.RECTANGULAR1) 3077 { 3078 if (AM != null && AM.size() > 0) { 3079 return "true"; 3080 } else { 3081 message += (" requires a modifiers object that has 1 distance/AM value."); 3082 return message; 3083 } 3084 } else if (drawRule == DrawRules.ELLIPSE1) 3085 { 3086 if (AM != null && AM.size() >= 2 3087 && AN != null && AN.size() >= 1) { 3088 return "true"; 3089 } else { 3090 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 3091 return message; 3092 } 3093 } 3094 else if (drawRule == DrawRules.RECTANGULAR3) 3095 { 3096 if (AM != null && AM.size() >= 1) { 3097 return "true"; 3098 } else { 3099 message += (" requires a modifiers object that has 1 distance/AM value."); 3100 return message; 3101 } 3102 } else { 3103 //should never get here 3104 return "true"; 3105 } 3106 } else if (drawRule == DrawRules.POINT17) { 3107 if (AM != null && AM.size() >= 2 3108 && AN != null && AN.size() >= 1) { 3109 return "true"; 3110 } else { 3111 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 3112 return message; 3113 } 3114 } else if (drawRule == DrawRules.POINT18) { 3115 if (AM != null && AM.size() >= 2 3116 && AN != null && AN.size() >= 2) { 3117 return "true"; 3118 } else { 3119 message += (" requires a modifiers object that has 2 distance/AM values and 2 azimuth/AN values."); 3120 return message; 3121 } 3122 } else if (drawRule == DrawRules.CORRIDOR1) { 3123 if (AM != null && AM.size() > 0) { 3124 return "true"; 3125 } else { 3126 message += (" requires a modifiers object that has 1 distance/AM value."); 3127 return message; 3128 } 3129 } else { 3130 //no required parameters 3131 return "true"; 3132 } 3133 } catch (Exception exc) { 3134 ErrorLogger.LogException("MultiPointHandler", "hasRequiredModifiers", exc); 3135 return "true"; 3136 } 3137 } 3138 3139 /** 3140 * 3141 * @param id 3142 * @param name 3143 * @param description 3144 * @param basicShapeType 3145 * @param controlPoints 3146 * @param scale 3147 * @param bbox 3148 * @param symbolModifiers 3149 * @param symbolAttributes 3150 * @return 3151 */ 3152 public static MilStdSymbol RenderBasicShapeAsMilStdSymbol(String id, 3153 String name, 3154 String description, 3155 int basicShapeType, 3156 String controlPoints, 3157 Double scale, 3158 String bbox, 3159 Map<String,String> symbolModifiers, 3160 Map<String,String> symbolAttributes) 3161 { 3162 MilStdSymbol mSymbol = null; 3163 boolean normalize = true; 3164 Double controlLat = 0.0; 3165 Double controlLong = 0.0; 3166 //String jsonContent = ""; 3167 3168 Rectangle rect = null; 3169 3170 //for symbol & line fill 3171 ArrayList<POINT2> tgPoints = null; 3172 3173 String[] coordinates = controlPoints.split(" "); 3174 ArrayList<ShapeInfo> shapes = null;//new ArrayList<ShapeInfo>(); 3175 ArrayList<ShapeInfo> modifiers = null;//new ArrayList<ShapeInfo>(); 3176 //ArrayList<Point2D> pixels = new ArrayList<Point2D>(); 3177 ArrayList<Point2D> geoCoords = new ArrayList<Point2D>(); 3178 int len = coordinates.length; 3179 3180 IPointConversion ipc = null; 3181 3182 //Deutch moved section 6-29-11 3183 Double left = 0.0; 3184 Double right = 0.0; 3185 Double top = 0.0; 3186 Double bottom = 0.0; 3187 Point2D temp = null; 3188 Point2D ptGeoUL = null; 3189 int width = 0; 3190 int height = 0; 3191 int leftX = 0; 3192 int topY = 0; 3193 int bottomY = 0; 3194 int rightX = 0; 3195 int j = 0; 3196 ArrayList<Point2D> bboxCoords = null; 3197 if (bbox != null && bbox.equals("") == false) { 3198 String[] bounds = null; 3199 if (bbox.contains(" "))//trapezoid 3200 { 3201 bboxCoords = new ArrayList<Point2D>(); 3202 double x = 0; 3203 double y = 0; 3204 String[] coords = bbox.split(" "); 3205 String[] arrCoord; 3206 for (String coord : coords) { 3207 arrCoord = coord.split(","); 3208 x = Double.valueOf(arrCoord[0]); 3209 y = Double.valueOf(arrCoord[1]); 3210 bboxCoords.add(new Point2D.Double(x, y)); 3211 } 3212 //use the upper left corner of the MBR containing geoCoords 3213 //to set the converter 3214 ptGeoUL = getGeoUL(bboxCoords); 3215 left = ptGeoUL.getX(); 3216 top = ptGeoUL.getY(); 3217 ipc = new PointConverter(left, top, scale); 3218 Point2D ptPixels = null; 3219 Point2D ptGeo = null; 3220 int n = bboxCoords.size(); 3221 //for (j = 0; j < bboxCoords.size(); j++) 3222 for (j = 0; j < n; j++) { 3223 ptGeo = bboxCoords.get(j); 3224 ptPixels = ipc.GeoToPixels(ptGeo); 3225 x = ptPixels.getX(); 3226 y = ptPixels.getY(); 3227 if (x < 20) { 3228 x = 20; 3229 } 3230 if (y < 20) { 3231 y = 20; 3232 } 3233 ptPixels.setLocation(x, y); 3234 //end section 3235 bboxCoords.set(j, (Point2D) ptPixels); 3236 } 3237 } else//rectangle 3238 { 3239 bounds = bbox.split(","); 3240 left = Double.valueOf(bounds[0]); 3241 right = Double.valueOf(bounds[2]); 3242 top = Double.valueOf(bounds[3]); 3243 bottom = Double.valueOf(bounds[1]); 3244 scale = getReasonableScale(bbox, scale); 3245 ipc = new PointConverter(left, top, scale); 3246 } 3247 3248 Point2D pt2d = null; 3249 if (bboxCoords == null) { 3250 pt2d = new Point2D.Double(left, top); 3251 temp = ipc.GeoToPixels(pt2d); 3252 3253 leftX = (int) temp.getX(); 3254 topY = (int) temp.getY(); 3255 3256 pt2d = new Point2D.Double(right, bottom); 3257 temp = ipc.GeoToPixels(pt2d); 3258 3259 bottomY = (int) temp.getY(); 3260 rightX = (int) temp.getX(); 3261 //diagnostic clipping does not work for large scales 3262// if (scale > 10e6) { 3263// //get widest point in the AOI 3264// double midLat = 0; 3265// if (bottom < 0 && top > 0) { 3266// midLat = 0; 3267// } else if (bottom < 0 && top < 0) { 3268// midLat = top; 3269// } else if (bottom > 0 && top > 0) { 3270// midLat = bottom; 3271// } 3272// 3273// temp = ipc.GeoToPixels(new Point2D.Double(right, midLat)); 3274// rightX = (int) temp.getX(); 3275// } 3276 //end section 3277 3278 width = (int) Math.abs(rightX - leftX); 3279 height = (int) Math.abs(bottomY - topY); 3280 3281 if(width==0 || height==0) 3282 rect=null; 3283 else 3284 rect = new Rectangle(leftX, topY, width, height); 3285 } 3286 } else { 3287 rect = null; 3288 } 3289 //end section 3290 3291 for (int i = 0; i < len; i++) { 3292 String[] coordPair = coordinates[i].split(","); 3293 Double latitude = Double.valueOf(coordPair[1].trim()); 3294 Double longitude = Double.valueOf(coordPair[0].trim()); 3295 geoCoords.add(new Point2D.Double(longitude, latitude)); 3296 } 3297 if (ipc == null) { 3298 Point2D ptCoordsUL = getGeoUL(geoCoords); 3299 ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale); 3300 } 3301 //if (crossesIDL(geoCoords) == true) 3302// if(Math.abs(right-left)>180) 3303// { 3304// normalize = true; 3305// ((PointConverter)ipc).set_normalize(true); 3306// } 3307// else { 3308// normalize = false; 3309// ((PointConverter)ipc).set_normalize(false); 3310// } 3311 3312 //seems to work ok at world view 3313// if (normalize) { 3314// NormalizeGECoordsToGEExtents(0, 360, geoCoords); 3315// } 3316 3317 //M. Deutch 10-3-11 3318 //must shift the rect pixels to synch with the new ipc 3319 //the old ipc was in synch with the bbox, so rect x,y was always 0,0 3320 //the new ipc synchs with the upper left of the geocoords so the boox is shifted 3321 //and therefore the clipping rectangle must shift by the delta x,y between 3322 //the upper left corner of the original bbox and the upper left corner of the geocoords 3323 ArrayList<Point2D> geoCoords2 = new ArrayList<Point2D>(); 3324 geoCoords2.add(new Point2D.Double(left, top)); 3325 geoCoords2.add(new Point2D.Double(right, bottom)); 3326 3327// if (normalize) { 3328// NormalizeGECoordsToGEExtents(0, 360, geoCoords2); 3329// } 3330 3331 //disable clipping 3332 if (crossesIDL(geoCoords) == false) { 3333 rect = null; 3334 bboxCoords = null; 3335 } 3336 3337 String symbolCode = ""; 3338 try { 3339 String fillColor = null; 3340 mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null); 3341 3342// mSymbol.setUseDashArray(true); 3343 3344 if (symbolModifiers != null || symbolAttributes != null) { 3345 populateModifiers(symbolModifiers, symbolAttributes, mSymbol); 3346 } else { 3347 mSymbol.setFillColor(null); 3348 } 3349 3350 if (mSymbol.getFillColor() != null) { 3351 Color fc = mSymbol.getFillColor(); 3352 //fillColor = Integer.toHexString(fc.getRGB()); 3353 fillColor = Integer.toHexString(fc.toARGB()); 3354 } 3355 3356 TGLight tg = clsRenderer.createTGLightFromMilStdSymbolBasicShape(mSymbol, ipc, basicShapeType); 3357 ArrayList<ShapeInfo> shapeInfos = new ArrayList(); 3358 ArrayList<ShapeInfo> modifierShapeInfos = new ArrayList(); 3359 Object clipArea; 3360 if (bboxCoords == null) { 3361 clipArea = rect; 3362 } else { 3363 clipArea = bboxCoords; 3364 } 3365 if (clsRenderer.intersectsClipArea(tg, ipc, clipArea)) { 3366 clsRenderer.render_GE(tg, shapeInfos, modifierShapeInfos, ipc, clipArea); 3367 } 3368 mSymbol.setSymbolShapes(shapeInfos); 3369 mSymbol.setModifierShapes(modifierShapeInfos); 3370 mSymbol.set_WasClipped(tg.get_WasClipped()); 3371 shapes = mSymbol.getSymbolShapes(); 3372 modifiers = mSymbol.getModifierShapes(); 3373 3374 //convert points//////////////////////////////////////////////////// 3375 ArrayList<ArrayList<Point2D>> polylines = null; 3376 ArrayList<ArrayList<Point2D>> newPolylines = null; 3377 ArrayList<Point2D> newLine = null; 3378 for (ShapeInfo shape : shapes) { 3379 polylines = shape.getPolylines(); 3380 //System.out.println("pixel polylines: " + String.valueOf(polylines)); 3381 newPolylines = ConvertPolylinePixelsToCoords(polylines, ipc, normalize); 3382 shape.setPolylines(newPolylines); 3383 } 3384 3385 for (ShapeInfo label : modifiers) { 3386 Point2D pixelCoord = label.getModifierPosition(); 3387 if (pixelCoord == null) { 3388 pixelCoord = label.getGlyphPosition(); 3389 } 3390 Point2D geoCoord = ipc.PixelsToGeo(pixelCoord); 3391 3392 if (normalize) { 3393 geoCoord = NormalizeCoordToGECoord(geoCoord); 3394 } 3395 3396 double latitude = geoCoord.getY(); 3397 double longitude = geoCoord.getX(); 3398 label.setModifierPosition(new Point2D.Double(longitude, latitude)); 3399 3400 } 3401 3402 //////////////////////////////////////////////////////////////////// 3403 mSymbol.setModifierShapes(modifiers); 3404 mSymbol.setSymbolShapes(shapes); 3405 3406 } catch (Exception exc) { 3407 System.out.println(exc.getMessage()); 3408 System.out.println("Symbol Code: " + symbolCode); 3409 exc.printStackTrace(); 3410 } 3411 3412 boolean debug = false; 3413 if (debug == true) { 3414 System.out.println("Symbol Code: " + symbolCode); 3415 System.out.println("Scale: " + scale); 3416 System.out.println("BBOX: " + bbox); 3417 if (controlPoints != null) { 3418 System.out.println("Geo Points: " + controlPoints); 3419 } 3420 if (bbox != null) { 3421 System.out.println("geo bounds: " + bbox); 3422 } 3423 if (rect != null) { 3424 System.out.println("pixel bounds: " + rect.toString()); 3425 } 3426 } 3427 3428 return mSymbol; 3429 3430 } 3431 3432 /** 3433 * 3434 * @param id - For the client to track the symbol, not related to rendering 3435 * @param name - For the client to track the symbol, not related to rendering 3436 * @param description - For the client to track the symbol, not related to rendering 3437 * @param basicShapeType 3438 * @param controlPoints 3439 * @param scale 3440 * @param bbox 3441 * @param symbolModifiers keyed using constants from 3442 * Modifiers. Pass in comma delimited String for modifiers with multiple 3443 * values like AM, AN & X 3444 * @param symbolAttributes keyed using constants from 3445 * MilStdAttributes. pass in double[] for AM, AN and X; Strings for the 3446 * rest. 3447 * @param format 3448 * @return 3449 */ 3450 public static String RenderBasicShape(String id, 3451 String name, 3452 String description, 3453 int basicShapeType, 3454 String controlPoints, 3455 Double scale, 3456 String bbox, 3457 Map<String,String> symbolModifiers, 3458 Map<String,String> symbolAttributes, 3459 int format)//, 3460 { 3461 boolean normalize = true; 3462 //Double controlLat = 0.0; 3463 //Double controlLong = 0.0; 3464 //Double metPerPix = GeoPixelConversion.metersPerPixel(scale); 3465 //String bbox2=getBoundingRectangle(controlPoints,bbox); 3466 StringBuilder jsonOutput = new StringBuilder(); 3467 String jsonContent = ""; 3468 3469 Rectangle rect = null; 3470 String[] coordinates = controlPoints.split(" "); 3471 ArrayList<ShapeInfo> shapes = new ArrayList<ShapeInfo>(); 3472 ArrayList<ShapeInfo> modifiers = new ArrayList<ShapeInfo>(); 3473 //ArrayList<Point2D> pixels = new ArrayList<Point2D>(); 3474 ArrayList<Point2D> geoCoords = new ArrayList<Point2D>(); 3475 int len = coordinates.length; 3476 //diagnostic create geoCoords here 3477 Point2D coordsUL=null; 3478 final String symbolCode = ""; 3479 3480 for (int i = 0; i < len; i++) 3481 { 3482 String[] coordPair = coordinates[i].split(","); 3483 Double latitude = Double.valueOf(coordPair[1].trim()).doubleValue(); 3484 Double longitude = Double.valueOf(coordPair[0].trim()).doubleValue(); 3485 geoCoords.add(new Point2D.Double(longitude, latitude)); 3486 } 3487 ArrayList<POINT2> tgPoints = null; 3488 IPointConversion ipc = null; 3489 3490 //Deutch moved section 6-29-11 3491 Double left = 0.0; 3492 Double right = 0.0; 3493 Double top = 0.0; 3494 Double bottom = 0.0; 3495 Point2D temp = null; 3496 Point2D ptGeoUL = null; 3497 int width = 0; 3498 int height = 0; 3499 int leftX = 0; 3500 int topY = 0; 3501 int bottomY = 0; 3502 int rightX = 0; 3503 int j = 0; 3504 ArrayList<Point2D> bboxCoords = null; 3505 if (bbox != null && bbox.equals("") == false) { 3506 String[] bounds = null; 3507 if (bbox.contains(" "))//trapezoid 3508 { 3509 bboxCoords = new ArrayList<Point2D>(); 3510 double x = 0; 3511 double y = 0; 3512 String[] coords = bbox.split(" "); 3513 String[] arrCoord; 3514 for (String coord : coords) { 3515 arrCoord = coord.split(","); 3516 x = Double.valueOf(arrCoord[0]); 3517 y = Double.valueOf(arrCoord[1]); 3518 bboxCoords.add(new Point2D.Double(x, y)); 3519 } 3520 //use the upper left corner of the MBR containing geoCoords 3521 //to set the converter 3522 ptGeoUL = getGeoUL(bboxCoords); 3523 left = ptGeoUL.getX(); 3524 top = ptGeoUL.getY(); 3525 String bbox2=getBboxFromCoords(bboxCoords); 3526 scale = getReasonableScale(bbox2, scale); 3527 ipc = new PointConverter(left, top, scale); 3528 Point2D ptPixels = null; 3529 Point2D ptGeo = null; 3530 int n = bboxCoords.size(); 3531 //for (j = 0; j < bboxCoords.size(); j++) 3532 for (j = 0; j < n; j++) { 3533 ptGeo = bboxCoords.get(j); 3534 ptPixels = ipc.GeoToPixels(ptGeo); 3535 x = ptPixels.getX(); 3536 y = ptPixels.getY(); 3537 if (x < 20) { 3538 x = 20; 3539 } 3540 if (y < 20) { 3541 y = 20; 3542 } 3543 ptPixels.setLocation(x, y); 3544 //end section 3545 bboxCoords.set(j, (Point2D) ptPixels); 3546 } 3547 } else//rectangle 3548 { 3549 bounds = bbox.split(","); 3550 left = Double.valueOf(bounds[0]); 3551 right = Double.valueOf(bounds[2]); 3552 top = Double.valueOf(bounds[3]); 3553 bottom = Double.valueOf(bounds[1]); 3554 scale = getReasonableScale(bbox, scale); 3555 ipc = new PointConverter(left, top, scale); 3556 } 3557 3558 Point2D pt2d = null; 3559 if (bboxCoords == null) { 3560 pt2d = new Point2D.Double(left, top); 3561 temp = ipc.GeoToPixels(pt2d); 3562 3563 leftX = (int) temp.getX(); 3564 topY = (int) temp.getY(); 3565 3566 pt2d = new Point2D.Double(right, bottom); 3567 temp = ipc.GeoToPixels(pt2d); 3568 3569 bottomY = (int) temp.getY(); 3570 rightX = (int) temp.getX(); 3571 3572 width = (int) Math.abs(rightX - leftX); 3573 height = (int) Math.abs(bottomY - topY); 3574 3575 rect = new Rectangle(leftX, topY, width, height); 3576 } 3577 } else { 3578 rect = null; 3579 } 3580 3581 if (ipc == null) { 3582 Point2D ptCoordsUL = getGeoUL(geoCoords); 3583 ipc = new PointConverter(ptCoordsUL.getX(), ptCoordsUL.getY(), scale); 3584 } 3585 3586 ArrayList<Point2D> geoCoords2 = new ArrayList<Point2D>(); 3587 geoCoords2.add(new Point2D.Double(left, top)); 3588 geoCoords2.add(new Point2D.Double(right, bottom)); 3589 3590// if (normalize) { 3591// NormalizeGECoordsToGEExtents(0, 360, geoCoords2); 3592// } 3593 3594 try { 3595 3596 //String fillColor = null; 3597 MilStdSymbol mSymbol = new MilStdSymbol(symbolCode, null, geoCoords, null); 3598 3599 if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG){ 3600 // Use dash array and hatch pattern fill for SVG output 3601 symbolAttributes.put(MilStdAttributes.UseDashArray, "true"); 3602 symbolAttributes.put(MilStdAttributes.UsePatternFill, "true"); 3603 } 3604 3605 if (symbolModifiers != null || symbolAttributes != null) { 3606 populateModifiers(symbolModifiers, symbolAttributes, mSymbol); 3607 } else { 3608 mSymbol.setFillColor(null); 3609 } 3610 3611 TGLight tg = clsRenderer.createTGLightFromMilStdSymbolBasicShape(mSymbol, ipc, basicShapeType); 3612 ArrayList<ShapeInfo> shapeInfos = new ArrayList(); 3613 ArrayList<ShapeInfo> modifierShapeInfos = new ArrayList(); 3614 Object clipArea; 3615 if (bboxCoords == null) { 3616 clipArea = rect; 3617 } else { 3618 clipArea = bboxCoords; 3619 } 3620 if (clsRenderer.intersectsClipArea(tg, ipc, clipArea)) { 3621 clsRenderer.render_GE(tg, shapeInfos, modifierShapeInfos, ipc, clipArea); 3622 } 3623 mSymbol.setSymbolShapes(shapeInfos); 3624 mSymbol.setModifierShapes(modifierShapeInfos); 3625 mSymbol.set_WasClipped(tg.get_WasClipped()); 3626 shapes = mSymbol.getSymbolShapes(); 3627 modifiers = mSymbol.getModifierShapes(); 3628 3629 if (format == WebRenderer.OUTPUT_FORMAT_JSON) { 3630 jsonOutput.append("{\"type\":\"symbol\","); 3631 jsonContent = JSONize(shapes, modifiers, ipc, true, normalize); 3632 jsonOutput.append(jsonContent); 3633 jsonOutput.append("}"); 3634 } else if (format == WebRenderer.OUTPUT_FORMAT_KML) { 3635 Color textColor = mSymbol.getTextColor(); 3636 if(textColor==null) 3637 textColor=mSymbol.getLineColor(); 3638 3639 jsonContent = KMLize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor, mSymbol.getWasClipped(), mSymbol.isTextScaleSensitive(), mSymbol.isSymbolScaleSensitive()); 3640 jsonOutput.append(jsonContent); 3641 } else if (format == WebRenderer.OUTPUT_FORMAT_GEOJSON) 3642 { 3643 jsonOutput.append("{\"type\":\"FeatureCollection\",\"features\":"); 3644 jsonContent = GeoJSONize(shapes, modifiers, ipc, normalize, mSymbol.getTextColor(), mSymbol.getTextBackgroundColor()); 3645 jsonOutput.append(jsonContent); 3646 3647 //moving meta data properties to the last feature with no coords as feature collection doesn't allow properties 3648 jsonOutput.replace(jsonOutput.toString().length()-1,jsonOutput.toString().length(),"" ); 3649 if (jsonContent.length() > 2) 3650 jsonOutput.append(","); 3651 jsonOutput.append("{\"type\": \"Feature\",\"geometry\": { \"type\": \"Polygon\",\"coordinates\": [ ]}"); 3652 3653 jsonOutput.append(",\"properties\":{\"id\":\""); 3654 jsonOutput.append(id); 3655 jsonOutput.append("\",\"name\":\""); 3656 jsonOutput.append(name); 3657 jsonOutput.append("\",\"description\":\""); 3658 jsonOutput.append(description); 3659 jsonOutput.append("\",\"symbolID\":\""); 3660 jsonOutput.append(symbolCode); 3661 jsonOutput.append("\",\"wasClipped\":\""); 3662 jsonOutput.append(String.valueOf(mSymbol.getWasClipped())); 3663 jsonOutput.append("\",\"textScaleSensitive\":\""); 3664 jsonOutput.append(String.valueOf(mSymbol.isTextScaleSensitive())); 3665 jsonOutput.append("\",\"symbolScaleSensitive\":\""); 3666 jsonOutput.append(String.valueOf(mSymbol.isSymbolScaleSensitive())); 3667 //jsonOutput.append("\"}}"); 3668 3669 jsonOutput.append("\"}}]}"); 3670 } else if (format == WebRenderer.OUTPUT_FORMAT_GEOSVG) { 3671 String textColor = mSymbol.getTextColor() != null ? RendererUtilities.colorToHexString(mSymbol.getTextColor(), false) : ""; 3672 String backgroundColor = mSymbol.getTextBackgroundColor() != null ? RendererUtilities.colorToHexString(mSymbol.getTextBackgroundColor(), false) : ""; 3673 //returns an svg with a geoTL and geoBR value to use to place the canvas on the map 3674 jsonContent = MultiPointHandlerSVG.GeoSVGize(id, name, description, symbolCode, shapes, modifiers, ipc, normalize, textColor, backgroundColor, mSymbol.get_WasClipped()); 3675 jsonOutput.append(jsonContent); 3676 } 3677 } catch (Exception exc) { 3678 String st = JavaRendererUtilities.getStackTrace(exc); 3679 jsonOutput = new StringBuilder(); 3680 jsonOutput.append("{\"type\":\"error\",\"error\":\"There was an error creating the MilStdSymbol " + symbolCode + ": " + "- "); 3681 jsonOutput.append(exc.getMessage() + " - "); 3682 jsonOutput.append(st); 3683 jsonOutput.append("\"}"); 3684 3685 ErrorLogger.LogException("MultiPointHandler", "RenderBasicShape", exc); 3686 } 3687 3688 boolean debug = false; 3689 if (debug == true) { 3690 System.out.println("Symbol Code: " + symbolCode); 3691 System.out.println("Scale: " + scale); 3692 System.out.println("BBOX: " + bbox); 3693 if (controlPoints != null) { 3694 System.out.println("Geo Points: " + controlPoints); 3695 } 3696 if (bbox != null) { 3697 System.out.println("geo bounds: " + bbox); 3698 } 3699 if (rect != null) { 3700 System.out.println("pixel bounds: " + rect.toString()); 3701 } 3702 if (jsonOutput != null) { 3703 System.out.println(jsonOutput.toString()); 3704 } 3705 } 3706 3707 ErrorLogger.LogMessage("MultiPointHandler", "RenderBasicShape()", "exit RenderBasicShape", Level.FINER); 3708 return jsonOutput.toString(); 3709 3710 } 3711}