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