/*
Copyright (C) 2001, 2006 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.layers;
import gov.nasa.worldwind.tracks.*;
import gov.nasa.worldwind.geom.Sector;
import gov.nasa.worldwind.util.Logging;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.globes.SectorGeometryList;
/**
* The <code>TrackLayer</code> class manages a collection of {@link gov.nasa.worldwind.tracks.Track} objects
* for rendering and picking.
*
* @author tag
* @version $Id: TrackLayer.java 4051 2007-12-22 19:57:09Z dcollins $
* @see gov.nasa.worldwind.tracks.Track
*/
public abstract class TrackLayer extends AbstractLayer
{
private java.util.Collection<Track> tracks = new java.util.ArrayList<Track>();
private Iterable<Track> tracksOverride;
private Sector boundingSector;
private int lowerLimit;
private int upperLimit;
private boolean overrideElevation = false;
private double elevation = 10d;
/**
* Creates a new <code>TrackLayer</code> with the specified <code>tracks</code> in its internal collection.
*
* @param tracks Collection of <code>Tracks</code> to add to this layer's internal collection.
*/
public TrackLayer(java.util.Collection<Track> tracks)
{
if (tracks == null)
{
String msg = Logging.getMessage("nullValue.TracksIsNull");
Logging.logger().severe(msg);
throw new IllegalArgumentException(msg);
}
this.tracks.addAll(tracks);
this.boundingSector = Sector.boundingSector(this.iterator());
}
public TrackPointIterator iterator()
{
return new TrackPointIteratorImpl(getActiveTracks());
}
public int getNumPoints()
{
return ((TrackPointIteratorImpl)this.iterator()).getNumPoints();
}
/**
* Returns the Iterable of Tracks currently in use by this layer.
* If the caller has specified a custom Iterable via {@link #setTrackIterable}, this will returns a reference
* to that Iterable. If the caller passed <code>setTrackIterable</code> a null parameter,
* or if <code>setTrackIterable</code> has not been called, this returns a view of this layer's internal
* collection of Tracks.
*
* @return Iterable of currently active Tracks.
*/
public Iterable<Track> getTracks()
{
return getActiveTracks();
}
/**
* Returns the Iterable of currently active Tracks.
* If the caller has specified a custom Iterable via {@link #setTrackIterable}, this will returns a reference
* to that Iterable. If the caller passed <code>setTrackIterable</code> a null parameter,
* or if <code>setTrackIterable</code> has not been called, this returns a view of this layer's internal
* collection of Tracks.
*
* @return Iterable of currently active Tracks.
*/
private Iterable<Track> getActiveTracks()
{
if (this.tracksOverride != null)
{
return this.tracksOverride;
}
else
{
// Return an unmodifiable reference to the internal list of tracks.
// This prevents callers from changing this list and invalidating any invariants we have established.
return java.util.Collections.unmodifiableCollection(this.tracks);
}
}
/**
* Sets the specified <code>tracks</code> as this layer's internal collection.
* If this layer's internal collection has been overriden with a call to {@link #setTrackIterable},
* this will throw an exception.
*
* @param tracks List of Tracks to use.
* @throws IllegalArgumentException If <code>tracks</code> is null.
* @throws IllegalStateException If a custom Iterable has been specified by a call to <code>setTrackIterable</code>.
*/
public void setTracks(java.util.Collection<Track> tracks)
{
if (tracks == null)
{
String msg = Logging.getMessage("nullValue.TracksIsNull");
Logging.logger().severe(msg);
throw new IllegalArgumentException(msg);
}
if (this.tracksOverride != null)
{
String msg = Logging.getMessage("generic.LayerIsUsingCustomIterable");
Logging.logger().severe(msg);
throw new IllegalStateException(msg);
}
clearTracks();
this.tracks.addAll(tracks);
}
/**
* Overrides the collection of currently active Tracks with the specified <code>trackIterable</code>.
* This layer will maintain a reference to <code>trackIterable</code> strictly for picking and rendering.
* This layer will not modify the Iterable reference. However, this will clear
* the internal collection of Tracks, and will prevent any modification to its contents via
* <code>setTracks</code>.
*
* If the specified <code>trackIterable</code> is null, this layer will revert to maintaining its internal
* collection.
*
* @param trackIterable Iterable to use instead of this layer's internal collection, or null to use this
* layer's internal collection.
*/
public void setTrackIterable(Iterable<Track> trackIterable)
{
this.tracksOverride = trackIterable;
// Clear the internal collection of Tracks.
clearTracks();
}
private void clearTracks()
{
if (this.tracks != null && this.tracks.size() > 0)
this.tracks.clear();
}
public Sector getBoundingSector()
{
return boundingSector;
}
public void setBoundingSector(Sector boundingSector)
{
this.boundingSector = boundingSector;
}
public int getLowerLimit()
{
return lowerLimit;
}
public void setLowerLimit(int lowerLimit)
{
this.lowerLimit = lowerLimit;
}
public int getUpperLimit()
{
return upperLimit;
}
public void setUpperLimit(int upperLimit)
{
this.upperLimit = upperLimit;
}
public double getElevation()
{
return this.elevation;
}
public void setElevation(double markerElevation)
{
this.elevation = markerElevation;
}
public boolean isOverrideElevation()
{
return this.overrideElevation;
}
public void setOverrideElevation(boolean overrideElevation)
{
this.overrideElevation = overrideElevation;
}
@Override
public String toString()
{
return Logging.getMessage("layers.TrackLayer.Name");
}
@Override
protected void doPick(DrawContext dc, java.awt.Point pickPoint)
{
this.draw(dc, pickPoint);
}
@Override
protected void doRender(DrawContext dc)
{
this.draw(dc, null);
}
private void draw(DrawContext dc, java.awt.Point pickPoint)
{
TrackPointIterator trackPoints = this.iterator();
if (!trackPoints.hasNext())
return;
if (dc.getVisibleSector() == null)
return;
SectorGeometryList geos = dc.getSurfaceGeometry();
if (geos == null)
return;
if (!dc.getVisibleSector().intersects(this.getBoundingSector()))
return;
this.doDraw(dc, trackPoints, pickPoint);
}
protected abstract void doDraw(DrawContext dc, TrackPointIterator trackPoints, java.awt.Point pickPoint);
}