/* JAI-Ext - OpenSource Java Advanced Image Extensions Library
* http://www.geo-solutions.it/
* Copyright 2014 GeoSolutions
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.geosolutions.jaiext.zonal;
import it.geosolutions.jaiext.iterators.RandomIterFactory;
import it.geosolutions.jaiext.range.Range;
import it.geosolutions.jaiext.range.Range.DataType;
import it.geosolutions.jaiext.range.RangeFactory;
import it.geosolutions.jaiext.stats.Statistics.StatsType;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.renderable.ParameterBlock;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.media.jai.BorderExtender;
import javax.media.jai.ImageLayout;
import javax.media.jai.JAI;
import javax.media.jai.OpImage;
import javax.media.jai.PlanarImage;
import javax.media.jai.ROI;
import javax.media.jai.ROIShape;
import javax.media.jai.RasterAccessor;
import javax.media.jai.RasterFormatTag;
import javax.media.jai.RenderedOp;
import javax.media.jai.iterator.RandomIter;
import javax.media.jai.iterator.RectIter;
import javax.media.jai.iterator.RectIterFactory;
import com.sun.media.jai.util.PropertyUtil;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.index.strtree.STRtree;
/**
* This class extends the {@link OpImage} class and executes the "ZonalStats" operation. This operation consists of calculating the image statistics
* on different locations, defined by their geometries, on the same image. In addition this operation supports the presence of ROI or No Data. The
* calculations are performed only in a rectangle that contains the union of all the input geometries. For every input geometry, a
* {@link ZoneGeometry} object is associated to it for storing its statistics. A spatial index is used for fast accessing the geometries that
* intersects the selected image pixel (in the case of overlapping). The final results can be returned by calling the getProperty() method with the
* ZonalStatsDescriptor.ZS_PROPERTY. This method returns a list containing all the ZoneGeometries objects associated with each input geometry object.
* The statistic results can be returned for each band or for each Class(if the classifier is present). It is important to remember that the
* classifier must be of integral data type.
*/
public class ZonalStatsOpImage extends OpImage {
/** ROI extender */
protected final static BorderExtender ROI_EXTENDER = BorderExtender
.createInstance(BorderExtender.BORDER_ZERO);
/** Logger object */
private static final Logger LOGGER = Logger.getLogger(ZonalStatsOpImage.class.getName());
/** Volatile variable indicating if the statistical computations has already been done or not */
private AtomicBoolean firstTime = new AtomicBoolean(true);
/** Spatial index for fast accessing the geometries that contain the selected pixel */
private final STRtree spatialIndex = new STRtree();
/** Boolean indicating if the classifier is present */
private final boolean classPresent;
/** Affine transformation for mapping the source image pixels to the classifiers pixels */
private AffineTransform inverseTrans;
/** Boolean indicating if a NoData Range is not used */
private final boolean notHasNoData;
/** Range object used for checking if a pixel is or not a NoData */
private final Range noData;
/** Boolean lookuptable used if no data are present */
private final boolean[] booleanLookupTable;
/** Rectangle containing the union of all the geometries */
private Rectangle union;
/** Source image bounds */
private Rectangle sourceBounds;
/** Classifier image bounds */
private Rectangle classBounds;
/** Random Iterator on the classifier image, if transformation is present */
private RandomIter randomIterator;
/** Array indicating the source image selected bands */
private int[] bands;
/** Band array length */
private int bandNum;
/** List of all the input geometries */
private List<ROI> rois;
/** Boolean indicating if the eventual transformation is not an Identity */
private boolean isNotIdentity;
/** Boolean indicating if the eventual rectIterator needs to be updated */
private final boolean updateIterator;
/** Classifier image */
private final RenderedImage classifier;
private List<Range> rangeList;
private final boolean ranges;
private final boolean localStats;
private Range rangeHelper;
private final boolean rangesNoClass;
private boolean hasROI;
// private RandomIter roiIter;
// private Rectangle roiBounds;
private boolean useROIAccessor;
private boolean caseA;
private boolean caseB;
private boolean caseC;
private PlanarImage srcROIImage;
private ROI srcROI;
private List<ZoneGeometry> zoneList;
private RenderedOp srcROIImgExt;
public ZonalStatsOpImage(RenderedImage source, ImageLayout layout, Map configuration,
RenderedImage classifier, AffineTransform transform, List<ROI> rois, Range noData,
ROI mask, boolean useROIAccessor, int[] bands, StatsType[] statsTypes,
double[] minBound, double[] maxBound, int[] numBins, List<Range> rangeData,
boolean localStats) {
super(vectorize(source), layout, configuration, true);
// Check if the classifier is present
classPresent = classifier != null && classifier instanceof RenderedImage;
// Check if the classifier is integral
if (classPresent) {
int classDataType = classifier.getSampleModel().getDataType();
if (!(classDataType == DataBuffer.TYPE_BYTE || classDataType == DataBuffer.TYPE_USHORT
|| classDataType == DataBuffer.TYPE_SHORT || classDataType == DataBuffer.TYPE_INT)) {
throw new IllegalArgumentException("Classifier must be integral");
}
this.classifier = classifier;
} else {
this.classifier = null;
}
// Calculation of the inverse transformation
classBounds = null;
isNotIdentity = false;
if (classPresent) {
// source image bounds
sourceBounds = createBounds(source);
if (transform == null) {
// If no transformation is set, the classifier bounds are the same of the image bounds
inverseTrans = new AffineTransform();
classBounds = sourceBounds;
} else {
try {
// If the transformation is set, then the source image bounds are mapped to the zone image bounds
inverseTrans = transform.createInverse();
classBounds = inverseTrans.createTransformedShape(sourceBounds).getBounds();
} catch (NoninvertibleTransformException ex) {
LOGGER.warning("The transformation matrix is non-invertible.");
}
}
isNotIdentity = !inverseTrans.isIdentity();
// Iterator on the classifier image bounds
if (isNotIdentity) {
randomIterator = RandomIterFactory.create(classifier, classBounds, false, true);
}
updateIterator = classPresent && !isNotIdentity;
} else {
updateIterator = false;
}
// Band selection
this.bands = bands;
this.bandNum = bands.length;
// Control on the bands number
SampleModel sm = source.getSampleModel();
// source data type
int dataType = sm.getDataType();
// Number of source bands
int numBands = sm.getNumBands();
if (bandNum > numBands) {
throw new IllegalArgumentException(
"The selected bands number cannot be greater than that of "
+ "image band number");
}
// If the band number is less or equal to 0, a new array containing only the first index is used.
if (bandNum <= 0) {
this.bands = new int[] { 0 };
this.bandNum = 1;
} else {
// If a band index is greater than the maximum band index, an exception is thrown
for (int i = 0; i < bandNum; i++) {
if (bands[i] > numBands) {
throw new IllegalArgumentException(
"Band index cannot be greater than the image band number");
}
}
}
// Complex Statistic types validation
double[] minBounds = null;
double[] maxBounds = null;
int[] numBinss = null;
boolean minBoundsNull = minBound == null;
boolean maxBoundsNull = maxBound == null;
boolean numBinsNull = numBins == null;
// Boolean indicating if one of the input arrays is null
boolean nullCondition = minBoundsNull || maxBoundsNull || numBinsNull;
// Check if the bounds or the bins are not null
for (int st = 0; st < statsTypes.length; st++) {
int statId = statsTypes[st].getStatsId();
if (statId > 6 && nullCondition) {
throw new IllegalArgumentException(
"If complex statistics are used, Bounds and Bin number should be defined");
}
}
if (!nullCondition) {
// Check if the bounds or the bins have the same length
int minLen = minBound.length;
int maxLen = maxBound.length;
int numLen = numBins.length;
if ((minLen + maxLen + numLen) != (minLen * 3)) {
throw new IllegalArgumentException("Bounds and Bin length must be equals");
}
// If the bounds and bins have a minor dimension than that of the bands array
// the bounds and the bin related to the index 0 are repeated on all the bound
// and bin array.
if (bandNum > minLen) {
double[] minBoundsTmp = new double[bands.length];
double[] maxBoundsTmp = new double[bands.length];
int[] numbinsTmp = new int[bands.length];
for (int i = 0; i < bands.length; i++) {
minBoundsTmp[i] = minBound[0];
maxBoundsTmp[i] = maxBound[0];
numbinsTmp[i] = numBins[0];
}
minBounds = minBoundsTmp;
maxBounds = maxBoundsTmp;
numBinss = numbinsTmp;
} else {
minBounds = minBound;
maxBounds = maxBound;
numBinss = numBins;
}
}
// If Range list is present then it is saved else a full Range is used
Range fullRange = RangeFactory.create(Double.NEGATIVE_INFINITY, true,
Double.POSITIVE_INFINITY, true, false);
List<Range> simpleRange = new ArrayList<Range>(1);
simpleRange.add(fullRange);
if (rangeData != null && !rangeData.isEmpty()) {
for (Range r : rangeData) {
DataType type = r.getDataType();
if (type.getDataType() != dataType) {
throw new IllegalArgumentException("Wrong Range data type");
}
}
this.rangeList = Collections.unmodifiableList(rangeData);
this.ranges = true;
this.localStats = localStats;
if (!localStats) {
this.rangeHelper = fullRange;
}
} else {
this.rangeHelper = fullRange;
this.ranges = false;
this.localStats = false;
}
rangesNoClass = ranges && !classPresent;
// Creation of a ZoneGeometry list, for storing the results
// Check if the rois are present. Otherwise the entire image statistics
// are calculated
if (rois == null) {
this.zoneList = new ArrayList<ZoneGeometry>(1);
this.rois = new ArrayList<ROI>();
if (sourceBounds == null) {
sourceBounds = createBounds(source);
}
ROI roi = new ROIShape(sourceBounds);
this.rois.add(roi);
// Bounds Union
union = new Rectangle(sourceBounds);
// Spatial index creation
Rectangle rect = roi.getBounds();
double minX = rect.getMinX();
double maxX = rect.getMaxX();
double minY = rect.getMinY();
double maxY = rect.getMaxY();
Envelope env = new Envelope(minX, maxX, minY, maxY);
// Creation of a new ZoneGeometry
ZoneGeometry geom;
if (ranges && localStats) {
geom = new ZoneGeometry(roi, rangeList, bands, statsTypes, classPresent, minBounds,
maxBounds, numBinss);
} else {
geom = new ZoneGeometry(roi, simpleRange, bands, statsTypes, classPresent,
minBounds, maxBounds, numBinss);
}
// Addition to the geometries list
spatialIndex.insert(env, geom);
zoneList.add(geom);
} else {
// Bounds Union
union = new Rectangle(rois.get(0).getBounds());
this.zoneList = new ArrayList<ZoneGeometry>(rois.size());
// Insertion of the zones to the spatial index and union of the bounds for every ROI/Zone object
for (ROI roi : rois) {
// Spatial index creation
Rectangle rect = roi.getBounds();
double minX = rect.getMinX();
double maxX = rect.getMaxX();
double minY = rect.getMinY();
double maxY = rect.getMaxY();
Envelope env = new Envelope(minX, maxX, minY, maxY);
// Union
union = union.union(rect);
// Creation of a new ZoneGeometry
ZoneGeometry geom;
if (ranges && localStats) {
geom = new ZoneGeometry(roi, rangeList, bands, statsTypes, classPresent,
minBounds, maxBounds, numBinss);
} else {
geom = new ZoneGeometry(roi, simpleRange, bands, statsTypes, classPresent,
minBounds, maxBounds, numBinss);
}
// Addition to the geometries list
spatialIndex.insert(env, geom);
zoneList.add(geom);
}
// Sets of the roi list
this.rois = rois;
}
// Building of the spatial index
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(0, 0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
spatialIndex.query(searchEnv);
// Check if No Data control must be done
if (noData != null) {
notHasNoData = false;
this.noData = noData;
} else {
notHasNoData = true;
this.noData = null;
}
// Creation of a boolean lookuptable indicating if the selected pixel is a NoData
// used only for byte images.
if (!notHasNoData && source.getSampleModel().getDataType() == DataBuffer.TYPE_BYTE) {
booleanLookupTable = new boolean[256];
for (int i = 0; i < booleanLookupTable.length; i++) {
byte value = (byte) i;
booleanLookupTable[i] = !noData.contains(value);
}
} else {
booleanLookupTable = null;
}
// Check if ROI control must be done
if (mask != null) {
hasROI = true;
// Roi object
srcROI = mask;
// The useRoiAccessor parameter is set
this.useROIAccessor = useROIAccessor;
if (useROIAccessor) {
// Creation of a PlanarImage containing the ROI data
srcROIImage = srcROI.getAsImage();
// Source Bounds
Rectangle srcRect = new Rectangle(source.getMinX(), source.getMinY(),
source.getWidth(), source.getHeight());
// Padding of the input ROI image in order to avoid the call of the getExtendedData() method
// ROI bounds are saved
Rectangle roiBounds = srcROIImage.getBounds();
int deltaX0 = (roiBounds.x - srcRect.x);
int leftP = deltaX0 > 0 ? deltaX0 : 0;
int deltaY0 = (roiBounds.y - srcRect.y);
int topP = deltaY0 > 0 ? deltaY0 : 0;
int deltaX1 = (srcRect.x + srcRect.width - roiBounds.x + roiBounds.width);
int rightP = deltaX1 > 0 ? deltaX1 : 0;
int deltaY1 = (srcRect.y + srcRect.height - roiBounds.y + roiBounds.height);
int bottomP = deltaY1 > 0 ? deltaY1 : 0;
// Extend the ROI image
ParameterBlock pb = new ParameterBlock();
pb.setSource(srcROIImage, 0);
pb.set(leftP, 0);
pb.set(rightP, 1);
pb.set(topP, 2);
pb.set(bottomP, 3);
pb.set(ROI_EXTENDER, 4);
srcROIImgExt = JAI.create("border", pb);
}
} else {
hasROI = false;
this.useROIAccessor = false;
srcROIImage = null;
}
// Definition of the possible cases that can be found
// caseA = no ROI nor No Data
// caseB = ROI present but No Data not present
// caseC = No Data present but ROI not present
// Last case not defined = both ROI and No Data are present
caseA = notHasNoData && !hasROI;
caseB = notHasNoData && hasROI;
caseC = !notHasNoData && !hasROI;
}
/**
* Creates a rectangle from the bounds of the specified image.
*/
private Rectangle createBounds(RenderedImage source) {
return new Rectangle(source.getMinX(), source.getMinY(), source.getWidth(), source.getHeight());
}
public Raster computeTile(int tileX, int tileY) {
// Selection of the tile associated with the tile x and y indexes
Raster tile = getSourceImage(0).getTile(tileX, tileY);
// Selection of the tile bounds
Rectangle tileRect = tile.getBounds();
// Boolean indicating if the tile is inside the ROI
boolean insideROIifPresent = true;
synchronized (this) {
insideROIifPresent = (hasROI && srcROI.intersects(tileRect) || !hasROI);
}
// Check if the tile is inside the geometry bound-union
if (union.intersects(tileRect) && insideROIifPresent) {
// STATISTICAL ELABORATIONS
// selection of the format tags
RasterFormatTag[] formatTags = getFormatTags();
// Selection of the active calculation area
Rectangle computableArea = union.intersection(tileRect);
// creation of the RasterAccessor
RasterAccessor src = new RasterAccessor(tile, computableArea, formatTags[0],
getSourceImage(0).getColorModel());
// ROI calculations if roiAccessor is used
RasterAccessor roi = null;
if (useROIAccessor) {
// Note that the getExtendedData() method is not called because the input images are padded.
// For each image there is a check if the rectangle is contained inside the source image;
// if this not happen, the data is taken from the padded image.
Raster roiRaster = null;
if(srcROIImage.getBounds().contains(computableArea)){
roiRaster = srcROIImage.getData(computableArea);
}else{
roiRaster = srcROIImgExt.getData(computableArea);
}
// creation of the rasterAccessor
roi = new RasterAccessor(roiRaster, computableArea,
RasterAccessor.findCompatibleTags(new RenderedImage[] { srcROIImage },
srcROIImage)[0], srcROIImage.getColorModel());
}
// Image dataType
int dataType = tile.getSampleModel().getDataType();
// From the data type is possible to choose the right calculation method
switch (dataType) {
case DataBuffer.TYPE_BYTE:
byteLoop(src, computableArea, tileX, tileY, roi);
break;
case DataBuffer.TYPE_USHORT:
ushortLoop(src, computableArea, tileX, tileY, roi);
break;
case DataBuffer.TYPE_SHORT:
shortLoop(src, computableArea, tileX, tileY, roi);
break;
case DataBuffer.TYPE_INT:
intLoop(src, computableArea, tileX, tileY, roi);
break;
case DataBuffer.TYPE_FLOAT:
floatLoop(src, computableArea, tileX, tileY, roi);
break;
case DataBuffer.TYPE_DOUBLE:
doubleLoop(src, computableArea, tileX, tileY, roi);
break;
default:
throw new IllegalArgumentException("Wrong data type");
}
}
return tile;
}
// NOTE: the statistic calculation is done in a synchronized block for avoiding race conditions
private void byteLoop(RasterAccessor src, Rectangle computableArea, int tileX, int tileY,
RasterAccessor roi) {
// Source RasterAccessor initial parameters
final int srcX = src.getX();
final int srcY = src.getY();
byte srcData[][] = src.getByteDataArrays();
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int[] srcBandOffsets = src.getBandOffsets();
int srcPixelStride = src.getPixelStride();
int srcScanlineStride = src.getScanlineStride();
RectIter rectIterator = null;
if (updateIterator) {
Raster ras = classifier.getTile(tileX, tileY);
rectIterator = RectIterFactory.create(ras, computableArea);
rectIterator.startBands();
rectIterator.startLines();
}
final byte[] roiDataArray;
final int roiScanLineStride;
final int roiDataLength;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiScanLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiScanLineStride = 0;
roiDataLength = 0;
}
// NO DATA AND ROI NOT PRESENT
if (caseA) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
byte value = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
int sample = value&0xFF;
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(value)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId, rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ONLY ROI PRESENT
} else if (caseB) {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]]&0xFF;
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((byte)sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]]&0xFF;
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((byte)sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
// ONLY NO DATA PRESENT
} else if (caseC) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]]&0xFF;
// NoData check
if (booleanLookupTable[sample]) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((byte)sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ROI AND NO DATA ARE PRESENT
} else {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]]& 0xFF;
// NoData check
if (booleanLookupTable[sample ]) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((byte)sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]]& 0xFF;
// NoData check
if (booleanLookupTable[sample ]) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((byte)sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
}
}
private void ushortLoop(RasterAccessor src, Rectangle computableArea, int tileX, int tileY,
RasterAccessor roi) {
// Source RasterAccessor initial parameters
final int srcX = src.getX();
final int srcY = src.getY();
short srcData[][] = src.getShortDataArrays();
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int[] srcBandOffsets = src.getBandOffsets();
int srcPixelStride = src.getPixelStride();
int srcScanlineStride = src.getScanlineStride();
RectIter rectIterator = null;
if (updateIterator) {
Raster ras = classifier.getTile(tileX, tileY);
rectIterator = RectIterFactory.create(ras, computableArea);
rectIterator.startBands();
rectIterator.startLines();
}
final byte[] roiDataArray;
final int roiScanLineStride;
final int roiDataLength;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiScanLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiScanLineStride = 0;
roiDataLength = 0;
}
// NO DATA AND ROI NOT PRESENT
if (caseA) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]] & 0xFFFF;
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((short) sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId, rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ONLY ROI PRESENT
} else if (caseB) {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]] & 0xFFFF;
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((short) sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]] & 0xFFFF;
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((short) sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
// ONLY NO DATA PRESENT
} else if (caseC) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]] & 0xFFFF;
// NoData check
if (!noData.contains((short) sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((short) sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ROI AND NO DATA ARE PRESENT
} else {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]] & 0xFFFF;
// NoData check
if (!noData.contains((short) sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((short) sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]] & 0xFFFF;
// NoData check
if (!noData.contains((short) sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains((short) sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
}
}
private void shortLoop(RasterAccessor src, Rectangle computableArea, int tileX, int tileY,
RasterAccessor roi) {
// Source RasterAccessor initial parameters
final int srcX = src.getX();
final int srcY = src.getY();
short srcData[][] = src.getShortDataArrays();
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int[] srcBandOffsets = src.getBandOffsets();
int srcPixelStride = src.getPixelStride();
int srcScanlineStride = src.getScanlineStride();
RectIter rectIterator = null;
if (updateIterator) {
Raster ras = classifier.getTile(tileX, tileY);
rectIterator = RectIterFactory.create(ras, computableArea);
rectIterator.startBands();
rectIterator.startLines();
}
final byte[] roiDataArray;
final int roiScanLineStride;
final int roiDataLength;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiScanLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiScanLineStride = 0;
roiDataLength = 0;
}
// NO DATA AND ROI NOT PRESENT
if (caseA) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
short sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId, rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ONLY ROI PRESENT
} else if (caseB) {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
short sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
short sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
// ONLY NO DATA PRESENT
} else if (caseC) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
short sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ROI AND NO DATA ARE PRESENT
} else {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
short sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
short sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
}
}
private void intLoop(RasterAccessor src, Rectangle computableArea, int tileX, int tileY,
RasterAccessor roi) {
// Source and ROI RasterAccessor initial parameters
final int srcX = src.getX();
final int srcY = src.getY();
int srcData[][] = src.getIntDataArrays();
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int[] srcBandOffsets = src.getBandOffsets();
int srcPixelStride = src.getPixelStride();
int srcScanlineStride = src.getScanlineStride();
RectIter rectIterator = null;
if (updateIterator) {
Raster ras = classifier.getTile(tileX, tileY);
rectIterator = RectIterFactory.create(ras, computableArea);
rectIterator.startBands();
rectIterator.startLines();
}
final byte[] roiDataArray;
final int roiScanLineStride;
final int roiDataLength;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiScanLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiScanLineStride = 0;
roiDataLength = 0;
}
// NO DATA AND ROI NOT PRESENT
if (caseA) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId, rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ONLY ROI PRESENT
} else if (caseB) {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
// ONLY NO DATA PRESENT
} else if (caseC) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ROI AND NO DATA ARE PRESENT
} else {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
int sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
}
}
private void floatLoop(RasterAccessor src, Rectangle computableArea, int tileX, int tileY,
RasterAccessor roi) {
// Source RasterAccessor initial parameters
final int srcX = src.getX();
final int srcY = src.getY();
float srcData[][] = src.getFloatDataArrays();
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int[] srcBandOffsets = src.getBandOffsets();
int srcPixelStride = src.getPixelStride();
int srcScanlineStride = src.getScanlineStride();
RectIter rectIterator = null;
if (updateIterator) {
Raster ras = classifier.getTile(tileX, tileY);
rectIterator = RectIterFactory.create(ras, computableArea);
rectIterator.startBands();
rectIterator.startLines();
}
final byte[] roiDataArray;
final int roiScanLineStride;
final int roiDataLength;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiScanLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiScanLineStride = 0;
roiDataLength = 0;
}
// NO DATA AND ROI NOT PRESENT
if (caseA) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
float sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId, rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ONLY ROI PRESENT
} else if (caseB) {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
float sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
float sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
// ONLY NO DATA PRESENT
} else if (caseC) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
float sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ROI AND NO DATA ARE PRESENT
} else {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
float sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
float sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
}
}
private void doubleLoop(RasterAccessor src, Rectangle computableArea, int tileX, int tileY,
RasterAccessor roi) {
// Source RasterAccessor initial parameters
final int srcX = src.getX();
final int srcY = src.getY();
double srcData[][] = src.getDoubleDataArrays();
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int[] srcBandOffsets = src.getBandOffsets();
int srcPixelStride = src.getPixelStride();
int srcScanlineStride = src.getScanlineStride();
RectIter rectIterator = null;
if (updateIterator) {
Raster ras = classifier.getTile(tileX, tileY);
rectIterator = RectIterFactory.create(ras, computableArea);
rectIterator.startBands();
rectIterator.startLines();
}
final byte[] roiDataArray;
final int roiScanLineStride;
final int roiDataLength;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiScanLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiScanLineStride = 0;
roiDataLength = 0;
}
// NO DATA AND ROI NOT PRESENT
if (caseA) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
double sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId, rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ONLY ROI PRESENT
} else if (caseB) {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
double sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the classId value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the classId point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
double sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
// ONLY NO DATA PRESENT
} else if (caseC) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y, 0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
double sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId, range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
// ROI AND NO DATA ARE PRESENT
} else {
if (useROIAccessor) {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// roi y position
int posYroi = y * roiScanLineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI index position
int windex = x + posYroi;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
if (w == 0) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
double sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
} else {
// Cycle on the y axis
for (int y = 0; y < srcHeight; y++) {
if (updateIterator) {
rectIterator.startPixels();
}
// y position on the source data array
int posy = y * srcScanlineStride;
// Cycle on the x axis
for (int x = 0; x < srcWidth; x++) {
// x position on the source data array
int posx = x * srcPixelStride;
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// check on containment
if (!union.contains(x0, y0)) {
// Update of the RectIterator
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// ROI value
boolean insideROI = false;
synchronized (this) { // HACK
insideROI = srcROI.contains(x0, y0);
}
if (!insideROI) {
if (updateIterator) {
rectIterator.nextPixel();
}
continue;
}
// Coordinate object creation for the spatial indexing
Coordinate p1 = new Coordinate(x0, y0);
// Envelope associated to the coordinate object
Envelope searchEnv = new Envelope(p1);
// Query on the geometry list
List<ZoneGeometry> geomList = spatialIndex.query(searchEnv);
// classId classifier initial value
int classId = 0;
// If the classifier is present then the zone value is taken
if (classPresent) {
// Selection of the initial point
Point pointSrc = new Point(x0, y0);
// Initialization of the zone point
Point pointClass = new Point();
// Source point inverse transformation for finding the related zone point
try {
if (isNotIdentity) {
inverseTrans.inverseTransform(pointSrc, pointClass);
// Selection of the classId point
classId = randomIterator.getSample(pointClass.x, pointClass.y,
0);
} else {
// Selection of the classId point
classId = rectIterator.getSample();
rectIterator.nextPixel();
}
} catch (NoninvertibleTransformException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
// Cycle on all the geometries found
for (ZoneGeometry zoneGeo : geomList) {
ROI geometry = zoneGeo.getROI();
// if every geometry really contains the selected point
boolean contains = false;
synchronized (zoneGeo) { // HACK
contains = geometry.contains(x0, y0);
}
if (contains) {
// Cycle on the selected Bands
for (int i = 0; i < bandNum; i++) {
double sample = srcData[bands[i]][posx + posy
+ srcBandOffsets[bands[i]]];
// NoData check
if (!noData.contains(sample)) {
// Update of all the statistics
// If a range list is present then the sample is checked if it is inside the range
if (rangesNoClass) {
for (Range range : rangeList) {
if (range.contains(sample)) {
// For local statistics the pixel is checked for every range
if (localStats) {
zoneGeo.add(sample, bands[i], classId,
range);
} else {
// For non local statistics the pixel when the pixel is contained inside a singular range
// it is added to the statistic container
zoneGeo.add(sample, bands[i], classId,
rangeHelper);
break;
}
}
}
} else {
zoneGeo.add(sample, bands[i], classId, rangeHelper);
}
}
}
}
}
}
if (updateIterator) {
rectIterator.nextLine();
}
}
}
}
}
/** {@link OpImage} method that returns the destination image bounds, because source and destination images are equals */
@Override
public Rectangle mapDestRect(Rectangle destRect, int index) {
return destRect;
}
/** {@link OpImage} method that returns the source image bounds, because source and destination images are equals */
@Override
public Rectangle mapSourceRect(Rectangle sourceRect, int index) {
return sourceRect;
}
/**
* Returns a list of property names that are recognized by this image.
*
* @return An array of <code>String</code>s containing valid property names.
*/
public String[] getPropertyNames() {
// Get statistics names and names from superclass.
String[] statsNames = new String[] { ZonalStatsDescriptor.ZS_PROPERTY };
String[] superNames = super.getPropertyNames();
// Return stats names if not superclass names.
if (superNames == null) {
return statsNames;
}
// Check for overlap between stats names and superclass names.
List extraNames = new ArrayList();
for (int i = 0; i < statsNames.length; i++) {
String prefix = statsNames[i];
String[] names = PropertyUtil.getPropertyNames(superNames, prefix);
if (names != null) {
for (int j = 0; j < names.length; j++) {
if (names[j].equalsIgnoreCase(prefix)) {
extraNames.add(prefix);
}
}
}
}
// If no overlap then return.
if (extraNames.size() == 0) {
return superNames;
}
// Combine superclass and extra names.
String[] propNames = new String[superNames.length + extraNames.size()];
System.arraycopy(superNames, 0, propNames, 0, superNames.length);
int offset = superNames.length;
for (int i = 0; i < extraNames.size(); i++) {
propNames[offset++] = (String) extraNames.get(i);
}
// Return combined name set.
return propNames;
}
/**
* This method is used if the user needs to perform again the statistical calculations.
*/
public synchronized void clearStatistic() {
firstTime.set(true);
}
/**
* Computes and returns all tiles in the image. The tiles are returned in a sequence corresponding to the row-major order of their respective tile
* indices. The returned array may of course be ignored, e.g., in the case of a subclass which caches the tiles and the intent is to force their
* computation. This method is overridden such that can be invoked only one time by using a flag for avoiding unnecessary computations.
*/
public Raster[] getTiles() {
if (firstTime.getAndSet(false)) {
//return getTiles(getTileIndices(getBounds()));
Point[] points = getTileIndices(union);
if(points!=null){
return getTiles(points);
}else{
return null;
}
} else {
return null;
}
}
/**
* Get the specified property.
* <p>
* Use this method to retrieve the calculated statistics as an array per band and per statistic types.
*
* @param name property name
*
* @return the requested property
*/
@Override
public Object getProperty(String name) {
// If the specified property is "JAI-EXT.stats", the calculations are performed.
if (ZonalStatsDescriptor.ZS_PROPERTY.equalsIgnoreCase(name)) {
getTiles();
//List<ZoneGeometry> copy = new ArrayList<ZoneGeometry>(zoneList);
return Collections.unmodifiableList(zoneList);
} else {
return super.getProperty(name);
}
}
@Override
public synchronized void dispose() {
if(srcROIImgExt != null) {
srcROIImgExt.dispose();
}
super.dispose();
}
}