package sec.geo.kml; import armyc2.c2sd.graphics2d.PathIterator; import sec.sun.awt.geom.AreaIterator; import java.util.ArrayList; import sec.geo.utilities.StringBuilder; import sec.geo.shape.*; public class KmlRenderer { private static final String EXCEPTION = "EXCEPTION:"; private static final String colorDefault = "ff003fff"; private static final String descriptionField = "#DESCRIPTION#"; private static final String extendedData = "#EXTENDEDDATA#"; private static final String colorField = "#COLOR#"; private static final String nameField = "#NAME#"; private static final String idField = "#ID#"; private static final String placemarkidField = "#PLACEMARKID#"; private static final String KML_START = "<Folder id=\"" + idField + "\">\n"; private static final String KML_END = "</Folder>\n"; private static final String PLACEMARK_START = "" + " <Placemark id=\"" + placemarkidField + "\">\n" + " <Style>\n" + " <PolyStyle>\n" + " <color>" + colorField + "</color>\n" + " </PolyStyle>\n" + " <LineStyle>\n" + " <color>" + colorField + "</color>\n" + " </LineStyle>\n" + " </Style>\n" + " <name>" + nameField + "</name>\n" + " <description>" + descriptionField + "</description>\n" + " <ExtendedData>" + extendedData + "</ExtendedData>\n" + " <MultiGeometry>\n"; private static final String PLACEMARK_END = "" + " </MultiGeometry>\n" + " </Placemark>\n"; //private static final String DEFAULT_EXDAT = "<Data name='sid'><value>#ID#</value></Data><Data name='shapeType'><value>#SHAPETYPE#</value></Data><Data name='lat'><value>#LAT#</value></Data><Data name='lon'><value>#LON#</value></Data><Data name='alt'><value>#ALT#</value></Data>"; //private static final String DEFAULT_BLSTY = "<!" + "[CDAT" + "A[" + "$[sid]" +"]]"+">"; public ArrayList<KmlPolygon> renderPolygons(AExtObject ext) { ArrayList<KmlPolygon> polys = new ArrayList<KmlPolygon>(); ext.setMaxDistance(200000); //ext.setFlatness(1); //ext.setLimit(3); ext.setFlatness(2); ext.setLimit(8); // Render perimeter polys ArrayList<Point> perimeterPoints = new ArrayList<Point>(); PathIterator it = null; AreaIterator ait = null; //PathIterator it = ext.getShape().getPathIterator(null); Object oit = ext.getPathIterator(null); if (oit instanceof PathIterator) { it = (PathIterator) oit; } else if (oit instanceof AreaIterator) { ait = (AreaIterator) oit; } Point pre = null; if (it != null) { while (!it.isDone()) { double[] strokePoints = new double[6]; int type = it.currentSegment(strokePoints); double longitudeDegrees = strokePoints[0]; double latitudeDegrees = strokePoints[1]; if (longitudeDegrees < -180) { longitudeDegrees += 360; } switch (type) { case PathIterator.SEG_MOVETO: case PathIterator.SEG_LINETO: if (pre != null) { ArrayList<Point> ps = new ArrayList<Point>(); ps.add(new Point(pre.getLongitude(), pre.getLatitude(), ext.getMinAltitude())); ps.add(new Point(pre.getLongitude(), pre.getLatitude(), ext.getMaxAltitude())); ps.add(new Point(longitudeDegrees, latitudeDegrees, ext.getMaxAltitude())); ps.add(new Point(longitudeDegrees, latitudeDegrees, ext.getMinAltitude())); ps.add(new Point(pre.getLongitude(), pre.getLatitude(), ext.getMinAltitude())); polys.add(new KmlPolygon(ps, ext.getAltitudeMode())); } pre = new Point(longitudeDegrees, latitudeDegrees); perimeterPoints.add(pre); } it.next(); } } else if (ait != null) { while (!ait.isDone()) { double[] strokePoints = new double[6]; int type = ait.currentSegment(strokePoints); double longitudeDegrees = strokePoints[0]; double latitudeDegrees = strokePoints[1]; if (longitudeDegrees < -180) { longitudeDegrees += 360; } switch (type) { case PathIterator.SEG_MOVETO: case PathIterator.SEG_LINETO: if (pre != null) { ArrayList<Point> ps = new ArrayList<Point>(); ps.add(new Point(pre.getLongitude(), pre.getLatitude(), ext.getMinAltitude())); ps.add(new Point(pre.getLongitude(), pre.getLatitude(), ext.getMaxAltitude())); ps.add(new Point(longitudeDegrees, latitudeDegrees, ext.getMaxAltitude())); ps.add(new Point(longitudeDegrees, latitudeDegrees, ext.getMinAltitude())); ps.add(new Point(pre.getLongitude(), pre.getLatitude(), ext.getMinAltitude())); polys.add(new KmlPolygon(ps, ext.getAltitudeMode())); } pre = new Point(longitudeDegrees, latitudeDegrees); perimeterPoints.add(pre); } ait.next(); } } // Render top and bottom poly if the perimeter is complete if (perimeterPoints.size() > 0) { // In some weird cases, for routes, when it builds an area, it will drop the closing // point in the shape. Route uses an area. This causes this condition to not execute. // adding the first point to the perimeterPoints fixes the issue, not sure if it causes any // side effects. if (perimeterPoints.get(0).equals(perimeterPoints.get(perimeterPoints.size() - 1))) { polys.add(new KmlPolygon(transformPoints(perimeterPoints, ext.getMinAltitude()), ext.getAltitudeMode())); polys.add(new KmlPolygon(transformPoints(perimeterPoints, ext.getMaxAltitude()), ext.getAltitudeMode())); } else { perimeterPoints.add(perimeterPoints.get(0)); polys.add(new KmlPolygon(transformPoints(perimeterPoints, ext.getMinAltitude()), ext.getAltitudeMode())); polys.add(new KmlPolygon(transformPoints(perimeterPoints, ext.getMaxAltitude()), ext.getAltitudeMode())); } } return polys; } //public String getPlacemarkKml(AExtrusion ext, String id, String name, String description, String lineColor, String fillColor) { public String getPlacemarkKml(AExtObject ext, String id, String name, String description, String lineColor, String fillColor) { try { StringBuilder sb = new StringBuilder(); ArrayList<KmlPolygon> polys = renderPolygons(ext); sb.append(PLACEMARK_START); int placemarkIdIndex = sb.indexOf(placemarkidField); int placemarkIdLength = placemarkidField.length(); if (id != null) { sb.replace(placemarkIdIndex, placemarkIdIndex + placemarkIdLength, id + "_mg"); } int descriptionIndex = sb.indexOf(descriptionField); int descriptionLength = descriptionField.length(); if (description != null) { sb.replace(descriptionIndex, descriptionIndex + descriptionLength, description); } int colorIndex = sb.indexOf(colorField); int colorLength = colorField.length(); if (fillColor != null) { sb.replace(colorIndex, colorIndex + colorLength, fillColor); } else { sb.replace(colorIndex, colorIndex + colorLength, colorDefault); } int lineColorIndex = sb.indexOf2(colorField, colorIndex + colorLength); if (lineColor != null) { sb.replace(lineColorIndex, lineColorIndex + colorLength, lineColor); } else { sb.replace(lineColorIndex, lineColorIndex + colorLength, colorDefault); } int nameIndex = sb.indexOf(nameField); int nameLength = nameField.length(); if (name != null) { sb.replace(nameIndex, nameIndex + nameLength, name); } for (KmlPolygon poly : polys) { sb.append(poly.toString()); } sb.append(PLACEMARK_END); return sb.toString(); } catch (Exception e) { e.printStackTrace(); return EXCEPTION + e.getMessage(); } } //public String getKml(AExtrusion ext, String id, String name, String description, String lineColor, String fillColor) { public String getKml(Object ext, String id, String name, String description, String lineColor, String fillColor) { try { AExtObject aext = getAExtObject(ext); if (aext.getElements() != null) { return (getTrackKml(ext, id, name, description, lineColor, fillColor)); } StringBuilder sb = new StringBuilder(); sb.append(KML_START); int idIndex = sb.indexOf(idField); int idLength = idField.length(); sb.replace(idIndex, idIndex + idLength, id); sb.append(getPlacemarkKml(aext, id, name, description, lineColor, fillColor)); sb.append(KML_END); return sb.toString(); } catch (Exception e) { e.printStackTrace(); return EXCEPTION + e.getMessage(); } } public String getTrackKml(Object ext, String id, String name, String description, String lineColor, String fillColor) { try { AExtObject aext = getAExtObject(ext); StringBuilder sb = new StringBuilder(); sb.append(this.KML_START); int idIndex = sb.indexOf(this.idField); int idLength = idField.length(); sb.replace(idIndex, idIndex + idLength, id); ArrayList elements = aext.getElements(); int j = 0; int n = elements.size(); //for (j = 0; j < elements.size(); j++) for (j = 0; j < n; j++) { Route route = (Route) elements.get(j); AExtObject aext2 = new sec.geo.shape.AExtObject(route); sb.append(this.getPlacemarkKml(aext2, id, name, description, lineColor, fillColor)); } sb.append(this.KML_END); return sb.toString(); } catch (Exception e) { e.printStackTrace(); return EXCEPTION + e.getMessage(); } } public String getCakeKml(Cake com, String id, String name, String description, String lineColor, String fillColor) { StringBuilder sb = new StringBuilder(); //Set<KmlPolygon> polys; sb.append(KML_START); int idIndex = sb.indexOf(idField); int idLength = idField.length(); sb.replace(idIndex, idIndex + idLength, id); for (Object ext : com.getElements()) { AExtObject aext = new AExtObject(ext); String extStr = getPlacemarkKml(aext, id, name, description, lineColor, fillColor); if (!extStr.startsWith(EXCEPTION)) { sb.append(extStr); } } sb.append(KML_END); return sb.toString(); } private AExtObject getAExtObject(Object obj) { Line line = null; Route route = null; Circle circle = null; Polyarc polyarc = null; Polygon polygon = null; Orbit orbit = null; Radarc radarc = null; Track track = null; Cake cake = null; Point point = null; AExtObject ext = null; if (obj instanceof Line) { line = (Line) obj; ext = new AExtObject(line); } else if (obj instanceof Route) { route = (Route) obj; ext = new AExtObject(route); } else if (obj instanceof Polyarc) { polyarc = (Polyarc) obj; ext = new AExtObject(polyarc); } else if (obj instanceof Orbit) { orbit = (Orbit) obj; ext = new AExtObject(orbit); } else if (obj instanceof Polygon) { polygon = (Polygon) obj; ext = new AExtObject(polygon); } else if (obj instanceof Circle) { circle = (Circle) obj; ext = new AExtObject(circle); } else if (obj instanceof Radarc) { radarc = (Radarc) obj; ext = new AExtObject(radarc); } else if (obj instanceof Track) { track = (Track) obj; ext = new AExtObject(track); } else if (obj instanceof Cake) { cake = (Cake) obj; ext = new AExtObject(cake); } else if (obj instanceof Point) { point = (Point) obj; ext = new AExtObject(point); } return ext; } public String[] getCoords(Object obj) { AExtObject ext = getAExtObject(obj); ArrayList<KmlPolygon> polys = renderPolygons(ext); // Iterate through the polygons and produce an array of KML coordinates String[] coords = new String[polys.size()]; int i = 0; for (KmlPolygon poly : polys) { coords[i] = poly.toCoordString(); i++; } return coords; } private ArrayList<Point> transformPoints(ArrayList<Point> points, double altitudeMeters) { ArrayList<Point> returnPoints = new ArrayList<Point>(); for (Point p : points) { returnPoints.add(new Point(p.getLongitude(), p.getLatitude(), altitudeMeters)); } return returnPoints; } }