gov.nasa.worldwind.render.airspaces.Cake Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2012 United States Government as represented by the Administrator of the
* National Aeronautics and Space Administration.
* All Rights Reserved.
*/
package gov.nasa.worldwind.render.airspaces;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.geom.Box;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.util.*;
import java.util.*;
/**
* A cake consists of mutiple adjacent cylinder segments. Each cylinder is defined by its center location in latitude
* longitude, its radius in meters, and two aziumths specifying the active circumferential portion of the cylinder. Cake
* segments are altitude-limited shapes and therefore have an associated minimum and maximum altitude.
*
* @author tag
* @version $Id: Cake.java 2331 2014-09-19 19:45:55Z tgaskins $
*/
public class Cake extends AbstractAirspace
{
/** An inner class of {@link Cake} defining the parameters of one of the cake's cylinders. */
public static class Layer extends PartialCappedCylinder
{
public Layer(LatLon location, double radius, Angle leftAzimuth, Angle rightAzimuth,
double lowerAltitude, double upperAltitude)
{
super(location, radius, leftAzimuth, rightAzimuth);
this.setAltitudes(lowerAltitude, upperAltitude);
}
public Layer(LatLon location, double radius, Angle leftAzimuth, Angle rightAzimuth)
{
super(location, radius, leftAzimuth, rightAzimuth);
}
public Layer(LatLon location, double radius)
{
super(location, radius);
}
public Layer(AirspaceAttributes attributes)
{
super(attributes);
}
public Layer()
{
}
}
private List layers = new ArrayList();
public Cake(Collection layers)
{
this.addLayers(layers);
}
public Cake(AirspaceAttributes attributes)
{
super(attributes);
}
public Cake()
{
}
/**
* Returns the partial cylinders comprising the shape.
*
* @return the cylinders comprising the shape, or an empty list if the shape contains no layers.
*/
public List getLayers()
{
return Collections.unmodifiableList(this.layers);
}
/**
* Set the partial cylinders comprising the shape.
*
* @param layers the cylinders comprising the shape. May be an empty list.
*
* @throws IllegalArgumentException if the list reference is null.
*/
public void setLayers(Collection layers)
{
this.layers.clear();
this.addLayers(layers);
}
protected void addLayers(Iterable newLayers)
{
if (newLayers != null)
{
for (Layer l : newLayers)
{
if (l != null)
this.layers.add(l);
}
}
this.invalidateAirspaceData();
}
public void setEnableCaps(boolean enable)
{
for (Layer l : this.layers)
{
l.setEnableCaps(enable);
}
}
public void setEnableDepthOffset(boolean enable)
{
for (Layer l : this.layers)
{
l.setEnableDepthOffset(enable);
}
}
public void setTerrainConforming(boolean lowerTerrainConformant, boolean upperTerrainConformant)
{
super.setTerrainConforming(lowerTerrainConformant, upperTerrainConformant);
for (Layer l : this.layers)
{
l.setTerrainConforming(lowerTerrainConformant, upperTerrainConformant);
}
}
public boolean isAirspaceVisible(DrawContext dc)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
// If the parent Cake is not visible, then return false immediately without testing the child layers.
if (!super.isAirspaceVisible(dc))
return false;
boolean visible = false;
// The parent Cake is visible. Since the parent Cake's extent potentially contains volumes where no child
// geometry exists, test that at least one of the child layers are visible.
for (Layer l : this.layers)
{
if (l.isAirspaceVisible(dc))
{
visible = true;
break;
}
}
return visible;
}
public Position getReferencePosition()
{
ArrayList locations = new ArrayList(this.layers.size());
for (Layer l : this.layers)
{
locations.add(l.getCenter());
}
return this.computeReferencePosition(locations, this.getAltitudes());
}
protected Extent computeExtent(Globe globe, double verticalExaggeration)
{
List cakeLayers = this.getLayers();
if (cakeLayers == null || cakeLayers.isEmpty())
{
return null;
}
else if (cakeLayers.size() == 1)
{
return cakeLayers.get(0).computeExtent(globe, verticalExaggeration);
}
else
{
ArrayList extents = new ArrayList();
for (Layer layer : cakeLayers)
{
extents.add(layer.computeExtent(globe, verticalExaggeration));
}
return Box.union(extents);
}
}
@Override
protected List computeMinimalGeometry(Globe globe, double verticalExaggeration)
{
return null; // Cake is a geometry container, and therefore has no geometry itself.
}
protected void doMoveTo(Globe globe, Position oldRef, Position newRef)
{
if (oldRef == null)
{
String message = "nullValue.OldRefIsNull";
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (newRef == null)
{
String message = "nullValue.NewRefIsNull";
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
super.doMoveTo(oldRef, newRef);
for (Layer l : this.layers)
{
l.doMoveTo(globe, oldRef, newRef);
}
this.invalidateAirspaceData();
}
protected void doMoveTo(Position oldRef, Position newRef)
{
if (oldRef == null)
{
String message = "nullValue.OldRefIsNull";
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (newRef == null)
{
String message = "nullValue.NewRefIsNull";
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
super.doMoveTo(oldRef, newRef);
for (Layer l : this.layers)
{
l.doMoveTo(oldRef, newRef);
}
this.invalidateAirspaceData();
}
//**************************************************************//
//******************** Geometry Rendering ********************//
//**************************************************************//
@Override
public void preRender(DrawContext dc)
{
if (dc == null)
{
String msg = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(msg);
throw new IllegalArgumentException(msg);
}
if (!this.isVisible())
return;
this.determineActiveAttributes(dc);
for (Layer layer : this.layers)
{
// Synchronize the layer's attributes with this cake's attributes, and setup this cake as the layer's pick
// delegate.
layer.setAttributes(this.getActiveAttributes());
layer.setDelegateOwner(this.getDelegateOwner() != null ? this.getDelegateOwner() : this);
layer.preRender(dc);
}
}
@Override
public void render(DrawContext dc)
{
if (dc == null)
{
String msg = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(msg);
throw new IllegalArgumentException(msg);
}
if (!this.isVisible())
return;
if (!this.isAirspaceVisible(dc))
return;
for (Layer layer : this.layers)
{
layer.render(dc);
}
}
@Override
protected void doRenderGeometry(DrawContext dc, String drawStyle)
{
// Intentionally left blank.
}
//**************************************************************//
//******************** END Geometry Rendering ****************//
//**************************************************************//
@Override
protected void doGetRestorableState(RestorableSupport rs, RestorableSupport.StateObject context)
{
super.doGetRestorableState(rs, context);
RestorableSupport.StateObject so = rs.addStateObject(context, "layers");
for (Layer layer : this.layers)
{
RestorableSupport.StateObject lso = rs.addStateObject(so, "layer");
layer.doGetRestorableState(rs, lso);
}
}
@Override
protected void doRestoreState(RestorableSupport rs, RestorableSupport.StateObject context)
{
super.doRestoreState(rs, context);
RestorableSupport.StateObject so = rs.getStateObject(context, "layers");
if (so == null)
return;
RestorableSupport.StateObject[] lsos = rs.getAllStateObjects(so, "layer");
if (lsos == null || lsos.length == 0)
return;
ArrayList layerList = new ArrayList(lsos.length);
for (RestorableSupport.StateObject lso : lsos)
{
if (lso != null)
{
Layer layer = new Layer();
layer.doRestoreState(rs, lso);
layerList.add(layer);
}
}
this.setLayers(layerList);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy