/* JAI-Ext - OpenSource Java Advanced Image Extensions Library * http://www.geo-solutions.it/ * Copyright 2014 - 2015 GeoSolutions * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package it.geosolutions.jaiext.range; import java.awt.image.DataBuffer; import java.util.ArrayList; import java.util.List; /** * This class is a factory class which creates a {@link Range} object for the specific data type. * This Range can have 2 bounds or be a single-point range. If the 2 bound values are equal and * almost one of them is included, then a single-point range is created, else an exception is * thrown. If the minimum bound value is bigger than the maximum value, then the 2 numbers are * inverted at the Range creation time. */ public class RangeFactory { private static final double TOLERANCE = 1E-6; // Private Constructor for avoiding a new factory instantiation private RangeFactory() { } // Byte data public static Range create(byte minValue, boolean minIncluded, byte maxValue, boolean maxIncluded) { return new RangeByte(minValue, minIncluded, maxValue, maxIncluded); } // Ushort data public static Range createU(short minValue, boolean minIncluded, short maxValue, boolean maxIncluded) { return new RangeUshort(minValue, minIncluded, maxValue, maxIncluded); } // Short data public static Range create(short minValue, boolean minIncluded, short maxValue, boolean maxIncluded) { return new RangeShort(minValue, minIncluded, maxValue, maxIncluded); } // Integer data public static Range create(int minValue, boolean minIncluded, int maxValue, boolean maxIncluded) { return new RangeInt(minValue, minIncluded, maxValue, maxIncluded); } // Float data public static Range create(float minValue, boolean minIncluded, float maxValue, boolean maxIncluded, boolean nanIncluded) { return new RangeFloat(minValue, minIncluded, maxValue, maxIncluded, nanIncluded); } // Double data public static Range create(double minValue, boolean minIncluded, double maxValue, boolean maxIncluded, boolean nanIncluded) { return new RangeDouble(minValue, minIncluded, maxValue, maxIncluded, nanIncluded); } // Byte data public static Range create(byte minValue, byte maxValue) { return new RangeByte(minValue, true, maxValue, true); } // Ushort data public static Range createU(short minValue, short maxValue) { return new RangeUshort(minValue, true, maxValue, true); } // Short data public static Range create(short minValue, short maxValue) { return new RangeShort(minValue, true, maxValue, true); } // Integer data public static Range create(int minValue, int maxValue) { return new RangeInt(minValue, true, maxValue, true); } // Float data public static Range create(float minValue, float maxValue) { return new RangeFloat(minValue, true, maxValue, true, false); } // Double data public static Range create(double minValue, double maxValue) { return new RangeDouble(minValue, true, maxValue, true, false); } // Float data public static Range create(float minValue, boolean minIncluded, float maxValue, boolean maxIncluded) { return new RangeFloat(minValue, minIncluded, maxValue, maxIncluded, false); } // Double data public static Range create(double minValue, boolean minIncluded, double maxValue, boolean maxIncluded) { return new RangeDouble(minValue, minIncluded, maxValue, maxIncluded, false); } // Long data public static Range create(long minValue, boolean minIncluded, long maxValue, boolean maxIncluded) { return new RangeLong(minValue, minIncluded, maxValue, maxIncluded); } public static Range convertToDoubleRange(Range input) { // If already double do nothing if (input instanceof RangeDouble) { return input; } // Otherwise get minimum and maximum values and convert it double min = input.getMin().doubleValue(); double max = input.getMax().doubleValue(); boolean minIncluded = input.isMinIncluded(); boolean maxIncluded = input.isMaxIncluded(); boolean nanIncluded = input.isNanIncluded(); // New Double range return new RangeDouble(min, minIncluded, max, maxIncluded, nanIncluded); } public static Range convertToFloatRange(Range input) { // If already double do nothing if (input instanceof RangeFloat) { return input; } // Otherwise get minimum and maximum values and convert it float min = input.getMin().floatValue(); float max = input.getMax().floatValue(); boolean minIncluded = input.isMinIncluded(); boolean maxIncluded = input.isMaxIncluded(); boolean nanIncluded = input.isNanIncluded(); // New Double range return new RangeFloat(min, minIncluded, max, maxIncluded, nanIncluded); } public static Range convert(Range input, int dataType) { if (input == null) { return null; } // If already double do nothing if (input.getDataType().getDataType() == dataType) { return input; } switch (dataType) { case DataBuffer.TYPE_BYTE: return RangeByte.FULL_RANGE.intersection(input); case DataBuffer.TYPE_USHORT: return RangeUshort.FULL_RANGE.intersection(input); case DataBuffer.TYPE_SHORT: return RangeShort.FULL_RANGE.intersection(input); case DataBuffer.TYPE_INT: return RangeInt.FULL_RANGE.intersection(input); case DataBuffer.TYPE_FLOAT: return RangeFloat.FULL_RANGE.intersection(input); case DataBuffer.TYPE_DOUBLE: return RangeDouble.FULL_RANGE.intersection(input); default: return null; } } public static Range convertToByteRange(Range input) { // If already double do nothing if (input instanceof RangeByte) { return input; } // Otherwise get minimum and maximum values and convert it byte min = input.getMin().byteValue(); byte max = input.getMax().byteValue(); boolean minIncluded = input.isMinIncluded(); boolean maxIncluded = input.isMaxIncluded(); // New Double range return new RangeByte(min, minIncluded, max, maxIncluded); } public static List<Range> subtract(Range r1, Range r2) { // Creation of the Range List List<Range> list = new ArrayList<Range>(); // Populating the list /* * Check for equality between inputs */ if (r1.equals(r2)) { return list; // empty list } Range common = intersect(r1, r2); /* * Check for no overlap between inputs */ if (common == null) { list.add(r2); return list; } /* * Check if r1 enclosed r2 */ if (common.equals(r2)) { return list; // empty list } // Checks on the minimum/maximum double min1 = r1.getMin().doubleValue(); double min2 = r2.getMin().doubleValue(); double max1 = r1.getMax().doubleValue(); double max2 = r2.getMax().doubleValue(); // Checks on the comparison between the min and max boolean minmin = equals(min1, min2); boolean maxmax = equals(max1, max2); boolean minmax = equals(min1, max2); boolean maxmin = equals(max1, min2); // Case 0a) min1 equals to max2 if (minmax) { if (r1.isMinIncluded()) { Range r = RangeFactory.create(min2, r2.isMinIncluded(), max2, false); list.add(r); return list; } else { list.add(r2); return list; } } // Case 0b) min2 equals to max1 if (maxmin) { if (r1.isMaxIncluded()) { Range r = RangeFactory.create(min2, false, max2, r2.isMinIncluded()); list.add(r); return list; } else { list.add(r2); return list; } } // Case 1) equal minimums and different max values if (minmin && max2 > max1 && !maxmax) { Range r = RangeFactory.create(max1, !r1.isMaxIncluded(), max2, r2.isMaxIncluded()); list.add(r); return list; } // Case 2) equal maximum and different min values if (maxmax && min2 < min1 && !minmin) { Range r = RangeFactory.create(min2, r2.isMinIncluded(), min1, !r1.isMinIncluded()); list.add(r); return list; } // Case 3) r2 on the left and r1 on the right if (min2 < min1 && max2 < max1) { Range r = RangeFactory.create(min2, r2.isMinIncluded(), min1, !r1.isMinIncluded()); list.add(r); return list; } // Case 4) r1 on the left and r2 on the right if (min2 > min1 && max2 > max1) { Range r = RangeFactory.create(max1, !r1.isMaxIncluded(), max2, r2.isMaxIncluded()); list.add(r); return list; } // Case 5) r1 contained in r2 (two ranges) if (min2 < min1 && max2 > max1) { Range r1New = RangeFactory.create(min2, r2.isMinIncluded(), min1, !r1.isMinIncluded()); Range r2New = RangeFactory.create(max1, !r1.isMaxIncluded(), max2, r2.isMaxIncluded()); list.add(r1New); list.add(r2New); return list; } return list; } public static Range intersect(Range r1, Range r2) { return r1.intersection(r2); } public static boolean equals(double d1, double d2) { return Math.abs(d1 - d2) < TOLERANCE; } }