Skip to content

Commit

Permalink
[GEOS-7566] WrappedCoverageDimension customizations won't survive a c…
Browse files Browse the repository at this point in the history
…overage operation
  • Loading branch information
aaime committed Jun 1, 2016
1 parent ff3b5e3 commit a63a265
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 115 deletions.
Expand Up @@ -8,9 +8,11 @@
import it.geosolutions.imageio.maskband.DatasetLayout; import it.geosolutions.imageio.maskband.DatasetLayout;
import it.geosolutions.jaiext.range.NoDataContainer; import it.geosolutions.jaiext.range.NoDataContainer;


import java.awt.Color;
import java.awt.image.ColorModel; import java.awt.image.ColorModel;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
Expand Down Expand Up @@ -272,7 +274,7 @@ protected GridSampleDimension[] wrapDimensions(SampleDimension[] dims) {
final int outputDims = dims.length; final int outputDims = dims.length;
wrappedDims = new GridSampleDimension[outputDims]; wrappedDims = new GridSampleDimension[outputDims];
for (SampleDimension dim: dims) { for (SampleDimension dim: dims) {
wrappedDims[i] = new WrappedSampleDimension((GridSampleDimension) dim, wrappedDims[i] = WrappedSampleDimension.build((GridSampleDimension) dim,
storedDimensions.get(outputDims != inputDims ? (i > (inputDims - 1 ) ? inputDims - 1 : i) : i)); storedDimensions.get(outputDims != inputDims ? (i > (inputDims - 1 ) ? inputDims - 1 : i) : i));
i++; i++;
} }
Expand Down Expand Up @@ -483,6 +485,133 @@ public static GridCoverage2D wrapCoverage(GridCoverage2D coverage, GridCoverage2
*/ */
static class WrappedSampleDimension extends GridSampleDimension implements SampleDimension { static class WrappedSampleDimension extends GridSampleDimension implements SampleDimension {


/** The original sample dimension */
private GridSampleDimension sampleDim;

/** The custom categories */
private List<Category> customCategories;

/** The custom noDataValues */
private double[] configuredNoDataValues;

/** The custom unit */
private Unit<?> configuredUnit;

/** The custom range */
private NumberRange<? extends Number> configuredRange;

/** The custom name */
private String name;

/** The custom description */
private InternationalString configuredDescription;

public static WrappedSampleDimension build(GridSampleDimension sampleDim, CoverageDimensionInfo info) {
String name = info.getName();
final InternationalString sampleDimDescription = sampleDim.getDescription();
InternationalString configuredDescription = (sampleDimDescription == null || !sampleDimDescription.toString()
.equalsIgnoreCase(name)) ?
new SimpleInternationalString(name) : sampleDimDescription;
final List<Category> categories = sampleDim.getCategories();
NumberRange configuredRange = info.getRange();
final String uom = info.getUnit();
Unit defaultUnit = sampleDim.getUnits();
Unit unit = defaultUnit;
try {
if (uom != null) {
unit = Unit.valueOf(uom);
}
} catch (IllegalArgumentException iae) {
if (LOGGER.isLoggable(Level.WARNING) && defaultUnit != null) {
LOGGER.warning("Unable to parse the specified unit (" + uom
+ "). Using the previous one: " + defaultUnit.toString());
}
}
Unit configuredUnit = unit;

// custom null values
final List<Double> nullValues = info.getNullValues();
double[] configuredNoDataValues;
if (nullValues != null && nullValues.size() > 0) {
final int size = nullValues.size();
configuredNoDataValues = new double[size];
for (int i = 0; i < size ; i++) {
configuredNoDataValues[i] = nullValues.get(i);
}
} else {
configuredNoDataValues = sampleDim.getNoDataValues();
}

// Check if the nodata has been configured
boolean nodataConfigured = configuredNoDataValues != null
&& configuredNoDataValues.length > 0;
// custom categories
int numCategories = 0;
List<Category> customCategories = new ArrayList<Category>(numCategories);
if (categories != null && (numCategories = categories.size()) > 0) {
Category wrapped = null;
for (Category category : categories) {
wrapped = category;
if (Category.NODATA.getName().equals(category.getName())) {
if (category.isQuantitative()) {
// Get minimum and maximum value
double minimum = nodataConfigured ? configuredNoDataValues[0]
: category.getRange().getMinimum();
double maximum = nodataConfigured ? configuredNoDataValues[0]
: category.getRange().getMaximum();
if (Double.isNaN(minimum) && Double.isNaN(maximum)) {
// Create a qualitative category
wrapped = new Category(Category.NODATA.getName(),
category.getColors()[0], minimum);
} else {
// Create the wrapped category
wrapped = new Category(Category.NODATA.getName(),
category.getColors(), NumberRange.create(minimum, maximum));
}
}
}
customCategories.add(wrapped);
}
}
// Adding the full data range, it's mandatory to have it if we want the configured range to survive a grid dimension copy
// (but an infinite range is not valid, the Category creation will throw an exception)
if(configuredRange != null && !Double.isInfinite(configuredRange.getMinimum()) && !Double.isInfinite(configuredRange.getMaximum())) {
Class targetType = categories != null && !categories.isEmpty() ? categories.get(0).getRange().getElementClass() : Double.class;
final NumberRange<Double> dataRange = new NumberRange<>(targetType, configuredRange.getMinimum(), configuredRange.getMaximum());
List<NumberRange<?>> dataRanges = new ArrayList<>();
dataRanges.add(dataRange);
for (Category category : customCategories) {
List<NumberRange<?>> newDataRanges = new ArrayList<>();
for (NumberRange<?> dr : dataRanges) {
NumberRange<?>[] subtracted = dr.subtract(category.getRange());
for (NumberRange<?> range : subtracted) {
if(!range.isEmpty()) {
newDataRanges.add(range);
}
}
}
dataRanges = newDataRanges;
}
for (int i = 0; i < dataRanges.size(); i++) {
customCategories.add(new Category("data" + i, (Color) null, dataRanges.get(i)));
}
}

return new WrappedSampleDimension(name, configuredDescription, configuredRange, configuredUnit, configuredNoDataValues,
(Category[]) customCategories.toArray(new Category[customCategories.size()]), sampleDim);
}

WrappedSampleDimension(String name, InternationalString configuredDescription, NumberRange<? extends Number> configuredRange,
Unit<?> configuredUnit, double[] configuredNoDataValues, Category[] customCategories, GridSampleDimension sampleDim) {
super(configuredDescription.toString(), customCategories, configuredUnit);
this.configuredDescription = configuredDescription;
this.configuredRange = configuredRange;
this.configuredUnit = configuredUnit;
this.configuredNoDataValues = configuredNoDataValues;
this.customCategories = Arrays.asList(customCategories);
this.sampleDim = sampleDim;
}

@Override @Override
public SampleDimensionType getSampleDimensionType() { public SampleDimensionType getSampleDimensionType() {
return sampleDim.getSampleDimensionType(); return sampleDim.getSampleDimensionType();
Expand Down Expand Up @@ -613,98 +742,6 @@ public String toString() {
} }
} }


/** The original sample dimension */
private GridSampleDimension sampleDim;

/** The custom categories */
private List<Category> customCategories;

/** The custom noDataValues */
private double[] configuredNoDataValues;

/** The custom unit */
private Unit<?> configuredUnit;

/** The custom range */
private NumberRange<? extends Number> configuredRange;

/** The custom name */
private String name;

/** The custom description */
private InternationalString configuredDescription;

public WrappedSampleDimension(GridSampleDimension sampleDim, CoverageDimensionInfo info) {
super(sampleDim);
this.name = info.getName();
final InternationalString sampleDimDescription = sampleDim.getDescription();
this.configuredDescription = (sampleDimDescription == null || !sampleDimDescription.toString()
.equalsIgnoreCase(name)) ?
new SimpleInternationalString(name) : sampleDimDescription;
this.sampleDim = sampleDim;
final List<Category> categories = sampleDim.getCategories();
this.configuredRange = info.getRange();
this.customCategories = categories;
final String uom = info.getUnit();
Unit defaultUnit = sampleDim.getUnits();
Unit unit = defaultUnit;
try {
if (uom != null) {
unit = Unit.valueOf(uom);
}
} catch (IllegalArgumentException iae) {
if (LOGGER.isLoggable(Level.WARNING) && defaultUnit != null) {
LOGGER.warning("Unable to parse the specified unit (" + uom
+ "). Using the previous one: " + defaultUnit.toString());
}
}
this.configuredUnit = unit;

// custom null values
final List<Double> nullValues = info.getNullValues();
if (nullValues != null && nullValues.size() > 0) {
final int size = nullValues.size();
configuredNoDataValues = new double[size];
for (int i = 0; i < size ; i++) {
configuredNoDataValues[i] = nullValues.get(i);
}
} else {
this.configuredNoDataValues = sampleDim.getNoDataValues();
}

// Check if the nodata has been configured
boolean nodataConfigured = configuredNoDataValues != null
&& configuredNoDataValues.length > 0;
// custom categories
int numCategories = 0;
if (categories != null && (numCategories = categories.size()) > 0) {
this.customCategories = new ArrayList<Category>(numCategories);
Category wrapped = null;
for (Category category : categories) {
wrapped = category;
if (Category.NODATA.getName().equals(category.getName())) {
if (category.isQuantitative()) {
// Get minimum and maximum value
double minimum = nodataConfigured ? configuredNoDataValues[0]
: category.getRange().getMinimum();
double maximum = nodataConfigured ? configuredNoDataValues[0]
: category.getRange().getMaximum();
if (Double.isNaN(minimum) && Double.isNaN(maximum)) {
// Create a qualitative category
wrapped = new Category(Category.NODATA.getName(),
category.getColors()[0], minimum);
} else {
// Create the wrapped category
wrapped = new Category(Category.NODATA.getName(),
category.getColors(), NumberRange.create(minimum, maximum));
}
}
}
customCategories.add(wrapped);
}
}
}

private void parseUOM(StringBuilder label, Unit uom) { private void parseUOM(StringBuilder label, Unit uom) {
String uomString = uom.toString(); String uomString = uom.toString();
uomString = uomString.replaceAll("\u00B2", "^2"); uomString = uomString.replaceAll("\u00B2", "^2");
Expand Down
Expand Up @@ -194,12 +194,12 @@ protected GridSampleDimension[] wrapDimensions(SampleDimension[] dims) {
for (CoverageBand band : coverageBands) { for (CoverageBand band : coverageBands) {
if (storedDimensions != null && storedDimensions.size() > 0) { if (storedDimensions != null && storedDimensions.size() > 0) {
CoverageDimensionInfo dimensionInfo = storedDimensions.get(band.getIndex()); CoverageDimensionInfo dimensionInfo = storedDimensions.get(band.getIndex());
wrappedDims[i] = new WrappedSampleDimension((GridSampleDimension) dims[i], wrappedDims[i] = WrappedSampleDimension.build((GridSampleDimension) dims[i],
dimensionInfo); dimensionInfo);
} else { } else {
CoverageDimensionInfo dimensionInfo = new CoverageDimensionImpl(); CoverageDimensionInfo dimensionInfo = new CoverageDimensionImpl();
dimensionInfo.setName(band.getDefinition()); dimensionInfo.setName(band.getDefinition());
wrappedDims[i] = new WrappedSampleDimension((GridSampleDimension) dims[i], wrappedDims[i] = WrappedSampleDimension.build((GridSampleDimension) dims[i],
dimensionInfo); dimensionInfo);
} }
i++; i++;
Expand Down
@@ -1,4 +1,4 @@
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved /* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2014 OpenPlans * (c) 2014 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root * This code is licensed under the GPL 2.0 license, available at the root
* application directory. * application directory.
Expand Down Expand Up @@ -63,7 +63,7 @@ public void testDimensionsWrapping() throws IOException {
nullValues.add(noData2); nullValues.add(noData2);
coverageDim.setNullValues(nullValues); coverageDim.setNullValues(nullValues);


final SampleDimension wrappedDim = new WrappedSampleDimension(sampleDim, coverageDim); final SampleDimension wrappedDim = WrappedSampleDimension.build(sampleDim, coverageDim);
double[] noData = wrappedDim.getNoDataValues(); double[] noData = wrappedDim.getNoDataValues();


assertEquals(2, noData.length); assertEquals(2, noData.length);
Expand All @@ -76,6 +76,43 @@ public void testDimensionsWrapping() throws IOException {


assertEquals(wrappedName, wrappedDim.getDescription().toString()); assertEquals(wrappedName, wrappedDim.getDescription().toString());
} }

@Test
public void testWrapCustomizationSurviveCopyConstructor() throws Exception {
final GridSampleDimension sampleDim = new GridSampleDimension("original",
SampleDimensionType.REAL_64BITS, ColorInterpretation.GRAY_INDEX,
null, null, new double[]{-9999.0}, -1000d, 1000d, 1d, 0d, null);

// Setting coverage dimension
final CoverageDimensionImpl coverageDim = new CoverageDimensionImpl();
final String wrappedName = "wrapped";
coverageDim.setName(wrappedName);
coverageDim.setDimensionType(SampleDimensionType.REAL_64BITS);

final double newMinimum = -2000d;
final double newMaximum = 2000d;
final NumberRange<Double> range = new NumberRange<Double>(Double.class, newMinimum, newMaximum);
coverageDim.setRange(range);

final List<Double> nullValues = new ArrayList<Double>();
final double noData1 = -32768d;
final double noData2 = -32767d;
nullValues.add(noData1);
nullValues.add(noData2);
coverageDim.setNullValues(nullValues);

final SampleDimension wrappedDim = WrappedSampleDimension.build(sampleDim, coverageDim);
double[] noData = wrappedDim.getNoDataValues();

assertEquals(2, noData.length);
assertEquals(noData1, noData[0], DELTA);
assertEquals(noData2, noData[1], DELTA);

NumberRange wrappedRange = ((WrappedSampleDimension)wrappedDim).getRange();
assertEquals(newMinimum, wrappedRange.getMinimum(), DELTA);
assertEquals(newMaximum, wrappedRange.getMaximum(), DELTA);

}


/** /**
* Test that the wrapped nodata categories contains the defined nodata * Test that the wrapped nodata categories contains the defined nodata
Expand Down Expand Up @@ -106,16 +143,15 @@ public void testNoDataCategoryWrapping() throws IOException {
new Color(0, 0, 0, 0), Double.NaN) }, null); new Color(0, 0, 0, 0), Double.NaN) }, null);


// Wrap the dimension // Wrap the dimension
GridSampleDimension wrappedDim = new WrappedSampleDimension(sampleDim, coverageDim); GridSampleDimension wrappedDim = WrappedSampleDimension.build(sampleDim, coverageDim);


// Ensure nodata are correct // run the copy constructor
double[] noData = wrappedDim.getNoDataValues(); GridSampleDimension copy = new GridSampleDimension(wrappedDim) {
assertEquals(2, noData.length); // the constructor is visible only to subclasses, hence this hack
assertEquals(noData1, noData[0], DELTA); };
assertEquals(noData2, noData[1], DELTA);


// Extract categories // Extract categories
List<Category> categories = wrappedDim.getCategories(); List<Category> categories = copy.getCategories();


// Ensure NoData Category is present // Ensure NoData Category is present
Category category = categories.get(0); Category category = categories.get(0);
Expand All @@ -131,16 +167,10 @@ public void testNoDataCategoryWrapping() throws IOException {
0, 0, 0) }, NumberRange.create(-9999, -9999)) }, null); 0, 0, 0) }, NumberRange.create(-9999, -9999)) }, null);


// Wrap the dimension // Wrap the dimension
wrappedDim = new WrappedSampleDimension(sampleDim, coverageDim); copy = WrappedSampleDimension.build(sampleDim, coverageDim);

// Ensure nodata are correct
noData = wrappedDim.getNoDataValues();
assertEquals(2, noData.length);
assertEquals(noData1, noData[0], DELTA);
assertEquals(noData2, noData[1], DELTA);


// Extract categories // Extract categories
categories = wrappedDim.getCategories(); categories = copy.getCategories();


// Ensure NoData Category is present // Ensure NoData Category is present
category = categories.get(0); category = categories.get(0);
Expand Down Expand Up @@ -168,7 +198,7 @@ public void testNoRange() throws IOException {
coverageDim.setName(wrappedName); coverageDim.setName(wrappedName);
coverageDim.setDimensionType(SampleDimensionType.REAL_64BITS); coverageDim.setDimensionType(SampleDimensionType.REAL_64BITS);
// Creation of the WrappedSampleDimension // Creation of the WrappedSampleDimension
SampleDimension wrappedDim = new WrappedSampleDimension(sampleDim, coverageDim); SampleDimension wrappedDim = WrappedSampleDimension.build(sampleDim, coverageDim);
// Get the range // Get the range
NumberRange<? extends Number> wrappedRange = ((WrappedSampleDimension) wrappedDim) NumberRange<? extends Number> wrappedRange = ((WrappedSampleDimension) wrappedDim)
.getRange(); .getRange();
Expand All @@ -183,7 +213,7 @@ public void testNoRange() throws IOException {
// Configure a new GridSampleDimension without categories // Configure a new GridSampleDimension without categories
sampleDim = new GridSampleDimension("original", null, new BaseUnit<Quantity>("test")); sampleDim = new GridSampleDimension("original", null, new BaseUnit<Quantity>("test"));
// New wrapped sample dimension // New wrapped sample dimension
wrappedDim = new WrappedSampleDimension(sampleDim, coverageDim); wrappedDim = WrappedSampleDimension.build(sampleDim, coverageDim);
// Get the range // Get the range
wrappedRange = ((WrappedSampleDimension) wrappedDim).getRange(); wrappedRange = ((WrappedSampleDimension) wrappedDim).getRange();
// Ensure the range is not present // Ensure the range is not present
Expand Down

0 comments on commit a63a265

Please sign in to comment.