001package armyc2.c5isr.JavaTacticalRenderer;
002
003import android.graphics.Bitmap;
004import android.graphics.BitmapShader;
005import android.graphics.Shader;
006
007import java.util.ArrayList;
008
009import armyc2.c5isr.JavaLineArray.CELineArray;
010import armyc2.c5isr.JavaLineArray.Channels;
011import armyc2.c5isr.JavaLineArray.POINT2;
012import armyc2.c5isr.JavaLineArray.Shape2;
013import armyc2.c5isr.JavaLineArray.TacticalLines;
014import armyc2.c5isr.JavaLineArray.arraysupport;
015import armyc2.c5isr.JavaLineArray.lineutility;
016import armyc2.c5isr.graphics2d.BasicStroke;
017import armyc2.c5isr.graphics2d.GeneralPath;
018import armyc2.c5isr.graphics2d.Rectangle2D;
019import armyc2.c5isr.graphics2d.TexturePaint;
020import armyc2.c5isr.renderer.PatternFillRenderer;
021import armyc2.c5isr.renderer.utilities.Color;
022import armyc2.c5isr.renderer.utilities.ErrorLogger;
023import armyc2.c5isr.renderer.utilities.RendererException;
024import armyc2.c5isr.renderer.utilities.RendererSettings;
025import armyc2.c5isr.renderer.utilities.ShapeInfo;
026import armyc2.c5isr.renderer.utilities.SymbolID;
027
028/**
029 * Class to calculate the points for the Weather symbols
030*
031 */
032public final class clsMETOC {
033    private static final String _className = "clsMETOC";
034    public static int getWeatherLinetype(int version, int entityCode)
035    {
036        switch(entityCode)
037        {
038            case 110301:
039                return TacticalLines.CF;
040            case 110302:
041                return TacticalLines.UCF;
042            case 110303:
043                return TacticalLines.CFG;
044            case 110304:
045                return TacticalLines.CFY;
046            case 110305:
047                return TacticalLines.WF;
048            case 110306:
049                return TacticalLines.UWF;
050            case 110307:
051                return TacticalLines.WFG;
052            case 110308:
053                return TacticalLines.WFY;
054            case 110309:
055                return TacticalLines.OCCLUDED;
056            case 110310:
057                return TacticalLines.UOF;
058            case 110311:
059                return TacticalLines.OFY;
060            case 110312:
061                return TacticalLines.SF;
062            case 110313:
063                return TacticalLines.USF;
064            case 110314:
065                return TacticalLines.SFG;
066            case 110315:
067                return TacticalLines.SFY;
068            case 110401:
069                return TacticalLines.TROUGH;
070            case 110402:
071                return TacticalLines.UPPER_TROUGH;
072            case 110403:
073                return TacticalLines.RIDGE;
074            case 110404:
075                return TacticalLines.SQUALL;
076            case 110405:
077                return TacticalLines.INSTABILITY;
078            case 110406:
079                return TacticalLines.SHEAR;
080            case 110407:
081                return TacticalLines.ITC;
082            case 110408:
083                return TacticalLines.CONVERGENCE;
084            case 110409:
085                return TacticalLines.ITD;
086            case 140300:
087                return TacticalLines.JET;
088            case 140400:
089                return TacticalLines.STREAM;
090            case 162004:            //tropical storm wind
091                break;
092            case 170100:
093                return TacticalLines.IFR;
094            case 170200:
095                return TacticalLines.MVFR;
096            case 170300:
097                return TacticalLines.TURBULENCE;
098            case 170400:
099                return TacticalLines.ICING;
100            case 170500:
101                return TacticalLines.NON_CONVECTIVE;
102            case 170501:
103                return TacticalLines.CONVECTIVE;
104            case 170600:
105                return TacticalLines.FROZEN;
106            case 170700:
107                return TacticalLines.THUNDERSTORMS;
108            case 170800:
109                return TacticalLines.FOG;                
110            case 170900:
111                return TacticalLines.SAND;
112            case 171000:
113                return TacticalLines.FREEFORM;
114            case 180100:
115                return TacticalLines.ISOBAR;
116            case 180200:
117                return TacticalLines.UPPER_AIR;
118            case 180300:
119                return TacticalLines.ISOTHERM;
120            case 180400:
121                return TacticalLines.ISOTACH;
122            case 180500:
123                return TacticalLines.ISODROSOTHERM;
124            case 180600:
125                return TacticalLines.ISOPLETHS;
126            case 180700:
127                return TacticalLines.OPERATOR_FREEFORM;
128            case 110501:
129                return TacticalLines.LVO;
130            case 110502:
131                return TacticalLines.UNDERCAST;
132            case 110503:
133                return TacticalLines.LRO;
134            case 110504:
135                return TacticalLines.ICE_EDGE;
136            case 110505:
137                return TacticalLines.ESTIMATED_ICE_EDGE;
138            case 110506:
139                return TacticalLines.ICE_EDGE_RADAR;
140            case 110601:
141                return TacticalLines.CRACKS;
142            case 110602:
143                return TacticalLines.CRACKS_SPECIFIC_LOCATION;
144            case 110603:
145                return TacticalLines.ICE_OPENINGS_LEAD;
146            case 110604:
147                return TacticalLines.ICE_OPENINGS_FROZEN;
148            case 120102:
149                return TacticalLines.DEPTH_CURVE;
150            case 120103:
151                return TacticalLines.DEPTH_CONTOUR;
152            case 120104:
153                return TacticalLines.DEPTH_AREA;
154            case 120201:
155                return TacticalLines.COASTLINE;
156            case 120202:
157                return TacticalLines.ISLAND;
158            case 120203:
159                return TacticalLines.BEACH;
160            case 120204:
161                return TacticalLines.WATER;
162            case 120205:
163                return TacticalLines.FORESHORE_LINE;
164            case 120206:
165                return TacticalLines.FORESHORE_AREA;
166            case 120305:
167                return TacticalLines.ANCHORAGE_LINE;
168            case 120306:
169                return TacticalLines.ANCHORAGE_AREA;
170                
171            case 120308:
172                return TacticalLines.PIER;
173            case 120312:
174                return TacticalLines.FISH_TRAPS;
175            case 120314:
176                return TacticalLines.DRYDOCK;
177            case 120317:
178                return TacticalLines.LOADING_FACILITY_LINE;
179            case 120318:
180                return TacticalLines.LOADING_FACILITY_AREA;
181                
182            case 120319:
183                return TacticalLines.RAMP_ABOVE_WATER;
184            case 120320:
185                return TacticalLines.RAMP_BELOW_WATER;
186                
187            case 120326:
188                return TacticalLines.JETTY_ABOVE_WATER;
189            case 120327:
190                return TacticalLines.JETTY_BELOW_WATER;
191            case 120328:
192                return TacticalLines.SEAWALL;
193            case 120405:
194                return TacticalLines.PERCHES;
195            case 120407:
196                return TacticalLines.LEADING_LINE;
197            case 120503:
198                return TacticalLines.UNDERWATER_HAZARD;
199            case 120505:
200                return TacticalLines.FOUL_GROUND;
201            case 120507:
202                return TacticalLines.KELP;
203            case 120511:
204                return TacticalLines.BREAKERS;
205            case 120512:
206                return TacticalLines.REEF;
207            case 120514:
208                return TacticalLines.DISCOLORED_WATER;
209            case 120702:
210                return TacticalLines.EBB_TIDE;
211            case 120703:
212                return TacticalLines.FLOOD_TIDE;
213                
214            case 130101:
215                return TacticalLines.VDR_LEVEL_12;
216            case 130102:
217                return TacticalLines.VDR_LEVEL_23;
218            case 130103:
219                return TacticalLines.VDR_LEVEL_34;
220            case 130104:
221                return TacticalLines.VDR_LEVEL_45;
222            case 130105:
223                return TacticalLines.VDR_LEVEL_56;
224            case 130106:
225                return TacticalLines.VDR_LEVEL_67;
226            case 130107:
227                return TacticalLines.VDR_LEVEL_78;
228            case 130108:
229                return TacticalLines.VDR_LEVEL_89;
230            case 130109:
231                return TacticalLines.VDR_LEVEL_910;
232            case 130201:
233                return TacticalLines.BEACH_SLOPE_FLAT;
234            case 130202:
235                return TacticalLines.BEACH_SLOPE_GENTLE;
236            case 130203:
237                return TacticalLines.BEACH_SLOPE_MODERATE;
238            case 130204:
239                return TacticalLines.BEACH_SLOPE_STEEP;
240            case 140101:
241                return TacticalLines.SOLID_ROCK;
242            case 140102:
243                return TacticalLines.CLAY;
244            case 140103:
245                return TacticalLines.VERY_COARSE_SAND;
246            case 140104:
247                return TacticalLines.COARSE_SAND;
248            case 140105:
249                return TacticalLines.MEDIUM_SAND;
250            case 140106:
251                return TacticalLines.FINE_SAND;
252            case 140107:
253                return TacticalLines.VERY_FINE_SAND;
254            case 140108:
255                return TacticalLines.VERY_FINE_SILT;
256            case 140109:
257                return TacticalLines.FINE_SILT;
258            case 140110:
259                return TacticalLines.MEDIUM_SILT;
260            case 140111:
261                return TacticalLines.COARSE_SILT;
262            case 140112:
263                return TacticalLines.BOULDERS;
264            case 140113:
265                return TacticalLines.OYSTER_SHELLS;
266            case 140114:
267                return TacticalLines.PEBBLES;
268            case 140115:
269                return TacticalLines.SAND_AND_SHELLS;
270            case 140116:
271                return TacticalLines.BOTTOM_SEDIMENTS_LAND;
272            case 140117:
273                return TacticalLines.BOTTOM_SEDIMENTS_NO_DATA;
274            case 140118:
275                return TacticalLines.BOTTOM_ROUGHNESS_SMOOTH;
276            case 140119:
277                return TacticalLines.BOTTOM_ROUGHNESS_MODERATE;
278            case 140120:
279                return TacticalLines.BOTTOM_ROUGHNESS_ROUGH;
280            case 140121:
281                return TacticalLines.CLUTTER_LOW;
282            case 140122:
283                return TacticalLines.CLUTTER_MEDIUM;
284            case 140123:
285                return TacticalLines.CLUTTER_HIGH;
286            case 140124:
287                return TacticalLines.IMPACT_BURIAL_0;
288            case 140125:
289                return TacticalLines.IMPACT_BURIAL_10;
290            case 140126:
291                return TacticalLines.IMPACT_BURIAL_20;
292            case 140127:
293                return TacticalLines.IMPACT_BURIAL_75;
294            case 140128:
295                return TacticalLines.IMPACT_BURIAL_100;
296            case 140129:
297                return TacticalLines.BOTTOM_CATEGORY_A;
298            case 140130:
299                return TacticalLines.BOTTOM_CATEGORY_B;
300            case 140131:
301                return TacticalLines.BOTTOM_CATEGORY_C;
302            case 140132:
303                return TacticalLines.BOTTOM_TYPE_A1;
304            case 140133:
305                return TacticalLines.BOTTOM_TYPE_A2;
306            case 140134:
307                return TacticalLines.BOTTOM_TYPE_A3;
308            case 140135:
309                return TacticalLines.BOTTOM_TYPE_B1;
310            case 140136:
311                return TacticalLines.BOTTOM_TYPE_B2;
312            case 140137:
313                return TacticalLines.BOTTOM_TYPE_B3;
314            case 140138:
315                return TacticalLines.BOTTOM_TYPE_C1;
316            case 140139:
317                return TacticalLines.BOTTOM_TYPE_C2;
318            case 140140:
319                return TacticalLines.BOTTOM_TYPE_C3;
320            
321            case 150100:
322                return TacticalLines.MARITIME_LIMIT;
323            case 150200:
324                return TacticalLines.MARITIME_AREA;
325            case 150300:
326                return TacticalLines.RESTRICTED_AREA;
327            case 150400:
328                return TacticalLines.SWEPT_AREA;
329            case 150500:
330                return TacticalLines.TRAINING_AREA;
331            case 150600:
332                return TacticalLines.OPERATOR_DEFINED;
333            case 160100:
334                return TacticalLines.CABLE;
335            case 160200:
336                return TacticalLines.SUBMERGED_CRIB;
337            case 160300:
338                return TacticalLines.CANAL;
339            case 160700:
340                return TacticalLines.OIL_RIG_FIELD;
341            case 160800:
342                return TacticalLines.PIPE;
343                
344            default:
345                return -1;
346        }
347        return -1;
348    }
349    /**
350     * @param symbolID Mil-Standard 2525 20-30 digit code
351     * @return the line type as an integer if it is a weather symbol, else return -1
352     */
353    public static int IsWeather(String symbolID) {
354        //the MeTOCs
355        try
356        {
357            if(symbolID==null)
358                return -1;
359
360            if(symbolID.length()>15)
361            {
362                int symbolSet = SymbolID.getSymbolSet(symbolID);
363                int entityCode = SymbolID.getEntityCode(symbolID);
364                int version = SymbolID.getVersion(symbolID);
365
366                switch(symbolSet)
367                {
368                    case 45:
369                    case 46:
370                        return getWeatherLinetype(version,entityCode);
371                }
372            }
373        } 
374        catch (Exception exc) {
375            //clsUtility.WriteFile("Error in clsMETOC.IsWeather");
376               ErrorLogger.LogException(_className ,"isWeather",
377                    new RendererException("Failed inside isWeather", exc));
378        }
379        return -1;
380    }
381/**
382 * Sets tactical graphic properties based on Mil-Std-2525 Appendix C.
383 * @param tg
384 */
385    private static void SetMeTOCProperties(TGLight tg) {
386        try
387        {
388            //METOC's have no user defined fills
389            //any fills per Mil-Std-2525 will be set below
390            //tg.set_FillColor(null);
391            String symbolId=tg.get_SymbolId();
392            switch (tg.get_LineType()) {   //255:150:150                    
393                case TacticalLines.SQUALL:
394                    tg.set_LineColor(Color.BLACK);
395                    tg.set_lineCap(BasicStroke.CAP_BUTT);
396                    break;
397                case TacticalLines.TROUGH:
398                    tg.set_LineStyle(1);
399                    tg.set_LineColor(Color.BLACK);
400                    tg.set_lineCap(BasicStroke.CAP_ROUND);
401                    break;
402                case TacticalLines.UPPER_TROUGH:
403                    tg.set_LineColor(Color.BLACK);
404                    tg.set_lineCap(BasicStroke.CAP_ROUND);
405                    break;
406                case TacticalLines.BOTTOM_TYPE_A1:
407                    tg.set_LineColor(new Color(48, 255, 0));   // green
408                    tg.set_FillColor(new Color(48, 255, 0));
409                    break;
410                case TacticalLines.BOTTOM_TYPE_A2:
411                    tg.set_LineColor(new Color(127, 255, 0));   //light green
412                    tg.set_FillColor(new Color(127, 255, 0));
413                    break;
414                case TacticalLines.BOTTOM_TYPE_C2:
415                    tg.set_LineColor(new Color(255, 80, 0));   //dark orange
416                    tg.set_FillColor(new Color(255, 80, 0));
417                    break;
418                case TacticalLines.BOTTOM_TYPE_C3:
419                    tg.set_LineColor(new Color(255, 48, 0));   //orange red
420                    tg.set_FillColor(new Color(255, 48, 0));
421                    break;
422                case TacticalLines.IMPACT_BURIAL_0:
423                    tg.set_LineColor(new Color(0, 0, 255));   //blue
424                    tg.set_FillColor(new Color(0, 0, 255));
425                    break;
426                case TacticalLines.BOTTOM_TYPE_C1:
427                case TacticalLines.IMPACT_BURIAL_75:
428                    tg.set_LineColor(new Color(255, 127, 0));   //orange
429                    tg.set_FillColor(new Color(255, 127, 0));
430                    break;
431                case TacticalLines.BOTTOM_CATEGORY_C:
432                case TacticalLines.IMPACT_BURIAL_100:
433                case TacticalLines.CLUTTER_HIGH:
434                case TacticalLines.BOTTOM_ROUGHNESS_ROUGH:
435                    tg.set_LineColor(new Color(255, 0, 0));   //red
436                    tg.set_FillColor(new Color(255, 0, 0));
437                    break;
438                case TacticalLines.BOTTOM_TYPE_B2:
439                case TacticalLines.BOTTOM_CATEGORY_B:
440                case TacticalLines.IMPACT_BURIAL_20:
441                case TacticalLines.CLUTTER_MEDIUM:
442                case TacticalLines.BOTTOM_ROUGHNESS_MODERATE:
443                    tg.set_LineColor(new Color(255, 255, 0));   //yellow
444                    tg.set_FillColor(new Color(255, 255, 0));
445                    break;
446                case TacticalLines.BOTTOM_CATEGORY_A:
447                case TacticalLines.IMPACT_BURIAL_10:
448                case TacticalLines.CLUTTER_LOW:
449                case TacticalLines.BOTTOM_ROUGHNESS_SMOOTH:
450                    tg.set_LineColor(new Color(0, 255, 0));   //green
451                    tg.set_FillColor(new Color(0, 255, 0));
452                    break;
453                case TacticalLines.BOTTOM_SEDIMENTS_NO_DATA:
454                    tg.set_LineColor(new Color(230, 230, 230));   //light gray
455                    tg.set_FillColor(new Color(230, 230, 230));
456                    break;
457                case TacticalLines.BOTTOM_SEDIMENTS_LAND:
458                    tg.set_LineColor(new Color(220, 220, 220));   //gray
459                    tg.set_FillColor(new Color(220, 220, 220));
460                    break;
461                case TacticalLines.SAND_AND_SHELLS:
462                    tg.set_LineColor(new Color(255, 220, 220));   //light peach
463                    tg.set_FillColor(new Color(255, 220, 220));
464                    break;
465                case TacticalLines.PEBBLES:
466                    tg.set_LineColor(new Color(255, 190, 190));   //peach
467                    tg.set_FillColor(new Color(255, 190, 190));
468                    break;
469                case TacticalLines.OYSTER_SHELLS:
470                    tg.set_LineColor(new Color(255, 150, 150));   //dark peach
471                    tg.set_FillColor(new Color(255, 150, 150));
472                    break;
473                case TacticalLines.BOULDERS:
474                    tg.set_LineColor(new Color(255, 0, 0));
475                    tg.set_FillColor(new Color(255, 0, 0));
476                    break;
477                case TacticalLines.COARSE_SILT:
478                    tg.set_LineColor(new Color(200, 255, 105));
479                    tg.set_FillColor(new Color(200, 255, 105));
480                    break;
481                case TacticalLines.MEDIUM_SILT:
482                    tg.set_LineColor(new Color(0, 255, 0));     //green
483                    tg.set_FillColor(new Color(0, 255, 0));
484                    break;
485                case TacticalLines.FINE_SILT:
486                    tg.set_LineColor(new Color(25, 255, 230));     //turquoise
487                    tg.set_FillColor(new Color(25, 255, 230));
488                    break;
489                case TacticalLines.VERY_FINE_SILT:
490                    tg.set_LineColor(new Color(0, 215, 255));     //turquoise
491                    tg.set_FillColor(new Color(0, 215, 255));
492                    break;
493                case TacticalLines.VERY_FINE_SAND:
494                    tg.set_LineColor(new Color(255, 255, 220));     //pale yellow
495                    tg.set_FillColor(new Color(255, 255, 220));
496                    break;
497                case TacticalLines.FINE_SAND:
498                    tg.set_LineColor(new Color(255, 255, 140));     //light yellow
499                    tg.set_FillColor(new Color(255, 255, 140));
500                    break;
501                case TacticalLines.MEDIUM_SAND:
502                    tg.set_LineColor(new Color(255, 235, 0));     //yellow
503                    tg.set_FillColor(new Color(255, 235, 0));
504                    break;
505                case TacticalLines.COARSE_SAND:
506                    tg.set_LineColor(new Color(255, 215, 0));     //light gold
507                    tg.set_FillColor(new Color(255, 215, 0));
508                    break;
509                case TacticalLines.BOTTOM_TYPE_B3:
510                    tg.set_LineColor(new Color(255, 207, 0));     //gold
511                    tg.set_FillColor(new Color(255, 207, 0));
512                    break;
513                case TacticalLines.VERY_COARSE_SAND:
514                    tg.set_LineColor(new Color(255, 180, 0));     //gold
515                    tg.set_FillColor(new Color(255, 180, 0));
516                    break;
517                case TacticalLines.CLAY:
518                    tg.set_LineColor(new Color(100, 130, 255));     //periwinkle
519                    tg.set_FillColor(new Color(100, 130, 255));
520                    break;
521                case TacticalLines.SOLID_ROCK:
522                    //tg.set_LineColor(new Color(160, 32, 240));     //purple
523                    //tg.set_FillColor(new Color(160, 32, 240));
524                    tg.set_LineColor(new Color(255, 0, 255));     //magenta
525                    tg.set_FillColor(new Color(255, 0, 255));
526                    break;
527                case TacticalLines.VDR_LEVEL_12:
528                    tg.set_LineColor(new Color(26, 153, 77));     //dark green
529                    tg.set_FillColor(new Color(26, 153, 77));
530                    break;
531                case TacticalLines.VDR_LEVEL_23:
532                    tg.set_LineColor(new Color(26, 204, 77));     //light green
533                    tg.set_FillColor(new Color(26, 204, 77));
534                    break;
535                case TacticalLines.BOTTOM_TYPE_A3:
536                    tg.set_LineColor(new Color(175, 255, 0));    //lime green
537                    tg.set_FillColor(new Color(175, 255, 0));
538                    break;
539                case TacticalLines.VDR_LEVEL_34:
540                    tg.set_LineColor(new Color(128, 255, 51));    //lime green
541                    tg.set_FillColor(new Color(128, 255, 51));
542                    break;
543                case TacticalLines.BOTTOM_TYPE_B1:
544                    tg.set_LineColor(new Color(207, 255, 0));    //yellow green
545                    tg.set_FillColor(new Color(207, 255, 0));
546                    break;
547                case TacticalLines.VDR_LEVEL_45:
548                    tg.set_LineColor(new Color(204, 255, 26));    //yellow green
549                    tg.set_FillColor(new Color(204, 255, 26));
550                    break;
551                case TacticalLines.VDR_LEVEL_56:
552                    tg.set_LineColor(new Color(255, 255, 0));     //yellow
553                    tg.set_FillColor(new Color(255, 255, 0));
554                    break;
555                case TacticalLines.VDR_LEVEL_67:
556                    tg.set_LineColor(new Color(255, 204, 0));     //gold
557                    tg.set_FillColor(new Color(255, 204, 0));
558                    break;
559                case TacticalLines.VDR_LEVEL_78:
560                    tg.set_LineColor(new Color(255, 128, 0));     //light orange
561                    tg.set_FillColor(new Color(255, 128, 0));
562                    break;
563                case TacticalLines.VDR_LEVEL_89:
564                    tg.set_LineColor(new Color(255, 77, 0));      //dark orange
565                    tg.set_FillColor(new Color(255, 77, 0));
566                    break;
567                case TacticalLines.VDR_LEVEL_910:
568                    tg.set_LineColor(Color.RED);
569                    tg.set_FillColor(Color.RED);
570                    break;
571                case TacticalLines.CANAL:
572                    tg.set_LineColor(Color.BLACK);
573                    tg.set_LineThickness(2 * tg.get_LineThickness()); // Thick line
574                    break;
575                case TacticalLines.OPERATOR_DEFINED:
576                    tg.set_LineColor(Color.ORANGE);
577                    break;
578                case TacticalLines.MARITIME_LIMIT:
579                case TacticalLines.MARITIME_AREA:
580                    tg.set_LineColor(Color.MAGENTA);
581                    tg.set_LineStyle(1);
582                    break;
583                case TacticalLines.PERCHES:
584                case TacticalLines.SUBMERGED_CRIB:
585                    tg.set_LineColor(Color.BLACK);
586                    tg.set_LineStyle(2);
587                    tg.set_lineCap(BasicStroke.CAP_ROUND);
588                    tg.set_FillColor(Color.BLUE);
589                    break;
590                case TacticalLines.DISCOLORED_WATER:
591                case TacticalLines.UNDERWATER_HAZARD:
592                    tg.set_LineColor(Color.BLACK);
593                    tg.set_LineStyle(2);
594                    tg.set_FillColor(new Color(0, 191, 255)); //deep sky blue
595                    break;
596                case TacticalLines.LOADING_FACILITY_AREA:
597                    tg.set_LineColor(new Color(210, 180, 140));
598                    tg.set_FillColor(new Color(210, 180, 140));
599                    break;
600                case TacticalLines.LOADING_FACILITY_LINE:
601                    tg.set_LineColor(Color.GRAY);
602                    tg.set_LineThickness(2 * tg.get_LineThickness()); // Thick line
603                    break;
604                case TacticalLines.DRYDOCK:
605                    tg.set_LineColor(Color.BLACK);
606                    //tg.set_FillColor(new Color(165, 42, 42)); //brown
607                    tg.set_FillColor(new Color(205, 133, 63)); //brown
608                    tg.set_LineStyle(1);
609                    break;
610                case TacticalLines.FORESHORE_AREA:
611                    //tg.set_LineColor(new Color(154, 205, 50));
612                    //tg.set_FillColor(new Color(154, 205, 50));
613                    tg.set_LineColor(new Color(173, 255, 47));
614                    tg.set_FillColor(new Color(173, 255, 47));
615                    break;
616                case TacticalLines.FORESHORE_LINE:
617                    //tg.set_LineColor(new Color(154, 205, 50));
618                    tg.set_LineColor(new Color(173, 255, 47));
619                    break;
620                case TacticalLines.RESTRICTED_AREA:
621                case TacticalLines.TRAINING_AREA:
622                case TacticalLines.ANCHORAGE_LINE:
623                case TacticalLines.ANCHORAGE_AREA:
624                    tg.set_LineColor(Color.MAGENTA);
625                    //tg.set_LineStyle(1);    //dashed
626                    break;
627                case TacticalLines.PIPE:
628                    tg.set_LineColor(Color.GRAY);
629                    tg.set_FillColor(Color.GRAY);
630                    break;
631                case TacticalLines.WATER:
632                    tg.set_LineColor(Color.WHITE);
633                    tg.set_FillColor(Color.WHITE);
634                    break;
635                case TacticalLines.FISH_TRAPS:
636                    tg.set_LineColor(new Color(192,192,192));
637                    tg.set_LineStyle(1);
638                    break;
639                case TacticalLines.SWEPT_AREA:
640                case TacticalLines.OIL_RIG_FIELD:
641                case TacticalLines.FOUL_GROUND:
642                case TacticalLines.KELP:
643                    tg.set_LineColor(null);
644                    break;
645                case TacticalLines.BEACH:
646                    tg.set_LineColor(new Color(206, 158, 140));
647                    tg.set_FillColor(new Color(206, 158, 140, (int) (255 * 0.12)));
648                    break;
649                case TacticalLines.DEPTH_AREA:
650                    tg.set_LineColor(Color.BLUE);
651                    tg.set_FillColor(Color.WHITE);
652                    break;
653                case TacticalLines.CONVERGENCE:
654                case TacticalLines.ITC:
655                    tg.set_LineColor(Color.ORANGE);
656                    tg.set_lineCap(BasicStroke.CAP_BUTT);
657                    break;
658                case TacticalLines.OFY:
659                case TacticalLines.OCCLUDED:
660                    tg.set_LineColor(new Color(160, 32, 240));
661                    tg.set_FillColor(new Color(160, 32, 240));
662                    break;
663                case TacticalLines.UOF:
664                    tg.set_LineColor(new Color(160, 32, 240));
665                    break;
666                case TacticalLines.WFY:
667                case TacticalLines.WFG:
668                case TacticalLines.WF:
669                    tg.set_FillColor(Color.RED);
670                    tg.set_LineColor(Color.RED);
671                    break;
672                case TacticalLines.UWF:
673                case TacticalLines.IFR:
674                    tg.set_LineColor(Color.RED);
675                    break;
676                case TacticalLines.CFG:
677                case TacticalLines.CFY:
678                case TacticalLines.CF:
679                    tg.set_LineColor(Color.BLUE);
680                    tg.set_FillColor(Color.BLUE);
681                    break;
682                case TacticalLines.UCF:
683                case TacticalLines.MVFR:
684                    tg.set_LineColor(Color.BLUE);
685                    break;
686                case TacticalLines.TURBULENCE:
687                    tg.set_LineColor(Color.BLUE);
688                    tg.set_LineStyle(2);
689                    tg.set_lineCap(BasicStroke.CAP_ROUND);
690                    int minThickness = Math.max(RendererSettings.getInstance().getDeviceDPI() / 96, 1) * 6;
691                    if (tg.get_LineThickness() < minThickness)
692                        tg.set_LineThickness(minThickness);
693                    break;
694                case TacticalLines.CABLE:
695                    tg.set_LineColor(Color.MAGENTA);
696                    break;
697                case TacticalLines.ISLAND:
698                    //tg.set_LineColor(new Color(165, 42, 42)); //brown
699                    //tg.set_FillColor(new Color(165, 42, 42)); //brown
700                    tg.set_LineColor(new Color(210, 180, 140)); //tan
701                    tg.set_FillColor(new Color(210, 180, 140)); //tan
702                    break;
703                case TacticalLines.SEAWALL:
704                case TacticalLines.SEAWALL_GE:
705                case TacticalLines.FLOOD_TIDE:
706                case TacticalLines.FLOOD_TIDE_GE:
707                case TacticalLines.EBB_TIDE:
708                case TacticalLines.EBB_TIDE_GE:
709                case TacticalLines.JETTY_ABOVE_WATER:
710                case TacticalLines.JETTY_ABOVE_WATER_GE:
711                    tg.set_LineColor(Color.GRAY);
712                    break;
713                case TacticalLines.BEACH_SLOPE_MODERATE:
714                case TacticalLines.BEACH_SLOPE_FLAT:
715                    tg.set_LineColor(new Color(179, 179, 179));
716                    tg.set_FillColor(null);
717                    break;
718                case TacticalLines.BEACH_SLOPE_GENTLE:
719                case TacticalLines.BEACH_SLOPE_STEEP:
720                    tg.set_LineColor(new Color(128, 128, 128));
721                    tg.set_FillColor(null);
722                    break;
723                case TacticalLines.BREAKERS:
724                    tg.set_LineStyle(1);
725                    tg.set_LineColor(Color.GRAY);
726                    break;
727                case TacticalLines.JETTY_BELOW_WATER:
728                case TacticalLines.JETTY_BELOW_WATER_GE:
729                    tg.set_LineStyle(1);
730                    tg.set_LineColor(Color.GRAY);
731                    break;
732                case TacticalLines.DEPTH_CURVE:
733                case TacticalLines.DEPTH_CURVE_GE:
734                case TacticalLines.DEPTH_CONTOUR:
735                case TacticalLines.DEPTH_CONTOUR_GE:
736                case TacticalLines.COASTLINE:
737                case TacticalLines.COASTLINE_GE:
738                case TacticalLines.PIER:
739                case TacticalLines.PIER_GE:
740                    tg.set_LineColor(Color.GRAY);
741                    break;
742                case TacticalLines.FROZEN:
743                case TacticalLines.JET:
744                case TacticalLines.JET_GE:
745                    tg.set_LineColor(Color.RED);
746                    break;
747                case TacticalLines.THUNDERSTORMS:
748                    tg.set_LineColor(Color.RED);
749                    tg.set_LineStyle(3);
750                    break;
751                case TacticalLines.RAMP_BELOW_WATER:
752                case TacticalLines.RAMP_BELOW_WATER_GE:
753                case TacticalLines.ESTIMATED_ICE_EDGE:
754                case TacticalLines.ESTIMATED_ICE_EDGE_GE:
755                    tg.set_LineStyle(1);
756                    tg.set_LineColor(Color.BLACK);
757                    break;
758                case TacticalLines.ISODROSOTHERM:
759                case TacticalLines.ISODROSOTHERM_GE:
760                    tg.set_LineColor(Color.GREEN);
761                    break;
762                case TacticalLines.LRO:
763                case TacticalLines.UNDERCAST:
764                case TacticalLines.LVO:
765                case TacticalLines.RIDGE:
766                //case TacticalLines.TROUGH:
767                case TacticalLines.ICE_OPENINGS_LEAD:
768                case TacticalLines.ICE_OPENINGS_LEAD_GE:
769                case TacticalLines.ICE_OPENINGS_FROZEN:
770                case TacticalLines.ICE_OPENINGS_FROZEN_GE:
771                case TacticalLines.LEADING_LINE:
772                case TacticalLines.STREAM:
773                case TacticalLines.STREAM_GE:
774                case TacticalLines.CRACKS:
775                case TacticalLines.CRACKS_GE:
776                case TacticalLines.CRACKS_SPECIFIC_LOCATION:
777                case TacticalLines.CRACKS_SPECIFIC_LOCATION_GE:
778                case TacticalLines.ISOBAR:
779                case TacticalLines.ISOBAR_GE:
780                case TacticalLines.UPPER_AIR:
781                case TacticalLines.UPPER_AIR_GE:
782                case TacticalLines.ICE_EDGE:
783                case TacticalLines.ICE_EDGE_GE:
784                case TacticalLines.ICE_EDGE_RADAR:
785                case TacticalLines.ICE_EDGE_RADAR_GE:
786                case TacticalLines.REEF:
787                    tg.set_LineColor(Color.BLACK);
788                    break;
789                case TacticalLines.INSTABILITY:
790                    tg.set_LineStyle(4);
791                    tg.set_lineCap(BasicStroke.CAP_ROUND);
792                    tg.set_LineColor(Color.BLACK);
793                    break;
794                case TacticalLines.SHEAR:
795                    tg.set_LineStyle(3);
796                    tg.set_lineCap(BasicStroke.CAP_ROUND);
797                    tg.set_LineColor(Color.BLACK);
798                    break;
799                case TacticalLines.ISOPLETHS:
800                case TacticalLines.ISOPLETHS_GE:
801                case TacticalLines.ISOTHERM:
802                case TacticalLines.ISOTHERM_GE:
803                    tg.set_LineStyle(1);
804                    tg.set_LineColor(Color.RED);
805                    break;
806                case TacticalLines.ISOTACH:
807                case TacticalLines.ISOTACH_GE:
808                    tg.set_LineStyle(1);
809                    tg.set_LineColor(new Color(160, 32, 240));
810                    break;
811                case TacticalLines.SAND:
812                    tg.set_LineColor(new Color(165, 121, 82)); //brown
813                    break;
814                case TacticalLines.ICING:
815                    tg.set_LineColor(new Color(189, 154, 56)); //brown
816                    break;
817                case TacticalLines.NON_CONVECTIVE:
818                    tg.set_LineColor(Color.GREEN);
819                    break;
820                case TacticalLines.CONVECTIVE:
821                    tg.set_LineColor(Color.GREEN);
822                    tg.set_LineStyle(3);
823                    break;
824                case TacticalLines.FOG:
825                    tg.set_LineColor(Color.YELLOW);
826                    break;
827                case TacticalLines.RAMP_ABOVE_WATER:
828                case TacticalLines.RAMP_ABOVE_WATER_GE:
829                    tg.set_LineColor(Color.BLACK);
830                    break;
831                default:
832                    break;
833            }
834        }
835        catch (Exception exc) {
836            //clsUtility.WriteFile("Error in clsMETOC.SetMeTOCProperties");
837               ErrorLogger.LogException(_className ,"SetMeTOCProperties",
838                    new RendererException("Failed inside SetMeTOCProperties", exc));
839        }
840    }
841
842    /**
843     *
844     * Rotates axis by theta for point and curve
845     * Finds next closest point with same x position on the splinePoints curve as pt
846     * walks up the curve and if it does not find a range that straddles x it return null.
847     * We ultimately will draw a line from pt to the extrapolated point on the splinePoints spline.
848     * used for ICE_OPENINGS_FROZEN_LEAD
849     *
850     * @param splinePoints - the points on the opposite spline
851     * @param pt - the point in the original curve from which the line will start
852     * @param theta angle of curve at pt. Perpendicular to new line to be drawn
853     *
854     * @return The extrapolated point on the opposite spline to which the line will be drawn
855     */
856    private static POINT2 ExtrapolatePointFromCurve(ArrayList<POINT2> splinePoints,
857                                                    POINT2 pt, double theta) {
858        try {
859            // cos(theta) and sin(theta) only need to be calculated once
860            final double cosTheta = Math.cos(theta);
861            final double sinTheta = Math.sin(theta);
862
863            // p at the end of variable name represents "prime" and means it's a rotated coordinate
864            double xp = pt.x * cosTheta + pt.y * sinTheta;
865
866            //if we find a pair which straddle xp then extrapolate the y value from the curve and
867            //return the point
868            for (int j = 0; j < splinePoints.size() - 1; j++) {
869                double x1p = splinePoints.get(j).x * cosTheta + splinePoints.get(j).y * sinTheta;
870                double x2p = splinePoints.get(j + 1).x * cosTheta + splinePoints.get(j + 1).y * sinTheta;
871                if ((x1p <= xp && x2p >= xp) || (x1p >= xp && x2p <= xp)) {
872                    double y1p = -splinePoints.get(j).x * sinTheta + splinePoints.get(j).y * cosTheta;
873                    double y2p = -splinePoints.get(j + 1).x * sinTheta + splinePoints.get(j + 1).y * cosTheta;
874
875                    double mp = (y2p - y1p) / (x2p - x1p); // slope
876                    double yp = y1p + (xp - x1p) * mp;
877
878                    // Rotate back to normal coordinates
879                    double x = xp * cosTheta - yp * sinTheta;
880                    double y = xp * sinTheta + yp * cosTheta;
881                    return new POINT2(x, y);
882                }
883            }
884        } catch (Exception exc) {
885            ErrorLogger.LogException(_className, "ExtrapolatePointFromCurve",
886                    new RendererException("Failed inside ExtrapolatePointFromCurve", exc));
887        }
888        return null;
889    }
890    /**
891     * The public interface, main function to return METOC shapes
892     * @param tg the tactical graphic
893     * @param shapes the ShapeInfo array
894     */
895    public static void GetMeTOCShape(TGLight tg, 
896            ArrayList<Shape2> shapes) {
897        try
898        {
899            if(shapes==null)
900                return;
901            GeneralPath lineObject = null;
902            GeneralPath lineObject2 = null;
903            ArrayList<POINT2> splinePoints = new ArrayList();
904            ArrayList<POINT2> splinePoints2 = new ArrayList();
905            double d = 0;
906            int j = 0, k=0, l=0;
907            Shape2 shape=null;
908            POINT2 ptLast = tg.Pixels.get(tg.Pixels.size() - 1);
909            ArrayList<POINT2> twoSplines = null;
910            ArrayList<POINT2> upperSpline = null;
911            ArrayList<POINT2> lowerSpline = null;
912            ArrayList<POINT2> originalPixels = null;
913            int t=0,u=0,v=0,w=0,tt=0,uu=0,vv=0,ww=0;
914            
915            ArrayList<POINT2>pixels=null;
916            originalPixels=null;
917            ArrayList<P1>partitions=null;
918            SetMeTOCProperties(tg);
919            switch (tg.get_LineType()) {
920                case TacticalLines.SF:
921                case TacticalLines.USF:
922                case TacticalLines.SFG:
923                case TacticalLines.SFY:
924                case TacticalLines.WFY:
925                case TacticalLines.WFG:
926                case TacticalLines.WF:
927                case TacticalLines.UWF:
928                case TacticalLines.UCF:
929                case TacticalLines.CF:
930                case TacticalLines.CFG:
931                case TacticalLines.CFY:
932                case TacticalLines.OCCLUDED:
933                case TacticalLines.UOF:
934                case TacticalLines.OFY:
935                case TacticalLines.TROUGH:
936                case TacticalLines.UPPER_TROUGH:
937                case TacticalLines.CABLE:
938                case TacticalLines.INSTABILITY:
939                case TacticalLines.SHEAR:
940                case TacticalLines.RIDGE:
941                case TacticalLines.SQUALL:
942                case TacticalLines.ITC:
943                case TacticalLines.CONVERGENCE:
944                case TacticalLines.ITD:
945                case TacticalLines.IFR:
946                case TacticalLines.MVFR:
947                case TacticalLines.TURBULENCE:
948                case TacticalLines.ICING:
949                case TacticalLines.NON_CONVECTIVE:
950                case TacticalLines.CONVECTIVE:
951                case TacticalLines.FROZEN:
952                case TacticalLines.THUNDERSTORMS:
953                case TacticalLines.FOG:
954                case TacticalLines.SAND:
955                case TacticalLines.FREEFORM:
956                case TacticalLines.OPERATOR_FREEFORM:
957                case TacticalLines.LVO:
958                case TacticalLines.UNDERCAST:
959                case TacticalLines.LRO:
960                case TacticalLines.DEPTH_AREA:
961                case TacticalLines.ISLAND:
962                case TacticalLines.BEACH:
963                case TacticalLines.WATER:
964                case TacticalLines.FISH_TRAPS:
965                case TacticalLines.SWEPT_AREA:
966                case TacticalLines.OIL_RIG_FIELD:
967                case TacticalLines.FOUL_GROUND:
968                case TacticalLines.KELP:
969                case TacticalLines.BEACH_SLOPE_MODERATE:
970                case TacticalLines.BEACH_SLOPE_STEEP:
971                case TacticalLines.ANCHORAGE_AREA:
972                case TacticalLines.ANCHORAGE_LINE:
973                case TacticalLines.PIPE:
974                case TacticalLines.TRAINING_AREA:
975                case TacticalLines.RESTRICTED_AREA:
976                case TacticalLines.REEF:
977                case TacticalLines.FORESHORE_AREA:
978                case TacticalLines.FORESHORE_LINE:
979                case TacticalLines.DRYDOCK:
980                case TacticalLines.LOADING_FACILITY_LINE:
981                case TacticalLines.LOADING_FACILITY_AREA:
982                case TacticalLines.PERCHES:
983                case TacticalLines.UNDERWATER_HAZARD:
984                case TacticalLines.BREAKERS:
985                case TacticalLines.DISCOLORED_WATER:
986                case TacticalLines.BEACH_SLOPE_FLAT:
987                case TacticalLines.BEACH_SLOPE_GENTLE:
988                case TacticalLines.MARITIME_LIMIT:
989                case TacticalLines.MARITIME_AREA:
990                case TacticalLines.OPERATOR_DEFINED:
991                case TacticalLines.SUBMERGED_CRIB:
992                case TacticalLines.CANAL:
993                case TacticalLines.VDR_LEVEL_12:
994                case TacticalLines.VDR_LEVEL_23:
995                case TacticalLines.VDR_LEVEL_34:
996                case TacticalLines.VDR_LEVEL_45:
997                case TacticalLines.VDR_LEVEL_56:
998                case TacticalLines.VDR_LEVEL_67:
999                case TacticalLines.VDR_LEVEL_78:
1000                case TacticalLines.VDR_LEVEL_89:
1001                case TacticalLines.VDR_LEVEL_910:
1002                case TacticalLines.SOLID_ROCK:
1003                case TacticalLines.CLAY:
1004                case TacticalLines.VERY_COARSE_SAND:
1005                case TacticalLines.COARSE_SAND:
1006                case TacticalLines.MEDIUM_SAND:
1007                case TacticalLines.FINE_SAND:
1008                case TacticalLines.VERY_FINE_SAND:
1009                case TacticalLines.VERY_FINE_SILT:
1010                case TacticalLines.FINE_SILT:
1011                case TacticalLines.MEDIUM_SILT:
1012                case TacticalLines.COARSE_SILT:
1013                case TacticalLines.BOULDERS:
1014                case TacticalLines.OYSTER_SHELLS:
1015                case TacticalLines.PEBBLES:
1016                case TacticalLines.SAND_AND_SHELLS:
1017                case TacticalLines.BOTTOM_SEDIMENTS_LAND:
1018                case TacticalLines.BOTTOM_SEDIMENTS_NO_DATA:
1019                case TacticalLines.BOTTOM_ROUGHNESS_SMOOTH:
1020                case TacticalLines.BOTTOM_ROUGHNESS_MODERATE:
1021                case TacticalLines.BOTTOM_ROUGHNESS_ROUGH:
1022                case TacticalLines.CLUTTER_LOW:
1023                case TacticalLines.CLUTTER_MEDIUM:
1024                case TacticalLines.CLUTTER_HIGH:
1025                case TacticalLines.IMPACT_BURIAL_0:
1026                case TacticalLines.IMPACT_BURIAL_10:
1027                case TacticalLines.IMPACT_BURIAL_20:
1028                case TacticalLines.IMPACT_BURIAL_75:
1029                case TacticalLines.IMPACT_BURIAL_100:
1030                case TacticalLines.BOTTOM_CATEGORY_A:
1031                case TacticalLines.BOTTOM_CATEGORY_B:
1032                case TacticalLines.BOTTOM_CATEGORY_C:
1033                case TacticalLines.BOTTOM_TYPE_A1:
1034                case TacticalLines.BOTTOM_TYPE_A2:
1035                case TacticalLines.BOTTOM_TYPE_A3:
1036                case TacticalLines.BOTTOM_TYPE_B1:
1037                case TacticalLines.BOTTOM_TYPE_B2:
1038                case TacticalLines.BOTTOM_TYPE_B3:
1039                case TacticalLines.BOTTOM_TYPE_C1:
1040                case TacticalLines.BOTTOM_TYPE_C2:
1041                case TacticalLines.BOTTOM_TYPE_C3:
1042                    arraysupport.GetLineArray2(tg, tg.Pixels, shapes,null,null);
1043                    break;
1044                case TacticalLines.ISOBAR:
1045                case TacticalLines.ISOBAR_GE:
1046                case TacticalLines.UPPER_AIR:
1047                case TacticalLines.UPPER_AIR_GE:
1048                case TacticalLines.ISOTHERM:
1049                case TacticalLines.ISOTHERM_GE:
1050                case TacticalLines.ISOTACH:
1051                case TacticalLines.ISOTACH_GE:
1052                case TacticalLines.ISODROSOTHERM:
1053                case TacticalLines.ISODROSOTHERM_GE:
1054                case TacticalLines.ISOPLETHS:
1055                case TacticalLines.ISOPLETHS_GE:
1056                case TacticalLines.ICE_EDGE:
1057                case TacticalLines.ICE_EDGE_GE:
1058                case TacticalLines.ESTIMATED_ICE_EDGE:
1059                case TacticalLines.ESTIMATED_ICE_EDGE_GE:
1060                case TacticalLines.CRACKS:
1061                case TacticalLines.CRACKS_GE:
1062                case TacticalLines.DEPTH_CURVE:
1063                case TacticalLines.DEPTH_CURVE_GE:
1064                case TacticalLines.DEPTH_CONTOUR:
1065                case TacticalLines.DEPTH_CONTOUR_GE:
1066                case TacticalLines.COASTLINE:
1067                case TacticalLines.COASTLINE_GE:
1068                case TacticalLines.PIER:
1069                case TacticalLines.PIER_GE:
1070                case TacticalLines.RAMP_ABOVE_WATER:
1071                case TacticalLines.RAMP_ABOVE_WATER_GE:
1072                case TacticalLines.RAMP_BELOW_WATER:
1073                case TacticalLines.RAMP_BELOW_WATER_GE:
1074                case TacticalLines.JETTY_ABOVE_WATER:
1075                case TacticalLines.JETTY_ABOVE_WATER_GE:
1076                case TacticalLines.JETTY_BELOW_WATER:
1077                case TacticalLines.JETTY_BELOW_WATER_GE:
1078                case TacticalLines.SEAWALL:
1079                case TacticalLines.SEAWALL_GE:
1080                case TacticalLines.EBB_TIDE:
1081                case TacticalLines.FLOOD_TIDE:
1082                case TacticalLines.EBB_TIDE_GE:
1083                case TacticalLines.FLOOD_TIDE_GE:
1084                case TacticalLines.JET:
1085                case TacticalLines.STREAM:
1086                case TacticalLines.JET_GE:
1087                case TacticalLines.STREAM_GE:
1088                    lineObject2 = DrawSplines(tg, splinePoints);
1089                    lineObject2.lineTo(ptLast.x, ptLast.y);
1090                    shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1091                    shape.setShape(lineObject2);
1092                    shapes.add(shape);
1093                    break;
1094                case TacticalLines.CRACKS_SPECIFIC_LOCATION:
1095                case TacticalLines.CRACKS_SPECIFIC_LOCATION_GE:
1096                case TacticalLines.ICE_EDGE_RADAR:
1097                case TacticalLines.ICE_EDGE_RADAR_GE:
1098                    lineObject2 = DrawSplines(tg, splinePoints);
1099                    shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1100                    shape.setShape(lineObject2);
1101                    shapes.add(shape);
1102                    break;
1103                case TacticalLines.ICE_OPENINGS_LEAD:
1104                    originalPixels=tg.Pixels;
1105                    partitions=clsChannelUtility.GetPartitions2(tg);
1106                    v=partitions.size();
1107                    //for(l=0;l<partitions.size();l++)
1108                    for(l=0;l<v;l++)
1109                    {
1110                        tg.Pixels=originalPixels;
1111                        pixels=new ArrayList();
1112                        for(k=partitions.get(l).start;k<=partitions.get(l).end_Renamed+1;k++)
1113                            pixels.add(tg.Pixels.get(k));
1114                        
1115                        if(pixels==null || pixels.isEmpty())
1116                            continue;
1117
1118                        twoSplines = new ArrayList();
1119                        twoSplines = ParallelLines2(pixels, (int) arraysupport.getScaledSize(20, tg.get_LineThickness()));
1120
1121                        upperSpline = new ArrayList();
1122                        lowerSpline = new ArrayList();
1123                        w=twoSplines.size();
1124                        //for (j = 0; j < twoSplines.size() / 2; j++) 
1125                        for (j = 0; j < w / 2; j++) 
1126                        {
1127                            upperSpline.add(twoSplines.get(j));
1128                        }
1129
1130                        //for (j = twoSplines.size() / 2; j < twoSplines.size(); j++) 
1131                        for (j = w / 2; j < w; j++) 
1132                        {
1133                            lowerSpline.add(twoSplines.get(j));
1134                        }
1135
1136                        tg.Pixels = lowerSpline;
1137                        lineObject2 = DrawSplines(tg, splinePoints);
1138                        shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1139                        shape.setShape(lineObject2);
1140                        shapes.add(shape);
1141
1142                        tg.Pixels = upperSpline;
1143                        lineObject2 = DrawSplines(tg, splinePoints);
1144                        shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1145                        shape.setShape(lineObject2);
1146                        shapes.add(shape);
1147                    }
1148                    break;
1149                case TacticalLines.ICE_OPENINGS_LEAD_GE:
1150                    originalPixels=tg.Pixels;
1151                    partitions=clsChannelUtility.GetPartitions2(tg);
1152                    t=partitions.size();
1153                    //for(l=0;l<partitions.size();l++)
1154                    for(l=0;l<t;l++)
1155                    {
1156                        tg.Pixels=originalPixels;
1157                        pixels=new ArrayList();
1158                        for(k=partitions.get(l).start;k<=partitions.get(l).end_Renamed+1;k++)
1159                            pixels.add(tg.Pixels.get(k));
1160
1161                        if(pixels==null || pixels.isEmpty())
1162                            continue;
1163
1164                        twoSplines = new ArrayList();
1165                        twoSplines = ParallelLines2(pixels, (int) arraysupport.getScaledSize(20, tg.get_LineThickness()));
1166
1167                        upperSpline = new ArrayList();
1168                        lowerSpline = new ArrayList();
1169                        u=twoSplines.size();
1170                        //for (j = 0; j < twoSplines.size() / 2; j++) 
1171                        for (j = 0; j < u / 2; j++) 
1172                        {
1173                            upperSpline.add(twoSplines.get(j));
1174                        }
1175
1176                        //for (j = twoSplines.size() / 2; j < twoSplines.size(); j++) 
1177                        for (j = u / 2; j < u; j++) 
1178                        {
1179                            lowerSpline.add(twoSplines.get(j));
1180                        }
1181
1182                        tg.Pixels = lowerSpline;
1183                        lineObject2 = DrawSplines(tg, splinePoints);
1184                        ptLast=tg.Pixels.get(tg.Pixels.size()-1);
1185                        lineObject2.lineTo(ptLast.x, ptLast.y);
1186                        shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1187                        shape.setShape(lineObject2);
1188                        shapes.add(shape);
1189
1190                        tg.Pixels = upperSpline;
1191                        splinePoints=new ArrayList();
1192                        lineObject2 = DrawSplines(tg, splinePoints);
1193                        ptLast=tg.Pixels.get(tg.Pixels.size()-1);
1194                        lineObject2.lineTo(ptLast.x, ptLast.y);
1195                        shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1196                        shape.setShape(lineObject2);
1197                        shapes.add(shape);
1198                    }
1199                    break;
1200                case TacticalLines.ICE_OPENINGS_FROZEN:
1201                case TacticalLines.ICE_OPENINGS_FROZEN_GE:
1202                    originalPixels = tg.Pixels;
1203                    partitions = clsChannelUtility.GetPartitions2(tg);
1204                    t = partitions.size();
1205                    //for(l=0;l<partitions.size();l++)
1206                    for (l = 0; l < t; l++) {
1207                        tg.Pixels = originalPixels;
1208                        pixels = new ArrayList<>();
1209                        for (k = partitions.get(l).start; k <= partitions.get(l).end_Renamed + 1; k++)
1210                            pixels.add(tg.Pixels.get(k));
1211
1212                        if (pixels.isEmpty())
1213                            continue;
1214
1215                        twoSplines = ParallelLines2(pixels, (int) arraysupport.getScaledSize(20, tg.get_LineThickness()));
1216                        upperSpline = new ArrayList<>();
1217                        lowerSpline = new ArrayList<>();
1218                        u = twoSplines.size();
1219                        //for (j = 0; j < twoSplines.size() / 2; j++) 
1220                        for (j = 0; j < u / 2; j++) {
1221                            upperSpline.add(twoSplines.get(j));
1222                        }
1223
1224                        //for (j = twoSplines.size() / 2; j < twoSplines.size(); j++) 
1225                        for (j = u / 2; j < u; j++) {
1226                            lowerSpline.add(twoSplines.get(j));
1227                        }
1228
1229                        tg.Pixels = lowerSpline;
1230                        if (tg.get_LineType() == TacticalLines.ICE_OPENINGS_FROZEN) {
1231                            lineObject2 = DrawSplines(tg, splinePoints);
1232                        } else {
1233                            ArrayList<POINT2> splinePoints3 = new ArrayList<>();
1234                            lineObject2 = DrawSplines(tg, splinePoints3);
1235                            splinePoints.addAll(splinePoints3);
1236                            ptLast = tg.Pixels.get(tg.Pixels.size() - 1);
1237                            lineObject2.lineTo(ptLast.x, ptLast.y);
1238                        }
1239                        shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1240                        shape.setShape(lineObject2);
1241                        shapes.add(shape);
1242
1243                        tg.Pixels = upperSpline;
1244                        if (tg.get_LineType() == TacticalLines.ICE_OPENINGS_FROZEN) {
1245                            lineObject2 = DrawSplines(tg, splinePoints2);
1246                        } else {
1247                            ArrayList<POINT2> splinePoints4 = new ArrayList<>();
1248                            lineObject2 = DrawSplines(tg, splinePoints4);
1249                            splinePoints2.addAll(splinePoints4);
1250                            ptLast = tg.Pixels.get(tg.Pixels.size() - 1);
1251                            lineObject2.lineTo(ptLast.x, ptLast.y);
1252                        }
1253                        shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1254                        shape.setShape(lineObject2);
1255                        shapes.add(shape);
1256
1257                        //parse upper and lower arrays to find the corresponding splines
1258                        ArrayList<ArrayList<POINT2>> splinePointsArrays = new ArrayList<>();
1259                        ArrayList<ArrayList<POINT2>> splinePoints2Arrays = new ArrayList<>();
1260                        ArrayList<POINT2> ptsArray = new ArrayList<>();
1261                        for (j = 0; j < splinePoints.size(); j++) {
1262                            if (splinePoints.get(j).style != 47) {
1263                                ptsArray.add(splinePoints.get(j));
1264                            } else {
1265                                splinePointsArrays.add(ptsArray);
1266                                ptsArray = new ArrayList<>();
1267                            }
1268                        }
1269                        for (j = 0; j < splinePoints2.size(); j++) {
1270                            if (splinePoints2.get(j).style != 47) {
1271                                ptsArray.add(splinePoints2.get(j));
1272                            } else {
1273                                splinePoints2Arrays.add(ptsArray);
1274                                ptsArray = new ArrayList<>();
1275                            }
1276                        }
1277
1278                        lineObject = new GeneralPath();
1279                        for (j = 0; j < splinePointsArrays.size(); j++) {
1280                            //the lines to connect the extrapolated points
1281                            ArrayList<POINT2> array;
1282                            ArrayList<POINT2> array2;
1283                            if (splinePoints2Arrays.size() <= j)
1284                                break;
1285                            if (splinePointsArrays.size() >= splinePoints2Arrays.size()) {
1286                                array = splinePointsArrays.get(j);
1287                                array2 = splinePoints2Arrays.get(j);
1288                            } else {
1289                                array = splinePoints2Arrays.get(j);
1290                                array2 = splinePointsArrays.get(j);
1291                            }
1292                            //extrapolate against points in the shortest array
1293                            for (k = 0; k < array.size(); k++) {
1294                                double theta;
1295                                if (array.size() == 1) // Unable to find slope
1296                                    continue;
1297                                else if (k == 0)
1298                                    theta = Math.atan2(array.get(k + 1).y - array.get(k).y, array.get(k + 1).x - array.get(k).x);
1299                                else if (k == array.size() - 1)
1300                                    theta = Math.atan2(array.get(k).y - array.get(k - 1).y, array.get(k).x - array.get(k - 1).x);
1301                                else
1302                                    theta = Math.atan2(array.get(k + 1).y - array.get(k - 1).y, array.get(k + 1).x - array.get(k - 1).x);
1303
1304                                POINT2 pt = array.get(k);
1305                                POINT2 pt2 = ExtrapolatePointFromCurve(array2, pt, theta);
1306                                //if we got a valid extrapolation point then draw the line
1307                                if (pt2 != null) {
1308                                    lineObject.moveTo(pt.x, pt.y);
1309                                    lineObject.lineTo(pt2.x, pt2.y);
1310                                }
1311                            }
1312                        }
1313                        shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1314                        shape.setShape(lineObject);
1315                        shapes.add(shape);
1316                    }
1317                    break;
1318                case TacticalLines.LEADING_LINE:
1319                    //the solid line
1320                    lineObject = DrawSplines(tg, splinePoints);
1321                    lineObject2 = new GeneralPath();
1322                    if(splinePoints.size()>0)
1323                        lineObject2.moveTo(splinePoints.get(0).x, splinePoints.get(0).y);
1324                    else
1325                    {
1326                        lineObject2.moveTo(tg.Pixels.get(0).x,tg.Pixels.get(0).y);
1327                        t=tg.Pixels.size();
1328                        //for(j=0;j<tg.Pixels.size();j++)
1329                        for(j=0;j<t;j++)
1330                            lineObject2.lineTo(tg.Pixels.get(j).x,tg.Pixels.get(j).y);
1331
1332                        shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1333                        shape.setShape(lineObject2);
1334                        shape.set_Style(1);
1335                        shapes.add(shape);
1336                        return;
1337                    }
1338
1339                    int n = splinePoints.size() / 2;
1340                    for (j = 1; j <= n; j++) {
1341                        if(splinePoints.size()>=j-1)
1342                            lineObject2.lineTo(splinePoints.get(j).x, splinePoints.get(j).y);
1343                    }
1344                    shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1345                    shape.setShape(lineObject2);
1346                    shapes.add(shape);
1347
1348                    //the dashed line
1349                    lineObject2 = new GeneralPath();
1350                    lineObject2.moveTo(splinePoints.get(n).x, splinePoints.get(n).y);
1351                    u=splinePoints.size();
1352                    //for (j = n + 1; j < splinePoints.size(); j++) 
1353                    for (j = n + 1; j < u; j++) 
1354                    {
1355                        if(splinePoints.size()>=j-1)
1356                            lineObject2.lineTo(splinePoints.get(j).x, splinePoints.get(j).y);
1357                    }
1358                    shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1359                    shape.setShape(lineObject2);
1360                    shape.set_Style(1);
1361                    shapes.add(shape);
1362                    break;
1363                default:
1364                    break;
1365            }
1366            //add the last point
1367            if (tg.get_LineType() != TacticalLines.ICE_OPENINGS_LEAD &&
1368                    tg.get_LineType() != TacticalLines.ICE_OPENINGS_LEAD_GE &&
1369                    tg.get_LineType() != TacticalLines.ICE_OPENINGS_FROZEN &&
1370                    tg.get_LineType() != TacticalLines.ICE_OPENINGS_FROZEN_GE &&
1371                    tg.get_LineType() != TacticalLines.ICE_EDGE_RADAR)
1372            {
1373                if (splinePoints != null && splinePoints.size() > 0)
1374                {
1375                    lineObject2 = new GeneralPath();
1376                    lineObject2.moveTo(splinePoints.get(splinePoints.size() - 1).x, splinePoints.get(splinePoints.size() - 1).y);
1377                    lineObject2.lineTo(ptLast.x, ptLast.y);
1378                    shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1379                    shape.setShape(lineObject2);
1380                    shape.set_Style(0);
1381                    shapes.add(shape);
1382                }
1383            }
1384            SetShapeProperties(tg, shapes);
1385        } 
1386        catch (Exception exc) {
1387               ErrorLogger.LogException(_className ,"GetMeTOCShape",
1388                    new RendererException("Failed inside GetMeTOCShape", exc));
1389        }
1390    }
1391/**
1392 * Sets the shape properties based on the tacttical graphic properties and also based on shape
1393 * styles which may have been set by JavaLineArray
1394 * @param tg
1395 * @param shapes shapes array to set properties
1396 */
1397    protected static void SetShapeProperties(TGLight tg, ArrayList<Shape2> shapes) {
1398        try
1399        {
1400            if (shapes == null)
1401            {
1402                return;
1403            }
1404            switch(tg.get_LineType())
1405            {
1406                case TacticalLines.DEPTH_AREA:
1407                    return;
1408                default:
1409                    break;
1410            }
1411
1412            int j = 0, n=0;
1413            Shape2 shape = null;
1414            BasicStroke stroke = null;
1415            Bitmap bi2 = null;
1416            int lineThickness = tg.get_LineThickness();
1417            Rectangle2D.Double rect = null;
1418            TexturePaint tp = tg.get_TexturePaint();
1419            switch (tg.get_LineType()) {
1420                case TacticalLines.FISH_TRAPS:
1421                case TacticalLines.SWEPT_AREA:
1422                case TacticalLines.OIL_RIG_FIELD:
1423                case TacticalLines.FOUL_GROUND:
1424                case TacticalLines.KELP:
1425                case TacticalLines.BEACH_SLOPE_MODERATE:
1426                case TacticalLines.BEACH_SLOPE_STEEP:
1427                    bi2 = PatternFillRenderer.MakeMetocPatternFill(tg);
1428                    shape = shapes.get(0);
1429                    shape.setLineColor(tg.get_LineColor());
1430                    shape.setPatternFillImage(bi2);
1431                    if (bi2 != null) {
1432                        shape.setShader(new BitmapShader(shape.getPatternFillImage(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
1433                    }
1434                    break;
1435                case TacticalLines.SF:
1436                case TacticalLines.USF:
1437                case TacticalLines.SFG:
1438                case TacticalLines.SFY:
1439                    n=shapes.size();
1440                    //for (j = 0; j < shapes.size(); j++) 
1441                    for (j = 0; j < n; j++) 
1442                    {
1443                        shape = shapes.get(j);
1444                        if (shape == null || shape.getShape() == null) {
1445                            continue;
1446                        }
1447
1448                        shape.set_Style(tg.get_LineStyle());
1449                        stroke = clsUtility.getLineStroke(lineThickness, shape.get_Style(), tg.get_lineCap(), BasicStroke.JOIN_ROUND);
1450                        shape.setStroke(stroke);
1451                    }
1452                    return;
1453                default:
1454                    break;
1455            }
1456
1457            int shapeType = -1;
1458            int lineType = tg.get_LineType();
1459            boolean isChange1Area = clsUtility.IsChange1Area(lineType);
1460            boolean isClosedPolygon = clsUtility.isClosedPolygon(lineType);
1461            n=shapes.size();
1462            //for (j = 0; j < shapes.size(); j++) 
1463            for (j = 0; j < n; j++) 
1464            {
1465                shape = shapes.get(j);
1466                if (shape == null || shape.getShape() == null) {
1467                    continue;
1468                }
1469
1470                if (shape.getShapeType() == Shape2.SHAPE_TYPE_FILL) {
1471                    shape.setFillColor(tg.get_FillColor());
1472                }
1473
1474                //clsUtility.ResolveModifierShape(tg,shape);
1475
1476                shapeType = shape.getShapeType();
1477                switch (tg.get_LineType()) {
1478                    case TacticalLines.SF:
1479                    case TacticalLines.USF:
1480                    case TacticalLines.SFG:
1481                    case TacticalLines.SFY:
1482                    case TacticalLines.ITD:
1483                        break;
1484                    case TacticalLines.LEADING_LINE:
1485                    case TacticalLines.TRAINING_AREA:
1486                        shape.setLineColor(tg.get_LineColor());
1487                        break;
1488                    default:
1489                        shape.setLineColor(tg.get_LineColor());
1490                        shape.set_Style(tg.get_LineStyle());
1491                        break;
1492                }
1493
1494                if (isClosedPolygon || shapeType == Shape2.SHAPE_TYPE_FILL)
1495                {
1496                    switch(tg.get_LineType())//these have fill instead of TexturePaint
1497                    {
1498                        case TacticalLines.FORESHORE_AREA:
1499                        case TacticalLines.WATER:
1500                        case TacticalLines.BEACH:
1501                        case TacticalLines.ISLAND:
1502                        case TacticalLines.DRYDOCK:
1503                        case TacticalLines.LOADING_FACILITY_AREA:
1504                        case TacticalLines.PERCHES:
1505                        case TacticalLines.UNDERWATER_HAZARD:
1506                        case TacticalLines.DISCOLORED_WATER:
1507                        case TacticalLines.VDR_LEVEL_12:
1508                        case TacticalLines.VDR_LEVEL_23:
1509                        case TacticalLines.VDR_LEVEL_34:
1510                        case TacticalLines.VDR_LEVEL_45:
1511                        case TacticalLines.VDR_LEVEL_56:
1512                        case TacticalLines.VDR_LEVEL_67:
1513                        case TacticalLines.VDR_LEVEL_78:
1514                        case TacticalLines.VDR_LEVEL_89:
1515                        case TacticalLines.VDR_LEVEL_910:
1516                        case TacticalLines.SOLID_ROCK:
1517                        case TacticalLines.CLAY:
1518                        case TacticalLines.FINE_SAND:
1519                        case TacticalLines.MEDIUM_SAND:
1520                        case TacticalLines.COARSE_SAND:
1521                        case TacticalLines.VERY_COARSE_SAND:
1522                        case TacticalLines.VERY_FINE_SAND:
1523                        case TacticalLines.VERY_FINE_SILT:
1524                        case TacticalLines.FINE_SILT:
1525                        case TacticalLines.MEDIUM_SILT:
1526                        case TacticalLines.COARSE_SILT:
1527                        case TacticalLines.BOULDERS:
1528                        case TacticalLines.OYSTER_SHELLS:
1529                        case TacticalLines.PEBBLES:
1530                        case TacticalLines.SAND_AND_SHELLS:
1531                        case TacticalLines.BOTTOM_SEDIMENTS_LAND:
1532                        case TacticalLines.BOTTOM_SEDIMENTS_NO_DATA:
1533                        case TacticalLines.BOTTOM_ROUGHNESS_MODERATE:
1534                        case TacticalLines.BOTTOM_ROUGHNESS_ROUGH:
1535                        case TacticalLines.BOTTOM_ROUGHNESS_SMOOTH:
1536                        case TacticalLines.CLUTTER_HIGH:
1537                        case TacticalLines.CLUTTER_MEDIUM:
1538                        case TacticalLines.CLUTTER_LOW:
1539                        case TacticalLines.IMPACT_BURIAL_0:
1540                        case TacticalLines.IMPACT_BURIAL_10:
1541                        case TacticalLines.IMPACT_BURIAL_100:
1542                        case TacticalLines.IMPACT_BURIAL_20:
1543                        case TacticalLines.IMPACT_BURIAL_75:
1544                        case TacticalLines.BOTTOM_CATEGORY_A:
1545                        case TacticalLines.BOTTOM_CATEGORY_B:
1546                        case TacticalLines.BOTTOM_CATEGORY_C:
1547                        case TacticalLines.BOTTOM_TYPE_A1:
1548                        case TacticalLines.BOTTOM_TYPE_A2:
1549                        case TacticalLines.BOTTOM_TYPE_A3:
1550                        case TacticalLines.BOTTOM_TYPE_B1:
1551                        case TacticalLines.BOTTOM_TYPE_B2:
1552                        case TacticalLines.BOTTOM_TYPE_B3:
1553                        case TacticalLines.BOTTOM_TYPE_C1:
1554                        case TacticalLines.BOTTOM_TYPE_C2:
1555                        case TacticalLines.BOTTOM_TYPE_C3:
1556                        case TacticalLines.SUBMERGED_CRIB:
1557                        case TacticalLines.FREEFORM:
1558                            shape.setFillColor(tg.get_FillColor());
1559                            break;
1560                        default:
1561                            break;
1562                    }
1563                }
1564
1565                if (lineType == TacticalLines.INSTABILITY || lineType == TacticalLines.SHEAR) {
1566                    // Calculate dash array for instability and shear so that dots are on peak of curves
1567                    final float dotLength = 1f;
1568                    float spacing = lineThickness * 2;
1569
1570                    ArrayList<POINT2> points = shape.getPoints();
1571
1572                    float arcLength = 0;
1573                    for (int i = 0; i < 6; i++) { // 6 segments in each arc
1574                        arcLength += (float) lineutility.CalcDistanceDouble(points.get(i), points.get(i + 1));
1575                    }
1576
1577                    // For very large line thicknesses get a reasonable spacing
1578                    // Helps avoid calculating negative dashLength if spacing is longer than arc
1579                    spacing = Math.min(spacing, arcLength / 5f);
1580
1581                    // dashLength is space remaining in arc after adding dots and spacing.
1582                    // Divide remaining space by two because there's a dash on both sides of the dots
1583                    float[] dash;
1584                    if (lineType == TacticalLines.INSTABILITY) {
1585                        float dotAndSpaceLength = dotLength * 2 + spacing * 3;
1586                        float dashLength = (arcLength - dotAndSpaceLength) / 2;
1587                        dash = new float[]{dashLength, spacing, dotLength, spacing, dotLength, spacing, dashLength, 0};
1588                    } else { // SHEAR
1589                        float dotAndSpaceLength = dotLength + spacing * 2;
1590                        float dashLength = (arcLength - dotAndSpaceLength) / 2;
1591                        dash = new float[]{dashLength, spacing, dotLength, spacing, dashLength, 0};
1592                    }
1593                    stroke = new BasicStroke(lineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 4f, dash, 0f);
1594                } else if (lineType == TacticalLines.TROUGH) {
1595                    // The dashed lines look odd when longer than the arc length. This will set a max length for dashes relative to the arc length.
1596                    ArrayList<POINT2> points = shape.getPoints();
1597
1598                    float arcLength = 0;
1599                    for (int i = 0; i < 6; i++) { // 6 segments in each arc
1600                        arcLength += (float) lineutility.CalcDistanceDouble(points.get(i), points.get(i + 1));
1601                    }
1602
1603                    float dashLength = 2 * lineThickness; // from clsUtility.getLineStroke
1604
1605                    dashLength = Math.min(dashLength, arcLength / 4);
1606
1607                    float[] dash = {dashLength, dashLength};
1608                    stroke = new BasicStroke(lineThickness, tg.get_lineCap(), BasicStroke.JOIN_ROUND, 4f, dash, 0f);
1609                } else {
1610                    stroke = clsUtility.getLineStroke(lineThickness, shape.get_Style(), tg.get_lineCap(), BasicStroke.JOIN_ROUND);
1611                }
1612                shape.setStroke(stroke);
1613            }
1614        } catch (Exception exc) {
1615            //clsUtility.WriteFile("error in clsMETOC.SetShapeProperties");
1616               ErrorLogger.LogException(_className ,"SetShapeProperties",
1617                    new RendererException("Failed inside SetShapeProperties", exc));
1618        }
1619    }
1620
1621    /**
1622     * Draws an arrow to the GeneralPath object from pt1 to pt2.
1623     *
1624     * @param pt1 arrow tip
1625     * @param pt2 - arrow base
1626     * @param size - arrow size in pixels
1627     * @param lineObject - general path to draw the arrow
1628     *
1629     * @return arrow sprite
1630     */
1631    private static void DrawArrow(POINT2 pt1,
1632            POINT2 pt2,
1633            double size,
1634            GeneralPath lineObject) {
1635        try
1636        {
1637            POINT2 ptBase = new POINT2();
1638            POINT2 ptTemp = new POINT2();
1639            ArrayList<POINT2> pts = new ArrayList();
1640            ptBase = lineutility.ExtendAlongLineDouble(pt2, pt1, size);
1641            ptTemp = lineutility.ExtendDirectedLine(pt1, ptBase, ptBase, 2, size);
1642
1643            pts.add(ptTemp);
1644            pts.add(pt2);
1645            ptTemp = lineutility.ExtendDirectedLine(pt1, ptBase, ptBase, 3, size);
1646            pts.add(ptTemp);
1647            lineObject.moveTo(pts.get(0).x, pts.get(0).y);
1648            lineObject.lineTo(pts.get(1).x, pts.get(1).y);
1649            lineObject.lineTo(pts.get(2).x, pts.get(2).y);
1650            pts.clear();
1651            pts = null;
1652        } catch (Exception exc) {
1653               ErrorLogger.LogException(_className ,"DrawArrow",
1654                    new RendererException("Failed inside DrawArrow", exc));
1655        }
1656    }
1657    /**
1658     * Returns a GeneralPath for symbols which require splines. Also returns the calculated
1659     * spline points for those symbols with additional features based on them.
1660     * @param tg
1661     * @param splinePoints2 spline points in pixels
1662     * @return
1663     */
1664    private static GeneralPath DrawSplines(TGLight tg,
1665            ArrayList<POINT2> splinePoints2) {
1666        GeneralPath lineObject = new GeneralPath();
1667        try {
1668            int i = 0, j = 0;
1669            int n=0,t=0;
1670            ArrayList<POINT2> splinePoints;
1671            ArrayList<POINT2> array = tg.get_Pixels();
1672            POINT2 pt0 = new POINT2(), pt1 = new POINT2(), pt2 = new POINT2(), pt3 = new POINT2(),
1673                    pt4 = new POINT2(), pt5 = new POINT2(), pt6 = new POINT2();
1674            POINT2 pt, pt_before, pt_after, Di, p2, p3, pt_after2;
1675            double tension = 0.33;
1676            double control_scale = (tension / 0.5 * 0.175);
1677            double d;
1678            ArrayList<POINT2> tmpArray = null;
1679            n=array.size();
1680            //for (i = 0; i < array.size() - 1; i++) //was length-1
1681            for (i = 0; i < n - 1; i++) //was length-1
1682            {
1683                pt = array.get(i);
1684                if (i == 0) {
1685                    lineObject.moveTo(pt.x, pt.y);
1686                    pt_before = pt;
1687                } else {
1688                    pt_before = array.get(i - 1);
1689                }
1690
1691                if (i == array.size() - 1) {
1692                    pt2 = array.get(i);
1693                } else {
1694                    pt2 = array.get(i + 1);
1695                }
1696
1697                if (i < array.size() - 2) {
1698                    pt_after = array.get(i + 1);
1699                } else {
1700                    pt_after = array.get(array.size() - 1);
1701                }
1702
1703                if (i < array.size() - 2) {
1704                    pt_after2 = array.get(i + 2);
1705                } else {
1706                    pt_after2 = array.get(array.size() - 1);
1707                }
1708
1709
1710                Di = new POINT2();
1711                p2 = new POINT2();
1712
1713                Di.x = pt_after.x - pt_before.x;
1714                Di.y = pt_after.y - pt_before.y;
1715                p2.x = pt.x + control_scale * Di.x;
1716                p2.y = pt.y + control_scale * Di.y;
1717
1718                p3 = new POINT2();
1719                POINT2 DiPlus1 = new POINT2();
1720
1721                DiPlus1.x = pt_after2.x - pt.x;
1722                DiPlus1.y = pt_after2.y - pt.y;
1723                p3.x = pt_after.x - control_scale * DiPlus1.x;
1724                p3.y = pt_after.y - control_scale * DiPlus1.y;
1725
1726                tmpArray = drawCubicBezier2(tg, lineObject, pt, p2, p3, pt2);
1727
1728                //ICE_OPENINGS_FROZEN needs to know which segment corresponds to each spline point
1729                if (tg.get_LineType() == TacticalLines.ICE_OPENINGS_FROZEN ||
1730                        tg.get_LineType() == TacticalLines.ICE_OPENINGS_FROZEN_GE)
1731                {
1732                    if(tmpArray.size()>0)
1733                        tmpArray.get(tmpArray.size() - 1).style = 47;   //use this to differentiate the arrays
1734                }
1735                splinePoints2.addAll(tmpArray);
1736
1737                splinePoints = tmpArray;
1738
1739                switch (tg.get_LineType()) {
1740                    case TacticalLines.EBB_TIDE:
1741                        if (i == array.size() - 2)
1742                        {
1743                            if(splinePoints.size()>=2)
1744                                DrawArrow(splinePoints.get(splinePoints.size() - 2), tg.Pixels.get(tg.Pixels.size() - 1), arraysupport.getScaledSize(10, tg.get_LineThickness()), lineObject);
1745                        }
1746                        break;
1747                    case TacticalLines.FLOOD_TIDE:
1748                        d = arraysupport.getScaledSize(10, tg.get_LineThickness());
1749                        if (i == 0 && splinePoints.size() > 1) {
1750                            //finally get the feather points
1751                            //must allocate for the feather points, requires 4 additional points
1752                            pt0 = splinePoints.get(0);
1753                            pt1 = splinePoints.get(1);
1754                            pt2 = lineutility.ExtendLineDouble(pt0, pt1, d);
1755                            pt3 = lineutility.ExtendLineDouble(pt0, pt1, d * 2);
1756                            pt4 = lineutility.ExtendLineDouble(pt0, pt1, d * 3);
1757                            pt5 = lineutility.ExtendDirectedLine(pt3, pt2, pt2, 3, d);
1758                            pt6 = lineutility.ExtendDirectedLine(pt4, pt3, pt3, 3, d);
1759
1760                            //first feather line
1761                            lineObject.moveTo(pt3.x, pt3.y);
1762                            lineObject.lineTo(pt5.x, pt5.y);
1763                            //second feather line
1764                            lineObject.moveTo(pt4.x, pt4.y);
1765                            lineObject.lineTo(pt6.x, pt6.y);
1766                        }
1767                        if (i == array.size() - 2)
1768                        {
1769                            if(splinePoints.size()>=2)
1770                                DrawArrow(splinePoints.get(splinePoints.size() - 2), tg.Pixels.get(tg.Pixels.size() - 1), d, lineObject);
1771                        }
1772                        break;
1773                    case TacticalLines.STREAM:
1774                    case TacticalLines.JET:
1775                        if (splinePoints.size() > i + 1) {
1776                            DrawArrow(splinePoints.get(i + 1), splinePoints.get(i), arraysupport.getScaledSize(10, tg.get_LineThickness()), lineObject);
1777                        }
1778                        break;
1779                    case TacticalLines.FLOOD_TIDE_GE:
1780                        d = arraysupport.getScaledSize(10, tg.get_LineThickness());
1781                        if (i == 0 && splinePoints.size() > 1) {
1782                            //finally get the feather points
1783                            //must allocate for the feather points, requires 4 additional points
1784                            pt0 = splinePoints.get(0);
1785                            pt1 = splinePoints.get(1);
1786                            pt2 = lineutility.ExtendLineDouble(pt0, pt1, d);
1787                            pt3 = lineutility.ExtendLineDouble(pt0, pt1, d * 2);
1788                            pt4 = lineutility.ExtendLineDouble(pt0, pt1, d * 3);
1789                            pt5 = lineutility.ExtendDirectedLine(pt3, pt2, pt2, 3, d);
1790                            pt6 = lineutility.ExtendDirectedLine(pt4, pt3, pt3, 3, d);
1791
1792                            //first feather line
1793                            lineObject.moveTo(pt3.x, pt3.y);
1794                            lineObject.lineTo(pt5.x, pt5.y);
1795                            //second feather line
1796                            lineObject.moveTo(pt4.x, pt4.y);
1797                            lineObject.lineTo(pt6.x, pt6.y);
1798                        }
1799                        if(i==array.size()-2)//the last point in the array
1800                        {
1801                            lineObject.moveTo((int)splinePoints2.get(0).x,(int)splinePoints2.get(0).y);
1802                            t=splinePoints2.size();
1803                            //for(j=1;j<splinePoints2.size();j++)
1804                            for(j=1;j<t;j++)
1805                                lineObject.lineTo((int)splinePoints2.get(j).x,(int)splinePoints2.get(j).y);
1806
1807                            if(splinePoints.size()>=2)
1808                                DrawArrow(splinePoints.get(splinePoints.size() - 2), tg.Pixels.get(tg.Pixels.size() - 1), d, lineObject);
1809                        }
1810                        break;
1811                    case TacticalLines.EBB_TIDE_GE:
1812                        if(i==array.size()-2)//the last point in the array
1813                        {
1814                            lineObject=new GeneralPath();
1815                            lineObject.moveTo((int)splinePoints2.get(0).x,(int)splinePoints2.get(0).y);
1816                            t=splinePoints2.size();
1817                            //for(j=1;j<splinePoints2.size();j++)
1818                            for(j=1;j<t;j++)
1819                                lineObject.lineTo((int)splinePoints2.get(j).x,(int)splinePoints2.get(j).y);
1820
1821                            if(splinePoints.size()>=2)
1822                                DrawArrow(splinePoints.get(splinePoints.size() - 2), tg.Pixels.get(tg.Pixels.size() - 1), arraysupport.getScaledSize(10, tg.get_LineThickness()), lineObject);
1823                        }
1824                        break;
1825                    case TacticalLines.JET_GE:
1826                    case TacticalLines.STREAM_GE:
1827                        if (splinePoints.size() > i + 1) {
1828                            DrawArrow(splinePoints.get(i + 1), splinePoints.get(i), arraysupport.getScaledSize(10, tg.get_LineThickness()), lineObject);
1829                        }
1830                        if(i==array.size()-2)//the last point in the array
1831                        {
1832                            lineObject.moveTo((int)splinePoints2.get(0).x,(int)splinePoints2.get(0).y);
1833                            t=splinePoints2.size();
1834                            //for(j=1;j<splinePoints2.size();j++)
1835                            for(j=1;j<t;j++)
1836                                lineObject.lineTo((int)splinePoints2.get(j).x,(int)splinePoints2.get(j).y);
1837                        }
1838                        break;
1839                    case TacticalLines.ICE_OPENINGS_FROZEN_GE:
1840                    case TacticalLines.ICE_OPENINGS_LEAD_GE:
1841                    case TacticalLines.SEAWALL_GE:
1842                    case TacticalLines.JETTY_BELOW_WATER_GE:
1843                    case TacticalLines.JETTY_ABOVE_WATER_GE:
1844                    case TacticalLines.RAMP_ABOVE_WATER_GE:
1845                    case TacticalLines.RAMP_BELOW_WATER_GE:
1846                    case TacticalLines.PIER_GE:
1847                    case TacticalLines.COASTLINE_GE:
1848                    case TacticalLines.DEPTH_CONTOUR_GE:
1849                    case TacticalLines.DEPTH_CURVE_GE:
1850                    case TacticalLines.CRACKS_GE:
1851                    case TacticalLines.ESTIMATED_ICE_EDGE_GE:
1852                    case TacticalLines.ICE_EDGE_GE:
1853                    case TacticalLines.ISOPLETHS_GE:
1854                    case TacticalLines.ISODROSOTHERM_GE:
1855                    case TacticalLines.ISOTACH_GE:
1856                    case TacticalLines.ISOTHERM_GE:
1857                    case TacticalLines.UPPER_AIR_GE:
1858                    case TacticalLines.ISOBAR_GE:
1859                        if(splinePoints2!=null && !splinePoints2.isEmpty())
1860                        {
1861                            lineObject=new GeneralPath();
1862                            if(i==array.size()-2)//the last point in the array
1863                            {
1864                                lineObject.moveTo((int)splinePoints2.get(0).x,(int)splinePoints2.get(0).y);
1865                                t=splinePoints2.size();
1866                                //for(j=1;j<splinePoints2.size();j++)
1867                                for(j=1;j<t;j++)
1868                                    lineObject.lineTo((int)splinePoints2.get(j).x,(int)splinePoints2.get(j).y);
1869                            }
1870                        }
1871                        break;
1872                    case TacticalLines.ICE_EDGE_RADAR:
1873                        t=splinePoints.size();
1874                        d = arraysupport.getScaledSize(5, tg.get_LineThickness());
1875                        //for (j = 0; j < splinePoints.size() - 1; j++) 
1876                        for (j = 0; j < t - 1; j++) 
1877                        {
1878                            pt0 = new POINT2(splinePoints.get(j).x, splinePoints.get(j).y);
1879                            pt2 = lineutility.ExtendAngledLine(splinePoints.get(j), splinePoints.get(j + 1), pt0, 45, d);
1880                            pt1 = new POINT2(splinePoints.get(j).x, splinePoints.get(j).y);
1881                            pt3 = lineutility.ExtendAngledLine(splinePoints.get(j), splinePoints.get(j + 1), pt1, -45, d);
1882                            lineObject.moveTo(splinePoints.get(j).x, splinePoints.get(j).y);
1883                            lineObject.lineTo(pt2.x, pt2.y);
1884                            lineObject.moveTo(splinePoints.get(j).x, splinePoints.get(j).y);
1885                            lineObject.lineTo(pt3.x, pt3.y);
1886
1887                            pt0 = new POINT2(splinePoints.get(j).x, splinePoints.get(j).y);
1888                            pt2 = lineutility.ExtendAngledLine(splinePoints.get(j), splinePoints.get(j + 1), pt0, 135, d);
1889                            pt1 = new POINT2(splinePoints.get(j).x, splinePoints.get(j).y);
1890                            pt3 = lineutility.ExtendAngledLine(splinePoints.get(j), splinePoints.get(j + 1), pt1, -135, d);
1891                            lineObject.moveTo(splinePoints.get(j).x, splinePoints.get(j).y);
1892                            lineObject.lineTo(pt2.x, pt2.y);
1893                            lineObject.moveTo(splinePoints.get(j).x, splinePoints.get(j).y);
1894                            lineObject.lineTo(pt3.x, pt3.y);
1895                        }
1896                        break;
1897                    case TacticalLines.ICE_EDGE_RADAR_GE:
1898                        t=splinePoints.size();
1899                        d = arraysupport.getScaledSize(5, tg.get_LineThickness());
1900                        //for (j = 0; j < splinePoints.size() - 1; j++)
1901                        for (j = 0; j < t - 1; j++)
1902                        {
1903                            pt0 = new POINT2(splinePoints.get(j).x, splinePoints.get(j).y);
1904                            pt2 = lineutility.ExtendAngledLine(splinePoints.get(j), splinePoints.get(j + 1), pt0, 45, d);
1905                            pt1 = new POINT2(splinePoints.get(j).x, splinePoints.get(j).y);
1906                            pt3 = lineutility.ExtendAngledLine(splinePoints.get(j), splinePoints.get(j + 1), pt1, -45, d);
1907                            lineObject.moveTo(splinePoints.get(j).x, splinePoints.get(j).y);
1908                            lineObject.lineTo(pt2.x, pt2.y);
1909                            lineObject.moveTo(splinePoints.get(j).x, splinePoints.get(j).y);
1910                            lineObject.lineTo(pt3.x, pt3.y);
1911
1912                            pt0 = new POINT2(splinePoints.get(j).x, splinePoints.get(j).y);
1913                            pt2 = lineutility.ExtendAngledLine(splinePoints.get(j), splinePoints.get(j + 1), pt0, 135, d);
1914                            pt1 = new POINT2(splinePoints.get(j).x, splinePoints.get(j).y);
1915                            pt3 = lineutility.ExtendAngledLine(splinePoints.get(j), splinePoints.get(j + 1), pt1, -135, d);
1916                            lineObject.moveTo(splinePoints.get(j).x, splinePoints.get(j).y);
1917                            lineObject.lineTo(pt2.x, pt2.y);
1918                            lineObject.moveTo(splinePoints.get(j).x, splinePoints.get(j).y);
1919                            lineObject.lineTo(pt3.x, pt3.y);
1920                        }
1921                        if(i==array.size()-2)//the last point in the array
1922                        {
1923                            lineObject.moveTo((int)splinePoints2.get(0).x,(int)splinePoints2.get(0).y);
1924                            t=splinePoints2.size();
1925                            //for(j=1;j<splinePoints2.size();j++)
1926                            for(j=1;j<t;j++)
1927                                lineObject.lineTo((int)splinePoints2.get(j).x,(int)splinePoints2.get(j).y);
1928                        }
1929                        break;
1930                    case TacticalLines.CRACKS_SPECIFIC_LOCATION:
1931                        t=splinePoints.size();
1932                        d = arraysupport.getScaledSize(5, tg.get_LineThickness());
1933                        //for (j = 0; j < splinePoints.size() - 1; j++)
1934                        for (j = 0; j < t - 1; j++)
1935                        {
1936                            //get perpendicular points (point pair)
1937                            pt0 = splinePoints.get(j + 1);
1938                            pt1 = lineutility.ExtendDirectedLine(splinePoints.get(j), splinePoints.get(j + 1), pt0, 2, d);
1939                            lineObject.moveTo(pt1.x, pt1.y);
1940                            pt1 = lineutility.ExtendDirectedLine(splinePoints.get(j), splinePoints.get(j + 1), pt0, 3, d);
1941                            lineObject.lineTo(pt1.x, pt1.y);
1942                        }
1943                        break;
1944                    case TacticalLines.CRACKS_SPECIFIC_LOCATION_GE:
1945                        t=splinePoints.size();
1946                        d = arraysupport.getScaledSize(5, tg.get_LineThickness());
1947                        //for (j = 0; j < splinePoints.size() - 1; j++)
1948                        for (j = 0; j < t - 1; j++)
1949                        {
1950                            //get perpendicular points (point pair)
1951                            pt0 = splinePoints.get(j + 1);
1952                            pt1 = lineutility.ExtendDirectedLine(splinePoints.get(j), splinePoints.get(j + 1), pt0, 2, d);
1953                            lineObject.moveTo(pt1.x, pt1.y);
1954                            pt1 = lineutility.ExtendDirectedLine(splinePoints.get(j), splinePoints.get(j + 1), pt0, 3, d);
1955                            lineObject.lineTo(pt1.x, pt1.y);
1956                        }
1957                        if(i==array.size()-2)//the last point in the array
1958                        {
1959                            lineObject.moveTo((int)splinePoints2.get(0).x,(int)splinePoints2.get(0).y);
1960                            t=splinePoints2.size();
1961                            //for(j=1;j<splinePoints2.size();j++)
1962                            for(j=1;j<t;j++)
1963                                lineObject.lineTo((int)splinePoints2.get(j).x,(int)splinePoints2.get(j).y);
1964                        }
1965                        break;
1966                    default:
1967                        break;
1968                }
1969            }
1970        }
1971        catch (Exception exc) {
1972               ErrorLogger.LogException(_className ,"DrawSplines",
1973                    new RendererException("Failed inside DrawSplines", exc));
1974        }
1975        return lineObject;
1976    }
1977
1978    /**
1979     * Calculates a point on a segment using a ratio of the segment length.
1980     * This function is used for calculating control points on Bezier curves.
1981     *
1982     * @param P0 the 1st point on the segment.
1983     * @param P1 the last point on the segment
1984     * @param ratio the fraction of the segment length
1985     *
1986     * @return calculated point on the P0-P1 segment.
1987     */
1988    private static POINT2 getPointOnSegment(POINT2 P0, POINT2 P1, double ratio) {
1989        //return {x: (P0.x + ((P1.x - P0.x) * ratio)), y: (P0.y + ((P1.y - P0.y) * ratio))};
1990        //var pt:Point=new Point();
1991        POINT2 pt = new POINT2();
1992        try
1993        {
1994            pt.x = P0.x + (P1.x - P0.x) * ratio;
1995            pt.y = P0.y + (P1.y - P0.y) * ratio;
1996        }
1997        catch (Exception exc)
1998        {
1999               ErrorLogger.LogException(_className ,"getPointOnSegment",
2000                    new RendererException("Failed inside getPointOnSegment", exc));
2001        }
2002        return pt;
2003    }
2004
2005    /**
2006     * This function will trace a cubic approximation of the cubic Bezier
2007     * It will calculate a series of (control point/Destination point] which
2008     * will be used to draw quadratic Bezier starting from P0
2009     *
2010     * @param lineObject - the sprite to use for drawing
2011     * @param P0 - 1st client point
2012     * @param P1 - 1st control point for a cubic Bezier
2013     * @param P2 - 2nd control point
2014     * @param P3 - 2nd client point
2015     *
2016     * @return an array of points along the spline at linetype specific intervals
2017     */
2018    private static ArrayList drawCubicBezier2(
2019            TGLight tg,
2020            GeneralPath lineObject,
2021            POINT2 P0,
2022            POINT2 P1,
2023            POINT2 P2,
2024            POINT2 P3)
2025    {
2026        ArrayList<POINT2> array = new ArrayList();
2027        try {
2028            // this stuff may be unnecessary
2029            // calculates the useful base points
2030            POINT2 PA = getPointOnSegment(P0, P1, 0.75);
2031            POINT2 PB = getPointOnSegment(P3, P2, 0.75);
2032
2033            // get 1/16 of the [P3, P0] segment
2034            double dx = (P3.x - P0.x) / 16d;
2035            double dy = (P3.y - P0.y) / 16d;
2036
2037            // calculates control point 1
2038            POINT2 Pc_1 = getPointOnSegment(P0, P1, 0.375);
2039
2040            // calculates control point 2
2041            POINT2 Pc_2 = getPointOnSegment(PA, PB, 0.375);
2042            Pc_2.x -= dx;
2043            Pc_2.y -= dy;
2044
2045            // calculates control point 3
2046            POINT2 Pc_3 = getPointOnSegment(PB, PA, 0.375);
2047            Pc_3.x += dx;
2048            Pc_3.y += dy;
2049
2050            // calculates control point 4
2051            POINT2 Pc_4 = getPointOnSegment(P3, P2, 0.375);
2052
2053            // calculates the 3 anchor points
2054            POINT2 Pa_1 = lineutility.MidPointDouble(Pc_1, Pc_2, 0);
2055            POINT2 Pa_2 = lineutility.MidPointDouble(PA, PB, 0);
2056            POINT2 Pa_3 = lineutility.MidPointDouble(Pc_3, Pc_4, 0);
2057            switch (tg.get_LineType()) {   //draw the solid curve for these
2058                case TacticalLines.ISOBAR:
2059                case TacticalLines.UPPER_AIR:
2060                case TacticalLines.ISODROSOTHERM:
2061                case TacticalLines.ICE_EDGE:
2062                case TacticalLines.CRACKS:
2063                case TacticalLines.DEPTH_CURVE:
2064                case TacticalLines.DEPTH_CONTOUR:
2065                case TacticalLines.COASTLINE:
2066                case TacticalLines.PIER:
2067                case TacticalLines.RAMP_ABOVE_WATER:
2068                case TacticalLines.JETTY_ABOVE_WATER:
2069                case TacticalLines.SEAWALL:
2070                case TacticalLines.ICE_OPENINGS_LEAD:
2071                case TacticalLines.ISOTACH:
2072                case TacticalLines.ISOTHERM:
2073                case TacticalLines.ISOPLETHS:
2074                case TacticalLines.ESTIMATED_ICE_EDGE:
2075                case TacticalLines.RAMP_BELOW_WATER:
2076                case TacticalLines.JETTY_BELOW_WATER:
2077                    lineObject.moveTo(P0.x, P0.y);
2078                    lineObject.curveTo(P1.x, P1.y, P2.x, P2.y, P3.x, P3.y);
2079                    return array;
2080                case TacticalLines.ICE_OPENINGS_LEAD_GE:
2081                case TacticalLines.SEAWALL_GE:
2082                case TacticalLines.JETTY_BELOW_WATER_GE:
2083                case TacticalLines.JETTY_ABOVE_WATER_GE:
2084                case TacticalLines.RAMP_ABOVE_WATER_GE:
2085                case TacticalLines.RAMP_BELOW_WATER_GE:
2086                case TacticalLines.PIER_GE:
2087                case TacticalLines.COASTLINE_GE:
2088                case TacticalLines.DEPTH_CONTOUR_GE:
2089                case TacticalLines.DEPTH_CURVE_GE:
2090                case TacticalLines.CRACKS_GE:
2091                case TacticalLines.ESTIMATED_ICE_EDGE_GE:
2092                case TacticalLines.ICE_EDGE_GE:
2093                case TacticalLines.ISOPLETHS_GE:
2094                case TacticalLines.ISOTACH_GE:
2095                case TacticalLines.ISOTHERM_GE:
2096                case TacticalLines.ISOBAR_GE:
2097                case TacticalLines.UPPER_AIR_GE:
2098                case TacticalLines.ISODROSOTHERM_GE:
2099                case TacticalLines.ICE_OPENINGS_FROZEN:
2100                case TacticalLines.ICE_OPENINGS_FROZEN_GE:
2101                case TacticalLines.ICE_EDGE_RADAR:
2102                case TacticalLines.ICE_EDGE_RADAR_GE:
2103                case TacticalLines.CRACKS_SPECIFIC_LOCATION:
2104                case TacticalLines.CRACKS_SPECIFIC_LOCATION_GE:
2105                case TacticalLines.EBB_TIDE:
2106                case TacticalLines.FLOOD_TIDE:
2107                case TacticalLines.EBB_TIDE_GE:
2108                case TacticalLines.FLOOD_TIDE_GE:
2109                case TacticalLines.JET:
2110                case TacticalLines.STREAM:
2111                case TacticalLines.JET_GE:
2112                case TacticalLines.STREAM_GE:
2113                    lineObject.moveTo(P0.x, P0.y);
2114                    lineObject.curveTo(P1.x, P1.y, P2.x, P2.y, P3.x, P3.y);
2115                    //do not return, we still need the spline points
2116                    //to claculate other features
2117                    break;
2118                default:
2119                    //the rest of them must use the calculated curve points
2120                    break;
2121            }
2122            //var sprite:Sprite;
2123            int j = 0;
2124            double distance;
2125            int n = 0;
2126            double x = 0, y = 0, increment = 0;
2127            POINT2 pt0, pt1, pt2;
2128            double t;
2129            POINT2 pt;
2130            array.clear();
2131            //distance=clsUtility.Distance2(P0,Pa_1);
2132            //add the curve points to tg.Pixels
2133            switch (tg.get_LineType()) {
2134                case TacticalLines.ICE_EDGE_RADAR:
2135                case TacticalLines.ICE_EDGE_RADAR_GE:
2136                    increment = arraysupport.getScaledSize(20, tg.get_LineThickness());
2137                    break;
2138                case TacticalLines.ICE_OPENINGS_FROZEN:
2139                case TacticalLines.ICE_OPENINGS_FROZEN_GE:
2140                case TacticalLines.CRACKS_SPECIFIC_LOCATION:
2141                case TacticalLines.CRACKS_SPECIFIC_LOCATION_GE:
2142                    //increment = 12.0;
2143                    increment = arraysupport.getScaledSize(7, tg.get_LineThickness());
2144                    break;
2145                default:
2146                    increment = arraysupport.getScaledSize(10, tg.get_LineThickness());
2147                    break;
2148            }
2149
2150            distance = lineutility.CalcDistanceDouble(P0, Pa_1);
2151            if(distance<increment)
2152                distance=increment;
2153            n = (int) (distance / increment);
2154            
2155            pt0 = P0;
2156            pt1 = Pc_1;
2157            pt2 = Pa_1;
2158            for (j = 0; j < n; j++) {
2159                t = (double) j * (increment / distance);
2160                x = (1d - t) * (1d - t) * pt0.x + 2 * (1d - t) * t * pt1.x + t * t * pt2.x;
2161                y = (1d - t) * (1d - t) * pt0.y + 2 * (1d - t) * t * pt1.y + t * t * pt2.y;
2162                pt = new POINT2(x, y);
2163                //array.push(pt);
2164                array.add(pt);
2165            }
2166            //distance=clsUtility.Distance2(Pa_1,Pa_2);
2167            distance = lineutility.CalcDistanceDouble(Pa_1, Pa_2);
2168
2169            //add the curve points to tg.Pixels
2170            n = (int) (distance / increment);
2171            pt0 = Pa_1;
2172            pt1 = Pc_2;
2173            pt2 = Pa_2;
2174            for (j = 0; j < n; j++) {
2175                t = (double) j * (increment / distance);
2176                x = (1d - t) * (1d - t) * pt0.x + 2 * (1d - t) * t * pt1.x + t * t * pt2.x;
2177                y = (1d - t) * (1d - t) * pt0.y + 2 * (1d - t) * t * pt1.y + t * t * pt2.y;
2178                pt = new POINT2(x, y);
2179                array.add(pt);
2180            }
2181
2182            //distance=clsUtility.Distance2(Pa_2,Pa_3);
2183            distance = lineutility.CalcDistanceDouble(Pa_2, Pa_3);
2184            //add the curve points to tg.Pixels
2185            n = (int) (distance / increment);
2186            pt0 = Pa_2;
2187            pt1 = Pc_3;
2188            pt2 = Pa_3;
2189            for (j = 0; j < n; j++) {
2190                t = (double) j * (increment / distance);
2191                x = (1d - t) * (1d - t) * pt0.x + 2 * (1d - t) * t * pt1.x + t * t * pt2.x;
2192                y = (1d - t) * (1d - t) * pt0.y + 2 * (1d - t) * t * pt1.y + t * t * pt2.y;
2193                pt = new POINT2(x, y);
2194                array.add(pt);
2195            }
2196            //distance=clsUtility.Distance2(Pa_3,P3);
2197            distance = lineutility.CalcDistanceDouble(Pa_3, P3);
2198            //add the curve points to tg.Pixels
2199            n = (int) (distance / increment);
2200            pt0 = Pa_3;
2201            pt1 = Pc_4;
2202            pt2 = P3;
2203            for (j = 0; j < n; j++) {
2204                t = (double) j * (increment / distance);
2205                x = (1d - t) * (1d - t) * pt0.x + 2 * (1d - t) * t * pt1.x + t * t * pt2.x;
2206                y = (1d - t) * (1d - t) * pt0.y + 2 * (1d - t) * t * pt1.y + t * t * pt2.y;
2207                pt = new POINT2(x, y);
2208                array.add(pt);
2209            }
2210        }
2211        catch (Exception exc) {
2212               ErrorLogger.LogException(_className ,"drawCubicBezier2",
2213                    new RendererException("Failed inside drawCubicBezier2", exc));
2214        }
2215        return array;
2216    }
2217
2218    /*
2219     *
2220     * Called by Splines2TG to get straight channel lines for splines.
2221     *
2222     * @param tg - TGlight
2223     *
2224     * @return An ArrayList to use for building the parallel splines
2225     */
2226//    private static ArrayList ParallelLines(TGLight tg,int rev) {
2227//        ArrayList<POINT2> channelPoints2 = new ArrayList();
2228//        try {
2229//            double[] pLinePoints = new double[tg.Pixels.size() * 2];
2230//            double[] channelPoints = new double[6 * tg.Pixels.size()];
2231//            int j = 0;
2232//            int n=tg.Pixels.size();
2233//            //for (j = 0; j < tg.Pixels.size(); j++) 
2234//            for (j = 0; j < n; j++) 
2235//            {
2236//                pLinePoints[2 * j] = tg.Pixels.get(j).x;
2237//                pLinePoints[2 * j + 1] = tg.Pixels.get(j).y;
2238//            }
2239//            int numPoints = tg.Pixels.size();
2240//            int channelWidth = 20;
2241//            int usePtr = 0;
2242//            ArrayList<Shape2> shapes = null;
2243//
2244//            try {
2245//                CELineArray.CGetChannel2Double(pLinePoints, pLinePoints, channelPoints, numPoints, numPoints, (int) TacticalLines.CHANNEL, channelWidth, usePtr, shapes,rev);
2246//            } catch (Exception e) {
2247//                ErrorLogger.LogException(_className, "ParallelLines",
2248//                    new RendererException("Failed inside ParallelLines", e));
2249//            }
2250//
2251//            POINT2 pt2 = null;
2252//            int style = 0;
2253//            n=channelPoints.length;
2254//            //for (j = 0; j < channelPoints.length / 3; j++) 
2255//            for (j = 0; j < n / 3; j++) 
2256//            {
2257//                pt2 = new POINT2(channelPoints[3 * j], channelPoints[3 * j + 1], style);
2258//                channelPoints2.add(pt2);
2259//            }
2260//        } catch (Exception exc) {
2261//            ErrorLogger.LogException(_className, "ParallelLines",
2262//                    new RendererException("Failed inside ParallelLines", exc));
2263//        }
2264//        return channelPoints2;
2265//    }
2266    /**
2267     * Call this function with segment
2268     * @param Pixels a segment of tg.Pixels
2269     * @return
2270     */
2271    private static ArrayList<POINT2> ParallelLines2(ArrayList<POINT2> Pixels, int channelWidth) {
2272        ArrayList<POINT2> channelPoints2 = new ArrayList();
2273        try {
2274            double[] pLinePoints = new double[Pixels.size() * 2];
2275            double[] channelPoints = new double[6 * Pixels.size()];
2276            int j = 0;
2277            int n=Pixels.size();
2278            //for (j = 0; j < Pixels.size(); j++) 
2279            for (j = 0; j < n; j++) 
2280            {
2281                pLinePoints[2 * j] = Pixels.get(j).x;
2282                pLinePoints[2 * j + 1] = Pixels.get(j).y;
2283            }
2284            int numPoints = Pixels.size();
2285            int usePtr = 0;
2286            ArrayList<Shape2> shapes = null;
2287
2288            try {
2289                TGLight tg = new TGLight();
2290                tg.set_LineType(TacticalLines.CHANNEL);
2291                Channels.GetChannel1Double(tg, pLinePoints, pLinePoints, channelPoints, numPoints, numPoints, channelWidth, usePtr, shapes);
2292            } catch (Exception e) {
2293                ErrorLogger.LogException(_className, "ParallelLines2",
2294                    new RendererException("Failed inside ParallelLines2", e));
2295            }
2296
2297            POINT2 pt2 = null;
2298            int style = 0;
2299            n=channelPoints.length;
2300            //for (j = 0; j < channelPoints.length / 3; j++) 
2301            for (j = 0; j < n / 3; j++) 
2302            {
2303                pt2 = new POINT2(channelPoints[3 * j], channelPoints[3 * j + 1], style);
2304                channelPoints2.add(pt2);
2305            }
2306        } catch (Exception exc) {
2307            ErrorLogger.LogException(_className, "ParallelLines2",
2308                    new RendererException("Failed inside ParallelLines2", exc));
2309        }
2310        return channelPoints2;
2311    }
2312}