Changeset 32394 in osm for applications/editors/josm/plugins/seachart/src/render
- Timestamp:
- 2016-06-24T03:48:12+02:00 (8 years ago)
- Location:
- applications/editors/josm/plugins/seachart/src/render
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/seachart/src/render/ChartContext.java
r32082 r32394 14 14 15 15 import s57.S57map; 16 import s57.S57map.*; 16 import s57.S57map.Feature; 17 import s57.S57map.Snode; 17 18 18 19 public interface ChartContext { 19 publicenum RuleSet { ALL, BASE, SEAMARK }20 enum RuleSet { ALL, BASE, SEAMARK } 20 21 21 Point2D getPoint(Snode coord); 22 double mile(Feature feature); 23 boolean clip(); 24 Color background(S57map map); 25 RuleSet ruleset(); 22 Point2D getPoint(Snode coord); 23 24 double mile(Feature feature); 25 26 boolean clip(); 27 28 Color background(S57map map); 29 30 RuleSet ruleset(); 26 31 } -
applications/editors/josm/plugins/seachart/src/render/Renderer.java
r32380 r32394 10 10 package render; 11 11 12 import java.awt.*; 13 import java.awt.font.*; 14 import java.awt.geom.*; 15 import java.awt.image.*; 16 import java.util.*; 17 18 import s57.S57val.*; 12 import java.awt.BasicStroke; 13 import java.awt.Color; 14 import java.awt.Font; 15 import java.awt.Graphics2D; 16 import java.awt.Rectangle; 17 import java.awt.RenderingHints; 18 import java.awt.TexturePaint; 19 import java.awt.font.FontRenderContext; 20 import java.awt.font.GlyphVector; 21 import java.awt.geom.AffineTransform; 22 import java.awt.geom.Arc2D; 23 import java.awt.geom.Ellipse2D; 24 import java.awt.geom.GeneralPath; 25 import java.awt.geom.Line2D; 26 import java.awt.geom.Path2D; 27 import java.awt.geom.Point2D; 28 import java.awt.geom.Rectangle2D; 29 import java.awt.geom.RoundRectangle2D; 30 import java.awt.image.AffineTransformOp; 31 import java.awt.image.BufferedImage; 32 import java.util.ArrayList; 33 19 34 import s57.S57map; 20 import s57.S57map.*; 35 import s57.S57map.GeomIterator; 36 import s57.S57map.Pflag; 37 import s57.S57map.Snode; 38 import s57.S57val.UniHLU; 21 39 import symbols.Areas; 22 40 import symbols.Symbols; 23 import symbols.Symbols.*; 41 import symbols.Symbols.Caption; 42 import symbols.Symbols.Delta; 43 import symbols.Symbols.Form; 44 import symbols.Symbols.Handle; 45 import symbols.Symbols.Instr; 46 import symbols.Symbols.LineStyle; 47 import symbols.Symbols.Scheme; 48 import symbols.Symbols.SubSymbol; 49 import symbols.Symbols.Symbol; 24 50 25 51 public class Renderer { 26 52 27 public static final double symbolScale[] = { 256.0, 128.0, 64.0, 32.0, 16.0, 8.0, 4.0, 2.0, 1.0, 0.61, 0.372, 0.227, 0.138, 0.0843, 0.0514, 0.0313, 0.0191, 0.0117, 0.007 }; 28 29 public enum LabelStyle { NONE, RRCT, RECT, ELPS, CIRC, VCLR, PCLR, HCLR } 30 31 static ChartContext context; 32 static S57map map; 33 static double sScale; 34 static Graphics2D g2; 35 static int zoom; 36 37 public static void reRender(Graphics2D g, Rectangle rect, int z, double factor, S57map m, ChartContext c) { 38 g2 = g; 39 zoom = z; 40 context = c; 41 map = m; 42 sScale = symbolScale[zoom] * factor; 43 if (map != null) { 44 if (context.clip()) { 45 Point2D tl = context.getPoint(map.new Snode(map.bounds.maxlat, map.bounds.minlon)); 46 Point2D br = context.getPoint(map.new Snode(map.bounds.minlat, map.bounds.maxlon)); 47 g2.clip(new Rectangle2D.Double(tl.getX(), tl.getY(), (br.getX() - tl.getX()), (br.getY() - tl.getY()))); 48 } 49 g2.setBackground(context.background(map)); 50 g2.clearRect(rect.x, rect.y, rect.width, rect.height); 51 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 52 g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); 53 g2.setStroke(new BasicStroke(0, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); 54 Rules.rules(); 55 } 56 } 57 58 public static void symbol(Symbol symbol) { 59 Point2D point = context.getPoint(Rules.feature.geom.centre); 60 Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), null, null); 61 } 62 public static void symbol(Symbol symbol, Scheme scheme) { 63 Point2D point = context.getPoint(Rules.feature.geom.centre); 64 Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), scheme, null); 65 } 66 public static void symbol(Symbol symbol, Delta delta) { 67 Point2D point = context.getPoint(Rules.feature.geom.centre); 68 Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), null, delta); 69 } 70 public static void symbol(Symbol symbol, Scheme scheme, Delta delta) { 71 Point2D point = context.getPoint(Rules.feature.geom.centre); 72 Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), scheme, delta); 73 } 74 75 public static void cluster(ArrayList<Symbol> symbols) { 76 Rectangle2D.Double bbox = null; 77 if (symbols.size() > 4) { 78 for (Instr instr : symbols.get(0)) { 79 if (instr.type == Form.BBOX) { 80 bbox = (Rectangle2D.Double) instr.params; 81 break; 82 } 83 } 84 if (bbox == null) return; 85 } 86 switch (symbols.size()) { 87 case 1: 88 symbol(symbols.get(0), new Delta(Handle.CC, new AffineTransform())); 89 break; 90 case 2: 91 symbol(symbols.get(0), new Delta(Handle.RC, new AffineTransform())); 92 symbol(symbols.get(1), new Delta(Handle.LC, new AffineTransform())); 93 break; 94 case 3: 95 symbol(symbols.get(0), new Delta(Handle.BC, new AffineTransform())); 96 symbol(symbols.get(1), new Delta(Handle.TR, new AffineTransform())); 97 symbol(symbols.get(2), new Delta(Handle.TL, new AffineTransform())); 98 break; 99 case 4: 100 symbol(symbols.get(0), new Delta(Handle.BR, new AffineTransform())); 101 symbol(symbols.get(1), new Delta(Handle.BL, new AffineTransform())); 102 symbol(symbols.get(2), new Delta(Handle.TR, new AffineTransform())); 103 symbol(symbols.get(3), new Delta(Handle.TL, new AffineTransform())); 104 break; 105 case 5: 106 symbol(symbols.get(0), new Delta(Handle.BR, new AffineTransform())); 107 symbol(symbols.get(1), new Delta(Handle.BL, new AffineTransform())); 108 symbol(symbols.get(2), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 109 symbol(symbols.get(3), new Delta(Handle.TC, new AffineTransform())); 110 symbol(symbols.get(4), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 111 break; 112 case 6: 113 symbol(symbols.get(0), new Delta(Handle.BR, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 114 symbol(symbols.get(1), new Delta(Handle.BC, new AffineTransform())); 115 symbol(symbols.get(2), new Delta(Handle.BL, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 116 symbol(symbols.get(3), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 117 symbol(symbols.get(4), new Delta(Handle.TC, new AffineTransform())); 118 symbol(symbols.get(5), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 119 break; 120 case 7: 121 symbol(symbols.get(0), new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -bbox.height/2))); 122 symbol(symbols.get(1), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 123 symbol(symbols.get(2), new Delta(Handle.CC, new AffineTransform())); 124 symbol(symbols.get(3), new Delta(Handle.LC, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 125 symbol(symbols.get(4), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, bbox.height/2))); 126 symbol(symbols.get(5), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, bbox.height/2))); 127 symbol(symbols.get(6), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, bbox.height/2))); 128 break; 129 case 8: 130 symbol(symbols.get(0), new Delta(Handle.BR, AffineTransform.getTranslateInstance(0, -bbox.height/2))); 131 symbol(symbols.get(1), new Delta(Handle.BL, AffineTransform.getTranslateInstance(0, -bbox.height/2))); 132 symbol(symbols.get(2), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 133 symbol(symbols.get(3), new Delta(Handle.CC, new AffineTransform())); 134 symbol(symbols.get(4), new Delta(Handle.LC, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 135 symbol(symbols.get(5), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, bbox.height/2))); 136 symbol(symbols.get(6), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, bbox.height/2))); 137 symbol(symbols.get(7), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, bbox.height/2))); 138 break; 139 case 9: 140 symbol(symbols.get(0), new Delta(Handle.BR, AffineTransform.getTranslateInstance(-bbox.width/2, -bbox.height/2))); 141 symbol(symbols.get(1), new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -bbox.height/2))); 142 symbol(symbols.get(2), new Delta(Handle.BL, AffineTransform.getTranslateInstance(bbox.width/2, -bbox.height/2))); 143 symbol(symbols.get(3), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 144 symbol(symbols.get(4), new Delta(Handle.CC, new AffineTransform())); 145 symbol(symbols.get(5), new Delta(Handle.LC, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 146 symbol(symbols.get(6), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, bbox.height/2))); 147 symbol(symbols.get(7), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, bbox.height/2))); 148 symbol(symbols.get(8), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, bbox.height/2))); 149 break; 150 } 151 } 152 153 private static Rectangle2D.Double symbolSize(Symbol symbol) { 154 Symbol ssymb = symbol; 155 while (ssymb != null) { 156 for (Instr item : symbol) { 157 if (item.type == Form.BBOX) { 158 return (Rectangle2D.Double) item.params; 159 } 160 if (item.type == Form.SYMB) { 161 ssymb = ((SubSymbol) item.params).instr; 162 break; 163 } 164 } 165 if (ssymb == symbol) 166 break; 167 } 168 return null; 169 } 170 171 public static void lineSymbols(Symbol prisymb, double space, Symbol secsymb, Symbol tersymb, int ratio, Color col) { 172 if ((Rules.feature.geom.prim == Pflag.NOSP) || (Rules.feature.geom.prim == Pflag.POINT)) 173 return; 174 Rectangle2D.Double prect = symbolSize(prisymb); 175 Rectangle2D.Double srect = symbolSize(secsymb); 176 Rectangle2D.Double trect = symbolSize(tersymb); 177 if (srect == null) 178 ratio = 0; 179 if (prect != null) { 180 double psize = Math.abs(prect.getY()) * sScale; 181 double ssize = (srect != null) ? Math.abs(srect.getY()) * sScale : 0; 182 double tsize = (trect != null) ? Math.abs(srect.getY()) * sScale : 0; 183 Point2D prev = new Point2D.Double(); 184 Point2D next = new Point2D.Double(); 185 Point2D curr = new Point2D.Double(); 186 Point2D succ = new Point2D.Double(); 187 boolean gap = true; 188 boolean piv = false; 189 double len = 0; 190 double angle = 0; 191 int stcount = ratio; 192 boolean stflag = false; 193 Symbol symbol = prisymb; 194 GeomIterator git = map.new GeomIterator(Rules.feature.geom); 195 while (git.hasComp()) { 196 git.nextComp(); 197 boolean first = true; 198 while (git.hasEdge()) { 199 git.nextEdge(); 200 while (git.hasNode()) { 201 Snode node = git.next(); 202 if (node == null) continue; 203 prev = next; 204 next = context.getPoint(node); 205 angle = Math.atan2(next.getY() - prev.getY(), next.getX() - prev.getX()); 206 piv = true; 207 if (first) { 208 curr = succ = next; 209 gap = (space > 0); 210 stcount = ratio - 1; 211 symbol = prisymb; 212 len = gap ? psize * space * 0.5 : psize; 213 first = false; 214 } else { 215 while (curr.distance(next) >= len) { 216 if (piv) { 217 double rem = len; 218 double s = prev.distance(next); 219 double p = curr.distance(prev); 220 if ((s > 0) && (p > 0)) { 221 double n = curr.distance(next); 222 double theta = Math.acos((s * s + p * p - n * n) / 2 / s / p); 223 double phi = Math.asin(p / len * Math.sin(theta)); 224 rem = len * Math.sin(Math.PI - theta - phi) / Math.sin(theta); 225 } 226 succ = new Point2D.Double(prev.getX() + (rem * Math.cos(angle)), prev.getY() + (rem * Math.sin(angle))); 227 piv = false; 228 } else { 229 succ = new Point2D.Double(curr.getX() + (len * Math.cos(angle)), curr.getY() + (len * Math.sin(angle))); 230 } 231 if (!gap) { 232 Symbols.drawSymbol(g2, symbol, sScale, curr.getX(), curr.getY(), new Scheme(col), 233 new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.atan2((succ.getY() - curr.getY()), (succ.getX() - curr.getX())) + Math.toRadians(90)))); 234 } 235 if (space > 0) 236 gap = !gap; 237 curr = succ; 238 len = gap ? (psize * space) : (--stcount == 0) ? (stflag ? tsize : ssize) : psize; 239 if (stcount == 0) { 240 symbol = stflag ? tersymb : secsymb; 241 if (trect != null) 242 stflag = !stflag; 243 stcount = ratio; 244 } else { 245 symbol = prisymb; 246 } 247 } 248 } 249 } 250 } 251 } 252 } 253 } 254 255 public static void lineVector(LineStyle style) { 256 Path2D.Double p = new Path2D.Double(); 257 p.setWindingRule(GeneralPath.WIND_EVEN_ODD); 258 Point2D point; 259 GeomIterator git = map.new GeomIterator(Rules.feature.geom); 260 while (git.hasComp()) { 261 git.nextComp(); 262 boolean first = true; 263 while (git.hasEdge()) { 264 git.nextEdge(); 265 point = context.getPoint(git.next()); 266 if (first) { 267 p.moveTo(point.getX(), point.getY()); 268 first = false; 269 } else { 270 p.lineTo(point.getX(), point.getY()); 271 } 272 while (git.hasNode()) { 273 Snode node = git.next(); 274 if (node == null) continue; 275 point = context.getPoint(node); 276 p.lineTo(point.getX(), point.getY()); 277 } 278 } 279 } 280 if ((style.fill != null) && (Rules.feature.geom.prim == Pflag.AREA)) { 281 g2.setPaint(style.fill); 282 g2.fill(p); 283 } 284 if (style.line != null) { 285 if (style.dash != null) { 286 float[] dash = new float[style.dash.length]; 287 System.arraycopy(style.dash, 0, dash, 0, style.dash.length); 288 for (int i = 0; i < style.dash.length; i++) { 289 dash[i] *= (float) sScale; 290 } 291 g2.setStroke(new BasicStroke((float) (style.width * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1, dash, 0)); 292 } else { 293 g2.setStroke(new BasicStroke((float) (style.width * sScale), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 294 } 295 g2.setPaint(style.line); 296 g2.draw(p); 297 } 298 } 299 300 public static void lineCircle(LineStyle style, double radius, UniHLU units) { 301 switch (units) { 302 case HLU_FEET: 303 radius /= 6076; 304 break; 305 case HLU_KMTR: 306 radius /= 1.852; 307 break; 308 case HLU_HMTR: 309 radius /= 18.52; 310 break; 311 case HLU_SMIL: 312 radius /= 1.15078; 313 break; 314 case HLU_NMIL: 315 break; 316 default: 317 radius /= 1852; 318 break; 319 } 320 radius *= context.mile(Rules.feature); 321 Symbol circle = new Symbol(); 322 if (style.fill != null) { 323 circle.add(new Instr(Form.FILL, style.fill)); 324 circle.add(new Instr(Form.RSHP, new Ellipse2D.Double(-radius,-radius,radius*2,radius*2))); 325 } 326 circle.add(new Instr(Form.FILL, style.line)); 327 circle.add(new Instr(Form.STRK, new BasicStroke(style.width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, style.dash, 0))); 328 circle.add(new Instr(Form.ELPS, new Ellipse2D.Double(-radius,-radius,radius*2,radius*2))); 329 Point2D point = context.getPoint(Rules.feature.geom.centre); 330 Symbols.drawSymbol(g2, circle, 1, point.getX(), point.getY(), null, null); 331 } 332 333 public static void fillPattern(BufferedImage image) { 334 Path2D.Double p = new Path2D.Double(); 335 p.setWindingRule(GeneralPath.WIND_EVEN_ODD); 336 Point2D point; 337 switch (Rules.feature.geom.prim) { 338 case POINT: 339 point = context.getPoint(Rules.feature.geom.centre); 340 g2.drawImage(image, new AffineTransformOp(AffineTransform.getScaleInstance(sScale, sScale), AffineTransformOp.TYPE_NEAREST_NEIGHBOR), 341 (int)(point.getX() - (50 * sScale)), (int)(point.getY() - (50 * sScale))); 342 break; 343 case AREA: 344 GeomIterator git = map.new GeomIterator(Rules.feature.geom); 345 while (git.hasComp()) { 346 git.nextComp(); 347 boolean newComp = true; 348 while (git.hasEdge()) { 349 git.nextEdge(); 350 point = context.getPoint(git.next()); 351 if (newComp) { 352 p.moveTo(point.getX(), point.getY()); 353 newComp = false; 354 } else { 355 p.lineTo(point.getX(), point.getY()); 356 } 357 while (git.hasNode()) { 358 Snode node = git.next(); 359 if (node == null) continue; 360 point = context.getPoint(node); 361 p.lineTo(point.getX(), point.getY()); 362 } 363 } 364 } 365 g2.setPaint(new TexturePaint(image, new Rectangle(0, 0, 1 + (int)(300 * sScale), 1 + (int)(300 * sScale)))); 366 g2.fill(p); 367 break; 368 default: 369 break; 370 } 371 } 372 373 public static void labelText(String str, Font font, Color tc) { 374 labelText(str, font, tc, LabelStyle.NONE, null, null, null); 375 } 376 public static void labelText(String str, Font font, Color tc, Delta delta) { 377 labelText(str, font, tc, LabelStyle.NONE, null, null, delta); 378 } 379 public static void labelText(String str, Font font, Color tc, LabelStyle style, Color fg) { 380 labelText(str, font, tc, style, fg, null, null); 381 } 382 public static void labelText(String str, Font font, Color tc, LabelStyle style, Color fg, Color bg) { 383 labelText(str, font, tc, style, fg, bg, null); 384 } 385 public static void labelText(String str, Font font, Color tc, LabelStyle style, Color fg, Delta delta) { 386 labelText(str, font, tc, style, fg, null, delta); 387 } 388 public static void labelText(String str, Font font, Color tc, LabelStyle style, Color fg, Color bg, Delta delta) { 389 if (delta == null) delta = new Delta(Handle.CC); 390 if (bg == null) bg = new Color(0x00000000, true); 391 if ((str == null) || (str.isEmpty())) str = " "; 392 FontRenderContext frc = g2.getFontRenderContext(); 393 GlyphVector gv = font.deriveFont((float)(font.getSize())).createGlyphVector(frc, str.equals(" ") ? "M" : str); 394 Rectangle2D bounds = gv.getVisualBounds(); 395 double width = bounds.getWidth(); 396 double height = bounds.getHeight(); 397 Symbol label = new Symbol(); 398 double lx, ly, tx, ty; 399 switch (style) { 400 case RRCT: 401 width += height * 1.0; 402 height *= 1.5; 403 if (width < height) width = height; 404 lx = -width / 2; 405 ly = -height / 2; 406 tx = lx + (height * 0.34); 407 ty = ly + (height * 0.17); 408 label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx,ly,width,height))); 409 label.add(new Instr(Form.FILL, bg)); 410 label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx,ly,width,height,height,height))); 411 label.add(new Instr(Form.FILL, fg)); 412 label.add(new Instr(Form.STRK, new BasicStroke(1 + (int)(height/10), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER))); 413 label.add(new Instr(Form.RRCT, new RoundRectangle2D.Double(lx,ly,width,height,height,height))); 414 break; 415 case VCLR: 416 width += height * 1.0; 417 height *= 2.0; 418 if (width < height) width = height; 419 lx = -width / 2; 420 ly = -height / 2; 421 tx = lx + (height * 0.27); 422 ty = ly + (height * 0.25); 423 label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx,ly,width,height))); 424 label.add(new Instr(Form.FILL, bg)); 425 label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx,ly,width,height,height,height))); 426 label.add(new Instr(Form.FILL, fg)); 427 int sw = 1 + (int)(height/10); 428 double po = sw / 2; 429 label.add(new Instr(Form.STRK, new BasicStroke(sw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER))); 430 Path2D.Double p = new Path2D.Double(); p.moveTo(-height*0.2,-ly-po); p.lineTo(height*0.2,-ly-po); p.moveTo(0,-ly-po); p.lineTo(0,-ly-po-(height*0.15)); 431 p.moveTo(-height*0.2,ly+po); p.lineTo((height*0.2),ly+po); p.moveTo(0,ly+po); p.lineTo(0,ly+po+(height*0.15)); 432 label.add(new Instr(Form.PLIN, p)); 433 break; 434 case PCLR: 435 width += height * 1.0; 436 height *= 2.0; 437 if (width < height) width = height; 438 lx = -width / 2; 439 ly = -height / 2; 440 tx = lx + (height * 0.27); 441 ty = ly + (height * 0.25); 442 label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx,ly,width,height))); 443 label.add(new Instr(Form.FILL, bg)); 444 label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx,ly,width,height,height,height))); 445 label.add(new Instr(Form.FILL, fg)); 446 sw = 1 + (int)(height/10); 447 po = sw / 2; 448 label.add(new Instr(Form.STRK, new BasicStroke(sw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER))); 449 p = new Path2D.Double(); p.moveTo(-height*0.2,-ly-po); p.lineTo(height*0.2,-ly-po); p.moveTo(0,-ly-po); p.lineTo(0,-ly-po-(height*0.15)); 450 p.moveTo(-height*0.2,ly+po); p.lineTo((height*0.2),ly+po); p.moveTo(0,ly+po); p.lineTo(0,ly+po+(height*0.15)); 451 label.add(new Instr(Form.PLIN, p)); 452 label.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Areas.CableFlash, 1, 0, 0, null, new Delta(Handle.CC, new AffineTransform(0,-1,1,0,-width/2,0))))); 453 label.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Areas.CableFlash, 1, 0, 0, null, new Delta(Handle.CC, new AffineTransform(0,-1,1,0,width/2,0))))); 454 break; 455 case HCLR: 456 width += height * 1.5; 457 height *= 1.5; 458 if (width < height) width = height; 459 lx = -width / 2; 460 ly = -height / 2; 461 tx = lx + (height * 0.5); 462 ty = ly + (height * 0.17); 463 label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx,ly,width,height))); 464 label.add(new Instr(Form.FILL, bg)); 465 label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx,ly,width,height,height,height))); 466 label.add(new Instr(Form.FILL, fg)); 467 sw = 1 + (int)(height/10); 468 double vo = height / 4; 469 label.add(new Instr(Form.STRK, new BasicStroke(sw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER))); 470 p = new Path2D.Double(); p.moveTo(-width*0.4-sw,-ly-vo); p.lineTo(-width*0.4-sw,ly+vo); p.moveTo(-width*0.4-sw,0); p.lineTo(-width*0.4+sw,0); 471 p.moveTo(width*0.4+sw,-ly-vo); p.lineTo(width*0.4+sw,ly+vo); p.moveTo(width*0.4-sw,0); p.lineTo(width*0.4+sw,0); 472 label.add(new Instr(Form.PLIN, p)); 473 break; 474 default: 475 lx = -width / 2; 476 ly = -height / 2; 477 tx = lx; 478 ty = ly; 479 label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx,ly,width,height))); 480 break; 481 } 482 label.add(new Instr(Form.TEXT, new Caption(str, font, tc, new Delta(Handle.TL, AffineTransform.getTranslateInstance(tx, ty))))); 483 Point2D point = context.getPoint(Rules.feature.geom.centre); 484 Symbols.drawSymbol(g2, label, sScale, point.getX(), point.getY(), null, delta); 485 } 486 487 public static void lineText(String str, Font font, Color colour, double dy) { 488 if (!str.isEmpty()) { 489 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 490 g2.setPaint(colour); 491 FontRenderContext frc = g2.getFontRenderContext(); 492 GlyphVector gv = font.deriveFont(font.getSize2D() * (float) sScale).createGlyphVector(frc, str); 493 double width = gv.getVisualBounds().getWidth(); 494 double height = gv.getVisualBounds().getHeight(); 495 double offset = (Rules.feature.geom.length * context.mile(Rules.feature) - width) / 2; 496 if (offset > 0) { 497 Point2D before = null; 498 Point2D after = null; 499 ArrayList<Point2D> between = new ArrayList<>(); 500 Point2D prev = null; 501 Point2D next = null; 502 double length = 0; 503 double lb = 0; 504 double la = 0; 505 GeomIterator git = map.new GeomIterator(Rules.feature.geom); 506 if (git.hasComp()) { 507 git.nextComp(); 508 while (git.hasEdge()) { 509 git.nextEdge(); 510 while (git.hasNode()) { 511 Snode node = git.next(); 512 if (node == null) 513 continue; 514 prev = next; 515 next = context.getPoint(node); 516 if (prev != null) 517 length += Math.sqrt(Math.pow((next.getX() - prev.getX()), 2) + Math.pow((next.getY() - prev.getY()), 2)); 518 if (length < offset) { 519 before = next; 520 lb = la = length; 521 } else if (after == null) { 522 if (length > (offset + width)) { 523 after = next; 524 la = length; 525 break; 526 } else { 527 between.add(next); 528 } 529 } 530 } 531 if (after != null) 532 break; 533 } 534 } 535 if (after != null) { 536 double angle = Math.atan2((after.getY() - before.getY()), (after.getX() - before.getX())); 537 double rotate = Math.abs(angle) < (Math.PI / 2) ? angle : angle + Math.PI; 538 Point2D mid = new Point2D.Double((before.getX() + after.getX()) / 2, (before.getY() + after.getY()) / 2); 539 Point2D centre = context.getPoint(Rules.feature.geom.centre); 540 AffineTransform pos = AffineTransform.getTranslateInstance(-dy * Math.sin(rotate), dy * Math.cos(rotate)); 541 pos.rotate(rotate); 542 pos.translate((mid.getX() - centre.getX()), (mid.getY() - centre.getY())); 543 Symbol label = new Symbol(); 544 label.add(new Instr(Form.BBOX, new Rectangle2D.Double((-width / 2), (-height), width, height))); 545 label.add(new Instr(Form.TEXT, new Caption(str, font, colour, new Delta(Handle.BC)))); 546 Symbols.drawSymbol(g2, label, sScale, centre.getX(), centre.getY(), null, new Delta(Handle.BC, pos)); 547 } 548 } 549 } 550 } 551 552 public static void lightSector(Color col1, Color col2, double radius, double s1, double s2, Double dir, String str) { 553 if ((zoom >= 16) && (radius > 0.2)) { 554 radius /= (Math.pow(2, zoom-15)); 555 } 556 double mid = (((s1 + s2) / 2) + (s1 > s2 ? 180 : 0)) % 360; 557 g2.setStroke(new BasicStroke((float) (3.0 * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1, new float[] {20 * (float)sScale, 20 * (float)sScale}, 0)); 558 g2.setPaint(Color.black); 559 Point2D.Double centre = (Point2D.Double) context.getPoint(Rules.feature.geom.centre); 560 double radial = radius * context.mile(Rules.feature); 561 if (dir != null) { 562 g2.draw(new Line2D.Double(centre.x, centre.y, centre.x - radial * Math.sin(Math.toRadians(dir)), centre.y + radial * Math.cos(Math.toRadians(dir)))); 563 } else { 564 if ((s1 != 0.0) || (s2 != 360.0)) { 565 g2.draw(new Line2D.Double(centre.x, centre.y, centre.x - radial * Math.sin(Math.toRadians(s1)), centre.y + radial * Math.cos(Math.toRadians(s1)))); 566 g2.draw(new Line2D.Double(centre.x, centre.y, centre.x - radial * Math.sin(Math.toRadians(s2)), centre.y + radial * Math.cos(Math.toRadians(s2)))); 567 } 568 } 569 double arcWidth = 10.0 * sScale; 570 g2.setStroke(new BasicStroke((float)arcWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1)); 571 g2.setPaint(col1); 572 g2.draw(new Arc2D.Double(centre.x - radial, centre.y - radial, 2 * radial, 2 * radial, -(s1 + 90), ((s1 < s2) ? (s1 - s2) : (s1 - s2 - 360)), Arc2D.OPEN)); 573 if (col2 != null) { 574 g2.setPaint(col2); 575 g2.draw(new Arc2D.Double(centre.x - radial + arcWidth, centre.y - radial + arcWidth, 2 * (radial - arcWidth), 2 * (radial - arcWidth), -(s1 + 90), ((s1 < s2) ? (s1 - s2) : (s1 - s2 - 360)), Arc2D.OPEN)); 576 } 577 if ((str != null) && (!str.isEmpty())) { 578 Font font = new Font("Arial", Font.PLAIN, 40); 579 double arc = (s2 > s1) ? (s2 - s1) : (s2 - s1 + 360); 580 double awidth = (Math.toRadians(arc) * radial); 581 boolean hand = ((mid > 270) || (mid < 90)); 582 double phi = Math.toRadians(mid); 583 radial += 30 * sScale; 584 AffineTransform at = AffineTransform.getTranslateInstance(-radial * Math.sin(phi) / sScale, radial * Math.cos(phi) / sScale); 585 if ((font.getSize() * sScale * str.length()) < awidth) { 586 at.rotate(Math.toRadians(mid + (hand ? 0 : 180))); 587 labelText(str, font, Color.black, new Delta(Handle.CC, at)); 588 } else if ((font.getSize() * sScale) < awidth) { 589 hand = (mid < 180); 590 at.rotate(Math.toRadians(mid + (hand ? -90 : 90))); 591 labelText(str, font, Color.black, hand ? new Delta(Handle.RC, at) : new Delta(Handle.LC, at)); 592 } 593 if (dir != null) { 594 font = new Font("Arial", Font.PLAIN, 30); 595 str = dir + "°"; 596 hand = (dir > 180); 597 phi = Math.toRadians(dir + (hand ? -0.5 : 0.5)); 598 radial -= 70 * sScale; 599 at = AffineTransform.getTranslateInstance(-radial * Math.sin(phi) / sScale, radial * Math.cos(phi) / sScale); 600 at.rotate(Math.toRadians(dir + (hand ? 90 : -90))); 601 labelText(str, font, Color.black, hand ? new Delta(Handle.BR, at) : new Delta(Handle.BL, at)); 602 } 603 } 604 } 53 public static final double[] symbolScale = {256.0, 128.0, 64.0, 32.0, 16.0, 8.0, 4.0, 2.0, 1.0, 0.61, 0.372, 0.227, 0.138, 0.0843, 0.0514, 0.0313, 0.0191, 0.0117, 0.007 }; 54 55 public enum LabelStyle { NONE, RRCT, RECT, ELPS, CIRC, VCLR, PCLR, HCLR } 56 57 static ChartContext context; 58 static S57map map; 59 static double sScale; 60 static Graphics2D g2; 61 static int zoom; 62 63 public static void reRender(Graphics2D g, Rectangle rect, int z, double factor, S57map m, ChartContext c) { 64 g2 = g; 65 zoom = z; 66 context = c; 67 map = m; 68 sScale = symbolScale[zoom] * factor; 69 if (map != null) { 70 if (context.clip()) { 71 Point2D tl = context.getPoint(map.new Snode(map.bounds.maxlat, map.bounds.minlon)); 72 Point2D br = context.getPoint(map.new Snode(map.bounds.minlat, map.bounds.maxlon)); 73 g2.clip(new Rectangle2D.Double(tl.getX(), tl.getY(), (br.getX() - tl.getX()), (br.getY() - tl.getY()))); 74 } 75 g2.setBackground(context.background(map)); 76 g2.clearRect(rect.x, rect.y, rect.width, rect.height); 77 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 78 g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); 79 g2.setStroke(new BasicStroke(0, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); 80 Rules.rules(); 81 } 82 } 83 84 public static void symbol(Symbol symbol) { 85 Point2D point = context.getPoint(Rules.feature.geom.centre); 86 Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), null, null); 87 } 88 89 public static void symbol(Symbol symbol, Scheme scheme) { 90 Point2D point = context.getPoint(Rules.feature.geom.centre); 91 Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), scheme, null); 92 } 93 94 public static void symbol(Symbol symbol, Delta delta) { 95 Point2D point = context.getPoint(Rules.feature.geom.centre); 96 Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), null, delta); 97 } 98 99 public static void symbol(Symbol symbol, Scheme scheme, Delta delta) { 100 Point2D point = context.getPoint(Rules.feature.geom.centre); 101 Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), scheme, delta); 102 } 103 104 public static void cluster(ArrayList<Symbol> symbols) { 105 Rectangle2D.Double bbox = null; 106 if (symbols.size() > 4) { 107 for (Instr instr : symbols.get(0)) { 108 if (instr.type == Form.BBOX) { 109 bbox = (Rectangle2D.Double) instr.params; 110 break; 111 } 112 } 113 if (bbox == null) return; 114 } 115 switch (symbols.size()) { 116 case 1: 117 symbol(symbols.get(0), new Delta(Handle.CC, new AffineTransform())); 118 break; 119 case 2: 120 symbol(symbols.get(0), new Delta(Handle.RC, new AffineTransform())); 121 symbol(symbols.get(1), new Delta(Handle.LC, new AffineTransform())); 122 break; 123 case 3: 124 symbol(symbols.get(0), new Delta(Handle.BC, new AffineTransform())); 125 symbol(symbols.get(1), new Delta(Handle.TR, new AffineTransform())); 126 symbol(symbols.get(2), new Delta(Handle.TL, new AffineTransform())); 127 break; 128 case 4: 129 symbol(symbols.get(0), new Delta(Handle.BR, new AffineTransform())); 130 symbol(symbols.get(1), new Delta(Handle.BL, new AffineTransform())); 131 symbol(symbols.get(2), new Delta(Handle.TR, new AffineTransform())); 132 symbol(symbols.get(3), new Delta(Handle.TL, new AffineTransform())); 133 break; 134 case 5: 135 symbol(symbols.get(0), new Delta(Handle.BR, new AffineTransform())); 136 symbol(symbols.get(1), new Delta(Handle.BL, new AffineTransform())); 137 symbol(symbols.get(2), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 138 symbol(symbols.get(3), new Delta(Handle.TC, new AffineTransform())); 139 symbol(symbols.get(4), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 140 break; 141 case 6: 142 symbol(symbols.get(0), new Delta(Handle.BR, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 143 symbol(symbols.get(1), new Delta(Handle.BC, new AffineTransform())); 144 symbol(symbols.get(2), new Delta(Handle.BL, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 145 symbol(symbols.get(3), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 146 symbol(symbols.get(4), new Delta(Handle.TC, new AffineTransform())); 147 symbol(symbols.get(5), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 148 break; 149 case 7: 150 symbol(symbols.get(0), new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -bbox.height/2))); 151 symbol(symbols.get(1), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 152 symbol(symbols.get(2), new Delta(Handle.CC, new AffineTransform())); 153 symbol(symbols.get(3), new Delta(Handle.LC, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 154 symbol(symbols.get(4), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, bbox.height/2))); 155 symbol(symbols.get(5), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, bbox.height/2))); 156 symbol(symbols.get(6), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, bbox.height/2))); 157 break; 158 case 8: 159 symbol(symbols.get(0), new Delta(Handle.BR, AffineTransform.getTranslateInstance(0, -bbox.height/2))); 160 symbol(symbols.get(1), new Delta(Handle.BL, AffineTransform.getTranslateInstance(0, -bbox.height/2))); 161 symbol(symbols.get(2), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 162 symbol(symbols.get(3), new Delta(Handle.CC, new AffineTransform())); 163 symbol(symbols.get(4), new Delta(Handle.LC, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 164 symbol(symbols.get(5), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, bbox.height/2))); 165 symbol(symbols.get(6), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, bbox.height/2))); 166 symbol(symbols.get(7), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, bbox.height/2))); 167 break; 168 case 9: 169 symbol(symbols.get(0), new Delta(Handle.BR, AffineTransform.getTranslateInstance(-bbox.width/2, -bbox.height/2))); 170 symbol(symbols.get(1), new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -bbox.height/2))); 171 symbol(symbols.get(2), new Delta(Handle.BL, AffineTransform.getTranslateInstance(bbox.width/2, -bbox.height/2))); 172 symbol(symbols.get(3), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-bbox.width/2, 0))); 173 symbol(symbols.get(4), new Delta(Handle.CC, new AffineTransform())); 174 symbol(symbols.get(5), new Delta(Handle.LC, AffineTransform.getTranslateInstance(bbox.width/2, 0))); 175 symbol(symbols.get(6), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, bbox.height/2))); 176 symbol(symbols.get(7), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, bbox.height/2))); 177 symbol(symbols.get(8), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, bbox.height/2))); 178 break; 179 } 180 } 181 182 private static Rectangle2D.Double symbolSize(Symbol symbol) { 183 Symbol ssymb = symbol; 184 while (ssymb != null) { 185 for (Instr item : symbol) { 186 if (item.type == Form.BBOX) { 187 return (Rectangle2D.Double) item.params; 188 } 189 if (item.type == Form.SYMB) { 190 ssymb = ((SubSymbol) item.params).instr; 191 break; 192 } 193 } 194 if (ssymb == symbol) 195 break; 196 } 197 return null; 198 } 199 200 public static void lineSymbols(Symbol prisymb, double space, Symbol secsymb, Symbol tersymb, int ratio, Color col) { 201 if ((Rules.feature.geom.prim == Pflag.NOSP) || (Rules.feature.geom.prim == Pflag.POINT)) 202 return; 203 Rectangle2D.Double prect = symbolSize(prisymb); 204 Rectangle2D.Double srect = symbolSize(secsymb); 205 Rectangle2D.Double trect = symbolSize(tersymb); 206 if (srect == null) 207 ratio = 0; 208 if (prect != null) { 209 double psize = Math.abs(prect.getY()) * sScale; 210 double ssize = (srect != null) ? Math.abs(srect.getY()) * sScale : 0; 211 double tsize = (trect != null) ? Math.abs(srect.getY()) * sScale : 0; 212 Point2D prev = new Point2D.Double(); 213 Point2D next = new Point2D.Double(); 214 Point2D curr = new Point2D.Double(); 215 Point2D succ = new Point2D.Double(); 216 boolean gap = true; 217 boolean piv = false; 218 double len = 0; 219 double angle = 0; 220 int stcount = ratio; 221 boolean stflag = false; 222 Symbol symbol = prisymb; 223 GeomIterator git = map.new GeomIterator(Rules.feature.geom); 224 while (git.hasComp()) { 225 git.nextComp(); 226 boolean first = true; 227 while (git.hasEdge()) { 228 git.nextEdge(); 229 while (git.hasNode()) { 230 Snode node = git.next(); 231 if (node == null) continue; 232 prev = next; 233 next = context.getPoint(node); 234 angle = Math.atan2(next.getY() - prev.getY(), next.getX() - prev.getX()); 235 piv = true; 236 if (first) { 237 curr = succ = next; 238 gap = (space > 0); 239 stcount = ratio - 1; 240 symbol = prisymb; 241 len = gap ? psize * space * 0.5 : psize; 242 first = false; 243 } else { 244 while (curr.distance(next) >= len) { 245 if (piv) { 246 double rem = len; 247 double s = prev.distance(next); 248 double p = curr.distance(prev); 249 if ((s > 0) && (p > 0)) { 250 double n = curr.distance(next); 251 double theta = Math.acos((s * s + p * p - n * n) / 2 / s / p); 252 double phi = Math.asin(p / len * Math.sin(theta)); 253 rem = len * Math.sin(Math.PI - theta - phi) / Math.sin(theta); 254 } 255 succ = new Point2D.Double(prev.getX() + (rem * Math.cos(angle)), prev.getY() + (rem * Math.sin(angle))); 256 piv = false; 257 } else { 258 succ = new Point2D.Double(curr.getX() + (len * Math.cos(angle)), curr.getY() + (len * Math.sin(angle))); 259 } 260 if (!gap) { 261 Symbols.drawSymbol(g2, symbol, sScale, curr.getX(), curr.getY(), new Scheme(col), 262 new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.atan2((succ.getY() - curr.getY()), (succ.getX() - curr.getX())) + Math.toRadians(90)))); 263 } 264 if (space > 0) 265 gap = !gap; 266 curr = succ; 267 len = gap ? (psize * space) : (--stcount == 0) ? (stflag ? tsize : ssize) : psize; 268 if (stcount == 0) { 269 symbol = stflag ? tersymb : secsymb; 270 if (trect != null) 271 stflag = !stflag; 272 stcount = ratio; 273 } else { 274 symbol = prisymb; 275 } 276 } 277 } 278 } 279 } 280 } 281 } 282 } 283 284 public static void lineVector(LineStyle style) { 285 Path2D.Double p = new Path2D.Double(); 286 p.setWindingRule(GeneralPath.WIND_EVEN_ODD); 287 Point2D point; 288 GeomIterator git = map.new GeomIterator(Rules.feature.geom); 289 while (git.hasComp()) { 290 git.nextComp(); 291 boolean first = true; 292 while (git.hasEdge()) { 293 git.nextEdge(); 294 point = context.getPoint(git.next()); 295 if (first) { 296 p.moveTo(point.getX(), point.getY()); 297 first = false; 298 } else { 299 p.lineTo(point.getX(), point.getY()); 300 } 301 while (git.hasNode()) { 302 Snode node = git.next(); 303 if (node == null) continue; 304 point = context.getPoint(node); 305 p.lineTo(point.getX(), point.getY()); 306 } 307 } 308 } 309 if ((style.fill != null) && (Rules.feature.geom.prim == Pflag.AREA)) { 310 g2.setPaint(style.fill); 311 g2.fill(p); 312 } 313 if (style.line != null) { 314 if (style.dash != null) { 315 float[] dash = new float[style.dash.length]; 316 System.arraycopy(style.dash, 0, dash, 0, style.dash.length); 317 for (int i = 0; i < style.dash.length; i++) { 318 dash[i] *= (float) sScale; 319 } 320 g2.setStroke(new BasicStroke((float) (style.width * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1, dash, 0)); 321 } else { 322 g2.setStroke(new BasicStroke((float) (style.width * sScale), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 323 } 324 g2.setPaint(style.line); 325 g2.draw(p); 326 } 327 } 328 329 public static void lineCircle(LineStyle style, double radius, UniHLU units) { 330 switch (units) { 331 case HLU_FEET: 332 radius /= 6076; 333 break; 334 case HLU_KMTR: 335 radius /= 1.852; 336 break; 337 case HLU_HMTR: 338 radius /= 18.52; 339 break; 340 case HLU_SMIL: 341 radius /= 1.15078; 342 break; 343 case HLU_NMIL: 344 break; 345 default: 346 radius /= 1852; 347 break; 348 } 349 radius *= context.mile(Rules.feature); 350 Symbol circle = new Symbol(); 351 if (style.fill != null) { 352 circle.add(new Instr(Form.FILL, style.fill)); 353 circle.add(new Instr(Form.RSHP, new Ellipse2D.Double(-radius, -radius, radius*2, radius*2))); 354 } 355 circle.add(new Instr(Form.FILL, style.line)); 356 circle.add(new Instr(Form.STRK, new BasicStroke(style.width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, style.dash, 0))); 357 circle.add(new Instr(Form.ELPS, new Ellipse2D.Double(-radius, -radius, radius*2, radius*2))); 358 Point2D point = context.getPoint(Rules.feature.geom.centre); 359 Symbols.drawSymbol(g2, circle, 1, point.getX(), point.getY(), null, null); 360 } 361 362 public static void fillPattern(BufferedImage image) { 363 Path2D.Double p = new Path2D.Double(); 364 p.setWindingRule(GeneralPath.WIND_EVEN_ODD); 365 Point2D point; 366 switch (Rules.feature.geom.prim) { 367 case POINT: 368 point = context.getPoint(Rules.feature.geom.centre); 369 g2.drawImage(image, new AffineTransformOp(AffineTransform.getScaleInstance(sScale, sScale), AffineTransformOp.TYPE_NEAREST_NEIGHBOR), 370 (int) (point.getX() - (50 * sScale)), (int) (point.getY() - (50 * sScale))); 371 break; 372 case AREA: 373 GeomIterator git = map.new GeomIterator(Rules.feature.geom); 374 while (git.hasComp()) { 375 git.nextComp(); 376 boolean newComp = true; 377 while (git.hasEdge()) { 378 git.nextEdge(); 379 point = context.getPoint(git.next()); 380 if (newComp) { 381 p.moveTo(point.getX(), point.getY()); 382 newComp = false; 383 } else { 384 p.lineTo(point.getX(), point.getY()); 385 } 386 while (git.hasNode()) { 387 Snode node = git.next(); 388 if (node == null) continue; 389 point = context.getPoint(node); 390 p.lineTo(point.getX(), point.getY()); 391 } 392 } 393 } 394 g2.setPaint(new TexturePaint(image, new Rectangle(0, 0, 1 + (int) (300 * sScale), 1 + (int) (300 * sScale)))); 395 g2.fill(p); 396 break; 397 default: 398 break; 399 } 400 } 401 402 public static void labelText(String str, Font font, Color tc) { 403 labelText(str, font, tc, LabelStyle.NONE, null, null, null); 404 } 405 406 public static void labelText(String str, Font font, Color tc, Delta delta) { 407 labelText(str, font, tc, LabelStyle.NONE, null, null, delta); 408 } 409 410 public static void labelText(String str, Font font, Color tc, LabelStyle style, Color fg) { 411 labelText(str, font, tc, style, fg, null, null); 412 } 413 414 public static void labelText(String str, Font font, Color tc, LabelStyle style, Color fg, Color bg) { 415 labelText(str, font, tc, style, fg, bg, null); 416 } 417 418 public static void labelText(String str, Font font, Color tc, LabelStyle style, Color fg, Delta delta) { 419 labelText(str, font, tc, style, fg, null, delta); 420 } 421 422 public static void labelText(String str, Font font, Color tc, LabelStyle style, Color fg, Color bg, Delta delta) { 423 if (delta == null) delta = new Delta(Handle.CC); 424 if (bg == null) bg = new Color(0x00000000, true); 425 if ((str == null) || (str.isEmpty())) str = " "; 426 FontRenderContext frc = g2.getFontRenderContext(); 427 GlyphVector gv = font.deriveFont((float) (font.getSize())).createGlyphVector(frc, str.equals(" ") ? "M" : str); 428 Rectangle2D bounds = gv.getVisualBounds(); 429 double width = bounds.getWidth(); 430 double height = bounds.getHeight(); 431 Symbol label = new Symbol(); 432 double lx, ly, tx, ty; 433 switch (style) { 434 case RRCT: 435 width += height * 1.0; 436 height *= 1.5; 437 if (width < height) width = height; 438 lx = -width / 2; 439 ly = -height / 2; 440 tx = lx + (height * 0.34); 441 ty = ly + (height * 0.17); 442 label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx, ly, width, height))); 443 label.add(new Instr(Form.FILL, bg)); 444 label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx, ly, width, height, height, height))); 445 label.add(new Instr(Form.FILL, fg)); 446 label.add(new Instr(Form.STRK, new BasicStroke(1 + (int) (height/10), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER))); 447 label.add(new Instr(Form.RRCT, new RoundRectangle2D.Double(lx, ly, width, height, height, height))); 448 break; 449 case VCLR: 450 width += height * 1.0; 451 height *= 2.0; 452 if (width < height) width = height; 453 lx = -width / 2; 454 ly = -height / 2; 455 tx = lx + (height * 0.27); 456 ty = ly + (height * 0.25); 457 label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx, ly, width, height))); 458 label.add(new Instr(Form.FILL, bg)); 459 label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx, ly, width, height, height, height))); 460 label.add(new Instr(Form.FILL, fg)); 461 int sw = 1 + (int) (height/10); 462 double po = sw / 2; 463 label.add(new Instr(Form.STRK, new BasicStroke(sw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER))); 464 Path2D.Double p = new Path2D.Double(); p.moveTo(-height*0.2, -ly-po); p.lineTo(height*0.2, -ly-po); p.moveTo(0, -ly-po); p.lineTo(0, -ly-po-(height*0.15)); 465 p.moveTo(-height*0.2, ly+po); p.lineTo((height*0.2), ly+po); p.moveTo(0, ly+po); p.lineTo(0, ly+po+(height*0.15)); 466 label.add(new Instr(Form.PLIN, p)); 467 break; 468 case PCLR: 469 width += height * 1.0; 470 height *= 2.0; 471 if (width < height) width = height; 472 lx = -width / 2; 473 ly = -height / 2; 474 tx = lx + (height * 0.27); 475 ty = ly + (height * 0.25); 476 label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx, ly, width, height))); 477 label.add(new Instr(Form.FILL, bg)); 478 label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx, ly, width, height, height, height))); 479 label.add(new Instr(Form.FILL, fg)); 480 sw = 1 + (int) (height/10); 481 po = sw / 2; 482 label.add(new Instr(Form.STRK, new BasicStroke(sw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER))); 483 p = new Path2D.Double(); p.moveTo(-height*0.2, -ly-po); p.lineTo(height*0.2, -ly-po); p.moveTo(0, -ly-po); p.lineTo(0, -ly-po-(height*0.15)); 484 p.moveTo(-height*0.2, ly+po); p.lineTo((height*0.2), ly+po); p.moveTo(0, ly+po); p.lineTo(0, ly+po+(height*0.15)); 485 label.add(new Instr(Form.PLIN, p)); 486 label.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Areas.CableFlash, 1, 0, 0, null, new Delta(Handle.CC, new AffineTransform(0, -1, 1, 0, -width/2, 0))))); 487 label.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Areas.CableFlash, 1, 0, 0, null, new Delta(Handle.CC, new AffineTransform(0, -1, 1, 0, width/2, 0))))); 488 break; 489 case HCLR: 490 width += height * 1.5; 491 height *= 1.5; 492 if (width < height) width = height; 493 lx = -width / 2; 494 ly = -height / 2; 495 tx = lx + (height * 0.5); 496 ty = ly + (height * 0.17); 497 label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx, ly, width, height))); 498 label.add(new Instr(Form.FILL, bg)); 499 label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx, ly, width, height, height, height))); 500 label.add(new Instr(Form.FILL, fg)); 501 sw = 1 + (int) (height/10); 502 double vo = height / 4; 503 label.add(new Instr(Form.STRK, new BasicStroke(sw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER))); 504 p = new Path2D.Double(); p.moveTo(-width*0.4-sw, -ly-vo); p.lineTo(-width*0.4-sw, ly+vo); p.moveTo(-width*0.4-sw, 0); p.lineTo(-width*0.4+sw, 0); 505 p.moveTo(width*0.4+sw, -ly-vo); p.lineTo(width*0.4+sw, ly+vo); p.moveTo(width*0.4-sw, 0); p.lineTo(width*0.4+sw, 0); 506 label.add(new Instr(Form.PLIN, p)); 507 break; 508 default: 509 lx = -width / 2; 510 ly = -height / 2; 511 tx = lx; 512 ty = ly; 513 label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx, ly, width, height))); 514 break; 515 } 516 label.add(new Instr(Form.TEXT, new Caption(str, font, tc, new Delta(Handle.TL, AffineTransform.getTranslateInstance(tx, ty))))); 517 Point2D point = context.getPoint(Rules.feature.geom.centre); 518 Symbols.drawSymbol(g2, label, sScale, point.getX(), point.getY(), null, delta); 519 } 520 521 public static void lineText(String str, Font font, Color colour, double dy) { 522 if (!str.isEmpty()) { 523 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 524 g2.setPaint(colour); 525 FontRenderContext frc = g2.getFontRenderContext(); 526 GlyphVector gv = font.deriveFont(font.getSize2D() * (float) sScale).createGlyphVector(frc, str); 527 double width = gv.getVisualBounds().getWidth(); 528 double height = gv.getVisualBounds().getHeight(); 529 double offset = (Rules.feature.geom.length * context.mile(Rules.feature) - width) / 2; 530 if (offset > 0) { 531 Point2D before = null; 532 Point2D after = null; 533 ArrayList<Point2D> between = new ArrayList<>(); 534 Point2D prev = null; 535 Point2D next = null; 536 double length = 0; 537 double lb = 0; 538 double la = 0; 539 GeomIterator git = map.new GeomIterator(Rules.feature.geom); 540 if (git.hasComp()) { 541 git.nextComp(); 542 while (git.hasEdge()) { 543 git.nextEdge(); 544 while (git.hasNode()) { 545 Snode node = git.next(); 546 if (node == null) 547 continue; 548 prev = next; 549 next = context.getPoint(node); 550 if (prev != null) 551 length += Math.sqrt(Math.pow((next.getX() - prev.getX()), 2) + Math.pow((next.getY() - prev.getY()), 2)); 552 if (length < offset) { 553 before = next; 554 lb = la = length; 555 } else if (after == null) { 556 if (length > (offset + width)) { 557 after = next; 558 la = length; 559 break; 560 } else { 561 between.add(next); 562 } 563 } 564 } 565 if (after != null) 566 break; 567 } 568 } 569 if (after != null) { 570 double angle = Math.atan2((after.getY() - before.getY()), (after.getX() - before.getX())); 571 double rotate = Math.abs(angle) < (Math.PI / 2) ? angle : angle + Math.PI; 572 Point2D mid = new Point2D.Double((before.getX() + after.getX()) / 2, (before.getY() + after.getY()) / 2); 573 Point2D centre = context.getPoint(Rules.feature.geom.centre); 574 AffineTransform pos = AffineTransform.getTranslateInstance(-dy * Math.sin(rotate), dy * Math.cos(rotate)); 575 pos.rotate(rotate); 576 pos.translate((mid.getX() - centre.getX()), (mid.getY() - centre.getY())); 577 Symbol label = new Symbol(); 578 label.add(new Instr(Form.BBOX, new Rectangle2D.Double((-width / 2), (-height), width, height))); 579 label.add(new Instr(Form.TEXT, new Caption(str, font, colour, new Delta(Handle.BC)))); 580 Symbols.drawSymbol(g2, label, sScale, centre.getX(), centre.getY(), null, new Delta(Handle.BC, pos)); 581 } 582 } 583 } 584 } 585 586 public static void lightSector(Color col1, Color col2, double radius, double s1, double s2, Double dir, String str) { 587 if ((zoom >= 16) && (radius > 0.2)) { 588 radius /= (Math.pow(2, zoom-15)); 589 } 590 double mid = (((s1 + s2) / 2) + (s1 > s2 ? 180 : 0)) % 360; 591 g2.setStroke(new BasicStroke((float) (3.0 * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1, new float[] {20 * (float) sScale, 20 * (float) sScale}, 0)); 592 g2.setPaint(Color.black); 593 Point2D.Double centre = (Point2D.Double) context.getPoint(Rules.feature.geom.centre); 594 double radial = radius * context.mile(Rules.feature); 595 if (dir != null) { 596 g2.draw(new Line2D.Double(centre.x, centre.y, centre.x - radial * Math.sin(Math.toRadians(dir)), centre.y + radial * Math.cos(Math.toRadians(dir)))); 597 } else { 598 if ((s1 != 0.0) || (s2 != 360.0)) { 599 g2.draw(new Line2D.Double(centre.x, centre.y, centre.x - radial * Math.sin(Math.toRadians(s1)), centre.y + radial * Math.cos(Math.toRadians(s1)))); 600 g2.draw(new Line2D.Double(centre.x, centre.y, centre.x - radial * Math.sin(Math.toRadians(s2)), centre.y + radial * Math.cos(Math.toRadians(s2)))); 601 } 602 } 603 double arcWidth = 10.0 * sScale; 604 g2.setStroke(new BasicStroke((float) arcWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1)); 605 g2.setPaint(col1); 606 g2.draw(new Arc2D.Double(centre.x - radial, centre.y - radial, 2 * radial, 2 * radial, -(s1 + 90), ((s1 < s2) ? (s1 - s2) : (s1 - s2 - 360)), Arc2D.OPEN)); 607 if (col2 != null) { 608 g2.setPaint(col2); 609 g2.draw(new Arc2D.Double(centre.x - radial + arcWidth, centre.y - radial + arcWidth, 2 * (radial - arcWidth), 2 * (radial - arcWidth), -(s1 + 90), ((s1 < s2) ? (s1 - s2) : (s1 - s2 - 360)), Arc2D.OPEN)); 610 } 611 if ((str != null) && (!str.isEmpty())) { 612 Font font = new Font("Arial", Font.PLAIN, 40); 613 double arc = (s2 > s1) ? (s2 - s1) : (s2 - s1 + 360); 614 double awidth = (Math.toRadians(arc) * radial); 615 boolean hand = ((mid > 270) || (mid < 90)); 616 double phi = Math.toRadians(mid); 617 radial += 30 * sScale; 618 AffineTransform at = AffineTransform.getTranslateInstance(-radial * Math.sin(phi) / sScale, radial * Math.cos(phi) / sScale); 619 if ((font.getSize() * sScale * str.length()) < awidth) { 620 at.rotate(Math.toRadians(mid + (hand ? 0 : 180))); 621 labelText(str, font, Color.black, new Delta(Handle.CC, at)); 622 } else if ((font.getSize() * sScale) < awidth) { 623 hand = (mid < 180); 624 at.rotate(Math.toRadians(mid + (hand ? -90 : 90))); 625 labelText(str, font, Color.black, hand ? new Delta(Handle.RC, at) : new Delta(Handle.LC, at)); 626 } 627 if (dir != null) { 628 font = new Font("Arial", Font.PLAIN, 30); 629 str = dir + "°"; 630 hand = (dir > 180); 631 phi = Math.toRadians(dir + (hand ? -0.5 : 0.5)); 632 radial -= 70 * sScale; 633 at = AffineTransform.getTranslateInstance(-radial * Math.sin(phi) / sScale, radial * Math.cos(phi) / sScale); 634 at.rotate(Math.toRadians(dir + (hand ? 90 : -90))); 635 labelText(str, font, Color.black, hand ? new Delta(Handle.BR, at) : new Delta(Handle.BL, at)); 636 } 637 } 638 } 605 639 } -
applications/editors/josm/plugins/seachart/src/render/Rules.java
r32393 r32394 18 18 import java.util.HashMap; 19 19 20 import render.ChartContext.RuleSet; 21 import render.Renderer.LabelStyle; 22 import s57.S57att.Att; 23 import s57.S57map.AttMap; 24 import s57.S57map.Feature; 25 import s57.S57map.ObjTab; 26 import s57.S57map.Pflag; 27 import s57.S57map.Rflag; 28 import s57.S57obj.Obj; 20 29 import s57.S57val; 21 import s57.S57val.*; 22 import s57.S57att.*; 23 import s57.S57obj.*; 24 import s57.S57map.*; 25 import render.ChartContext.RuleSet; 26 import render.Renderer.*; 27 import symbols.*; 28 import symbols.Symbols.*; 30 import s57.S57val.AddMRK; 31 import s57.S57val.AttVal; 32 import s57.S57val.BcnSHP; 33 import s57.S57val.BnkWTW; 34 import s57.S57val.BoySHP; 35 import s57.S57val.CatACH; 36 import s57.S57val.CatCBL; 37 import s57.S57val.CatCRN; 38 import s57.S57val.CatDIS; 39 import s57.S57val.CatHAF; 40 import s57.S57val.CatLAM; 41 import s57.S57val.CatLMK; 42 import s57.S57val.CatMOR; 43 import s57.S57val.CatNMK; 44 import s57.S57val.CatOBS; 45 import s57.S57val.CatOFP; 46 import s57.S57val.CatPIL; 47 import s57.S57val.CatPRA; 48 import s57.S57val.CatREA; 49 import s57.S57val.CatROD; 50 import s57.S57val.CatSCF; 51 import s57.S57val.CatSEA; 52 import s57.S57val.CatSIL; 53 import s57.S57val.CatSIT; 54 import s57.S57val.CatSIW; 55 import s57.S57val.CatSLC; 56 import s57.S57val.CatWED; 57 import s57.S57val.CatWRK; 58 import s57.S57val.ColCOL; 59 import s57.S57val.ColPAT; 60 import s57.S57val.FncFNC; 61 import s57.S57val.MarSYS; 62 import s57.S57val.StsSTS; 63 import s57.S57val.TopSHP; 64 import s57.S57val.TrfTRF; 65 import s57.S57val.UniHLU; 66 import s57.S57val.WatLEV; 67 import symbols.Areas; 68 import symbols.Beacons; 69 import symbols.Buoys; 70 import symbols.Facilities; 71 import symbols.Harbours; 72 import symbols.Landmarks; 73 import symbols.Notices; 74 import symbols.Symbols; 75 import symbols.Symbols.Delta; 76 import symbols.Symbols.Handle; 77 import symbols.Symbols.LineStyle; 78 import symbols.Symbols.Patt; 79 import symbols.Symbols.Scheme; 80 import symbols.Symbols.Symbol; 81 import symbols.Topmarks; 29 82 30 83 public class Rules { 31 32 static final DecimalFormat df = new DecimalFormat("#.#"); 33 34 static final EnumMap<ColCOL, Color> bodyColours = new EnumMap<>(ColCOL.class); 35 static { 36 bodyColours.put(ColCOL.COL_UNK, new Color(0, true)); 37 bodyColours.put(ColCOL.COL_WHT, new Color(0xffffff)); 38 bodyColours.put(ColCOL.COL_BLK, new Color(0x000000)); 39 bodyColours.put(ColCOL.COL_RED, new Color(0xd40000)); 40 bodyColours.put(ColCOL.COL_GRN, new Color(0x00d400)); 41 bodyColours.put(ColCOL.COL_BLU, Color.blue); 42 bodyColours.put(ColCOL.COL_YEL, new Color(0xffd400)); 43 bodyColours.put(ColCOL.COL_GRY, Color.gray); 44 bodyColours.put(ColCOL.COL_BRN, new Color(0x8b4513)); 45 bodyColours.put(ColCOL.COL_AMB, new Color(0xfbf00f)); 46 bodyColours.put(ColCOL.COL_VIO, new Color(0xee82ee)); 47 bodyColours.put(ColCOL.COL_ORG, Color.orange); 48 bodyColours.put(ColCOL.COL_MAG, new Color(0xf000f0)); 49 bodyColours.put(ColCOL.COL_PNK, Color.pink); 50 } 51 52 static final EnumMap<ColPAT, Patt> pattMap = new EnumMap<>(ColPAT.class); 53 static { 54 pattMap.put(ColPAT.PAT_UNKN, Patt.Z); 55 pattMap.put(ColPAT.PAT_HORI, Patt.H); 56 pattMap.put(ColPAT.PAT_VERT, Patt.V); 57 pattMap.put(ColPAT.PAT_DIAG, Patt.D); 58 pattMap.put(ColPAT.PAT_BRDR, Patt.B); 59 pattMap.put(ColPAT.PAT_SQUR, Patt.S); 60 pattMap.put(ColPAT.PAT_CROS, Patt.C); 61 pattMap.put(ColPAT.PAT_SALT, Patt.X); 62 pattMap.put(ColPAT.PAT_STRP, Patt.H); 63 } 64 65 static String getName() { 66 AttVal<?> name = feature.atts.get(Att.OBJNAM); 67 if (name == null) { 68 AttMap atts = feature.objs.get(feature.type).get(0); 69 if (atts != null) { 70 name = atts.get(Att.OBJNAM); 71 } 72 } 73 return (name != null) ? (String)name.val: null; 74 } 75 76 public static void addName(int z, Font font) { 77 addName(z, font, Color.black, new Delta(Handle.CC, new AffineTransform())); 78 } 79 public static void addName(int z, Font font, Color colour) { 80 addName(z, font, colour, new Delta(Handle.CC, new AffineTransform())); 81 } 82 public static void addName(int z, Font font, Delta delta) { 83 addName(z, font, Color.black, delta); 84 } 85 public static void addName(int z, Font font, Color colour, Delta delta) { 86 if (Renderer.zoom >= z) { 87 String name = getName(); 88 if (name != null) { 89 Renderer.labelText(name, font, colour, delta); 90 } 91 } 92 } 93 94 static AttMap getAtts(Obj obj, int idx) { 95 HashMap<Integer, AttMap> objs = feature.objs.get(obj); 96 if (objs == null) 97 return null; 98 else 99 return objs.get(idx); 100 } 101 102 public static Object getAttVal(Obj obj, Att att) { 103 AttMap atts; 104 HashMap<Integer, AttMap> objs; 105 AttVal<?> item; 106 if ((objs = feature.objs.get(obj)) != null) 107 atts = objs.get(0); 108 else 109 return null; 110 if ((item = atts.get(att)) == null) 111 return null; 112 else 113 return item.val; 114 } 115 116 public static String getAttStr(Obj obj, Att att) { 117 String str = (String)getAttVal(obj, att); 118 if (str != null) { 119 return str; 120 } 121 return ""; 122 } 123 124 @SuppressWarnings("unchecked") 125 public static Enum<?> getAttEnum(Obj obj, Att att) { 126 ArrayList<?> list = (ArrayList<?>)getAttVal(obj, att); 127 if (list != null) { 128 return ((ArrayList<Enum<?>>)list).get(0); 129 } 130 return S57val.unknAtt(att); 131 } 132 133 @SuppressWarnings("unchecked") 134 public static ArrayList<?> getAttList(Obj obj, Att att) { 135 ArrayList<Enum<?>> list = (ArrayList<Enum<?>>)getAttVal(obj, att); 136 if (list != null) { 137 return list; 138 } 139 list = new ArrayList<>(); 140 list.add(S57val.unknAtt(att)); 141 return list; 142 } 143 144 @SuppressWarnings("unchecked") 145 static Scheme getScheme(Obj obj) { 146 ArrayList<Color> colours = new ArrayList<>(); 147 for (ColCOL col : (ArrayList<ColCOL>) getAttList(obj, Att.COLOUR)) { 148 colours.add(bodyColours.get(col)); 149 } 150 ArrayList<Patt> patterns = new ArrayList<>(); 151 for (ColPAT pat : (ArrayList<ColPAT>) getAttList(obj, Att.COLPAT)) { 152 patterns.add(pattMap.get(pat)); 153 } 154 return new Scheme(patterns, colours); 155 } 156 157 static boolean hasAttribute(Obj obj, Att att) { 158 AttMap atts; 159 if ((atts = getAtts(obj, 0)) != null) { 160 AttVal<?> item = atts.get(att); 161 return item != null; 162 } 163 return false; 164 } 165 166 static boolean testAttribute(Obj obj, Att att, Object val) { 167 AttMap atts; 168 if ((atts = getAtts(obj, 0)) != null) { 169 AttVal<?> item = atts.get(att); 170 if (item != null) { 171 switch (item.conv) { 172 case S: 173 case A: 174 return ((String)item.val).equals(val); 175 case E: 176 case L: 177 return ((ArrayList<?>)item.val).contains(val); 178 case F: 179 case I: 180 return item.val == val; 181 } 182 } 183 } 184 return false; 185 } 186 187 static boolean hasObject(Obj obj) { 188 return (feature.objs.containsKey(obj)); 189 } 190 191 public static Feature feature; 192 static ArrayList<Feature> objects; 193 194 static boolean testObject(Obj obj) { 195 return ((objects = Renderer.map.features.get(obj)) != null); 196 } 197 198 static boolean testFeature(Feature f) { 199 return ((feature = f).reln == Rflag.MASTER); 200 } 201 202 public static void rules () { 203 if ((Renderer.context.ruleset() == RuleSet.ALL) || (Renderer.context.ruleset() == RuleSet.BASE)) { 204 if (testObject(Obj.LNDARE)) for (Feature f : objects) if (testFeature(f)) areas(); 205 if (testObject(Obj.BUAARE)) for (Feature f : objects) if (testFeature(f)) areas(); 206 if (testObject(Obj.HRBFAC)) for (Feature f : objects) if (testFeature(f)) areas(); 207 if (testObject(Obj.HRBBSN)) for (Feature f : objects) if (testFeature(f)) areas(); 208 if (testObject(Obj.LOKBSN)) for (Feature f : objects) if (testFeature(f)) areas(); 209 if (testObject(Obj.LKBSPT)) for (Feature f : objects) if (testFeature(f)) areas(); 210 if (testObject(Obj.LAKARE)) for (Feature f : objects) if (testFeature(f)) areas(); 211 if (testObject(Obj.RIVERS)) for (Feature f : objects) if (testFeature(f)) waterways(); 212 if (testObject(Obj.CANALS)) for (Feature f : objects) if (testFeature(f)) waterways(); 213 if (testObject(Obj.DEPARE)) for (Feature f : objects) if (testFeature(f)) areas(); 214 if (testObject(Obj.COALNE)) for (Feature f : objects) if (testFeature(f)) areas(); 215 if (testObject(Obj.ROADWY)) for (Feature f : objects) if (testFeature(f)) highways(); 216 if (testObject(Obj.RAILWY)) for (Feature f : objects) if (testFeature(f)) highways(); 217 } 218 if (Renderer.context.ruleset() == RuleSet.ALL) { 219 if (testObject(Obj.SOUNDG)) for (Feature f : objects) if (testFeature(f)) depths(); 220 if (testObject(Obj.DEPCNT)) for (Feature f : objects) if (testFeature(f)) depths(); 221 } 222 if (testObject(Obj.SLCONS)) for (Feature f : objects) if (testFeature(f)) shoreline(); 223 if ((Renderer.context.ruleset() == RuleSet.ALL) || (Renderer.context.ruleset() == RuleSet.SEAMARK)) { 224 if (testObject(Obj.PIPSOL)) for (Feature f : objects) if (testFeature(f)) pipelines(); 225 if (testObject(Obj.CBLSUB)) for (Feature f : objects) if (testFeature(f)) cables(); 226 if (testObject(Obj.PIPOHD)) for (Feature f : objects) if (testFeature(f)) pipelines(); 227 if (testObject(Obj.CBLOHD)) for (Feature f : objects) if (testFeature(f)) cables(); 228 if (testObject(Obj.TSEZNE)) for (Feature f : objects) if (testFeature(f)) separation(); 229 if (testObject(Obj.TSSCRS)) for (Feature f : objects) if (testFeature(f)) separation(); 230 if (testObject(Obj.TSSRON)) for (Feature f : objects) if (testFeature(f)) separation(); 231 if (testObject(Obj.TSELNE)) for (Feature f : objects) if (testFeature(f)) separation(); 232 if (testObject(Obj.TSSLPT)) for (Feature f : objects) if (testFeature(f)) separation(); 233 if (testObject(Obj.TSSBND)) for (Feature f : objects) if (testFeature(f)) separation(); 234 if (testObject(Obj.ISTZNE)) for (Feature f : objects) if (testFeature(f)) separation(); 235 if (testObject(Obj.SNDWAV)) for (Feature f : objects) if (testFeature(f)) areas(); 236 if (testObject(Obj.WEDKLP)) for (Feature f : objects) if (testFeature(f)) areas(); 237 if (testObject(Obj.OSPARE)) for (Feature f : objects) if (testFeature(f)) areas(); 238 if (testObject(Obj.FAIRWY)) for (Feature f : objects) if (testFeature(f)) areas(); 239 if (testObject(Obj.DRGARE)) for (Feature f : objects) if (testFeature(f)) areas(); 240 if (testObject(Obj.RESARE)) for (Feature f : objects) if (testFeature(f)) areas(); 241 if (testObject(Obj.PRCARE)) for (Feature f : objects) if (testFeature(f)) areas(); 242 if (testObject(Obj.SPLARE)) for (Feature f : objects) if (testFeature(f)) areas(); 243 if (testObject(Obj.SEAARE)) for (Feature f : objects) if (testFeature(f)) areas(); 244 if (testObject(Obj.OBSTRN)) for (Feature f : objects) if (testFeature(f)) obstructions(); 245 if (testObject(Obj.UWTROC)) for (Feature f : objects) if (testFeature(f)) obstructions(); 246 if (testObject(Obj.MARCUL)) for (Feature f : objects) if (testFeature(f)) areas(); 247 if (testObject(Obj.RECTRC)) for (Feature f : objects) if (testFeature(f)) transits(); 248 if (testObject(Obj.NAVLNE)) for (Feature f : objects) if (testFeature(f)) transits(); 249 if (testObject(Obj.HRBFAC)) for (Feature f : objects) if (testFeature(f)) harbours(); 250 if (testObject(Obj.ACHARE)) for (Feature f : objects) if (testFeature(f)) harbours(); 251 if (testObject(Obj.ACHBRT)) for (Feature f : objects) if (testFeature(f)) harbours(); 252 if (testObject(Obj.BERTHS)) for (Feature f : objects) if (testFeature(f)) harbours(); 253 if (testObject(Obj.DISMAR)) for (Feature f : objects) if (testFeature(f)) distances(); 254 if (testObject(Obj.HULKES)) for (Feature f : objects) if (testFeature(f)) ports(); 255 if (testObject(Obj.CRANES)) for (Feature f : objects) if (testFeature(f)) ports(); 256 if (testObject(Obj.LNDMRK)) for (Feature f : objects) if (testFeature(f)) landmarks(); 257 if (testObject(Obj.SILTNK)) for (Feature f : objects) if (testFeature(f)) landmarks(); 258 if (testObject(Obj.BUISGL)) for (Feature f : objects) if (testFeature(f)) harbours(); 259 if (testObject(Obj.MORFAC)) for (Feature f : objects) if (testFeature(f)) moorings(); 260 if (testObject(Obj.NOTMRK)) for (Feature f : objects) if (testFeature(f)) notices(); 261 if (testObject(Obj.SMCFAC)) for (Feature f : objects) if (testFeature(f)) marinas(); 262 if (testObject(Obj.BRIDGE)) for (Feature f : objects) if (testFeature(f)) bridges(); 263 if (testObject(Obj.PILPNT)) for (Feature f : objects) if (testFeature(f)) points(); 264 if (testObject(Obj.TOPMAR)) for (Feature f : objects) if (testFeature(f)) points(); 265 if (testObject(Obj.DAYMAR)) for (Feature f : objects) if (testFeature(f)) points(); 266 if (testObject(Obj.FOGSIG)) for (Feature f : objects) if (testFeature(f)) points(); 267 if (testObject(Obj.RDOCAL)) for (Feature f : objects) if (testFeature(f)) callpoint(); 268 if (testObject(Obj.LITMIN)) for (Feature f : objects) if (testFeature(f)) lights(); 269 if (testObject(Obj.LITMAJ)) for (Feature f : objects) if (testFeature(f)) lights(); 270 if (testObject(Obj.LIGHTS)) for (Feature f : objects) if (testFeature(f)) lights(); 271 if (testObject(Obj.SISTAT)) for (Feature f : objects) if (testFeature(f)) stations(); 272 if (testObject(Obj.SISTAW)) for (Feature f : objects) if (testFeature(f)) stations(); 273 if (testObject(Obj.CGUSTA)) for (Feature f : objects) if (testFeature(f)) stations(); 274 if (testObject(Obj.RDOSTA)) for (Feature f : objects) if (testFeature(f)) stations(); 275 if (testObject(Obj.RADRFL)) for (Feature f : objects) if (testFeature(f)) stations(); 276 if (testObject(Obj.RADSTA)) for (Feature f : objects) if (testFeature(f)) stations(); 277 if (testObject(Obj.RTPBCN)) for (Feature f : objects) if (testFeature(f)) stations(); 278 if (testObject(Obj.RSCSTA)) for (Feature f : objects) if (testFeature(f)) stations(); 279 if (testObject(Obj.PILBOP)) for (Feature f : objects) if (testFeature(f)) stations(); 280 if (testObject(Obj.WTWGAG)) for (Feature f : objects) if (testFeature(f)) gauges(); 281 if (testObject(Obj.OFSPLF)) for (Feature f : objects) if (testFeature(f)) platforms(); 282 if (testObject(Obj.WRECKS)) for (Feature f : objects) if (testFeature(f)) wrecks(); 283 if (testObject(Obj.LITVES)) for (Feature f : objects) if (testFeature(f)) floats(); 284 if (testObject(Obj.LITFLT)) for (Feature f : objects) if (testFeature(f)) floats(); 285 if (testObject(Obj.BOYINB)) for (Feature f : objects) if (testFeature(f)) floats(); 286 if (testObject(Obj.BOYLAT)) for (Feature f : objects) if (testFeature(f)) buoys(); 287 if (testObject(Obj.BOYCAR)) for (Feature f : objects) if (testFeature(f)) buoys(); 288 if (testObject(Obj.BOYISD)) for (Feature f : objects) if (testFeature(f)) buoys(); 289 if (testObject(Obj.BOYSAW)) for (Feature f : objects) if (testFeature(f)) buoys(); 290 if (testObject(Obj.BOYSPP)) for (Feature f : objects) if (testFeature(f)) buoys(); 291 if (testObject(Obj.BCNLAT)) for (Feature f : objects) if (testFeature(f)) beacons(); 292 if (testObject(Obj.BCNCAR)) for (Feature f : objects) if (testFeature(f)) beacons(); 293 if (testObject(Obj.BCNISD)) for (Feature f : objects) if (testFeature(f)) beacons(); 294 if (testObject(Obj.BCNSAW)) for (Feature f : objects) if (testFeature(f)) beacons(); 295 if (testObject(Obj.BCNSPP)) for (Feature f : objects) if (testFeature(f)) beacons(); 296 } 297 } 298 299 private static void areas() { 300 String name = getName(); 301 switch (feature.type) { 302 case BUAARE: 303 Renderer.lineVector(new LineStyle(new Color(0x20000000, true))); 304 break; 305 case COALNE: 306 if (Renderer.zoom >= 12) 307 Renderer.lineVector(new LineStyle(Color.black, 10)); 308 break; 309 case DEPARE: 310 Double depmax = 0.0; 311 if (((depmax = (Double) getAttVal(Obj.DEPARE, Att.DRVAL2)) != null) && (depmax <= 0.0)) { 312 Renderer.lineVector(new LineStyle(Symbols.Gdries)); 313 } 314 break; 315 case LAKARE: 316 if ((Renderer.zoom >= 12) || (feature.geom.area > 10.0)) 317 Renderer.lineVector(new LineStyle(Symbols.Bwater)); 318 break; 319 case DRGARE: 320 if (Renderer.zoom < 16) 321 Renderer.lineVector(new LineStyle(Color.black, 8, new float[] { 25, 25 }, new Color(0x40ffffff, true))); 322 else 323 Renderer.lineVector(new LineStyle(Color.black, 8, new float[] { 25, 25 })); 324 addName(12, new Font("Arial", Font.PLAIN, 100), new Delta(Handle.CC, new AffineTransform())); 325 break; 326 case FAIRWY: 327 if (feature.geom.area > 2.0) { 328 if (Renderer.zoom < 16) 329 Renderer.lineVector(new LineStyle(Symbols.Mline, 8, new float[] { 50, 50 }, new Color(0x40ffffff, true))); 330 else 331 Renderer.lineVector(new LineStyle(Symbols.Mline, 8, new float[] { 50, 50 })); 332 } else { 333 if (Renderer.zoom >= 14) 334 Renderer.lineVector(new LineStyle(new Color(0x40ffffff, true))); 335 } 336 break; 337 case LKBSPT: 338 case LOKBSN: 339 case HRBBSN: 340 if (Renderer.zoom >= 12) { 341 Renderer.lineVector(new LineStyle(Color.black, 10, Symbols.Bwater)); 342 } else { 343 Renderer.lineVector(new LineStyle(Symbols.Bwater)); 344 } 345 break; 346 case HRBFAC: 347 if (feature.objs.get(Obj.HRBBSN) != null) { 348 if (Renderer.zoom >= 12) { 349 Renderer.lineVector(new LineStyle(Color.black, 10, Symbols.Bwater)); 350 } else { 351 Renderer.lineVector(new LineStyle(Symbols.Bwater)); 352 } 353 } 354 break; 355 case LNDARE: 356 Renderer.lineVector(new LineStyle(Symbols.Yland)); 357 break; 358 case MARCUL: 359 if (Renderer.zoom >= 12) { 360 if (Renderer.zoom >= 14) { 361 Renderer.symbol(Areas.MarineFarm); 362 } 363 if ((feature.geom.area > 0.2) || ((feature.geom.area > 0.05) && (Renderer.zoom >= 14)) || ((feature.geom.area > 0.005) && (Renderer.zoom >= 16))) { 364 Renderer.lineVector(new LineStyle(Color.black, 4, new float[] { 10, 10 })); 365 } 366 } 367 break; 368 case OSPARE: 369 if (testAttribute(feature.type, Att.CATPRA, CatPRA.PRA_WFRM)) { 370 Renderer.symbol(Areas.WindFarm); 371 Renderer.lineVector(new LineStyle(Color.black, 20, new float[] { 40, 40 })); 372 addName(15, new Font("Arial", Font.BOLD, 80), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, 10))); 373 } 374 break; 375 case RESARE: 376 case MIPARE: 377 if (Renderer.zoom >= 12) { 378 Renderer.lineSymbols(Areas.Restricted, 1.0, null, null, 0, Symbols.Mline); 379 if (testAttribute(feature.type, Att.CATREA, CatREA.REA_NWAK)) { 380 Renderer.symbol(Areas.NoWake); 381 } 382 } 383 break; 384 case PRCARE: 385 if (Renderer.zoom >= 12) { 386 Renderer.lineVector(new LineStyle(Symbols.Mline, 10, new float[] { 40, 40 })); 387 } 388 break; 389 case SEAARE: 390 switch ((CatSEA) getAttEnum(feature.type, Att.CATSEA)) { 391 case SEA_RECH: 392 if ((Renderer.zoom >= 10) && (name != null)) 393 if (feature.geom.prim == Pflag.LINE) { 394 Renderer.lineText(name, new Font("Arial", Font.PLAIN, 150), Color.black, -40); 395 } else { 396 Renderer.labelText(name, new Font("Arial", Font.PLAIN, 150), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40))); 397 } 398 break; 399 case SEA_BAY: 400 if ((Renderer.zoom >= 12) && (name != null)) 401 if (feature.geom.prim == Pflag.LINE) { 402 Renderer.lineText(name, new Font("Arial", Font.PLAIN, 150), Color.black, -40); 403 } else { 404 Renderer.labelText(name, new Font("Arial", Font.PLAIN, 150), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40))); 405 } 406 break; 407 case SEA_SHOL: 408 if (Renderer.zoom >= 14) { 409 if (feature.geom.prim == Pflag.AREA) { 410 Renderer.lineVector(new LineStyle(new Color(0xc480ff), 4, new float[] { 25, 25 })); 411 if (name != null) { 412 Renderer.labelText(name, new Font("Arial", Font.ITALIC, 75), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40))); 413 Renderer.labelText("(Shoal)", new Font("Arial", Font.PLAIN, 60), Color.black, new Delta(Handle.BC)); 414 } 415 } else if (feature.geom.prim == Pflag.LINE) { 416 if (name != null) { 417 Renderer.lineText(name, new Font("Arial", Font.ITALIC, 75), Color.black, -40); 418 Renderer.lineText("(Shoal)", new Font("Arial", Font.PLAIN, 60), Color.black, 0); 419 } 420 } else { 421 if (name != null) { 422 Renderer.labelText(name, new Font("Arial", Font.ITALIC, 75), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40))); 423 Renderer.labelText("(Shoal)", new Font("Arial", Font.PLAIN, 60), Color.black, new Delta(Handle.BC)); 424 } 425 } 426 } 427 break; 428 case SEA_GAT: 429 case SEA_NRRW: 430 addName(12, new Font("Arial", Font.PLAIN, 100)); 431 break; 432 default: 433 break; 434 } 435 break; 436 case SNDWAV: 437 if (Renderer.zoom >= 12) Renderer.fillPattern(Areas.Sandwaves); 438 break; 439 case WEDKLP: 440 if (Renderer.zoom >= 12) { 441 switch ((CatWED) getAttEnum(feature.type, Att.CATWED)) { 442 case WED_KELP: 443 if (feature.geom.prim == Pflag.AREA) { 444 Renderer.fillPattern(Areas.KelpA); 445 } else { 446 Renderer.symbol(Areas.KelpS); 447 } 448 break; 449 default: 450 break; 451 } 452 } 453 break; 454 case SPLARE: 455 if (Renderer.zoom >= 12) { 456 Renderer.symbol(Areas.Plane, new Scheme(Symbols.Msymb)); 457 Renderer.lineSymbols(Areas.Restricted, 0.5, Areas.LinePlane, null, 10, Symbols.Mline); 458 } 459 addName(15, new Font("Arial", Font.BOLD, 80), new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -90))); 460 break; 461 default: 462 break; 463 } 464 } 465 466 @SuppressWarnings("unchecked") 467 private static void beacons() { 468 if ((Renderer.zoom >= 14) || ((Renderer.zoom >= 12) && ((feature.type == Obj.BCNLAT) || (feature.type == Obj.BCNCAR))) 469 || ((Renderer.zoom >= 11) && ((feature.type == Obj.BCNSAW) || hasObject(Obj.RTPBCN)))) { 470 BcnSHP shape = (BcnSHP)getAttEnum(feature.type, Att.BCNSHP); 471 if (shape == BcnSHP.BCN_UNKN) 472 shape = BcnSHP.BCN_PILE; 473 if ((shape == BcnSHP.BCN_WTHY) && (feature.type == Obj.BCNLAT)) { 474 switch ((CatLAM) getAttEnum(feature.type, Att.CATLAM)) { 475 case LAM_PORT: 476 Renderer.symbol(Beacons.WithyPort); 477 break; 478 case LAM_STBD: 479 Renderer.symbol(Beacons.WithyStarboard); 480 break; 481 default: 482 Renderer.symbol(Beacons.Stake, getScheme(feature.type)); 483 } 484 } else if ((shape == BcnSHP.BCN_PRCH) && (feature.type == Obj.BCNLAT) && !(feature.objs.containsKey(Obj.TOPMAR))) { 485 switch ((CatLAM) getAttEnum(feature.type, Att.CATLAM)) { 486 case LAM_PORT: 487 Renderer.symbol(Beacons.PerchPort); 488 break; 489 case LAM_STBD: 490 Renderer.symbol(Beacons.PerchStarboard); 491 break; 492 default: 493 Renderer.symbol(Beacons.Stake, getScheme(feature.type)); 494 } 495 } else { 496 Renderer.symbol(Beacons.Shapes.get(shape), getScheme(feature.type)); 497 if (feature.objs.containsKey(Obj.TOPMAR)) { 498 AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0); 499 if (topmap.containsKey(Att.TOPSHP)) { 500 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>)(topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.TOPMAR), Topmarks.BeaconDelta); 501 } 502 } else if (feature.objs.containsKey(Obj.DAYMAR)) { 503 AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0); 504 if (topmap.containsKey(Att.TOPSHP)) { 505 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>)(topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.DAYMAR), Topmarks.BeaconDelta); 506 } 507 } 508 } 509 if (hasObject(Obj.NOTMRK)) 510 notices(); 511 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(60, -50))); 512 Signals.addSignals(); 513 } 514 } 515 516 @SuppressWarnings("unchecked") 517 private static void buoys() { 518 if ((Renderer.zoom >= 14) || ((Renderer.zoom >= 12) && ((feature.type == Obj.BOYLAT) || (feature.type == Obj.BOYCAR))) 519 || ((Renderer.zoom >= 11) && ((feature.type == Obj.BOYSAW) || hasObject(Obj.RTPBCN)))) { 520 BoySHP shape = (BoySHP) getAttEnum(feature.type, Att.BOYSHP); 521 if (shape == BoySHP.BOY_UNKN) shape = BoySHP.BOY_PILR; 522 Renderer.symbol(Buoys.Shapes.get(shape), getScheme(feature.type)); 523 if (feature.objs.containsKey(Obj.TOPMAR)) { 524 AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0); 525 if (topmap.containsKey(Att.TOPSHP)) { 526 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>)(topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.TOPMAR), Topmarks.BuoyDeltas.get(shape)); 527 } 528 } else if (feature.objs.containsKey(Obj.DAYMAR)) { 529 AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0); 530 if (topmap.containsKey(Att.TOPSHP)) { 531 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>)(topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.DAYMAR), Topmarks.BuoyDeltas.get(shape)); 532 } 533 } 534 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(60, -50))); 535 Signals.addSignals(); 536 } 537 } 538 539 private static void bridges() { 540 if (Renderer.zoom >= 16) { 541 double verclr, verccl, vercop, horclr; 542 AttMap atts = feature.objs.get(Obj.BRIDGE).get(0); 543 String vstr = ""; 544 String hstr = ""; 545 if (atts != null) { 546 if (atts.containsKey(Att.HORCLR)) { 547 horclr = (Double) atts.get(Att.HORCLR).val; 548 hstr = String.valueOf(horclr); 549 } 550 if (atts.containsKey(Att.VERCLR)) { 551 verclr = (Double) atts.get(Att.VERCLR).val; 552 } else { 553 verclr = atts.containsKey(Att.VERCSA) ? (Double) atts.get(Att.VERCSA).val : 0; 554 } 555 verccl = atts.containsKey(Att.VERCCL) ? (Double) atts.get(Att.VERCCL).val : 0; 556 vercop = atts.containsKey(Att.VERCOP) ? (Double) atts.get(Att.VERCOP).val : 0; 557 if (verclr > 0) { 558 vstr += String.valueOf(verclr); 559 } else if (verccl > 0) { 560 if (vercop == 0) { 561 vstr += String.valueOf(verccl) + "/-"; 562 } else { 563 vstr += String.valueOf(verccl) + "/" + String.valueOf(vercop); 564 } 565 } 566 if (hstr.isEmpty() && !vstr.isEmpty()) { 567 Renderer.labelText(vstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.VCLR, Color.black, Color.white, new Delta(Handle.CC)); 568 } else if (!hstr.isEmpty() && !vstr.isEmpty()) { 569 Renderer.labelText(vstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.VCLR, Color.black, Color.white, new Delta(Handle.BC)); 570 Renderer.labelText(hstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.HCLR, Color.black, Color.white, new Delta(Handle.TC)); 571 } else if (!hstr.isEmpty() && vstr.isEmpty()) { 572 Renderer.labelText(hstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.HCLR, Color.black, Color.white, new Delta(Handle.CC)); 573 } 574 } 575 } 576 } 577 578 private static void cables() { 579 if ((Renderer.zoom >= 16) && (feature.geom.length < 2)) { 580 if (feature.type == Obj.CBLSUB) { 581 Renderer.lineSymbols(Areas.Cable, 0.0, null, null, 0, Symbols.Mline); 582 } else if (feature.type == Obj.CBLOHD) { 583 AttMap atts = feature.objs.get(Obj.CBLOHD).get(0); 584 if ((atts != null) && (atts.containsKey(Att.CATCBL)) && (atts.get(Att.CATCBL).val == CatCBL.CBL_POWR)) { 585 Renderer.lineSymbols(Areas.CableDash, 0, Areas.CableDot, Areas.CableFlash, 2, Color.black); 586 } else { 587 Renderer.lineSymbols(Areas.CableDash, 0, Areas.CableDot, null, 2, Color.black); 588 } 589 if (atts != null) { 590 if (atts.containsKey(Att.VERCLR)) { 591 Renderer.labelText(String.valueOf((Double) atts.get(Att.VERCLR).val), new Font("Arial", Font.PLAIN, 50), Color.black, LabelStyle.VCLR, Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0,25))); 592 } else if (atts.containsKey(Att.VERCSA)) { 593 Renderer.labelText(String.valueOf((Double) atts.get(Att.VERCSA).val), new Font("Arial", Font.PLAIN, 50), Color.black, LabelStyle.PCLR, Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0,25))); 594 } 595 } 596 } 597 } 598 } 599 600 private static void callpoint() { 601 if (Renderer.zoom >= 14) { 602 Symbol symb = Harbours.CallPoint2; 603 TrfTRF trf = (TrfTRF) getAttEnum(feature.type, Att.TRAFIC); 604 if (trf != TrfTRF.TRF_TWOW) { 605 symb = Harbours.CallPoint1; 606 } 607 Double orient = 0.0; 608 if ((orient = (Double) getAttVal(feature.type, Att.ORIENT)) == null) { 609 orient = 0.0; 610 } 611 Renderer.symbol(symb, new Delta(Handle.CC, AffineTransform.getRotateInstance(Math.toRadians(orient)))); 612 String chn; 613 if (!(chn = getAttStr(feature.type, Att.COMCHA)).isEmpty()) { 614 Renderer.labelText(("Ch." + chn), new Font("Arial", Font.PLAIN, 50), Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0,50))); 615 } 616 } 617 } 618 619 private static void depths() { 620 switch (feature.type) { 621 case SOUNDG: 622 if ((Renderer.zoom >= 14) && hasAttribute(Obj.SOUNDG, Att.VALSOU)) { 623 double depth = (double)getAttVal(Obj.SOUNDG, Att.VALSOU); 624 String dstr = df.format(depth); 625 String tok[] = dstr.split("[-.]"); 626 String ul = ""; 627 String id = tok[0]; 628 String dd = ""; 629 if (tok[0].equals("")) { 630 for (int i = 0; i < tok[1].length(); i++) 631 ul += "_"; 632 id = tok[1]; 633 dd = (tok.length == 3) ? tok[2] : ""; 634 } else { 635 dd = (tok.length == 2) ? tok[1] : ""; 636 } 637 Renderer.labelText(ul, new Font("Arial", Font.PLAIN, 30), Color.black, new Delta(Handle.RC, AffineTransform.getTranslateInstance(10,15))); 638 Renderer.labelText(id, new Font("Arial", Font.PLAIN, 30), Color.black, new Delta(Handle.RC, AffineTransform.getTranslateInstance(10,0))); 639 Renderer.labelText(dd, new Font("Arial", Font.PLAIN, 20), Color.black, new Delta(Handle.LC, AffineTransform.getTranslateInstance(15,10))); 640 } 641 break; 642 case DEPCNT: 643 break; 644 default: 645 break; 646 } 647 } 648 649 private static void distances() { 650 if (Renderer.zoom >= 14) { 651 if (!testAttribute(Obj.DISMAR, Att.CATDIS, CatDIS.DIS_NONI)) { 652 Renderer.symbol(Harbours.DistanceI); 653 } else { 654 Renderer.symbol(Harbours.DistanceU); 655 } 656 if (Renderer.zoom >= 15) { 657 AttMap atts = getAtts(Obj.DISMAR, 0); 658 if ((atts != null) && (atts.containsKey(Att.WTWDIS))) { 659 Double dist = (Double) atts.get(Att.WTWDIS).val; 660 String str = ""; 661 if (atts.containsKey(Att.HUNITS)) { 662 switch ((UniHLU) getAttEnum(Obj.DISMAR, Att.HUNITS)) { 663 case HLU_METR: 664 str += "m "; 665 break; 666 case HLU_FEET: 667 str += "ft "; 668 break; 669 case HLU_HMTR: 670 str += "hm "; 671 break; 672 case HLU_KMTR: 673 str += "km "; 674 break; 675 case HLU_SMIL: 676 str += "M "; 677 break; 678 case HLU_NMIL: 679 str += "NM "; 680 break; 681 default: 682 break; 683 } 684 } 685 str += String.format("%1.0f", dist); 686 Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.CC, AffineTransform.getTranslateInstance(0, 45))); 687 } 688 } 689 } 690 } 691 692 @SuppressWarnings("unchecked") 693 private static void floats() { 694 if ((Renderer.zoom >= 12) || ((Renderer.zoom >= 11) && ((feature.type == Obj.LITVES) || (feature.type == Obj.BOYINB) || hasObject(Obj.RTPBCN)))) { 695 switch (feature.type) { 696 case LITVES: 697 Renderer.symbol(Buoys.Super, getScheme(feature.type)); 698 break; 699 case LITFLT: 700 Renderer.symbol(Buoys.Float, getScheme(feature.type)); 701 break; 702 case BOYINB: 703 Renderer.symbol(Buoys.Super, getScheme(feature.type)); 704 break; 705 default: 706 break; 707 } 708 if (feature.objs.containsKey(Obj.TOPMAR)) { 709 AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0); 710 if (topmap.containsKey(Att.TOPSHP)) { 711 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>)(topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.TOPMAR), Topmarks.FloatDelta); 712 } 713 } else if (feature.objs.containsKey(Obj.DAYMAR)) { 714 AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0); 715 if (topmap.containsKey(Att.TOPSHP)) { 716 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>)(topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.DAYMAR), Topmarks.FloatDelta); 717 } 718 } 719 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(20, -50))); 720 Signals.addSignals(); 721 } 722 } 723 724 private static void gauges() { 725 if (Renderer.zoom >= 14) { 726 Renderer.symbol(Harbours.TideGauge); 727 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(20, -50))); 728 Signals.addSignals(); 729 } 730 } 731 732 @SuppressWarnings("unchecked") 733 private static void harbours() { 734 String name = getName(); 735 switch (feature.type) { 736 case ACHBRT: 737 if (Renderer.zoom >= 14) { 738 Renderer.symbol(Harbours.Anchor, new Scheme(Symbols.Msymb)); 739 if (Renderer.zoom >= 15) { 740 Renderer.labelText(name == null ? "" : name, new Font("Arial", Font.PLAIN, 30), Symbols.Msymb, LabelStyle.RRCT, Symbols.Msymb, Color.white, new Delta(Handle.BC)); 741 } 742 } 743 if (getAttVal(Obj.ACHBRT, Att.RADIUS) != null) { 744 double radius; 745 if ((radius = (Double) getAttVal(Obj.ACHBRT, Att.RADIUS)) != 0) { 746 UniHLU units = (UniHLU) getAttEnum(Obj.ACHBRT, Att.HUNITS); 747 if (units == UniHLU.HLU_UNKN) { 748 units = UniHLU.HLU_METR; 749 } 750 Renderer.lineCircle(new LineStyle(Symbols.Mline, 4, new float[] { 10, 10 }, null), radius, units); 751 } 752 } 753 break; 754 case ACHARE: 755 if (Renderer.zoom >= 12) { 756 if (feature.geom.prim != Pflag.AREA) { 757 Renderer.symbol(Harbours.Anchorage, new Scheme(Color.black)); 758 } else { 759 Renderer.symbol(Harbours.Anchorage, new Scheme(Symbols.Mline)); 760 Renderer.lineSymbols(Areas.Restricted, 1.0, Areas.LineAnchor, null, 10, Symbols.Mline); 761 } 762 addName(15, new Font("Arial", Font.BOLD, 60), Symbols.Mline, new Delta(Handle.LC, AffineTransform.getTranslateInstance(70, 0))); 763 ArrayList<StsSTS> sts = (ArrayList<StsSTS>) getAttList(Obj.ACHARE, Att.STATUS); 764 if ((Renderer.zoom >= 15) && (sts.contains(StsSTS.STS_RESV))) { 765 Renderer.labelText("Reserved", new Font("Arial", Font.PLAIN, 50), Symbols.Mline, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, 60))); 766 } 767 ArrayList<CatACH> cats = (ArrayList<CatACH>) getAttList(Obj.ACHARE, Att.CATACH); 768 int dy = (cats.size() - 1) * -30; 769 for (CatACH cat : cats) { 770 switch (cat) { 771 case ACH_DEEP: 772 Renderer.labelText("DW", new Font("Arial", Font.BOLD, 50), Symbols.Msymb, new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 773 dy += 60; 774 break; 775 case ACH_TANK: 776 Renderer.labelText("Tanker", new Font("Arial", Font.BOLD, 50), Symbols.Msymb, new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 777 dy += 60; 778 break; 779 case ACH_H24P: 780 Renderer.labelText("24h", new Font("Arial", Font.BOLD, 50), Symbols.Msymb, new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 781 dy += 60; 782 break; 783 case ACH_EXPL: 784 Renderer.symbol(Harbours.Explosives, new Scheme(Symbols.Msymb), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 785 dy += 60; 786 break; 787 case ACH_QUAR: 788 Renderer.symbol(Harbours.Hospital, new Scheme(Symbols.Msymb), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 789 dy += 60; 790 break; 791 case ACH_SEAP: 792 Renderer.symbol(Areas.Seaplane, new Scheme(Symbols.Msymb), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 793 dy += 60; 794 break; 795 default: 796 } 797 } 798 } 799 break; 800 case BERTHS: 801 if (Renderer.zoom >= 14) { 802 Renderer.lineVector(new LineStyle(Symbols.Mline, 6, new float[] { 20, 20 })); 803 Renderer.labelText(name == null ? " " : name, new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, LabelStyle.RRCT, Symbols.Mline, Color.white); 804 } 805 break; 806 case BUISGL: 807 if (Renderer.zoom >= 16) { 808 ArrayList<Symbol> symbols = new ArrayList<>(); 809 ArrayList<FncFNC> fncs = (ArrayList<FncFNC>) getAttList(Obj.BUISGL, Att.FUNCTN); 810 for (FncFNC fnc : fncs) { 811 symbols.add(Landmarks.Funcs.get(fnc)); 812 } 813 if (feature.objs.containsKey(Obj.SMCFAC)) { 814 ArrayList<CatSCF> scfs = (ArrayList<CatSCF>) getAttList(Obj.SMCFAC, Att.CATSCF); 815 for (CatSCF scf : scfs) { 816 symbols.add(Facilities.Cats.get(scf)); 817 } 818 } 819 Renderer.cluster(symbols); 820 } 821 break; 822 case HRBFAC: 823 if (Renderer.zoom >= 12) { 824 ArrayList<CatHAF> cathaf = (ArrayList<CatHAF>) getAttList(Obj.HRBFAC, Att.CATHAF); 825 if (cathaf.size() == 1) { 826 switch (cathaf.get(0)) { 827 case HAF_MRNA: 828 Renderer.symbol(Harbours.Marina); 829 break; 830 case HAF_MANF: 831 Renderer.symbol(Harbours.MarinaNF); 832 break; 833 case HAF_FISH: 834 Renderer.symbol(Harbours.Fishing); 835 break; 836 default: 837 Renderer.symbol(Harbours.Harbour); 838 break; 839 } 840 } else { 841 Renderer.symbol(Harbours.Harbour); 842 } 843 } 844 break; 845 default: 846 break; 847 } 848 } 849 850 @SuppressWarnings("unchecked") 851 private static void highways() { 852 switch (feature.type) { 853 case ROADWY: 854 ArrayList<CatROD> cat = (ArrayList<CatROD>) (getAttList(Obj.ROADWY, Att.CATROD)); 855 if (cat.size() > 0) { 856 switch (cat.get(0)) { 857 case ROD_MWAY: 858 Renderer.lineVector(new LineStyle(Color.black, 20)); 859 break; 860 case ROD_MAJR: 861 Renderer.lineVector(new LineStyle(Color.black, 15)); 862 break; 863 case ROD_MINR: 864 Renderer.lineVector(new LineStyle(Color.black, 10)); 865 break; 866 default: 867 Renderer.lineVector(new LineStyle(Color.black, 5)); 868 } 869 } else { 870 Renderer.lineVector(new LineStyle(Color.black, 5)); 871 } 872 break; 873 case RAILWY: 874 Renderer.lineVector(new LineStyle(Color.gray, 10)); 875 Renderer.lineVector(new LineStyle(Color.black, 10, new float[] { 30, 30 })); 876 break; 877 default: 878 } 879 } 880 881 @SuppressWarnings("unchecked") 882 private static void landmarks() { 883 if (!hasAttribute(Obj.LNDMRK, Att.CATLMK) 884 && (!hasAttribute(Obj.LNDMRK, Att.FUNCTN) || testAttribute(Obj.LNDMRK, Att.FUNCTN, FncFNC.FNC_LGHT)) 885 && hasObject(Obj.LIGHTS)) 886 lights(); 887 else if (Renderer.zoom >= 12) { 888 switch (feature.type) { 889 case LNDMRK: 890 ArrayList<CatLMK> cats = (ArrayList<CatLMK>) getAttList(feature.type, Att.CATLMK); 891 Symbol catSym = Landmarks.Shapes.get(cats.get(0)); 892 ArrayList<FncFNC> fncs = (ArrayList<FncFNC>) getAttList(feature.type, Att.FUNCTN); 893 Symbol fncSym = Landmarks.Funcs.get(fncs.get(0)); 894 if ((fncs.get(0) == FncFNC.FNC_CHCH) && (cats.get(0) == CatLMK.LMK_TOWR)) 895 catSym = Landmarks.ChurchTower; 896 if (cats.get(0) == CatLMK.LMK_RADR) 897 fncSym = Landmarks.RadioTV; 898 Renderer.symbol(catSym); 899 Renderer.symbol(fncSym); 900 break; 901 case SILTNK: 902 if (testAttribute(feature.type, Att.CATSIL, CatSIL.SIL_WTRT)) 903 Renderer.symbol(Landmarks.WaterTower); 904 break; 905 default: 906 break; 907 } 908 if (Renderer.zoom >= 15) 909 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(60, -50))); 910 Signals.addSignals(); 911 } 912 } 913 914 @SuppressWarnings("unchecked") 915 private static void points() { 916 boolean ok = false; 917 switch (feature.type) { 918 case FOGSIG: 919 if (Renderer.zoom >= 12) { 920 if (feature.objs.containsKey(Obj.LIGHTS)) 921 lights(); 922 else 923 Renderer.symbol(Harbours.Post); 924 ok = true; 925 } 926 break; 927 default: 928 if (Renderer.zoom >= 14) { 929 if (feature.objs.containsKey(Obj.LIGHTS)) 930 lights(); 931 else 932 Renderer.symbol(Harbours.Post); 933 ok = true; 934 } 935 break; 936 } 937 if (ok) { 938 if (feature.objs.containsKey(Obj.TOPMAR)) { 939 AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0); 940 if (topmap.containsKey(Att.TOPSHP)) { 941 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.TOPMAR), null); 942 } 943 } else if (feature.objs.containsKey(Obj.DAYMAR)) { 944 AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0); 945 if (topmap.containsKey(Att.TOPSHP)) { 946 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.DAYMAR), null); 947 } 948 } 949 Signals.addSignals(); 950 } 951 } 952 953 @SuppressWarnings("unchecked") 954 private static void lights() { 955 boolean ok = false; 956 switch (feature.type) { 957 case LITMAJ: 958 case LNDMRK: 959 if (Renderer.zoom >= 12) { 960 Renderer.symbol(Beacons.LightMajor); 961 ok = true; 962 } 963 break; 964 case LITMIN: 965 case LIGHTS: 966 case PILPNT: 967 if (Renderer.zoom >= 14) { 968 Renderer.symbol(Beacons.LightMinor); 969 ok = true; 970 } 971 break; 972 default: 973 break; 974 } 975 if (ok) { 976 if (feature.objs.containsKey(Obj.TOPMAR)) { 977 AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0); 978 if (topmap.containsKey(Att.TOPSHP)) { 979 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.TOPMAR), Topmarks.LightDelta); 980 } 981 } else if (feature.objs.containsKey(Obj.DAYMAR)) { 982 AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0); 983 if (topmap.containsKey(Att.TOPSHP)) { 984 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.DAYMAR), Topmarks.LightDelta); 985 } 986 } 987 Signals.addSignals(); 988 } 989 } 990 991 @SuppressWarnings("unchecked") 992 private static void marinas() { 993 if (Renderer.zoom >= 16) { 994 ArrayList<Symbol> symbols = new ArrayList<>(); 995 ArrayList<CatSCF> scfs = (ArrayList<CatSCF>) getAttList(Obj.SMCFAC, Att.CATSCF); 996 for (CatSCF scf : scfs) { 997 symbols.add(Facilities.Cats.get(scf)); 998 } 999 Renderer.cluster(symbols); 1000 } 1001 } 1002 1003 private static void moorings() { 1004 if (Renderer.zoom >= 14) { 1005 switch ((CatMOR) getAttEnum(feature.type, Att.CATMOR)) { 1006 case MOR_DLPN: 1007 Renderer.symbol(Harbours.Dolphin); 1008 break; 1009 case MOR_DDPN: 1010 Renderer.symbol(Harbours.DeviationDolphin); 1011 break; 1012 case MOR_BLRD: 1013 case MOR_POST: 1014 Renderer.symbol(Harbours.Bollard); 1015 break; 1016 case MOR_BUOY: 1017 BoySHP shape = (BoySHP) getAttEnum(feature.type, Att.BOYSHP); 1018 if (shape == BoySHP.BOY_UNKN) { 1019 shape = BoySHP.BOY_SPHR; 1020 } 1021 Renderer.symbol(Buoys.Shapes.get(shape), getScheme(feature.type)); 1022 Renderer.symbol(Topmarks.TopMooring, Topmarks.BuoyDeltas.get(shape)); 1023 break; 1024 default: 1025 break; 1026 } 1027 Signals.addSignals(); 1028 } 1029 } 1030 1031 @SuppressWarnings("unchecked") 1032 private static void notices() { 1033 if (Renderer.zoom >= 14) { 1034 double dx = 0.0, dy = 0.0; 1035 switch (feature.type) { 1036 case BCNCAR: 1037 case BCNISD: 1038 case BCNLAT: 1039 case BCNSAW: 1040 case BCNSPP: 1041 if (testAttribute(Obj.TOPMAR, Att.TOPSHP, TopSHP.TOP_BORD) || testAttribute(Obj.DAYMAR, Att.TOPSHP, TopSHP.TOP_BORD)) { 1042 dy = -100.0; 1043 } else { 1044 dy = -45.0; 1045 } 1046 break; 1047 case NOTMRK: 1048 dy = 0.0; 1049 break; 1050 default: 1051 return; 1052 } 1053 MarSYS sys = MarSYS.SYS_CEVN; 1054 BnkWTW bnk = BnkWTW.BWW_UNKN; 1055 AttVal<?> att = feature.atts.get(Att.MARSYS); 1056 if (att != null) sys = (MarSYS)att.val; 1057 att = feature.atts.get(Att.BNKWTW); 1058 if (att != null) bnk = (BnkWTW)att.val; 1059 ObjTab objs = feature.objs.get(Obj.NOTMRK); 1060 int n = objs.size(); 1061 if (n > 5) { 1062 Renderer.symbol(Notices.Notice, new Delta(Handle.CC, AffineTransform.getTranslateInstance(dx, dy))); 1063 } else { 1064 int i = 0; 1065 for (AttMap atts : objs.values()) { 1066 if (atts.get(Att.MARSYS) != null) sys = ((ArrayList<MarSYS>)(atts.get(Att.MARSYS).val)).get(0); 1067 if (atts.get(Att.BNKWTW) != null) bnk = ((ArrayList<BnkWTW>)(atts.get(Att.BNKWTW).val)).get(0); 1068 CatNMK cat = CatNMK.NMK_UNKN; 1069 if (atts.get(Att.CATNMK) != null) cat = ((ArrayList<CatNMK>)(atts.get(Att.CATNMK).val)).get(0); 1070 Symbol sym = Notices.getNotice(cat, sys, bnk); 1071 Scheme sch = Notices.getScheme(sys, bnk); 1072 ArrayList<AddMRK> add = new ArrayList<>(); 1073 if (atts.get(Att.ADDMRK) != null) add = (ArrayList<AddMRK>)(atts.get(Att.ADDMRK).val); 1074 Handle h = Handle.CC; 1075 double ax = 0.0; 1076 double ay = 0.0; 1077 switch (i) { 1078 case 0: 1079 if (n != 1) h = null; 1080 break; 1081 case 1: 1082 if (n <= 3) { 1083 h = Handle.RC; 1084 ax = -30; 1085 ay = dy; 1086 } 1087 else { 1088 h = Handle.BR; 1089 } 1090 break; 1091 case 2: 1092 if (n <= 3) 1093 h = Handle.LC; 1094 else 1095 h = Handle.BL; 1096 break; 1097 case 3: 1098 if (n == 4) 1099 h = Handle.TC; 1100 else 1101 h = Handle.TR; 1102 break; 1103 case 4: 1104 h = Handle.TL; 1105 break; 1106 } 1107 if (h != null) { 1108 Renderer.symbol(sym, sch, new Delta(h, AffineTransform.getTranslateInstance(dx, dy))); 1109 if (!add.isEmpty()) Renderer.symbol(Notices.NoticeBoard, new Delta(Handle.BC, AffineTransform.getTranslateInstance(ax, ay - 30))); 1110 } 1111 i++; 1112 } 1113 } 1114 } 1115 } 1116 1117 private static void obstructions() { 1118 if ((Renderer.zoom >= 12) && (feature.type == Obj.OBSTRN)) { 1119 switch ((CatOBS) getAttEnum(feature.type, Att.CATOBS)) { 1120 case OBS_BOOM: 1121 Renderer.lineVector(new LineStyle(Color.black, 5, new float[] { 20, 20 }, null)); 1122 if (Renderer.zoom >= 15) { 1123 Renderer.lineText("Boom", new Font("Arial", Font.PLAIN, 80), Color.black, -20); 1124 } 1125 default: 1126 break; 1127 } 1128 } 1129 if ((Renderer.zoom >= 14) && (feature.type == Obj.UWTROC)) { 1130 switch ((WatLEV) getAttEnum(feature.type, Att.WATLEV)) { 1131 case LEV_CVRS: 1132 Renderer.symbol(Areas.RockC); 1133 break; 1134 case LEV_AWSH: 1135 Renderer.symbol(Areas.RockA); 1136 break; 1137 default: 1138 Renderer.symbol(Areas.Rock); 1139 } 1140 } else { 1141 Renderer.symbol(Areas.Rock); 1142 } 1143 } 1144 1145 private static void pipelines() { 1146 if ((Renderer.zoom >= 16) && (feature.geom.length < 2)) { 1147 if (feature.type == Obj.PIPSOL) { 1148 Renderer.lineSymbols(Areas.Pipeline, 1.0, null, null, 0, Symbols.Mline); 1149 } else if (feature.type == Obj.PIPOHD) { 1150 Renderer.lineVector(new LineStyle(Color.black, 8)); 1151 AttMap atts = feature.atts; 1152 double verclr = 0; 1153 if (atts != null) { 1154 if (atts.containsKey(Att.VERCLR)) { 1155 verclr = (Double) atts.get(Att.VERCLR).val; 1156 } else { 1157 verclr = atts.containsKey(Att.VERCSA) ? (Double) atts.get(Att.VERCSA).val : 0; 1158 } 1159 if (verclr > 0) { 1160 Renderer.labelText(String.valueOf(verclr), new Font("Arial", Font.PLAIN, 50), Color.black, LabelStyle.VCLR, Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0,25))); 1161 } 1162 } 1163 } 1164 } 1165 } 1166 1167 @SuppressWarnings("unchecked") 1168 private static void platforms() { 1169 ArrayList<CatOFP> cats = (ArrayList<CatOFP>) getAttList(Obj.OFSPLF, Att.CATOFP); 1170 if ((CatOFP) cats.get(0) == CatOFP.OFP_FPSO) 1171 Renderer.symbol(Buoys.Storage); 1172 else 1173 Renderer.symbol(Landmarks.Platform); 1174 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(20, -50))); 1175 Signals.addSignals(); 1176 } 1177 1178 private static void ports() { 1179 if (Renderer.zoom >= 14) { 1180 if (feature.type == Obj.CRANES) { 1181 if ((CatCRN) getAttEnum(feature.type, Att.CATCRN) == CatCRN.CRN_CONT) 1182 Renderer.symbol(Harbours.ContainerCrane); 1183 else 1184 Renderer.symbol(Harbours.PortCrane); 1185 } else if (feature.type == Obj.HULKES) { 1186 Renderer.lineVector(new LineStyle(Color.black, 4, null, new Color(0xffe000))); 1187 addName(15, new Font("Arial", Font.BOLD, 40)); 1188 } 1189 } 1190 } 1191 1192 private static void separation() { 1193 switch (feature.type) { 1194 case TSEZNE: 1195 case TSSCRS: 1196 case TSSRON: 1197 if (Renderer.zoom <= 15) 1198 Renderer.lineVector(new LineStyle(Symbols.Mtss)); 1199 else 1200 Renderer.lineVector(new LineStyle(Symbols.Mtss, 20, null, null)); 1201 addName(10, new Font("Arial", Font.BOLD, 150), Symbols.Mline); 1202 break; 1203 case TSELNE: 1204 Renderer.lineVector(new LineStyle(Symbols.Mtss, 20, null, null)); 1205 break; 1206 case TSSLPT: 1207 Renderer.lineSymbols(Areas.LaneArrow, 0.5, null, null, 0, Symbols.Mtss); 1208 break; 1209 case TSSBND: 1210 Renderer.lineVector(new LineStyle(Symbols.Mtss, 20, new float[] { 40, 40 }, null)); 1211 break; 1212 case ISTZNE: 1213 Renderer.lineSymbols(Areas.Restricted, 1.0, null, null, 0, Symbols.Mtss); 1214 break; 1215 default: 1216 break; 1217 } 1218 } 1219 1220 @SuppressWarnings("unchecked") 1221 private static void shoreline() { 1222 CatSLC cat = (CatSLC) getAttEnum(feature.type, Att.CATSLC); 1223 if ((Renderer.context.ruleset() == RuleSet.ALL) || (Renderer.context.ruleset() == RuleSet.BASE)) { 1224 if ((cat != CatSLC.SLC_SWAY) && (cat != CatSLC.SLC_TWAL)) { 1225 if (Renderer.zoom >= 12) { 1226 Renderer.lineVector(new LineStyle(Color.black, 10, Symbols.Yland)); 1227 } else { 1228 Renderer.lineVector(new LineStyle(Symbols.Yland)); 1229 } 1230 } 1231 } 1232 if ((Renderer.context.ruleset() == RuleSet.ALL) || (Renderer.context.ruleset() == RuleSet.SEAMARK)) { 1233 if (Renderer.zoom >= 12) { 1234 switch (cat) { 1235 case SLC_TWAL: 1236 WatLEV lev = (WatLEV) getAttEnum(feature.type, Att.WATLEV); 1237 if (lev == WatLEV.LEV_CVRS) { 1238 Renderer.lineVector(new LineStyle(Color.black, 10, new float[] { 40, 40 }, null)); 1239 if (Renderer.zoom >= 15) 1240 Renderer.lineText("(covers)", new Font("Arial", Font.PLAIN, 60), Color.black, 80); 1241 } else { 1242 Renderer.lineVector(new LineStyle(Color.black, 10, null, null)); 1243 } 1244 if (Renderer.zoom >= 15) 1245 Renderer.lineText("Training Wall", new Font("Arial", Font.PLAIN, 60), Color.black, -30); 1246 break; 1247 case SLC_SWAY: 1248 Renderer.lineVector(new LineStyle(Color.black, 2, null, new Color(0xffe000))); 1249 if ((Renderer.zoom >= 16) && feature.objs.containsKey(Obj.SMCFAC)) { 1250 ArrayList<Symbol> symbols = new ArrayList<>(); 1251 ArrayList<CatSCF> scfs = (ArrayList<CatSCF>) getAttList(Obj.SMCFAC, Att.CATSCF); 1252 for (CatSCF scf : scfs) { 1253 symbols.add(Facilities.Cats.get(scf)); 1254 } 1255 Renderer.cluster(symbols); 1256 } 1257 break; 1258 default: 1259 break; 1260 } 1261 } 1262 } 1263 } 1264 1265 @SuppressWarnings("unchecked") 1266 private static void stations() { 1267 if (Renderer.zoom >= 14) { 1268 String str = ""; 1269 switch (feature.type) { 1270 case SISTAT: 1271 Renderer.symbol(Harbours.SignalStation); 1272 str = "SS"; 1273 ArrayList<CatSIT> tcats = (ArrayList<CatSIT>) getAttList(Obj.SISTAT, Att.CATSIT); 1274 switch (tcats.get(0)) { 1275 case SIT_IPT: 1276 str += "(INT)"; 1277 break; 1278 case SIT_PRTE: 1279 str += "(Traffic)"; 1280 break; 1281 case SIT_PRTC: 1282 str += "(Port Control)"; 1283 break; 1284 case SIT_LOCK: 1285 str += "(Lock)"; 1286 break; 1287 case SIT_BRDG: 1288 str += "(Bridge)"; 1289 break; 1290 default: 1291 break; 1292 } 1293 break; 1294 case SISTAW: 1295 Renderer.symbol(Harbours.SignalStation); 1296 str = "SS"; 1297 str = "SS"; 1298 ArrayList<CatSIW> wcats = (ArrayList<CatSIW>) getAttList(Obj.SISTAW, Att.CATSIW); 1299 switch (wcats.get(0)) { 1300 case SIW_STRM: 1301 str += "(Storm)"; 1302 break; 1303 case SIW_WTHR: 1304 str += "(Weather)"; 1305 break; 1306 case SIW_ICE: 1307 str += "(Ice)"; 1308 break; 1309 case SIW_TIDG: 1310 str = "Tide gauge"; 1311 break; 1312 case SIW_TIDS: 1313 str = "Tide scale"; 1314 break; 1315 case SIW_TIDE: 1316 str += "(Tide)"; 1317 break; 1318 case SIW_TSTR: 1319 str += "(Stream)"; 1320 break; 1321 case SIW_DNGR: 1322 str += "(Danger)"; 1323 break; 1324 case SIW_MILY: 1325 str += "(Firing)"; 1326 break; 1327 case SIW_TIME: 1328 str += "(Time)"; 1329 break; 1330 default: 1331 break; 1332 } 1333 break; 1334 case RDOSTA: 1335 case RTPBCN: 1336 Renderer.symbol(Harbours.SignalStation); 1337 Renderer.symbol(Beacons.RadarStation); 1338 break; 1339 case RADRFL: 1340 Renderer.symbol(Topmarks.RadarReflector); 1341 break; 1342 case RADSTA: 1343 Renderer.symbol(Harbours.SignalStation); 1344 Renderer.symbol(Beacons.RadarStation); 1345 Renderer.labelText("Ra", new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -70))); 1346 break; 1347 case PILBOP: 1348 Renderer.symbol(Harbours.Pilot); 1349 addName(15, new Font("Arial", Font.BOLD, 40), Symbols.Msymb , new Delta(Handle.LC, AffineTransform.getTranslateInstance(70, -40))); 1350 CatPIL cat = (CatPIL) getAttEnum(feature.type, Att.CATPIL); 1351 if (cat == CatPIL.PIL_HELI) { 1352 Renderer.labelText("H", new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.LC, AffineTransform.getTranslateInstance(70, 0))); 1353 } 1354 break; 1355 case CGUSTA: 1356 Renderer.symbol(Harbours.SignalStation); 1357 str = "CG"; 1358 if (feature.objs.containsKey(Obj.RSCSTA)) Renderer.symbol(Harbours.Rescue, new Delta(Handle.CC, AffineTransform.getTranslateInstance(130, 0))); 1359 break; 1360 case RSCSTA: 1361 Renderer.symbol(Harbours.Rescue); 1362 break; 1363 default: 1364 break; 1365 } 1366 if ((Renderer.zoom >= 15) && !str.isEmpty()) { 1367 Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.LC, AffineTransform.getTranslateInstance(40, 0))); 1368 } 1369 Signals.addSignals(); 1370 } 1371 } 1372 1373 private static void transits() { 1374 if (Renderer.zoom >= 14) { 1375 if (feature.type == Obj.RECTRC) Renderer.lineVector (new LineStyle(Color.black, 10, null, null)); 1376 else if (feature.type == Obj.NAVLNE) Renderer.lineVector (new LineStyle(Color.black, 10, new float[] { 25, 25 }, null)); 1377 } 1378 if (Renderer.zoom >= 15) { 1379 String str = ""; 1380 String name = getName(); 1381 if (name != null) 1382 str += name + " "; 1383 Double ort; 1384 if ((ort = (Double) getAttVal(feature.type, Att.ORIENT)) != null) { 1385 str += df.format(ort) + "º"; 1386 if (!str.isEmpty()) 1387 Renderer.lineText(str, new Font("Arial", Font.PLAIN, 80), Color.black, -20); 1388 } 1389 } 1390 } 1391 1392 private static void waterways() { 1393 Renderer.lineVector(new LineStyle(Symbols.Bwater, 20, (feature.geom.prim == Pflag.AREA) ? Symbols.Bwater : null)); 1394 } 1395 1396 private static void wrecks() { 1397 if (Renderer.zoom >= 14) { 1398 switch ((CatWRK) getAttEnum(feature.type, Att.CATWRK)) { 1399 case WRK_DNGR: 1400 case WRK_MSTS: 1401 Renderer.symbol(Areas.WreckD); 1402 break; 1403 case WRK_HULS: 1404 Renderer.symbol(Areas.WreckS); 1405 break; 1406 default: 1407 Renderer.symbol(Areas.WreckND); 1408 } 1409 } 1410 } 84 85 static final DecimalFormat df = new DecimalFormat("#.#"); 86 87 static final EnumMap<ColCOL, Color> bodyColours = new EnumMap<>(ColCOL.class); 88 static { 89 bodyColours.put(ColCOL.COL_UNK, new Color(0, true)); 90 bodyColours.put(ColCOL.COL_WHT, new Color(0xffffff)); 91 bodyColours.put(ColCOL.COL_BLK, new Color(0x000000)); 92 bodyColours.put(ColCOL.COL_RED, new Color(0xd40000)); 93 bodyColours.put(ColCOL.COL_GRN, new Color(0x00d400)); 94 bodyColours.put(ColCOL.COL_BLU, Color.blue); 95 bodyColours.put(ColCOL.COL_YEL, new Color(0xffd400)); 96 bodyColours.put(ColCOL.COL_GRY, Color.gray); 97 bodyColours.put(ColCOL.COL_BRN, new Color(0x8b4513)); 98 bodyColours.put(ColCOL.COL_AMB, new Color(0xfbf00f)); 99 bodyColours.put(ColCOL.COL_VIO, new Color(0xee82ee)); 100 bodyColours.put(ColCOL.COL_ORG, Color.orange); 101 bodyColours.put(ColCOL.COL_MAG, new Color(0xf000f0)); 102 bodyColours.put(ColCOL.COL_PNK, Color.pink); 103 } 104 105 static final EnumMap<ColPAT, Patt> pattMap = new EnumMap<>(ColPAT.class); 106 static { 107 pattMap.put(ColPAT.PAT_UNKN, Patt.Z); 108 pattMap.put(ColPAT.PAT_HORI, Patt.H); 109 pattMap.put(ColPAT.PAT_VERT, Patt.V); 110 pattMap.put(ColPAT.PAT_DIAG, Patt.D); 111 pattMap.put(ColPAT.PAT_BRDR, Patt.B); 112 pattMap.put(ColPAT.PAT_SQUR, Patt.S); 113 pattMap.put(ColPAT.PAT_CROS, Patt.C); 114 pattMap.put(ColPAT.PAT_SALT, Patt.X); 115 pattMap.put(ColPAT.PAT_STRP, Patt.H); 116 } 117 118 static String getName() { 119 AttVal<?> name = feature.atts.get(Att.OBJNAM); 120 if (name == null) { 121 AttMap atts = feature.objs.get(feature.type).get(0); 122 if (atts != null) { 123 name = atts.get(Att.OBJNAM); 124 } 125 } 126 return (name != null) ? (String) name.val : null; 127 } 128 129 public static void addName(int z, Font font) { 130 addName(z, font, Color.black, new Delta(Handle.CC, new AffineTransform())); 131 } 132 133 public static void addName(int z, Font font, Color colour) { 134 addName(z, font, colour, new Delta(Handle.CC, new AffineTransform())); 135 } 136 137 public static void addName(int z, Font font, Delta delta) { 138 addName(z, font, Color.black, delta); 139 } 140 141 public static void addName(int z, Font font, Color colour, Delta delta) { 142 if (Renderer.zoom >= z) { 143 String name = getName(); 144 if (name != null) { 145 Renderer.labelText(name, font, colour, delta); 146 } 147 } 148 } 149 150 static AttMap getAtts(Obj obj, int idx) { 151 HashMap<Integer, AttMap> objs = feature.objs.get(obj); 152 if (objs == null) 153 return null; 154 else 155 return objs.get(idx); 156 } 157 158 public static Object getAttVal(Obj obj, Att att) { 159 AttMap atts; 160 HashMap<Integer, AttMap> objs; 161 AttVal<?> item; 162 if ((objs = feature.objs.get(obj)) != null) 163 atts = objs.get(0); 164 else 165 return null; 166 if ((item = atts.get(att)) == null) 167 return null; 168 else 169 return item.val; 170 } 171 172 public static String getAttStr(Obj obj, Att att) { 173 String str = (String) getAttVal(obj, att); 174 if (str != null) { 175 return str; 176 } 177 return ""; 178 } 179 180 @SuppressWarnings("unchecked") 181 public static Enum<?> getAttEnum(Obj obj, Att att) { 182 ArrayList<?> list = (ArrayList<?>) getAttVal(obj, att); 183 if (list != null) { 184 return ((ArrayList<Enum<?>>) list).get(0); 185 } 186 return S57val.unknAtt(att); 187 } 188 189 @SuppressWarnings("unchecked") 190 public static ArrayList<?> getAttList(Obj obj, Att att) { 191 ArrayList<Enum<?>> list = (ArrayList<Enum<?>>) getAttVal(obj, att); 192 if (list != null) { 193 return list; 194 } 195 list = new ArrayList<>(); 196 list.add(S57val.unknAtt(att)); 197 return list; 198 } 199 200 @SuppressWarnings("unchecked") 201 static Scheme getScheme(Obj obj) { 202 ArrayList<Color> colours = new ArrayList<>(); 203 for (ColCOL col : (ArrayList<ColCOL>) getAttList(obj, Att.COLOUR)) { 204 colours.add(bodyColours.get(col)); 205 } 206 ArrayList<Patt> patterns = new ArrayList<>(); 207 for (ColPAT pat : (ArrayList<ColPAT>) getAttList(obj, Att.COLPAT)) { 208 patterns.add(pattMap.get(pat)); 209 } 210 return new Scheme(patterns, colours); 211 } 212 213 static boolean hasAttribute(Obj obj, Att att) { 214 AttMap atts; 215 if ((atts = getAtts(obj, 0)) != null) { 216 AttVal<?> item = atts.get(att); 217 return item != null; 218 } 219 return false; 220 } 221 222 static boolean testAttribute(Obj obj, Att att, Object val) { 223 AttMap atts; 224 if ((atts = getAtts(obj, 0)) != null) { 225 AttVal<?> item = atts.get(att); 226 if (item != null) { 227 switch (item.conv) { 228 case S: 229 case A: 230 return ((String) item.val).equals(val); 231 case E: 232 case L: 233 return ((ArrayList<?>) item.val).contains(val); 234 case F: 235 case I: 236 return item.val == val; 237 } 238 } 239 } 240 return false; 241 } 242 243 static boolean hasObject(Obj obj) { 244 return (feature.objs.containsKey(obj)); 245 } 246 247 public static Feature feature; 248 static ArrayList<Feature> objects; 249 250 static boolean testObject(Obj obj) { 251 return ((objects = Renderer.map.features.get(obj)) != null); 252 } 253 254 static boolean testFeature(Feature f) { 255 return ((feature = f).reln == Rflag.MASTER); 256 } 257 258 public static void rules() { 259 if ((Renderer.context.ruleset() == RuleSet.ALL) || (Renderer.context.ruleset() == RuleSet.BASE)) { 260 if (testObject(Obj.LNDARE)) for (Feature f : objects) if (testFeature(f)) areas(); 261 if (testObject(Obj.BUAARE)) for (Feature f : objects) if (testFeature(f)) areas(); 262 if (testObject(Obj.HRBFAC)) for (Feature f : objects) if (testFeature(f)) areas(); 263 if (testObject(Obj.HRBBSN)) for (Feature f : objects) if (testFeature(f)) areas(); 264 if (testObject(Obj.LOKBSN)) for (Feature f : objects) if (testFeature(f)) areas(); 265 if (testObject(Obj.LKBSPT)) for (Feature f : objects) if (testFeature(f)) areas(); 266 if (testObject(Obj.LAKARE)) for (Feature f : objects) if (testFeature(f)) areas(); 267 if (testObject(Obj.RIVERS)) for (Feature f : objects) if (testFeature(f)) waterways(); 268 if (testObject(Obj.CANALS)) for (Feature f : objects) if (testFeature(f)) waterways(); 269 if (testObject(Obj.DEPARE)) for (Feature f : objects) if (testFeature(f)) areas(); 270 if (testObject(Obj.COALNE)) for (Feature f : objects) if (testFeature(f)) areas(); 271 if (testObject(Obj.ROADWY)) for (Feature f : objects) if (testFeature(f)) highways(); 272 if (testObject(Obj.RAILWY)) for (Feature f : objects) if (testFeature(f)) highways(); 273 } 274 if (Renderer.context.ruleset() == RuleSet.ALL) { 275 if (testObject(Obj.SOUNDG)) for (Feature f : objects) if (testFeature(f)) depths(); 276 if (testObject(Obj.DEPCNT)) for (Feature f : objects) if (testFeature(f)) depths(); 277 } 278 if (testObject(Obj.SLCONS)) for (Feature f : objects) if (testFeature(f)) shoreline(); 279 if ((Renderer.context.ruleset() == RuleSet.ALL) || (Renderer.context.ruleset() == RuleSet.SEAMARK)) { 280 if (testObject(Obj.PIPSOL)) for (Feature f : objects) if (testFeature(f)) pipelines(); 281 if (testObject(Obj.CBLSUB)) for (Feature f : objects) if (testFeature(f)) cables(); 282 if (testObject(Obj.PIPOHD)) for (Feature f : objects) if (testFeature(f)) pipelines(); 283 if (testObject(Obj.CBLOHD)) for (Feature f : objects) if (testFeature(f)) cables(); 284 if (testObject(Obj.TSEZNE)) for (Feature f : objects) if (testFeature(f)) separation(); 285 if (testObject(Obj.TSSCRS)) for (Feature f : objects) if (testFeature(f)) separation(); 286 if (testObject(Obj.TSSRON)) for (Feature f : objects) if (testFeature(f)) separation(); 287 if (testObject(Obj.TSELNE)) for (Feature f : objects) if (testFeature(f)) separation(); 288 if (testObject(Obj.TSSLPT)) for (Feature f : objects) if (testFeature(f)) separation(); 289 if (testObject(Obj.TSSBND)) for (Feature f : objects) if (testFeature(f)) separation(); 290 if (testObject(Obj.ISTZNE)) for (Feature f : objects) if (testFeature(f)) separation(); 291 if (testObject(Obj.SNDWAV)) for (Feature f : objects) if (testFeature(f)) areas(); 292 if (testObject(Obj.WEDKLP)) for (Feature f : objects) if (testFeature(f)) areas(); 293 if (testObject(Obj.OSPARE)) for (Feature f : objects) if (testFeature(f)) areas(); 294 if (testObject(Obj.FAIRWY)) for (Feature f : objects) if (testFeature(f)) areas(); 295 if (testObject(Obj.DRGARE)) for (Feature f : objects) if (testFeature(f)) areas(); 296 if (testObject(Obj.RESARE)) for (Feature f : objects) if (testFeature(f)) areas(); 297 if (testObject(Obj.PRCARE)) for (Feature f : objects) if (testFeature(f)) areas(); 298 if (testObject(Obj.SPLARE)) for (Feature f : objects) if (testFeature(f)) areas(); 299 if (testObject(Obj.SEAARE)) for (Feature f : objects) if (testFeature(f)) areas(); 300 if (testObject(Obj.OBSTRN)) for (Feature f : objects) if (testFeature(f)) obstructions(); 301 if (testObject(Obj.UWTROC)) for (Feature f : objects) if (testFeature(f)) obstructions(); 302 if (testObject(Obj.MARCUL)) for (Feature f : objects) if (testFeature(f)) areas(); 303 if (testObject(Obj.RECTRC)) for (Feature f : objects) if (testFeature(f)) transits(); 304 if (testObject(Obj.NAVLNE)) for (Feature f : objects) if (testFeature(f)) transits(); 305 if (testObject(Obj.HRBFAC)) for (Feature f : objects) if (testFeature(f)) harbours(); 306 if (testObject(Obj.ACHARE)) for (Feature f : objects) if (testFeature(f)) harbours(); 307 if (testObject(Obj.ACHBRT)) for (Feature f : objects) if (testFeature(f)) harbours(); 308 if (testObject(Obj.BERTHS)) for (Feature f : objects) if (testFeature(f)) harbours(); 309 if (testObject(Obj.DISMAR)) for (Feature f : objects) if (testFeature(f)) distances(); 310 if (testObject(Obj.HULKES)) for (Feature f : objects) if (testFeature(f)) ports(); 311 if (testObject(Obj.CRANES)) for (Feature f : objects) if (testFeature(f)) ports(); 312 if (testObject(Obj.LNDMRK)) for (Feature f : objects) if (testFeature(f)) landmarks(); 313 if (testObject(Obj.SILTNK)) for (Feature f : objects) if (testFeature(f)) landmarks(); 314 if (testObject(Obj.BUISGL)) for (Feature f : objects) if (testFeature(f)) harbours(); 315 if (testObject(Obj.MORFAC)) for (Feature f : objects) if (testFeature(f)) moorings(); 316 if (testObject(Obj.NOTMRK)) for (Feature f : objects) if (testFeature(f)) notices(); 317 if (testObject(Obj.SMCFAC)) for (Feature f : objects) if (testFeature(f)) marinas(); 318 if (testObject(Obj.BRIDGE)) for (Feature f : objects) if (testFeature(f)) bridges(); 319 if (testObject(Obj.PILPNT)) for (Feature f : objects) if (testFeature(f)) points(); 320 if (testObject(Obj.TOPMAR)) for (Feature f : objects) if (testFeature(f)) points(); 321 if (testObject(Obj.DAYMAR)) for (Feature f : objects) if (testFeature(f)) points(); 322 if (testObject(Obj.FOGSIG)) for (Feature f : objects) if (testFeature(f)) points(); 323 if (testObject(Obj.RDOCAL)) for (Feature f : objects) if (testFeature(f)) callpoint(); 324 if (testObject(Obj.LITMIN)) for (Feature f : objects) if (testFeature(f)) lights(); 325 if (testObject(Obj.LITMAJ)) for (Feature f : objects) if (testFeature(f)) lights(); 326 if (testObject(Obj.LIGHTS)) for (Feature f : objects) if (testFeature(f)) lights(); 327 if (testObject(Obj.SISTAT)) for (Feature f : objects) if (testFeature(f)) stations(); 328 if (testObject(Obj.SISTAW)) for (Feature f : objects) if (testFeature(f)) stations(); 329 if (testObject(Obj.CGUSTA)) for (Feature f : objects) if (testFeature(f)) stations(); 330 if (testObject(Obj.RDOSTA)) for (Feature f : objects) if (testFeature(f)) stations(); 331 if (testObject(Obj.RADRFL)) for (Feature f : objects) if (testFeature(f)) stations(); 332 if (testObject(Obj.RADSTA)) for (Feature f : objects) if (testFeature(f)) stations(); 333 if (testObject(Obj.RTPBCN)) for (Feature f : objects) if (testFeature(f)) stations(); 334 if (testObject(Obj.RSCSTA)) for (Feature f : objects) if (testFeature(f)) stations(); 335 if (testObject(Obj.PILBOP)) for (Feature f : objects) if (testFeature(f)) stations(); 336 if (testObject(Obj.WTWGAG)) for (Feature f : objects) if (testFeature(f)) gauges(); 337 if (testObject(Obj.OFSPLF)) for (Feature f : objects) if (testFeature(f)) platforms(); 338 if (testObject(Obj.WRECKS)) for (Feature f : objects) if (testFeature(f)) wrecks(); 339 if (testObject(Obj.LITVES)) for (Feature f : objects) if (testFeature(f)) floats(); 340 if (testObject(Obj.LITFLT)) for (Feature f : objects) if (testFeature(f)) floats(); 341 if (testObject(Obj.BOYINB)) for (Feature f : objects) if (testFeature(f)) floats(); 342 if (testObject(Obj.BOYLAT)) for (Feature f : objects) if (testFeature(f)) buoys(); 343 if (testObject(Obj.BOYCAR)) for (Feature f : objects) if (testFeature(f)) buoys(); 344 if (testObject(Obj.BOYISD)) for (Feature f : objects) if (testFeature(f)) buoys(); 345 if (testObject(Obj.BOYSAW)) for (Feature f : objects) if (testFeature(f)) buoys(); 346 if (testObject(Obj.BOYSPP)) for (Feature f : objects) if (testFeature(f)) buoys(); 347 if (testObject(Obj.BCNLAT)) for (Feature f : objects) if (testFeature(f)) beacons(); 348 if (testObject(Obj.BCNCAR)) for (Feature f : objects) if (testFeature(f)) beacons(); 349 if (testObject(Obj.BCNISD)) for (Feature f : objects) if (testFeature(f)) beacons(); 350 if (testObject(Obj.BCNSAW)) for (Feature f : objects) if (testFeature(f)) beacons(); 351 if (testObject(Obj.BCNSPP)) for (Feature f : objects) if (testFeature(f)) beacons(); 352 } 353 } 354 355 private static void areas() { 356 String name = getName(); 357 switch (feature.type) { 358 case BUAARE: 359 Renderer.lineVector(new LineStyle(new Color(0x20000000, true))); 360 break; 361 case COALNE: 362 if (Renderer.zoom >= 12) 363 Renderer.lineVector(new LineStyle(Color.black, 10)); 364 break; 365 case DEPARE: 366 Double depmax = 0.0; 367 if (((depmax = (Double) getAttVal(Obj.DEPARE, Att.DRVAL2)) != null) && (depmax <= 0.0)) { 368 Renderer.lineVector(new LineStyle(Symbols.Gdries)); 369 } 370 break; 371 case LAKARE: 372 if ((Renderer.zoom >= 12) || (feature.geom.area > 10.0)) 373 Renderer.lineVector(new LineStyle(Symbols.Bwater)); 374 break; 375 case DRGARE: 376 if (Renderer.zoom < 16) 377 Renderer.lineVector(new LineStyle(Color.black, 8, new float[] {25, 25 }, new Color(0x40ffffff, true))); 378 else 379 Renderer.lineVector(new LineStyle(Color.black, 8, new float[] {25, 25 })); 380 addName(12, new Font("Arial", Font.PLAIN, 100), new Delta(Handle.CC, new AffineTransform())); 381 break; 382 case FAIRWY: 383 if (feature.geom.area > 2.0) { 384 if (Renderer.zoom < 16) 385 Renderer.lineVector(new LineStyle(Symbols.Mline, 8, new float[] {50, 50 }, new Color(0x40ffffff, true))); 386 else 387 Renderer.lineVector(new LineStyle(Symbols.Mline, 8, new float[] {50, 50 })); 388 } else { 389 if (Renderer.zoom >= 14) 390 Renderer.lineVector(new LineStyle(new Color(0x40ffffff, true))); 391 } 392 break; 393 case LKBSPT: 394 case LOKBSN: 395 case HRBBSN: 396 if (Renderer.zoom >= 12) { 397 Renderer.lineVector(new LineStyle(Color.black, 10, Symbols.Bwater)); 398 } else { 399 Renderer.lineVector(new LineStyle(Symbols.Bwater)); 400 } 401 break; 402 case HRBFAC: 403 if (feature.objs.get(Obj.HRBBSN) != null) { 404 if (Renderer.zoom >= 12) { 405 Renderer.lineVector(new LineStyle(Color.black, 10, Symbols.Bwater)); 406 } else { 407 Renderer.lineVector(new LineStyle(Symbols.Bwater)); 408 } 409 } 410 break; 411 case LNDARE: 412 Renderer.lineVector(new LineStyle(Symbols.Yland)); 413 break; 414 case MARCUL: 415 if (Renderer.zoom >= 12) { 416 if (Renderer.zoom >= 14) { 417 Renderer.symbol(Areas.MarineFarm); 418 } 419 if ((feature.geom.area > 0.2) || ((feature.geom.area > 0.05) && (Renderer.zoom >= 14)) || ((feature.geom.area > 0.005) && (Renderer.zoom >= 16))) { 420 Renderer.lineVector(new LineStyle(Color.black, 4, new float[] {10, 10})); 421 } 422 } 423 break; 424 case OSPARE: 425 if (testAttribute(feature.type, Att.CATPRA, CatPRA.PRA_WFRM)) { 426 Renderer.symbol(Areas.WindFarm); 427 Renderer.lineVector(new LineStyle(Color.black, 20, new float[] {40, 40})); 428 addName(15, new Font("Arial", Font.BOLD, 80), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, 10))); 429 } 430 break; 431 case RESARE: 432 case MIPARE: 433 if (Renderer.zoom >= 12) { 434 Renderer.lineSymbols(Areas.Restricted, 1.0, null, null, 0, Symbols.Mline); 435 if (testAttribute(feature.type, Att.CATREA, CatREA.REA_NWAK)) { 436 Renderer.symbol(Areas.NoWake); 437 } 438 } 439 break; 440 case PRCARE: 441 if (Renderer.zoom >= 12) { 442 Renderer.lineVector(new LineStyle(Symbols.Mline, 10, new float[] {40, 40})); 443 } 444 break; 445 case SEAARE: 446 switch ((CatSEA) getAttEnum(feature.type, Att.CATSEA)) { 447 case SEA_RECH: 448 if ((Renderer.zoom >= 10) && (name != null)) 449 if (feature.geom.prim == Pflag.LINE) { 450 Renderer.lineText(name, new Font("Arial", Font.PLAIN, 150), Color.black, -40); 451 } else { 452 Renderer.labelText(name, new Font("Arial", Font.PLAIN, 150), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40))); 453 } 454 break; 455 case SEA_BAY: 456 if ((Renderer.zoom >= 12) && (name != null)) 457 if (feature.geom.prim == Pflag.LINE) { 458 Renderer.lineText(name, new Font("Arial", Font.PLAIN, 150), Color.black, -40); 459 } else { 460 Renderer.labelText(name, new Font("Arial", Font.PLAIN, 150), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40))); 461 } 462 break; 463 case SEA_SHOL: 464 if (Renderer.zoom >= 14) { 465 if (feature.geom.prim == Pflag.AREA) { 466 Renderer.lineVector(new LineStyle(new Color(0xc480ff), 4, new float[] {25, 25})); 467 if (name != null) { 468 Renderer.labelText(name, new Font("Arial", Font.ITALIC, 75), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40))); 469 Renderer.labelText("(Shoal)", new Font("Arial", Font.PLAIN, 60), Color.black, new Delta(Handle.BC)); 470 } 471 } else if (feature.geom.prim == Pflag.LINE) { 472 if (name != null) { 473 Renderer.lineText(name, new Font("Arial", Font.ITALIC, 75), Color.black, -40); 474 Renderer.lineText("(Shoal)", new Font("Arial", Font.PLAIN, 60), Color.black, 0); 475 } 476 } else { 477 if (name != null) { 478 Renderer.labelText(name, new Font("Arial", Font.ITALIC, 75), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40))); 479 Renderer.labelText("(Shoal)", new Font("Arial", Font.PLAIN, 60), Color.black, new Delta(Handle.BC)); 480 } 481 } 482 } 483 break; 484 case SEA_GAT: 485 case SEA_NRRW: 486 addName(12, new Font("Arial", Font.PLAIN, 100)); 487 break; 488 default: 489 break; 490 } 491 break; 492 case SNDWAV: 493 if (Renderer.zoom >= 12) Renderer.fillPattern(Areas.Sandwaves); 494 break; 495 case WEDKLP: 496 if (Renderer.zoom >= 12) { 497 switch ((CatWED) getAttEnum(feature.type, Att.CATWED)) { 498 case WED_KELP: 499 if (feature.geom.prim == Pflag.AREA) { 500 Renderer.fillPattern(Areas.KelpA); 501 } else { 502 Renderer.symbol(Areas.KelpS); 503 } 504 break; 505 default: 506 break; 507 } 508 } 509 break; 510 case SPLARE: 511 if (Renderer.zoom >= 12) { 512 Renderer.symbol(Areas.Plane, new Scheme(Symbols.Msymb)); 513 Renderer.lineSymbols(Areas.Restricted, 0.5, Areas.LinePlane, null, 10, Symbols.Mline); 514 } 515 addName(15, new Font("Arial", Font.BOLD, 80), new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -90))); 516 break; 517 default: 518 break; 519 } 520 } 521 522 @SuppressWarnings("unchecked") 523 private static void beacons() { 524 if ((Renderer.zoom >= 14) || ((Renderer.zoom >= 12) && ((feature.type == Obj.BCNLAT) || (feature.type == Obj.BCNCAR))) 525 || ((Renderer.zoom >= 11) && ((feature.type == Obj.BCNSAW) || hasObject(Obj.RTPBCN)))) { 526 BcnSHP shape = (BcnSHP) getAttEnum(feature.type, Att.BCNSHP); 527 if (shape == BcnSHP.BCN_UNKN) 528 shape = BcnSHP.BCN_PILE; 529 if ((shape == BcnSHP.BCN_WTHY) && (feature.type == Obj.BCNLAT)) { 530 switch ((CatLAM) getAttEnum(feature.type, Att.CATLAM)) { 531 case LAM_PORT: 532 Renderer.symbol(Beacons.WithyPort); 533 break; 534 case LAM_STBD: 535 Renderer.symbol(Beacons.WithyStarboard); 536 break; 537 default: 538 Renderer.symbol(Beacons.Stake, getScheme(feature.type)); 539 } 540 } else if ((shape == BcnSHP.BCN_PRCH) && (feature.type == Obj.BCNLAT) && !(feature.objs.containsKey(Obj.TOPMAR))) { 541 switch ((CatLAM) getAttEnum(feature.type, Att.CATLAM)) { 542 case LAM_PORT: 543 Renderer.symbol(Beacons.PerchPort); 544 break; 545 case LAM_STBD: 546 Renderer.symbol(Beacons.PerchStarboard); 547 break; 548 default: 549 Renderer.symbol(Beacons.Stake, getScheme(feature.type)); 550 } 551 } else { 552 Renderer.symbol(Beacons.Shapes.get(shape), getScheme(feature.type)); 553 if (feature.objs.containsKey(Obj.TOPMAR)) { 554 AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0); 555 if (topmap.containsKey(Att.TOPSHP)) { 556 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.TOPMAR), Topmarks.BeaconDelta); 557 } 558 } else if (feature.objs.containsKey(Obj.DAYMAR)) { 559 AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0); 560 if (topmap.containsKey(Att.TOPSHP)) { 561 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.DAYMAR), Topmarks.BeaconDelta); 562 } 563 } 564 } 565 if (hasObject(Obj.NOTMRK)) 566 notices(); 567 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(60, -50))); 568 Signals.addSignals(); 569 } 570 } 571 572 @SuppressWarnings("unchecked") 573 private static void buoys() { 574 if ((Renderer.zoom >= 14) || ((Renderer.zoom >= 12) && ((feature.type == Obj.BOYLAT) || (feature.type == Obj.BOYCAR))) 575 || ((Renderer.zoom >= 11) && ((feature.type == Obj.BOYSAW) || hasObject(Obj.RTPBCN)))) { 576 BoySHP shape = (BoySHP) getAttEnum(feature.type, Att.BOYSHP); 577 if (shape == BoySHP.BOY_UNKN) shape = BoySHP.BOY_PILR; 578 Renderer.symbol(Buoys.Shapes.get(shape), getScheme(feature.type)); 579 if (feature.objs.containsKey(Obj.TOPMAR)) { 580 AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0); 581 if (topmap.containsKey(Att.TOPSHP)) { 582 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.TOPMAR), Topmarks.BuoyDeltas.get(shape)); 583 } 584 } else if (feature.objs.containsKey(Obj.DAYMAR)) { 585 AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0); 586 if (topmap.containsKey(Att.TOPSHP)) { 587 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.DAYMAR), Topmarks.BuoyDeltas.get(shape)); 588 } 589 } 590 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(60, -50))); 591 Signals.addSignals(); 592 } 593 } 594 595 private static void bridges() { 596 if (Renderer.zoom >= 16) { 597 double verclr, verccl, vercop, horclr; 598 AttMap atts = feature.objs.get(Obj.BRIDGE).get(0); 599 String vstr = ""; 600 String hstr = ""; 601 if (atts != null) { 602 if (atts.containsKey(Att.HORCLR)) { 603 horclr = (Double) atts.get(Att.HORCLR).val; 604 hstr = String.valueOf(horclr); 605 } 606 if (atts.containsKey(Att.VERCLR)) { 607 verclr = (Double) atts.get(Att.VERCLR).val; 608 } else { 609 verclr = atts.containsKey(Att.VERCSA) ? (Double) atts.get(Att.VERCSA).val : 0; 610 } 611 verccl = atts.containsKey(Att.VERCCL) ? (Double) atts.get(Att.VERCCL).val : 0; 612 vercop = atts.containsKey(Att.VERCOP) ? (Double) atts.get(Att.VERCOP).val : 0; 613 if (verclr > 0) { 614 vstr += String.valueOf(verclr); 615 } else if (verccl > 0) { 616 if (vercop == 0) { 617 vstr += String.valueOf(verccl) + "/-"; 618 } else { 619 vstr += String.valueOf(verccl) + "/" + String.valueOf(vercop); 620 } 621 } 622 if (hstr.isEmpty() && !vstr.isEmpty()) { 623 Renderer.labelText(vstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.VCLR, Color.black, Color.white, new Delta(Handle.CC)); 624 } else if (!hstr.isEmpty() && !vstr.isEmpty()) { 625 Renderer.labelText(vstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.VCLR, Color.black, Color.white, new Delta(Handle.BC)); 626 Renderer.labelText(hstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.HCLR, Color.black, Color.white, new Delta(Handle.TC)); 627 } else if (!hstr.isEmpty() && vstr.isEmpty()) { 628 Renderer.labelText(hstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.HCLR, Color.black, Color.white, new Delta(Handle.CC)); 629 } 630 } 631 } 632 } 633 634 private static void cables() { 635 if ((Renderer.zoom >= 16) && (feature.geom.length < 2)) { 636 if (feature.type == Obj.CBLSUB) { 637 Renderer.lineSymbols(Areas.Cable, 0.0, null, null, 0, Symbols.Mline); 638 } else if (feature.type == Obj.CBLOHD) { 639 AttMap atts = feature.objs.get(Obj.CBLOHD).get(0); 640 if ((atts != null) && (atts.containsKey(Att.CATCBL)) && (atts.get(Att.CATCBL).val == CatCBL.CBL_POWR)) { 641 Renderer.lineSymbols(Areas.CableDash, 0, Areas.CableDot, Areas.CableFlash, 2, Color.black); 642 } else { 643 Renderer.lineSymbols(Areas.CableDash, 0, Areas.CableDot, null, 2, Color.black); 644 } 645 if (atts != null) { 646 if (atts.containsKey(Att.VERCLR)) { 647 Renderer.labelText(String.valueOf(atts.get(Att.VERCLR).val), new Font("Arial", Font.PLAIN, 50), Color.black, LabelStyle.VCLR, Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, 25))); 648 } else if (atts.containsKey(Att.VERCSA)) { 649 Renderer.labelText(String.valueOf(atts.get(Att.VERCSA).val), new Font("Arial", Font.PLAIN, 50), Color.black, LabelStyle.PCLR, Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, 25))); 650 } 651 } 652 } 653 } 654 } 655 656 private static void callpoint() { 657 if (Renderer.zoom >= 14) { 658 Symbol symb = Harbours.CallPoint2; 659 TrfTRF trf = (TrfTRF) getAttEnum(feature.type, Att.TRAFIC); 660 if (trf != TrfTRF.TRF_TWOW) { 661 symb = Harbours.CallPoint1; 662 } 663 Double orient = 0.0; 664 if ((orient = (Double) getAttVal(feature.type, Att.ORIENT)) == null) { 665 orient = 0.0; 666 } 667 Renderer.symbol(symb, new Delta(Handle.CC, AffineTransform.getRotateInstance(Math.toRadians(orient)))); 668 String chn; 669 if (!(chn = getAttStr(feature.type, Att.COMCHA)).isEmpty()) { 670 Renderer.labelText(("Ch." + chn), new Font("Arial", Font.PLAIN, 50), Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, 50))); 671 } 672 } 673 } 674 675 private static void depths() { 676 switch (feature.type) { 677 case SOUNDG: 678 if ((Renderer.zoom >= 14) && hasAttribute(Obj.SOUNDG, Att.VALSOU)) { 679 double depth = (double) getAttVal(Obj.SOUNDG, Att.VALSOU); 680 String dstr = df.format(depth); 681 String[] tok = dstr.split("[-.]"); 682 String ul = ""; 683 String id = tok[0]; 684 String dd = ""; 685 if (tok[0].equals("")) { 686 for (int i = 0; i < tok[1].length(); i++) { 687 ul += "_"; 688 } 689 id = tok[1]; 690 dd = (tok.length == 3) ? tok[2] : ""; 691 } else { 692 dd = (tok.length == 2) ? tok[1] : ""; 693 } 694 Renderer.labelText(ul, new Font("Arial", Font.PLAIN, 30), Color.black, new Delta(Handle.RC, AffineTransform.getTranslateInstance(10, 15))); 695 Renderer.labelText(id, new Font("Arial", Font.PLAIN, 30), Color.black, new Delta(Handle.RC, AffineTransform.getTranslateInstance(10, 0))); 696 Renderer.labelText(dd, new Font("Arial", Font.PLAIN, 20), Color.black, new Delta(Handle.LC, AffineTransform.getTranslateInstance(15, 10))); 697 } 698 break; 699 case DEPCNT: 700 break; 701 default: 702 break; 703 } 704 } 705 706 private static void distances() { 707 if (Renderer.zoom >= 14) { 708 if (!testAttribute(Obj.DISMAR, Att.CATDIS, CatDIS.DIS_NONI)) { 709 Renderer.symbol(Harbours.DistanceI); 710 } else { 711 Renderer.symbol(Harbours.DistanceU); 712 } 713 if (Renderer.zoom >= 15) { 714 AttMap atts = getAtts(Obj.DISMAR, 0); 715 if ((atts != null) && (atts.containsKey(Att.WTWDIS))) { 716 Double dist = (Double) atts.get(Att.WTWDIS).val; 717 String str = ""; 718 if (atts.containsKey(Att.HUNITS)) { 719 switch ((UniHLU) getAttEnum(Obj.DISMAR, Att.HUNITS)) { 720 case HLU_METR: 721 str += "m "; 722 break; 723 case HLU_FEET: 724 str += "ft "; 725 break; 726 case HLU_HMTR: 727 str += "hm "; 728 break; 729 case HLU_KMTR: 730 str += "km "; 731 break; 732 case HLU_SMIL: 733 str += "M "; 734 break; 735 case HLU_NMIL: 736 str += "NM "; 737 break; 738 default: 739 break; 740 } 741 } 742 str += String.format("%1.0f", dist); 743 Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.CC, AffineTransform.getTranslateInstance(0, 45))); 744 } 745 } 746 } 747 } 748 749 @SuppressWarnings("unchecked") 750 private static void floats() { 751 if ((Renderer.zoom >= 12) || ((Renderer.zoom >= 11) && ((feature.type == Obj.LITVES) || (feature.type == Obj.BOYINB) || hasObject(Obj.RTPBCN)))) { 752 switch (feature.type) { 753 case LITVES: 754 Renderer.symbol(Buoys.Super, getScheme(feature.type)); 755 break; 756 case LITFLT: 757 Renderer.symbol(Buoys.Float, getScheme(feature.type)); 758 break; 759 case BOYINB: 760 Renderer.symbol(Buoys.Super, getScheme(feature.type)); 761 break; 762 default: 763 break; 764 } 765 if (feature.objs.containsKey(Obj.TOPMAR)) { 766 AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0); 767 if (topmap.containsKey(Att.TOPSHP)) { 768 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.TOPMAR), Topmarks.FloatDelta); 769 } 770 } else if (feature.objs.containsKey(Obj.DAYMAR)) { 771 AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0); 772 if (topmap.containsKey(Att.TOPSHP)) { 773 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.DAYMAR), Topmarks.FloatDelta); 774 } 775 } 776 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(20, -50))); 777 Signals.addSignals(); 778 } 779 } 780 781 private static void gauges() { 782 if (Renderer.zoom >= 14) { 783 Renderer.symbol(Harbours.TideGauge); 784 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(20, -50))); 785 Signals.addSignals(); 786 } 787 } 788 789 @SuppressWarnings("unchecked") 790 private static void harbours() { 791 String name = getName(); 792 switch (feature.type) { 793 case ACHBRT: 794 if (Renderer.zoom >= 14) { 795 Renderer.symbol(Harbours.Anchor, new Scheme(Symbols.Msymb)); 796 if (Renderer.zoom >= 15) { 797 Renderer.labelText(name == null ? "" : name, new Font("Arial", Font.PLAIN, 30), Symbols.Msymb, LabelStyle.RRCT, Symbols.Msymb, Color.white, new Delta(Handle.BC)); 798 } 799 } 800 if (getAttVal(Obj.ACHBRT, Att.RADIUS) != null) { 801 double radius; 802 if ((radius = (Double) getAttVal(Obj.ACHBRT, Att.RADIUS)) != 0) { 803 UniHLU units = (UniHLU) getAttEnum(Obj.ACHBRT, Att.HUNITS); 804 if (units == UniHLU.HLU_UNKN) { 805 units = UniHLU.HLU_METR; 806 } 807 Renderer.lineCircle(new LineStyle(Symbols.Mline, 4, new float[] {10, 10}, null), radius, units); 808 } 809 } 810 break; 811 case ACHARE: 812 if (Renderer.zoom >= 12) { 813 if (feature.geom.prim != Pflag.AREA) { 814 Renderer.symbol(Harbours.Anchorage, new Scheme(Color.black)); 815 } else { 816 Renderer.symbol(Harbours.Anchorage, new Scheme(Symbols.Mline)); 817 Renderer.lineSymbols(Areas.Restricted, 1.0, Areas.LineAnchor, null, 10, Symbols.Mline); 818 } 819 addName(15, new Font("Arial", Font.BOLD, 60), Symbols.Mline, new Delta(Handle.LC, AffineTransform.getTranslateInstance(70, 0))); 820 ArrayList<StsSTS> sts = (ArrayList<StsSTS>) getAttList(Obj.ACHARE, Att.STATUS); 821 if ((Renderer.zoom >= 15) && (sts.contains(StsSTS.STS_RESV))) { 822 Renderer.labelText("Reserved", new Font("Arial", Font.PLAIN, 50), Symbols.Mline, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, 60))); 823 } 824 ArrayList<CatACH> cats = (ArrayList<CatACH>) getAttList(Obj.ACHARE, Att.CATACH); 825 int dy = (cats.size() - 1) * -30; 826 for (CatACH cat : cats) { 827 switch (cat) { 828 case ACH_DEEP: 829 Renderer.labelText("DW", new Font("Arial", Font.BOLD, 50), Symbols.Msymb, new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 830 dy += 60; 831 break; 832 case ACH_TANK: 833 Renderer.labelText("Tanker", new Font("Arial", Font.BOLD, 50), Symbols.Msymb, new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 834 dy += 60; 835 break; 836 case ACH_H24P: 837 Renderer.labelText("24h", new Font("Arial", Font.BOLD, 50), Symbols.Msymb, new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 838 dy += 60; 839 break; 840 case ACH_EXPL: 841 Renderer.symbol(Harbours.Explosives, new Scheme(Symbols.Msymb), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 842 dy += 60; 843 break; 844 case ACH_QUAR: 845 Renderer.symbol(Harbours.Hospital, new Scheme(Symbols.Msymb), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 846 dy += 60; 847 break; 848 case ACH_SEAP: 849 Renderer.symbol(Areas.Seaplane, new Scheme(Symbols.Msymb), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy))); 850 dy += 60; 851 break; 852 default: 853 } 854 } 855 } 856 break; 857 case BERTHS: 858 if (Renderer.zoom >= 14) { 859 Renderer.lineVector(new LineStyle(Symbols.Mline, 6, new float[] {20, 20})); 860 Renderer.labelText(name == null ? " " : name, new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, LabelStyle.RRCT, Symbols.Mline, Color.white); 861 } 862 break; 863 case BUISGL: 864 if (Renderer.zoom >= 16) { 865 ArrayList<Symbol> symbols = new ArrayList<>(); 866 ArrayList<FncFNC> fncs = (ArrayList<FncFNC>) getAttList(Obj.BUISGL, Att.FUNCTN); 867 for (FncFNC fnc : fncs) { 868 symbols.add(Landmarks.Funcs.get(fnc)); 869 } 870 if (feature.objs.containsKey(Obj.SMCFAC)) { 871 ArrayList<CatSCF> scfs = (ArrayList<CatSCF>) getAttList(Obj.SMCFAC, Att.CATSCF); 872 for (CatSCF scf : scfs) { 873 symbols.add(Facilities.Cats.get(scf)); 874 } 875 } 876 Renderer.cluster(symbols); 877 } 878 break; 879 case HRBFAC: 880 if (Renderer.zoom >= 12) { 881 ArrayList<CatHAF> cathaf = (ArrayList<CatHAF>) getAttList(Obj.HRBFAC, Att.CATHAF); 882 if (cathaf.size() == 1) { 883 switch (cathaf.get(0)) { 884 case HAF_MRNA: 885 Renderer.symbol(Harbours.Marina); 886 break; 887 case HAF_MANF: 888 Renderer.symbol(Harbours.MarinaNF); 889 break; 890 case HAF_FISH: 891 Renderer.symbol(Harbours.Fishing); 892 break; 893 default: 894 Renderer.symbol(Harbours.Harbour); 895 break; 896 } 897 } else { 898 Renderer.symbol(Harbours.Harbour); 899 } 900 } 901 break; 902 default: 903 break; 904 } 905 } 906 907 @SuppressWarnings("unchecked") 908 private static void highways() { 909 switch (feature.type) { 910 case ROADWY: 911 ArrayList<CatROD> cat = (ArrayList<CatROD>) (getAttList(Obj.ROADWY, Att.CATROD)); 912 if (cat.size() > 0) { 913 switch (cat.get(0)) { 914 case ROD_MWAY: 915 Renderer.lineVector(new LineStyle(Color.black, 20)); 916 break; 917 case ROD_MAJR: 918 Renderer.lineVector(new LineStyle(Color.black, 15)); 919 break; 920 case ROD_MINR: 921 Renderer.lineVector(new LineStyle(Color.black, 10)); 922 break; 923 default: 924 Renderer.lineVector(new LineStyle(Color.black, 5)); 925 } 926 } else { 927 Renderer.lineVector(new LineStyle(Color.black, 5)); 928 } 929 break; 930 case RAILWY: 931 Renderer.lineVector(new LineStyle(Color.gray, 10)); 932 Renderer.lineVector(new LineStyle(Color.black, 10, new float[] {30, 30})); 933 break; 934 default: 935 } 936 } 937 938 @SuppressWarnings("unchecked") 939 private static void landmarks() { 940 if (!hasAttribute(Obj.LNDMRK, Att.CATLMK) 941 && (!hasAttribute(Obj.LNDMRK, Att.FUNCTN) || testAttribute(Obj.LNDMRK, Att.FUNCTN, FncFNC.FNC_LGHT)) 942 && hasObject(Obj.LIGHTS)) 943 lights(); 944 else if (Renderer.zoom >= 12) { 945 switch (feature.type) { 946 case LNDMRK: 947 ArrayList<CatLMK> cats = (ArrayList<CatLMK>) getAttList(feature.type, Att.CATLMK); 948 Symbol catSym = Landmarks.Shapes.get(cats.get(0)); 949 ArrayList<FncFNC> fncs = (ArrayList<FncFNC>) getAttList(feature.type, Att.FUNCTN); 950 Symbol fncSym = Landmarks.Funcs.get(fncs.get(0)); 951 if ((fncs.get(0) == FncFNC.FNC_CHCH) && (cats.get(0) == CatLMK.LMK_TOWR)) 952 catSym = Landmarks.ChurchTower; 953 if (cats.get(0) == CatLMK.LMK_RADR) 954 fncSym = Landmarks.RadioTV; 955 Renderer.symbol(catSym); 956 Renderer.symbol(fncSym); 957 break; 958 case SILTNK: 959 if (testAttribute(feature.type, Att.CATSIL, CatSIL.SIL_WTRT)) 960 Renderer.symbol(Landmarks.WaterTower); 961 break; 962 default: 963 break; 964 } 965 if (Renderer.zoom >= 15) 966 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(60, -50))); 967 Signals.addSignals(); 968 } 969 } 970 971 @SuppressWarnings("unchecked") 972 private static void points() { 973 boolean ok = false; 974 switch (feature.type) { 975 case FOGSIG: 976 if (Renderer.zoom >= 12) { 977 if (feature.objs.containsKey(Obj.LIGHTS)) 978 lights(); 979 else 980 Renderer.symbol(Harbours.Post); 981 ok = true; 982 } 983 break; 984 default: 985 if (Renderer.zoom >= 14) { 986 if (feature.objs.containsKey(Obj.LIGHTS)) 987 lights(); 988 else 989 Renderer.symbol(Harbours.Post); 990 ok = true; 991 } 992 break; 993 } 994 if (ok) { 995 if (feature.objs.containsKey(Obj.TOPMAR)) { 996 AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0); 997 if (topmap.containsKey(Att.TOPSHP)) { 998 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.TOPMAR), null); 999 } 1000 } else if (feature.objs.containsKey(Obj.DAYMAR)) { 1001 AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0); 1002 if (topmap.containsKey(Att.TOPSHP)) { 1003 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.DAYMAR), null); 1004 } 1005 } 1006 Signals.addSignals(); 1007 } 1008 } 1009 1010 @SuppressWarnings("unchecked") 1011 private static void lights() { 1012 boolean ok = false; 1013 switch (feature.type) { 1014 case LITMAJ: 1015 case LNDMRK: 1016 if (Renderer.zoom >= 12) { 1017 Renderer.symbol(Beacons.LightMajor); 1018 ok = true; 1019 } 1020 break; 1021 case LITMIN: 1022 case LIGHTS: 1023 case PILPNT: 1024 if (Renderer.zoom >= 14) { 1025 Renderer.symbol(Beacons.LightMinor); 1026 ok = true; 1027 } 1028 break; 1029 default: 1030 break; 1031 } 1032 if (ok) { 1033 if (feature.objs.containsKey(Obj.TOPMAR)) { 1034 AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0); 1035 if (topmap.containsKey(Att.TOPSHP)) { 1036 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.TOPMAR), Topmarks.LightDelta); 1037 } 1038 } else if (feature.objs.containsKey(Obj.DAYMAR)) { 1039 AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0); 1040 if (topmap.containsKey(Att.TOPSHP)) { 1041 Renderer.symbol(Topmarks.Shapes.get(((ArrayList<TopSHP>) (topmap.get(Att.TOPSHP).val)).get(0)), getScheme(Obj.DAYMAR), Topmarks.LightDelta); 1042 } 1043 } 1044 Signals.addSignals(); 1045 } 1046 } 1047 1048 @SuppressWarnings("unchecked") 1049 private static void marinas() { 1050 if (Renderer.zoom >= 16) { 1051 ArrayList<Symbol> symbols = new ArrayList<>(); 1052 ArrayList<CatSCF> scfs = (ArrayList<CatSCF>) getAttList(Obj.SMCFAC, Att.CATSCF); 1053 for (CatSCF scf : scfs) { 1054 symbols.add(Facilities.Cats.get(scf)); 1055 } 1056 Renderer.cluster(symbols); 1057 } 1058 } 1059 1060 private static void moorings() { 1061 if (Renderer.zoom >= 14) { 1062 switch ((CatMOR) getAttEnum(feature.type, Att.CATMOR)) { 1063 case MOR_DLPN: 1064 Renderer.symbol(Harbours.Dolphin); 1065 break; 1066 case MOR_DDPN: 1067 Renderer.symbol(Harbours.DeviationDolphin); 1068 break; 1069 case MOR_BLRD: 1070 case MOR_POST: 1071 Renderer.symbol(Harbours.Bollard); 1072 break; 1073 case MOR_BUOY: 1074 BoySHP shape = (BoySHP) getAttEnum(feature.type, Att.BOYSHP); 1075 if (shape == BoySHP.BOY_UNKN) { 1076 shape = BoySHP.BOY_SPHR; 1077 } 1078 Renderer.symbol(Buoys.Shapes.get(shape), getScheme(feature.type)); 1079 Renderer.symbol(Topmarks.TopMooring, Topmarks.BuoyDeltas.get(shape)); 1080 break; 1081 default: 1082 break; 1083 } 1084 Signals.addSignals(); 1085 } 1086 } 1087 1088 @SuppressWarnings("unchecked") 1089 private static void notices() { 1090 if (Renderer.zoom >= 14) { 1091 double dx = 0.0, dy = 0.0; 1092 switch (feature.type) { 1093 case BCNCAR: 1094 case BCNISD: 1095 case BCNLAT: 1096 case BCNSAW: 1097 case BCNSPP: 1098 if (testAttribute(Obj.TOPMAR, Att.TOPSHP, TopSHP.TOP_BORD) || testAttribute(Obj.DAYMAR, Att.TOPSHP, TopSHP.TOP_BORD)) { 1099 dy = -100.0; 1100 } else { 1101 dy = -45.0; 1102 } 1103 break; 1104 case NOTMRK: 1105 dy = 0.0; 1106 break; 1107 default: 1108 return; 1109 } 1110 MarSYS sys = MarSYS.SYS_CEVN; 1111 BnkWTW bnk = BnkWTW.BWW_UNKN; 1112 AttVal<?> att = feature.atts.get(Att.MARSYS); 1113 if (att != null) sys = (MarSYS) att.val; 1114 att = feature.atts.get(Att.BNKWTW); 1115 if (att != null) bnk = (BnkWTW) att.val; 1116 ObjTab objs = feature.objs.get(Obj.NOTMRK); 1117 int n = objs.size(); 1118 if (n > 5) { 1119 Renderer.symbol(Notices.Notice, new Delta(Handle.CC, AffineTransform.getTranslateInstance(dx, dy))); 1120 } else { 1121 int i = 0; 1122 for (AttMap atts : objs.values()) { 1123 if (atts.get(Att.MARSYS) != null) sys = ((ArrayList<MarSYS>) (atts.get(Att.MARSYS).val)).get(0); 1124 if (atts.get(Att.BNKWTW) != null) bnk = ((ArrayList<BnkWTW>) (atts.get(Att.BNKWTW).val)).get(0); 1125 CatNMK cat = CatNMK.NMK_UNKN; 1126 if (atts.get(Att.CATNMK) != null) cat = ((ArrayList<CatNMK>) (atts.get(Att.CATNMK).val)).get(0); 1127 Symbol sym = Notices.getNotice(cat, sys, bnk); 1128 Scheme sch = Notices.getScheme(sys, bnk); 1129 ArrayList<AddMRK> add = new ArrayList<>(); 1130 if (atts.get(Att.ADDMRK) != null) add = (ArrayList<AddMRK>) (atts.get(Att.ADDMRK).val); 1131 Handle h = Handle.CC; 1132 double ax = 0.0; 1133 double ay = 0.0; 1134 switch (i) { 1135 case 0: 1136 if (n != 1) h = null; 1137 break; 1138 case 1: 1139 if (n <= 3) { 1140 h = Handle.RC; 1141 ax = -30; 1142 ay = dy; 1143 } else { 1144 h = Handle.BR; 1145 } 1146 break; 1147 case 2: 1148 if (n <= 3) 1149 h = Handle.LC; 1150 else 1151 h = Handle.BL; 1152 break; 1153 case 3: 1154 if (n == 4) 1155 h = Handle.TC; 1156 else 1157 h = Handle.TR; 1158 break; 1159 case 4: 1160 h = Handle.TL; 1161 break; 1162 } 1163 if (h != null) { 1164 Renderer.symbol(sym, sch, new Delta(h, AffineTransform.getTranslateInstance(dx, dy))); 1165 if (!add.isEmpty()) 1166 Renderer.symbol(Notices.NoticeBoard, new Delta(Handle.BC, AffineTransform.getTranslateInstance(ax, ay - 30))); 1167 } 1168 i++; 1169 } 1170 } 1171 } 1172 } 1173 1174 private static void obstructions() { 1175 if ((Renderer.zoom >= 12) && (feature.type == Obj.OBSTRN)) { 1176 switch ((CatOBS) getAttEnum(feature.type, Att.CATOBS)) { 1177 case OBS_BOOM: 1178 Renderer.lineVector(new LineStyle(Color.black, 5, new float[] {20, 20}, null)); 1179 if (Renderer.zoom >= 15) { 1180 Renderer.lineText("Boom", new Font("Arial", Font.PLAIN, 80), Color.black, -20); 1181 } 1182 default: 1183 break; 1184 } 1185 } 1186 if ((Renderer.zoom >= 14) && (feature.type == Obj.UWTROC)) { 1187 switch ((WatLEV) getAttEnum(feature.type, Att.WATLEV)) { 1188 case LEV_CVRS: 1189 Renderer.symbol(Areas.RockC); 1190 break; 1191 case LEV_AWSH: 1192 Renderer.symbol(Areas.RockA); 1193 break; 1194 default: 1195 Renderer.symbol(Areas.Rock); 1196 } 1197 } else { 1198 Renderer.symbol(Areas.Rock); 1199 } 1200 } 1201 1202 private static void pipelines() { 1203 if ((Renderer.zoom >= 16) && (feature.geom.length < 2)) { 1204 if (feature.type == Obj.PIPSOL) { 1205 Renderer.lineSymbols(Areas.Pipeline, 1.0, null, null, 0, Symbols.Mline); 1206 } else if (feature.type == Obj.PIPOHD) { 1207 Renderer.lineVector(new LineStyle(Color.black, 8)); 1208 AttMap atts = feature.atts; 1209 double verclr = 0; 1210 if (atts != null) { 1211 if (atts.containsKey(Att.VERCLR)) { 1212 verclr = (Double) atts.get(Att.VERCLR).val; 1213 } else { 1214 verclr = atts.containsKey(Att.VERCSA) ? (Double) atts.get(Att.VERCSA).val : 0; 1215 } 1216 if (verclr > 0) { 1217 Renderer.labelText(String.valueOf(verclr), new Font("Arial", Font.PLAIN, 50), Color.black, LabelStyle.VCLR, Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, 25))); 1218 } 1219 } 1220 } 1221 } 1222 } 1223 1224 @SuppressWarnings("unchecked") 1225 private static void platforms() { 1226 ArrayList<CatOFP> cats = (ArrayList<CatOFP>) getAttList(Obj.OFSPLF, Att.CATOFP); 1227 if (cats.get(0) == CatOFP.OFP_FPSO) 1228 Renderer.symbol(Buoys.Storage); 1229 else 1230 Renderer.symbol(Landmarks.Platform); 1231 addName(15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(20, -50))); 1232 Signals.addSignals(); 1233 } 1234 1235 private static void ports() { 1236 if (Renderer.zoom >= 14) { 1237 if (feature.type == Obj.CRANES) { 1238 if ((CatCRN) getAttEnum(feature.type, Att.CATCRN) == CatCRN.CRN_CONT) 1239 Renderer.symbol(Harbours.ContainerCrane); 1240 else 1241 Renderer.symbol(Harbours.PortCrane); 1242 } else if (feature.type == Obj.HULKES) { 1243 Renderer.lineVector(new LineStyle(Color.black, 4, null, new Color(0xffe000))); 1244 addName(15, new Font("Arial", Font.BOLD, 40)); 1245 } 1246 } 1247 } 1248 1249 private static void separation() { 1250 switch (feature.type) { 1251 case TSEZNE: 1252 case TSSCRS: 1253 case TSSRON: 1254 if (Renderer.zoom <= 15) 1255 Renderer.lineVector(new LineStyle(Symbols.Mtss)); 1256 else 1257 Renderer.lineVector(new LineStyle(Symbols.Mtss, 20, null, null)); 1258 addName(10, new Font("Arial", Font.BOLD, 150), Symbols.Mline); 1259 break; 1260 case TSELNE: 1261 Renderer.lineVector(new LineStyle(Symbols.Mtss, 20, null, null)); 1262 break; 1263 case TSSLPT: 1264 Renderer.lineSymbols(Areas.LaneArrow, 0.5, null, null, 0, Symbols.Mtss); 1265 break; 1266 case TSSBND: 1267 Renderer.lineVector(new LineStyle(Symbols.Mtss, 20, new float[] {40, 40}, null)); 1268 break; 1269 case ISTZNE: 1270 Renderer.lineSymbols(Areas.Restricted, 1.0, null, null, 0, Symbols.Mtss); 1271 break; 1272 default: 1273 break; 1274 } 1275 } 1276 1277 @SuppressWarnings("unchecked") 1278 private static void shoreline() { 1279 CatSLC cat = (CatSLC) getAttEnum(feature.type, Att.CATSLC); 1280 if ((Renderer.context.ruleset() == RuleSet.ALL) || (Renderer.context.ruleset() == RuleSet.BASE)) { 1281 if ((cat != CatSLC.SLC_SWAY) && (cat != CatSLC.SLC_TWAL)) { 1282 if (Renderer.zoom >= 12) { 1283 Renderer.lineVector(new LineStyle(Color.black, 10, Symbols.Yland)); 1284 } else { 1285 Renderer.lineVector(new LineStyle(Symbols.Yland)); 1286 } 1287 } 1288 } 1289 if ((Renderer.context.ruleset() == RuleSet.ALL) || (Renderer.context.ruleset() == RuleSet.SEAMARK)) { 1290 if (Renderer.zoom >= 12) { 1291 switch (cat) { 1292 case SLC_TWAL: 1293 WatLEV lev = (WatLEV) getAttEnum(feature.type, Att.WATLEV); 1294 if (lev == WatLEV.LEV_CVRS) { 1295 Renderer.lineVector(new LineStyle(Color.black, 10, new float[] {40, 40}, null)); 1296 if (Renderer.zoom >= 15) 1297 Renderer.lineText("(covers)", new Font("Arial", Font.PLAIN, 60), Color.black, 80); 1298 } else { 1299 Renderer.lineVector(new LineStyle(Color.black, 10, null, null)); 1300 } 1301 if (Renderer.zoom >= 15) 1302 Renderer.lineText("Training Wall", new Font("Arial", Font.PLAIN, 60), Color.black, -30); 1303 break; 1304 case SLC_SWAY: 1305 Renderer.lineVector(new LineStyle(Color.black, 2, null, new Color(0xffe000))); 1306 if ((Renderer.zoom >= 16) && feature.objs.containsKey(Obj.SMCFAC)) { 1307 ArrayList<Symbol> symbols = new ArrayList<>(); 1308 ArrayList<CatSCF> scfs = (ArrayList<CatSCF>) getAttList(Obj.SMCFAC, Att.CATSCF); 1309 for (CatSCF scf : scfs) { 1310 symbols.add(Facilities.Cats.get(scf)); 1311 } 1312 Renderer.cluster(symbols); 1313 } 1314 break; 1315 default: 1316 break; 1317 } 1318 } 1319 } 1320 } 1321 1322 @SuppressWarnings("unchecked") 1323 private static void stations() { 1324 if (Renderer.zoom >= 14) { 1325 String str = ""; 1326 switch (feature.type) { 1327 case SISTAT: 1328 Renderer.symbol(Harbours.SignalStation); 1329 str = "SS"; 1330 ArrayList<CatSIT> tcats = (ArrayList<CatSIT>) getAttList(Obj.SISTAT, Att.CATSIT); 1331 switch (tcats.get(0)) { 1332 case SIT_IPT: 1333 str += "(INT)"; 1334 break; 1335 case SIT_PRTE: 1336 str += "(Traffic)"; 1337 break; 1338 case SIT_PRTC: 1339 str += "(Port Control)"; 1340 break; 1341 case SIT_LOCK: 1342 str += "(Lock)"; 1343 break; 1344 case SIT_BRDG: 1345 str += "(Bridge)"; 1346 break; 1347 default: 1348 break; 1349 } 1350 break; 1351 case SISTAW: 1352 Renderer.symbol(Harbours.SignalStation); 1353 str = "SS"; 1354 str = "SS"; 1355 ArrayList<CatSIW> wcats = (ArrayList<CatSIW>) getAttList(Obj.SISTAW, Att.CATSIW); 1356 switch (wcats.get(0)) { 1357 case SIW_STRM: 1358 str += "(Storm)"; 1359 break; 1360 case SIW_WTHR: 1361 str += "(Weather)"; 1362 break; 1363 case SIW_ICE: 1364 str += "(Ice)"; 1365 break; 1366 case SIW_TIDG: 1367 str = "Tide gauge"; 1368 break; 1369 case SIW_TIDS: 1370 str = "Tide scale"; 1371 break; 1372 case SIW_TIDE: 1373 str += "(Tide)"; 1374 break; 1375 case SIW_TSTR: 1376 str += "(Stream)"; 1377 break; 1378 case SIW_DNGR: 1379 str += "(Danger)"; 1380 break; 1381 case SIW_MILY: 1382 str += "(Firing)"; 1383 break; 1384 case SIW_TIME: 1385 str += "(Time)"; 1386 break; 1387 default: 1388 break; 1389 } 1390 break; 1391 case RDOSTA: 1392 case RTPBCN: 1393 Renderer.symbol(Harbours.SignalStation); 1394 Renderer.symbol(Beacons.RadarStation); 1395 break; 1396 case RADRFL: 1397 Renderer.symbol(Topmarks.RadarReflector); 1398 break; 1399 case RADSTA: 1400 Renderer.symbol(Harbours.SignalStation); 1401 Renderer.symbol(Beacons.RadarStation); 1402 Renderer.labelText("Ra", new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -70))); 1403 break; 1404 case PILBOP: 1405 Renderer.symbol(Harbours.Pilot); 1406 addName(15, new Font("Arial", Font.BOLD, 40), Symbols.Msymb, new Delta(Handle.LC, AffineTransform.getTranslateInstance(70, -40))); 1407 CatPIL cat = (CatPIL) getAttEnum(feature.type, Att.CATPIL); 1408 if (cat == CatPIL.PIL_HELI) { 1409 Renderer.labelText("H", new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.LC, AffineTransform.getTranslateInstance(70, 0))); 1410 } 1411 break; 1412 case CGUSTA: 1413 Renderer.symbol(Harbours.SignalStation); 1414 str = "CG"; 1415 if (feature.objs.containsKey(Obj.RSCSTA)) Renderer.symbol(Harbours.Rescue, new Delta(Handle.CC, AffineTransform.getTranslateInstance(130, 0))); 1416 break; 1417 case RSCSTA: 1418 Renderer.symbol(Harbours.Rescue); 1419 break; 1420 default: 1421 break; 1422 } 1423 if ((Renderer.zoom >= 15) && !str.isEmpty()) { 1424 Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.LC, AffineTransform.getTranslateInstance(40, 0))); 1425 } 1426 Signals.addSignals(); 1427 } 1428 } 1429 1430 private static void transits() { 1431 if (Renderer.zoom >= 14) { 1432 if (feature.type == Obj.RECTRC) Renderer.lineVector(new LineStyle(Color.black, 10, null, null)); 1433 else if (feature.type == Obj.NAVLNE) Renderer.lineVector(new LineStyle(Color.black, 10, new float[] {25, 25}, null)); 1434 } 1435 if (Renderer.zoom >= 15) { 1436 String str = ""; 1437 String name = getName(); 1438 if (name != null) 1439 str += name + " "; 1440 Double ort; 1441 if ((ort = (Double) getAttVal(feature.type, Att.ORIENT)) != null) { 1442 str += df.format(ort) + "º"; 1443 if (!str.isEmpty()) 1444 Renderer.lineText(str, new Font("Arial", Font.PLAIN, 80), Color.black, -20); 1445 } 1446 } 1447 } 1448 1449 private static void waterways() { 1450 Renderer.lineVector(new LineStyle(Symbols.Bwater, 20, (feature.geom.prim == Pflag.AREA) ? Symbols.Bwater : null)); 1451 } 1452 1453 private static void wrecks() { 1454 if (Renderer.zoom >= 14) { 1455 switch ((CatWRK) getAttEnum(feature.type, Att.CATWRK)) { 1456 case WRK_DNGR: 1457 case WRK_MSTS: 1458 Renderer.symbol(Areas.WreckD); 1459 break; 1460 case WRK_HULS: 1461 Renderer.symbol(Areas.WreckS); 1462 break; 1463 default: 1464 Renderer.symbol(Areas.WreckND); 1465 } 1466 } 1467 } 1411 1468 } -
applications/editors/josm/plugins/seachart/src/render/Signals.java
r32393 r32394 12 12 import java.awt.Color; 13 13 import java.awt.Font; 14 import java.awt.geom. *;14 import java.awt.geom.AffineTransform; 15 15 import java.text.DecimalFormat; 16 16 import java.util.ArrayList; 17 17 import java.util.EnumMap; 18 18 19 import s57.S57att.Att; 20 import s57.S57map.AttMap; 21 import s57.S57map.ObjTab; 22 import s57.S57obj.Obj; 23 import s57.S57val.BoySHP; 24 import s57.S57val.CatFOG; 19 25 import s57.S57val.CatLIT; 26 import s57.S57val.CatROS; 27 import s57.S57val.CatRTB; 20 28 import s57.S57val.ColCOL; 21 import s57.S57att.*; 22 import s57.S57obj.*; 23 import s57.S57val.*; 24 import s57.S57map.*; 29 import s57.S57val.LitCHR; 25 30 import symbols.Beacons; 26 31 import symbols.Symbols; 32 import symbols.Symbols.Delta; 33 import symbols.Symbols.Handle; 34 import symbols.Symbols.Scheme; 27 35 import symbols.Topmarks; 28 import symbols.Symbols.*; 29 30 public class Signals extends Rules{ 31 32 static final EnumMap<ColCOL, Color> LightColours = new EnumMap<>(ColCOL.class); 33 static { 34 LightColours.put(ColCOL.COL_WHT, new Color(0xffff00)); 35 LightColours.put(ColCOL.COL_RED, new Color(0xff0000)); 36 LightColours.put(ColCOL.COL_GRN, new Color(0x00ff00)); 37 LightColours.put(ColCOL.COL_BLU, new Color(0x0000ff)); 38 LightColours.put(ColCOL.COL_YEL, new Color(0xffff00)); 39 LightColours.put(ColCOL.COL_AMB, new Color(0xffc200)); 40 LightColours.put(ColCOL.COL_VIO, new Color(0xee82ee)); 41 LightColours.put(ColCOL.COL_ORG, Color.orange); 42 LightColours.put(ColCOL.COL_MAG, Color.magenta); 43 } 44 45 static final EnumMap<ColCOL, String> LightLetters = new EnumMap<>(ColCOL.class); 46 static { 47 LightLetters.put(ColCOL.COL_WHT, "W"); 48 LightLetters.put(ColCOL.COL_RED, "R"); 49 LightLetters.put(ColCOL.COL_GRN, "G"); 50 LightLetters.put(ColCOL.COL_BLU, "Bu"); 51 LightLetters.put(ColCOL.COL_YEL, "Y"); 52 LightLetters.put(ColCOL.COL_AMB, "Am"); 53 LightLetters.put(ColCOL.COL_VIO, "Vi"); 54 LightLetters.put(ColCOL.COL_ORG, "Or"); 55 } 56 57 static final EnumMap<LitCHR, String> LightCharacters = new EnumMap<>(LitCHR.class); 58 static { 59 LightCharacters.put(LitCHR.CHR_F, "F"); 60 LightCharacters.put(LitCHR.CHR_FL, "Fl"); 61 LightCharacters.put(LitCHR.CHR_LFL, "LFl"); 62 LightCharacters.put(LitCHR.CHR_Q, "Q"); 63 LightCharacters.put(LitCHR.CHR_VQ, "VQ"); 64 LightCharacters.put(LitCHR.CHR_UQ, "UQ"); 65 LightCharacters.put(LitCHR.CHR_ISO, "Iso"); 66 LightCharacters.put(LitCHR.CHR_OC, "Oc"); 67 LightCharacters.put(LitCHR.CHR_IQ, "IQ"); 68 LightCharacters.put(LitCHR.CHR_IVQ, "IVQ"); 69 LightCharacters.put(LitCHR.CHR_IUQ, "IUQ"); 70 LightCharacters.put(LitCHR.CHR_MO, "Mo"); 71 LightCharacters.put(LitCHR.CHR_FFL, "FFl"); 72 LightCharacters.put(LitCHR.CHR_FLLFL, "FlLFl"); 73 LightCharacters.put(LitCHR.CHR_OCFL, "OcFl"); 74 LightCharacters.put(LitCHR.CHR_FLFL, "FLFl"); 75 LightCharacters.put(LitCHR.CHR_ALOC, "Al.Oc"); 76 LightCharacters.put(LitCHR.CHR_ALLFL, "Al.LFl"); 77 LightCharacters.put(LitCHR.CHR_ALFL, "Al.Fl"); 78 LightCharacters.put(LitCHR.CHR_ALGR, "Al.Gr"); 79 LightCharacters.put(LitCHR.CHR_QLFL, "Q+LFl"); 80 LightCharacters.put(LitCHR.CHR_VQLFL, "VQ+LFl"); 81 LightCharacters.put(LitCHR.CHR_UQLFL, "UQ+LFl"); 82 LightCharacters.put(LitCHR.CHR_AL, "Al"); 83 LightCharacters.put(LitCHR.CHR_ALFFL, "Al.FFl"); 84 } 85 86 static final EnumMap<CatFOG, String> fogSignals = new EnumMap<>(CatFOG.class); 87 static { 88 fogSignals.put(CatFOG.FOG_EXPL, "Explos"); 89 fogSignals.put(CatFOG.FOG_DIA, "Dia"); 90 fogSignals.put(CatFOG.FOG_SIRN, "Siren"); 91 fogSignals.put(CatFOG.FOG_NAUT, "Horn"); 92 fogSignals.put(CatFOG.FOG_REED, "Horn"); 93 fogSignals.put(CatFOG.FOG_TYPH, "Horn"); 94 fogSignals.put(CatFOG.FOG_BELL, "Bell"); 95 fogSignals.put(CatFOG.FOG_WHIS, "Whis"); 96 fogSignals.put(CatFOG.FOG_GONG, "Gong"); 97 fogSignals.put(CatFOG.FOG_HORN, "Horn"); 98 } 99 100 static final DecimalFormat df = new DecimalFormat("#.#"); 101 102 public static void addSignals() { 103 if (feature.objs.containsKey(Obj.RADRFL)) reflectors(); 104 if (feature.objs.containsKey(Obj.FOGSIG)) fogSignals(); 105 if (feature.objs.containsKey(Obj.RTPBCN)) radarStations(); 106 if (feature.objs.containsKey(Obj.RADSTA)) radarStations(); 107 if (feature.objs.containsKey(Obj.RDOSTA)) radioStations(); 108 if (feature.objs.containsKey(Obj.LIGHTS)) lights(); 109 } 110 111 public static void reflectors() { 112 if (Renderer.zoom >= 14) { 113 switch (feature.type) { 114 case BCNLAT: 115 case BCNCAR: 116 case BCNISD: 117 case BCNSAW: 118 case BCNSPP: 119 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) { 120 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -140))); 121 } else { 122 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -80))); 123 } 124 break; 125 case LITFLT: 126 case LITVES: 127 case BOYINB: 128 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) { 129 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -110))); 130 } else { 131 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -60))); 132 } 133 break; 134 case LITMAJ: 135 case LITMIN: 136 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) { 137 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -90))); 138 } else { 139 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -30))); 140 } 141 break; 142 case BOYLAT: 143 case BOYCAR: 144 case BOYISD: 145 case BOYSAW: 146 case BOYSPP: 147 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) { 148 if (testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_PILR) || testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_SPAR)) { 149 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(50, -160))); 150 } else { 151 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(25, -80))); 152 } 153 } else { 154 if (testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_PILR) || testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_SPAR)) { 155 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(30, -100))); 156 } else { 157 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(10, -50))); 158 } 159 } 160 break; 161 default: 162 break; 163 } 164 } 165 } 166 167 public static void fogSignals() { 168 if (Renderer.zoom >= 11) 169 Renderer.symbol(Beacons.FogSignal); 170 if (Renderer.zoom >= 15) { 171 AttMap atts = feature.objs.get(Obj.FOGSIG).get(0); 172 if (atts != null) { 173 String str = ""; 174 if (atts.containsKey(Att.CATFOG)) { 175 str += fogSignals.get(((ArrayList<?>) (atts.get(Att.CATFOG).val)).get(0)); 176 } 177 if (atts.containsKey(Att.SIGGRP)) { 178 str += "(" + atts.get(Att.SIGGRP).val + ")"; 179 } else { 180 str += " "; 181 } 182 if (atts.containsKey(Att.SIGPER)) { 183 str += df.format(atts.get(Att.SIGPER).val) + "s"; 184 } 185 if (atts.containsKey(Att.VALMXR)) { 186 str += df.format(atts.get(Att.VALMXR).val) + "M"; 187 } 188 if (!str.isEmpty()) { 189 Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-60, -30))); 190 } 191 } 192 } 193 } 194 195 public static void radarStations() { 196 if (Renderer.zoom >= 11) 197 Renderer.symbol(Beacons.RadarStation); 198 if (Renderer.zoom >= 15) { 199 String bstr = ""; 200 CatRTB cat = (CatRTB) getAttEnum(Obj.RTPBCN, Att.CATRTB); 201 String wal = getAttStr(Obj.RTPBCN, Att.RADWAL); 202 switch (cat) { 203 case RTB_RAMK: 204 bstr += " Ramark"; 205 break; 206 case RTB_RACN: 207 bstr += " Racon"; 208 String astr = getAttStr(Obj.RTPBCN, Att.SIGGRP); 209 if (!astr.isEmpty()) { 210 bstr += "(" + astr + ")"; 211 } 212 Double per = (Double) getAttVal(Obj.RTPBCN, Att.SIGPER); 213 Double mxr = (Double) getAttVal(Obj.RTPBCN, Att.VALMXR); 214 if ((per != null) || (mxr != null)) { 215 bstr += (astr.isEmpty() ? " " : ""); 216 if (per != null) 217 bstr += (per != 0) ? per.toString() + "s" : ""; 218 if (mxr != null) 219 bstr += (mxr != 0) ? mxr.toString() + "M" : ""; 220 } 221 break; 222 default: 223 break; 224 } 225 if (!wal.isEmpty()) { 226 switch (wal) { 227 case "0.03-X": 228 bstr += "(3cm)"; 229 break; 230 case "0.10-S": 231 bstr += "(10cm)"; 232 break; 233 } 234 } 235 if (!bstr.isEmpty()) { 236 Renderer.labelText(bstr, new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -70))); 237 } 238 } 239 } 240 241 @SuppressWarnings("unchecked") 242 public static void radioStations() { 243 boolean vais = false; 244 String bstr = ""; 245 if (Renderer.zoom >= 11) { 246 ArrayList<CatROS> cats = (ArrayList<CatROS>) getAttList(Obj.RDOSTA, Att.CATROS); 247 for (CatROS ros : cats) { 248 switch (ros) { 249 case ROS_OMNI: 250 bstr += " RC"; 251 break; 252 case ROS_DIRL: 253 bstr += " RD"; 254 break; 255 case ROS_ROTP: 256 bstr += " RW"; 257 break; 258 case ROS_CNSL: 259 bstr += " Consol"; 260 break; 261 case ROS_RDF: 262 bstr += " RG"; 263 break; 264 case ROS_QTA: 265 bstr += " R"; 266 break; 267 case ROS_AERO: 268 bstr += " AeroRC"; 269 break; 270 case ROS_DECA: 271 bstr += " Decca"; 272 break; 273 case ROS_LORN: 274 bstr += " Loran"; 275 break; 276 case ROS_DGPS: 277 bstr += " DGPS"; 278 break; 279 case ROS_TORN: 280 bstr += " Toran"; 281 break; 282 case ROS_OMGA: 283 bstr += " Omega"; 284 break; 285 case ROS_SYLD: 286 bstr += " Syledis"; 287 break; 288 case ROS_CHKA: 289 bstr += " Chiaka"; 290 break; 291 case ROS_PCOM: 292 case ROS_COMB: 293 case ROS_FACS: 294 case ROS_TIME: 295 break; 296 case ROS_PAIS: 297 case ROS_SAIS: 298 bstr += " AIS"; 299 break; 300 case ROS_VAIS: 301 vais = true; 302 break; 303 case ROS_VANC: 304 vais = true; 305 Renderer.symbol(Topmarks.TopNorth, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 306 break; 307 case ROS_VASC: 308 vais = true; 309 Renderer.symbol(Topmarks.TopSouth, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 310 break; 311 case ROS_VAEC: 312 vais = true; 313 Renderer.symbol(Topmarks.TopEast, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 314 break; 315 case ROS_VAWC: 316 vais = true; 317 Renderer.symbol(Topmarks.TopWest, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 318 break; 319 case ROS_VAPL: 320 vais = true; 321 Renderer.symbol(Topmarks.TopCan, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 322 break; 323 case ROS_VASL: 324 vais = true; 325 Renderer.symbol(Topmarks.TopCone, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 326 break; 327 case ROS_VAID: 328 vais = true; 329 Renderer.symbol(Topmarks.TopIsol, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 330 break; 331 case ROS_VASW: 332 vais = true; 333 Renderer.symbol(Topmarks.TopSphere, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 334 break; 335 case ROS_VASP: 336 vais = true; 337 Renderer.symbol(Topmarks.TopX, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 338 break; 339 case ROS_VAWK: 340 vais = true; 341 Renderer.symbol(Topmarks.TopCross, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 342 break; 343 default: 344 break; 345 } 346 } 347 if (!vais) { 348 Renderer.symbol(Beacons.RadarStation); 349 } 350 } 351 if (Renderer.zoom >= 15) { 352 if (vais) { 353 Renderer.labelText("V-AIS", new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, 70))); 354 } 355 if (!bstr.isEmpty()) { 356 Renderer.labelText(bstr, new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -110))); 357 } 358 } 359 } 360 361 class Sect { 362 int dir; 363 LitCHR chr; 364 ColCOL col; 365 ColCOL alt; 366 String grp; 367 double per; 368 double rng; 369 } 370 371 @SuppressWarnings("unchecked") 372 public static void lights() { 373 Enum<ColCOL> col = null; 374 Enum<ColCOL> tcol = null; 375 ObjTab lights = feature.objs.get(Obj.LIGHTS); 376 for (AttMap atts : lights.values()) { 377 if (atts.containsKey(Att.COLOUR)) { 378 ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val; 379 if (cols.size() == 1) { 380 tcol = cols.get(0); 381 if (col == null) { 382 col = tcol; 383 } else if (tcol != col) { 384 col = ColCOL.COL_MAG; 385 break; 386 } 387 } else { 388 col = ColCOL.COL_MAG; 389 break; 390 } 391 } 392 } 393 Renderer.symbol(Beacons.LightFlare, new Scheme(LightColours.get(col)), new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.toRadians(120)))); 394 if (Renderer.zoom >= 12) { 395 String str = ""; 396 if (lights.get(1) != null) { 397 for (AttMap atts : lights.values()) { 398 Enum<ColCOL> col1 = null; 399 Enum<ColCOL> col2 = null; 400 double radius = 0.2; 401 double s1 = 361; 402 double s2 = 361; 403 Double dir = null; 404 if (atts.containsKey(Att.COLOUR)) { 405 ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val; 406 col1 = cols.get(0); 407 if (cols.size() > 1) 408 col2 = cols.get(1); 409 } else { 410 continue; 411 } 412 if (atts.containsKey(Att.LITRAD)) { 413 radius = (Double) atts.get(Att.LITRAD).val; 414 } 415 if (atts.containsKey(Att.CATLIT)) { 416 ArrayList<CatLIT> cats = (ArrayList<CatLIT>) atts.get(Att.CATLIT).val; 417 if (cats.contains(CatLIT.LIT_DIR)) { 418 if (atts.containsKey(Att.ORIENT)) { 419 dir = (Double) atts.get(Att.ORIENT).val; 420 s1 = ((dir - 4) + 360) % 360; 421 s2 = (dir + 4) % 360; 422 for (AttMap satts : lights.values()) { 423 double srad = 0.2; 424 double ss1 = 361; 425 double ss2 = 361; 426 Double sdir = null; 427 if (satts == atts) 428 continue; 429 if (satts.containsKey(Att.LITRAD)) { 430 srad = (Double) satts.get(Att.LITRAD).val; 431 } 432 if (srad == radius) { 433 ArrayList<CatLIT> scats = (satts.containsKey(Att.CATLIT)) ? (ArrayList<CatLIT>) satts.get(Att.CATLIT).val : new ArrayList<CatLIT>(); 434 if (scats.contains(CatLIT.LIT_DIR)) { 435 if (satts.containsKey(Att.ORIENT)) { 436 sdir = (Double) satts.get(Att.ORIENT).val; 437 ss1 = sdir; 438 ss2 = sdir; 439 } 440 } else { 441 if (satts.containsKey(Att.SECTR1)) { 442 ss1 = (Double) satts.get(Att.SECTR1).val; 443 } 444 if (satts.containsKey(Att.SECTR2)) { 445 ss2 = (Double) satts.get(Att.SECTR2).val; 446 } 447 } 448 if ((ss1 > 360) || (ss2 > 360)) 449 continue; 450 if (sdir != null) { 451 if (((dir - sdir + 360) % 360) < 8) { 452 s1 = ((((sdir > dir) ? 360 : 0) + sdir + dir) / 2) % 360; 453 } 454 if (((sdir - dir + 360) % 360) < 8) { 455 s2 = ((((dir > sdir) ? 360 : 0) + sdir + dir) / 2) % 360; 456 } 457 } else { 458 if (((dir - ss2 + 360) % 360) < 4) { 459 s1 = ss2; 460 } 461 if (((ss1 - dir + 360) % 360) < 4) { 462 s2 = ss1; 463 } 464 } 465 } 466 } 467 } 468 } 469 } 470 if ((s1 > 360) && atts.containsKey(Att.SECTR1)) { 471 s1 = (Double) atts.get(Att.SECTR1).val; 472 } else if (dir == null) { 473 continue; 474 } 475 if ((s2 > 360) && atts.containsKey(Att.SECTR2)) { 476 s2 = (Double) atts.get(Att.SECTR2).val; 477 } else if (dir == null) { 478 continue; 479 } 480 str = ""; 481 if (atts.containsKey(Att.LITCHR)) { 482 str += LightCharacters.get(((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0)); 483 } 484 if (atts.containsKey(Att.SIGGRP)) { 485 str += "(" + atts.get(Att.SIGGRP).val + ")"; 486 } else if (!str.isEmpty()) { 487 str += "."; 488 } 489 if (atts.containsKey(Att.COLOUR)) { 490 ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val; 491 str += LightLetters.get(cols.get(0)); 492 if (cols.size() > 1) 493 str += LightLetters.get(cols.get(1)); 494 } 495 if (atts.containsKey(Att.SIGPER)) { 496 str += "." + df.format(atts.get(Att.SIGPER).val) + "s"; 497 } 498 if ((s1 <= 360) && (s2 <= 360) && (s1 != s2)) 499 Renderer.lightSector(LightColours.get(col1), LightColours.get(col2), radius, s1, s2, dir, (Renderer.zoom >= 15) ? str : ""); 500 } 501 if (Renderer.zoom >= 15) { 502 class LitSect { 503 boolean dir; 504 LitCHR chr; 505 ColCOL col; 506 String grp; 507 double per; 508 double rng; 509 double hgt; 510 } 511 ArrayList<LitSect> litatts = new ArrayList<>(); 512 for (AttMap atts : lights.values()) { 513 LitSect sect = new LitSect(); 514 sect.dir = (atts.containsKey(Att.CATLIT) && ((ArrayList<CatLIT>) atts.get(Att.CATLIT).val).contains(CatLIT.LIT_DIR)); 515 sect.chr = atts.containsKey(Att.LITCHR) ? ((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0) : LitCHR.CHR_UNKN; 516 switch (sect.chr) { 517 case CHR_AL: 518 sect.chr = LitCHR.CHR_F; 519 break; 520 case CHR_ALOC: 521 sect.chr = LitCHR.CHR_OC; 522 break; 523 case CHR_ALLFL: 524 sect.chr = LitCHR.CHR_LFL; 525 break; 526 case CHR_ALFL: 527 sect.chr = LitCHR.CHR_FL; 528 break; 529 case CHR_ALFFL: 530 sect.chr = LitCHR.CHR_FFL; 531 break; 532 default: 533 break; 534 } 535 sect.grp = atts.containsKey(Att.SIGGRP) ? (String) atts.get(Att.SIGGRP).val : ""; 536 sect.per = atts.containsKey(Att.SIGPER) ? (Double) atts.get(Att.SIGPER).val : 0.0; 537 sect.rng = atts.containsKey(Att.VALNMR) ? (Double) atts.get(Att.VALNMR).val : 0.0; 538 sect.hgt = atts.containsKey(Att.HEIGHT) ? (Double) atts.get(Att.HEIGHT).val : 0.0; 539 ArrayList<ColCOL> cols = (ArrayList<ColCOL>) (atts.containsKey(Att.COLOUR) ? atts.get(Att.COLOUR).val : new ArrayList<>()); 540 sect.col = cols.size() > 0 ? cols.get(0) : ColCOL.COL_UNK; 541 if ((sect.chr != LitCHR.CHR_UNKN) && (sect.col != null)) 542 litatts.add(sect); 543 } 544 ArrayList<ArrayList<LitSect>> groupings = new ArrayList<>(); 545 for (LitSect lit : litatts) { 546 boolean found = false; 547 for (ArrayList<LitSect> group : groupings) { 548 LitSect mem = group.get(0); 549 if ((lit.dir == mem.dir) && (lit.chr == mem.chr) && (lit.grp.equals(mem.grp)) && (lit.per == mem.per) && (lit.hgt == mem.hgt)) { 550 group.add(lit); 551 found = true; 552 } 553 } 554 if (!found) { 555 ArrayList<LitSect> tmp = new ArrayList<>(); 556 tmp.add(lit); 557 groupings.add(tmp); 558 } 559 } 560 for (boolean moved = true; moved;) { 561 moved = false; 562 for (int i = 0; i < groupings.size() - 1; i++) { 563 if (groupings.get(i).size() < groupings.get(i + 1).size()) { 564 ArrayList<LitSect> tmp = groupings.remove(i); 565 groupings.add(i + 1, tmp); 566 moved = true; 567 } 568 } 569 } 570 class ColRng { 571 ColCOL col; 572 double rng; 573 574 public ColRng(ColCOL c, double r) { 575 col = c; 576 rng = r; 577 } 578 } 579 int y = -30; 580 for (ArrayList<LitSect> group : groupings) { 581 ArrayList<ColRng> colrng = new ArrayList<>(); 582 for (LitSect lit : group) { 583 boolean found = false; 584 for (ColRng cr : colrng) { 585 if (cr.col == lit.col) { 586 if (lit.rng > cr.rng) { 587 cr.rng = lit.rng; 588 } 589 found = true; 590 } 591 } 592 if (!found) { 593 colrng.add(new ColRng(lit.col, lit.rng)); 594 } 595 } 596 for (boolean moved = true; moved;) { 597 moved = false; 598 for (int i = 0; i < colrng.size() - 1; i++) { 599 if (colrng.get(i).rng < colrng.get(i + 1).rng) { 600 ColRng tmp = colrng.remove(i); 601 colrng.add(i + 1, tmp); 602 moved = true; 603 } 604 } 605 } 606 LitSect tmp = group.get(0); 607 str = (tmp.dir) ? "Dir" : ""; 608 str += LightCharacters.get(tmp.chr); 609 if (!tmp.grp.isEmpty()) 610 str += "(" + tmp.grp + ")"; 611 else 612 str += "."; 613 for (ColRng cr : colrng) { 614 str += LightLetters.get(cr.col); 615 } 616 if ((tmp.per > 0) || (tmp.hgt > 0) || (colrng.get(0).rng > 0)) 617 str += "."; 618 if (tmp.per > 0) 619 str += df.format(tmp.per) + "s"; 620 if (tmp.hgt > 0) 621 str += df.format(tmp.hgt) + "m"; 622 if (colrng.get(0).rng > 0) 623 str += df.format(colrng.get(0).rng) + ((colrng.size() > 1) ? ((colrng.size() > 2) ? ("-" + df.format(colrng.get(colrng.size() - 1).rng)) : ("/" + df.format(colrng.get(1).rng))) : "") + "M"; 624 Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.TL, AffineTransform.getTranslateInstance(60, y))); 625 y += 40; 626 str = ""; 627 } 628 } 629 } else { 630 if (Renderer.zoom >= 15) { 631 AttMap atts = lights.get(0); 632 ArrayList<CatLIT> cats = new ArrayList<>(); 633 if (atts.containsKey(Att.CATLIT)) { 634 cats = (ArrayList<CatLIT>) atts.get(Att.CATLIT).val; 635 } 636 str = (cats.contains(CatLIT.LIT_DIR)) ? "Dir" : ""; 637 str += (atts.containsKey(Att.MLTYLT)) ? atts.get(Att.MLTYLT).val : ""; 638 if (atts.containsKey(Att.LITCHR)) { 639 LitCHR chr = ((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0); 640 if (atts.containsKey(Att.SIGGRP)) { 641 String grp = (String) atts.get(Att.SIGGRP).val; 642 switch (chr) { 643 case CHR_QLFL: 644 str += String.format("Q(%s)+LFl", grp); 645 break; 646 case CHR_VQLFL: 647 str += String.format("VQ(%s)+LFl", grp); 648 break; 649 case CHR_UQLFL: 650 str += String.format("UQ(%s)+LFl", grp); 651 break; 652 default: 653 str += String.format("%s(%s)", LightCharacters.get(chr), grp); 654 break; 655 } 656 } else { 657 str += LightCharacters.get(chr); 658 } 659 } 660 if (atts.containsKey(Att.COLOUR)) { 661 ArrayList<ColCOL> cols = (ArrayList<ColCOL>) atts.get(Att.COLOUR).val; 662 if (!((cols.size() == 1) && (cols.get(0) == ColCOL.COL_WHT))) { 663 if (!str.isEmpty() && !str.endsWith(")")) { 664 str += "."; 665 } 666 for (ColCOL acol : cols) { 667 str += LightLetters.get(acol); 668 } 669 } 670 } 671 str += (cats.contains(CatLIT.LIT_VERT)) ? "(vert)" : ""; 672 str += (cats.contains(CatLIT.LIT_HORI)) ? "(hor)" : ""; 673 str += (!str.isEmpty() && (atts.containsKey(Att.SIGPER) || atts.containsKey(Att.HEIGHT) || atts.containsKey(Att.VALMXR)) && !str.endsWith(")")) ? "." : ""; 674 str += (atts.containsKey(Att.SIGPER)) ? df.format(atts.get(Att.SIGPER).val) + "s" : ""; 675 str += (atts.containsKey(Att.HEIGHT)) ? df.format(atts.get(Att.HEIGHT).val) + "m" : ""; 676 str += (atts.containsKey(Att.VALNMR)) ? df.format(atts.get(Att.VALNMR).val) + "M" : ""; 677 str += (cats.contains(CatLIT.LIT_FRNT)) ? "(Front)" : ""; 678 str += (cats.contains(CatLIT.LIT_REAR)) ? "(Rear)" : ""; 679 str += (cats.contains(CatLIT.LIT_UPPR)) ? "(Upper)" : ""; 680 str += (cats.contains(CatLIT.LIT_LOWR)) ? "(Lower)" : ""; 681 Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.TL, AffineTransform.getTranslateInstance(60, -30))); 682 } 683 } 684 } 685 } 36 37 public class Signals extends Rules { 38 39 static final EnumMap<ColCOL, Color> LightColours = new EnumMap<>(ColCOL.class); 40 static { 41 LightColours.put(ColCOL.COL_WHT, new Color(0xffff00)); 42 LightColours.put(ColCOL.COL_RED, new Color(0xff0000)); 43 LightColours.put(ColCOL.COL_GRN, new Color(0x00ff00)); 44 LightColours.put(ColCOL.COL_BLU, new Color(0x0000ff)); 45 LightColours.put(ColCOL.COL_YEL, new Color(0xffff00)); 46 LightColours.put(ColCOL.COL_AMB, new Color(0xffc200)); 47 LightColours.put(ColCOL.COL_VIO, new Color(0xee82ee)); 48 LightColours.put(ColCOL.COL_ORG, Color.orange); 49 LightColours.put(ColCOL.COL_MAG, Color.magenta); 50 } 51 52 static final EnumMap<ColCOL, String> LightLetters = new EnumMap<>(ColCOL.class); 53 static { 54 LightLetters.put(ColCOL.COL_WHT, "W"); 55 LightLetters.put(ColCOL.COL_RED, "R"); 56 LightLetters.put(ColCOL.COL_GRN, "G"); 57 LightLetters.put(ColCOL.COL_BLU, "Bu"); 58 LightLetters.put(ColCOL.COL_YEL, "Y"); 59 LightLetters.put(ColCOL.COL_AMB, "Am"); 60 LightLetters.put(ColCOL.COL_VIO, "Vi"); 61 LightLetters.put(ColCOL.COL_ORG, "Or"); 62 } 63 64 static final EnumMap<LitCHR, String> LightCharacters = new EnumMap<>(LitCHR.class); 65 static { 66 LightCharacters.put(LitCHR.CHR_F, "F"); 67 LightCharacters.put(LitCHR.CHR_FL, "Fl"); 68 LightCharacters.put(LitCHR.CHR_LFL, "LFl"); 69 LightCharacters.put(LitCHR.CHR_Q, "Q"); 70 LightCharacters.put(LitCHR.CHR_VQ, "VQ"); 71 LightCharacters.put(LitCHR.CHR_UQ, "UQ"); 72 LightCharacters.put(LitCHR.CHR_ISO, "Iso"); 73 LightCharacters.put(LitCHR.CHR_OC, "Oc"); 74 LightCharacters.put(LitCHR.CHR_IQ, "IQ"); 75 LightCharacters.put(LitCHR.CHR_IVQ, "IVQ"); 76 LightCharacters.put(LitCHR.CHR_IUQ, "IUQ"); 77 LightCharacters.put(LitCHR.CHR_MO, "Mo"); 78 LightCharacters.put(LitCHR.CHR_FFL, "FFl"); 79 LightCharacters.put(LitCHR.CHR_FLLFL, "FlLFl"); 80 LightCharacters.put(LitCHR.CHR_OCFL, "OcFl"); 81 LightCharacters.put(LitCHR.CHR_FLFL, "FLFl"); 82 LightCharacters.put(LitCHR.CHR_ALOC, "Al.Oc"); 83 LightCharacters.put(LitCHR.CHR_ALLFL, "Al.LFl"); 84 LightCharacters.put(LitCHR.CHR_ALFL, "Al.Fl"); 85 LightCharacters.put(LitCHR.CHR_ALGR, "Al.Gr"); 86 LightCharacters.put(LitCHR.CHR_QLFL, "Q+LFl"); 87 LightCharacters.put(LitCHR.CHR_VQLFL, "VQ+LFl"); 88 LightCharacters.put(LitCHR.CHR_UQLFL, "UQ+LFl"); 89 LightCharacters.put(LitCHR.CHR_AL, "Al"); 90 LightCharacters.put(LitCHR.CHR_ALFFL, "Al.FFl"); 91 } 92 93 static final EnumMap<CatFOG, String> fogSignals = new EnumMap<>(CatFOG.class); 94 static { 95 fogSignals.put(CatFOG.FOG_EXPL, "Explos"); 96 fogSignals.put(CatFOG.FOG_DIA, "Dia"); 97 fogSignals.put(CatFOG.FOG_SIRN, "Siren"); 98 fogSignals.put(CatFOG.FOG_NAUT, "Horn"); 99 fogSignals.put(CatFOG.FOG_REED, "Horn"); 100 fogSignals.put(CatFOG.FOG_TYPH, "Horn"); 101 fogSignals.put(CatFOG.FOG_BELL, "Bell"); 102 fogSignals.put(CatFOG.FOG_WHIS, "Whis"); 103 fogSignals.put(CatFOG.FOG_GONG, "Gong"); 104 fogSignals.put(CatFOG.FOG_HORN, "Horn"); 105 } 106 107 static final DecimalFormat df = new DecimalFormat("#.#"); 108 109 public static void addSignals() { 110 if (feature.objs.containsKey(Obj.RADRFL)) reflectors(); 111 if (feature.objs.containsKey(Obj.FOGSIG)) fogSignals(); 112 if (feature.objs.containsKey(Obj.RTPBCN)) radarStations(); 113 if (feature.objs.containsKey(Obj.RADSTA)) radarStations(); 114 if (feature.objs.containsKey(Obj.RDOSTA)) radioStations(); 115 if (feature.objs.containsKey(Obj.LIGHTS)) lights(); 116 } 117 118 public static void reflectors() { 119 if (Renderer.zoom >= 14) { 120 switch (feature.type) { 121 case BCNLAT: 122 case BCNCAR: 123 case BCNISD: 124 case BCNSAW: 125 case BCNSPP: 126 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) { 127 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -140))); 128 } else { 129 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -80))); 130 } 131 break; 132 case LITFLT: 133 case LITVES: 134 case BOYINB: 135 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) { 136 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -110))); 137 } else { 138 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -60))); 139 } 140 break; 141 case LITMAJ: 142 case LITMIN: 143 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) { 144 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -90))); 145 } else { 146 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -30))); 147 } 148 break; 149 case BOYLAT: 150 case BOYCAR: 151 case BOYISD: 152 case BOYSAW: 153 case BOYSPP: 154 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) { 155 if (testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_PILR) || testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_SPAR)) { 156 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(50, -160))); 157 } else { 158 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(25, -80))); 159 } 160 } else { 161 if (testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_PILR) || testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_SPAR)) { 162 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(30, -100))); 163 } else { 164 Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(10, -50))); 165 } 166 } 167 break; 168 default: 169 break; 170 } 171 } 172 } 173 174 public static void fogSignals() { 175 if (Renderer.zoom >= 11) 176 Renderer.symbol(Beacons.FogSignal); 177 if (Renderer.zoom >= 15) { 178 AttMap atts = feature.objs.get(Obj.FOGSIG).get(0); 179 if (atts != null) { 180 String str = ""; 181 if (atts.containsKey(Att.CATFOG)) { 182 str += fogSignals.get(((ArrayList<?>) (atts.get(Att.CATFOG).val)).get(0)); 183 } 184 if (atts.containsKey(Att.SIGGRP)) { 185 str += "(" + atts.get(Att.SIGGRP).val + ")"; 186 } else { 187 str += " "; 188 } 189 if (atts.containsKey(Att.SIGPER)) { 190 str += df.format(atts.get(Att.SIGPER).val) + "s"; 191 } 192 if (atts.containsKey(Att.VALMXR)) { 193 str += df.format(atts.get(Att.VALMXR).val) + "M"; 194 } 195 if (!str.isEmpty()) { 196 Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-60, -30))); 197 } 198 } 199 } 200 } 201 202 public static void radarStations() { 203 if (Renderer.zoom >= 11) 204 Renderer.symbol(Beacons.RadarStation); 205 if (Renderer.zoom >= 15) { 206 String bstr = ""; 207 CatRTB cat = (CatRTB) getAttEnum(Obj.RTPBCN, Att.CATRTB); 208 String wal = getAttStr(Obj.RTPBCN, Att.RADWAL); 209 switch (cat) { 210 case RTB_RAMK: 211 bstr += " Ramark"; 212 break; 213 case RTB_RACN: 214 bstr += " Racon"; 215 String astr = getAttStr(Obj.RTPBCN, Att.SIGGRP); 216 if (!astr.isEmpty()) { 217 bstr += "(" + astr + ")"; 218 } 219 Double per = (Double) getAttVal(Obj.RTPBCN, Att.SIGPER); 220 Double mxr = (Double) getAttVal(Obj.RTPBCN, Att.VALMXR); 221 if ((per != null) || (mxr != null)) { 222 bstr += (astr.isEmpty() ? " " : ""); 223 if (per != null) 224 bstr += (per != 0) ? per.toString() + "s" : ""; 225 if (mxr != null) 226 bstr += (mxr != 0) ? mxr.toString() + "M" : ""; 227 } 228 break; 229 default: 230 break; 231 } 232 if (!wal.isEmpty()) { 233 switch (wal) { 234 case "0.03-X": 235 bstr += "(3cm)"; 236 break; 237 case "0.10-S": 238 bstr += "(10cm)"; 239 break; 240 } 241 } 242 if (!bstr.isEmpty()) { 243 Renderer.labelText(bstr, new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -70))); 244 } 245 } 246 } 247 248 @SuppressWarnings("unchecked") 249 public static void radioStations() { 250 boolean vais = false; 251 String bstr = ""; 252 if (Renderer.zoom >= 11) { 253 ArrayList<CatROS> cats = (ArrayList<CatROS>) getAttList(Obj.RDOSTA, Att.CATROS); 254 for (CatROS ros : cats) { 255 switch (ros) { 256 case ROS_OMNI: 257 bstr += " RC"; 258 break; 259 case ROS_DIRL: 260 bstr += " RD"; 261 break; 262 case ROS_ROTP: 263 bstr += " RW"; 264 break; 265 case ROS_CNSL: 266 bstr += " Consol"; 267 break; 268 case ROS_RDF: 269 bstr += " RG"; 270 break; 271 case ROS_QTA: 272 bstr += " R"; 273 break; 274 case ROS_AERO: 275 bstr += " AeroRC"; 276 break; 277 case ROS_DECA: 278 bstr += " Decca"; 279 break; 280 case ROS_LORN: 281 bstr += " Loran"; 282 break; 283 case ROS_DGPS: 284 bstr += " DGPS"; 285 break; 286 case ROS_TORN: 287 bstr += " Toran"; 288 break; 289 case ROS_OMGA: 290 bstr += " Omega"; 291 break; 292 case ROS_SYLD: 293 bstr += " Syledis"; 294 break; 295 case ROS_CHKA: 296 bstr += " Chiaka"; 297 break; 298 case ROS_PCOM: 299 case ROS_COMB: 300 case ROS_FACS: 301 case ROS_TIME: 302 break; 303 case ROS_PAIS: 304 case ROS_SAIS: 305 bstr += " AIS"; 306 break; 307 case ROS_VAIS: 308 vais = true; 309 break; 310 case ROS_VANC: 311 vais = true; 312 Renderer.symbol(Topmarks.TopNorth, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 313 break; 314 case ROS_VASC: 315 vais = true; 316 Renderer.symbol(Topmarks.TopSouth, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 317 break; 318 case ROS_VAEC: 319 vais = true; 320 Renderer.symbol(Topmarks.TopEast, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 321 break; 322 case ROS_VAWC: 323 vais = true; 324 Renderer.symbol(Topmarks.TopWest, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 325 break; 326 case ROS_VAPL: 327 vais = true; 328 Renderer.symbol(Topmarks.TopCan, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 329 break; 330 case ROS_VASL: 331 vais = true; 332 Renderer.symbol(Topmarks.TopCone, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 333 break; 334 case ROS_VAID: 335 vais = true; 336 Renderer.symbol(Topmarks.TopIsol, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 337 break; 338 case ROS_VASW: 339 vais = true; 340 Renderer.symbol(Topmarks.TopSphere, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 341 break; 342 case ROS_VASP: 343 vais = true; 344 Renderer.symbol(Topmarks.TopX, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 345 break; 346 case ROS_VAWK: 347 vais = true; 348 Renderer.symbol(Topmarks.TopCross, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25))); 349 break; 350 default: 351 break; 352 } 353 } 354 if (!vais) { 355 Renderer.symbol(Beacons.RadarStation); 356 } 357 } 358 if (Renderer.zoom >= 15) { 359 if (vais) { 360 Renderer.labelText("V-AIS", new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, 70))); 361 } 362 if (!bstr.isEmpty()) { 363 Renderer.labelText(bstr, new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -110))); 364 } 365 } 366 } 367 368 class Sect { 369 int dir; 370 LitCHR chr; 371 ColCOL col; 372 ColCOL alt; 373 String grp; 374 double per; 375 double rng; 376 } 377 378 @SuppressWarnings("unchecked") 379 public static void lights() { 380 Enum<ColCOL> col = null; 381 Enum<ColCOL> tcol = null; 382 ObjTab lights = feature.objs.get(Obj.LIGHTS); 383 for (AttMap atts : lights.values()) { 384 if (atts.containsKey(Att.COLOUR)) { 385 ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val; 386 if (cols.size() == 1) { 387 tcol = cols.get(0); 388 if (col == null) { 389 col = tcol; 390 } else if (tcol != col) { 391 col = ColCOL.COL_MAG; 392 break; 393 } 394 } else { 395 col = ColCOL.COL_MAG; 396 break; 397 } 398 } 399 } 400 Renderer.symbol(Beacons.LightFlare, new Scheme(LightColours.get(col)), new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.toRadians(120)))); 401 if (Renderer.zoom >= 12) { 402 String str = ""; 403 if (lights.get(1) != null) { 404 for (AttMap atts : lights.values()) { 405 Enum<ColCOL> col1 = null; 406 Enum<ColCOL> col2 = null; 407 double radius = 0.2; 408 double s1 = 361; 409 double s2 = 361; 410 Double dir = null; 411 if (atts.containsKey(Att.COLOUR)) { 412 ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val; 413 col1 = cols.get(0); 414 if (cols.size() > 1) 415 col2 = cols.get(1); 416 } else { 417 continue; 418 } 419 if (atts.containsKey(Att.LITRAD)) { 420 radius = (Double) atts.get(Att.LITRAD).val; 421 } 422 if (atts.containsKey(Att.CATLIT)) { 423 ArrayList<CatLIT> cats = (ArrayList<CatLIT>) atts.get(Att.CATLIT).val; 424 if (cats.contains(CatLIT.LIT_DIR)) { 425 if (atts.containsKey(Att.ORIENT)) { 426 dir = (Double) atts.get(Att.ORIENT).val; 427 s1 = ((dir - 4) + 360) % 360; 428 s2 = (dir + 4) % 360; 429 for (AttMap satts : lights.values()) { 430 double srad = 0.2; 431 double ss1 = 361; 432 double ss2 = 361; 433 Double sdir = null; 434 if (satts == atts) 435 continue; 436 if (satts.containsKey(Att.LITRAD)) { 437 srad = (Double) satts.get(Att.LITRAD).val; 438 } 439 if (srad == radius) { 440 ArrayList<CatLIT> scats = (satts.containsKey(Att.CATLIT)) ? (ArrayList<CatLIT>) satts.get(Att.CATLIT).val : new ArrayList<CatLIT>(); 441 if (scats.contains(CatLIT.LIT_DIR)) { 442 if (satts.containsKey(Att.ORIENT)) { 443 sdir = (Double) satts.get(Att.ORIENT).val; 444 ss1 = sdir; 445 ss2 = sdir; 446 } 447 } else { 448 if (satts.containsKey(Att.SECTR1)) { 449 ss1 = (Double) satts.get(Att.SECTR1).val; 450 } 451 if (satts.containsKey(Att.SECTR2)) { 452 ss2 = (Double) satts.get(Att.SECTR2).val; 453 } 454 } 455 if ((ss1 > 360) || (ss2 > 360)) 456 continue; 457 if (sdir != null) { 458 if (((dir - sdir + 360) % 360) < 8) { 459 s1 = ((((sdir > dir) ? 360 : 0) + sdir + dir) / 2) % 360; 460 } 461 if (((sdir - dir + 360) % 360) < 8) { 462 s2 = ((((dir > sdir) ? 360 : 0) + sdir + dir) / 2) % 360; 463 } 464 } else { 465 if (((dir - ss2 + 360) % 360) < 4) { 466 s1 = ss2; 467 } 468 if (((ss1 - dir + 360) % 360) < 4) { 469 s2 = ss1; 470 } 471 } 472 } 473 } 474 } 475 } 476 } 477 if ((s1 > 360) && atts.containsKey(Att.SECTR1)) { 478 s1 = (Double) atts.get(Att.SECTR1).val; 479 } else if (dir == null) { 480 continue; 481 } 482 if ((s2 > 360) && atts.containsKey(Att.SECTR2)) { 483 s2 = (Double) atts.get(Att.SECTR2).val; 484 } else if (dir == null) { 485 continue; 486 } 487 str = ""; 488 if (atts.containsKey(Att.LITCHR)) { 489 str += LightCharacters.get(((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0)); 490 } 491 if (atts.containsKey(Att.SIGGRP)) { 492 str += "(" + atts.get(Att.SIGGRP).val + ")"; 493 } else if (!str.isEmpty()) { 494 str += "."; 495 } 496 if (atts.containsKey(Att.COLOUR)) { 497 ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val; 498 str += LightLetters.get(cols.get(0)); 499 if (cols.size() > 1) 500 str += LightLetters.get(cols.get(1)); 501 } 502 if (atts.containsKey(Att.SIGPER)) { 503 str += "." + df.format(atts.get(Att.SIGPER).val) + "s"; 504 } 505 if ((s1 <= 360) && (s2 <= 360) && (s1 != s2)) 506 Renderer.lightSector(LightColours.get(col1), LightColours.get(col2), radius, s1, s2, dir, (Renderer.zoom >= 15) ? str : ""); 507 } 508 if (Renderer.zoom >= 15) { 509 class LitSect { 510 boolean dir; 511 LitCHR chr; 512 ColCOL col; 513 String grp; 514 double per; 515 double rng; 516 double hgt; 517 } 518 519 ArrayList<LitSect> litatts = new ArrayList<>(); 520 for (AttMap atts : lights.values()) { 521 LitSect sect = new LitSect(); 522 sect.dir = (atts.containsKey(Att.CATLIT) && ((ArrayList<CatLIT>) atts.get(Att.CATLIT).val).contains(CatLIT.LIT_DIR)); 523 sect.chr = atts.containsKey(Att.LITCHR) ? ((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0) : LitCHR.CHR_UNKN; 524 switch (sect.chr) { 525 case CHR_AL: 526 sect.chr = LitCHR.CHR_F; 527 break; 528 case CHR_ALOC: 529 sect.chr = LitCHR.CHR_OC; 530 break; 531 case CHR_ALLFL: 532 sect.chr = LitCHR.CHR_LFL; 533 break; 534 case CHR_ALFL: 535 sect.chr = LitCHR.CHR_FL; 536 break; 537 case CHR_ALFFL: 538 sect.chr = LitCHR.CHR_FFL; 539 break; 540 default: 541 break; 542 } 543 sect.grp = atts.containsKey(Att.SIGGRP) ? (String) atts.get(Att.SIGGRP).val : ""; 544 sect.per = atts.containsKey(Att.SIGPER) ? (Double) atts.get(Att.SIGPER).val : 0.0; 545 sect.rng = atts.containsKey(Att.VALNMR) ? (Double) atts.get(Att.VALNMR).val : 0.0; 546 sect.hgt = atts.containsKey(Att.HEIGHT) ? (Double) atts.get(Att.HEIGHT).val : 0.0; 547 ArrayList<ColCOL> cols = (ArrayList<ColCOL>) (atts.containsKey(Att.COLOUR) ? atts.get(Att.COLOUR).val : new ArrayList<>()); 548 sect.col = cols.size() > 0 ? cols.get(0) : ColCOL.COL_UNK; 549 if ((sect.chr != LitCHR.CHR_UNKN) && (sect.col != null)) 550 litatts.add(sect); 551 } 552 ArrayList<ArrayList<LitSect>> groupings = new ArrayList<>(); 553 for (LitSect lit : litatts) { 554 boolean found = false; 555 for (ArrayList<LitSect> group : groupings) { 556 LitSect mem = group.get(0); 557 if ((lit.dir == mem.dir) && (lit.chr == mem.chr) && (lit.grp.equals(mem.grp)) && (lit.per == mem.per) && (lit.hgt == mem.hgt)) { 558 group.add(lit); 559 found = true; 560 } 561 } 562 if (!found) { 563 ArrayList<LitSect> tmp = new ArrayList<>(); 564 tmp.add(lit); 565 groupings.add(tmp); 566 } 567 } 568 for (boolean moved = true; moved;) { 569 moved = false; 570 for (int i = 0; i < groupings.size() - 1; i++) { 571 if (groupings.get(i).size() < groupings.get(i + 1).size()) { 572 ArrayList<LitSect> tmp = groupings.remove(i); 573 groupings.add(i + 1, tmp); 574 moved = true; 575 } 576 } 577 } 578 class ColRng { 579 ColCOL col; 580 double rng; 581 582 ColRng(ColCOL c, double r) { 583 col = c; 584 rng = r; 585 } 586 } 587 588 int y = -30; 589 for (ArrayList<LitSect> group : groupings) { 590 ArrayList<ColRng> colrng = new ArrayList<>(); 591 for (LitSect lit : group) { 592 boolean found = false; 593 for (ColRng cr : colrng) { 594 if (cr.col == lit.col) { 595 if (lit.rng > cr.rng) { 596 cr.rng = lit.rng; 597 } 598 found = true; 599 } 600 } 601 if (!found) { 602 colrng.add(new ColRng(lit.col, lit.rng)); 603 } 604 } 605 for (boolean moved = true; moved;) { 606 moved = false; 607 for (int i = 0; i < colrng.size() - 1; i++) { 608 if (colrng.get(i).rng < colrng.get(i + 1).rng) { 609 ColRng tmp = colrng.remove(i); 610 colrng.add(i + 1, tmp); 611 moved = true; 612 } 613 } 614 } 615 LitSect tmp = group.get(0); 616 str = (tmp.dir) ? "Dir" : ""; 617 str += LightCharacters.get(tmp.chr); 618 if (!tmp.grp.isEmpty()) 619 str += "(" + tmp.grp + ")"; 620 else 621 str += "."; 622 for (ColRng cr : colrng) { 623 str += LightLetters.get(cr.col); 624 } 625 if ((tmp.per > 0) || (tmp.hgt > 0) || (colrng.get(0).rng > 0)) 626 str += "."; 627 if (tmp.per > 0) 628 str += df.format(tmp.per) + "s"; 629 if (tmp.hgt > 0) 630 str += df.format(tmp.hgt) + "m"; 631 if (colrng.get(0).rng > 0) 632 str += df.format(colrng.get(0).rng) + ((colrng.size() > 1) ? ((colrng.size() > 2) ? ("-" + df.format(colrng.get(colrng.size() - 1).rng)) : ("/" + df.format(colrng.get(1).rng))) : "") + "M"; 633 Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.TL, AffineTransform.getTranslateInstance(60, y))); 634 y += 40; 635 str = ""; 636 } 637 } 638 } else { 639 if (Renderer.zoom >= 15) { 640 AttMap atts = lights.get(0); 641 ArrayList<CatLIT> cats = new ArrayList<>(); 642 if (atts.containsKey(Att.CATLIT)) { 643 cats = (ArrayList<CatLIT>) atts.get(Att.CATLIT).val; 644 } 645 str = (cats.contains(CatLIT.LIT_DIR)) ? "Dir" : ""; 646 str += (atts.containsKey(Att.MLTYLT)) ? atts.get(Att.MLTYLT).val : ""; 647 if (atts.containsKey(Att.LITCHR)) { 648 LitCHR chr = ((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0); 649 if (atts.containsKey(Att.SIGGRP)) { 650 String grp = (String) atts.get(Att.SIGGRP).val; 651 switch (chr) { 652 case CHR_QLFL: 653 str += String.format("Q(%s)+LFl", grp); 654 break; 655 case CHR_VQLFL: 656 str += String.format("VQ(%s)+LFl", grp); 657 break; 658 case CHR_UQLFL: 659 str += String.format("UQ(%s)+LFl", grp); 660 break; 661 default: 662 str += String.format("%s(%s)", LightCharacters.get(chr), grp); 663 break; 664 } 665 } else { 666 str += LightCharacters.get(chr); 667 } 668 } 669 if (atts.containsKey(Att.COLOUR)) { 670 ArrayList<ColCOL> cols = (ArrayList<ColCOL>) atts.get(Att.COLOUR).val; 671 if (!((cols.size() == 1) && (cols.get(0) == ColCOL.COL_WHT))) { 672 if (!str.isEmpty() && !str.endsWith(")")) { 673 str += "."; 674 } 675 for (ColCOL acol : cols) { 676 str += LightLetters.get(acol); 677 } 678 } 679 } 680 str += (cats.contains(CatLIT.LIT_VERT)) ? "(vert)" : ""; 681 str += (cats.contains(CatLIT.LIT_HORI)) ? "(hor)" : ""; 682 str += (!str.isEmpty() && (atts.containsKey(Att.SIGPER) || atts.containsKey(Att.HEIGHT) || atts.containsKey(Att.VALMXR)) && !str.endsWith(")")) ? "." : ""; 683 str += (atts.containsKey(Att.SIGPER)) ? df.format(atts.get(Att.SIGPER).val) + "s" : ""; 684 str += (atts.containsKey(Att.HEIGHT)) ? df.format(atts.get(Att.HEIGHT).val) + "m" : ""; 685 str += (atts.containsKey(Att.VALNMR)) ? df.format(atts.get(Att.VALNMR).val) + "M" : ""; 686 str += (cats.contains(CatLIT.LIT_FRNT)) ? "(Front)" : ""; 687 str += (cats.contains(CatLIT.LIT_REAR)) ? "(Rear)" : ""; 688 str += (cats.contains(CatLIT.LIT_UPPR)) ? "(Upper)" : ""; 689 str += (cats.contains(CatLIT.LIT_LOWR)) ? "(Lower)" : ""; 690 Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.TL, AffineTransform.getTranslateInstance(60, -30))); 691 } 692 } 693 } 694 } 686 695 }
Note:
See TracChangeset
for help on using the changeset viewer.