001/*
002 * To change this license header, choose License Headers in Project Properties.
003 * To change this template file, choose Tools | Templates
004 * and open the template in the editor.
005 */
006package sec.geo.shape;
007
008import sec.geo.GeoEllipse;
009import armyc2.c2sd.JavaTacticalRenderer.mdlGeodesic;
010import armyc2.c2sd.JavaLineArray.POINT2;
011import java.util.ArrayList;
012import armyc2.c2sd.JavaLineArray.ref;
013import sec.geo.GeoPoint;
014import sec.geo.ShapeObject;
015import sec.geo.kml.KmlOptions;
016import armyc2.c2sd.graphics2d.*;
017
018/**
019 *
020 * @author Michael Deutch
021 */
022public class Ellipse {
023    protected GeoPoint pivot;
024    protected double radiusMeters;
025    private ShapeObject shape;
026    protected double maxDistanceMeters;
027    protected double flatnessDistanceMeters;
028    protected KmlOptions.AltitudeMode altitudeMode;
029    private double minAltitudeMeters;
030    private double maxAltitudeMeters;
031    protected int limit;
032        private double _semiMajor=0;
033        private double _semiMinor=0;
034        private double _rotation=0;
035        public Ellipse(double semiMajor,double semiMinor,double rotation)
036        {
037            _semiMajor=semiMajor;
038            _semiMinor=semiMinor;
039            _rotation=rotation;
040            limit=4;
041            flatnessDistanceMeters=2;
042            maxDistanceMeters=200000;
043        }
044        //@Override
045        public ShapeObject createShape() {
046                //GeoEllipse e = new GeoEllipse(pivot, radiusMeters * 2, radiusMeters * 2, maxDistanceMeters,
047                //              flatnessDistanceMeters, limit);
048                GeoEllipse e = new GeoEllipse(pivot, _semiMajor * 2, _semiMinor * 2, maxDistanceMeters,
049                                flatnessDistanceMeters, limit);
050                
051                float[] coords = new float[2];
052                int type=0;
053                POINT2 pt0=new POINT2(pivot.x,pivot.y),pt=null;
054                POINT2 pt1=null;
055                double R=0;
056                ref<double[]> a12 = new ref(), a21 = new ref();
057                double x=0,y=0,x1=0,y1=0;
058                //test arbitray rotation angle                
059                double rotation=_rotation;
060                //navigation is clockwise from 0. 0 is true north
061                rotation=90-rotation;
062                if(rotation == 0 || _semiMajor==_semiMinor)
063                    return new ShapeObject(e);                
064                ArrayList<POINT2>pts=new ArrayList();
065                for (PathIterator i = e.getPathIterator(null); !i.isDone(); i.next()) {
066                    type = i.currentSegment(coords);
067                    pt1=new POINT2(coords[0],coords[1]);
068                    R=mdlGeodesic.geodesic_distance(pt0, pt1, a12, a21);
069                    //x=R*Math.cos(a12.value[0]*Math.PI/180d);
070                    //y=R*Math.sin(a12.value[0]*Math.PI/180d);                  
071                    //rotate the points
072                    //x1=x*Math.cos(rotation*Math.PI/180d)-y*Math.sin(rotation*Math.PI/180d);
073                    //y1=x*Math.sin(rotation*Math.PI/180d)+y*Math.cos(rotation*Math.PI/180d);
074                    pt=mdlGeodesic.geodesic_coordinate(pt0, R, a12.value[0]-rotation);
075                    pts.add(pt);                    
076                }
077                //clear the path
078                GeneralPath path=e.getPath();
079                //path.reset();
080                path.getPath().reset();
081                //rebuild the path with the rotated points
082                for(int j=0;j<pts.size();j++)
083                {
084                    x=pts.get(j).x;
085                    y=pts.get(j).y;
086                    if(j==0)
087                        path.moveTo(x, y);
088                    else
089                        path.lineTo(x, y);
090                }
091                return new ShapeObject(e);
092        } 
093        public ArrayList<GeoPoint>getEllipsePoints()
094        {
095                GeoEllipse e = new GeoEllipse(pivot, _semiMajor * 2, _semiMinor * 2, maxDistanceMeters,
096                                flatnessDistanceMeters, limit);
097                
098                float[] coords = new float[2];
099                int type=0;
100                POINT2 pt0=new POINT2(pivot.x,pivot.y),pt=null;
101                POINT2 pt1=null;
102                double R=0;
103                ref<double[]> a12 = new ref(), a21 = new ref();
104                double x=0,y=0,x1=0,y1=0;
105                double rotation=_rotation;
106                //navigation is clockwise from 0. 0 is true north
107                rotation=90-rotation;
108                ArrayList<GeoPoint>pts=new ArrayList();
109                for (PathIterator i = e.getPathIterator(null); !i.isDone(); i.next()) {
110                    type = i.currentSegment(coords);
111                    pt1=new POINT2(coords[0],coords[1]);
112                    R=mdlGeodesic.geodesic_distance(pt0, pt1, a12, a21);
113                    if(!(_semiMajor == _semiMinor))
114                        pt=mdlGeodesic.geodesic_coordinate(pt0, R, a12.value[0]-rotation);
115                    else
116                        pt=pt1;
117                    pts.add(new GeoPoint(pt.x,pt.y));                    
118                }
119                //clear the path
120                GeneralPath path=e.getPath();
121                path.getPath().reset();
122                //rebuild the path with the rotated points
123                for(int j=0;j<pts.size();j++)
124                {
125                    x=pts.get(j).x;
126                    y=pts.get(j).y;
127                    if(j==0)
128                        path.moveTo(x, y);
129                    else
130                        path.lineTo(x, y);
131                }
132                return pts;            
133        }
134    protected void shapeChanged() {
135        shape = null;
136    }
137
138    public double getMinAltitude() {
139        return minAltitudeMeters;
140    }
141
142    public void setMinAltitude(double minAltitudeMeters) {
143        this.minAltitudeMeters = minAltitudeMeters;
144        shapeChanged();
145    }
146
147    public double getMaxAltitude() {
148        return maxAltitudeMeters;
149    }
150
151    public void setMaxAltitude(double maxAltitudeMeters) {
152        this.maxAltitudeMeters = maxAltitudeMeters;
153        shapeChanged();
154    }
155
156    public void setMaxDistance(double maxDistanceMeters) {
157        this.maxDistanceMeters = maxDistanceMeters;
158        shapeChanged();
159    }
160
161    public void setFlatness(double flatnessDistanceMeters) {
162        this.flatnessDistanceMeters = flatnessDistanceMeters;
163        shapeChanged();
164    }
165
166    public void setLimit(int limit) {
167        this.limit = limit;
168        shapeChanged();
169    }
170    public void setPivot(GeoPoint pvt) {
171        this.pivot = pvt;
172        shapeChanged();
173    }
174
175    public KmlOptions.AltitudeMode getAltitudeMode() {
176        return altitudeMode;
177    }
178
179    public void setAltitudeMode(KmlOptions.AltitudeMode altitudeMode) {
180        this.altitudeMode = altitudeMode;
181    }
182        
183}