001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005package sec.web.render;
006
007import sec.geo.GeoPoint;
008import sec.geo.kml.KmlOptions;
009import sec.geo.kml.KmlRenderer;
010import sec.geo.kml.XsltCoordinateWrapper;
011import sec.geo.shape.Cake;
012import sec.geo.shape.Radarc;
013import sec.geo.shape.Route;
014import sec.geo.shape.Track;
015import sec.web.exceptions.InvalidNumberOfPointsException;
016import sec.geo.utilities.StringBuilder;
017
018
019/**
020 * Responsible for generating the KML for all 3D shapes.  This
021 * 
022 * 
023 * @author stephen.pinizzotto
024 */
025@SuppressWarnings({"unused"})
026public class Shape3DHandler {
027
028    // constants for the available shape types that can
029    // be generated into KML
030    public static final String CYLINDER = "CYLINDER-------";
031    public static final String ORBIT = "ORBIT----------";
032    public static final String ROUTE = "ROUTE----------";
033    public static final String POLYGON = "POLYGON--------";
034    public static final String RADARC = "RADARC---------";
035    public static final String POLYARC = "POLYARC--------";
036    public static final String CAKE = "CAKE-----------";
037    public static final String TRACK = "TRACK----------";
038    // Attribute names of the 3D shapes
039    public static final String ATTRIBUTES = "attributes";
040    public static final String MIN_ALT = "minalt";
041    public static final String MAX_ALT = "maxalt";
042    public static final String RADIUS1 = "radius1";
043    public static final String RADIUS2 = "radius2";
044    public static final String LEFT_AZIMUTH = "leftAzimuth";
045    public static final String RIGHT_AZIMUTH = "rightAzimuth";
046    // Arbitrary default values of attributes
047    public static final double MIN_ALT_DEFAULT = 0.0D;
048    public static final double MAX_ALT_DEFAULT = 100.0D;
049    public static final double RADIUS1_DEFAULT = 50.0D;
050    public static final double RADIUS2_DEFAULT = 100.0D;
051    public static final double LEFT_AZIMUTH_DEFAULT = 0.0D;
052    public static final double RIGHT_AZIMUTH_DEFAULT = 90.0D;
053    
054    public static final String DEFAULT_ATTRIBUTES = "[{radius1:"
055            + RADIUS1_DEFAULT + ",radius2:"
056            + RADIUS2_DEFAULT + ",minalt:"
057            + MIN_ALT_DEFAULT + ",maxalt:"
058            + MAX_ALT_DEFAULT + ",rightAzimuth:"
059            + RIGHT_AZIMUTH_DEFAULT + ",leftAzimuth:"
060            + LEFT_AZIMUTH_DEFAULT + "}]";
061    // Error messages
062    public static final String ERR_ATTRIBUTES_NOT_FORMATTED = "{\"type\":\"error\","
063            + "\"error\":\"The attribute paramaters are not formatted "
064            + "correctly";
065    public static final String ERR_COORDINATES_NOT_FORMATTED = "{\"type\":\"error\",\""
066            + "error\":\"There was an error creating the Symbol - the "
067            + "coordinates were not formatted correctly";
068    public static final String ERR_GENERAL_ERROR = "{\"type\":\"error\",\"error\""
069            + ":\"There was an error creating the Symbol - An unknown error "
070            + "occurred.  Please refer to the stack trace";
071    public static final String ERR_INVALID_NUMBER_POINTS_ERROR = "{\"type\":\""
072            + "error\","
073            + "\"error\":\"Not enough points were passed in to create a "
074            + "graphic.";       
075
076    /**
077     * Generates the KML for a 3D symbol.  Symbol should include the all the
078     * attributes and information required by the KML for output.  
079     * 
080     * @param name The user displayed name for the symbol.  Users will use this 
081     * to identify with the symbol.
082     * @param id An internally used unique id that developers can use to 
083     * uniquely distinguish this symbol from others.
084     * @param shapeType A 15 character ID of the type of symbol to draw.
085     * @param description A brief description of what the symbol represents.  
086     * Generic text that does not require any format.
087     * @param color The fill color of the graphic
088     * @param altitudeMode Indicates whether the symbol should interpret 
089     * altitudes as above sea level or above ground level. Options are 
090     * "relativeToGround" (from surface of earth), "absolute" (sea level), 
091     * "relativeToSeaFloor" (from the bottom of major bodies of water).
092     * @param controlPoints The vertices of the shape.  The number of required
093     * vertices varies based on the shapeType of the symbol.  The simplest shape 
094     * requires at least one point.  Shapes that require more points than 
095     * required will ignore extra points.  Format for numbers is as follows: 
096     * <br/><br/>
097     * "x,y,z [x,y,z ]..."
098     * @param attributes A JSON  A JSON array holding the parameters for the 
099     * shape.  Attributes should be of the following format: <br/><br/>
100     * <tr><code>{"attributes":[{"<i>attribute1</i>":<i>value</i>,...},{<i>[optional]</i>]}</code></tr>
101     * @return A KML string that represents a placemark for the 3D shape
102     */
103    public static String render3dSymbol(String name, String id, String shapeType,
104            String description, String lineColor, String fillColor, String altitudeMode,
105            String controlPoints,
106            SymbolModifiers attributes) {
107
108        String result = "";
109        
110        KmlOptions.AltitudeMode convertedAltitudeMode = KmlOptions.AltitudeMode.RELATIVE_TO_GROUND;
111
112        // Convert altitude mode to an enum that we understand.  If it does not
113        // understand or is "", then convert to ALTITUDE_RELATIVE_TO_GROUND.
114        if (!altitudeMode.equals(""))
115        {
116            convertedAltitudeMode = KmlOptions.AltitudeMode.fromString(altitudeMode);
117        }
118                
119        if (shapeType.equals(CYLINDER)) {
120            result = buildCylinder(controlPoints, id, name, description, lineColor, fillColor, convertedAltitudeMode, attributes);            
121        } else if (shapeType.equals(ORBIT)) {
122            result = buildOrbit(controlPoints, id, name, description, lineColor, fillColor, convertedAltitudeMode, attributes);
123        } else if (shapeType.equals(RADARC)) {
124            result = buildRadarc(controlPoints, id, name, description, lineColor, fillColor, convertedAltitudeMode, attributes);
125        } else if (shapeType.equals(POLYARC)) {
126            result = buildPolyArc(controlPoints, id, name, description, lineColor, fillColor, convertedAltitudeMode, attributes);
127        } else if (shapeType.equals(ROUTE)) {
128            result = buildRoute(controlPoints, id, name, description, lineColor, fillColor, convertedAltitudeMode, attributes);
129        } else if (shapeType.equals(POLYGON)) {
130            result = buildPolygon(controlPoints, id, name, description, lineColor, fillColor, convertedAltitudeMode, attributes);
131        } else if (shapeType.equals(CAKE)) {
132            result = buildCake(controlPoints, id, name, description, lineColor, fillColor, convertedAltitudeMode, attributes);
133        } else if (shapeType.equals(TRACK)) {
134            result = buildTrack(controlPoints, id, name, description, lineColor, fillColor, convertedAltitudeMode, attributes);
135        } else {
136            StringBuilder sb = new StringBuilder();
137            sb.append("Given shape type \""+shapeType+"\" does not match any of the available shape types.");
138            sb.append("\n");
139            sb.append("Available Types: ");
140            sb.append(CYLINDER+"\n");
141            sb.append(ORBIT+"\n");
142            sb.append(ROUTE+"\n");
143            sb.append(POLYGON+"\n");
144            sb.append(RADARC+"\n");
145            sb.append(POLYARC+"\n");
146            sb.append(CAKE+"\n");
147            sb.append(TRACK);
148
149            System.out.println(sb.toString());
150
151        }
152
153        //System.out.println(result);
154        //System.out.println("Render3DSymbolExited");
155        return result;
156    }
157        
158
159    /**
160     * Builds a 3d Polygon with elevation.
161     * 
162     * @param controlPoints
163     * @param attributes
164     * @return 
165     */
166    public static String buildPolygon(String controlPoints, String id, 
167            String name, String description, String lineColor, String fillColor, KmlOptions.AltitudeMode altitudeMode, 
168            SymbolModifiers attributes) {
169                
170        StringBuilder output = new StringBuilder();       
171        String pointArrayStringList = "";
172       
173        try {
174            
175            // Get the points of the icons.  For the polyarc we need only
176            // one point, the pivot point, then the rest of the points for the 
177            // polygon.  
178            String[] latlons = controlPoints.split(" ");
179            if (latlons.length >= 2) {
180
181                // Build the polyarc
182                pointArrayStringList = XsltCoordinateWrapper.getPolygonKml(
183                        latlons, id, name, description, lineColor, fillColor, altitudeMode,
184                        attributes.X_ALTITUDE_DEPTH.get(0), 
185                        attributes.X_ALTITUDE_DEPTH.get(1));
186            } else {
187                // throw illegal number of points exception
188                throw new InvalidNumberOfPointsException();
189            }       
190        } catch (Exception e) {
191            pointArrayStringList = "";                                     
192        }
193
194        return pointArrayStringList;
195
196    }
197
198    /**
199     * Builds a cylinder given a point. Can also apply a radius size and an
200     * altitude for lower and upper boundaries.
201     * @param controlPoints 
202     * @param attributes
203     * @return 
204     */
205    public static String buildCylinder(String controlPoints, String id, 
206            String name, String description, String lineColor, String fillColor, KmlOptions.AltitudeMode altitudeMode, 
207            SymbolModifiers attributes) {
208        StringBuilder output = new StringBuilder();        
209        String pointArrayStringList = "";
210
211        // variables for the cylinder position
212        double pivotx = 0.0D;
213        double pivoty = 0.0D;
214
215        try {           
216            
217            // Get the points of the icons.  For the cylinder we need only
218            // one point.  Ignore any more than the first point.
219            String[] latlons = controlPoints.split(" ");
220
221            if (latlons.length > 0) {
222                String[] pivot = latlons[0].split(",");
223
224                if (pivot.length >= 2) {
225                    pivotx = Double.parseDouble(pivot[0]);
226                    pivoty = Double.parseDouble(pivot[1]);
227                } else {
228                    throw new NumberFormatException();
229                }
230            } else {
231                // throw an illegal number of points exception
232                throw new InvalidNumberOfPointsException();
233            }
234                        
235            // Build the cylinder
236            pointArrayStringList = XsltCoordinateWrapper.getCircleKml(pivotx,
237                    pivoty, id, name, description, lineColor, fillColor, altitudeMode,
238                    attributes.AM_DISTANCE.get(0),
239                    attributes.X_ALTITUDE_DEPTH.get(0),
240                    attributes.X_ALTITUDE_DEPTH.get(1));                       
241        } catch (Exception e) {
242            pointArrayStringList = "";                                     
243        }
244
245        return pointArrayStringList;
246
247    }
248
249    public static String buildKml(String[] coords, String id, String name, String lineColor, String fillColor) {
250        StringBuilder kml = new StringBuilder();
251        kml.append("<Placemark>");
252        kml.append("<name>");
253        kml.append(name);
254        kml.append("</name>");
255        kml.append("<id>");
256        kml.append(id);
257        kml.append("</id>");
258        kml.append("<Style>");
259        kml.append("<PolyStyle>");
260        kml.append("<color>");
261        kml.append(fillColor);
262        kml.append("</color>");
263
264        kml.append("</PolyStyle>");
265        kml.append("<LineStyle>");
266        kml.append(lineColor);
267        kml.append("</LineStyle>");
268        kml.append("</Style>");
269        kml.append("<MultiGeometry>");
270        for (String s : coords) {
271            kml.append("<Polygon>");
272            kml.append("<extrude>0</extrude>");
273            kml.append("<altitudeMode>relativeToGround</altitudeMode>");
274            kml.append("<outerBoundaryIs>");
275            kml.append("<LinearRing>");
276            kml.append("<coordinates>");
277            kml.append(s);
278            kml.append("</coordinates>");
279            kml.append("</LinearRing>");
280            kml.append("</outerBoundaryIs>");
281            kml.append("</Polygon>");
282        }
283        kml.append("</MultiGeometry>");
284        kml.append("</Placemark>");
285        return kml.toString();
286    }
287
288    /**
289     * Build an Orbit graphic.  
290     * 
291     * @param controlPoints
292     * @param attributes
293     * @return 
294     */
295    public static String buildOrbit(String controlPoints, String id, 
296            String name, String description, String lineColor, String fillColor, KmlOptions.AltitudeMode altitudeMode, 
297            SymbolModifiers attributes) {
298
299        StringBuilder output = new StringBuilder();        
300        String pointArrayStringList = "";
301        // variables for the cylinder position
302        double point1x = 0.0D;
303        double point1y = 0.0D;
304        double point2x = 0.0D;
305        double point2y = 0.0D;
306
307        try {
308            
309            // Get the points of the icons.  For the cylinder we need only
310            // one point.  Ignore any more than the first point.
311            String[] latlons = controlPoints.split(" ");
312            if (latlons.length > 1) {
313                String[] point1 = latlons[0].split(",");
314
315                if (point1.length >= 2) {
316                    point1x = Double.parseDouble(point1[0]); // x value
317                    point1y = Double.parseDouble(point1[1]); // y value
318                } else {
319                    throw new NumberFormatException();
320                }
321
322                String[] point2 = latlons[1].split(",");
323
324                if (point2.length >= 2) {
325                    point2x = Double.parseDouble(point2[0]);  // x value
326                    point2y = Double.parseDouble(point2[1]);  // y value
327                } else {
328                    throw new NumberFormatException();
329                }
330            } else {
331                // throw invalid number of points exception
332                throw new InvalidNumberOfPointsException();
333            }
334
335            // Build the orbit
336            pointArrayStringList = XsltCoordinateWrapper.getOrbitKml(point1x, point1y,
337                    point2x, point2y, id, name, description, lineColor, fillColor,  altitudeMode, attributes.AM_DISTANCE.get(0), attributes.X_ALTITUDE_DEPTH.get(0), attributes.X_ALTITUDE_DEPTH.get(1));
338
339        } catch (Exception e) {
340            pointArrayStringList = "";                                     
341        }
342
343        return pointArrayStringList;
344
345    }
346
347    /**
348     * Builds the Radarc graphic
349     * 
350     * @param controlPoints
351     * @param attributes 
352     * @return 
353     */
354    public static String buildRadarc(String controlPoints, String id, 
355            String name, String description, String lineColor, String fillColor, KmlOptions.AltitudeMode altitudeMode, 
356            SymbolModifiers attributes) {
357
358        StringBuilder output = new StringBuilder();      
359        String pointArrayStringList = "";
360        
361        // variables for the cylinder position
362        double pivotx = 0.0D;
363        double pivoty = 0.0D;
364
365        try {        
366
367            // Get the points of the icons.  For the radarc we need only
368            // one point.  Ignore any more than the first point.
369            String[] latlons = controlPoints.split(" ");
370            if (latlons.length > 0) {
371                String[] pivot = latlons[0].split(",");
372
373                if (pivot.length >= 2) {
374                    pivotx = Double.parseDouble(pivot[0]);
375                    pivoty = Double.parseDouble(pivot[1]);
376                } else {
377                    throw new NumberFormatException();
378                }
379            } else {
380                // throw invalid number of points exception
381                throw new InvalidNumberOfPointsException();
382            }
383
384            // Build the orbit
385            pointArrayStringList = XsltCoordinateWrapper.getRadarcKml(pivotx, pivoty,
386                    id, name, description, lineColor, fillColor, altitudeMode,
387                    attributes.AM_DISTANCE.get(0), 
388                    attributes.AM_DISTANCE.get(1), 
389                    attributes.AN_AZIMUTH.get(0), 
390                    attributes.AN_AZIMUTH.get(1), 
391                    attributes.X_ALTITUDE_DEPTH.get(0), 
392                    attributes.X_ALTITUDE_DEPTH.get(1));
393
394
395        } catch (Exception e) {
396            pointArrayStringList = "";                                     
397        }
398
399        return pointArrayStringList;
400
401    }
402
403    /**
404     * Builds the PolyArc graphic
405     * 
406     * @param controlPoints
407     * @param attributes
408     * @return 
409     */
410    public static String buildPolyArc(String controlPoints, String id, 
411            String name, String description, String lineColor, String fillColor, KmlOptions.AltitudeMode altitudeMode, 
412            SymbolModifiers attributes) {
413        StringBuilder output = new StringBuilder();
414        
415        String pointArrayStringList = "";
416        
417        // variables for the cylinder position
418        double pivotx = 0.0D;
419        double pivoty = 0.0D;
420
421        try {
422            // Get the points of the icons.  For the polyarc we need only
423            // one point, the pivot point, then the rest of the points for the 
424            // polygon.  
425            String[] latlons = controlPoints.split(" ");
426            if (latlons.length >= 3) {
427                String[] pivot = latlons[0].split(",");
428
429                if (pivot.length >= 2) {
430                    pivotx = Double.parseDouble(pivot[0]);
431                    pivoty = Double.parseDouble(pivot[1]);
432                } else {
433                    throw new NumberFormatException();
434                }
435
436                int length = latlons.length - 1;
437                String[] points = new String[length];
438                System.arraycopy(latlons, 1, points, 0, length);
439                              
440
441                // Build the polyarc
442                pointArrayStringList = XsltCoordinateWrapper.getPolyarcKml(points,
443                        pivotx, pivoty, id, name, description, lineColor, fillColor, altitudeMode,
444                        attributes.AM_DISTANCE.get(0),
445                        attributes.AN_AZIMUTH.get(0), attributes.AN_AZIMUTH.get(1),
446                        attributes.X_ALTITUDE_DEPTH.get(0), attributes.X_ALTITUDE_DEPTH.get(1));
447
448            } else {
449                // illegal number of points exception
450                throw new InvalidNumberOfPointsException();
451            }
452        } catch (Exception e) {
453            pointArrayStringList = "";                                     
454        }
455
456        return pointArrayStringList;
457
458    }
459
460    /**
461     * Builds a route graphic.
462     * @param controlPoints
463     * @param attributes
464     * @return 
465     */
466    public static String buildRoute(String controlPoints, String id, 
467            String name, String description, String lineColor, String fillColor, KmlOptions.AltitudeMode altitudeMode, 
468            SymbolModifiers attributes) {
469        
470        String pointArrayStringList = "";  
471        double width;
472        double leftWidth;
473        double rightWidth;               
474
475        try {
476            // Get the points of the icons.  For the polyarc we need only
477            // one point, the pivot point, then the rest of the points for the 
478            // polygon.  
479            String[] latlons = controlPoints.split(" ");
480            if (latlons.length >= 2) {
481                width = attributes.AM_DISTANCE.get(0);
482                leftWidth = width / 2;
483                rightWidth = width / 2;
484                
485                // Build the polyarc
486                pointArrayStringList = XsltCoordinateWrapper.getRouteKml(latlons,
487                        id, name, description, lineColor, fillColor, altitudeMode,
488                        leftWidth, rightWidth, attributes.X_ALTITUDE_DEPTH.get(0), attributes.X_ALTITUDE_DEPTH.get(1));
489
490            } else {
491                // illegal number of points exception
492                throw new InvalidNumberOfPointsException();
493            }
494        } catch (Exception e) {
495            pointArrayStringList = "";                                     
496        }
497
498        return pointArrayStringList;
499
500    }
501
502    /**
503     * Builds a cake graphic--multiple radarcs stacked on top of each other.
504     * <br/>
505     * This graphic can take up to 6 attributes.  "radius1" is the max radius, 
506     * "radius2" is the min radius, "minalt", "maxalt", "leftAzimuth", and 
507     * "rightAzimuth"
508     * 
509     * @param controlPoints
510     * @param attributes
511     * @return 
512     */
513    public static String buildCake(String controlPoints, String id, 
514            String name, String description, String lineColor, String fillColor, KmlOptions.AltitudeMode altitudeMode, 
515            SymbolModifiers attributes) {
516
517        StringBuilder output = new StringBuilder();        
518        String pointArrayStringList = "";
519
520        // Creat a new cake to begin adding layers to.
521        Cake letThemEat = new Cake();
522
523        // variables for the cylinder position
524        double pivotx = 0.0D;
525        double pivoty = 0.0D;
526
527        // Used to store all the polygons for the cakelayers
528        //Set<KmlPolygon> combinedCakeLayers = null;
529
530        // Used to generate the points
531        KmlRenderer kmlRender = new KmlRenderer();
532
533        try {
534
535            // Get the points of graphic.  
536            String[] latlons = controlPoints.split(" ");
537            int numberOfPoints = latlons.length;
538
539            if (numberOfPoints > 0) {
540
541                //get the pivot point for this graphics.
542                // all cake layers will use this pivot point for its 
543                //origin.               
544                String[] pivotString = latlons[0].split(",");
545
546                if (pivotString.length >= 2) {
547                    pivotx = Double.parseDouble(pivotString[0]);
548                    pivoty = Double.parseDouble(pivotString[1]);
549                    letThemEat.setPivot(new GeoPoint(pivotx, pivoty));
550                } else {
551                    throw new NumberFormatException();
552                }
553                
554                int attributesArrayLength = attributes.X_ALTITUDE_DEPTH.size();                                
555                
556                for (int i = 0; i < attributesArrayLength; i++) {
557                    // Create a new cake layer and set its pivot point.
558                    Radarc layerCake = new Radarc();
559                    layerCake.setAltitudeMode(altitudeMode);
560                    layerCake.setPivot(new GeoPoint(pivotx, pivoty));
561                    
562                    layerCake.setMinRadius(attributes.AM_DISTANCE.get(i));
563                    layerCake.setRadius(attributes.AM_DISTANCE.get(i + 1));
564                    layerCake.setMinAltitude(attributes.X_ALTITUDE_DEPTH.get(i));
565                    layerCake.setMaxAltitude(attributes.X_ALTITUDE_DEPTH.get(i + 1));
566                    layerCake.setLeftAzimuthDegrees(attributes.AN_AZIMUTH.get(i));
567                    layerCake.setRightAzimuthDegrees(attributes.AN_AZIMUTH.get(i + 1));
568                    i++;
569                    
570                    letThemEat.addLayer(layerCake);
571
572                }
573
574                pointArrayStringList = kmlRender.getCakeKml(letThemEat, id, name, description, lineColor, fillColor);
575                
576            } else {
577                // if not enough points throw exception
578                throw new InvalidNumberOfPointsException();
579            }        
580        } catch (Exception e) {
581            pointArrayStringList = "";                                     
582        }
583
584        return pointArrayStringList;
585    }
586
587    /**
588     * Builds a track graphic composed of multiple routes
589     * 
590     * @param controlPoints
591     * @param attributes
592     * @return 
593     */
594    public static String buildTrack(String controlPoints, String id, 
595            String name, String description, String lineColor, String fillColor, KmlOptions.AltitudeMode altitudeMode, 
596            SymbolModifiers attributes) {
597              
598        String pointArrayStringList = "";        
599        
600        // generates the points for the track.
601        KmlRenderer kmlRender = new KmlRenderer();
602
603        try {
604
605            // Get the points of graphic.  
606            String[] latlons = controlPoints.split(" ");
607            int numberOfPoints = latlons.length;            
608            
609            //ensure enough values in distance and altitude arrays for the number of points M. Deutch 4-15-15
610            int numAM=attributes.AM_DISTANCE.size();
611            int numX=attributes.X_ALTITUDE_DEPTH.size();
612            double nextToLastAlt=attributes.X_ALTITUDE_DEPTH.get(numX-2);
613            double lastAlt=attributes.X_ALTITUDE_DEPTH.get(numX-1);
614            double lastWidth=attributes.AM_DISTANCE.get(numAM-1);
615            int delta=2*(numberOfPoints-1)-numAM;   //one width per segment            
616            delta=2*(numberOfPoints-1)-numX;    //two alts per segment
617            int j=0;
618            if(delta>0)
619                for(j=0;j<delta;j++)
620                    attributes.AM_DISTANCE.add(lastWidth);
621            int k=0;
622            while(k<delta)
623            {
624                attributes.X_ALTITUDE_DEPTH.add(nextToLastAlt);
625                attributes.X_ALTITUDE_DEPTH.add(lastAlt);
626                k+=2;
627            }
628
629            // Ensure the track has an appropriate amount of points.
630            if (numberOfPoints >= 2) {                               
631
632                Track track = new Track();                
633
634                for (int i = 0; i < numberOfPoints - 1; i++) {
635                    // Create a new route from first point to the next point.
636                    Route route = new Route();
637                    route.setAltitudeMode(altitudeMode);
638
639                    String[] point1String = latlons[i].split(",");
640                    String[] point2String = latlons[i + 1].split(",");
641
642                    double point1lon = 0.0D;
643                    double point1lat = 0.0D;
644                    double point2lon = 0.0D;
645                    double point2lat = 0.0D;
646                    if (point1String.length >= 2) {
647                        point1lon = Double.parseDouble(point1String[0]);
648                        point1lat = Double.parseDouble(point1String[1]);
649                    } else {
650                        throw new NumberFormatException();
651                    }
652
653                    if (point2String.length >= 2) {
654                        point2lon = Double.parseDouble(point2String[0]);
655                        point2lat = Double.parseDouble(point2String[1]);
656                    } else {
657                        throw new NumberFormatException();
658                    }
659
660                    route.addPoint(new GeoPoint(point1lon, point1lat));
661                    route.addPoint(new GeoPoint(point2lon, point2lat));                    
662                    route.setLeftWidth(attributes.AM_DISTANCE.get(2 * i));
663                    route.setRightWidth(attributes.AM_DISTANCE.get(2 * i + 1));
664                    route.setMinAltitude(attributes.X_ALTITUDE_DEPTH.get(2 * i));
665                    route.setMaxAltitude(attributes.X_ALTITUDE_DEPTH.get(2 * i + 1));
666                    
667                    // Add the route to our track
668                    track.addRoute(route);
669
670                }
671                
672                pointArrayStringList = kmlRender.getKml(track, id, name, description, lineColor, fillColor);
673
674            } else {                
675                //throw invalid number of points exception
676                throw new InvalidNumberOfPointsException();
677            }        
678        } catch (Exception e) {
679            pointArrayStringList = "";                                     
680        }      
681        return pointArrayStringList;
682
683    }
684}