Updated to worldwind release 20070817
[worldwind-tracker.git] / gov / nasa / worldwind / geom / Polyline.java
blob608c986aedba88ca482231bd5e48c3d3495f1f58
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 2233 2007-07-06 23:56:34Z tgaskins $
22 public class Polyline implements Renderable
24 private ArrayList<Position> positions;
25 private Vec4 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, 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 Vec4(refCenter[0], refCenter[1], refCenter[2]);
188 double avgX = this.referenceCenter.x;
189 double avgY = this.referenceCenter.y;
190 double avgZ = this.referenceCenter.z;
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 Vec4 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 Vec4 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 if (this.color.getAlpha() != 255)
309 attrBits |= GL.GL_COLOR_BUFFER_BIT;
312 gl.glPushAttrib(attrBits);
313 gl.glPushClientAttrib(GL.GL_CLIENT_VERTEX_ARRAY_BIT);
314 dc.getView().pushReferenceCenter(dc, this.referenceCenter);
318 if (!dc.isPickingMode())
320 if (this.color.getAlpha() != 255)
322 gl.glEnable(GL.GL_BLEND);
323 gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
325 dc.getGL().glColor4ub((byte) this.color.getRed(), (byte) this.color.getGreen(),
326 (byte) this.color.getBlue(), (byte) this.color.getAlpha());
329 int hintAttr = GL.GL_LINE_SMOOTH_HINT;
330 if (this.filled)
331 hintAttr = GL.GL_POLYGON_SMOOTH_HINT;
332 gl.glHint(hintAttr, this.antiAliasHint);
334 gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
335 gl.glVertexPointer(3, GL.GL_DOUBLE, 0, this.vertices.rewind());
337 int primType = GL.GL_LINE_STRIP;
338 if (this.filled)
339 primType = GL.GL_POLYGON;
340 gl.glDrawArrays(primType, 0, this.vertices.capacity() / 3);
342 finally
344 gl.glPopClientAttrib();
345 gl.glPopAttrib();
346 dc.getView().popReferenceCenter(dc);