// An accumulation bin counts the number of hits in a certain area. This area // is determined by the range of the accumulation grid and its resolution. // The accumulation allows fractional counts, for example a hit can result in a 0.25/0.75 distribution over two bins. // This generalisation helps in reducing sharp pixel artefacts in very high density areas. // The accumulation grid serves two purposes. It collects an array of bins and // assigns each a certain physical area. // The physical limits (e.g. -1.0f to 1.0f) are determined by the attractor system. // The resolution (e.g. 100 by 100 bins) is defined here. class AccumulationGrid{ float[][] count; // bins float[][] fastCount; // simple bins without fractiobal hits float maxCount; float minCount; float invLogCount; GridParameters parameters; float idx, idy;// inverse dimensions of bin area AccumulationGrid(GridParameters GP){ parameters = GP.get(); idx=parameters.resX/(parameters.maxVisX-parameters.minVisX);// inverse width of a bin idy=parameters.resY/(parameters.maxVisY-parameters.minVisY);// inverse height of a bin count = new float[parameters.resX][parameters.resY]; fastCount = new float[parameters.resX][parameters.resY]; maxCount=minCount=invLogCount=0f; } void reset(boolean resized){ idx=parameters.resX/(parameters.maxVisX-parameters.minVisX); idy=parameters.resY/(parameters.maxVisY-parameters.minVisY); if(resized){ count = new float[parameters.resX][parameters.resY]; fastCount = new float[parameters.resX][parameters.resY]; maxCount=minCount=invLogCount=0f; } else{ for(int i=0;i=parameters.minVisX)&&(x=parameters.minVisY)&&(y10^rc) have no spread, only bilinear interpolation fastCount[gridX][gridY]++; int range =0; if(quality==2){ if(fastCount[gridX][gridY]<10){// The first few hits in Gaussian mode are used to estimate the local density range=-1; } else{ range=max(0, gck.maxRange-(int)(2f*gck.maxRange*FastFunctions.log2(fastCount[gridX][gridY]+1f)*invLogCount)); } } if( quality==0){ count[gridX][gridY]+=c; updateStatBins(gridX,gridY); } else if(range==0){ float residuX=gridfx-gridX; float residuY=gridfy-gridY; count[gridX][gridY]+=(1f-residuX)*(1f-residuY)*c; updateStatBins(gridX,gridY); if(gridX+1=0)&&(X+i=0)&&(Y+jmaxCount){ maxCount=count[i][j]; recalcLogCount=true; } if(count[i][j]0f)?1f/FastFunctions.log2(1f+maxCount-minCount):0f; } // This is the second important part, used for displaying the grid. It resamples the accumulation grid // to arbitrary resolution, e.g 200x200 bins to 500x500 pixels or 2000x2000 bins to 1000x1000 pixels. // Both downscaling and upscaling are supported. Non-integer ratios, // e.g. 1.5x1.5 bins per pixel are handled by weighing values for partial overlap, half a bin would add half its value. // Furthermore the range of the returned values should be independent of the requested resolution. For this the returned values // are averaged over the sampling area. ResultBin getValues(int i, int j, int w, int h){ float binsPerPixelx = (float)parameters.resX/(float)w; float binsPerPixely = (float)parameters.resY/(float)h; float startx=max(0f,i*binsPerPixelx); int sx = (int)startx; float residusx = 1f-startx+sx; float starty=max(0f,j*binsPerPixely); int sy = (int)starty; float residusy = 1f-starty+sy; float endx=startx+binsPerPixelx-0.0001f; int ex = (int)endx; float residuex = endx-ex; float endy=starty+binsPerPixely-0.0001f; int ey = (int)endy; float residuey = endy-ey; float c=0f; // Running total of count float area=0f; // Running total of the number of bins float factorx=0f; float factory=0f; float phi; for(int x=sx; x