001package sec.geo; 002 003import armyc2.c2sd.graphics2d.*; 004import java.util.ArrayList; 005 006import org.gavaghan.geodesy.Angle; 007import org.gavaghan.geodesy.Ellipsoid; 008import org.gavaghan.geodesy.GeodeticCalculator; 009import org.gavaghan.geodesy.GeodeticCurve; 010import org.gavaghan.geodesy.GlobalCoordinates; 011 012public class GeoPath /* implements Shape */ { 013 protected static final Ellipsoid REFERENCE_ELLIPSOID = Ellipsoid.WGS84; 014 015 private GeneralPath path; 016 private ArrayList<GeoPoint> toPoints; 017 private double maxDistanceMeters; 018 private double flatnessDistanceMeters; 019 private int limit; 020 021 protected final GeodeticCalculator geoCalc; 022 023 public GeoPath() { 024 this(100000, 1, 4); 025 } 026 027 public GeoPath(double maxDistanceMeters, double flatnessDistanceMeters, int limit) { 028 path = new GeneralPath(); 029 toPoints = new ArrayList<GeoPoint>(); 030 geoCalc = new GeodeticCalculator(); 031 this.maxDistanceMeters = maxDistanceMeters; 032 this.flatnessDistanceMeters = flatnessDistanceMeters; 033 this.limit = limit; 034 } 035 036 public void moveTo(GeoPoint point) { 037 path.moveTo(point.x, point.y); 038 toPoints.add(point); 039 } 040 041 public void moveToLatLong(double longitudeDegrees, double latitudeDegrees) { 042 moveTo(new GeoPoint(longitudeDegrees, latitudeDegrees)); 043 } 044 045 public void lineTo(GeoPoint point) { 046 GeneralPath newPath = new GeneralPath(); 047 048 // Move to the initial point 049 GeoPoint lastPoint = new GeoPoint(); 050 if (toPoints.size() > 0) { 051 lastPoint = toPoints.get(toPoints.size() - 1); 052 newPath.moveTo(lastPoint.x, lastPoint.y); 053 } 054 055 // Calculate the curve to the new point 056 GlobalCoordinates start = toGlobalCoord(lastPoint); 057 GlobalCoordinates end = toGlobalCoord(point); 058 GeodeticCurve curve = geoCalc.calculateGeodeticCurve(REFERENCE_ELLIPSOID, start, end); 059 060 // Generate points along the curve, adding them to the new path 061 double distance = maxDistanceMeters; 062 while (distance < curve.getEllipsoidalDistance()) { 063 GlobalCoordinates c = geoCalc.calculateEndingGlobalCoordinates(REFERENCE_ELLIPSOID, start, curve 064 .getAzimuth(), distance); 065 newPath.lineTo(c.getLongitude(), c.getLatitude()); 066 distance += maxDistanceMeters; 067 } 068 newPath.lineTo(point.x, point.y); 069 070 // Append the new path to the existing path 071 path.append(newPath, true); 072 toPoints.add(point); 073 074 } 075 076 public void lineToLatLong(double longitudeDegrees, double latitudeDegrees) { 077 lineTo(new GeoPoint(longitudeDegrees, latitudeDegrees)); 078 } 079 080 public void arcTo(GeoPoint pivot, double widthMeters, double heightMeters, double leftAzimuthDegrees, 081 double rightAzimuthDegrees) { 082 GeneralPath newPath = new GeneralPath(); 083 Arc2D arc; 084 085 if (leftAzimuthDegrees > rightAzimuthDegrees) { 086 arc = new Arc2D(-widthMeters / 2, -heightMeters / 2, widthMeters, heightMeters, 087 leftAzimuthDegrees - 90, Math.abs((360 - leftAzimuthDegrees) + rightAzimuthDegrees), Arc2D.OPEN); 088 } else { 089 arc = new Arc2D(-widthMeters / 2, -heightMeters / 2, widthMeters, heightMeters, 090 leftAzimuthDegrees - 90, Math.abs(leftAzimuthDegrees - rightAzimuthDegrees), Arc2D.OPEN); 091 } 092 093 GeoPoint point = null; 094 if (pivot != null) { 095 FlatteningPathIterator it = new FlatteningPathIterator(arc.getPathIterator(null), flatnessDistanceMeters, limit); 096 while (!it.isDone()) { 097 // Add a point to the list for each segment flattened from the curve 098 double[] strokePoints = new double[6]; 099 int type = it.currentSegment(strokePoints); 100 double x = strokePoints[0]; 101 double y = strokePoints[1]; 102 double azimuth = Angle.toDegrees(Math.atan2(x, y)); 103 GlobalCoordinates coord = new GlobalCoordinates(pivot.getLatitude(), pivot.getLongitude()); 104 GlobalCoordinates c = geoCalc.calculateEndingGlobalCoordinates(REFERENCE_ELLIPSOID, coord, azimuth, 105 //new Point2D(0,0).distance(x, y)); 106 Point2D.distance(0, 0, x, y)); 107 switch (type) { 108 case PathIterator.SEG_MOVETO: 109 newPath.moveTo(c.getLongitude(), c.getLatitude()); 110 GeoPoint startPoint = new GeoPoint(c.getLongitude(), c.getLatitude()); 111 if (toPoints.size() > 0 && !startPoint.equals(toPoints.get(toPoints.size() - 1))) { 112 lineTo(startPoint); 113 } 114 break; 115 case PathIterator.SEG_LINETO: 116 newPath.lineTo(c.getLongitude(), c.getLatitude()); 117 point = new GeoPoint(c.getLongitude(), c.getLatitude()); 118 break; 119 } 120 it.next(); 121 } 122 } 123 124 path.append(newPath, true); 125 toPoints.add(point); 126 } 127 128 public ArrayList<GeoPoint> getToPoints() { 129 return toPoints; 130 } 131 132 public void closePath() { 133 134 135 if (toPoints.size() > 0 && !toPoints.get(0).equals(toPoints.get(toPoints.size() - 1))) { 136 lineTo(toPoints.get(0)); 137 } 138 } 139 140// @Override 141// public boolean contains(Point2D p) { 142// return path.contains(p); 143// } 144// 145// @Override 146// public boolean contains(Rectangle2D r) { 147// return path.contains(r); 148// } 149// 150// @Override 151// public boolean contains(double x, double y) { 152// return path.contains(x, y); 153// } 154// 155// @Override 156// public boolean contains(double x, double y, double w, double h) { 157// return contains(x, y, w, h); 158// } 159// 160// @Override 161// public Rectangle getBounds() { 162// return path.getBounds(); 163// } 164// 165// @Override 166// public Rectangle2D getBounds2D() { 167// return path.getBounds2D(); 168// } 169 170// @Override 171 public PathIterator getPathIterator(AffineTransform at) { 172 return path.getPathIterator(at); 173 } 174 175// @Override 176// public PathIterator getPathIterator(AffineTransform at, double flatness) { 177// return path.getPathIterator(at, flatness); 178// } 179// 180// @Override 181// public boolean intersects(Rectangle2D r) { 182// return path.intersects(r); 183// } 184// 185// @Override 186// public boolean intersects(double x, double y, double w, double h) { 187// return path.intersects(x, y, w, h); 188// } 189 190 @Override 191 public String toString() { 192 return toPoints.toString(); 193 } 194 195 protected GlobalCoordinates toGlobalCoord(GeoPoint point) { 196 return new GlobalCoordinates(point.getLatitude(), point.getLongitude()); 197 } 198}