Ignore:
Timestamp:
2018-01-11T15:35:23+01:00 (7 years ago)
Author:
malcolmh
Message:

[Seachart] Publish new release

Location:
applications/editors/josm/plugins/seachart/src/render
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/seachart/src/render/Rules.java

    r33956 r33995  
    10001000                        if (Renderer.zoom >= 14) {
    10011001                                if (testAttribute(Obj.LIGHTS, Att.CATLIT, CatLIT.LIT_FLDL)) {
    1002                                         Renderer.symbol(Beacons.Floodlight, new Delta(Handle.CC, AffineTransform.getRotateInstance(Math.toRadians(180))));
     1002                                        Renderer.symbol(Beacons.Floodlight, new Delta(Handle.CC, AffineTransform.getRotateInstance(Math.toRadians(90))));
    10031003                                        Renderer.symbol(Harbours.SignalStation);
    10041004                                } else {
  • applications/editors/josm/plugins/seachart/src/render/Signals.java

    r33956 r33995  
    3232public class Signals extends Rules {
    3333
    34     static final EnumMap<ColCOL, Color> LightColours = new EnumMap<>(ColCOL.class);
    35     static {
    36         LightColours.put(ColCOL.COL_WHT, new Color(0xffff00));
    37         LightColours.put(ColCOL.COL_RED, new Color(0xff0000));
    38         LightColours.put(ColCOL.COL_GRN, new Color(0x00ff00));
    39         LightColours.put(ColCOL.COL_BLU, new Color(0x0000ff));
    40         LightColours.put(ColCOL.COL_YEL, new Color(0xffff00));
    41         LightColours.put(ColCOL.COL_AMB, new Color(0xffc200));
    42         LightColours.put(ColCOL.COL_VIO, new Color(0xee82ee));
    43         LightColours.put(ColCOL.COL_ORG, Color.orange);
    44         LightColours.put(ColCOL.COL_MAG, Color.magenta);
    45     }
    46 
    47     static final EnumMap<ColCOL, String> LightLetters = new EnumMap<>(ColCOL.class);
    48     static {
    49         LightLetters.put(ColCOL.COL_WHT, "W");
    50         LightLetters.put(ColCOL.COL_RED, "R");
    51         LightLetters.put(ColCOL.COL_GRN, "G");
    52         LightLetters.put(ColCOL.COL_BLU, "Bu");
    53         LightLetters.put(ColCOL.COL_YEL, "Y");
    54         LightLetters.put(ColCOL.COL_AMB, "Am");
    55         LightLetters.put(ColCOL.COL_VIO, "Vi");
    56         LightLetters.put(ColCOL.COL_ORG, "Or");
    57     }
    58 
    59     static final EnumMap<LitCHR, String> LightCharacters = new EnumMap<>(LitCHR.class);
    60     static {
    61         LightCharacters.put(LitCHR.CHR_F, "F");
    62         LightCharacters.put(LitCHR.CHR_FL, "Fl");
    63         LightCharacters.put(LitCHR.CHR_LFL, "LFl");
    64         LightCharacters.put(LitCHR.CHR_Q, "Q");
    65         LightCharacters.put(LitCHR.CHR_VQ, "VQ");
    66         LightCharacters.put(LitCHR.CHR_UQ, "UQ");
    67         LightCharacters.put(LitCHR.CHR_ISO, "Iso");
    68         LightCharacters.put(LitCHR.CHR_OC, "Oc");
    69         LightCharacters.put(LitCHR.CHR_IQ, "IQ");
    70         LightCharacters.put(LitCHR.CHR_IVQ, "IVQ");
    71         LightCharacters.put(LitCHR.CHR_IUQ, "IUQ");
    72         LightCharacters.put(LitCHR.CHR_MO, "Mo");
    73         LightCharacters.put(LitCHR.CHR_FFL, "FFl");
    74         LightCharacters.put(LitCHR.CHR_FLLFL, "FlLFl");
    75         LightCharacters.put(LitCHR.CHR_OCFL, "OcFl");
    76         LightCharacters.put(LitCHR.CHR_FLFL, "FLFl");
    77         LightCharacters.put(LitCHR.CHR_ALOC, "Al.Oc");
    78         LightCharacters.put(LitCHR.CHR_ALLFL, "Al.LFl");
    79         LightCharacters.put(LitCHR.CHR_ALFL, "Al.Fl");
    80         LightCharacters.put(LitCHR.CHR_ALGR, "Al.Gr");
    81         LightCharacters.put(LitCHR.CHR_QLFL, "Q+LFl");
    82         LightCharacters.put(LitCHR.CHR_VQLFL, "VQ+LFl");
    83         LightCharacters.put(LitCHR.CHR_UQLFL, "UQ+LFl");
    84         LightCharacters.put(LitCHR.CHR_AL, "Al");
    85         LightCharacters.put(LitCHR.CHR_ALFFL, "Al.FFl");
    86     }
    87 
    88     static final EnumMap<CatFOG, String> fogSignals = new EnumMap<>(CatFOG.class);
    89     static {
    90         fogSignals.put(CatFOG.FOG_EXPL, "Explos");
    91         fogSignals.put(CatFOG.FOG_DIA, "Dia");
    92         fogSignals.put(CatFOG.FOG_SIRN, "Siren");
    93         fogSignals.put(CatFOG.FOG_NAUT, "Horn");
    94         fogSignals.put(CatFOG.FOG_REED, "Horn");
    95         fogSignals.put(CatFOG.FOG_TYPH, "Horn");
    96         fogSignals.put(CatFOG.FOG_BELL, "Bell");
    97         fogSignals.put(CatFOG.FOG_WHIS, "Whis");
    98         fogSignals.put(CatFOG.FOG_GONG, "Gong");
    99         fogSignals.put(CatFOG.FOG_HORN, "Horn");
    100     }
    101 
    102     static final DecimalFormat df = new DecimalFormat("#.#");
    103 
    104     public static void addSignals() {
    105         if (feature.objs.containsKey(Obj.RADRFL)) reflectors();
    106         if (feature.objs.containsKey(Obj.FOGSIG)) fogSignals();
    107         if (feature.objs.containsKey(Obj.RTPBCN)) radarStations();
    108         if (feature.objs.containsKey(Obj.RADSTA)) radarStations();
    109         if (feature.objs.containsKey(Obj.RDOSTA)) radioStations();
    110         if (feature.objs.containsKey(Obj.LIGHTS)) lights();
    111     }
    112 
    113     public static void reflectors() {
    114         if (Renderer.zoom >= 14) {
    115             switch (feature.type) {
    116             case BCNLAT:
    117             case BCNCAR:
    118             case BCNISD:
    119             case BCNSAW:
    120             case BCNSPP:
    121                 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) {
    122                     Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -140)));
    123                 } else {
    124                     Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -80)));
    125                 }
    126                 break;
    127             case LITFLT:
    128             case LITVES:
    129             case BOYINB:
    130                 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) {
    131                     Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -110)));
    132                 } else {
    133                     Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -60)));
    134                 }
    135                 break;
    136             case LITMAJ:
    137             case LITMIN:
    138                 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) {
    139                     Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -90)));
    140                 } else {
    141                     Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -30)));
    142                 }
    143                 break;
    144             case BOYLAT:
    145             case BOYCAR:
    146             case BOYISD:
    147             case BOYSAW:
    148             case BOYSPP:
    149                 if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) {
    150                     if (testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_PILR) || testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_SPAR)) {
    151                         Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(50, -160)));
    152                     } else {
    153                         Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(25, -80)));
    154                     }
    155                 } else {
    156                     if (testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_PILR) || testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_SPAR)) {
    157                         Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(30, -100)));
    158                     } else {
    159                         Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(10, -50)));
    160                     }
    161                 }
    162                 break;
    163             default:
    164                 break;
    165             }
    166         }
    167     }
    168 
    169     public static void fogSignals() {
    170         if (Renderer.zoom >= 11)
    171             Renderer.symbol(Beacons.FogSignal);
    172         if (Renderer.zoom >= 15) {
    173             AttMap atts = feature.objs.get(Obj.FOGSIG).get(0);
    174             if (atts != null) {
    175                 String str = "";
    176                 if (atts.containsKey(Att.CATFOG)) {
    177                     str += fogSignals.get(((ArrayList<?>) (atts.get(Att.CATFOG).val)).get(0));
    178                 }
    179                 if (atts.containsKey(Att.SIGGRP)) {
    180                     str += "(" + atts.get(Att.SIGGRP).val + ")";
    181                 } else {
    182                     str += " ";
    183                 }
    184                 if (atts.containsKey(Att.SIGPER)) {
    185                     str += df.format(atts.get(Att.SIGPER).val) + "s";
    186                 }
    187                 if (atts.containsKey(Att.VALMXR)) {
    188                     str += df.format(atts.get(Att.VALMXR).val) + "M";
    189                 }
    190                 if (!str.isEmpty()) {
    191                     Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black,
    192                             new Delta(Handle.TR, AffineTransform.getTranslateInstance(-60, -30)));
    193                 }
    194             }
    195         }
    196     }
    197 
    198     public static void radarStations() {
    199         if (Renderer.zoom >= 11)
    200             Renderer.symbol(Beacons.RadarStation);
    201         if (Renderer.zoom >= 15) {
    202             String bstr = "";
    203             CatRTB cat = (CatRTB) getAttEnum(Obj.RTPBCN, Att.CATRTB);
    204             String wal = getAttStr(Obj.RTPBCN, Att.RADWAL);
    205             switch (cat) {
    206             case RTB_RAMK:
    207                 bstr += " Ramark";
    208                 break;
    209             case RTB_RACN:
    210                 bstr += " Racon";
    211                 String astr = getAttStr(Obj.RTPBCN, Att.SIGGRP);
    212                 if (!astr.isEmpty()) {
    213                     bstr += "(" + astr + ")";
    214                 }
    215                 Double per = (Double) getAttVal(Obj.RTPBCN, Att.SIGPER);
    216                 Double mxr = (Double) getAttVal(Obj.RTPBCN, Att.VALMXR);
    217                 if ((per != null) || (mxr != null)) {
    218                     bstr += (astr.isEmpty() ? " " : "");
    219                     if (per != null)
    220                         bstr += (per != 0) ? per.toString() + "s" : "";
    221                     if (mxr != null)
    222                         bstr += (mxr != 0) ? mxr.toString() + "M" : "";
    223                 }
    224                 break;
    225             default:
    226                 break;
    227             }
    228             if (!wal.isEmpty()) {
    229                 switch (wal) {
    230                 case "0.03-X":
    231                     bstr += "(3cm)";
    232                     break;
    233                 case "0.10-S":
    234                     bstr += "(10cm)";
    235                     break;
    236                 }
    237             }
    238             if (!bstr.isEmpty()) {
    239                 Renderer.labelText(bstr, new Font("Arial", Font.PLAIN, 40), Symbols.Msymb,
    240                         new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -70)));
    241             }
    242         }
    243     }
    244 
    245     @SuppressWarnings("unchecked")
    246     public static void radioStations() {
    247         boolean vais = false;
    248         String bstr = "";
    249         if (Renderer.zoom >= 11) {
    250             ArrayList<CatROS> cats = (ArrayList<CatROS>) getAttList(Obj.RDOSTA, Att.CATROS);
    251             for (CatROS ros : cats) {
    252                 switch (ros) {
    253                 case ROS_OMNI:
    254                     bstr += " RC";
    255                     break;
    256                 case ROS_DIRL:
    257                     bstr += " RD";
    258                     break;
    259                 case ROS_ROTP:
    260                     bstr += " RW";
    261                     break;
    262                 case ROS_CNSL:
    263                     bstr += " Consol";
    264                     break;
    265                 case ROS_RDF:
    266                     bstr += " RG";
    267                     break;
    268                 case ROS_QTA:
    269                     bstr += " R";
    270                     break;
    271                 case ROS_AERO:
    272                     bstr += " AeroRC";
    273                     break;
    274                 case ROS_DECA:
    275                     bstr += " Decca";
    276                     break;
    277                 case ROS_LORN:
    278                     bstr += " Loran";
    279                     break;
    280                 case ROS_DGPS:
    281                     bstr += " DGPS";
    282                     break;
    283                 case ROS_TORN:
    284                     bstr += " Toran";
    285                     break;
    286                 case ROS_OMGA:
    287                     bstr += " Omega";
    288                     break;
    289                 case ROS_SYLD:
    290                     bstr += " Syledis";
    291                     break;
    292                 case ROS_CHKA:
    293                     bstr += " Chiaka";
    294                     break;
    295                 case ROS_PCOM:
    296                 case ROS_COMB:
    297                 case ROS_FACS:
    298                 case ROS_TIME:
    299                     break;
    300                 case ROS_PAIS:
    301                 case ROS_SAIS:
    302                     bstr += " AIS";
    303                     break;
    304                 case ROS_VAIS:
    305                     vais = true;
    306                     break;
    307                 case ROS_VANC:
    308                     vais = true;
    309                     Renderer.symbol(Topmarks.TopNorth, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
    310                     break;
    311                 case ROS_VASC:
    312                     vais = true;
    313                     Renderer.symbol(Topmarks.TopSouth, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
    314                     break;
    315                 case ROS_VAEC:
    316                     vais = true;
    317                     Renderer.symbol(Topmarks.TopEast, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
    318                     break;
    319                 case ROS_VAWC:
    320                     vais = true;
    321                     Renderer.symbol(Topmarks.TopWest, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
    322                     break;
    323                 case ROS_VAPL:
    324                     vais = true;
    325                     Renderer.symbol(Topmarks.TopCan, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
    326                     break;
    327                 case ROS_VASL:
    328                     vais = true;
    329                     Renderer.symbol(Topmarks.TopCone, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
    330                     break;
    331                 case ROS_VAID:
    332                     vais = true;
    333                     Renderer.symbol(Topmarks.TopIsol, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
    334                     break;
    335                 case ROS_VASW:
    336                     vais = true;
    337                     Renderer.symbol(Topmarks.TopSphere, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
    338                     break;
    339                 case ROS_VASP:
    340                     vais = true;
    341                     Renderer.symbol(Topmarks.TopX, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
    342                     break;
    343                 case ROS_VAWK:
    344                     vais = true;
    345                     Renderer.symbol(Topmarks.TopCross, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
    346                     break;
    347                 default:
    348                     break;
    349                 }
    350             }
    351             if (!vais) {
    352                 Renderer.symbol(Beacons.RadarStation);
    353             }
    354         }
    355         if (Renderer.zoom >= 15) {
    356             if (vais) {
    357                 Renderer.labelText("V-AIS", new Font("Arial", Font.PLAIN, 40), Symbols.Msymb,
    358                         new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, 70)));
    359             }
    360             if (!bstr.isEmpty()) {
    361                 Renderer.labelText(bstr, new Font("Arial", Font.PLAIN, 40), Symbols.Msymb,
    362                         new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -110)));
    363             }
    364         }
    365     }
    366 
    367     static class Sect {
    368         int dir;
    369         LitCHR chr;
    370         ColCOL col;
    371         ColCOL alt;
    372         String grp;
    373         double per;
    374         double rng;
    375     }
    376 
    377     @SuppressWarnings("unchecked")
    378     public static void lights() {
    379       if ((hasAttribute(Obj.LIGHTS, Att.CATLIT) && (testAttribute(Obj.LIGHTS, Att.CATLIT, CatLIT.LIT_FLDL))))
    380         return;
    381         Enum<ColCOL> col = null;
    382         Enum<ColCOL> tcol = null;
    383         ObjTab lights = feature.objs.get(Obj.LIGHTS);
    384         for (AttMap atts : lights.values()) {
    385             if (atts.containsKey(Att.COLOUR)) {
    386                 ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val;
    387                 if (cols.size() == 1) {
    388                     tcol = cols.get(0);
    389                     if (col == null) {
    390                         col = tcol;
    391                     } else if (tcol != col) {
    392                         col = ColCOL.COL_MAG;
    393                         break;
    394                     }
    395                 } else {
    396                     col = ColCOL.COL_MAG;
    397                     break;
    398                 }
    399             }
    400         }
    401         Renderer.symbol(Beacons.LightFlare, new Scheme(LightColours.get(col)),
    402                         new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.toRadians(120))));
    403         if (Renderer.zoom >= 12) {
    404             String str = "";
    405             if (lights.get(1) != null) {
    406                 for (AttMap atts : lights.values()) {
    407                     Enum<ColCOL> col1 = null;
    408                     Enum<ColCOL> col2 = null;
    409                     double radius = 0.2;
    410                     double s1 = 361;
    411                     double s2 = 361;
    412                     Double dir = null;
    413                     if (atts.containsKey(Att.COLOUR)) {
    414                         ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val;
    415                         col1 = cols.get(0);
    416                         if (cols.size() > 1)
    417                             col2 = cols.get(1);
    418                     } else {
    419                         continue;
    420                     }
    421                     if (atts.containsKey(Att.CATLIT)) {
    422                         ArrayList<CatLIT> cats = (ArrayList<CatLIT>) atts.get(Att.CATLIT).val;
    423                         if (cats.contains(CatLIT.LIT_DIR)) {
    424                             if (atts.containsKey(Att.ORIENT)) {
    425                                 dir = (Double) atts.get(Att.ORIENT).val;
    426                                 s1 = ((dir - 4) + 360) % 360;
    427                                 s2 = (dir + 4) % 360;
    428                                 for (AttMap satts : lights.values()) {
    429                                     double srad = 0.2;
    430                                     double ss1 = 361;
    431                                     double ss2 = 361;
    432                                     Double sdir = null;
    433                                     if (satts == atts)
    434                                         continue;
    435                                     if (srad == radius) {
    436                                         ArrayList<CatLIT> scats = (ArrayList<CatLIT>) ((satts.containsKey(Att.CATLIT)) ?
    437                                                 (ArrayList<CatLIT>) satts.get(Att.CATLIT).val : new ArrayList<>());
    438                                         if (scats.contains(CatLIT.LIT_DIR)) {
    439                                             if (satts.containsKey(Att.ORIENT)) {
    440                                                 sdir = (Double) satts.get(Att.ORIENT).val;
    441                                                 ss1 = sdir;
    442                                                 ss2 = sdir;
    443                                             }
    444                                         } else {
    445                                             if (satts.containsKey(Att.SECTR1)) {
    446                                                 ss1 = (Double) satts.get(Att.SECTR1).val;
    447                                             }
    448                                             if (satts.containsKey(Att.SECTR2)) {
    449                                                 ss2 = (Double) satts.get(Att.SECTR2).val;
    450                                             }
    451                                         }
    452                                         if ((ss1 > 360) || (ss2 > 360))
    453                                             continue;
    454                                         if (sdir != null) {
    455                                             if (((dir - sdir + 360) % 360) < 8) {
    456                                                 s1 = ((((sdir > dir) ? 360 : 0) + sdir + dir) / 2) % 360;
    457                                             }
    458                                             if (((sdir - dir + 360) % 360) < 8) {
    459                                                 s2 = ((((dir > sdir) ? 360 : 0) + sdir + dir) / 2) % 360;
    460                                             }
    461                                         } else {
    462                                             if (((dir - ss2 + 360) % 360) < 4) {
    463                                                 s1 = ss2;
    464                                             }
    465                                             if (((ss1 - dir + 360) % 360) < 4) {
    466                                                 s2 = ss1;
    467                                             }
    468                                         }
    469                                     }
    470                                 }
    471                             }
    472                         }
    473                     }
    474                     if ((s1 > 360) && atts.containsKey(Att.SECTR1)) {
    475                         s1 = (Double) atts.get(Att.SECTR1).val;
    476                     } else if (dir == null) {
    477                         continue;
    478                     }
    479                     if ((s2 > 360) && atts.containsKey(Att.SECTR2)) {
    480                         s2 = (Double) atts.get(Att.SECTR2).val;
    481                     } else if (dir == null) {
    482                         continue;
    483                     }
    484                     str = "";
    485                     if (atts.containsKey(Att.LITCHR)) {
    486                         str += LightCharacters.get(((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0));
    487                     }
    488                     if (atts.containsKey(Att.SIGGRP)) {
    489                         str += "(" + atts.get(Att.SIGGRP).val + ")";
    490                     } else if (!str.isEmpty()) {
    491                         str += ".";
    492                     }
    493                     if (atts.containsKey(Att.COLOUR)) {
    494                         ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val;
    495                         str += LightLetters.get(cols.get(0));
    496                         if (cols.size() > 1)
    497                             str += LightLetters.get(cols.get(1));
    498                     }
    499                     if (atts.containsKey(Att.SIGPER)) {
    500                         str += "." + df.format(atts.get(Att.SIGPER).val) + "s";
    501                     }
    502                     if ((s1 <= 360) && (s2 <= 360) && (s1 != s2))
    503                         Renderer.lightSector(LightColours.get(col1), LightColours.get(col2), radius, s1, s2, dir,
    504                                 (Renderer.zoom >= 15) ? str : "");
    505                 }
    506                 if (Renderer.zoom >= 15) {
    507                     class LitSect {
    508                         boolean dir;
    509                         LitCHR chr;
    510                         ColCOL col;
    511                         String grp;
    512                         double per;
    513                         double rng;
    514                         double hgt;
    515                     }
    516 
    517                     ArrayList<LitSect> litatts = new ArrayList<>();
    518                     for (AttMap atts : lights.values()) {
    519                         LitSect sect = new LitSect();
    520                         sect.dir = (atts.containsKey(Att.CATLIT) && ((ArrayList<CatLIT>) atts.get(Att.CATLIT).val).contains(CatLIT.LIT_DIR));
    521                         sect.chr = atts.containsKey(Att.LITCHR) ? ((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0) : LitCHR.CHR_UNKN;
    522                         switch (sect.chr) {
    523                         case CHR_AL:
    524                             sect.chr = LitCHR.CHR_F;
    525                             break;
    526                         case CHR_ALOC:
    527                             sect.chr = LitCHR.CHR_OC;
    528                             break;
    529                         case CHR_ALLFL:
    530                             sect.chr = LitCHR.CHR_LFL;
    531                             break;
    532                         case CHR_ALFL:
    533                             sect.chr = LitCHR.CHR_FL;
    534                             break;
    535                         case CHR_ALFFL:
    536                             sect.chr = LitCHR.CHR_FFL;
    537                             break;
    538                         default:
    539                             break;
    540                         }
    541                         sect.grp = atts.containsKey(Att.SIGGRP) ? (String) atts.get(Att.SIGGRP).val : "";
    542                         sect.per = atts.containsKey(Att.SIGPER) ? (Double) atts.get(Att.SIGPER).val : 0.0;
    543                         sect.rng = atts.containsKey(Att.VALNMR) ? (Double) atts.get(Att.VALNMR).val : 0.0;
    544                         sect.hgt = atts.containsKey(Att.HEIGHT) ? (Double) atts.get(Att.HEIGHT).val : 0.0;
    545                         ArrayList<ColCOL> cols = (ArrayList<ColCOL>)
    546                                 (atts.containsKey(Att.COLOUR) ? atts.get(Att.COLOUR).val : new ArrayList<>());
    547                         sect.col = cols.size() > 0 ? cols.get(0) : ColCOL.COL_UNK;
    548                         if ((sect.chr != LitCHR.CHR_UNKN) && (sect.col != null))
    549                             litatts.add(sect);
    550                     }
    551                     ArrayList<ArrayList<LitSect>> groupings = new ArrayList<>();
    552                     for (LitSect lit : litatts) {
    553                         boolean found = false;
    554                         for (ArrayList<LitSect> group : groupings) {
    555                             LitSect mem = group.get(0);
    556                             if ((lit.dir == mem.dir) && (lit.chr == mem.chr) && (lit.grp.equals(mem.grp)) &&
    557                                 (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) ?
    633                                     ("-" + df.format(colrng.get(colrng.size() - 1).rng)) : ("/" + df.format(colrng.get(1).rng))) : "") + "M";
    634                         Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black,
    635                                 new Delta(Handle.TL, AffineTransform.getTranslateInstance(60, y)));
    636                         y += 40;
    637                         str = "";
    638                     }
    639                 }
    640             } else {
    641                 if (Renderer.zoom >= 15) {
    642                     AttMap atts = lights.get(0);
    643                     ArrayList<CatLIT> cats = new ArrayList<>();
    644                     if (atts.containsKey(Att.CATLIT)) {
    645                         cats = (ArrayList<CatLIT>) atts.get(Att.CATLIT).val;
    646                     }
    647                     str = (cats.contains(CatLIT.LIT_DIR)) ? "Dir" : "";
    648                     str += (atts.containsKey(Att.MLTYLT)) ? atts.get(Att.MLTYLT).val : "";
    649                     if (atts.containsKey(Att.LITCHR)) {
    650                         LitCHR chr = ((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0);
    651                         if (atts.containsKey(Att.SIGGRP)) {
    652                             String grp = (String) atts.get(Att.SIGGRP).val;
    653                             switch (chr) {
    654                             case CHR_QLFL:
    655                                 str += String.format("Q(%s)+LFl", grp);
    656                                 break;
    657                             case CHR_VQLFL:
    658                                 str += String.format("VQ(%s)+LFl", grp);
    659                                 break;
    660                             case CHR_UQLFL:
    661                                 str += String.format("UQ(%s)+LFl", grp);
    662                                 break;
    663                             default:
    664                                 str += String.format("%s(%s)", LightCharacters.get(chr), grp);
    665                                 break;
    666                             }
    667                         } else {
    668                             str += LightCharacters.get(chr);
    669                         }
    670                     }
    671                     if (atts.containsKey(Att.COLOUR)) {
    672                         ArrayList<ColCOL> cols = (ArrayList<ColCOL>) atts.get(Att.COLOUR).val;
    673                         if (!((cols.size() == 1) && (cols.get(0) == ColCOL.COL_WHT))) {
    674                             if (!str.isEmpty() && !str.endsWith(")")) {
    675                                 str += ".";
    676                             }
    677                             for (ColCOL acol : cols) {
    678                                 str += LightLetters.get(acol);
    679                             }
    680                         }
    681                     }
    682                     str += (cats.contains(CatLIT.LIT_VERT)) ? "(vert)" : "";
    683                     str += (cats.contains(CatLIT.LIT_HORI)) ? "(hor)" : "";
    684                     str += (!str.isEmpty() && (atts.containsKey(Att.SIGPER) || atts.containsKey(Att.HEIGHT) || atts.containsKey(Att.VALMXR))
    685                             && !str.endsWith(")")) ? "." : "";
    686                     str += (atts.containsKey(Att.SIGPER)) ? df.format(atts.get(Att.SIGPER).val) + "s" : "";
    687                     str += (atts.containsKey(Att.HEIGHT)) ? df.format(atts.get(Att.HEIGHT).val) + "m" : "";
    688                     str += (atts.containsKey(Att.VALNMR)) ? df.format(atts.get(Att.VALNMR).val) + "M" : "";
    689                     str += (cats.contains(CatLIT.LIT_FRNT)) ? "(Front)" : "";
    690                     str += (cats.contains(CatLIT.LIT_REAR)) ? "(Rear)" : "";
    691                     str += (cats.contains(CatLIT.LIT_UPPR)) ? "(Upper)" : "";
    692                     str += (cats.contains(CatLIT.LIT_LOWR)) ? "(Lower)" : "";
    693                     Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black,
    694                             new Delta(Handle.TL, AffineTransform.getTranslateInstance(60, -30)));
    695                 }
    696             }
    697         }
    698     }
     34        static final EnumMap<ColCOL, Color> LightColours = new EnumMap<>(ColCOL.class);
     35        static {
     36                LightColours.put(ColCOL.COL_WHT, new Color(0xffff00));
     37                LightColours.put(ColCOL.COL_RED, new Color(0xff0000));
     38                LightColours.put(ColCOL.COL_GRN, new Color(0x00ff00));
     39                LightColours.put(ColCOL.COL_BLU, new Color(0x0000ff));
     40                LightColours.put(ColCOL.COL_YEL, new Color(0xffff00));
     41                LightColours.put(ColCOL.COL_AMB, new Color(0xffc200));
     42                LightColours.put(ColCOL.COL_VIO, new Color(0xee82ee));
     43                LightColours.put(ColCOL.COL_ORG, Color.orange);
     44                LightColours.put(ColCOL.COL_MAG, Color.magenta);
     45        }
     46
     47        static final EnumMap<ColCOL, String> LightLetters = new EnumMap<>(ColCOL.class);
     48        static {
     49                LightLetters.put(ColCOL.COL_WHT, "W");
     50                LightLetters.put(ColCOL.COL_RED, "R");
     51                LightLetters.put(ColCOL.COL_GRN, "G");
     52                LightLetters.put(ColCOL.COL_BLU, "Bu");
     53                LightLetters.put(ColCOL.COL_YEL, "Y");
     54                LightLetters.put(ColCOL.COL_AMB, "Am");
     55                LightLetters.put(ColCOL.COL_VIO, "Vi");
     56                LightLetters.put(ColCOL.COL_ORG, "Or");
     57        }
     58
     59        static final EnumMap<LitCHR, String> LightCharacters = new EnumMap<>(LitCHR.class);
     60        static {
     61                LightCharacters.put(LitCHR.CHR_F, "F");
     62                LightCharacters.put(LitCHR.CHR_FL, "Fl");
     63                LightCharacters.put(LitCHR.CHR_LFL, "LFl");
     64                LightCharacters.put(LitCHR.CHR_Q, "Q");
     65                LightCharacters.put(LitCHR.CHR_VQ, "VQ");
     66                LightCharacters.put(LitCHR.CHR_UQ, "UQ");
     67                LightCharacters.put(LitCHR.CHR_ISO, "Iso");
     68                LightCharacters.put(LitCHR.CHR_OC, "Oc");
     69                LightCharacters.put(LitCHR.CHR_IQ, "IQ");
     70                LightCharacters.put(LitCHR.CHR_IVQ, "IVQ");
     71                LightCharacters.put(LitCHR.CHR_IUQ, "IUQ");
     72                LightCharacters.put(LitCHR.CHR_MO, "Mo");
     73                LightCharacters.put(LitCHR.CHR_FFL, "FFl");
     74                LightCharacters.put(LitCHR.CHR_FLLFL, "FlLFl");
     75                LightCharacters.put(LitCHR.CHR_OCFL, "OcFl");
     76                LightCharacters.put(LitCHR.CHR_FLFL, "FLFl");
     77                LightCharacters.put(LitCHR.CHR_ALOC, "Al.Oc");
     78                LightCharacters.put(LitCHR.CHR_ALLFL, "Al.LFl");
     79                LightCharacters.put(LitCHR.CHR_ALFL, "Al.Fl");
     80                LightCharacters.put(LitCHR.CHR_ALGR, "Al.Gr");
     81                LightCharacters.put(LitCHR.CHR_QLFL, "Q+LFl");
     82                LightCharacters.put(LitCHR.CHR_VQLFL, "VQ+LFl");
     83                LightCharacters.put(LitCHR.CHR_UQLFL, "UQ+LFl");
     84                LightCharacters.put(LitCHR.CHR_AL, "Al");
     85                LightCharacters.put(LitCHR.CHR_ALFFL, "Al.FFl");
     86        }
     87
     88        static final EnumMap<CatFOG, String> fogSignals = new EnumMap<>(CatFOG.class);
     89        static {
     90                fogSignals.put(CatFOG.FOG_EXPL, "Explos");
     91                fogSignals.put(CatFOG.FOG_DIA, "Dia");
     92                fogSignals.put(CatFOG.FOG_SIRN, "Siren");
     93                fogSignals.put(CatFOG.FOG_NAUT, "Horn");
     94                fogSignals.put(CatFOG.FOG_REED, "Horn");
     95                fogSignals.put(CatFOG.FOG_TYPH, "Horn");
     96                fogSignals.put(CatFOG.FOG_BELL, "Bell");
     97                fogSignals.put(CatFOG.FOG_WHIS, "Whis");
     98                fogSignals.put(CatFOG.FOG_GONG, "Gong");
     99                fogSignals.put(CatFOG.FOG_HORN, "Horn");
     100        }
     101
     102        static final DecimalFormat df = new DecimalFormat("#.#");
     103
     104        public static void addSignals() {
     105                if (feature.objs.containsKey(Obj.RADRFL))
     106                        reflectors();
     107                if (feature.objs.containsKey(Obj.FOGSIG))
     108                        fogSignals();
     109                if (feature.objs.containsKey(Obj.RTPBCN))
     110                        radarStations();
     111                if (feature.objs.containsKey(Obj.RADSTA))
     112                        radarStations();
     113                if (feature.objs.containsKey(Obj.RDOSTA))
     114                        radioStations();
     115                if (feature.objs.containsKey(Obj.LIGHTS))
     116                        lights();
     117        }
     118
     119        public static void reflectors() {
     120                if (Renderer.zoom >= 14) {
     121                        switch (feature.type) {
     122                        case BCNLAT:
     123                        case BCNCAR:
     124                        case BCNISD:
     125                        case BCNSAW:
     126                        case BCNSPP:
     127                                if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) {
     128                                        Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -140)));
     129                                } else {
     130                                        Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -80)));
     131                                }
     132                                break;
     133                        case LITFLT:
     134                        case LITVES:
     135                        case BOYINB:
     136                                if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) {
     137                                        Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -110)));
     138                                } else {
     139                                        Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -60)));
     140                                }
     141                                break;
     142                        case LITMAJ:
     143                        case LITMIN:
     144                                if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) {
     145                                        Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -90)));
     146                                } else {
     147                                        Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -30)));
     148                                }
     149                                break;
     150                        case BOYLAT:
     151                        case BOYCAR:
     152                        case BOYISD:
     153                        case BOYSAW:
     154                        case BOYSPP:
     155                                if ((feature.objs.containsKey(Obj.TOPMAR)) || (feature.objs.containsKey(Obj.DAYMAR))) {
     156                                        if (testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_PILR) || testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_SPAR)) {
     157                                                Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(50, -160)));
     158                                        } else {
     159                                                Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(25, -80)));
     160                                        }
     161                                } else {
     162                                        if (testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_PILR) || testAttribute(feature.type, Att.BOYSHP, BoySHP.BOY_SPAR)) {
     163                                                Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(30, -100)));
     164                                        } else {
     165                                                Renderer.symbol(Topmarks.RadarReflector, new Delta(Handle.BC, AffineTransform.getTranslateInstance(10, -50)));
     166                                        }
     167                                }
     168                                break;
     169                        default:
     170                                break;
     171                        }
     172                }
     173        }
     174
     175        public static void fogSignals() {
     176                if (Renderer.zoom >= 11)
     177                        Renderer.symbol(Beacons.FogSignal);
     178                if (Renderer.zoom >= 15) {
     179                        AttMap atts = feature.objs.get(Obj.FOGSIG).get(0);
     180                        if (atts != null) {
     181                                String str = "";
     182                                if (atts.containsKey(Att.CATFOG)) {
     183                                        str += fogSignals.get(((ArrayList<?>) (atts.get(Att.CATFOG).val)).get(0));
     184                                }
     185                                if (atts.containsKey(Att.SIGGRP)) {
     186                                        str += "(" + atts.get(Att.SIGGRP).val + ")";
     187                                } else {
     188                                        str += " ";
     189                                }
     190                                if (atts.containsKey(Att.SIGPER)) {
     191                                        str += df.format(atts.get(Att.SIGPER).val) + "s";
     192                                }
     193                                if (atts.containsKey(Att.VALMXR)) {
     194                                        str += df.format(atts.get(Att.VALMXR).val) + "M";
     195                                }
     196                                if (!str.isEmpty()) {
     197                                        Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-60, -30)));
     198                                }
     199                        }
     200                }
     201        }
     202
     203        public static void radarStations() {
     204                if (Renderer.zoom >= 11)
     205                        Renderer.symbol(Beacons.RadarStation);
     206                if (Renderer.zoom >= 15) {
     207                        String bstr = "";
     208                        CatRTB cat = (CatRTB) getAttEnum(Obj.RTPBCN, Att.CATRTB);
     209                        String wal = getAttStr(Obj.RTPBCN, Att.RADWAL);
     210                        switch (cat) {
     211                        case RTB_RAMK:
     212                                bstr += " Ramark";
     213                                break;
     214                        case RTB_RACN:
     215                                bstr += " Racon";
     216                                String astr = getAttStr(Obj.RTPBCN, Att.SIGGRP);
     217                                if (!astr.isEmpty()) {
     218                                        bstr += "(" + astr + ")";
     219                                }
     220                                Double per = (Double) getAttVal(Obj.RTPBCN, Att.SIGPER);
     221                                Double mxr = (Double) getAttVal(Obj.RTPBCN, Att.VALMXR);
     222                                if ((per != null) || (mxr != null)) {
     223                                        bstr += (astr.isEmpty() ? " " : "");
     224                                        if (per != null)
     225                                                bstr += (per != 0) ? per.toString() + "s" : "";
     226                                        if (mxr != null)
     227                                                bstr += (mxr != 0) ? mxr.toString() + "M" : "";
     228                                }
     229                                break;
     230                        default:
     231                                break;
     232                        }
     233                        if (!wal.isEmpty()) {
     234                                switch (wal) {
     235                                case "0.03-X":
     236                                        bstr += "(3cm)";
     237                                        break;
     238                                case "0.10-S":
     239                                        bstr += "(10cm)";
     240                                        break;
     241                                }
     242                        }
     243                        if (!bstr.isEmpty()) {
     244                                Renderer.labelText(bstr, new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -70)));
     245                        }
     246                }
     247        }
     248
     249        @SuppressWarnings("unchecked")
     250        public static void radioStations() {
     251                boolean vais = false;
     252                String bstr = "";
     253                if (Renderer.zoom >= 11) {
     254                        ArrayList<CatROS> cats = (ArrayList<CatROS>) getAttList(Obj.RDOSTA, Att.CATROS);
     255                        for (CatROS ros : cats) {
     256                                switch (ros) {
     257                                case ROS_OMNI:
     258                                        bstr += " RC";
     259                                        break;
     260                                case ROS_DIRL:
     261                                        bstr += " RD";
     262                                        break;
     263                                case ROS_ROTP:
     264                                        bstr += " RW";
     265                                        break;
     266                                case ROS_CNSL:
     267                                        bstr += " Consol";
     268                                        break;
     269                                case ROS_RDF:
     270                                        bstr += " RG";
     271                                        break;
     272                                case ROS_QTA:
     273                                        bstr += " R";
     274                                        break;
     275                                case ROS_AERO:
     276                                        bstr += " AeroRC";
     277                                        break;
     278                                case ROS_DECA:
     279                                        bstr += " Decca";
     280                                        break;
     281                                case ROS_LORN:
     282                                        bstr += " Loran";
     283                                        break;
     284                                case ROS_DGPS:
     285                                        bstr += " DGPS";
     286                                        break;
     287                                case ROS_TORN:
     288                                        bstr += " Toran";
     289                                        break;
     290                                case ROS_OMGA:
     291                                        bstr += " Omega";
     292                                        break;
     293                                case ROS_SYLD:
     294                                        bstr += " Syledis";
     295                                        break;
     296                                case ROS_CHKA:
     297                                        bstr += " Chiaka";
     298                                        break;
     299                                case ROS_PCOM:
     300                                case ROS_COMB:
     301                                case ROS_FACS:
     302                                case ROS_TIME:
     303                                        break;
     304                                case ROS_PAIS:
     305                                case ROS_SAIS:
     306                                        bstr += " AIS";
     307                                        break;
     308                                case ROS_VAIS:
     309                                        vais = true;
     310                                        break;
     311                                case ROS_VANC:
     312                                        vais = true;
     313                                        Renderer.symbol(Topmarks.TopNorth, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
     314                                        break;
     315                                case ROS_VASC:
     316                                        vais = true;
     317                                        Renderer.symbol(Topmarks.TopSouth, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
     318                                        break;
     319                                case ROS_VAEC:
     320                                        vais = true;
     321                                        Renderer.symbol(Topmarks.TopEast, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
     322                                        break;
     323                                case ROS_VAWC:
     324                                        vais = true;
     325                                        Renderer.symbol(Topmarks.TopWest, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
     326                                        break;
     327                                case ROS_VAPL:
     328                                        vais = true;
     329                                        Renderer.symbol(Topmarks.TopCan, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
     330                                        break;
     331                                case ROS_VASL:
     332                                        vais = true;
     333                                        Renderer.symbol(Topmarks.TopCone, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
     334                                        break;
     335                                case ROS_VAID:
     336                                        vais = true;
     337                                        Renderer.symbol(Topmarks.TopIsol, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
     338                                        break;
     339                                case ROS_VASW:
     340                                        vais = true;
     341                                        Renderer.symbol(Topmarks.TopSphere, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
     342                                        break;
     343                                case ROS_VASP:
     344                                        vais = true;
     345                                        Renderer.symbol(Topmarks.TopX, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
     346                                        break;
     347                                case ROS_VAWK:
     348                                        vais = true;
     349                                        Renderer.symbol(Topmarks.TopCross, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
     350                                        break;
     351                                default:
     352                                        break;
     353                                }
     354                        }
     355                        if (!vais) {
     356                                Renderer.symbol(Beacons.RadarStation);
     357                        }
     358                }
     359                if (Renderer.zoom >= 15) {
     360                        if (vais) {
     361                                Renderer.labelText("V-AIS", new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, 70)));
     362                        }
     363                        if (!bstr.isEmpty()) {
     364                                Renderer.labelText(bstr, new Font("Arial", Font.PLAIN, 40), Symbols.Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -110)));
     365                        }
     366                }
     367        }
     368
     369        static class Sect {
     370                int dir;
     371                LitCHR chr;
     372                ColCOL col;
     373                ColCOL alt;
     374                String grp;
     375                double per;
     376                double rng;
     377        }
     378
     379        @SuppressWarnings("unchecked")
     380        public static void lights() {
     381                Enum<ColCOL> col = null;
     382                Enum<ColCOL> tcol = null;
     383                ObjTab lights = feature.objs.get(Obj.LIGHTS);
     384                for (AttMap atts : lights.values()) {
     385                        if (atts.containsKey(Att.COLOUR)) {
     386                                ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val;
     387                                if (cols.size() == 1) {
     388                                        if (atts.containsKey(Att.CATLIT) && ((ArrayList<?>) atts.get(Att.CATLIT).val).contains(CatLIT.LIT_FLDL)) {
     389                                                Renderer.symbol(Beacons.Floodlight, new Delta(Handle.CC, AffineTransform.getRotateInstance(Math.toRadians(90))));
     390                                        } else {
     391                                                tcol = cols.get(0);
     392                                                if (col == null) {
     393                                                        col = tcol;
     394                                                } else if (tcol != col) {
     395                                                        col = ColCOL.COL_MAG;
     396                                                        break;
     397                                                }
     398                                        }
     399                                } else {
     400                                        col = ColCOL.COL_MAG;
     401                                        break;
     402                                }
     403                        }
     404                }
     405                if (col != null) {
     406                        Renderer.symbol(Beacons.LightFlare, new Scheme(LightColours.get(col)), new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.toRadians(120))));
     407                }
     408                if (Renderer.zoom >= 12) {
     409                        String str = "";
     410                        if (lights.get(1) != null) {
     411                                for (AttMap atts : lights.values()) {
     412                                        Enum<ColCOL> col1 = null;
     413                                        Enum<ColCOL> col2 = null;
     414                                        double radius = 0.2;
     415                                        double s1 = 361;
     416                                        double s2 = 361;
     417                                        Double dir = null;
     418                                        if (atts.containsKey(Att.COLOUR)) {
     419                                                ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val;
     420                                                col1 = cols.get(0);
     421                                                if (cols.size() > 1)
     422                                                        col2 = cols.get(1);
     423                                        } else {
     424                                                continue;
     425                                        }
     426                                        if (atts.containsKey(Att.CATLIT)) {
     427                                                ArrayList<CatLIT> cats = (ArrayList<CatLIT>) atts.get(Att.CATLIT).val;
     428                                                if (cats.contains(CatLIT.LIT_DIR)) {
     429                                                        if (atts.containsKey(Att.ORIENT)) {
     430                                                                dir = (Double) atts.get(Att.ORIENT).val;
     431                                                                s1 = ((dir - 4) + 360) % 360;
     432                                                                s2 = (dir + 4) % 360;
     433                                                                for (AttMap satts : lights.values()) {
     434                                                                        double srad = 0.2;
     435                                                                        double ss1 = 361;
     436                                                                        double ss2 = 361;
     437                                                                        Double sdir = null;
     438                                                                        if (satts == atts)
     439                                                                                continue;
     440                                                                        if (srad == radius) {
     441                                                                                ArrayList<CatLIT> scats = (ArrayList<CatLIT>) ((satts.containsKey(Att.CATLIT)) ? (ArrayList<CatLIT>) satts.get(Att.CATLIT).val : new ArrayList<>());
     442                                                                                if (scats.contains(CatLIT.LIT_DIR)) {
     443                                                                                        if (satts.containsKey(Att.ORIENT)) {
     444                                                                                                sdir = (Double) satts.get(Att.ORIENT).val;
     445                                                                                                ss1 = sdir;
     446                                                                                                ss2 = sdir;
     447                                                                                        }
     448                                                                                } else {
     449                                                                                        if (satts.containsKey(Att.SECTR1)) {
     450                                                                                                ss1 = (Double) satts.get(Att.SECTR1).val;
     451                                                                                        }
     452                                                                                        if (satts.containsKey(Att.SECTR2)) {
     453                                                                                                ss2 = (Double) satts.get(Att.SECTR2).val;
     454                                                                                        }
     455                                                                                }
     456                                                                                if ((ss1 > 360) || (ss2 > 360))
     457                                                                                        continue;
     458                                                                                if (sdir != null) {
     459                                                                                        if (((dir - sdir + 360) % 360) < 8) {
     460                                                                                                s1 = ((((sdir > dir) ? 360 : 0) + sdir + dir) / 2) % 360;
     461                                                                                        }
     462                                                                                        if (((sdir - dir + 360) % 360) < 8) {
     463                                                                                                s2 = ((((dir > sdir) ? 360 : 0) + sdir + dir) / 2) % 360;
     464                                                                                        }
     465                                                                                } else {
     466                                                                                        if (((dir - ss2 + 360) % 360) < 4) {
     467                                                                                                s1 = ss2;
     468                                                                                        }
     469                                                                                        if (((ss1 - dir + 360) % 360) < 4) {
     470                                                                                                s2 = ss1;
     471                                                                                        }
     472                                                                                }
     473                                                                        }
     474                                                                }
     475                                                        }
     476                                                }
     477                                        }
     478                                        if ((s1 > 360) && atts.containsKey(Att.SECTR1)) {
     479                                                s1 = (Double) atts.get(Att.SECTR1).val;
     480                                        } else if (dir == null) {
     481                                                continue;
     482                                        }
     483                                        if ((s2 > 360) && atts.containsKey(Att.SECTR2)) {
     484                                                s2 = (Double) atts.get(Att.SECTR2).val;
     485                                        } else if (dir == null) {
     486                                                continue;
     487                                        }
     488                                        str = "";
     489                                        if (atts.containsKey(Att.LITCHR)) {
     490                                                str += LightCharacters.get(((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0));
     491                                        }
     492                                        if (atts.containsKey(Att.SIGGRP)) {
     493                                                str += "(" + atts.get(Att.SIGGRP).val + ")";
     494                                        } else if (!str.isEmpty()) {
     495                                                str += ".";
     496                                        }
     497                                        if (atts.containsKey(Att.COLOUR)) {
     498                                                ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val;
     499                                                str += LightLetters.get(cols.get(0));
     500                                                if (cols.size() > 1)
     501                                                        str += LightLetters.get(cols.get(1));
     502                                        }
     503                                        if (atts.containsKey(Att.SIGPER)) {
     504                                                str += "." + df.format(atts.get(Att.SIGPER).val) + "s";
     505                                        }
     506                                        if ((s1 <= 360) && (s2 <= 360) && (s1 != s2))
     507                                                Renderer.lightSector(LightColours.get(col1), LightColours.get(col2), radius, s1, s2, dir, (Renderer.zoom >= 15) ? str : "");
     508                                }
     509                                if (Renderer.zoom >= 15) {
     510                                        class LitSect {
     511                                                boolean dir;
     512                                                LitCHR chr;
     513                                                ColCOL col;
     514                                                String grp;
     515                                                double per;
     516                                                double rng;
     517                                                double hgt;
     518                                        }
     519
     520                                        ArrayList<LitSect> litatts = new ArrayList<>();
     521                                        for (AttMap atts : lights.values()) {
     522                                                LitSect sect = new LitSect();
     523                                                sect.dir = (atts.containsKey(Att.CATLIT) && ((ArrayList<CatLIT>) atts.get(Att.CATLIT).val).contains(CatLIT.LIT_DIR));
     524                                                sect.chr = atts.containsKey(Att.LITCHR) ? ((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0) : LitCHR.CHR_UNKN;
     525                                                switch (sect.chr) {
     526                                                case CHR_AL:
     527                                                        sect.chr = LitCHR.CHR_F;
     528                                                        break;
     529                                                case CHR_ALOC:
     530                                                        sect.chr = LitCHR.CHR_OC;
     531                                                        break;
     532                                                case CHR_ALLFL:
     533                                                        sect.chr = LitCHR.CHR_LFL;
     534                                                        break;
     535                                                case CHR_ALFL:
     536                                                        sect.chr = LitCHR.CHR_FL;
     537                                                        break;
     538                                                case CHR_ALFFL:
     539                                                        sect.chr = LitCHR.CHR_FFL;
     540                                                        break;
     541                                                default:
     542                                                        break;
     543                                                }
     544                                                sect.grp = atts.containsKey(Att.SIGGRP) ? (String) atts.get(Att.SIGGRP).val : "";
     545                                                sect.per = atts.containsKey(Att.SIGPER) ? (Double) atts.get(Att.SIGPER).val : 0.0;
     546                                                sect.rng = atts.containsKey(Att.VALNMR) ? (Double) atts.get(Att.VALNMR).val : 0.0;
     547                                                sect.hgt = atts.containsKey(Att.HEIGHT) ? (Double) atts.get(Att.HEIGHT).val : 0.0;
     548                                                ArrayList<ColCOL> cols = (ArrayList<ColCOL>) (atts.containsKey(Att.COLOUR) ? atts.get(Att.COLOUR).val : new ArrayList<>());
     549                                                sect.col = cols.size() > 0 ? cols.get(0) : ColCOL.COL_UNK;
     550                                                if ((sect.chr != LitCHR.CHR_UNKN) && (sect.col != null))
     551                                                        litatts.add(sect);
     552                                        }
     553                                        ArrayList<ArrayList<LitSect>> groupings = new ArrayList<>();
     554                                        for (LitSect lit : litatts) {
     555                                                boolean found = false;
     556                                                for (ArrayList<LitSect> group : groupings) {
     557                                                        LitSect mem = group.get(0);
     558                                                        if ((lit.dir == mem.dir) && (lit.chr == mem.chr) && (lit.grp.equals(mem.grp)) && (lit.per == mem.per) && (lit.hgt == mem.hgt)) {
     559                                                                group.add(lit);
     560                                                                found = true;
     561                                                        }
     562                                                }
     563                                                if (!found) {
     564                                                        ArrayList<LitSect> tmp = new ArrayList<>();
     565                                                        tmp.add(lit);
     566                                                        groupings.add(tmp);
     567                                                }
     568                                        }
     569                                        for (boolean moved = true; moved;) {
     570                                                moved = false;
     571                                                for (int i = 0; i < groupings.size() - 1; i++) {
     572                                                        if (groupings.get(i).size() < groupings.get(i + 1).size()) {
     573                                                                ArrayList<LitSect> tmp = groupings.remove(i);
     574                                                                groupings.add(i + 1, tmp);
     575                                                                moved = true;
     576                                                        }
     577                                                }
     578                                        }
     579                                        class ColRng {
     580                                                ColCOL col;
     581                                                double rng;
     582
     583                                                ColRng(ColCOL c, double r) {
     584                                                        col = c;
     585                                                        rng = r;
     586                                                }
     587                                        }
     588
     589                                        int y = -30;
     590                                        for (ArrayList<LitSect> group : groupings) {
     591                                                ArrayList<ColRng> colrng = new ArrayList<>();
     592                                                for (LitSect lit : group) {
     593                                                        boolean found = false;
     594                                                        for (ColRng cr : colrng) {
     595                                                                if (cr.col == lit.col) {
     596                                                                        if (lit.rng > cr.rng) {
     597                                                                                cr.rng = lit.rng;
     598                                                                        }
     599                                                                        found = true;
     600                                                                }
     601                                                        }
     602                                                        if (!found) {
     603                                                                colrng.add(new ColRng(lit.col, lit.rng));
     604                                                        }
     605                                                }
     606                                                for (boolean moved = true; moved;) {
     607                                                        moved = false;
     608                                                        for (int i = 0; i < colrng.size() - 1; i++) {
     609                                                                if (colrng.get(i).rng < colrng.get(i + 1).rng) {
     610                                                                        ColRng tmp = colrng.remove(i);
     611                                                                        colrng.add(i + 1, tmp);
     612                                                                        moved = true;
     613                                                                }
     614                                                        }
     615                                                }
     616                                                LitSect tmp = group.get(0);
     617                                                str = (tmp.dir) ? "Dir" : "";
     618                                                str += LightCharacters.get(tmp.chr);
     619                                                if (!tmp.grp.isEmpty())
     620                                                        str += "(" + tmp.grp + ")";
     621                                                else
     622                                                        str += ".";
     623                                                for (ColRng cr : colrng) {
     624                                                        str += LightLetters.get(cr.col);
     625                                                }
     626                                                if ((tmp.per > 0) || (tmp.hgt > 0) || (colrng.get(0).rng > 0))
     627                                                        str += ".";
     628                                                if (tmp.per > 0)
     629                                                        str += df.format(tmp.per) + "s";
     630                                                if (tmp.hgt > 0)
     631                                                        str += df.format(tmp.hgt) + "m";
     632                                                if (colrng.get(0).rng > 0)
     633                                                        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";
     634                                                Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.TL, AffineTransform.getTranslateInstance(60, y)));
     635                                                y += 40;
     636                                                str = "";
     637                                        }
     638                                }
     639                        } else {
     640                                if (Renderer.zoom >= 15) {
     641                                        AttMap atts = lights.get(0);
     642                                        ArrayList<CatLIT> cats = new ArrayList<>();
     643                                        if (atts.containsKey(Att.CATLIT)) {
     644                                                cats = (ArrayList<CatLIT>) atts.get(Att.CATLIT).val;
     645                                        }
     646                                        str = (cats.contains(CatLIT.LIT_DIR)) ? "Dir" : "";
     647                                        str += (atts.containsKey(Att.MLTYLT)) ? atts.get(Att.MLTYLT).val : "";
     648                                        if (atts.containsKey(Att.LITCHR)) {
     649                                                LitCHR chr = ((ArrayList<LitCHR>) atts.get(Att.LITCHR).val).get(0);
     650                                                if (atts.containsKey(Att.SIGGRP)) {
     651                                                        String grp = (String) atts.get(Att.SIGGRP).val;
     652                                                        switch (chr) {
     653                                                        case CHR_QLFL:
     654                                                                str += String.format("Q(%s)+LFl", grp);
     655                                                                break;
     656                                                        case CHR_VQLFL:
     657                                                                str += String.format("VQ(%s)+LFl", grp);
     658                                                                break;
     659                                                        case CHR_UQLFL:
     660                                                                str += String.format("UQ(%s)+LFl", grp);
     661                                                                break;
     662                                                        default:
     663                                                                str += String.format("%s(%s)", LightCharacters.get(chr), grp);
     664                                                                break;
     665                                                        }
     666                                                } else {
     667                                                        str += LightCharacters.get(chr);
     668                                                }
     669                                        }
     670                                        if (atts.containsKey(Att.COLOUR)) {
     671                                                ArrayList<ColCOL> cols = (ArrayList<ColCOL>) atts.get(Att.COLOUR).val;
     672                                                if (!((cols.size() == 1) && (cols.get(0) == ColCOL.COL_WHT))) {
     673                                                        if (!str.isEmpty() && !str.endsWith(")")) {
     674                                                                str += ".";
     675                                                        }
     676                                                        for (ColCOL acol : cols) {
     677                                                                str += LightLetters.get(acol);
     678                                                        }
     679                                                }
     680                                        }
     681                                        str += (cats.contains(CatLIT.LIT_VERT)) ? "(vert)" : "";
     682                                        str += (cats.contains(CatLIT.LIT_HORI)) ? "(hor)" : "";
     683                                        str += (!str.isEmpty() && (atts.containsKey(Att.SIGPER) || atts.containsKey(Att.HEIGHT) || atts.containsKey(Att.VALMXR)) && !str.endsWith(")")) ? "." : "";
     684                                        str += (atts.containsKey(Att.SIGPER)) ? df.format(atts.get(Att.SIGPER).val) + "s" : "";
     685                                        str += (atts.containsKey(Att.HEIGHT)) ? df.format(atts.get(Att.HEIGHT).val) + "m" : "";
     686                                        str += (atts.containsKey(Att.VALNMR)) ? df.format(atts.get(Att.VALNMR).val) + "M" : "";
     687                                        str += (cats.contains(CatLIT.LIT_FRNT)) ? "(Front)" : "";
     688                                        str += (cats.contains(CatLIT.LIT_REAR)) ? "(Rear)" : "";
     689                                        str += (cats.contains(CatLIT.LIT_UPPR)) ? "(Upper)" : "";
     690                                        str += (cats.contains(CatLIT.LIT_LOWR)) ? "(Lower)" : "";
     691                                        Renderer.labelText(str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.TL, AffineTransform.getTranslateInstance(60, -30)));
     692                                }
     693                        }
     694                }
     695        }
    699696}
    700697
Note: See TracChangeset for help on using the changeset viewer.