Update to Worldwind release 0.4.1
[worldwind-tracker.git] / gov / nasa / worldwind / render / SurfacePolygon.java
blobc3652d6c5343f69922bbf592188a7c35cea922bc
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.render;
9 import gov.nasa.worldwind.geom.*;
10 import gov.nasa.worldwind.globes.Globe;
12 import java.awt.*;
13 import java.awt.geom.*;
14 import java.awt.image.*;
15 import java.util.Iterator;
17 /**
18 * @author tag
19 * @version $Id: SurfacePolygon.java 2543 2007-08-14 03:16:40Z tgaskins $
21 public class SurfacePolygon extends SurfaceShape
24 /**
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);
36 /**
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);
53 /**
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
74 double lonOffset = 0;
75 if (sector.getMaxLongitude().getDegrees() == 180 && sector.getDeltaLonDegrees() < 180)
76 lonOffset = -180;
77 if (sector.getMinLongitude().getDegrees() == -180 && sector.getDeltaLonDegrees() < 180)
78 lonOffset = 180;
80 GeneralPath path = new GeneralPath();
82 Iterator<LatLon> positions = this.getPositions().iterator();
83 if (!positions.hasNext())
84 return image;
86 // Start position
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())
95 // Next position
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++)
104 // In between steps
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);
117 // Next
119 pos = posNext;
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);
128 // Draw interior
129 if (this.isDrawInterior())
131 g2.setPaint(this.getPaint());
132 g2.fill(path);
134 // Draw border
135 if (this.isDrawBorder())
137 g2.setPaint(this.getBorderColor());
138 g2.setStroke(this.getStroke());
139 g2.draw(path);
142 return image;
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)
156 int directionOffset;
157 directionOffset = sector.getMaxLongitude().degrees - pos.getLongitude().getDegrees() > 180 ?
158 360 : 0;
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);