/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2016, Open Source Geospatial Foundation (OSGeo) * * 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; * version 2.1 of the License. * * 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. */ package org.geotools.processing.jai; import java.awt.image.RenderedImage; import java.util.Iterator; import java.util.Map; import java.util.TreeSet; import javax.media.jai.ROI; import org.geotools.process.raster.classify.Classification; import org.geotools.process.raster.classify.QuantileClassification; /** * Classification op for the quantile method. */ public class QuantileBreaksOpImage extends ClassBreaksOpImage { public QuantileBreaksOpImage(RenderedImage image, Integer numClasses, Double[][] extrema, ROI roi, Integer[] bands, Integer xStart, Integer yStart, Integer xPeriod, Integer yPeriod, Double noData) { super(image, numClasses, extrema, roi, bands, xStart, yStart, xPeriod, yPeriod, noData); } @Override protected Classification createClassification() { return new QuantileClassification(bands.length); } @Override protected void handleValue(double d, Classification c, int band) { QuantileClassification qc = (QuantileClassification) c; if (extrema != null) { double min = extrema[0][band]; double max = extrema[1][band]; if (d < min || d > max) { return; } } qc.count(d, band); } @Override protected void postCalculate(Classification c, int band) { QuantileClassification qc = (QuantileClassification) c; //get the total number of values int nvalues = qc.getCount(band); //calculate the number of values per class int size = (int) Math.ceil(nvalues / (double) numClasses); //grab the key iterator Iterator<Map.Entry<Double, Integer>> it = qc.getTable(band).entrySet().iterator(); TreeSet<Double> set = new TreeSet<Double>(); Map.Entry<Double, Integer> e = it.next(); while(nvalues > 0) { //add the next break set.add(e.getKey()); for (int i = 0; i < size && nvalues > 0; i++) { //consume the next value int count = e.getValue(); e.setValue(--count); nvalues--; if (count == 0) { //number of occurences of this entry exhausted, move to next if (!it.hasNext()) { break; } e = it.next(); } } if (nvalues == 0) { //add the last value set.add(e.getKey()); } } qc.setBreaks(band, set.toArray(new Double[set.size()])); } }