gov.nasa.worldwind.util.VecBuffer 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.util;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.render.DrawContext;
import com.jogamp.opengl.GL2;
import java.nio.Buffer;
import java.util.*;
/**
* VecBuffer provides an logical interface on {@link BufferWrapper} to interpret its contents as a series of vector
* tuples (rather than individual primitive types). The number of coordinates in each logical vector is specified by the
* property coordsPerElem
. For example, if a VecBuffer is composed of (x, y, z) tuples then coordsPerElem
* would be 3.
*
* @author dcollins
* @version $Id: VecBuffer.java 1171 2013-02-11 21:45:02Z dcollins $
*/
public class VecBuffer
{
protected int coordsPerVec;
protected BufferWrapper buffer;
/**
* Constructs a new VecBuffer with the specified vector size, and backing BufferWrapper.
*
* @param coordsPerVec the number of coordinates per logical vector.
* @param buffer the backing BufferWrapper.
*
* @throws IllegalArgumentException if coordsPerElem is 0 or negative, or if the buffer is null.
*/
public VecBuffer(int coordsPerVec, BufferWrapper buffer)
{
if (coordsPerVec < 1)
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "coordsPerVec < 1");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (buffer == null)
{
String message = Logging.getMessage("nullValue.BufferIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.coordsPerVec = coordsPerVec;
this.buffer = buffer;
}
/**
* Returns the empty VecBuffer. The returned VecBuffer has no backing buffer, and is immutable.
*
* @param coordsPerVec the number of coordinates per logical vector.
*
* @return the empty VecBuffer.
*/
public static VecBuffer emptyVecBuffer(int coordsPerVec)
{
return new VecBuffer(coordsPerVec, BufferWrapper.emptyBufferWrapper());
}
/**
* Returns the number of coordinates per logical vector element.
*
* @return the cardinality of a logical vector element.
*/
public int getCoordsPerVec()
{
return this.coordsPerVec;
}
/**
* Returns the number of logical vector elements contained in the VecBuffer.
*
* @return the size of this VecBuffer, in units of logical vectors.
*/
public int getSize()
{
return this.buffer.length() / this.coordsPerVec;
}
/**
* Returns the backing BufferWrapper.
*
* @return the backing buffer.
*/
public BufferWrapper getBufferWrapper()
{
return this.buffer;
}
/**
* Returns the vector element at the specified position. The position is a logical vector position, position n
* corresponds to the buffer's nth vector. If the specified array length is smaller than the logical vector size,
* only the specified portion of the vector element is returned.
*
* @param position the logical vector position.
* @param array the destination array.
*
* @return an array of vector elements.
*
* @throws IllegalArgumentException if the position is out of range, or if the array is null.
*/
public double[] get(int position, double[] array)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (array == null)
{
String message = Logging.getMessage("nullValue.ArrayIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int index = this.indexFromVectorPosition(position);
int length = array.length;
if (length > this.coordsPerVec)
length = this.coordsPerVec;
this.buffer.getDouble(index, array, 0, length);
return array;
}
/**
* Returns the vector element at the specified position. The position is a logical vector position, position n
* corresponds to the buffer's nth vector. If the specified array length is smaller than the logical vector size,
* only the specified portion of the vector element is returned.
*
* @param position the logical vector position.
* @param array the destination array.
*
* @return an array of vector elements.
*
* @throws IllegalArgumentException if the position is out of range, or if the array is null.
*/
public float[] getFloat(int position, float[] array)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (array == null)
{
String message = Logging.getMessage("nullValue.ArrayIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int index = this.indexFromVectorPosition(position);
int length = array.length;
if (length > this.coordsPerVec)
length = this.coordsPerVec;
this.buffer.getFloat(index, array, 0, length);
return array;
}
/**
* Sets the vector element at the specified position. The position is a logical vector position, position n
* corresponds to the buffer's nth vector. If the specified array length is smaller than the logical vector size,
* only the specified portion of the vector element is set.
*
* @param position the logical vector position.
* @param array the source array.
*
* @throws IllegalArgumentException if the position is out of range, or if the array is null.
*/
public void put(int position, double[] array)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (array == null)
{
String message = Logging.getMessage("nullValue.ArrayIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int index = this.indexFromVectorPosition(position);
int length = array.length;
if (length > this.coordsPerVec)
length = this.coordsPerVec;
this.buffer.putDouble(index, array, 0, length);
}
/**
* Sets the vector element at the specified position. The position is a logical vector position, position n
* corresponds to the buffer's nth vector. If the specified array length is smaller than the logical vector size,
* only the specified portion of the vector element is set.
*
* @param position the logical vector position.
* @param array the source array.
*
* @throws IllegalArgumentException if the position is out of range, or if the array is null.
*/
public void putFloat(int position, float[] array)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (array == null)
{
String message = Logging.getMessage("nullValue.ArrayIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int index = this.indexFromVectorPosition(position);
int length = array.length;
if (length > this.coordsPerVec)
length = this.coordsPerVec;
this.buffer.putFloat(index, array, 0, length);
}
/**
* Sets the vector elements starting at the specified position, and ending at the specified position + count. The
* position is a logical vector position, position n corresponds to the buffer's nth vector. The array must have
* sufficient length to represent count separate logical vectors (each with size equal to coordsPerVec) tightly
* packed into the array, starting at index 0.
*
* @param position the starting logical vector position.
* @param array the source array.
* @param count the number of logical arrays to set.
*
* @throws IllegalArgumentException if the position is out of range, if the array is null, or if the array has
* insufficient length.
*/
public void putAll(int position, double[] array, int count)
{
if (position < 0 || position + count > this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange",
"position < 0 or position + count >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (array == null)
{
String message = Logging.getMessage("nullValue.ArrayIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int index = this.indexFromVectorPosition(position);
int length = this.indexFromVectorPosition(count);
if (array.length < length)
{
String message = Logging.getMessage("generic.ArrayInvalidLength", array.length);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.buffer.putDouble(index, array, 0, length);
}
/**
* Returns a new VecBuffer which is a subsequence of this buffer. The new buffer starts with the vector at the
* specified position, and has the specified length. The two buffers share the same backing store, so changes to
* this buffer are reflected in the new buffer, and visa versa.
*
* @param position the new buffer's staring position, in logical vectors.
* @param size the new buffer's size, in logical vectors.
*
* @return a subsequence of this buffer.
*/
public VecBuffer getSubBuffer(int position, int size)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int index = this.indexFromVectorPosition(position);
int length = this.indexFromVectorPosition(size);
BufferWrapper subBuffer = this.buffer.getSubBuffer(index, length);
return new VecBuffer(this.coordsPerVec, subBuffer);
}
/**
* Sets a subsequence of this buffer with the contents of the specified buffer. The subsequence to set starts with
* the vector at the specified position, and has size equal to the specified buffer's size. The specified buffer
* must have the same logical vector size as this buffer (coordsPerVec must be equivalent).
*
* @param position the starting vector position to set.
* @param buffer the input buffer.
*
* @throws IllegalArgumentException if the position is out of range, if the buffer is null or incompatible, or if
* this buffer has insufficient length to store the sub-buffer at the specified
* position.
*/
public void putSubBuffer(int position, VecBuffer buffer)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (buffer == null)
{
String message = Logging.getMessage("nullValue.BufferIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.putSubBuffer(position, buffer, 0, buffer.getSize());
}
/**
* Sets a subsequence of this buffer with the contents of the specified buffer. The subsequence to set starts with
* the vector at the specified position, and has size equal to the specified size. The specified buffer must have
* the same logical vector size as this buffer (coordsPerVec must be equivalent).
*
* @param position the starting vector position to set.
* @param buffer the input buffer.
* @param offset the vector position to start copying values from the specified buffer.
* @param size the number of vectors to read copy form the specified buffer.
*
* @throws IllegalArgumentException if the position is out of range, if the buffer is null or incompatible, if this
* buffer has insufficient length to store the sub-buffer at the specified
* position, or if the specified offset and size define a range outside of the
* specified buffer.
*/
public void putSubBuffer(int position, VecBuffer buffer, int offset, int size)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (buffer == null)
{
String message = Logging.getMessage("nullValue.BufferIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
// Not enough room in buffer.
if (buffer.getSize() < (offset + size))
{
String message = Logging.getMessage("generic.BufferOverflow", buffer.getSize(), size);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
// Buffer is incompatible.
if (this.coordsPerVec != buffer.coordsPerVec)
{
String message = Logging.getMessage("generic.BufferIncompatible", buffer);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
// Buffer is too large.
int sizeNeeded = position + size;
if (this.getSize() < sizeNeeded)
{
String message = Logging.getMessage("generic.BufferOverflow", this.getSize(), sizeNeeded);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int index = this.indexFromVectorPosition(position);
int off = this.indexFromVectorPosition(offset);
int length = this.indexFromVectorPosition(size);
this.buffer.putSubBuffer(index, buffer.getBufferWrapper(), off, length);
}
/**
* Returns the vector element at the specified position, as a {@link Vec4}. This buffer's logical vector size must
* be either 2, 3 or 4.
*
* @param position the logical vector position.
*
* @return the vector at the specified vector position.
*
* @throws IllegalArgumentException if the position is out of range, or if this buffer cannot store a Vec4.
*/
public Vec4 getVector(int position)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.coordsPerVec != 2 && this.coordsPerVec != 3 && this.coordsPerVec != 4)
{
String message = Logging.getMessage("generic.BufferIncompatible", this);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
double[] compArray = new double[this.coordsPerVec];
this.get(position, compArray);
return Vec4.fromDoubleArray(compArray, 0, this.coordsPerVec);
}
/**
* Sets the vector element at the specified position, as a Vec4. This buffer's logical vector size must be either 2,
* 3 or 4.
*
* @param position the logical vector position.
* @param vec the vector to set.
*
* @throws IllegalArgumentException if the position is out of range, if the vector is null, or if this buffer cannot
* store a Vec4.
*/
public void putVector(int position, Vec4 vec)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (vec == null)
{
String message = Logging.getMessage("nullValue.Vec4IsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.coordsPerVec != 2 && this.coordsPerVec != 3 && this.coordsPerVec != 4)
{
String message = Logging.getMessage("generic.BufferIncompatible", this);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
double[] compArray = new double[this.coordsPerVec];
vec.toDoubleArray(compArray, 0, this.coordsPerVec);
this.put(position, compArray);
}
/**
* Returns the vector element at the specified position, as a geographic {@link LatLon}. This buffer's logical
* vector size must be at least 2.
*
* @param position the logical vector position.
*
* @return the geographic location at the specified vector position.
*
* @throws IllegalArgumentException if the position is out of range, or if this buffer cannot store a LatLon.
*/
public LatLon getLocation(int position)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.coordsPerVec < 2)
{
String message = Logging.getMessage("generic.BufferIncompatible", this);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
double[] compArray = new double[2];
this.get(position, compArray);
return LatLon.fromDegrees(compArray[1], compArray[0]);
}
/**
* Sets the vector element at the specified position, as a geographic LatLon. This buffer's logical vector size must
* be at least 2.
*
* @param position the logical vector position.
* @param ll the geographic location to set.
*
* @throws IllegalArgumentException if the position is out of range, if the LatLon is null, or if this buffer cannot
* store a LatLon.
*/
public void putLocation(int position, LatLon ll)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (ll == null)
{
String message = Logging.getMessage("nullValue.LatLonIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.coordsPerVec < 2)
{
String message = Logging.getMessage("generic.BufferIncompatible", this);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
double[] compArray = new double[2];
compArray[1] = ll.getLatitude().degrees;
compArray[0] = ll.getLongitude().degrees;
this.put(position, compArray);
}
/**
* Returns the vector element at the specified position, as a geographic {@link Position}. This buffer's logical
* vector size must be at least 2.
*
* @param position the logical vector position.
*
* @return the geographic Position at the specified vector position.
*
* @throws IllegalArgumentException if the position is out of range, or if this buffer cannot store a Position.
*/
public Position getPosition(int position)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.coordsPerVec < 2)
{
String message = Logging.getMessage("generic.BufferIncompatible", this);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
double[] compArray = new double[this.coordsPerVec];
this.get(position, compArray);
return Position.fromDegrees(
compArray[1],
compArray[0],
(this.coordsPerVec > 2) ? compArray[2] : 0);
}
/**
* Sets the vector element at the specified position, as a geographic Position. This buffer's logical vector size
* must be at least 2.
*
* @param position the logical vector position.
* @param p the geographic Position to set.
*
* @throws IllegalArgumentException if the position is out of range, if the Position is null, or if this buffer
* cannot store a Position.
*/
public void putPosition(int position, Position p)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (p == null)
{
String message = Logging.getMessage("nullValue.PositionIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.coordsPerVec < 2)
{
String message = Logging.getMessage("generic.BufferIncompatible", this);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
double[] compArray = new double[3];
compArray[1] = p.getLatitude().degrees;
compArray[0] = p.getLongitude().degrees;
compArray[2] = p.getElevation();
this.put(position, compArray);
}
/**
* Returns a copy of this VecBuffer with the specified new size. The new size must be greater than or equal to this
* VecBuffer's size. If the new size is greater than this buffer's size, this returns a new buffer which is
* partially filled with the contents of this buffer. The returned VecBuffer has the same number of coordinates per
* tuple and the same backing buffer type, but its contents are independent from this VecBuffer.
*
* @param newSize the new buffer's size.
*
* @return the new buffer, with the specified size.
*/
public VecBuffer copyOf(int newSize)
{
if (newSize < this.getSize())
{
String message = Logging.getMessage("generic.SizeOutOfRange", newSize);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
BufferWrapper newBuffer = this.buffer.copyOf(this.coordsPerVec * newSize);
return new VecBuffer(this.coordsPerVec, newBuffer);
}
/**
* Returns an iterator over this buffer's logical vectors, as double[] coordinate arrays. The array returned from
* each call to Iterator.next() will be newly allocated, and will have length equal to coordsPerVec.
*
* @return iterator over this buffer's vectors, as double[] arrays.
*/
public Iterable getCoords()
{
return this.getCoords(this.coordsPerVec);
}
/**
* Returns an iterator over this buffer's logical vectors, as double[] coordinate arrays. The array returned from a
* call to Iterator.next() will be newly allocated, and will have length equal to coordsPerVec or minCoordsPerVec,
* whichever is larger. If minCoordsPerVec is larger than coordsPerVec, then the elements in the returned array will
* after index "coordsPerVec - 1" will be undefined.
*
* @param minCoordsPerVec the minimum number of coordinates returned in each double[] array.
*
* @return iterator over this buffer's vectors, as double[] arrays.
*/
public Iterable getCoords(final int minCoordsPerVec)
{
return new Iterable()
{
public Iterator iterator()
{
return new BasicIterator(new CoordAccessor(minCoordsPerVec));
}
};
}
/**
* Returns a reverse iterator over this buffer's logical vectors, as double[] coordinate arrays. The array returned
* from a call to Iterator.next() will be newly allocated, and will have length equal to coordsPerVec or
* minCoordsPerVec, whichever is larger. If minCoordsPerVec is larger than coordsPerVec, then the elements in the
* returned array will after index "coordsPerVec - 1" will be undefined.
*
* @param minCoordsPerVec the minimum number of coordinates returned in each double[] array.
*
* @return reverse iterator over this buffer's vectors, as double[] arrays.
*/
public Iterable getReverseCoords(final int minCoordsPerVec)
{
return new Iterable()
{
public Iterator iterator()
{
return new ReverseIterator(new CoordAccessor(minCoordsPerVec));
}
};
}
/**
* Sets a subsequence of this buffer with the contents of the specified Iterable. The subsequence to set starts with
* the vector at the specified position, and has size equal to the number of elements in the Iterable or the number
* of remaining vectors in the buffer, whichever is less.
*
* @param position the starting vector position to set.
* @param iterable iterator over the elements to set.
*
* @throws IllegalArgumentException if the position is out of range, or if the iterable is null.
*/
public void putCoords(int position, Iterable iterable)
{
if (position < 0 || position >= this.getSize())
{
String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (iterable == null)
{
String message = Logging.getMessage("nullValue.IterableIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int pos = position;
for (double[] coords : iterable)
{
this.put(pos, coords);
if (++pos >= this.getSize())
break;
}
}
/**
* Returns an iterator over this buffer's logical vectors, as Vec4 references.
*
* @return iterator over this buffer's vectors, as Vec4 references.
*/
public Iterable getVectors()
{
return new Iterable()
{
public Iterator iterator()
{
return new BasicIterator(new VectorAccessor());
}
};
}
/**
* Returns a reverse iterator over this buffer's logical vectors, as Vec4 references.
*
* @return reverse iterator over this buffer's vectors, as Vec4 references.
*/
public Iterable getReverseVectors()
{
return new Iterable()
{
public Iterator iterator()
{
return new ReverseIterator(new VectorAccessor());
}
};
}
/**
* Sets a subsequence of this buffer with the contents of the specified Iterable. The subsequence to set starts with
* the vector at the specified position, and has size equal to the number of elements in the Iterable or the number
* of remaining vectors in the buffer, whichever is less. This buffer's logical vector size must be either 2, 3 or
* 4.
*
* @param position the starting vector position to set.
* @param iterable iterator over the elements to set.
*
* @throws IllegalArgumentException if the position is out of range, if the iterable is null, or if this buffer
* cannot store a Vec4.
*/
public void putVectors(int position, Iterable extends Vec4> iterable)
{
if (iterable == null)
{
String message = Logging.getMessage("nullValue.IterableIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int pos = position;
for (Vec4 vec : iterable)
{
this.putVector(pos, vec);
if (++pos >= this.getSize())
break;
}
}
/**
* Returns an iterator over this buffer's logical vectors, as LatLon locations.
*
* @return iterator over this buffer's vectors, as LatLon locations.
*/
public Iterable getLocations()
{
return new Iterable()
{
public Iterator iterator()
{
return new BasicIterator(new LocationAccessor());
}
};
}
/**
* Returns a reverse iterator over this buffer's logical vectors, as LatLon locations.
*
* @return reverse iterator over this buffer's vectors, as LatLon locations.
*/
public Iterable getReverseLocations()
{
return new Iterable()
{
public Iterator iterator()
{
return new ReverseIterator(new LocationAccessor());
}
};
}
/**
* Sets a subsequence of this buffer with the contents of the specified Iterable. The subsequence to set starts with
* the vector at the specified position, and has size equal to the number of elements in the Iterable or the number
* of remaining vectors in the buffer, whichever is less. This buffer's logical vector size must be at least 2.
*
* @param position the starting vector position to set.
* @param iterable iterator over the elements to set.
*
* @throws IllegalArgumentException if the position is out of range, if the iterable is null, or if this buffer
* cannot store a LatLon.
*/
public void putLocations(int position, Iterable extends LatLon> iterable)
{
if (iterable == null)
{
String message = Logging.getMessage("nullValue.IterableIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int pos = position;
for (LatLon ll : iterable)
{
this.putLocation(pos, ll);
if (++pos >= this.getSize())
break;
}
}
/**
* Returns an iterator over this buffer's logical vectors, as geographic Positions.
*
* @return iterator over this buffer's vectors, as geographic Positions.
*/
public Iterable getPositions()
{
return new Iterable()
{
public Iterator iterator()
{
return new BasicIterator(new PositionAccessor());
}
};
}
/**
* Returns a reverse iterator over this buffer's logical vectors, as geographic Positions.
*
* @return reverse iterator over this buffer's vectors, as geographic Positions.
*/
public Iterable getReversePositions()
{
return new Iterable()
{
public Iterator iterator()
{
return new ReverseIterator(new PositionAccessor());
}
};
}
/**
* Sets a subsequence of this buffer with the contents of the specified Iterable. The subsequence to set starts with
* the vector at the specified position, and has size equal to the number of elements in the Iterable or the number
* of remaining vectors in the buffer, whichever is less. This buffer's logical vector size must be at least 2.
*
* @param position the starting vector position to set.
* @param iterable iterator over the elements to set.
*
* @throws IllegalArgumentException if the position is out of range, if the iterable is null, or if this buffer
* cannot store a LatLon.
*/
public void putPositions(int position, Iterable extends Position> iterable)
{
if (iterable == null)
{
String message = Logging.getMessage("nullValue.IterableIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
int pos = position;
for (Position p : iterable)
{
this.putPosition(pos, p);
if (++pos >= this.getSize())
break;
}
}
/**
* Binds this buffer as the source of color values to use when rendering OpenGL primitives. The color type is equal
* to buffer's underlying BufferWrapper GL type, the stride is 0, and the vertex data itself is this buffer's
* backing NIO {@link Buffer}. This buffer's vector size must be 3, or 4.
*
* @param dc the current {@link DrawContext}.
*
* @throws IllegalArgumentException if the DrawContext is null, or if this buffer is not compatible as a color
* buffer.
*/
public void bindAsColorBuffer(DrawContext dc)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.coordsPerVec != 3 && this.coordsPerVec != 4)
{
String message = Logging.getMessage("generic.ArgumentOutOfRange",
"coordinates per vertex = " + this.coordsPerVec);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
gl.glColorPointer(this.coordsPerVec, this.buffer.getGLDataType(), 0, this.buffer.getBackingBuffer());
}
/**
* Binds this buffer as the source of normal coordinates to use when rendering OpenGL primitives. The normal type is
* equal to buffer's underlying BufferWrapper GL type, the stride is 0, and the vertex data itself is this buffer's
* backing NIO {@link Buffer}. This buffer's vector size must be 3.
*
* @param dc the current {@link DrawContext}.
*
* @throws IllegalArgumentException if the DrawContext is null, or if this buffer is not compatible as a normal
* buffer.
*/
public void bindAsNormalBuffer(DrawContext dc)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.coordsPerVec != 3)
{
String message = Logging.getMessage("generic.ArgumentOutOfRange",
"coordinates per vertex = " + this.coordsPerVec);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
gl.glNormalPointer(this.buffer.getGLDataType(), 0, this.buffer.getBackingBuffer());
}
/**
* Binds this buffer as the source of vertex coordinates to use when rendering OpenGL primitives. The vertex size is
* equal to coordsPerVertex, the vertex type is equal to buffer's underlying BufferWrapper GL type, the stride is 0,
* and the normal data itself is this buffer's backing NIO Buffer. This buffer's vector size must be 2, 3, or 4.
*
* @param dc the current DrawContext.
*
* @throws IllegalArgumentException if the DrawContext is null, or if this buffer is not compatible as a vertex
* buffer.
*/
public void bindAsVertexBuffer(DrawContext dc)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.coordsPerVec != 2 && this.coordsPerVec != 3 && this.coordsPerVec != 4)
{
String message = Logging.getMessage("generic.ArgumentOutOfRange",
"coordinates per vertex = " + this.coordsPerVec);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
gl.glVertexPointer(this.coordsPerVec, this.buffer.getGLDataType(), 0, this.buffer.getBackingBuffer());
}
/**
* Binds this buffer as the source of texture coordinates to use when rendering OpenGL primitives. The texture
* coordinate size is equal to coordsPerVertex, the texture coordinate type is equal to buffer's underlying
* BufferWrapper GL type, the stride is 0, and the texture coordinate data itself is this buffer's backing NIO
* Buffer. This buffer's vector size must be 1, 2, 3, or 4.
*
* @param dc the current DrawContext.
*
* @throws IllegalArgumentException if the DrawContext is null, or if this buffer is not compatible as a normal
* buffer.
*/
public void bindAsTexCoordBuffer(DrawContext dc)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (this.coordsPerVec != 1 && this.coordsPerVec != 2 && this.coordsPerVec != 3 && this.coordsPerVec != 4)
{
String message = Logging.getMessage("generic.ArgumentOutOfRange",
"coordinates per vertex = " + this.coordsPerVec);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
gl.glTexCoordPointer(this.coordsPerVec, this.buffer.getGLDataType(), 0, this.buffer.getBackingBuffer());
}
/**
* Renders getSize()
elements from the currently bounds OpenGL coordinate buffers, beginning with
* element 0. The specified drawMode indicates which type of OpenGL primitives to render.
*
* @param dc the current DrawContext.
* @param drawMode the type of OpenGL primtives to render.
*
* @throws IllegalArgumentException if the DrawContext is null.
*/
public void drawArrays(DrawContext dc, int drawMode)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
dc.getGL().glDrawArrays(drawMode, 0, this.getSize());
}
/**
* Maps the logical vector position to a physical buffer index.
*
* @param position the vector position.
*
* @return the physical buffer index.
*/
protected int indexFromVectorPosition(int position)
{
return this.coordsPerVec * position;
}
/**
* Maps the physical buffer index to a logical vector position.
*
* @param index the physical buffer index.
*
* @return the vector position.
*/
protected int vectorPositionFromIndex(int index)
{
return index / this.coordsPerVec;
}
//**************************************************************//
//******************** Iterators *****************************//
//**************************************************************//
protected class BasicIterator implements Iterator
{
protected int position;
protected final int size;
protected ElementAccessor accessor;
public BasicIterator(ElementAccessor accessor)
{
this.position = -1;
this.size = getSize();
this.accessor = accessor;
}
public boolean hasNext()
{
return this.position < (this.size - 1);
}
public T next()
{
this.position++;
if (this.position < this.size)
{
return this.accessor.getElement(this.position);
}
else
{
throw new NoSuchElementException();
}
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
protected class ReverseIterator implements Iterator
{
protected int position;
protected ElementAccessor accessor;
public ReverseIterator(ElementAccessor accessor)
{
this.position = getSize();
this.accessor = accessor;
}
public boolean hasNext()
{
return this.position > 0;
}
public T next()
{
this.position--;
if (this.position >= 0)
{
return this.accessor.getElement(this.position);
}
else
{
throw new NoSuchElementException();
}
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
protected interface ElementAccessor
{
T getElement(int position);
}
protected class CoordAccessor implements ElementAccessor
{
private int numCoords;
public CoordAccessor(int minCoordsPerVec)
{
this.numCoords = coordsPerVec;
if (this.numCoords < minCoordsPerVec)
this.numCoords = minCoordsPerVec;
}
public double[] getElement(int position)
{
double[] compArray = new double[this.numCoords];
get(position, compArray);
return compArray;
}
}
protected class VectorAccessor implements ElementAccessor
{
public Vec4 getElement(int position)
{
return getVector(position);
}
}
protected class LocationAccessor implements ElementAccessor
{
public LatLon getElement(int position)
{
return getLocation(position);
}
}
protected class PositionAccessor implements ElementAccessor
{
public Position getElement(int position)
{
return getPosition(position);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy