package org.osm2world.core.math;
import static java.lang.Math.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.collections.iterators.ArrayIterator;
import org.apache.commons.collections.iterators.IteratorChain;
/**
* regular grid of {@link VectorXZ}.
*
* Individual points are created only when they are first accessed,
* so no memory is wasted on unused points.
*/
public class VectorGridXZ implements Iterable<VectorXZ> {
private static final VectorXZ[][] EMPTY_GRID = new VectorXZ[0][0];
private final VectorXZ[][] grid;
private final double sampleDistance;
private final int startX;
private final int startZ;
/**
* returns a regular grid of points within a bounding box.
*/
public VectorGridXZ(AxisAlignedBoundingBoxXZ box, double sampleDistance) {
this.sampleDistance = sampleDistance;
startX = (int)ceil((box.minX + 0.01) / sampleDistance);
startZ = (int)ceil((box.minZ + 0.01) / sampleDistance);
int endX = (int)floor((box.maxX - 0.01) / sampleDistance);
int endZ = (int)floor((box.maxZ - 0.01) / sampleDistance);
int numSamplesX = endX - startX + 1;
int numSamplesZ = endZ - startZ + 1;
if (numSamplesX <= 0 || numSamplesZ <= 0) {
grid = EMPTY_GRID;
} else {
grid = new VectorXZ[numSamplesX][numSamplesZ];
}
}
public int size() {
return sizeX() * sizeZ();
}
public int sizeX() {
return grid.length;
}
public int sizeZ() {
return grid == EMPTY_GRID ? 0 : grid[0].length;
}
public boolean isEmpty() {
return grid == EMPTY_GRID;
}
public VectorXZ get(int indexX, int indexZ) {
createIfNecessary(indexX, indexZ);
return grid[indexX][indexZ];
}
@Override
@SuppressWarnings("unchecked")
public Iterator<VectorXZ> iterator() {
if (isEmpty()) {
return Collections.EMPTY_LIST.iterator();
} else {
List<Iterator<VectorXZ>> columnIterators =
new ArrayList<Iterator<VectorXZ>>(sizeX());
for (int x = 0; x < sizeX(); x++) {
for (int z = 0; z < sizeZ(); z++) {
createIfNecessary(x, z);
}
columnIterators.add(new ArrayIterator(grid[x]));
}
return new IteratorChain(columnIterators);
}
}
private void createIfNecessary(int indexX, int indexZ) {
if (grid[indexX][indexZ] == null) {
grid[indexX][indexZ] = new VectorXZ(
(startX + indexX) * sampleDistance,
(startZ + indexZ) * sampleDistance);
}
}
@Override
public String toString() {
if (isEmpty()) {
return "{0*0}";
} else {
return "{" + sizeX() + "*" + sizeZ() + ", start " + get(0,0) + "}";
}
}
}