001package sec.geo;
002import armyc2.c2sd.graphics2d.*;
003import java.util.ArrayList;
004import armyc2.c2sd.JavaLineArray.POINT2;
005import org.gavaghan.geodesy.Ellipsoid;
006import org.gavaghan.geodesy.GeodeticCalculator;
007
008import org.gavaghan.geodesy.GeodeticCurve;
009import org.gavaghan.geodesy.GlobalCoordinates;
010
011public class GeoBlock /*extends GeoPath*/ {
012        protected static final Ellipsoid REFERENCE_ELLIPSOID = Ellipsoid.WGS84;
013        
014        private GeneralPath path;
015        private ArrayList<GeoPoint> toPoints;
016        private double maxDistanceMeters;
017        //private double flatnessDistanceMeters;
018        //private int limit;
019        
020        protected final GeodeticCalculator geoCalc;
021        public GeoBlock(GeoPoint p1, GeoPoint p2, double widthMeters, double maxDistanceMeters,
022                        double flatnessDistanceMeters, int limit) {
023                //super(maxDistanceMeters, flatnessDistanceMeters, limit);
024                path = new GeneralPath();
025                toPoints = new ArrayList<GeoPoint>();
026                geoCalc = new GeodeticCalculator();
027                this.maxDistanceMeters = maxDistanceMeters;
028                //this.flatnessDistanceMeters = flatnessDistanceMeters;
029                //this.limit = limit;
030                
031                GlobalCoordinates c1 = toGlobalCoord(p1);
032                GlobalCoordinates c2 = toGlobalCoord(p2);                                
033                GeodeticCurve curve = geoCalc.calculateGeodeticCurve(REFERENCE_ELLIPSOID, c1, c2);                
034                double a1 = curve.getAzimuth();
035                double a2 = curve.getReverseAzimuth();             
036                double radius = widthMeters / 2;                
037                 //diagnostic to prevent error in calculate global coords if points are identical
038                if(p1.x==p2.x && p1.y==p2.y)
039                    return;
040                //end section
041                GlobalCoordinates c = geoCalc.calculateEndingGlobalCoordinates(REFERENCE_ELLIPSOID, c1, a1 - 90, radius);                
042                moveToLatLong(c.getLongitude(), c.getLatitude());
043                c = geoCalc.calculateEndingGlobalCoordinates(REFERENCE_ELLIPSOID, c2, a2 + 90, radius);                
044                lineToLatLong(c.getLongitude(), c.getLatitude());
045                c = geoCalc.calculateEndingGlobalCoordinates(REFERENCE_ELLIPSOID, c2, a2 - 90, radius);                
046                lineToLatLong(c.getLongitude(), c.getLatitude());
047                c = geoCalc.calculateEndingGlobalCoordinates(REFERENCE_ELLIPSOID, c1, a1 + 90, radius);                
048                lineToLatLong(c.getLongitude(), c.getLatitude());
049                closePath();
050        }
051        public void moveTo(GeoPoint point) {
052                path.moveTo(point.x, point.y);
053                toPoints.add(point);
054        }
055        
056        public final void moveToLatLong(double longitudeDegrees, double latitudeDegrees) {
057                moveTo(new GeoPoint(longitudeDegrees, latitudeDegrees));
058        }
059        public void simplify()
060        {
061            PathIterator pi=path.getPathIterator(null);
062            ArrayList<POINT2>pts=pi.getPoints();
063            ArrayList<POINT2>newPts=new ArrayList();
064            int j=0;
065            int style=-1,lastStyle=-1,nextstyle=-1;
066            POINT2 currentPt=null, lastPt=null;
067            int n=pts.size();
068            //for(j=0;j<pts.size();j++)
069            for(j=0;j<n;j++)
070            {
071                style=pts.get(j).style;
072                currentPt=pts.get(j);
073                if(j>0)
074                {
075                    lastStyle=pts.get(j-1).style;                
076                    lastPt=pts.get(j-1);
077                }
078                if(lastStyle==PathIterator.SEG_LINETO && style==PathIterator.SEG_MOVETO)
079                {
080                    //if the last move as lineto and the current move is moveto then
081                    //don't add the current point if the last point is equal
082                    if(currentPt.x==lastPt.x && currentPt.y==lastPt.y)
083                        continue;
084                }
085                newPts.add(currentPt);    
086            }
087            pi.setPathIterator(newPts);
088        }
089        public void lineTo(GeoPoint point) {
090                GeneralPath newPath = new GeneralPath();
091                
092                // Move to the initial point
093                GeoPoint lastPoint = new GeoPoint();
094                if (toPoints.size() > 0) {
095                        lastPoint = toPoints.get(toPoints.size() - 1);
096                        newPath.moveTo(lastPoint.x, lastPoint.y);
097                }
098                
099                // Calculate the curve to the new point
100                GlobalCoordinates start = toGlobalCoord(lastPoint);
101                GlobalCoordinates end = toGlobalCoord(point);
102                GeodeticCurve curve = geoCalc.calculateGeodeticCurve(REFERENCE_ELLIPSOID, start, end);
103                
104                // Generate points along the curve, adding them to the new path
105                double distance = maxDistanceMeters;
106                while (distance < curve.getEllipsoidalDistance()) {
107                        GlobalCoordinates c = geoCalc.calculateEndingGlobalCoordinates(REFERENCE_ELLIPSOID, start, curve
108                                        .getAzimuth(), distance);
109                        newPath.lineTo(c.getLongitude(), c.getLatitude());
110                        distance += maxDistanceMeters;
111                }
112                newPath.lineTo(point.x, point.y);
113                // Append the new path to the existing path
114                path.append(newPath, true);                
115                //path.lineTo(point.x, point.y);
116                toPoints.add(point);
117                simplify();
118                
119        }
120        
121        public final void lineToLatLong(double longitudeDegrees, double latitudeDegrees) {
122                lineTo(new GeoPoint(longitudeDegrees, latitudeDegrees));
123        }
124        
125        
126        public ArrayList<GeoPoint> getToPoints() {
127                return toPoints;
128        }
129        
130        public final void closePath() {
131            
132                
133                if (toPoints.size() > 0 && !toPoints.get(0).equals(toPoints.get(toPoints.size() - 1))) {                        
134                        lineTo(toPoints.get(0));                        
135                }
136        }
137        
138        
139//      @Override
140        public PathIterator getPathIterator(AffineTransform at) {
141                return path.getPathIterator(at);
142        }
143        
144        
145        @Override
146        public String toString() {
147            return toPoints.toString();
148        }
149        
150        protected final GlobalCoordinates toGlobalCoord(GeoPoint point) {
151                return new GlobalCoordinates(point.getLatitude(), point.getLongitude());
152        }
153}