/* XXL: The eXtensible and fleXible Library for data processing
Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger
Head of the Database Research Group
Department of Mathematics and Computer Science
University of Marburg
Germany
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; If not, see <http://www.gnu.org/licenses/>.
http://code.google.com/p/xxl/
*/
package xxl.core.spatial.rectangles;
import java.util.Random;
import xxl.core.cursors.AbstractCursor;
import xxl.core.cursors.Cursors;
import xxl.core.cursors.mappers.Mapper;
import xxl.core.cursors.sources.ArrayCursor;
import xxl.core.functions.AbstractFunction;
import xxl.core.functions.ArrayFactory;
import xxl.core.spatial.points.DoublePoint;
import xxl.core.util.random.ContinuousRandomWrapper;
import xxl.core.util.random.JavaContinuousRandomWrapper;
/**
* A Cursor that returns randomly created Rectangles (of type Rectangle).
*
*/
public class RandomRectangle extends AbstractCursor{
/** The extension of a rectangle in each dimension.
*/
protected double d;
/** The dimensionality of the rectangle
*/
protected int dim;
/** The number of rectangles to create
*/
protected int number;
/** 1 minus the attribute d (used for internal computations)
*/
protected double _1minusd;
/** The ContinuousRandomWrappers to use.
*/
protected ContinuousRandomWrapper[] randomWrapper;
/** Creates a new RandomRectangle returning <code>number</code> rectangles of dimension
* <code>dim</code> and extension <code>d</code> in each dimension.
*
* @param d the extension of a rectangle in each dimension
* @param dim the dimensionality of the rectangle
* @param number the number of rectangles to create
* @param randomWrapper the ContinuousRandomWrappers to use
*/
public RandomRectangle(double d, int dim, int number, ContinuousRandomWrapper[] randomWrapper){
this.d = d;
this.dim = dim;
this.number = number;
this.randomWrapper = randomWrapper;
this._1minusd = (1-d);
}
/** Creates a new RandomRectangle returning <code>number</code> rectangles of dimension
* <code>dim</code> and extension <code>d</code> in each dimension.
*
* @param d the extension of a rectangle in each dimension
* @param dim the dimensionality of the rectangle
* @param number the number of rectangles to create
* @param random the Random enginge to use to use
*/
public RandomRectangle(double d, int dim, int number, Random[] random){
this(d,dim, number,
(JavaContinuousRandomWrapper[]) Cursors.toArray(
new Mapper(
new AbstractFunction(){
public Object invoke(Object object){
return new JavaContinuousRandomWrapper((Random)object);
}
}
, new ArrayCursor<Random>(random)
),
new JavaContinuousRandomWrapper[random.length]
)
);
}
/** Creates a new RandomRectangle returning <code>number</code> rectangles of dimension
* <code>dim</code> and extension <code>d</code> in each dimension.
*
* @param d the extension of a rectangle in each dimension
* @param dim the dimensionality of the rectangle
* @param number the number of rectangles to create
*/
public RandomRectangle(double d, final int dim, int number){
this(d, dim, number,
(Random[])new ArrayFactory(
new AbstractFunction(){
public Object invoke(Object object){
return new Random[dim];
}
},
new AbstractFunction(){
int t = 4;
public Object invoke(Object object){
return new Random(System.currentTimeMillis()+(t+=1234));
}
}
).invoke()
);
}
/**
* If the needed number of rectangles was not reached yet
* computes the next rectangle and returns <tt>true</tt>
* otherwise returns <tt>false</tt>
*
* @return <tt>true</tt> if next rectangle were created and <tt>false</tt>
* if needed number of rectangles was reached already.
*/
public boolean hasNextObject(){
if (number-->0){
double[] leftBorders = new double[dim];
double[] rightBorders = new double[dim];
for(int i=0; i<dim; i++){
leftBorders[i] = randomWrapper[i].nextDouble()*_1minusd;
rightBorders[i] = leftBorders[i]+d;
}
DoublePoint leftPoint = new DoublePoint(leftBorders);
DoublePoint rightPoint = new DoublePoint(rightBorders);
next = new DoublePointRectangle(leftPoint, rightPoint);
return true;
}
return false;
}
/**
* Returns the next element in the iteration. This element will be
* accessible by some of the cursor's methods, e.g., <tt>update</tt> or
* <tt>remove</tt>, until a call to <tt>next</tt> or <tt>peek</tt> occurs.
* This is calling <tt>next</tt> or <tt>peek</tt> proceeds the iteration and
* therefore its previous element will not be accessible any more.
*
* <p>This abstract operation should implement the core functionality of
* the <tt>next</tt> method which secures that the cursor is in a proper
* state when this method is called. Due to this the <tt>nextObject</tt>
* method need not to deal with exception handling.</p>
*
* @return the next element in the iteration.
*/
public Object nextObject() {
return next;
}
}