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 GeoArc /*extends GeoPath*/ { 013 014 protected static final Ellipsoid REFERENCE_ELLIPSOID = Ellipsoid.WGS84; 015 016 private GeneralPath path = null; 017 private ArrayList<GeoPoint> toPoints; 018 private double maxDistanceMeters; 019 private double flatnessDistanceMeters; 020 private int limit; 021 022 protected final GeodeticCalculator geoCalc; 023 024 public GeoArc(GeoPoint pivot, double widthMeters, double heightMeters, double leftAzimuth, double rightAzimuth, 025 double maxDistanceMeters, double flatnessDistanceMeters, int limit) { 026 //super(maxDistanceMeters, flatnessDistanceMeters, limit); 027 path = new GeneralPath(); 028 toPoints = new ArrayList<GeoPoint>(); 029 geoCalc = new GeodeticCalculator(); 030 this.maxDistanceMeters = maxDistanceMeters; 031 this.flatnessDistanceMeters = flatnessDistanceMeters; 032 this.limit = limit; 033 034 moveTo(pivot); 035 arcTo(pivot, widthMeters, heightMeters, leftAzimuth, rightAzimuth); 036 closePath(); 037 } 038 039 public final void moveTo(GeoPoint point) { 040 path.moveTo(point.x, point.y); 041 toPoints.add(point); 042 } 043 044 public void moveToLatLong(double longitudeDegrees, double latitudeDegrees) { 045 moveTo(new GeoPoint(longitudeDegrees, latitudeDegrees)); 046 } 047 048 public void lineTo(GeoPoint point) { 049 GeneralPath newPath = new GeneralPath(); 050 051 // Move to the initial point 052 GeoPoint lastPoint = new GeoPoint(); 053 if (toPoints.size() > 0) { 054 lastPoint = toPoints.get(toPoints.size() - 1); 055 newPath.moveTo(lastPoint.x, lastPoint.y); 056 } 057 058 // Calculate the curve to the new point 059 GlobalCoordinates start = toGlobalCoord(lastPoint); 060 GlobalCoordinates end = toGlobalCoord(point); 061 GeodeticCurve curve = geoCalc.calculateGeodeticCurve(REFERENCE_ELLIPSOID, start, end); 062 063 // Generate points along the curve, adding them to the new path 064 double distance = maxDistanceMeters; 065 while (distance < curve.getEllipsoidalDistance()) { 066 GlobalCoordinates c = geoCalc.calculateEndingGlobalCoordinates(REFERENCE_ELLIPSOID, start, curve 067 .getAzimuth(), distance); 068 newPath.lineTo(c.getLongitude(), c.getLatitude()); 069 distance += maxDistanceMeters; 070 } 071 newPath.lineTo(point.x, point.y); 072 073 // Append the new path to the existing path 074 path.append(newPath, true); 075 toPoints.add(point); 076 077 } 078 079 public void lineToLatLong(double longitudeDegrees, double latitudeDegrees) { 080 lineTo(new GeoPoint(longitudeDegrees, latitudeDegrees)); 081 } 082 083 public final void arcTo(GeoPoint pivot, double widthMeters, double heightMeters, double leftAzimuthDegrees, 084 double rightAzimuthDegrees) { 085 GeneralPath newPath = new GeneralPath(); 086 Arc2D arc; 087 088 if (leftAzimuthDegrees > rightAzimuthDegrees) { 089 arc = new Arc2D(-widthMeters / 2, -heightMeters / 2, widthMeters, heightMeters, 090 leftAzimuthDegrees - 90, Math.abs((360 - leftAzimuthDegrees) + rightAzimuthDegrees), Arc2D.OPEN); 091 } else { 092 arc = new Arc2D(-widthMeters / 2, -heightMeters / 2, widthMeters, heightMeters, 093 leftAzimuthDegrees - 90, Math.abs(leftAzimuthDegrees - rightAzimuthDegrees), Arc2D.OPEN); 094 } 095 096 GeoPoint point = null; 097 if (pivot != null) { 098 FlatteningPathIterator it = new FlatteningPathIterator(arc.getPathIterator(null), flatnessDistanceMeters, limit); 099 while (!it.isDone()) { 100 // Add a point to the list for each segment flattened from the curve 101 double[] strokePoints = new double[6]; 102 int type = it.currentSegment(strokePoints); 103 double x = strokePoints[0]; 104 double y = strokePoints[1]; 105 double azimuth = Angle.toDegrees(Math.atan2(x, y)); 106 GlobalCoordinates coord = new GlobalCoordinates(pivot.getLatitude(), pivot.getLongitude()); 107 GlobalCoordinates c = geoCalc.calculateEndingGlobalCoordinates(REFERENCE_ELLIPSOID, coord, azimuth, 108 //new Point2D.Double(0,0).distance(x, y)); 109 Point2D.distance(0, 0, x, y)); 110 switch (type) { 111 case PathIterator.SEG_MOVETO: 112 newPath.moveTo(c.getLongitude(), c.getLatitude()); 113 GeoPoint startPoint = new GeoPoint(c.getLongitude(), c.getLatitude()); 114 if (toPoints.size() > 0 && !startPoint.equals(toPoints.get(toPoints.size() - 1))) { 115 lineTo(startPoint); 116 } 117 break; 118 case PathIterator.SEG_LINETO: 119 newPath.lineTo(c.getLongitude(), c.getLatitude()); 120 point = new GeoPoint(c.getLongitude(), c.getLatitude()); 121 break; 122 } 123 it.next(); 124 } 125 } 126 127 path.append(newPath, true); 128 toPoints.add(point); 129 } 130 131 public ArrayList<GeoPoint> getToPoints() { 132 return toPoints; 133 } 134 135 public final void closePath() { 136 137 if(toPoints.get(0)!=null && toPoints.get(toPoints.size() - 1) != null) 138 if (toPoints.size() > 0 && !toPoints.get(0).equals(toPoints.get(toPoints.size() - 1))) { 139 lineTo(toPoints.get(0)); 140 } 141 } 142 143 public PathIterator getPathIterator(AffineTransform at) { 144 return path.getPathIterator(at); 145 } 146 147 public String toString() { 148 return toPoints.toString(); 149 } 150 151 protected GlobalCoordinates toGlobalCoord(GeoPoint point) { 152 return new GlobalCoordinates(point.getLatitude(), point.getLongitude()); 153 } 154}