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 double patternScale = RendererSettings.getInstance().getPatternScale(); 1582 1583 try { 1584 1585 // The following attirubtes are labels. All of them 1586 // are strings and can be added on the creation of the 1587 // MilStdSymbol by adding to a Map and passing in the 1588 // modifiers parameter. 1589 if (saModifiers != null) { 1590 if (saModifiers.containsKey(Modifiers.C_QUANTITY)) { 1591 modifiers.put(Modifiers.C_QUANTITY, String.valueOf(saModifiers.get(Modifiers.C_QUANTITY))); 1592 } 1593 1594 if (saModifiers.containsKey(Modifiers.H_ADDITIONAL_INFO_1)) { 1595 modifiers.put(Modifiers.H_ADDITIONAL_INFO_1, String.valueOf(saModifiers.get(Modifiers.H_ADDITIONAL_INFO_1))); 1596 } 1597 1598 if (saModifiers.containsKey(Modifiers.H1_ADDITIONAL_INFO_2)) { 1599 modifiers.put(Modifiers.H1_ADDITIONAL_INFO_2, String.valueOf(saModifiers.get(Modifiers.H1_ADDITIONAL_INFO_2))); 1600 } 1601 1602 if (saModifiers.containsKey(Modifiers.H2_ADDITIONAL_INFO_3)) { 1603 modifiers.put(Modifiers.H2_ADDITIONAL_INFO_3, String.valueOf(saModifiers.get(Modifiers.H2_ADDITIONAL_INFO_3))); 1604 } 1605 1606 if (saModifiers.containsKey(Modifiers.N_HOSTILE)) { 1607 if (saModifiers.get(Modifiers.N_HOSTILE) == null) { 1608 modifiers.put(Modifiers.N_HOSTILE, ""); 1609 } else { 1610 modifiers.put(Modifiers.N_HOSTILE, String.valueOf(saModifiers.get(Modifiers.N_HOSTILE))); 1611 } 1612 } 1613 1614 if (saModifiers.containsKey(Modifiers.Q_DIRECTION_OF_MOVEMENT)) { 1615 modifiers.put(Modifiers.Q_DIRECTION_OF_MOVEMENT, String.valueOf(saModifiers.get(Modifiers.Q_DIRECTION_OF_MOVEMENT))); 1616 } 1617 1618 if (saModifiers.containsKey(Modifiers.T_UNIQUE_DESIGNATION_1)) { 1619 modifiers.put(Modifiers.T_UNIQUE_DESIGNATION_1, String.valueOf(saModifiers.get(Modifiers.T_UNIQUE_DESIGNATION_1))); 1620 } 1621 1622 if (saModifiers.containsKey(Modifiers.T1_UNIQUE_DESIGNATION_2)) { 1623 modifiers.put(Modifiers.T1_UNIQUE_DESIGNATION_2, String.valueOf(saModifiers.get(Modifiers.T1_UNIQUE_DESIGNATION_2))); 1624 } 1625 1626 if (saModifiers.containsKey(Modifiers.V_EQUIP_TYPE)) { 1627 modifiers.put(Modifiers.V_EQUIP_TYPE, String.valueOf(saModifiers.get(Modifiers.V_EQUIP_TYPE))); 1628 } 1629 1630 if (saModifiers.containsKey(Modifiers.AS_COUNTRY)) { 1631 modifiers.put(Modifiers.AS_COUNTRY, String.valueOf(saModifiers.get(Modifiers.AS_COUNTRY))); 1632 } else if (SymbolID.getCountryCode(symbol.getSymbolID()) > 0 && !GENCLookup.getInstance().get3CharCode(SymbolID.getCountryCode(symbol.getSymbolID())).equals("")) { 1633 modifiers.put(Modifiers.AS_COUNTRY, GENCLookup.getInstance().get3CharCode(SymbolID.getCountryCode(symbol.getSymbolID()))); 1634 } 1635 1636 if (saModifiers.containsKey(Modifiers.AP_TARGET_NUMBER)) { 1637 modifiers.put(Modifiers.AP_TARGET_NUMBER, String.valueOf(saModifiers.get(Modifiers.AP_TARGET_NUMBER))); 1638 } 1639 1640 if (saModifiers.containsKey(Modifiers.W_DTG_1)) { 1641 modifiers.put(Modifiers.W_DTG_1, String.valueOf(saModifiers.get(Modifiers.W_DTG_1))); 1642 } 1643 1644 if (saModifiers.containsKey(Modifiers.W1_DTG_2)) { 1645 modifiers.put(Modifiers.W1_DTG_2, String.valueOf(saModifiers.get(Modifiers.W1_DTG_2))); 1646 } 1647 1648 if (saModifiers.containsKey(Modifiers.Y_LOCATION)) { 1649 modifiers.put(Modifiers.Y_LOCATION, String.valueOf(saModifiers.get(Modifiers.Y_LOCATION))); 1650 } 1651 1652 //Required multipoint modifier arrays 1653 if (saModifiers.containsKey(Modifiers.X_ALTITUDE_DEPTH)) { 1654 altitudes = new ArrayList<Double>(); 1655 String[] arrAltitudes = String.valueOf(saModifiers.get(Modifiers.X_ALTITUDE_DEPTH)).split(","); 1656 for (String x : arrAltitudes) { 1657 if (x.equals("") != true) { 1658 altitudes.add(Double.parseDouble(x)); 1659 } 1660 } 1661 } 1662 1663 if (saModifiers.containsKey(Modifiers.AM_DISTANCE)) { 1664 distances = new ArrayList<Double>(); 1665 String[] arrDistances = String.valueOf(saModifiers.get(Modifiers.AM_DISTANCE)).split(","); 1666 for (String am : arrDistances) { 1667 if (am.equals("") != true) { 1668 distances.add(Double.parseDouble(am)); 1669 } 1670 } 1671 } 1672 1673 if (saModifiers.containsKey(Modifiers.AN_AZIMUTH)) { 1674 azimuths = new ArrayList<Double>(); 1675 String[] arrAzimuths = String.valueOf(saModifiers.get(Modifiers.AN_AZIMUTH)).split(",");; 1676 for (String an : arrAzimuths) { 1677 if (an.equals("") != true) { 1678 azimuths.add(Double.parseDouble(an)); 1679 } 1680 } 1681 } 1682 } 1683 if (saAttributes != null) { 1684 // These properties are ints, not labels, they are colors.////////////////// 1685 if (saAttributes.containsKey(MilStdAttributes.FillColor)) { 1686 fillColor = (String) saAttributes.get(MilStdAttributes.FillColor); 1687 } 1688 1689 if (saAttributes.containsKey(MilStdAttributes.LineColor)) { 1690 lineColor = (String) saAttributes.get(MilStdAttributes.LineColor); 1691 } 1692 1693 if (saAttributes.containsKey(MilStdAttributes.LineWidth)) { 1694 lineWidth = Integer.parseInt(saAttributes.get(MilStdAttributes.LineWidth)); 1695 } 1696 1697 if (saAttributes.containsKey(MilStdAttributes.TextColor)) { 1698 textColor = (String) saAttributes.get(MilStdAttributes.TextColor); 1699 } 1700 1701 if (saAttributes.containsKey(MilStdAttributes.TextBackgroundColor)) { 1702 textBackgroundColor = (String) saAttributes.get(MilStdAttributes.TextBackgroundColor); 1703 } 1704 1705 if (saAttributes.containsKey(MilStdAttributes.AltitudeMode)) { 1706 altMode = saAttributes.get(MilStdAttributes.AltitudeMode); 1707 } 1708 1709 if (saAttributes.containsKey(MilStdAttributes.UseDashArray)) { 1710 useDashArray = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.UseDashArray)); 1711 } 1712 1713 if (saAttributes.containsKey(MilStdAttributes.UsePatternFill)) { 1714 usePatternFill = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.UsePatternFill)); 1715 } 1716 1717 if (saAttributes.containsKey(MilStdAttributes.PatternFillType)) { 1718 patternFillType = Integer.parseInt((saAttributes.get(MilStdAttributes.PatternFillType))); 1719 } 1720 1721 if (saAttributes.containsKey(MilStdAttributes.HideOptionalLabels)) { 1722 hideOptionalLabels = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.HideOptionalLabels)); 1723 } 1724 1725 if(saAttributes.containsKey(MilStdAttributes.AltitudeUnits)) { 1726 altitudeUnit = DistanceUnit.parse(saAttributes.get(MilStdAttributes.AltitudeUnits)); 1727 } 1728 1729 if(saAttributes.containsKey(MilStdAttributes.DistanceUnits)) { 1730 distanceUnit = DistanceUnit.parse(saAttributes.get(MilStdAttributes.DistanceUnits)); 1731 } 1732 1733 if(saAttributes.containsKey(MilStdAttributes.PixelSize)) { 1734 pixelSize = Integer.parseInt(saAttributes.get(MilStdAttributes.PixelSize)); 1735 symbol.setUnitSize(pixelSize); 1736 } 1737 1738 if (saAttributes.containsKey(MilStdAttributes.KeepUnitRatio)) { 1739 keepUnitRatio = Boolean.parseBoolean(saAttributes.get(MilStdAttributes.KeepUnitRatio)); 1740 symbol.setKeepUnitRatio(keepUnitRatio); 1741 } 1742 1743 if(saAttributes.containsKey(MilStdAttributes.PatternScale)) { 1744 patternScale = Double.parseDouble(saAttributes.get(MilStdAttributes.PatternScale)); 1745 } 1746 } 1747 1748 symbol.setModifierMap(modifiers); 1749 1750 if (fillColor != null && fillColor.equals("") == false) { 1751 symbol.setFillColor(RendererUtilities.getColorFromHexString(fillColor)); 1752 } 1753 1754 if (lineColor != null && lineColor.equals("") == false) { 1755 symbol.setLineColor(RendererUtilities.getColorFromHexString(lineColor)); 1756 symbol.setTextColor(RendererUtilities.getColorFromHexString(lineColor)); 1757 } 1758 else if(symbol.getLineColor()==null) 1759 symbol.setLineColor(Color.black); 1760 1761 if (lineWidth > 0) { 1762 symbol.setLineWidth(lineWidth); 1763 } 1764 1765 if (textColor != null && textColor.equals("") == false) { 1766 symbol.setTextColor(RendererUtilities.getColorFromHexString(textColor)); 1767 } else if(symbol.getTextColor()==null) 1768 symbol.setTextColor(Color.black); 1769 1770 if (textBackgroundColor != null && textBackgroundColor.equals("") == false) { 1771 symbol.setTextBackgroundColor(RendererUtilities.getColorFromHexString(textBackgroundColor)); 1772 } 1773 1774 if (altMode != null) { 1775 symbol.setAltitudeMode(altMode); 1776 } 1777 1778 symbol.setUseDashArray(useDashArray); 1779 symbol.setUseFillPattern(usePatternFill); 1780 symbol.setHideOptionalLabels(hideOptionalLabels); 1781 symbol.setAltitudeUnit(altitudeUnit); 1782 symbol.setDistanceUnit(distanceUnit); 1783 symbol.setPatternScale(patternScale); 1784 1785 // Check grpahic modifiers variables. If we set earlier, populate 1786 // the fields, otherwise, ignore. 1787 if (altitudes != null) { 1788 symbol.setModifiers_AM_AN_X(Modifiers.X_ALTITUDE_DEPTH, altitudes); 1789 } 1790 if (distances != null) { 1791 symbol.setModifiers_AM_AN_X(Modifiers.AM_DISTANCE, distances); 1792 } 1793 1794 if (azimuths != null) { 1795 symbol.setModifiers_AM_AN_X(Modifiers.AN_AZIMUTH, azimuths); 1796 } 1797 1798 //Check if sector range fan has required min range 1799 if (SymbolUtilities.getBasicSymbolID(symbol.getSymbolID()).equals("25242200")) { 1800 if (symbol.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH) != null 1801 && symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE) != null) { 1802 int anCount = symbol.getModifiers_AM_AN_X(Modifiers.AN_AZIMUTH).size(); 1803 int amCount = symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE).size(); 1804 ArrayList<Double> am = null; 1805 if (amCount < ((anCount / 2) + 1)) { 1806 am = symbol.getModifiers_AM_AN_X(Modifiers.AM_DISTANCE); 1807 if (am.get(0) != 0.0) { 1808 am.add(0, 0.0); 1809 } 1810 } 1811 } 1812 } 1813 } catch (Exception exc2) { 1814 Log.e("MPH.populateModifiers", exc2.getMessage(), exc2); 1815 } 1816 return true; 1817 1818 } 1819 1820 private static String KMLize(String id, String name, 1821 String description, 1822 String symbolCode, 1823 ArrayList<ShapeInfo> shapes, 1824 ArrayList<ShapeInfo> modifiers, 1825 IPointConversion ipc, 1826 boolean normalize, Color textColor) { 1827 1828 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 1829 1830 ShapeInfo tempModifier = null; 1831 1832 String cdataStart = "<![CDATA["; 1833 String cdataEnd = "]]>"; 1834 1835 int len = shapes.size(); 1836 kml.append("<Folder id=\"" + id + "\">"); 1837 kml.append("<name>" + cdataStart + name + cdataEnd + "</name>"); 1838 kml.append("<visibility>1</visibility>"); 1839 for (int i = 0; i < len; i++) { 1840 1841 String shapesToAdd = ShapeToKMLString(name, description, symbolCode, shapes.get(i), ipc, normalize); 1842 kml.append(shapesToAdd); 1843 } 1844 1845 int len2 = modifiers.size(); 1846 1847 for (int j = 0; j < len2; j++) { 1848 1849 tempModifier = modifiers.get(j); 1850 1851 //if(geMap)//if using google earth 1852 //assume kml text is going to be centered 1853 //AdjustModifierPointToCenter(tempModifier); 1854 1855 String labelsToAdd = LabelToKMLString(tempModifier, ipc, normalize, textColor); 1856 kml.append(labelsToAdd); 1857 } 1858 1859 kml.append("</Folder>"); 1860 return kml.toString(); 1861 } 1862 1863 /** 1864 * 1865 * @param shapes 1866 * @param modifiers 1867 * @param ipc 1868 * @param geMap 1869 * @param normalize 1870 * @return 1871 * @deprecated Use GeoJSONize() 1872 */ 1873 private static String JSONize(ArrayList<ShapeInfo> shapes, ArrayList<ShapeInfo> modifiers, IPointConversion ipc, Boolean geMap, boolean normalize) { 1874 String polygons = ""; 1875 String lines = ""; 1876 String labels = ""; 1877 String jstr = ""; 1878 ShapeInfo tempModifier = null; 1879 1880 int len = shapes.size(); 1881 for (int i = 0; i < len; i++) { 1882 if (jstr.length() > 0) { 1883 jstr += ","; 1884 } 1885 String shapesToAdd = ShapeToJSONString(shapes.get(i), ipc, geMap, normalize); 1886 if (shapesToAdd.length() > 0) { 1887 if (shapesToAdd.startsWith("line", 2)) { 1888 if (lines.length() > 0) { 1889 lines += ","; 1890 } 1891 1892 lines += shapesToAdd; 1893 } else if (shapesToAdd.startsWith("polygon", 2)) { 1894 if (polygons.length() > 0) { 1895 polygons += ","; 1896 } 1897 1898 polygons += shapesToAdd; 1899 } 1900 } 1901 } 1902 1903 jstr += "\"polygons\": [" + polygons + "]," 1904 + "\"lines\": [" + lines + "],"; 1905 int len2 = modifiers.size(); 1906 labels = ""; 1907 for (int j = 0; j < len2; j++) { 1908 tempModifier = modifiers.get(j); 1909 if (geMap) { 1910 AdjustModifierPointToCenter(tempModifier); 1911 } 1912 String labelsToAdd = LabelToJSONString(tempModifier, ipc, normalize); 1913 if (labelsToAdd.length() > 0) { 1914 if (labels.length() > 0) { 1915 labels += ","; 1916 } 1917 1918 labels += labelsToAdd; 1919 1920 } 1921 } 1922 jstr += "\"labels\": [" + labels + "]"; 1923 return jstr; 1924 } 1925 1926 private static Color getIdealTextBackgroundColor(Color fgColor) { 1927 //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "in function", Level.SEVERE); 1928 try { 1929 //an array of three elements containing the 1930 //hue, saturation, and brightness (in that order), 1931 //of the color with the indicated red, green, and blue components/ 1932 float hsbvals[] = new float[3]; 1933 1934 if (fgColor != null) {/* 1935 Color.RGBtoHSB(fgColor.getRed(), fgColor.getGreen(), fgColor.getBlue(), hsbvals); 1936 1937 if(hsbvals != null) 1938 { 1939 //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "length: " + String.valueOf(hsbvals.length)); 1940 //ErrorLogger.LogMessage("SymbolDraw","getIdealtextBGColor", "H: " + String.valueOf(hsbvals[0]) + " S: " + String.valueOf(hsbvals[1]) + " B: " + String.valueOf(hsbvals[2]),Level.SEVERE); 1941 if(hsbvals[2] > 0.6) 1942 return Color.BLACK; 1943 else 1944 return Color.WHITE; 1945 }*/ 1946 1947 int nThreshold = RendererSettings.getInstance().getTextBackgroundAutoColorThreshold();//160; 1948 int bgDelta = (int) ((fgColor.getRed() * 0.299) + (fgColor.getGreen() * 0.587) + (fgColor.getBlue() * 0.114)); 1949 //ErrorLogger.LogMessage("bgDelta: " + String.valueOf(255-bgDelta)); 1950 //if less than threshold, black, otherwise white. 1951 //return (255 - bgDelta < nThreshold) ? Color.BLACK : Color.WHITE;//new Color(0, 0, 0, fgColor.getAlpha()) 1952 return (255 - bgDelta < nThreshold) ? new Color(0, 0, 0, fgColor.getAlpha()) : new Color(255, 255, 255, fgColor.getAlpha()); 1953 } 1954 } catch (Exception exc) { 1955 ErrorLogger.LogException("SymbolDraw", "getIdealtextBGColor", exc); 1956 } 1957 return Color.WHITE; 1958 } 1959 1960 private static String LabelToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize, Color textColor, Color textBackgroundColor) { 1961 1962 StringBuilder JSONed = new StringBuilder(); 1963 StringBuilder properties = new StringBuilder(); 1964 StringBuilder geometry = new StringBuilder(); 1965 1966 Color outlineColor = getIdealTextBackgroundColor(textColor); 1967 if(textBackgroundColor != null) 1968 outlineColor = textBackgroundColor; 1969 1970 //AffineTransform at = shapeInfo.getAffineTransform(); 1971 //Point2D coord = (Point2D)new Point2D.Double(at.getTranslateX(), at.getTranslateY()); 1972 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 1973 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 1974 Point2D geoCoord = ipc.PixelsToGeo(coord); 1975 //M. Deutch 9-27-11 1976 if (normalize) { 1977 geoCoord = NormalizeCoordToGECoord(geoCoord); 1978 } 1979 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 1980 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 1981 double angle = shapeInfo.getModifierAngle(); 1982 coord.setLocation(longitude, latitude); 1983 1984 //diagnostic M. Deutch 10-18-11 1985 shapeInfo.setGlyphPosition(coord); 1986 1987 String text = shapeInfo.getModifierString(); 1988 1989 int justify=shapeInfo.getTextJustify(); 1990 String strJustify="left"; 1991 if(justify==0) 1992 strJustify="left"; 1993 else if(justify==1) 1994 strJustify="center"; 1995 else if(justify==2) 1996 strJustify="right"; 1997 1998 1999 RendererSettings RS = RendererSettings.getInstance(); 2000 2001 if (text != null && text.equals("") == false) { 2002 2003 JSONed.append("{\"type\":\"Feature\",\"properties\":{\"label\":\""); 2004 JSONed.append(text); 2005 JSONed.append("\",\"pointRadius\":0,\"fontColor\":\""); 2006 JSONed.append(RendererUtilities.colorToHexString(textColor, false)); 2007 JSONed.append("\",\"fontSize\":\""); 2008 JSONed.append(String.valueOf(RS.getMPLabelFontSize()) + "pt\""); 2009 JSONed.append(",\"fontFamily\":\""); 2010 JSONed.append(RS.getMPLabelFontName()); 2011 JSONed.append(", sans-serif"); 2012 2013 if (RS.getMPLabelFontType() == Typeface.BOLD) { 2014 JSONed.append("\",\"fontWeight\":\"bold\""); 2015 } else { 2016 JSONed.append("\",\"fontWeight\":\"normal\""); 2017 } 2018 2019 //JSONed.append(",\"labelAlign\":\"lm\""); 2020 JSONed.append(",\"labelAlign\":\""); 2021 JSONed.append(strJustify); 2022 JSONed.append("\",\"labelBaseline\":\"alphabetic\""); 2023 JSONed.append(",\"labelXOffset\":0"); 2024 JSONed.append(",\"labelYOffset\":0"); 2025 JSONed.append(",\"labelOutlineColor\":\""); 2026 JSONed.append(RendererUtilities.colorToHexString(outlineColor, false)); 2027 JSONed.append("\",\"labelOutlineWidth\":"); 2028 JSONed.append("4"); 2029 JSONed.append(",\"rotation\":"); 2030 JSONed.append(angle); 2031 JSONed.append(",\"angle\":"); 2032 JSONed.append(angle); 2033 JSONed.append("},"); 2034 2035 JSONed.append("\"geometry\":{\"type\":\"Point\",\"coordinates\":["); 2036 JSONed.append(longitude); 2037 JSONed.append(","); 2038 JSONed.append(latitude); 2039 JSONed.append("]"); 2040 JSONed.append("}}"); 2041 2042 } else { 2043 return ""; 2044 } 2045 2046 return JSONed.toString(); 2047 } 2048 2049 private static String ShapeToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2050 StringBuilder JSONed = new StringBuilder(); 2051 StringBuilder properties = new StringBuilder(); 2052 StringBuilder geometry = new StringBuilder(); 2053 String geometryType = null; 2054 String sda = null; 2055 /* 2056 NOTE: Google Earth / KML colors are backwards. 2057 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2058 * */ 2059 Color lineColor = shapeInfo.getLineColor(); 2060 Color fillColor = shapeInfo.getFillColor(); 2061 2062 if (shapeInfo.getShapeType() == ShapeInfo.SHAPE_TYPE_FILL || fillColor != null || shapeInfo.getPatternFillImage() != null) { 2063 geometryType = "\"Polygon\""; 2064 } else //if(shapeInfo.getShapeType() == ShapeInfo.SHAPE_TYPE_POLYLINE) 2065 { 2066 geometryType = "\"MultiLineString\""; 2067 } 2068 2069 BasicStroke stroke = null; 2070 stroke = shapeInfo.getStroke(); 2071 int lineWidth = 4; 2072 2073 if (stroke != null) { 2074 lineWidth = (int) stroke.getLineWidth(); 2075 //lineWidth++; 2076 //System.out.println("lineWidth: " + String.valueOf(lineWidth)); 2077 } 2078 2079 //generate JSON properties for feature 2080 properties.append("\"properties\":{"); 2081 properties.append("\"label\":\"\","); 2082 if (lineColor != null) { 2083 properties.append("\"strokeColor\":\"" + RendererUtilities.colorToHexString(lineColor, false) + "\","); 2084 properties.append("\"lineOpacity\":" + String.valueOf(lineColor.getAlpha() / 255f) + ","); 2085 } 2086 if (fillColor != null) { 2087 properties.append("\"fillColor\":\"" + RendererUtilities.colorToHexString(fillColor, false) + "\","); 2088 properties.append("\"fillOpacity\":" + String.valueOf(fillColor.getAlpha() / 255f) + ","); 2089 } 2090 if (shapeInfo.getPatternFillImage() != null) { 2091 properties.append("\"fillPattern\":\"" + bitmapToString(shapeInfo.getPatternFillImage()) + "\","); 2092 } 2093 if(stroke.getDashArray() != null) 2094 { 2095 float[] arrSDA = stroke.getDashArray(); 2096 sda = "["; 2097 sda += String.valueOf(arrSDA[0]); 2098 if(arrSDA.length > 1) 2099 { 2100 for(int i = 1; i < arrSDA.length; i++) 2101 { 2102 sda = sda + ", " + String.valueOf(arrSDA[i]); 2103 } 2104 } 2105 sda += "]"; 2106 sda = "\"strokeDasharray\":" + sda + ","; 2107 properties.append(sda); 2108 } 2109 2110 int lineCap = stroke.getEndCap(); 2111 properties.append("\"lineCap\":" + lineCap + ","); 2112 2113 String strokeWidth = String.valueOf(lineWidth); 2114 properties.append("\"strokeWidth\":" + strokeWidth + ","); 2115 properties.append("\"strokeWeight\":" + strokeWidth + ""); 2116 properties.append("},"); 2117 2118 2119 properties.append("\"style\":{"); 2120 if (lineColor != null) { 2121 properties.append("\"stroke\":\"" + RendererUtilities.colorToHexString(lineColor, false) + "\","); 2122 properties.append("\"line-opacity\":" + String.valueOf(lineColor.getAlpha() / 255f) + ","); 2123 } 2124 if (fillColor != null) { 2125 properties.append("\"fill\":\"" + RendererUtilities.colorToHexString(fillColor, false) + "\","); 2126 properties.append("\"fill-opacity\":" + String.valueOf(fillColor.getAlpha() / 255f) + ","); 2127 } 2128 if(stroke.getDashArray() != null) 2129 { 2130 float[] da = stroke.getDashArray(); 2131 sda = String.valueOf(da[0]); 2132 if(da.length > 1) 2133 { 2134 for(int i = 1; i < da.length; i++) 2135 { 2136 sda = sda + " " + String.valueOf(da[i]); 2137 } 2138 } 2139 sda = "\"stroke-dasharray\":\"" + sda + "\","; 2140 properties.append(sda); 2141 sda = null; 2142 } 2143 2144 if(lineCap == BasicStroke.CAP_SQUARE) 2145 properties.append("\"stroke-linecap\":\"square\","); 2146 else if(lineCap == BasicStroke.CAP_ROUND) 2147 properties.append("\"stroke-linecap\":\"round\","); 2148 else if(lineCap == BasicStroke.CAP_BUTT) 2149 properties.append("\"stroke-linecap\":\"butt\","); 2150 2151 strokeWidth = String.valueOf(lineWidth); 2152 properties.append("\"stroke-width\":" + strokeWidth); 2153 properties.append("}"); 2154 2155 2156 //generate JSON geometry for feature 2157 geometry.append("\"geometry\":{\"type\":"); 2158 geometry.append(geometryType); 2159 geometry.append(",\"coordinates\":["); 2160 2161 ArrayList shapesArray = shapeInfo.getPolylines(); 2162 2163 for (int i = 0; i < shapesArray.size(); i++) { 2164 ArrayList pointList = (ArrayList) shapesArray.get(i); 2165 2166 normalize = normalizePoints(pointList, ipc); 2167 2168 geometry.append("["); 2169 2170 //System.out.println("Pixel Coords:"); 2171 for (int j = 0; j < pointList.size(); j++) { 2172 Point2D coord = (Point2D) pointList.get(j); 2173 Point2D geoCoord = ipc.PixelsToGeo(coord); 2174 //M. Deutch 9-27-11 2175 if (normalize) { 2176 geoCoord = NormalizeCoordToGECoord(geoCoord); 2177 } 2178 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2179 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2180 2181 //fix for fill crossing DTL 2182 if (normalize && fillColor != null) { 2183 if (longitude > 0) { 2184 longitude -= 360; 2185 } 2186 } 2187 2188 //diagnostic M. Deutch 10-18-11 2189 //set the point as geo so that the 2190 //coord.setLocation(longitude, latitude); 2191 coord = new Point2D.Double(longitude, latitude); 2192 pointList.set(j, coord); 2193 //end section 2194 2195 geometry.append("["); 2196 geometry.append(longitude); 2197 geometry.append(","); 2198 geometry.append(latitude); 2199 geometry.append("]"); 2200 2201 if (j < (pointList.size() - 1)) { 2202 geometry.append(","); 2203 } 2204 } 2205 2206 geometry.append("]"); 2207 2208 if (i < (shapesArray.size() - 1)) { 2209 geometry.append(","); 2210 } 2211 } 2212 geometry.append("]}"); 2213 2214 JSONed.append("{\"type\":\"Feature\","); 2215 JSONed.append(properties.toString()); 2216 JSONed.append(","); 2217 JSONed.append(geometry.toString()); 2218 JSONed.append("}"); 2219 2220 return JSONed.toString(); 2221 } 2222 2223 private static String ImageToGeoJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2224 2225 StringBuilder JSONed = new StringBuilder(); 2226 StringBuilder properties = new StringBuilder(); 2227 StringBuilder geometry = new StringBuilder(); 2228 2229 //AffineTransform at = shapeInfo.getAffineTransform(); 2230 //Point2D coord = (Point2D)new Point2D.Double(at.getTranslateX(), at.getTranslateY()); 2231 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2232 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 2233 Point2D geoCoord = ipc.PixelsToGeo(coord); 2234 //M. Deutch 9-27-11 2235 if (normalize) { 2236 geoCoord = NormalizeCoordToGECoord(geoCoord); 2237 } 2238 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2239 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2240 double angle = shapeInfo.getModifierAngle(); 2241 coord.setLocation(longitude, latitude); 2242 2243 //diagnostic M. Deutch 10-18-11 2244 shapeInfo.setGlyphPosition(coord); 2245 2246 Bitmap image = shapeInfo.getModifierImage(); 2247 2248 RendererSettings RS = RendererSettings.getInstance(); 2249 2250 if (image != null) { 2251 2252 JSONed.append("{\"type\":\"Feature\",\"properties\":{\"image\":\""); 2253 JSONed.append(bitmapToString(image)); 2254 JSONed.append("\",\"rotation\":"); 2255 JSONed.append(angle); 2256 JSONed.append(",\"angle\":"); 2257 JSONed.append(angle); 2258 JSONed.append("},"); 2259 JSONed.append("\"geometry\":{\"type\":\"Point\",\"coordinates\":["); 2260 JSONed.append(longitude); 2261 JSONed.append(","); 2262 JSONed.append(latitude); 2263 JSONed.append("]"); 2264 JSONed.append("}}"); 2265 2266 } else { 2267 return ""; 2268 } 2269 2270 return JSONed.toString(); 2271 } 2272 2273 protected static String bitmapToString(Bitmap bitmap) { 2274 final int COMPRESSION_QUALITY = 100; 2275 String encodedImage; 2276 ByteArrayOutputStream byteArrayBitmapStream = new ByteArrayOutputStream(); 2277 bitmap.compress(Bitmap.CompressFormat.PNG, COMPRESSION_QUALITY, 2278 byteArrayBitmapStream); 2279 byte[] b = byteArrayBitmapStream.toByteArray(); 2280 encodedImage = Base64.encodeToString(b, Base64.DEFAULT); 2281 return "data:image/png;base64," + encodedImage; 2282 } 2283 2284 private static String GeoJSONize(ArrayList<ShapeInfo> shapes, ArrayList<ShapeInfo> modifiers, IPointConversion ipc, boolean normalize, Color textColor, Color textBackgroundColor) { 2285 2286 String jstr = ""; 2287 ShapeInfo tempModifier = null; 2288 StringBuilder fc = new StringBuilder();//JSON feature collection 2289 2290 fc.append("["); 2291 2292 int len = shapes.size(); 2293 for (int i = 0; i < len; i++) { 2294 2295 String shapesToAdd = ShapeToGeoJSONString(shapes.get(i), ipc, normalize); 2296 if (shapesToAdd.length() > 0) { 2297 fc.append(shapesToAdd); 2298 } 2299 if (i < len - 1) { 2300 fc.append(","); 2301 } 2302 } 2303 2304 int len2 = modifiers.size(); 2305 2306 for (int j = 0; j < len2; j++) { 2307 tempModifier = modifiers.get(j); 2308 2309 String modifiersToAdd = null; 2310 if(modifiers.get(j).getModifierImage() != null) { 2311 modifiersToAdd = ImageToGeoJSONString(tempModifier, ipc, normalize); 2312 } else { 2313 modifiersToAdd = LabelToGeoJSONString(tempModifier, ipc, normalize, textColor, textBackgroundColor); 2314 } 2315 if (modifiersToAdd.length() > 0) { 2316 fc.append(","); 2317 fc.append(modifiersToAdd); 2318 } 2319 } 2320 fc.append("]"); 2321 String GeoJSON = fc.toString(); 2322 return GeoJSON; 2323 } 2324 2325 /** 2326 * 2327 * @param shapes 2328 * @param modifiers 2329 * @param ipc 2330 * @param normalize 2331 * @deprecated 2332 */ 2333 private static void MakeWWReady( 2334 ArrayList<ShapeInfo> shapes, 2335 ArrayList<ShapeInfo> modifiers, 2336 IPointConversion ipc, 2337 boolean normalize) { 2338 ShapeInfo temp = null; 2339 int len = shapes.size(); 2340 for (int i = 0; i < len; i++) { 2341 2342 temp = ShapeToWWReady(shapes.get(i), ipc, normalize); 2343 shapes.set(i, temp); 2344 2345 } 2346 2347 int len2 = modifiers.size(); 2348 ShapeInfo tempModifier = null; 2349 for (int j = 0; j < len2; j++) { 2350 2351 tempModifier = modifiers.get(j); 2352 2353 //Do we need this for World Wind? 2354 tempModifier = LabelToWWReady(tempModifier, ipc, normalize); 2355 modifiers.set(j, tempModifier); 2356 2357 } 2358 2359 } 2360 2361 private static Boolean normalizePoints(ArrayList<Point2D.Double> shape, IPointConversion ipc) { 2362 ArrayList geoCoords = new ArrayList(); 2363 int n = shape.size(); 2364 //for (int j = 0; j < shape.size(); j++) 2365 for (int j = 0; j < n; j++) { 2366 Point2D coord = shape.get(j); 2367 Point2D geoCoord = ipc.PixelsToGeo(coord); 2368 geoCoord = NormalizeCoordToGECoord(geoCoord); 2369 double latitude = geoCoord.getY(); 2370 double longitude = geoCoord.getX(); 2371 Point2D pt2d = new Point2D.Double(longitude, latitude); 2372 geoCoords.add(pt2d); 2373 } 2374 Boolean normalize = crossesIDL(geoCoords); 2375 return normalize; 2376 } 2377 2378 private static Boolean IsOnePointSymbolCode(String symbolCode) { 2379 String basicCode = SymbolUtilities.getBasicSymbolID(symbolCode); 2380 //TODO: Revisit for basic shapes 2381 //some airspaces affected 2382 if (symbolCode.equals("CAKE-----------")) { 2383 return true; 2384 } else if (symbolCode.equals("CYLINDER-------")) { 2385 return true; 2386 } else if (symbolCode.equals("RADARC---------")) { 2387 return true; 2388 } 2389 2390 return false; 2391 } 2392 2393 private static String ShapeToKMLString(String name, 2394 String description, 2395 String symbolCode, 2396 ShapeInfo shapeInfo, 2397 IPointConversion ipc, 2398 boolean normalize) { 2399 2400 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 2401 2402 Color lineColor = null; 2403 Color fillColor = null; 2404 String googleLineColor = null; 2405 String googleFillColor = null; 2406 2407 //String lineStyleId = "lineColor"; 2408 2409 BasicStroke stroke = null; 2410 int lineWidth = 4; 2411 2412 symbolCode = JavaRendererUtilities.normalizeSymbolCode(symbolCode); 2413 2414 String cdataStart = "<![CDATA["; 2415 String cdataEnd = "]]>"; 2416 2417 kml.append("<Placemark>");//("<Placemark id=\"" + id + "_mg" + "\">"); 2418 kml.append("<description>" + cdataStart + "<b>" + name + "</b><br/>" + "\n" + description + cdataEnd + "</description>"); 2419 //kml.append("<Style id=\"" + lineStyleId + "\">"); 2420 kml.append("<Style>"); 2421 2422 lineColor = shapeInfo.getLineColor(); 2423 if (lineColor != null) { 2424 googleLineColor = Integer.toHexString(shapeInfo.getLineColor().toARGB()); 2425 2426 stroke = shapeInfo.getStroke(); 2427 2428 if (stroke != null) { 2429 lineWidth = (int) stroke.getLineWidth(); 2430 } 2431 2432 googleLineColor = JavaRendererUtilities.ARGBtoABGR(googleLineColor); 2433 2434 kml.append("<LineStyle>"); 2435 kml.append("<color>" + googleLineColor + "</color>"); 2436 kml.append("<colorMode>normal</colorMode>"); 2437 kml.append("<width>" + String.valueOf(lineWidth) + "</width>"); 2438 kml.append("</LineStyle>"); 2439 } 2440 2441 fillColor = shapeInfo.getFillColor(); 2442 Bitmap fillPattern = shapeInfo.getPatternFillImage(); 2443 if (fillColor != null || fillPattern != null) { 2444 kml.append("<PolyStyle>"); 2445 2446 if (fillColor != null) { 2447 googleFillColor = Integer.toHexString(shapeInfo.getFillColor().toARGB()); 2448 googleFillColor = JavaRendererUtilities.ARGBtoABGR(googleFillColor); 2449 kml.append("<color>" + googleFillColor + "</color>"); 2450 kml.append("<colorMode>normal</colorMode>"); 2451 } 2452 if (fillPattern != null){ 2453 kml.append("<shader>" + bitmapToString(fillPattern) + "</shader>"); 2454 } 2455 2456 kml.append("<fill>1</fill>"); 2457 if (lineColor != null) { 2458 kml.append("<outline>1</outline>"); 2459 } else { 2460 kml.append("<outline>0</outline>"); 2461 } 2462 kml.append("</PolyStyle>"); 2463 } 2464 2465 kml.append("</Style>"); 2466 2467 ArrayList shapesArray = shapeInfo.getPolylines(); 2468 int len = shapesArray.size(); 2469 kml.append("<MultiGeometry>"); 2470 2471 for (int i = 0; i < len; i++) { 2472 ArrayList shape = (ArrayList) shapesArray.get(i); 2473 normalize = normalizePoints(shape, ipc); 2474 if (lineColor != null && fillColor == null) { 2475 kml.append("<LineString>"); 2476 kml.append("<tessellate>1</tessellate>"); 2477 kml.append("<altitudeMode>clampToGround</altitudeMode>"); 2478 kml.append("<coordinates>"); 2479 int n = shape.size(); 2480 //for (int j = 0; j < shape.size(); j++) 2481 for (int j = 0; j < n; j++) { 2482 Point2D coord = (Point2D) shape.get(j); 2483 Point2D geoCoord = ipc.PixelsToGeo(coord); 2484 if (normalize) { 2485 geoCoord = NormalizeCoordToGECoord(geoCoord); 2486 } 2487 2488 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2489 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2490 2491 kml.append(longitude); 2492 kml.append(","); 2493 kml.append(latitude); 2494 if(j<shape.size()-1) 2495 kml.append(" "); 2496 } 2497 2498 kml.append("</coordinates>"); 2499 kml.append("</LineString>"); 2500 } 2501 2502 if (fillColor != null) { 2503 2504 if (i == 0) { 2505 kml.append("<Polygon>"); 2506 } 2507 //kml.append("<outerBoundaryIs>"); 2508 if (i == 1 && len > 1) { 2509 kml.append("<innerBoundaryIs>"); 2510 } else { 2511 kml.append("<outerBoundaryIs>"); 2512 } 2513 kml.append("<LinearRing>"); 2514 kml.append("<altitudeMode>clampToGround</altitudeMode>"); 2515 kml.append("<tessellate>1</tessellate>"); 2516 kml.append("<coordinates>"); 2517 2518 //this section is a workaround for a google earth bug. Issue 417 was closed 2519 //for linestrings but they did not fix the smae issue for fills. If Google fixes the issue 2520 //for fills then this section will need to be commented or it will induce an error. 2521 double lastLongitude = Double.MIN_VALUE; 2522 if (normalize == false && IsOnePointSymbolCode(symbolCode)) { 2523 int n = shape.size(); 2524 //for (int j = 0; j < shape.size(); j++) 2525 for (int j = 0; j < n; j++) { 2526 Point2D coord = (Point2D) shape.get(j); 2527 Point2D geoCoord = ipc.PixelsToGeo(coord); 2528 double longitude = geoCoord.getX(); 2529 if (lastLongitude != Double.MIN_VALUE) { 2530 if (Math.abs(longitude - lastLongitude) > 180d) { 2531 normalize = true; 2532 break; 2533 } 2534 } 2535 lastLongitude = longitude; 2536 } 2537 } 2538 int n = shape.size(); 2539 //for (int j = 0; j < shape.size(); j++) 2540 for (int j = 0; j < n; j++) { 2541 Point2D coord = (Point2D) shape.get(j); 2542 Point2D geoCoord = ipc.PixelsToGeo(coord); 2543 2544 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2545 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2546 2547 //fix for fill crossing DTL 2548 if (normalize) { 2549 if (longitude > 0) { 2550 longitude -= 360; 2551 } 2552 } 2553 2554 kml.append(longitude); 2555 kml.append(","); 2556 kml.append(latitude); 2557 if(j<shape.size()-1) 2558 kml.append(" "); 2559 } 2560 2561 kml.append("</coordinates>"); 2562 kml.append("</LinearRing>"); 2563 if (i == 1 && len > 1) { 2564 kml.append("</innerBoundaryIs>"); 2565 } else { 2566 kml.append("</outerBoundaryIs>"); 2567 } 2568 if (i == len - 1) { 2569 kml.append("</Polygon>"); 2570 } 2571 } 2572 } 2573 2574 kml.append("</MultiGeometry>"); 2575 kml.append("</Placemark>"); 2576 2577 return kml.toString(); 2578 } 2579 2580 /** 2581 * 2582 * @param shapeInfo 2583 * @param ipc 2584 * @param normalize 2585 * @return 2586 * @deprecated 2587 */ 2588 private static ShapeInfo ShapeToWWReady( 2589 ShapeInfo shapeInfo, 2590 IPointConversion ipc, 2591 boolean normalize) { 2592 2593 ArrayList shapesArray = shapeInfo.getPolylines(); 2594 int len = shapesArray.size(); 2595 2596 for (int i = 0; i < len; i++) { 2597 ArrayList shape = (ArrayList) shapesArray.get(i); 2598 2599 if (shapeInfo.getLineColor() != null) { 2600 int n = shape.size(); 2601 //for (int j = 0; j < shape.size(); j++) 2602 for (int j = 0; j < n; j++) { 2603 Point2D coord = (Point2D) shape.get(j); 2604 Point2D geoCoord = ipc.PixelsToGeo(coord); 2605 //M. Deutch 9-26-11 2606 if (normalize) { 2607 geoCoord = NormalizeCoordToGECoord(geoCoord); 2608 } 2609 2610 shape.set(j, geoCoord); 2611 2612 } 2613 2614 } 2615 2616 if (shapeInfo.getFillColor() != null) { 2617 int n = shape.size(); 2618 //for (int j = 0; j < shape.size(); j++) 2619 for (int j = 0; j < n; j++) { 2620 Point2D coord = (Point2D) shape.get(j); 2621 Point2D geoCoord = ipc.PixelsToGeo(coord); 2622 //M. Deutch 9-26-11 2623 //commenting these two lines seems to help with fill not go around the pole 2624 //if(normalize) 2625 //geoCoord=NormalizeCoordToGECoord(geoCoord); 2626 2627 shape.set(j, geoCoord); 2628 } 2629 } 2630 } 2631 2632 return shapeInfo; 2633 } 2634 2635 private static ShapeInfo LabelToWWReady(ShapeInfo shapeInfo, 2636 IPointConversion ipc, 2637 boolean normalize) { 2638 2639 try { 2640 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2641 Point2D geoCoord = ipc.PixelsToGeo(coord); 2642 //M. Deutch 9-26-11 2643 if (normalize) { 2644 geoCoord = NormalizeCoordToGECoord(geoCoord); 2645 } 2646 double latitude = geoCoord.getY(); 2647 double longitude = geoCoord.getX(); 2648 long angle = Math.round(shapeInfo.getModifierAngle()); 2649 2650 String text = shapeInfo.getModifierString(); 2651 2652 if (text != null && text.equals("") == false) { 2653 shapeInfo.setModifierPosition(geoCoord); 2654 } else { 2655 return null; 2656 } 2657 } catch (Exception exc) { 2658 System.err.println(exc.getMessage()); 2659 exc.printStackTrace(); 2660 } 2661 2662 return shapeInfo; 2663 } 2664 2665 /** 2666 * Google earth centers text on point rather than drawing from that point. 2667 * So we need to adjust the point to where the center of the text would be. 2668 * 2669 * @param modifier 2670 */ 2671 private static void AdjustModifierPointToCenter(ShapeInfo modifier) { 2672 AffineTransform at = null; 2673 try { 2674 Rectangle bounds2 = modifier.getTextLayout().getBounds(); 2675 Rectangle2D bounds = new Rectangle2D.Double(bounds2.x, bounds2.y, bounds2.width, bounds2.height); 2676 } catch (Exception exc) { 2677 System.err.println(exc.getMessage()); 2678 exc.printStackTrace(); 2679 } 2680 } 2681 2682 /** 2683 * 2684 * @param shapeInfo 2685 * @param ipc 2686 * @param geMap 2687 * @param normalize 2688 * @return 2689 * @deprecated 2690 */ 2691 private static String ShapeToJSONString(ShapeInfo shapeInfo, IPointConversion ipc, Boolean geMap, boolean normalize) { 2692 StringBuilder JSONed = new StringBuilder(); 2693 /* 2694 NOTE: Google Earth / KML colors are backwards. 2695 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2696 * */ 2697 String fillColor = null; 2698 String lineColor = null; 2699 2700 if (shapeInfo.getLineColor() != null) { 2701 lineColor = Integer.toHexString(shapeInfo.getLineColor().toARGB()); 2702 if (geMap) { 2703 lineColor = JavaRendererUtilities.ARGBtoABGR(lineColor); 2704 } 2705 2706 } 2707 if (shapeInfo.getFillColor() != null) { 2708 fillColor = Integer.toHexString(shapeInfo.getFillColor().toARGB()); 2709 if (geMap) { 2710 fillColor = JavaRendererUtilities.ARGBtoABGR(fillColor); 2711 } 2712 } 2713 2714 BasicStroke stroke = null; 2715 stroke = shapeInfo.getStroke(); 2716 int lineWidth = 4; 2717 2718 if (stroke != null) { 2719 lineWidth = (int) stroke.getLineWidth(); 2720 } 2721 2722 ArrayList shapesArray = shapeInfo.getPolylines(); 2723 int n = shapesArray.size(); 2724 //for (int i = 0; i < shapesArray.size(); i++) 2725 for (int i = 0; i < n; i++) { 2726 ArrayList shape = (ArrayList) shapesArray.get(i); 2727 2728 if (fillColor != null) { 2729 JSONed.append("{\"polygon\":["); 2730 } else { 2731 JSONed.append("{\"line\":["); 2732 } 2733 2734 int t = shape.size(); 2735 //for (int j = 0; j < shape.size(); j++) 2736 for (int j = 0; j < t; j++) { 2737 Point2D coord = (Point2D) shape.get(j); 2738 Point2D geoCoord = ipc.PixelsToGeo(coord); 2739 //M. Deutch 9-27-11 2740 if (normalize) { 2741 geoCoord = NormalizeCoordToGECoord(geoCoord); 2742 } 2743 double latitude = geoCoord.getY(); 2744 double longitude = geoCoord.getX(); 2745 2746 //diagnostic M. Deutch 10-18-11 2747 //set the point as geo so that the 2748 coord = new Point2D.Double(longitude, latitude); 2749 shape.set(j, coord); 2750 2751 JSONed.append("["); 2752 JSONed.append(longitude); 2753 JSONed.append(","); 2754 JSONed.append(latitude); 2755 JSONed.append("]"); 2756 2757 if (j < (shape.size() - 1)) { 2758 JSONed.append(","); 2759 } 2760 } 2761 2762 JSONed.append("]"); 2763 if (lineColor != null) { 2764 JSONed.append(",\"lineColor\":\""); 2765 JSONed.append(lineColor); 2766 2767 JSONed.append("\""); 2768 } 2769 if (fillColor != null) { 2770 JSONed.append(",\"fillColor\":\""); 2771 JSONed.append(fillColor); 2772 JSONed.append("\""); 2773 } 2774 2775 JSONed.append(",\"lineWidth\":\""); 2776 JSONed.append(String.valueOf(lineWidth)); 2777 JSONed.append("\""); 2778 2779 JSONed.append("}"); 2780 2781 if (i < (shapesArray.size() - 1)) { 2782 JSONed.append(","); 2783 } 2784 } 2785 2786 return JSONed.toString(); 2787 } 2788 2789 private static String LabelToKMLString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize, Color textColor) { 2790 java.lang.StringBuilder kml = new java.lang.StringBuilder(); 2791 2792 //Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2793 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getModifierPosition().getX(), shapeInfo.getModifierPosition().getY()); 2794 Point2D geoCoord = ipc.PixelsToGeo(coord); 2795 //M. Deutch 9-26-11 2796 if (normalize) { 2797 geoCoord = NormalizeCoordToGECoord(geoCoord); 2798 } 2799 double latitude = Math.round(geoCoord.getY() * 100000000.0) / 100000000.0; 2800 double longitude = Math.round(geoCoord.getX() * 100000000.0) / 100000000.0; 2801 long angle = Math.round(shapeInfo.getModifierAngle()); 2802 2803 String text = shapeInfo.getModifierString(); 2804 2805 String cdataStart = "<![CDATA["; 2806 String cdataEnd = "]]>"; 2807 2808 String color = Integer.toHexString(textColor.toARGB()); 2809 color = JavaRendererUtilities.ARGBtoABGR(color); 2810 float kmlScale = RendererSettings.getInstance().getKMLLabelScale(); 2811 2812 if (kmlScale > 0 && text != null && text.equals("") == false) { 2813 kml.append("<Placemark>");//("<Placemark id=\"" + id + "_lp" + i + "\">"); 2814 kml.append("<name>" + cdataStart + text + cdataEnd + "</name>"); 2815 kml.append("<Style>"); 2816 kml.append("<IconStyle>"); 2817 kml.append("<scale>" + kmlScale + "</scale>"); 2818 kml.append("<heading>" + angle + "</heading>"); 2819 kml.append("<Icon>"); 2820 kml.append("<href></href>"); 2821 kml.append("</Icon>"); 2822 kml.append("</IconStyle>"); 2823 kml.append("<LabelStyle>"); 2824 kml.append("<color>" + color + "</color>"); 2825 kml.append("<scale>" + String.valueOf(kmlScale) +"</scale>"); 2826 kml.append("</LabelStyle>"); 2827 kml.append("</Style>"); 2828 kml.append("<Point>"); 2829 kml.append("<extrude>1</extrude>"); 2830 kml.append("<altitudeMode>relativeToGround</altitudeMode>"); 2831 kml.append("<coordinates>"); 2832 kml.append(longitude); 2833 kml.append(","); 2834 kml.append(latitude); 2835 kml.append("</coordinates>"); 2836 kml.append("</Point>"); 2837 kml.append("</Placemark>"); 2838 } else { 2839 return ""; 2840 } 2841 2842 return kml.toString(); 2843 } 2844 2845 /** 2846 * 2847 * @param shapeInfo 2848 * @param ipc 2849 * @param normalize 2850 * @return 2851 * @deprecated 2852 */ 2853 private static String LabelToJSONString(ShapeInfo shapeInfo, IPointConversion ipc, boolean normalize) { 2854 StringBuilder JSONed = new StringBuilder(); 2855 /* 2856 NOTE: Google Earth / KML colors are backwards. 2857 They are ordered Alpha,Blue,Green,Red, not Red,Green,Blue,Aplha like the rest of the world 2858 * */ 2859 JSONed.append("{\"label\":"); 2860 2861 Point2D coord = (Point2D) new Point2D.Double(shapeInfo.getGlyphPosition().getX(), shapeInfo.getGlyphPosition().getY()); 2862 Point2D geoCoord = ipc.PixelsToGeo(coord); 2863 if (normalize) { 2864 geoCoord = NormalizeCoordToGECoord(geoCoord); 2865 } 2866 double latitude = geoCoord.getY(); 2867 double longitude = geoCoord.getX(); 2868 double angle = shapeInfo.getModifierAngle(); 2869 coord.setLocation(longitude, latitude); 2870 2871 shapeInfo.setGlyphPosition(coord); 2872 2873 String text = shapeInfo.getModifierString(); 2874 2875 if (text != null && text.equals("") == false) { 2876 JSONed.append("["); 2877 JSONed.append(longitude); 2878 JSONed.append(","); 2879 JSONed.append(latitude); 2880 JSONed.append("]"); 2881 2882 JSONed.append(",\"text\":\""); 2883 JSONed.append(text); 2884 JSONed.append("\""); 2885 2886 JSONed.append(",\"angle\":\""); 2887 JSONed.append(angle); 2888 JSONed.append("\"}"); 2889 } else { 2890 return ""; 2891 } 2892 2893 return JSONed.toString(); 2894 } 2895 2896 public static String canRenderMultiPoint(String symbolID, Map<String,String> modifiers, int numPoints) { 2897 try { 2898 String basicID = SymbolUtilities.getBasicSymbolID(symbolID); 2899 MSInfo info = MSLookup.getInstance().getMSLInfo(symbolID); 2900 2901 if (info == null) { 2902 if (SymbolID.getVersion(symbolID) == SymbolID.Version_2525E) { 2903 return"Basic ID: " + basicID + " not recognized in version E (13)"; 2904 } else { 2905 return "Basic ID: " + basicID + " not recognized in version D (11)"; 2906 } 2907 } 2908 2909 int drawRule = info.getDrawRule(); 2910 2911 if (drawRule == DrawRules.DONOTDRAW) { 2912 return "Basic ID: " + basicID + " has no draw rule"; 2913 } else if (!SymbolUtilities.isMultiPoint(symbolID)) { 2914 return "Basic ID: " + basicID + " is not a multipoint symbol"; 2915 } else if (numPoints < info.getMinPointCount()) { 2916 return "Basic ID: " + basicID + " requires a minimum of " + String.valueOf(info.getMinPointCount()) + " points. " + String.valueOf(numPoints) + " are present."; 2917 } 2918 2919 //now check for required modifiers 2920 ArrayList<Double> AM = new ArrayList(); 2921 ArrayList<Double> AN = new ArrayList(); 2922 if (modifiers.containsKey(Modifiers.AM_DISTANCE)) { 2923 String[] amArray = modifiers.get(Modifiers.AM_DISTANCE).split(","); 2924 for (String str : amArray) { 2925 if (!str.equals("")) { 2926 AM.add(Double.parseDouble(str)); 2927 } 2928 } 2929 } 2930 if (modifiers.containsKey(Modifiers.AN_AZIMUTH)) { 2931 String[] anArray = modifiers.get(Modifiers.AN_AZIMUTH).split(","); 2932 for (String str : anArray) { 2933 if (!str.equals("")) { 2934 AN.add(Double.parseDouble(str)); 2935 } 2936 } 2937 } 2938 2939 return hasRequiredModifiers(symbolID, drawRule, AM, AN); 2940 } catch (Exception exc) { 2941 ErrorLogger.LogException("MultiPointHandler", "canRenderMultiPoint", exc); 2942 return "false: " + exc.getMessage(); 2943 } 2944 } 2945 2946 static private String hasRequiredModifiers(String symbolID, int drawRule, ArrayList<Double> AM, ArrayList<Double> AN) { 2947 2948 String message = symbolID; 2949 try { 2950 if (drawRule > 700) { 2951 if (drawRule == DrawRules.CIRCULAR1) 2952 { 2953 if (AM != null && AM.size() > 0) { 2954 return "true"; 2955 } else { 2956 message += " requires a modifiers object that has 1 distance/AM value."; 2957 return message; 2958 } 2959 } else if (drawRule == DrawRules.RECTANGULAR2) 2960 { 2961 if (AM != null && AM.size() >= 2 2962 && AN != null && AN.size() >= 1) { 2963 return "true"; 2964 } else { 2965 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 2966 return message; 2967 } 2968 } else if (drawRule == DrawRules.ARC1) 2969 { 2970 if (AM != null && AM.size() >= 1 2971 && AN != null && AN.size() >= 2) { 2972 return "true"; 2973 } else { 2974 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."); 2975 return message; 2976 } 2977 } else if (drawRule == DrawRules.CIRCULAR2) 2978 { 2979 if (AM != null && AM.size() > 0) { 2980 return "true"; 2981 } else { 2982 message += (" requires a modifiers object that has at least 1 distance/AM value"); 2983 return message; 2984 } 2985 } else if (drawRule == DrawRules.RECTANGULAR1) 2986 { 2987 if (AM != null && AM.size() > 0) { 2988 return "true"; 2989 } else { 2990 message += (" requires a modifiers object that has 1 distance/AM value."); 2991 return message; 2992 } 2993 } else if (drawRule == DrawRules.ELLIPSE1) 2994 { 2995 if (AM != null && AM.size() >= 2 2996 && AN != null && AN.size() >= 1) { 2997 return "true"; 2998 } else { 2999 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 3000 return message; 3001 } 3002 } 3003 else if (drawRule == DrawRules.RECTANGULAR3) 3004 { 3005 if (AM != null && AM.size() >= 1) { 3006 return "true"; 3007 } else { 3008 message += (" requires a modifiers object that has 1 distance/AM value."); 3009 return message; 3010 } 3011 } else { 3012 //should never get here 3013 return "true"; 3014 } 3015 } else if (drawRule == DrawRules.POINT17) { 3016 if (AM != null && AM.size() >= 2 3017 && AN != null && AN.size() >= 1) { 3018 return "true"; 3019 } else { 3020 message += (" requires a modifiers object that has 2 distance/AM values and 1 azimuth/AN value."); 3021 return message; 3022 } 3023 } else if (drawRule == DrawRules.POINT18) { 3024 if (AM != null && AM.size() >= 2 3025 && AN != null && AN.size() >= 2) { 3026 return "true"; 3027 } else { 3028 message += (" requires a modifiers object that has 2 distance/AM values and 2 azimuth/AN values."); 3029 return message; 3030 } 3031 } else if (drawRule == DrawRules.CORRIDOR1) { 3032 if (AM != null && AM.size() > 0) { 3033 return "true"; 3034 } else { 3035 message += (" requires a modifiers object that has 1 distance/AM value."); 3036 return message; 3037 } 3038 } else { 3039 //no required parameters 3040 return "true"; 3041 } 3042 } catch (Exception exc) { 3043 ErrorLogger.LogException("MultiPointHandler", "hasRequiredModifiers", exc); 3044 return "true"; 3045 } 3046 } 3047}