Skip to content

Partial surface-ellipses #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/gov/nasa/worldwind/render/SurfaceCircle.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,25 @@ public SurfaceCircle(ShapeAttributes normalAttrs, LatLon center, double radius,
{
super(normalAttrs, center, radius, radius, Angle.ZERO, intervals);
}

/**
* Constructs a new surface circle with the specified normal (as opposed to highlight) attributes, the specified
* center location, radius (in meters), and initial number of geometry intervals. Modifying the attribute reference
* after calling this constructor causes this shape's appearance to change accordingly.
*
* @param normalAttrs the normal attributes. May be null, in which case default attributes are used.
* @param center the circle's center location.
* @param radius the circle's radius, in meters.
* @param intervals the initial number of intervals (or slices) defining the circle's geometry.
* @param theta the angle defining the start and end of the circle's geometry.
*
* @throws IllegalArgumentException if the center is null, if the radius is negative, or if the number of intervals
* is less than 8.
*/
public SurfaceCircle(ShapeAttributes normalAttrs, LatLon center, double radius, int intervals, Angle theta)
{
super(normalAttrs, center, radius, radius, Angle.ZERO, intervals, theta);
}

public double getRadius()
{
Expand Down
93 changes: 85 additions & 8 deletions src/gov/nasa/worldwind/render/SurfaceEllipse.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class SurfaceEllipse extends AbstractSurfaceShape
protected double majorRadius;
protected double minorRadius;
protected Angle heading = Angle.ZERO;
protected Angle theta = Angle.POS360;
private int intervals = DEFAULT_NUM_INTERVALS;

/**
Expand Down Expand Up @@ -252,6 +253,38 @@ public SurfaceEllipse(ShapeAttributes normalAttrs, LatLon center, double majorRa

this.intervals = intervals;
}

/**
* Constructs a new surface ellipse with the specified normal (as opposed to highlight) attributes, the specified
* center location, radii (in meters), heading clockwise from North, and initial number of geometry intervals.
* Modifying the attribute reference after calling this constructor causes this shape's appearance to change
* accordingly.
*
* @param normalAttrs the normal attributes. May be null, in which case default attributes are used.
* @param center the ellipse's center location.
* @param majorRadius the ellipse's major radius, in meters.
* @param minorRadius the ellipse's minor radius, in meters.
* @param heading the ellipse's heading, clockwise from North.
* @param intervals the initial number of intervals (or slices) defining the ellipse's geometry.
* @param theta the angle defining the start and end of the ellipse's geometry.
*
* @throws IllegalArgumentException if the center or heading are null, if either radii is negative, or if the number
* of intervals is less than 8.
*/
public SurfaceEllipse(ShapeAttributes normalAttrs, LatLon center, double majorRadius, double minorRadius,
Angle heading, int intervals, Angle theta)
{
this(normalAttrs, center, majorRadius, minorRadius, heading, intervals);

if (theta == null)
{
String message = Logging.getMessage("nullValue.ThetaIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}

this.theta = theta;
}

public LatLon getCenter()
{
Expand Down Expand Up @@ -348,6 +381,24 @@ public void setIntervals(int intervals)
this.intervals = intervals;
this.onShapeChanged();
}

public Angle getTheta()
{
return this.theta;
}

public void setTheta(Angle theta)
{
if (theta == null)
{
String message = Logging.getMessage("nullValue.ThetaIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}

this.theta = theta;
this.onShapeChanged();
}

/**
* {@inheritDoc}
Expand Down Expand Up @@ -408,27 +459,48 @@ protected List<LatLon> computeLocations(Globe globe, int intervals)

if (this.majorRadius == 0 && this.minorRadius == 0)
return null;

boolean closed = this.theta.equals(Angle.POS360);

int numLocations = 1 + Math.max(MIN_NUM_INTERVALS, intervals);
double da = (2 * Math.PI) / (numLocations - 1);
int numIntervals = Math.max(MIN_NUM_INTERVALS, intervals);
int numLocations = 1 + numIntervals;
double da = (this.theta.radians) / (numLocations - 1);
double globeRadius = globe.getRadiusAt(this.center.getLatitude(), this.center.getLongitude());

LatLon[] locations = new LatLon[numLocations];
List<LatLon> locations = new ArrayList<LatLon>(numLocations);

// If the ellipse is not closed, start drawing from the center-position.
if (!closed) {
locations.add(this.center);
}

for (int i = 0; i < numLocations; i++)
{
double angle = (i != numLocations - 1) ? i * da : 0;
double angle = 0.0;
// If the ellipse is closed, snap angle to 0-degrees on final location.
if (closed) {
angle = (i != numIntervals) ? i * da : 0;
} else {
angle = (i != numIntervals) ? i * da : this.theta.radians;
}

double xLength = this.majorRadius * Math.cos(angle);
double yLength = this.minorRadius * Math.sin(angle);
double distance = Math.sqrt(xLength * xLength + yLength * yLength);
// azimuth runs positive clockwise from north and through 360 degrees.

// azimuth runs positive clockwise from north and through theta degrees.
double azimuth = (Math.PI / 2.0) - (Math.acos(xLength / distance) * Math.signum(yLength)
- this.heading.radians);

locations[i] = LatLon.greatCircleEndPosition(this.center, azimuth, distance / globeRadius);
locations.add(LatLon.rhumbEndPosition(this.center, Angle.fromRadians(azimuth), Angle.fromRadians(distance / globeRadius)));
}

// If the ellipse is not closed, end at the center-position.
if (!closed) {
locations.add(this.center);
}

return Arrays.asList(locations);
return locations;
}

protected List<List<LatLon>> createGeometry(Globe globe, double edgeIntervalsPerDegree)
Expand Down Expand Up @@ -469,7 +541,7 @@ protected int computeNumEdgeIntervals(Globe globe, double edgeIntervalsPerDegree

int numPositions = 1 + Math.max(MIN_NUM_INTERVALS, intervals);
double radius = Math.max(this.majorRadius, this.minorRadius);
double da = (2 * Math.PI) / (numPositions - 1);
double da = (this.theta.radians) / (numPositions - 1);
Angle edgePathLength = Angle.fromRadians(da * radius / globe.getRadiusAt(this.center));

double edgeIntervals = WWMath.clamp(edgeIntervalsPerDegree * edgePathLength.degrees,
Expand All @@ -491,6 +563,7 @@ protected void doGetRestorableState(RestorableSupport rs, RestorableSupport.Stat
rs.addStateValueAsDouble(context, "minorRadius", this.getMinorRadius());
rs.addStateValueAsDouble(context, "headingDegrees", this.getHeading().degrees);
rs.addStateValueAsInteger(context, "intervals", this.getIntervals());
rs.addStateValueAsDouble(context, "theta", this.getTheta().degrees);
}

protected void doRestoreState(RestorableSupport rs, RestorableSupport.StateObject context)
Expand All @@ -516,6 +589,10 @@ protected void doRestoreState(RestorableSupport rs, RestorableSupport.StateObjec
Integer i = rs.getStateValueAsInteger(context, "intervals");
if (d != null)
this.setIntervals(i);

d = rs.getStateValueAsDouble(context, "theta");
if (d != null)
this.setTheta(Angle.fromDegrees(d));
}

protected void legacyRestoreState(RestorableSupport rs, RestorableSupport.StateObject context)
Expand Down
1 change: 1 addition & 0 deletions src/gov/nasa/worldwind/util/MessageStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ nullValue.TextureDataIsNull=TextureData is null
nullValue.TextureIsNull=Texture is null
nullValue.TextureCacheIsNull=Texture cache is null
nullValue.TextureCoordinateComputerIsNull=Texture coordinate computer is null
nullValue.ThetaIsNull=Theta is null
nullValue.ThreadIsNull=Thread is null
nullValue.ThrowableIsNull=Throwable is null
nullValue.TileIsNull=Tile is null
Expand Down