2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
7 package gov
.nasa
.worldwind
.geom
;
9 import com
.sun
.opengl
.util
.*;
10 import gov
.nasa
.worldwind
.*;
12 import javax
.media
.opengl
.*;
16 import java
.util
.List
;
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()
62 public void setColor(Color color
)
66 String msg
= WorldWind
.retrieveErrMsg("nullValue.ColorIsNull");
67 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, msg
);
68 throw new IllegalArgumentException(msg
);
74 public int getAntiAliasHint()
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()
96 public void setFilled(boolean 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)
181 double[] refCenter
= new double[3];
182 if (this.followGreatCircles
)
183 this.vertices
= this.makeGreatCircleVertices(dc
, this.positions
, refCenter
);
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);
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());
220 refCenter
[0] = avgX
/ (double) n
;
221 refCenter
[1] = avgY
/ (double) n
;
222 refCenter
[2] = avgZ
/ (double) n
;
227 protected DoubleBuffer
makeGreatCircleVertices(DrawContext dc
, List
<Position
> posList
, double[] refCenter
)
229 if (posList
.size() < 1)
232 int size
= posList
.size() + (this.numEdgeIntervals
- 1) * (posList
.size() - 1);
233 DoubleBuffer verts
= BufferUtil
.newDoubleBuffer(size
* 3);
240 Iterator
<Position
> iter
= posList
.iterator();
241 Position pos
= iter
.next();
242 Point pt
= dc
.getGlobe().computePointFromPosition(pos
.getLatitude(), pos
.getLongitude(), pos
.getElevation());
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());
268 pt
= dc
.getGlobe().computePointFromPosition(posNext
.getLatitude(), posNext
.getLongitude(),
270 verts
.put(pt
.x()).put(pt
.y()).put(pt
.z());
279 refCenter
[0] = avgX
/ (double) n
;
280 refCenter
[1] = avgY
/ (double) n
;
281 refCenter
[2] = avgZ
/ (double) n
;
286 public void render(DrawContext dc
)
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
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
;
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
;
340 primType
= GL
.GL_POLYGON
;
341 gl
.glDrawArrays(primType
, 0, this.vertices
.capacity() / 3);
345 gl
.glPopClientAttrib();
347 dc
.getView().popReferenceCenter(dc
);