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
.render
;
9 import gov
.nasa
.worldwind
.geom
.*;
10 import gov
.nasa
.worldwind
.globes
.Globe
;
13 import java
.awt
.geom
.*;
14 import java
.awt
.image
.*;
15 import java
.util
.Iterator
;
19 * @version $Id: SurfacePolygon.java 2543 2007-08-14 03:16:40Z tgaskins $
21 public class SurfacePolygon
extends SurfaceShape
25 * A Renderable polygon shape defined by a list of LatLon
27 * @param positions the list of LatLon positions that makes the polygon
28 * @param color the interior fill color
29 * @param borderColor the border color
31 public SurfacePolygon(Iterable
<LatLon
> positions
, Color color
, Color borderColor
)
33 super(positions
, color
, borderColor
, null);
37 * A Renderable polygon shape defined by a list of LatLon
39 * @param positions the list of LatLon positions that makes the polygon
41 public SurfacePolygon(Iterable
<LatLon
> positions
)
43 super(positions
, null, null, null);
46 public SurfacePolygon(Iterable
<LatLon
> positions
, Color color
, Color borderColor
, Dimension textureSize
)
48 super(positions
, color
, borderColor
, textureSize
);
51 private static final double TO_RADIANS
= (Math
.PI
/ 180);
54 * Draw all or part of the shape that intersects a given Sector into the given BufferedImage
56 protected final BufferedImage
drawShape(Globe globe
, Sector sector
, BufferedImage image
)
58 double rsw
= globe
.getRadiusAt(sector
.getMinLatitude(), sector
.getMinLongitude());
59 double rne
= globe
.getRadiusAt(sector
.getMaxLatitude(), sector
.getMaxLongitude());
60 double xsw
= rsw
* sector
.getMinLongitude().radians
;
61 double ysw
= rsw
* sector
.getMinLatitude().radians
;
62 double xne
= rne
* sector
.getMaxLongitude().radians
;
63 double yne
= rne
* sector
.getMaxLatitude().radians
;
64 double dy
= yne
- ysw
;
65 double dx
= xne
- xsw
;
67 // Note : WWJ-36 negate latScale to define path upside-down
68 // (will be drawn with a mirror transform - this gets paint patterns right)
69 double latScale
= dy
> 0 ?
-(image
.getHeight() - 1) / dy
: 0;
70 double lonScale
= dx
> 0 ?
(image
.getWidth() - 1) / dx
: 0;
72 // If we may cross +-180 degrees longitude, then offset
73 // all longitudes 180 degrees the other way
75 if (sector
.getMaxLongitude().getDegrees() == 180 && sector
.getDeltaLonDegrees() < 180)
77 if (sector
.getMinLongitude().getDegrees() == -180 && sector
.getDeltaLonDegrees() < 180)
80 GeneralPath path
= new GeneralPath();
82 Iterator
<LatLon
> positions
= this.getPositions().iterator();
83 if (!positions
.hasNext())
87 LatLon pos
= this.computeDrawLatLon(positions
.next(), sector
, lonOffset
);
88 double r
= globe
.getRadiusAt(pos
.getLatitude(), pos
.getLongitude());
89 double x
= lonScale
* (r
* pos
.getLongitude().radians
- r
* TO_RADIANS
* lonOffset
- xsw
);
90 double y
= latScale
* (r
* pos
.getLatitude().radians
- ysw
);
91 path
.moveTo((float) x
, (float) y
);
93 while (positions
.hasNext())
96 LatLon posNext
= this.computeDrawLatLon(positions
.next(), sector
, lonOffset
);
97 // Compute number of necessary steps
98 int numIntervals
= (int) Math
.max(1d
,
99 this.getNumEdgeIntervalsPerDegree() * LatLon
.sphericalDistance(pos
, posNext
).degrees
);
100 double delta
= 1d
/ numIntervals
;
101 // Draw segments to next position
102 for (int i
= 1; i
< numIntervals
; i
++)
105 LatLon p
= LatLon
.interpolate(i
* delta
, pos
, posNext
);
106 r
= globe
.getRadiusAt(p
.getLatitude(), p
.getLongitude());
107 x
= lonScale
* (r
* p
.getLongitude().radians
- r
* TO_RADIANS
* lonOffset
- xsw
);
108 y
= latScale
* (r
* p
.getLatitude().radians
- ysw
);
109 path
.lineTo((float) x
, (float) y
);
112 // Set the last point directly to avoid any round-off error in the iteration above.
113 r
= globe
.getRadiusAt(posNext
.getLatitude(), posNext
.getLongitude());
114 x
= lonScale
* (r
* posNext
.getLongitude().radians
- r
* TO_RADIANS
* lonOffset
- xsw
);
115 y
= latScale
* (r
* posNext
.getLatitude().radians
- ysw
);
116 path
.lineTo((float) x
, (float) y
);
122 Graphics2D g2
= image
.createGraphics();
123 // Set mirror Y transform
124 g2
.setTransform(AffineTransform
.getScaleInstance(1, -1));
125 // Set antiliasing hint
126 if (this.isAntiAlias())
127 g2
.setRenderingHint(RenderingHints
.KEY_ANTIALIASING
, RenderingHints
.VALUE_ANTIALIAS_ON
);
129 if (this.isDrawInterior())
131 g2
.setPaint(this.getPaint());
135 if (this.isDrawBorder())
137 g2
.setPaint(this.getBorderColor());
138 g2
.setStroke(this.getStroke());
146 * Returns the drawing LatLon relative to a given Sector and a longitude offset Can go beyond +-180 degrees
147 * longitude if the offset is zero
149 * @param pos the real LatLon
150 * @param sector the drawing Sector
151 * @param lonOffset the current longitude offset in degrees
152 * @return the appropiate drawing LatLon
154 private LatLon
computeDrawLatLon(LatLon pos
, Sector sector
, double lonOffset
)
157 directionOffset
= sector
.getMaxLongitude().degrees
- pos
.getLongitude().getDegrees() > 180 ?
159 directionOffset
= pos
.getLongitude().getDegrees() - sector
.getMinLongitude().getDegrees() > 180 ?
160 -360 : directionOffset
;
161 return LatLon
.fromDegrees(pos
.getLatitude().getDegrees(),
162 pos
.getLongitude().getDegrees() + directionOffset
+ lonOffset
);