Worldwind public release 0.2
[worldwind-tracker.git] / gov / nasa / worldwind / geom / Polyline.java
blobd8827193f3478014bf8249f42e340bce970fc5ad
1 /*
2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
5 All Rights Reserved.
6 */
7 package gov.nasa.worldwind.geom;
9 import com.sun.opengl.util.*;
10 import gov.nasa.worldwind.*;
12 import javax.media.opengl.*;
13 import java.awt.*;
14 import java.nio.*;
15 import java.util.*;
16 import java.util.List;
18 /**
19 * @author tag
20 * @version $Id: Polyline.java 1787 2007-05-08 17:11:30Z dcollins $
22 public class Polyline implements Renderable
24 private ArrayList<Position> positions;
25 private Point referenceCenter;
26 private DoubleBuffer vertices;
27 private int antiAliasHint = GL.GL_FASTEST;
28 private Color color = Color.WHITE;
29 private boolean filled = false; // makes it a polygon
30 private boolean followGreatCircles = true;
31 private int numEdgeIntervals = 10;
33 public Polyline(Iterable<Position> positions)
35 if (positions == null)
37 String msg = WorldWind.retrieveErrMsg("nullValue.PositionsListIsNull");
38 WorldWind.logger().log(java.util.logging.Level.FINE, msg);
39 throw new IllegalArgumentException(msg);
42 this.setPositions(positions);
45 public Polyline(Iterable<LatLon> positions, double elevation)
47 if (positions == null)
49 String msg = WorldWind.retrieveErrMsg("nullValue.PositionsListIsNull");
50 WorldWind.logger().log(java.util.logging.Level.FINE, msg);
51 throw new IllegalArgumentException(msg);
54 this.setPositions(positions, elevation);
57 public Color getColor()
59 return color;
62 public void setColor(Color color)
64 if (color == null)
66 String msg = WorldWind.retrieveErrMsg("nullValue.ColorIsNull");
67 WorldWind.logger().log(java.util.logging.Level.FINE, msg);
68 throw new IllegalArgumentException(msg);
71 this.color = color;
74 public int getAntiAliasHint()
76 return antiAliasHint;
79 public void setAntiAliasHint(int hint)
81 if (!(hint == GL.GL_DONT_CARE || hint == GL.GL_FASTEST || hint == GL.GL_NICEST))
83 String msg = WorldWind.retrieveErrMsg("generic.InvalidHint");
84 WorldWind.logger().log(java.util.logging.Level.FINE, msg);
85 throw new IllegalArgumentException(msg);
88 this.antiAliasHint = hint;
91 public boolean isFilled()
93 return filled;
96 public void setFilled(boolean filled)
98 this.filled = filled;
101 public boolean isFollowGreatCircles()
103 return followGreatCircles;
106 public void setFollowGreatCircles(boolean followGreatCircles)
108 this.followGreatCircles = followGreatCircles;
111 public int getNumEdgeIntervals()
113 return numEdgeIntervals;
116 public void setNumEdgeIntervals(int numEdgeIntervals)
118 this.numEdgeIntervals = numEdgeIntervals;
121 public void setPositions(Iterable<Position> inPositions)
123 if (inPositions == null)
125 String msg = WorldWind.retrieveErrMsg("nullValue.PositionsListIsNull");
126 WorldWind.logger().log(java.util.logging.Level.FINE, msg);
127 throw new IllegalArgumentException(msg);
130 this.positions = new ArrayList<Position>();
131 for (Position position : inPositions)
133 this.positions.add(position);
136 if ((this.filled && this.positions.size() < 3) || (!this.filled && this.positions.size() < 2))
138 String msg = WorldWind.retrieveErrMsg("generic.InsufficientPositions");
139 WorldWind.logger().log(java.util.logging.Level.FINE, msg);
140 throw new IllegalArgumentException(msg);
143 this.vertices = null;
146 public void setPositions(Iterable<LatLon> inPositions, double elevation)
148 if (inPositions == null)
150 String msg = WorldWind.retrieveErrMsg("nullValue.PositionsListIsNull");
151 WorldWind.logger().log(java.util.logging.Level.FINE, msg);
152 throw new IllegalArgumentException(msg);
155 this.positions = new ArrayList<Position>();
156 for (LatLon position : inPositions)
158 this.positions.add(new Position(position.getLatitude(), position.getLongitude(), elevation));
161 if (this.positions.size() < 2 || (this.filled && this.positions.size() < 3))
163 String msg = WorldWind.retrieveErrMsg("generic.InsufficientPositions");
164 WorldWind.logger().log(java.util.logging.Level.FINE, msg);
165 throw new IllegalArgumentException(msg);
168 this.vertices = null;
171 public Iterable<Position> getPositions()
173 return this.positions;
176 private void intializeGeometry(DrawContext dc)
178 if (this.positions.size() < 2)
179 return;
181 double[] refCenter = new double[3];
182 if (this.followGreatCircles)
183 this.vertices = this.makeGreatCircleVertices(dc, this.positions, refCenter);
184 else
185 this.vertices = makeVertices(dc, this.positions, refCenter);
186 this.referenceCenter = new Point(refCenter[0], refCenter[1], refCenter[2]);
188 double avgX = this.referenceCenter.getX();
189 double avgY = this.referenceCenter.getY();
190 double avgZ = this.referenceCenter.getZ();
192 this.vertices.rewind();
193 for (int i = 0; i < this.vertices.limit(); i += 3)
195 this.vertices.put(i, this.vertices.get(i) - avgX);
196 this.vertices.put(i + 1, this.vertices.get(i + 1) - avgY);
197 this.vertices.put(i + 2, this.vertices.get(i + 2) - avgZ);
201 protected DoubleBuffer makeVertices(DrawContext dc, List<Position> posList, double[] refCenter)
203 DoubleBuffer verts = BufferUtil.newDoubleBuffer(posList.size() * 3);
205 double avgX = 0;
206 double avgY = 0;
207 double avgZ = 0;
209 int n = 0;
210 for (Position p : posList)
212 Point pt = dc.getGlobe().computePointFromPosition(p.getLatitude(), p.getLongitude(), p.getElevation());
213 verts.put(pt.x()).put(pt.y()).put(pt.z());
214 avgX += pt.x();
215 avgY += pt.y();
216 avgZ += pt.z();
217 ++n;
220 refCenter[0] = avgX / (double) n;
221 refCenter[1] = avgY / (double) n;
222 refCenter[2] = avgZ / (double) n;
224 return verts;
227 protected DoubleBuffer makeGreatCircleVertices(DrawContext dc, List<Position> posList, double[] refCenter)
229 if (posList.size() < 1)
230 return null;
232 int size = posList.size() + (this.numEdgeIntervals - 1) * (posList.size() - 1);
233 DoubleBuffer verts = BufferUtil.newDoubleBuffer(size * 3);
235 double avgX = 0;
236 double avgY = 0;
237 double avgZ = 0;
238 int n = 0;
240 Iterator<Position> iter = posList.iterator();
241 Position pos = iter.next();
242 Point pt = dc.getGlobe().computePointFromPosition(pos.getLatitude(), pos.getLongitude(), pos.getElevation());
243 verts.put(pt.x());
244 verts.put(pt.y());
245 verts.put(pt.z());
246 avgX += pt.x();
247 avgY += pt.y();
248 avgZ += pt.z();
249 ++n;
251 double delta = 1d / this.numEdgeIntervals;
252 while (iter.hasNext())
254 Position posNext = iter.next();
255 for (int i = 1; i < numEdgeIntervals; i++)
257 LatLon ll = LatLon.interpolate(i * delta, new LatLon(pos.getLatitude(), pos.getLongitude()),
258 new LatLon(posNext.getLatitude(), posNext.getLongitude()));
259 double elevation = (i * delta) * pos.getElevation() + (1d - i * delta) * posNext.getElevation();
260 pt = dc.getGlobe().computePointFromPosition(ll.getLatitude(), ll.getLongitude(), elevation);
261 verts.put(pt.x()).put(pt.y()).put(pt.z());
262 avgX += pt.x();
263 avgY += pt.y();
264 avgZ += pt.z();
265 ++n;
268 pt = dc.getGlobe().computePointFromPosition(posNext.getLatitude(), posNext.getLongitude(),
269 pos.getElevation());
270 verts.put(pt.x()).put(pt.y()).put(pt.z());
271 avgX += pt.x();
272 avgY += pt.y();
273 avgZ += pt.z();
274 ++n;
276 pos = posNext;
279 refCenter[0] = avgX / (double) n;
280 refCenter[1] = avgY / (double) n;
281 refCenter[2] = avgZ / (double) n;
283 return verts;
286 public void render(DrawContext dc)
288 if (dc == null)
290 String message = WorldWind.retrieveErrMsg("nullValue.DrawContextIsNull");
291 WorldWind.logger().log(java.util.logging.Level.FINE, message);
292 throw new IllegalStateException(message);
295 if (this.vertices == null)
297 this.intializeGeometry(dc);
299 if (this.vertices == null)
300 return; // TODO: log a warning
303 GL gl = dc.getGL();
305 int attrBits = GL.GL_HINT_BIT | GL.GL_CURRENT_BIT;
306 if (!dc.isPickingMode())
308 attrBits += GL.GL_CURRENT_BIT;
309 if (this.color.getAlpha() != 255)
310 attrBits += GL.GL_COLOR_BUFFER_BIT;
313 gl.glPushAttrib(attrBits);
314 gl.glPushClientAttrib(GL.GL_CLIENT_VERTEX_ARRAY_BIT);
315 dc.getView().pushReferenceCenter(dc, this.referenceCenter);
319 if (!dc.isPickingMode())
321 if (this.color.getAlpha() != 255)
323 gl.glEnable(GL.GL_BLEND);
324 gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
326 dc.getGL().glColor4ub((byte) this.color.getRed(), (byte) this.color.getGreen(),
327 (byte) this.color.getBlue(), (byte) this.color.getAlpha());
330 int hintAttr = GL.GL_LINE_SMOOTH_HINT;
331 if (this.filled)
332 hintAttr = GL.GL_POLYGON_SMOOTH_HINT;
333 gl.glHint(hintAttr, this.antiAliasHint);
335 gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
336 gl.glVertexPointer(3, GL.GL_DOUBLE, 0, this.vertices.rewind());
338 int primType = GL.GL_LINE_STRIP;
339 if (this.filled)
340 primType = GL.GL_POLYGON;
341 gl.glDrawArrays(primType, 0, this.vertices.capacity() / 3);
343 finally
345 gl.glPopClientAttrib();
346 gl.glPopAttrib();
347 dc.getView().popReferenceCenter(dc);