/** * For generating Geographically Weighted Statistics * Copyright (C) 2005 Andy Turner, CCG, University of Leeds, UK. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ package uk.ac.leeds.ccg.andyt.gws.core; // java dependencies import java.util.HashSet; import java.awt.geom.Point2D; import java.math.BigDecimal; import java.util.Iterator; // uk.ac.leeds.ccg.andyt.grids dependencies import uk.ac.leeds.ccg.andyt.grids.core.Grid2DSquareCellDouble; import uk.ac.leeds.ccg.andyt.grids.core.Grid2DSquareCellDoubleFactory; import uk.ac.leeds.ccg.andyt.grids.process.Grid2DSquareCellProcessor; import uk.ac.leeds.ccg.andyt.grids.utilities.Kernel; // uk.ac.leeds.ccg.andyt.gws dependencies import uk.ac.leeds.ccg.andyt.gws.utilities.Utilities; import uk.ac.leeds.ccg.andyt.gws.utilities.Point2DBigDecimal; /** * TODO: * docs */ public class AdaptiveGWS extends GWS { private Point2D.Double[] t0Points; private HashSet t0PointIDs; private Point2DDouble_DistanceDouble_IDInt[] t0NearestPoint2DDouble_DistanceDouble_IDInts; private HashSet t0InSetDistanceIDs; private int t0Counter; private Point2D.Double[] t1Points; private HashSet t1PointIDs; private Point2DDouble_DistanceDouble_IDInt[] t1NearestPoint2DDouble_DistanceDouble_IDInts; private HashSet t1InSetDistanceIDs; private int t1Counter; private double maxDistanceToNthNearestNeighbour; private int numberOfPoints; private int numberOfPointsFactor; private double setDistance; // Kernel parameters private double sumAdaptiveKernelWeights; private int precision; public AdaptiveGWS() {} /** * Returns an Grid2DSquareCellDouble thats values are the sums of * adaptiveKernelWeights for cells in grid2DSquareCellDouble. The weights are based on Points * in points in a nearest neighbourhood given by numberOfPoints to each cell * in grid2DSquareCellDouble. The kernel shape is defined by weightIntersect and weightFactor. * The kernel volume is given by sumAdaptiveKernelWeights approximated using * precision. This method can be slow. Each cell in grid is calculated by * going through all t0Points. If this method is too slow then try using * getAdaptiveKernelWeights( Point2D.Double[], * Grid2DSquareCellDoubleFactory, * AbstractGrid2DSquareCellDoube, int, int, * double, double, double, int, double ) * @param t0Points the Point2D.Double[] from which kernel weights are * calculated * @param grid2DSquareCellDoubleFactory the Grid2DSquareCellDoubleFactory used to * generate the result * @param grid an Grid2DSquareCellDouble defining the frame and * extent processed * @param numberOfPoints the number of points accounted for in each kernel * calculation * @param weightIntersect an arbitrary double * @param weightFactor defines the shape of the kernel distance decay * @param sumAdaptiveKernelWeights the volume for the kernel * @param precision the precision with which the kernels volume is * approximated */ public Grid2DSquareCellDouble getAdaptiveKernelWeights( Point2D.Double[] t0Points, Grid2DSquareCellDoubleFactory grid2DSquareCellDoubleFactory, Grid2DSquareCellDouble grid2DSquareCellDouble, int numberOfPoints, double weightIntersect, double weightFactor, double sumAdaptiveKernelWeights, int precision ) { this.t0Points = t0Points; this.numberOfPoints = numberOfPoints; this.weightIntersect = weightIntersect; this.weightFactor = weightFactor; this.sumAdaptiveKernelWeights = sumAdaptiveKernelWeights; this.precision = precision; this.numberOfPointsFactor = 1; Grid2DSquareCellDouble result = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( grid2DSquareCellDouble ); long ncols = result.getNcols(); long nrows = result.getNrows(); //double xllcorner = grid2DSquareCellDouble.getXllcorner(); //double yllcorner = grid2DSquareCellDouble.getYllcorner(); //double gridWidth = grid2DSquareCellDouble.getWidth(); //double gridHeight = grid2DSquareCellDouble.getHeight(); BigDecimal[] dimensions = grid2DSquareCellDouble.getDimensions(); t0NearestPoint2DDouble_DistanceDouble_IDInts = null; t0PointIDs = new HashSet(); double sumWeight; // Go around the edge, calculating the sum of adaptive kernel weights // and adding to t0PointIDs. // left column col = 0L; for ( row = 0L; row < nrows; row ++ ) { doCell1( result ); } // right column col = ncols - 1L; for ( row = 0L; row < nrows; row ++ ) { doCell1( result ); } // top row row = 0L; for ( col = 0L; col < ncols; col ++ ) { doCell1( result ); } // bottom row row = nrows - 1L; for ( col = 0L; col < ncols; col ++ ) { doCell1( result ); } // Add all points in the grid to t0PointIDs //t0PointIDs.addAll( Utilities.getInBoundPointIDs( t0Points, xllcorner, yllcorner, xllcorner + gridWidth, yllcorner + gridHeight ) ); t0PointIDs.addAll( Utilities.getPointsIntersected( t0Points, dimensions ) ); // Calculate and set all non-edge cells Point2D.Double point2DDouble = null; double kernelVolume = Kernel.getKernelVolume( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, precision, weightIntersect, weightFactor ); for ( row = 1; row < nrows - 1; row ++ ) { for ( col = 1; col < ncols - 1; col ++ ) { sumWeight = 0.0d; point2DDouble = new Point2D.Double( grid2DSquareCellDouble.getCellXDouble( col, this.handleOutOfMemoryErrorFalse ), grid2DSquareCellDouble.getCellYDouble( row, this.handleOutOfMemoryErrorFalse ) ); t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0PointIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); for ( int k = 0; k < numberOfPoints; k ++ ) { //sumWeight += uk.ac.leeds.ccg.andyt.grids.Utilities.getAdaptiveKernelWeight( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distance, sumAdaptiveKernelWeights, precision, weightIntersect, weightFactor ); sumWeight += Kernel.getKernelWeight( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); } //result.setCell( row, col, sumWeight ); result.setCell( row, col, sumWeight * this.sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } } return result; } /** * For doing the edge cells of * getAdaptiveKernelWeights( Point2D.Double[], * Grid2DSquareCellDoubleFactory, * AbstractGrid2DSquareCellDoube, int, double, * double, double, int ) */ private void doCell1( Grid2DSquareCellDouble grid2DSquareCellDouble ) { double sumWeight = 0.0d; Point2D.Double point2DDouble = new Point2D.Double( grid2DSquareCellDouble.getCellXDouble( col, this.handleOutOfMemoryErrorFalse ), grid2DSquareCellDouble.getCellYDouble( row, this.handleOutOfMemoryErrorFalse ) ); t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); double kernelVolume = Kernel.getKernelVolume( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, precision, weightIntersect, weightFactor ); for ( int k = 0; k < numberOfPoints; k ++ ) { t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); //sumWeight += Kernel.getAdaptiveKernelWeight( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distance, sumAdaptiveKernelWeights, precision, weightIntersect, weightFactor ); sumWeight += Kernel.getKernelWeight( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); } //grid2DSquareCellDouble.setCell( row, col, sumWeight ); grid2DSquareCellDouble.setCell( row, col, sumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } /** * Returns a Grid2DSquareCellDouble thats values are the sums of * adaptiveKernelWeights for cells in grid2DSquareCellDouble. The weights are based on Points * in points in a nearest neighbourhood given by numberOfPoints to each cell * in grid2DSquareCellDouble. The kernel shape is defined by weightIntersect and weightFactor. * The kernel volume is given by sumAdaptiveKernelWeights approximated using * precision. The parameter setDistance is used to speed up processing by * keeping a memory of what points have recently been examined. If * sufficient then this memory is sometimes (when safe) used to calculate * the weight for the next cell. A more basic way to process would be to go * through the entire points array for each cell as in * getAdaptiveKernelWeights( Point2D.Double[], * Grid2DSquareCellDoubleFactory, * Grid2DSquareCellDoubeAbstract, int, double, * double, double, int ) * however this can be slow (especially since a spatial indexing (or a * spatial database) is not being used. This method is a speed up that will * return the same answer as the above mentioned method. The main speed up * comes from keeping a memory of a larger number of nearby points and using * this when it can be guaranteed to work when calculating the adaptive * kernel weight sum. The parameters setDistance and numberOfPointsFactor * control the size of the memory. If setDistance and numberOfPointsFactor * are set too high this method may be slow. Typically: numberOfPointsFactor * will be between 1 and 10 depending on numberOfPoints; and, setDistance * will be greater than the grid cellsize. * @param points the Point2D.Double[] from which kernel weights are * calculated * @param grid2DSquareCellDoubleFactory the Grid2DSquareCellDoubleFactory used to * generate the result * @param grid an Grid2DSquareCellDouble defining the frame and * extent processed * @param numberOfPoints the number of points accounted for in each kernel * calculation * @param numberOfPointsFactor a memory control * @param weightIntersect an arbitrary double * @param weightFactor defines the shape of the kernel distance decay * @param sumAdaptiveKernelWeights the volume for the kernel * @param precision the precision with which the kernels volume is * approximated * @param setDistance a memory control */ public Grid2DSquareCellDouble getAdaptiveKernelWeights( Point2D.Double[] t0Points, Grid2DSquareCellDoubleFactory grid2DSquareCellDoubleFactory, Grid2DSquareCellDouble grid2DSquareCellDouble, int numberOfPoints, int numberOfPointsFactor, double weightIntersect, double weightFactor, double sumAdaptiveKernelWeights, int precision, double setDistance ) { this.t0Points = t0Points; this.numberOfPoints = numberOfPoints; this.numberOfPointsFactor = numberOfPointsFactor; this.weightIntersect = weightIntersect; this.weightFactor = weightFactor; this.sumAdaptiveKernelWeights = sumAdaptiveKernelWeights; this.precision = precision; this.setDistance = setDistance; Grid2DSquareCellDouble result = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( grid2DSquareCellDouble ); long ncols = grid2DSquareCellDouble.getNcols(); long nrows = grid2DSquareCellDouble.getNrows(); BigDecimal[] dimensions = grid2DSquareCellDouble.getDimensions(); this.cellsizeDouble = grid2DSquareCellDouble.getCellsizeDouble( this.handleOutOfMemoryErrorFalse ); double sumWeight; t0PointIDs = new HashSet(); //System.out.println( "Calculate for the first cell" ); row = 0; col = 0; Point2D.Double point2DDouble = new Point2D.Double( grid2DSquareCellDouble.getCellX( col, this.handleOutOfMemoryErrorFalse ), grid2DSquareCellDouble.getCellY( row, this.handleOutOfMemoryErrorFalse ) ); Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; sumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, precision, weightIntersect, weightFactor ); for ( int k = 0; k < numberOfPoints; k ++ ) { //sumWeight += Kernel.getAdaptiveKernelWeight( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distance, sumAdaptiveKernelWeights, precision, weightIntersect, weightFactor ); sumWeight += Kernel.getKernelWeight( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } //result.setCell( row, col, sumWeight ); result.setCell( row, col, sumWeight * this.sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); t0Counter = 1; //System.out.println( "Continue down the first column..." ); //col = 0; for ( row = 1; row < nrows; row ++ ) { doCell2( result ); } //System.out.println( "Continue along bottom row..." ); row = nrows - 1; for ( col = 0; col < ncols; col ++ ) { doCell2( result ); } //System.out.println( "Continue up right column..." ); col = ncols - 1; for ( row = nrows - 2; row > -1; row -- ) { doCell2( result ); } //System.out.println( "Continue right along top row..." ); row = 0; for ( col = ncols - 2; col > 0; col -- ) { doCell2( result ); } //System.out.println( "Add all points in bounds to t0PointIDs..." ); //t0PointIDs.addAll( Utilities.getInBoundPointIDs( t0Points, xllcorner, yllcorner, xllcorner + gridWidth, yllcorner + gridHeight ) ); t0PointIDs.addAll( Utilities.getPointsIntersected( t0Points, dimensions ) ); //System.out.println( "Calculate remaining cells..." ); // Row prime order processing boolean alternator = true; for ( row = 1; row < nrows - 1; row ++ ) { if ( alternator ) { alternator = false; // go right along row for ( col = 1; col < ncols - 1; col ++ ) { doCell3( result ); } } else { alternator = true; // go left along row for ( col = ncols - 2; col > 0; col -- ) { doCell3( result ); } } //System.out.println( "Done row " + row ); } return result; } /** * For doing edge cells in * getAdaptiveKernelWeights( Point2D.Double[], * Grid2DSquareCellDoubleFactory, * AbstractGrid2DSquareCellDoube, int, int, * double, double, double, int, double ) */ private void doCell2( Grid2DSquareCellDouble grid2DSquareCellDouble ) { double sumWeight; Point2D.Double point2DDouble = new Point2D.Double( grid2DSquareCellDouble.getCellX( col, this.handleOutOfMemoryErrorFalse ), grid2DSquareCellDouble.getCellY( row, this.handleOutOfMemoryErrorFalse ) ); maxDistanceToNthNearestNeighbour = t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble; if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) > maxDistanceToNthNearestNeighbour ) { if ( setDistance >= t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck0 = Math.max( setDistance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0NearestPoint2DDouble_DistanceDouble_IDInts, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, distanceCheck0 ); } t0Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); t0Counter ++; } else { // Recalculate as initally done Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; t0Counter = 1; } } sumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, precision, weightIntersect, weightFactor ); for ( int k = 0; k < numberOfPoints; k ++ ) { //sumWeight += Kernel.getAdaptiveKernelWeight( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distance, sumAdaptiveKernelWeights, precision, weightIntersect, weightFactor ); sumWeight += Kernel.getKernelWeight( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } //grid2DSquareCellDouble.setCell( row, col, sumWeight ); grid2DSquareCellDouble.setCell( row, col, sumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } /** * For doing internal cells in * getAdaptiveKernelWeights( Point2D.Double[], * Grid2DSquareCellDoubleFactory, * AbstractGrid2DSquareCellDoube, int, int, * double, double, double, int, double ) */ private void doCell3( Grid2DSquareCellDouble grid2DSquareCellDouble ) { Point2D.Double point2DDouble = new Point2D.Double( grid2DSquareCellDouble.getCellXDouble( col, this.handleOutOfMemoryErrorFalse ), grid2DSquareCellDouble.getCellYDouble( row, this.handleOutOfMemoryErrorFalse ) ); maxDistanceToNthNearestNeighbour = t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble; if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( this.cellsizeDouble * 2.0d * ( double ) t0Counter ) > maxDistanceToNthNearestNeighbour ) { if ( setDistance >= t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck0 = Math.max( setDistance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0NearestPoint2DDouble_DistanceDouble_IDInts, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, distanceCheck0 ); } t0Counter ++; } else { if ( setDistance - ( this.cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); t0Counter ++; } else { // Recalculate as initally done Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t0PointIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; t0Counter = 1; } } double sumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, precision, weightIntersect, weightFactor ); for ( int k = 0; k < numberOfPoints; k ++ ) { //sumWeight += uk.ac.leeds.ccg.andyt.grids.Utilities.getAdaptiveKernelWeight( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distance, sumAdaptiveKernelWeights, precision, weightIntersect, weightFactor ); sumWeight += Kernel.getKernelWeight( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); } //grid2DSquareCellDouble.setCell( row, col, sumWeight ); grid2DSquareCellDouble.setCell( row, col, sumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } /** * Returns an Grid2DSquareCellDouble[] The first element of which is * the Adaptive Kernel Weights for t0Points, the second element of which is * the Adaptive Kernel Weights for t1Points (where the width of the kernel * is the radius of the circle which contains at least numberOfPoints in * t0Points AND at least numberOfPoints points in t1Points). * @param t0Points one of the two Point2D.Double[] from which kernel weights * are calculated * @param t1Points one of the two Point2D.Double[] from which kernel weights * are calculated * @param grid2DSquareCellDoubleFactory the Grid2DSquareCellDoubleFactory used to * generate the result * @param grid an Grid2DSquareCellDouble defining the frame and * extent processed * @param numberOfPoints the number of points accounted for in each kernel * calculation * @param weightIntersect an arbitrary double * @param weightFactor defines the shape of the kernel distance decay * @param xmin the minimum x-coordinate for any point considered * @param ymin the minimum y-coordinate for any point considered * @param xmax the maximum x-coordinate for any point considered * @param ymax the maximum y-coordinate for any point considered * @param sumAdaptiveKerneWeights the volume under the kernel to be * preserved * @param precision the precision with which the kernel volume is estimated */ public Grid2DSquareCellDouble[] getAdaptiveKernelWeights( Point2D.Double[] t0Points, Point2D.Double[] t1Points, Grid2DSquareCellDoubleFactory grid2DSquareCellDoubleFactory, Grid2DSquareCellDouble grid2DSquareCellDouble, int numberOfPoints, int numberOfPointsFactor, double setDistance, double weightIntersect, double weightFactor, double sumAdaptiveKernelWeights, int precision ) { this.t0Points = t0Points; this.t1Points = t1Points; this.numberOfPoints = numberOfPoints; this.numberOfPointsFactor = numberOfPointsFactor; this.weightIntersect = weightIntersect; this.weightFactor = weightFactor; this.sumAdaptiveKernelWeights = sumAdaptiveKernelWeights; this.precision = precision; this.setDistance = setDistance; Grid2DSquareCellDouble[] result = new Grid2DSquareCellDouble[ 2 ]; result[ 0 ] = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( grid2DSquareCellDouble ); result[ 1 ] = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( grid2DSquareCellDouble ); long ncols = grid2DSquareCellDouble.getNcols(); long nrows = grid2DSquareCellDouble.getNrows(); BigDecimal[] dimensions = grid2DSquareCellDouble.getDimensions(); this.cellsizeDouble = grid2DSquareCellDouble.getCellsizeDouble( this.handleOutOfMemoryErrorFalse ); this.t0PointIDs = new HashSet(); this.t1PointIDs = new HashSet(); //System.out.println( "Calculate first cell..." ); row = 0; col = 0; Point2D.Double point2DDouble = new Point2D.Double( grid2DSquareCellDouble.getCellX( col, this.handleOutOfMemoryErrorFalse ), grid2DSquareCellDouble.getCellY( row, this.handleOutOfMemoryErrorFalse ) ); Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; Object[] t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t1NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t1InSetDistanceIDs = ( HashSet ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; maxDistanceToNthNearestNeighbour = Math.max( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, t1NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble ); // Get other points if necessary if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { // Since t0Counter = 0 if ( setDistance >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0InSetDistanceIDs, t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { // Since t1Counter = 0 if ( setDistance >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1InSetDistanceIDs, t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } // Calculate and set weights double t0SumWeight = 0.0d; double t1SumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( maxDistanceToNthNearestNeighbour, precision, weightIntersect, weightFactor ); for ( int k = 0; k < t0NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t0SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); this.t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { this.t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } for ( int k = 0; k < t1NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t1SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); this.t1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { this.t1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } result[ 0 ].setCell( row, col, t0SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); result[ 1 ].setCell( row, col, t1SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); // Set t0Counter and t1Counter t0Counter = 1; t1Counter = 1; //System.out.println( "Continue down first column..." ); col = 0; for ( row = 1; row < nrows; row ++ ) { doCell4( result[ 0 ], result[ 1 ] ); } //System.out.println( "Continue along bottom row..." ); row = nrows - 1; for ( col = 1; col < ncols; col ++ ) { doCell4( result[ 0 ], result[ 1 ] ); } //System.out.println( "Continue up right column..." ); col = ncols - 1; for ( row = nrows - 2; row > -1; row -- ) { doCell4( result[ 0 ], result[ 1 ] ); } //System.out.println( "Continue along top row..." ); row = 0; for ( col = ncols - 2; col > 0; col -- ) { doCell4( result[ 0 ], result[ 1 ] ); } //System.out.println( "Get other points in boundary..." ); //this.t0PointIDs.addAll( Utilities.getInBoundPointIDs( t0Points, xllcorner, yllcorner, xllcorner + gridWidth, yllcorner + gridHeight ) ); //this.t1PointIDs.addAll( Utilities.getInBoundPointIDs( t1Points, xllcorner, yllcorner, xllcorner + gridWidth, yllcorner + gridHeight ) ); this.t0PointIDs.addAll( Utilities.getPointsIntersected( t0Points, dimensions ) ); this.t1PointIDs.addAll( Utilities.getPointsIntersected( t1Points, dimensions ) ); //System.out.println( "Calculate and set all non-edge cells..." ); boolean alternator = true; for ( row = 1; row < nrows - 1; row ++ ) { if ( alternator ) { alternator = false; // go right along columns for ( col = 1; col < ncols - 1; col ++ ) { doCell5( result[ 0 ], result[ 1 ] ); } } else { alternator = true; // go left along row for ( col = ncols - 2; col > 0; col -- ) { doCell5( result[ 0 ], result[ 1 ] ); } } } return result; } /** * For doing the edge cells in * getAdaptiveKernelWeights( Point2D.Double[], Point2D.Double[], * Grid2DSquareCellDoubleFactory * Grid2DSquareCellDouble, int, int, * double, double, double, double, int ) */ private void doCell4( Grid2DSquareCellDouble t0Weights, Grid2DSquareCellDouble t1Weights ) { Point2D.Double point2DDouble = new Point2D.Double( t0Weights.getCellXDouble( col, this.handleOutOfMemoryErrorFalse ), t0Weights.getCellYDouble( row, this.handleOutOfMemoryErrorFalse ) ); if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck0 = Math.max( setDistance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0NearestPoint2DDouble_DistanceDouble_IDInts, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, distanceCheck0 ); } t0Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); t0Counter ++; } else { // Recalculate as initally done Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; t0Counter = 1; } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck1 = Math.max( setDistance, t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1NearestPoint2DDouble_DistanceDouble_IDInts, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor, distanceCheck1 ); } t1Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); t1Counter ++; } else { // Recalculate as initally done Object[] t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t1NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t1InSetDistanceIDs = ( HashSet ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; t1Counter = 1; } } maxDistanceToNthNearestNeighbour = Math.max( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, t1NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble ); // Get other points if necessary if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0InSetDistanceIDs, t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1InSetDistanceIDs, t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } // Calculate and set weights double t0SumWeight = 0.0d; double t1SumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( maxDistanceToNthNearestNeighbour, precision, weightIntersect, weightFactor ); for ( int k = 0; k < t0NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t0SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); this.t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { this.t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } for ( int k = 0; k < t1NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t1SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); this.t1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { this.t1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } t0Weights.setCell( row, col, t0SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); t1Weights.setCell( row, col, t1SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } /** * For doing internal cells in * getAdaptiveKernelWeights( Point2D.Double[], Point2D.Double[], * Grid2DSquareCellDoubleFactory * Grid2DSquareCellDouble, int, int, * double, double, double, double, int ) */ private void doCell5( Grid2DSquareCellDouble t0Weights, Grid2DSquareCellDouble t1Weights ) { Point2D.Double point2DDouble = new Point2D.Double( t0Weights.getCellX( col, this.handleOutOfMemoryErrorFalse ), t0Weights.getCellY( row, this.handleOutOfMemoryErrorFalse ) ); if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck0 = Math.max( setDistance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0NearestPoint2DDouble_DistanceDouble_IDInts, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, distanceCheck0 ); } t0Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); t0Counter ++; } else { // Recalculate as initially done using t0PointsID Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( this.t0PointIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; t0Counter = 1; } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck1 = Math.max( setDistance, t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1NearestPoint2DDouble_DistanceDouble_IDInts, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor, distanceCheck1 ); } t1Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); t1Counter ++; } else { // Recalculate as initally done Object[] t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( this.t1PointIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t1NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t1InSetDistanceIDs = ( HashSet ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; t1Counter = 1; } } maxDistanceToNthNearestNeighbour = Math.max( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, t1NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble ); // Get other points if necessary if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0InSetDistanceIDs, t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( this.t0PointIDs, t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1InSetDistanceIDs, t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( this.t1PointIDs, t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } // Calculate and set weights double t0SumWeight = 0.0d; double t1SumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( maxDistanceToNthNearestNeighbour, precision, weightIntersect, weightFactor ); for ( int k = 0; k < t0NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t0SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); } } for ( int k = 0; k < t1NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t1SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); } } t0Weights.setCell( row, col, t0SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); t1Weights.setCell( row, col, t1SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } /** * Returns an Grid2DSquareCellDouble[] The first element of which is * the Adaptive Kernel Weights for t0Points, the second element of which is * the Adaptive Kernel Weights for t1Points (where the width of the kernel * is the radius of the circle which contains at least numberOfPoints in * t0Points AND at least numberOfPoints points in t1Points). * @param t0PointIDs this is a HashSet for restricting which of t0Points * need to be used in the calculation. * @param t0Points one of the two Point2D.Double[] from which kernel weights * are calculated * @param t1PointIDs this is a HashSet for restricting which of t1Points * need to be used in the calculation. * @param t1Points one of the two Point2D.Double[] from which kernel weights * are calculated * @param grid2DSquareCellDoubleFactory the Grid2DSquareCellDoubleFactory used to * generate the result * @param grid an Grid2DSquareCellDouble defining the frame and * extent processed * @param numberOfPoints the number of points accounted for in each kernel * calculation * @param weightIntersect an arbitrary double * @param weightFactor defines the shape of the kernel distance decay * @param xmin the minimum x-coordinate for any point considered * @param ymin the minimum y-coordinate for any point considered * @param xmax the maximum x-coordinate for any point considered * @param ymax the maximum y-coordinate for any point considered * @param sumAdaptiveKerneWeights the volume under the kernel to be * preserved * @param precision the precision with which the kernel volume is estimated */ public Grid2DSquareCellDouble[] getAdaptiveKernelWeights( HashSet mt0PointIDs, Point2D.Double[] t0Points, HashSet mt1PointIDs, Point2D.Double[] t1Points, Grid2DSquareCellDoubleFactory grid2DSquareCellDoubleFactory, Grid2DSquareCellDouble grid2DSquareCellDouble, int numberOfPoints, int numberOfPointsFactor, double setDistance, double weightIntersect, double weightFactor, double sumAdaptiveKernelWeights, int precision ) { // Set global variables to save passing all this information around //this.t0Points = t0Points; //this.t1Points = t1Points; this.numberOfPoints = numberOfPoints; this.numberOfPointsFactor = numberOfPointsFactor; this.weightIntersect = weightIntersect; this.weightFactor = weightFactor; this.sumAdaptiveKernelWeights = sumAdaptiveKernelWeights; this.precision = precision; this.setDistance = setDistance; Grid2DSquareCellDouble[] result = new Grid2DSquareCellDouble[ 2 ]; result[ 0 ] = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( grid2DSquareCellDouble ); result[ 1 ] = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( grid2DSquareCellDouble ); long ncols = grid2DSquareCellDouble.getNcols(); long nrows = grid2DSquareCellDouble.getNrows(); BigDecimal[] dimensions = grid2DSquareCellDouble.getDimensions(); this.cellsizeDouble = grid2DSquareCellDouble.getCellsizeDouble( this.handleOutOfMemoryErrorFalse ); this.t0PointIDs = new HashSet(); this.t1PointIDs = new HashSet(); //System.out.println( "Calculate first cell..." ); row = 0; col = 0; Point2D.Double point2DDouble = new Point2D.Double( grid2DSquareCellDouble.getCellX( col, this.handleOutOfMemoryErrorFalse ), grid2DSquareCellDouble.getCellY( row, this.handleOutOfMemoryErrorFalse ) ); Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( mt0PointIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; Object[] t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( mt1PointIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t1NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t1InSetDistanceIDs = ( HashSet ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; maxDistanceToNthNearestNeighbour = Math.max( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, t1NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble ); // Get other points if necessary if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { //XXXX Correct as t0Counter = 0 if ( setDistance >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0InSetDistanceIDs, t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( mt0PointIDs, t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { //XXXX Correct as t1Counter = 0 if ( setDistance >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1InSetDistanceIDs, t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( mt1PointIDs, t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } // Calculate and set weights double t0SumWeight = 0.0d; double t1SumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( maxDistanceToNthNearestNeighbour, precision, weightIntersect, weightFactor ); for ( int k = 0; k < t0NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t0SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); this.t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { this.t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } for ( int k = 0; k < t1NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t1SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); this.t1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { this.t1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } result[ 0 ].setCell( row, col, t0SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); result[ 1 ].setCell( row, col, t1SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); // Set t0Counter and t1Counter t0Counter = 1; t1Counter = 1; //System.out.println( "Continue down first column..." ); col = 0; for ( row = 1; row < nrows; row ++ ) { doCell6( mt0PointIDs, mt1PointIDs, result[ 0 ], result[ 1 ] ); } //System.out.println( "Continue along bottom row..." ); row = nrows - 1; for ( col = 1; col < ncols; col ++ ) { doCell6( mt0PointIDs, mt1PointIDs, result[ 0 ], result[ 1 ] ); } //System.out.println( "Continue up right column..." ); col = ncols - 1; for ( row = nrows - 2; row > -1; row -- ) { doCell6( mt0PointIDs, mt1PointIDs, result[ 0 ], result[ 1 ] ); } //System.out.println( "Continue along top row..." ); row = 0; for ( col = ncols - 2; col > 0; col -- ) { doCell6( mt0PointIDs, mt1PointIDs, result[ 0 ], result[ 1 ] ); } //System.out.println( "Get other points in boundary..." ); //this.t0PointIDs.addAll( Utilities.getInBoundPointIDs( mt0PointIDs, t0Points, xllcorner, yllcorner, xllcorner + gridWidth, yllcorner + gridHeight ) ); //this.t1PointIDs.addAll( Utilities.getInBoundPointIDs( mt1PointIDs, t1Points, xllcorner, yllcorner, xllcorner + gridWidth, yllcorner + gridHeight ) ); this.t0PointIDs.addAll( Utilities.getPointsIntersected( mt0PointIDs, t0Points, dimensions ) ); this.t1PointIDs.addAll( Utilities.getPointsIntersected( mt1PointIDs, t1Points, dimensions ) ); //System.out.println( "Calculate and set all non-edge cells..." ); boolean alternator = true; for ( row = 1; row < nrows - 1; row ++ ) { //System.out.println( "Row " + row ); if ( alternator ) { alternator = false; // go right along columns for ( col = 1; col < ncols - 1; col ++ ) { //System.out.println( "Col " + col ); doCell7( result[ 0 ], result[ 1 ] ); } } else { alternator = true; // go left along row for ( col = ncols - 2; col > 0; col -- ) { //System.out.println( "Col " + col ); doCell7( result[ 0 ], result[ 1 ] ); } } } return result; } /** * For doing the edge cells in * getAdaptiveKernelWeights( Point2D.Double[], Point2D.Double[], * Grid2DSquareCellDoubleFactory * Grid2DSquareCellDouble, int, int, * double, double, double, double, int ) */ private void doCell6( HashSet mt0PointIDs, HashSet mt1PointIDs, Grid2DSquareCellDouble t0Weights, Grid2DSquareCellDouble t1Weights ) { Point2D.Double point2DDouble = new Point2D.Double( t0Weights.getCellXDouble( col, this.handleOutOfMemoryErrorFalse ), t0Weights.getCellYDouble( row, this.handleOutOfMemoryErrorFalse ) ); if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck0 = Math.max( setDistance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0NearestPoint2DDouble_DistanceDouble_IDInts, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, distanceCheck0 ); } t0Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); t0Counter ++; } else { // Recalculate as initally done Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( mt0PointIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; t0Counter = 1; } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck1 = Math.max( setDistance, t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1NearestPoint2DDouble_DistanceDouble_IDInts, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor, distanceCheck1 ); } t1Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); t1Counter ++; } else { // Recalculate as initally done Object[] t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( mt1PointIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t1NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t1InSetDistanceIDs = ( HashSet ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; t1Counter = 1; } } maxDistanceToNthNearestNeighbour = Math.max( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, t1NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble ); // Get other points if necessary if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0InSetDistanceIDs, t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( mt0PointIDs, t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1InSetDistanceIDs, t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( mt1PointIDs, t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } // Calculate and set weights double t0SumWeight = 0.0d; double t1SumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( maxDistanceToNthNearestNeighbour, precision, weightIntersect, weightFactor ); for ( int k = 0; k < t0NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t0SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); this.t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { this.t0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } for ( int k = 0; k < t1NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t1SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); this.t1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { this.t1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } //double x = point2DDouble.getX(); //double y = point2DDouble.getY(); t0Weights.setCell( row, col, t0SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); t1Weights.setCell( row, col, t1SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } /** * For doing internal cells in * getAdaptiveKernelWeights( Point2D.Double[], Point2D.Double[], * Grid2DSquareCellDoubleFactory * Grid2DSquareCellDouble, int, int, * double, double, double, double, int ) */ private void doCell7( Grid2DSquareCellDouble t0Weights, Grid2DSquareCellDouble t1Weights ) { Point2D.Double point2DDouble = new Point2D.Double( t0Weights.getCellXDouble( col, this.handleOutOfMemoryErrorFalse ), t0Weights.getCellYDouble( row, this.handleOutOfMemoryErrorFalse ) ); if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck0 = Math.max( setDistance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0NearestPoint2DDouble_DistanceDouble_IDInts, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, distanceCheck0 ); } t0Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); t0Counter ++; } else { // Recalculate as initially done but using this.t0PointsIDs Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( this.t0PointIDs, t0Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; t0Counter = 1; } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck1 = Math.max( setDistance, t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1NearestPoint2DDouble_DistanceDouble_IDInts, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor, distanceCheck1 ); } t1Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor ); t1Counter ++; } else { // Recalculate as initally done but using this.t1PointsIDs Object[] t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( this.t1PointIDs, t1Points, point2DDouble, numberOfPoints, numberOfPointsFactor, setDistance ); t1NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t1InSetDistanceIDs = ( HashSet ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; t1Counter = 1; } } maxDistanceToNthNearestNeighbour = Math.max( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, t1NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble ); // Get other points if necessary if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0InSetDistanceIDs, t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( this.t0PointIDs, t0Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) t1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1InSetDistanceIDs, t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } else { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( this.t1PointIDs, t1Points, point2DDouble, maxDistanceToNthNearestNeighbour ); } } // Calculate and set weights double t0SumWeight = 0.0d; double t1SumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( maxDistanceToNthNearestNeighbour, precision, weightIntersect, weightFactor ); for ( int k = 0; k < t0NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t0SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); } } for ( int k = 0; k < t1NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t1SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); } } t0Weights.setCell( row, col, t0SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); t1Weights.setCell( row, col, t1SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } /** * Returns an Grid2DSquareCellDouble[] The first element of which is * the Adaptive Kernel Weights for t0Points, the second element of which is * the Adaptive Kernel Weights for t1Points (where the width of the kernel * is the radius of the circle which contains at least numberOfPoints in * t0Points AND at least numberOfPoints points in t1Points). * @param divisions controls the number of times the problem is divided * @param t0Points one of the two Point2D.Double[] from which kernel weights * are calculated * @param t1Points one of the two Point2D.Double[] from which kernel weights * are calculated * @param grid2DSquareCellDoubleFactory the Grid2DSquareCellDoubleFactory used to * generate the result * @param grid an Grid2DSquareCellDouble defining the frame and * extent processed * @param numberOfPoints the number of points accounted for in each kernel * calculation * @param weightIntersect an arbitrary double * @param weightFactor defines the shape of the kernel distance decay * @param xmin the minimum x-coordinate for any point considered * @param ymin the minimum y-coordinate for any point considered * @param xmax the maximum x-coordinate for any point considered * @param ymax the maximum y-coordinate for any point considered * @param sumAdaptiveKerneWeights the volume under the kernel to be * preserved * @param precision the precision with which the kernel volume is estimated */ public Grid2DSquareCellDouble[] getAdaptiveKernelWeights( int divisions, Point2D.Double[] t0Points, Point2D.Double[] t1Points, Grid2DSquareCellDoubleFactory grid2DSquareCellDoubleFactory, Grid2DSquareCellDouble grid2DSquareCellDouble, int numberOfPoints, int numberOfPointsFactor, double setDistance, double weightIntersect, double weightFactor, double sumAdaptiveKernelWeights, int precision ) { this.t0Points = t0Points; this.t1Points = t1Points; this.numberOfPoints = numberOfPoints; this.numberOfPointsFactor = numberOfPointsFactor; this.setDistance = setDistance; this.weightIntersect = weightIntersect; this.weightFactor = weightFactor; this.sumAdaptiveKernelWeights = sumAdaptiveKernelWeights; this.precision = precision; this.cellsizeDouble = grid2DSquareCellDouble.getCellsizeDouble( this.handleOutOfMemoryErrorFalse ); Grid2DSquareCellDouble[] result = new Grid2DSquareCellDouble[ 2 ]; result[ 0 ] = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( grid2DSquareCellDouble ); result[ 1 ] = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( grid2DSquareCellDouble ); HashSet mt0PointIDs = new HashSet(); HashSet mt1PointIDs = new HashSet(); for ( int i = 0; i < t0Points.length; i ++ ) { mt0PointIDs.add( new Integer( i ) ); } for ( int i = 0; i < t1Points.length; i ++ ) { mt1PointIDs.add( new Integer( i ) ); } //doAdaptiveKernelWeights( divisions, t0PointIDs, t0Points, t1PointIDs, t1Points, grid2DSquareCellDoubleFactory, grid, result[ 0 ], result[ 1 ], numberOfPoints, numberOfPointsFactor, setDistance, weightIntersect, weightFactor, sumAdaptiveKernelWeights, precision ); doAdaptiveKernelWeights( divisions, mt0PointIDs, mt1PointIDs, grid2DSquareCellDoubleFactory, grid2DSquareCellDouble, result[ 0 ], result[ 1 ] ); return result; } // Variables required for dividing the problem private int divT0Counter; private int divT1Counter; /** * @param divisions controls the number of times the problem is divided */ private void doAdaptiveKernelWeights( int divisions, HashSet mt0PointIDs, HashSet mt1PointIDs, Grid2DSquareCellDoubleFactory grid2DSquareCellDoubleFactory, Grid2DSquareCellDouble grid2DSquareCellDouble, Grid2DSquareCellDouble t0Weights, Grid2DSquareCellDouble t1Weights ) { //System.out.println( "Level of division " + divisions ); long nrows = grid2DSquareCellDouble.getNrows(); long ncols = grid2DSquareCellDouble.getNcols(); long maxNrowsNcols = Math.max( nrows, ncols ); if ( divisions == 0 || mt0PointIDs.size() == numberOfPoints * numberOfPointsFactor || mt1PointIDs.size() == numberOfPoints * numberOfPointsFactor || ( double ) maxNrowsNcols < setDistance / cellsizeDouble ) { //System.out.println( "Lowest level of division" ); //System.out.println( "Grid" ); //System.out.println( grid2DSquareCellDouble.toString() ); //AdaptiveGWS a = new AdaptiveGWS(); //Grid2DSquareCellDouble[] divisonResult = a.getAdaptiveKernelWeights( t0PointIDs, t0Points, t1PointIDs, t1Points, grid2DSquareCellDoubleFactory, grid2DSquareCellDouble, numberOfPoints, numberOfPointsFactor, setDistance, weightIntersect, weightFactor, sumAdaptiveKernelWeights, precision ); Grid2DSquareCellDouble[] divisonResult = getAdaptiveKernelWeights( mt0PointIDs, t0Points, mt1PointIDs, t1Points, grid2DSquareCellDoubleFactory, grid2DSquareCellDouble, numberOfPoints, numberOfPointsFactor, setDistance, weightIntersect, weightFactor, sumAdaptiveKernelWeights, precision ); //System.out.println( divisonResult[ 0 ].toString() ); //System.out.println( divisonResult[ 1 ].toString() ); // Add to the results grids to save adding multiple times this.grid2DSquareCellProcessor.addToGrid( t0Weights, divisonResult[ 0 ], this.handleOutOfMemoryErrorFalse ); this.grid2DSquareCellProcessor.addToGrid( t1Weights, divisonResult[ 1 ], this.handleOutOfMemoryErrorFalse ); } else { // Divide problem in two... // For divisions can use any type of // Grid2DSquareCellDoubleFactory for producing grids as it // is only their dimensions that are important therefore use the // following //AdaptiveGWS divAdaptiveGWS = new AdaptiveGWS(); double noDataValue = grid2DSquareCellDouble.getNoDataValue(); Grid2DSquareCellDouble divGrid = null; HashSet div0T0PointIDs = new HashSet(); HashSet div0T1PointIDs = new HashSet(); HashSet div1T0PointIDs = new HashSet(); HashSet div1T1PointIDs = new HashSet(); //double divXllcorner; //double divYllcorner; BigDecimal divXllcorner; BigDecimal divYllcorner; Point2D.Double point = null; BigDecimal[] grid2DSquareCellDoubleDimensions = grid2DSquareCellDouble.getDimensions(); BigDecimal[] dimensions = new BigDecimal[ 5 ]; // TODO: // - What is a sensible scale? int scale = 324; BigDecimal halfCellsizeBigDecimal = grid2DSquareCellDoubleDimensions[ 0 ].divide( new BigDecimal( "2" ), scale, BigDecimal.ROUND_HALF_EVEN ); // double ymin; // double ymax; // double xmax; // double xmin; Iterator ite; BigDecimal doubleMaxValueBigDecimal = new BigDecimal( Double.MAX_VALUE ); BigDecimal doubleMinValueBigDecimal = new BigDecimal( Double.MIN_VALUE ); if ( maxNrowsNcols == nrows ) { //System.out.println( "Dividing horizontally..." ); // TODO: // Should this simply be: row = ( nrows - 1L / 2L ); or row = nrows / 2L; row = ( long ) Math.ceil( ( ( ( double ) nrows ) - 1.0d ) / 2.0d ); long divNrows = row; // Done here as row could change? //System.out.println( "Division row " + row ); col = 0; //double divisionY = grid2DSquareCellDouble.getCellYDouble( col ); BigDecimal divisionY = grid2DSquareCellDouble.getCellYBigDecimal( col, this.handleOutOfMemoryErrorFalse ); //System.out.println( "DivisionY " + divisionY ); // Go along the division and calculate answer storing IDs to use // later... // Calculate the first cell of the division... doCell8( grid2DSquareCellDouble, mt0PointIDs, mt1PointIDs, t0Weights, t1Weights, div0T0PointIDs, div0T1PointIDs ); // Add to divT0PointIDs and divT1PointIDs pointIDs from region where they may effect the division // ymin = Double.POSITIVE_INFINITY; // ymax = Double.NEGATIVE_INFINITY; // xmax = grid2DSquareCellDouble.getCellXDouble( col ); // xmin = xmax - ( grid2DSquareCellDouble.getHeight() / 2.0d ); dimensions[ 2 ] = new BigDecimal( Double.MAX_VALUE ); dimensions[ 3 ] = new BigDecimal( col ); dimensions[ 4 ] = new BigDecimal( Double.MIN_VALUE ); dimensions[ 1 ] = dimensions[ 4 ].subtract( grid2DSquareCellDouble.getHeightBigDecimal( this.handleOutOfMemoryErrorFalse ).divide( new BigDecimal( "2" ), scale, BigDecimal.ROUND_HALF_EVEN ) ); ite = div0T0PointIDs.iterator(); while ( ite.hasNext() ) { point = t0Points[ ( ( Integer ) ite.next() ).intValue() ]; // ymin = Math.min( ymin, point.y ); // ymax = Math.max( ymax, point.y ); // TODO: // Are there any gremlins with the double conversion? dimensions[ 2 ] = dimensions[ 2 ].min( new BigDecimal( point.getY() ) ); dimensions[ 4 ] = dimensions[ 4 ].max( new BigDecimal( point.getY() ) ); } ite = div1T0PointIDs.iterator(); while ( ite.hasNext() ) { point = t1Points[ ( ( Integer ) ite.next() ).intValue() ]; // ymin = Math.min( ymin, point.y ); // ymax = Math.max( ymax, point.y ); // TODO: // Are there any gremlins with the double conversion? dimensions[ 2 ] = dimensions[ 2 ].min( new BigDecimal( point.getY() ) ); dimensions[ 4 ] = dimensions[ 4 ].max( new BigDecimal( point.getY() ) ); } div0T0PointIDs.addAll( Utilities.getPointsIntersected( mt0PointIDs, t0Points, dimensions ) ); div0T1PointIDs.addAll( Utilities.getPointsIntersected( mt1PointIDs, t1Points, dimensions ) ); // Continue along the division row... for ( col = 1; col < ncols - 1; col ++ ) { doCell9( grid2DSquareCellDouble, mt0PointIDs, mt1PointIDs, t0Weights, t1Weights, div0T0PointIDs, div0T1PointIDs ); } // Calculate the final cell of the division... col = ncols - 1; HashSet temp0 = new HashSet(); HashSet temp1 = new HashSet(); doCell10( grid2DSquareCellDouble, mt0PointIDs, mt1PointIDs, t0Weights, t1Weights, div0T0PointIDs, div0T1PointIDs, temp0, temp1 ); // Add to divT0PointIDs and divT1PointIDs pointIDs from region where they may effect the division // ymin = Double.POSITIVE_INFINITY; // ymax = Double.NEGATIVE_INFINITY; // xmin = grid2DSquareCellDouble.getCellX( row, col ); // xmax = xmin + ( grid2DSquareCellDouble.getHeight() / 2.0d ); dimensions[ 1 ] = new BigDecimal( col ); dimensions[ 2 ] = doubleMaxValueBigDecimal; dimensions[ 3 ] = dimensions[ 1 ].add( grid2DSquareCellDouble.getHeightBigDecimal( this.handleOutOfMemoryErrorFalse ).divide( new BigDecimal( "2" ), scale ) ); dimensions[ 4 ] = doubleMinValueBigDecimal; ite = temp0.iterator(); while ( ite.hasNext() ) { point = t0Points[ ( ( Integer ) ite.next() ).intValue() ]; // ymin = Math.min( ymin, point.y ); // ymax = Math.max( ymax, point.y ); // TODO: // Are there any gremlins with the double conversion? dimensions[ 2 ] = dimensions[ 2 ].min( new BigDecimal( point.getY() ) ); dimensions[ 4 ] = dimensions[ 4 ].max( new BigDecimal( point.getY() ) ); } ite = temp1.iterator(); while ( ite.hasNext() ) { point = t1Points[ ( ( Integer ) ite.next() ).intValue() ]; // ymin = Math.min( ymin, point.y ); // ymax = Math.max( ymax, point.y ); // TODO: // Are there any gremlins with the double conversion? dimensions[ 2 ] = dimensions[ 2 ].min( new BigDecimal( point.getY() ) ); dimensions[ 4 ] = dimensions[ 4 ].max( new BigDecimal( point.getY() ) ); } div0T0PointIDs.addAll( Utilities.getPointsIntersected( mt0PointIDs, t0Points, dimensions ) ); div0T1PointIDs.addAll( Utilities.getPointsIntersected( mt1PointIDs, t1Points, dimensions ) ); // Add all IDs of cells along the division to the other ID // holders div1T0PointIDs.addAll( div0T0PointIDs ); div1T1PointIDs.addAll( div0T1PointIDs ); // Focus on the top part // Add all point IDs above row to div1T0PointIDs and // div1T1PointIDs dimensions[ 1 ] = doubleMinValueBigDecimal; dimensions[ 2 ] = divisionY; dimensions[ 3 ] = doubleMaxValueBigDecimal; dimensions[ 4 ] = doubleMaxValueBigDecimal; div1T0PointIDs.addAll( Utilities.getPointsIntersected( mt0PointIDs, t0Points, dimensions ) ); div1T1PointIDs.addAll( Utilities.getPointsIntersected( mt1PointIDs, t1Points, dimensions ) ); // Create grid //divXllcorner = grid2DSquareCellDouble.getXllcorner(); //divYllcorner = divisionY + ( cellsize / 2.0d ); dimensions[ 0 ] = grid2DSquareCellDoubleDimensions[ 0 ]; dimensions[ 1 ] = grid2DSquareCellDoubleDimensions[ 1 ]; dimensions[ 2 ] = divisionY.add( halfCellsizeBigDecimal ); dimensions[ 3 ] = dimensions[ 1 ].add( new BigDecimal( divNrows ).multiply ( grid2DSquareCellDoubleDimensions[ 0 ] ) ); dimensions[ 4 ] = dimensions[ 2 ].add( new BigDecimal( ncols ).multiply( grid2DSquareCellDoubleDimensions[ 0 ] ) ); divGrid = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( divNrows, ncols, dimensions ); // Add Adaptive Kernel Weights to t0Weights and t1Weights doAdaptiveKernelWeights( divisions - 1, div1T0PointIDs, div1T1PointIDs, grid2DSquareCellDoubleFactory, divGrid, t0Weights, t1Weights ); // Focus on the bottom part // Add all point IDs below row to ID holders div0T0PointIDs and // div0T1PointIDs dimensions[ 1 ] = doubleMinValueBigDecimal; dimensions[ 2 ] = doubleMinValueBigDecimal; dimensions[ 3 ] = doubleMaxValueBigDecimal; dimensions[ 4 ] = divisionY; div0T0PointIDs.addAll( Utilities.getPointsIntersected( mt0PointIDs, t0Points, dimensions ) ); div0T1PointIDs.addAll( Utilities.getPointsIntersected( mt1PointIDs, t1Points, dimensions ) ); // Create grid //divXllcorner = grid2DSquareCellDouble.getXllcorner(); //divYllcorner = grid2DSquareCellDouble.getYllcorner(); divNrows = nrows - divNrows - 1L; dimensions[ 0 ] = grid2DSquareCellDoubleDimensions[ 0 ]; dimensions[ 1 ] = grid2DSquareCellDoubleDimensions[ 1 ]; dimensions[ 2 ] = grid2DSquareCellDoubleDimensions[ 2 ]; dimensions[ 3 ] = dimensions[ 1 ].add( new BigDecimal( divNrows ).multiply ( grid2DSquareCellDoubleDimensions[ 0 ] ) ); dimensions[ 4 ] = dimensions[ 2 ].add( new BigDecimal( ncols ).multiply( grid2DSquareCellDoubleDimensions[ 0 ] ) ); divGrid = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( divNrows, ncols, dimensions ); // Add Adaptive Kernel Weights to t0Weights and t1Weights doAdaptiveKernelWeights( divisions - 1, div0T0PointIDs, div0T1PointIDs, grid2DSquareCellDoubleFactory, divGrid, t0Weights, t1Weights ); } else { //System.out.println( "Dividing vertically..." ); // TODO: // Should this simply be: col = ( ncols - 1L / 2L ); or col = ncols / 2L; col = ( int ) Math.ceil( ( ( ( double ) ncols ) - 1.0d ) / 2.0d ); long divNcols = col; row = 0L; //System.out.println( "Division col " + col ); //double divisionX = grid2DSquareCellDouble.getCellX( row, col ); BigDecimal divisionX = grid2DSquareCellDouble.getCellXBigDecimal( row, this.handleOutOfMemoryErrorFalse ); //System.out.println( "DivisionX " + divisionX ); // Go along the division and calculate answer storing IDs to use // later... // Calculate the first cell of the division... doCell8( grid2DSquareCellDouble, mt0PointIDs, mt1PointIDs, t0Weights, t1Weights, div0T0PointIDs, div0T1PointIDs ); // Add to divT0PointIDs and divT1PointIDs pointIDs from region where they may effect the division // xmin = Double.POSITIVE_INFINITY; // xmax = Double.NEGATIVE_INFINITY; // ymin = grid2DSquareCellDouble.getCellY( row, col ); // ymax = ymin + ( grid2DSquareCellDouble.getWidth() / 2.0d ); dimensions[ 1 ] = doubleMaxValueBigDecimal; dimensions[ 2 ] = grid2DSquareCellDouble.getCellYBigDecimal( col, this.handleOutOfMemoryErrorFalse ); dimensions[ 3 ] = doubleMinValueBigDecimal; dimensions[ 4 ] = dimensions[ 2 ].add( grid2DSquareCellDouble.getWidthBigDecimal( this.handleOutOfMemoryErrorFalse ).divide( new BigDecimal( "2" ), scale, BigDecimal.ROUND_HALF_EVEN ) ); ite = div0T0PointIDs.iterator(); BigDecimal xBigDecimal; while ( ite.hasNext() ) { point = t0Points[ ( ( Integer ) ite.next() ).intValue() ]; xBigDecimal = new BigDecimal( point.getX() ); // xmin = Math.min( xmin, point.x ); // xmax = Math.max( xmax, point.x ); dimensions[ 1 ] = dimensions[ 1 ].min( xBigDecimal ); dimensions[ 3 ] = dimensions[ 3 ].max( xBigDecimal ); } ite = div1T0PointIDs.iterator(); while ( ite.hasNext() ) { point = t1Points[ ( ( Integer ) ite.next() ).intValue() ]; xBigDecimal = new BigDecimal( point.getX() ); // xmin = Math.min( xmin, point.x ); // xmax = Math.max( xmax, point.x ); dimensions[ 1 ] = dimensions[ 1 ].min( xBigDecimal ); dimensions[ 3 ] = dimensions[ 3 ].max( xBigDecimal ); } div0T0PointIDs.addAll( Utilities.getPointsIntersected( mt0PointIDs, t0Points, dimensions ) ); div0T1PointIDs.addAll( Utilities.getPointsIntersected( mt1PointIDs, t1Points, dimensions ) ); // Continue along the division col... //System.out.println( "Calculate the division col..." ); for ( row = 1; row < nrows - 1; row ++ ) { doCell9( grid2DSquareCellDouble, mt0PointIDs, mt1PointIDs, t0Weights, t1Weights, div0T0PointIDs, div0T1PointIDs ); } // Calculate the final cell of the division... row = nrows - 1; HashSet temp0 = new HashSet(); HashSet temp1 = new HashSet(); doCell10( grid2DSquareCellDouble, mt0PointIDs, mt1PointIDs, t0Weights, t1Weights, div0T0PointIDs, div0T1PointIDs, temp0, temp1 ); // Add to divT0PointIDs and divT1PointIDs pointIDs from region where they may effect the division // xmin = Double.POSITIVE_INFINITY; // xmax = Double.NEGATIVE_INFINITY; // ymax = grid2DSquareCellDouble.getCellY( row, col ); // ymin = ymax - ( grid2DSquareCellDouble.getWidth() / 2.0d ); dimensions[ 1 ] = doubleMaxValueBigDecimal; dimensions[ 3 ] = doubleMinValueBigDecimal; dimensions[ 4 ] = grid2DSquareCellDouble.getCellYBigDecimal( col, this.handleOutOfMemoryErrorFalse ); dimensions[ 2 ] = dimensions[ 4 ].subtract( grid2DSquareCellDouble.getWidthBigDecimal( this.handleOutOfMemoryErrorFalse ).divide( new BigDecimal( "2" ), scale, BigDecimal.ROUND_HALF_EVEN ) ); ite = temp0.iterator(); while ( ite.hasNext() ) { point = t0Points[ ( ( Integer ) ite.next() ).intValue() ]; xBigDecimal = new BigDecimal( point.getX() ); // xmin = Math.min( xmin, point.x ); // xmax = Math.max( xmax, point.x ); dimensions[ 1 ] = dimensions[ 1 ].min( xBigDecimal ); dimensions[ 3 ] = dimensions[ 3 ].max( xBigDecimal ); } ite = temp1.iterator(); while ( ite.hasNext() ) { point = t1Points[ ( ( Integer ) ite.next() ).intValue() ]; xBigDecimal = new BigDecimal( point.getX() ); // xmin = Math.min( xmin, point.x ); // xmax = Math.max( xmax, point.x ); dimensions[ 1 ] = dimensions[ 1 ].min( xBigDecimal ); dimensions[ 3 ] = dimensions[ 3 ].max( xBigDecimal );point = t1Points[ ( ( Integer ) ite.next() ).intValue() ]; } div0T0PointIDs.addAll( Utilities.getPointsIntersected( mt0PointIDs, t0Points, dimensions ) ); div0T1PointIDs.addAll( Utilities.getPointsIntersected( mt1PointIDs, t1Points, dimensions ) ); // Add all IDs of cells along the division to the other ID // holders div1T0PointIDs.addAll( div0T0PointIDs ); div1T1PointIDs.addAll( div0T1PointIDs ); // Focus on the left part // Add all point IDs left of col to ID holders div0T0PointIDs // and div0T1PointIDs dimensions[ 1 ] = doubleMinValueBigDecimal; dimensions[ 2 ] = doubleMinValueBigDecimal; dimensions[ 3 ] = divisionX; dimensions[ 4 ] = doubleMaxValueBigDecimal; div0T0PointIDs.addAll( Utilities.getPointsIntersected( mt0PointIDs, t0Points, dimensions ) ); div0T1PointIDs.addAll( Utilities.getPointsIntersected( mt1PointIDs, t1Points, dimensions ) ); // Create divGrid dimensions[ 0 ] = grid2DSquareCellDoubleDimensions[ 0 ]; dimensions[ 1 ] = grid2DSquareCellDoubleDimensions[ 1 ]; dimensions[ 2 ] = grid2DSquareCellDoubleDimensions[ 2 ]; dimensions[ 3 ] = dimensions[ 1 ].add( new BigDecimal( divNcols ).multiply( grid2DSquareCellDoubleDimensions[ 0 ] ) ); dimensions[ 4 ] = dimensions[ 2 ].add( new BigDecimal( nrows ).multiply( grid2DSquareCellDoubleDimensions[ 0 ] ) ); divGrid = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( nrows, divNcols, dimensions ); //divGrid = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( gridNrows, divNcols, divXllcorner, divYllcorner, cellsize, noDataValue, 1 ); // Add Adaptive Kernel Weights to t0Weights and t1Weights doAdaptiveKernelWeights( divisions - 1, div0T0PointIDs, div0T1PointIDs, grid2DSquareCellDoubleFactory, divGrid, t0Weights, t1Weights ); // Focus on the right part // Add all point IDs right of col to ID holders div1T0PointIDs // and div1T1PointIDs dimensions[ 1 ] = divisionX; dimensions[ 2 ] = doubleMinValueBigDecimal; dimensions[ 3 ] = doubleMaxValueBigDecimal; dimensions[ 4 ] = doubleMaxValueBigDecimal; div1T0PointIDs.addAll( Utilities.getPointsIntersected( mt0PointIDs, t0Points, dimensions ) ); div1T1PointIDs.addAll( Utilities.getPointsIntersected( mt1PointIDs, t1Points, dimensions ) ); // Create grid //divXllcorner = divisionX + ( cellsize / 2.0d ); ////divYllcorner = grid2DSquareCellDouble.getYllcorner(); divNcols = ncols - divNcols - 1L; dimensions[ 1 ] = divisionX.add( halfCellsizeBigDecimal ); dimensions[ 2 ] = grid2DSquareCellDoubleDimensions[ 2 ]; dimensions[ 3 ] = dimensions[ 1 ].add( new BigDecimal( divNcols ).multiply( grid2DSquareCellDoubleDimensions[ 0 ] ) ); dimensions[ 4 ] = dimensions[ 2 ].add( new BigDecimal( nrows ).multiply( grid2DSquareCellDoubleDimensions[ 0 ] ) ); divGrid = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( nrows, divNcols, dimensions ); //divGrid = grid2DSquareCellDoubleFactory.createGrid2DSquareCellDouble( gridNrows, divNcols, divXllcorner, divYllcorner, cellsize, noDataValue, 1 ); // Add Adaptive Kernel Weights to t0Weights and t1Weights doAdaptiveKernelWeights( divisions - 1, div1T0PointIDs, div1T1PointIDs, grid2DSquareCellDoubleFactory, divGrid, t0Weights, t1Weights ); } } } /** * For doing the first cell of a division in * getAdaptiveKernelWeights( int, HashSet, Point2D.Double[], HashSet, * Point2D.Double[], * Grid2DSquareCellDoubleFactory * Grid2DSquareCellDouble, int, int, * double, double, double, double, int ) */ private void doCell8( Grid2DSquareCellDouble grid2DSquareCellDouble, HashSet mt0PointIDs, HashSet mt1PointIDs, Grid2DSquareCellDouble t0Weights, Grid2DSquareCellDouble t1Weights, HashSet divT0PointIDs, HashSet divT1PointIDs ) { double x = grid2DSquareCellDouble.getCellXDouble( col, this.handleOutOfMemoryErrorFalse ); double y = grid2DSquareCellDouble.getCellYDouble( row, this.handleOutOfMemoryErrorFalse ); Point2D.Double point = new Point2D.Double( x, y ); Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( mt0PointIDs, t0Points, point, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; Object[] t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( mt1PointIDs, t1Points, point, numberOfPoints, numberOfPointsFactor, setDistance ); t1NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t1InSetDistanceIDs = ( HashSet ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; maxDistanceToNthNearestNeighbour = Math.max( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, t1NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble ); // Get other points if necessary if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { //XXXX Correct as divT0Counter = 0 if ( setDistance >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0InSetDistanceIDs, t0Points, point, maxDistanceToNthNearestNeighbour ); } else { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( mt0PointIDs, t0Points, point, maxDistanceToNthNearestNeighbour ); } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { //XXXX Correct as divT1Counter = 0 if ( setDistance >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1InSetDistanceIDs, t0Points, point, maxDistanceToNthNearestNeighbour ); } else { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( mt1PointIDs, t1Points, point, maxDistanceToNthNearestNeighbour ); } } // Calculate and set weights double t0SumWeight = 0.0d; double t1SumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( maxDistanceToNthNearestNeighbour, precision, weightIntersect, weightFactor ); for ( int k = 0; k < t0NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t0SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); divT0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { divT0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } for ( int k = 0; k < t1NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t1SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); divT1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { divT1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } divT0Counter = 1; divT1Counter = 1; t0Weights.setCell( x, y, t0SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); t1Weights.setCell( x, y, t1SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } /** * For doing all but the last remaining cell of a division in * getAdaptiveKernelWeights( int, HashSet, Point2D.Double[], HashSet, * Point2D.Double[], * Grid2DSquareCellDoubleFactory * Grid2DSquareCellDouble, int, int, * double, double, double, double, int ) */ private void doCell9( Grid2DSquareCellDouble grid2DSquareCellDouble, HashSet t0PointIDs, HashSet t1PointIDs, Grid2DSquareCellDouble t0Weights, Grid2DSquareCellDouble t1Weights, HashSet divT0PointIDs, HashSet divT1PointIDs ) { double x = grid2DSquareCellDouble.getCellXDouble( col, this.handleOutOfMemoryErrorFalse ); double y = grid2DSquareCellDouble.getCellYDouble( row, this.handleOutOfMemoryErrorFalse ); Point2D.Double point = new Point2D.Double( x, y ); if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) divT0Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT0Counter ) >= t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck0 = Math.max( setDistance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0NearestPoint2DDouble_DistanceDouble_IDInts, t0Points, point, numberOfPoints, numberOfPointsFactor, distanceCheck0 ); } divT0Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point, numberOfPoints, numberOfPointsFactor ); divT0Counter ++; } else { // Recalculate as initially done using t0PointsID Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t0PointIDs, t0Points, point, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; divT0Counter = 1; } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) divT1Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT1Counter ) >= t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck1 = Math.max( setDistance, t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1NearestPoint2DDouble_DistanceDouble_IDInts, t1Points, point, numberOfPoints, numberOfPointsFactor, distanceCheck1 ); } divT1Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point, numberOfPoints, numberOfPointsFactor ); divT1Counter ++; } else { // Recalculate as initally done Object[] t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t1PointIDs, t1Points, point, numberOfPoints, numberOfPointsFactor, setDistance ); t1NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t1InSetDistanceIDs = ( HashSet ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; divT1Counter = 1; } } maxDistanceToNthNearestNeighbour = Math.max( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, t1NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble ); // Get other points if necessary if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0InSetDistanceIDs, t0Points, point, maxDistanceToNthNearestNeighbour ); } else { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0PointIDs, t0Points, point, maxDistanceToNthNearestNeighbour ); } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1InSetDistanceIDs, t1Points, point, maxDistanceToNthNearestNeighbour ); } else { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1PointIDs, t1Points, point, maxDistanceToNthNearestNeighbour ); } } // Calculate and set weights double t0SumWeight = 0.0d; double t1SumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( maxDistanceToNthNearestNeighbour, precision, weightIntersect, weightFactor ); for ( int k = 0; k < t0NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t0SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); divT0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { divT0PointIDs.add( new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } for ( int k = 0; k < t1NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t1SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); divT1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } else { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { divT1PointIDs.add( new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ) ); } } } t0Weights.setCell( x, y, t0SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); t1Weights.setCell( x, y, t1SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } /** * For doing the final cell of a division in * getAdaptiveKernelWeights( int, HashSet, Point2D.Double[], HashSet, * Point2D.Double[], * Grid2DSquareCellDoubleFactory * Grid2DSquareCellDouble, int, int, * double, double, double, double, int ) */ private void doCell10( Grid2DSquareCellDouble grid2DSquareCellDouble, HashSet t0PointIDs, HashSet t1PointIDs, Grid2DSquareCellDouble t0Weights, Grid2DSquareCellDouble t1Weights, HashSet divT0PointIDs, HashSet divT1PointIDs, HashSet temp0, HashSet temp1 ) { double x = grid2DSquareCellDouble.getCellXDouble( col, this.handleOutOfMemoryErrorFalse ); double y = grid2DSquareCellDouble.getCellYDouble( row, this.handleOutOfMemoryErrorFalse ); Point2D.Double point = new Point2D.Double( x, y ); if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) divT0Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT0Counter ) >= t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck0 = Math.max( setDistance, t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0NearestPoint2DDouble_DistanceDouble_IDInts, t0Points, point, numberOfPoints, numberOfPointsFactor, distanceCheck0 ); } divT0Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t0InSetDistanceIDs, t0Points, point, numberOfPoints, numberOfPointsFactor ); divT0Counter ++; } else { // Recalculate as initially done using t0PointsID Object[] t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t0PointIDs, t0Points, point, numberOfPoints, numberOfPointsFactor, setDistance ); t0NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t0InSetDistanceIDs = ( HashSet ) t0NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; divT0Counter = 1; } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble - ( cellsizeDouble * 2.0d * ( double ) divT1Counter ) >= maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT1Counter ) >= t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point, numberOfPoints, numberOfPointsFactor ); } else { double distanceCheck1 = Math.max( setDistance, t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble ); t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1NearestPoint2DDouble_DistanceDouble_IDInts, t1Points, point, numberOfPoints, numberOfPointsFactor, distanceCheck1 ); } divT1Counter ++; } else { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getNearestPoint2DDouble_DistanceDouble_IDInts( t1InSetDistanceIDs, t1Points, point, numberOfPoints, numberOfPointsFactor ); divT1Counter ++; } else { // Recalculate as initally done Object[] t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo = getNearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo( t1PointIDs, t1Points, point, numberOfPoints, numberOfPointsFactor, setDistance ); t1NearestPoint2DDouble_DistanceDouble_IDInts = ( Point2DDouble_DistanceDouble_IDInt[] ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 0 ]; t1InSetDistanceIDs = ( HashSet ) t1NearestPoint2DDouble_DistanceDouble_IDIntsAndOtherInfo[ 1 ]; divT1Counter = 1; } } maxDistanceToNthNearestNeighbour = Math.max( t0NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble, t1NearestPoint2DDouble_DistanceDouble_IDInts[ numberOfPoints - 1 ].distanceDouble ); // Get other points if necessary if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ t0NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT0Counter ) >= maxDistanceToNthNearestNeighbour ) { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0InSetDistanceIDs, t0Points, point, maxDistanceToNthNearestNeighbour ); } else { t0NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t0PointIDs, t0Points, point, maxDistanceToNthNearestNeighbour ); } } if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ t1NearestPoint2DDouble_DistanceDouble_IDInts.length - 1 ].distanceDouble < maxDistanceToNthNearestNeighbour ) { if ( setDistance - ( cellsizeDouble * 2.0d * ( double ) divT1Counter ) >= maxDistanceToNthNearestNeighbour ) { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1InSetDistanceIDs, t1Points, point, maxDistanceToNthNearestNeighbour ); } else { t1NearestPoint2DDouble_DistanceDouble_IDInts = getInDistancePoint2DDouble_DistanceDouble_IDIntsArray( t1PointIDs, t1Points, point, maxDistanceToNthNearestNeighbour ); } } // Calculate and set weights double t0SumWeight = 0.0d; double t1SumWeight = 0.0d; double kernelVolume = Kernel.getKernelVolume( maxDistanceToNthNearestNeighbour, precision, weightIntersect, weightFactor ); Integer ID; for ( int k = 0; k < t0NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t0SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); ID = new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ); divT0PointIDs.add( ID ); temp0.add( ID ); } else { if ( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { ID = new Integer( t0NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ); divT0PointIDs.add( ID ); temp0.add( ID ); } } } for ( int k = 0; k < t1NearestPoint2DDouble_DistanceDouble_IDInts.length; k ++ ) { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble < maxDistanceToNthNearestNeighbour ) { t1SumWeight += Kernel.getKernelWeight( maxDistanceToNthNearestNeighbour, weightIntersect, weightFactor, t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble ); ID = new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ); divT1PointIDs.add( ID ); temp1.add( ID ); } else { if ( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].distanceDouble == maxDistanceToNthNearestNeighbour ) { ID = new Integer( t1NearestPoint2DDouble_DistanceDouble_IDInts[ k ].iDInt ); divT1PointIDs.add( ID ); temp1.add( ID ); } } } t0Weights.setCell( x, y, t0SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); t1Weights.setCell( x, y, t1SumWeight * sumAdaptiveKernelWeights / kernelVolume, this.handleOutOfMemoryErrorFalse ); } }