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