/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2008, 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.coverage.io.range;
import java.awt.image.SampleModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.measure.Measure;
import javax.measure.quantity.Length;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import org.geotools.coverage.io.range.RangeAxisBin.WavelengthBin;
import org.geotools.feature.NameImpl;
import org.geotools.referencing.crs.DefaultEngineeringCRS;
import org.geotools.referencing.cs.DefaultCoordinateSystemAxis;
import org.geotools.referencing.cs.DefaultLinearCS;
import org.geotools.referencing.datum.DefaultEngineeringDatum;
import org.geotools.util.MeasurementRange;
import org.geotools.util.SimpleInternationalString;
import org.opengis.coverage.SampleDimension;
import org.opengis.feature.type.Name;
import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.datum.EngineeringDatum;
import org.opengis.util.InternationalString;
/**
* Definition of one axis in a field for which we have some
* measurements/observations/forecasts. The {@link RangeAxis} data structure
* describes the nature of each control variable for a certain {@link RangeDescriptor}
*
*
* @author Simone Giannecchini, GeoSolutions
*/
public class RangeAxis{
/**
* Implementation of {@link RangeAxis} for multibands images.
*
* <p>
* This implementation of RangeAxis can be seen as a stub implementation since in
* this case we do not really have an {@link RangeAxis} for this kind of data, or
* rather we have an axis that just represents an ordinal or a certain set of .
*
* @author Simone Giannecchini, GeoSolutions
* @todo add convenience constructor based on {@link SampleDimension} and or
* {@link SampleModel}
*/
public static class DimensionlessAxis extends RangeAxis {
/**
*
*/
public DimensionlessAxis(final Name name,final InternationalString description) {
super(name,description,Unit.ONE );
}
/**
*
*/
public DimensionlessAxis(final String name,final String description) {
super(new NameImpl(name),new SimpleInternationalString(description),Unit.ONE );
}
/**
*
*/
public DimensionlessAxis(final String name) {
super(new NameImpl(name),new SimpleInternationalString(name),Unit.ONE );
}
}
public static class WavelengthAxis extends RangeAxis{
/**
* Singleton instance of a {@link WavelengthAxis} that measures in nanometers.
*/
public final static WavelengthAxis WAVELENGTH_AXIS_NM= new WavelengthAxis("WAVELENGTH_AXIS_NM",RangeUtilities.WAVELENGTH_UOM);
/**
* Keys for this {@link RangeAxis}.
*/
private ArrayList<Measure<MeasurementRange<Double>, Length>> keys;
private NameImpl name;
/** LANDSAT7 definition of BLUE */
public static final WavelengthBin LANDSAT7_BLUE_AXIS_BIN= new WavelengthBin( "BLUE", 450, 520, "useful for soil/vegetation discrimination, forest type mapping, and identifying man-made features",WavelengthAxis.WAVELENGTH_AXIS_NM);
/** Blue light between 450-495 nm */
public static final WavelengthBin COLOR_BLUE_AXIS_BIN= new WavelengthBin( "Blue", 450, 495, "Visible light between 450-495 nm" ,WavelengthAxis.WAVELENGTH_AXIS_NM);
/** Green light between 495-570 nm */
public static final WavelengthBin COLOR_GREEN_AXIS_BIN= new WavelengthBin( "Green", 495, 570, "Visible light between 495-570 nm" ,WavelengthAxis.WAVELENGTH_AXIS_NM);
/** Orange light between 590-620 nm */
public static final WavelengthBin COLOR_ORANGE_AXIS_BIN= new WavelengthBin( "Green", 590,620, "Visible light between 590-620 nm",WavelengthAxis.WAVELENGTH_AXIS_NM );
/** Red between 620-750 nm */
public static final WavelengthBin COLOR_RED_AXIS_BIN= new WavelengthBin( "Yellow", 620, 750, "Visible light between 620-750 nm" ,WavelengthAxis.WAVELENGTH_AXIS_NM);
/** Violet light between 380-450 nm */
public static final WavelengthBin COLOR_VIOLET_AXIS_BIN= new WavelengthBin( "Violet", 380, 450, "Visible light between 380-450 nm" ,WavelengthAxis.WAVELENGTH_AXIS_NM);
/** Yellow between 570-590 nm */
public static final WavelengthBin COLOR_YELLOW_AXIS_BIN= new WavelengthBin( "Yellow", 570,590, "Visible light between 570-590 nm" ,WavelengthAxis.WAVELENGTH_AXIS_NM);
/** LANDSAT7 definition of GREEN */
public static final WavelengthBin GREEN_AXIS_BIN= new WavelengthBin( "GREEN", 520, 610, "penetrates clear water fairly well, and gives excellent contrast between clear and turbid (muddy) water.",WavelengthAxis.WAVELENGTH_AXIS_NM);
/** LANDSAT7 definition of NIR */
public static final WavelengthBin NIR_AXIS_BIN =new WavelengthBin("NIR", 775, 900, " good for mapping shorelines and biomass content",WavelengthAxis.WAVELENGTH_AXIS_NM);
/** LANDSAT7 definition of RED */
public static final WavelengthBin RED_AXIS_BIN= new WavelengthBin("RED", 630, 690, "useful for identifying vegetation types, soils, and urban (city and town) features",WavelengthAxis.WAVELENGTH_AXIS_NM);
/** LANDSAT7 definition of SWIR */
public static final WavelengthBin SWIR_AXIS_BIN =new WavelengthBin("SWIR", 1550, 17560, "useful to measure the moisture content of soil and vegetation",WavelengthAxis.WAVELENGTH_AXIS_NM);
/** LANDSAT7 definition of SWIR2 */
public static final WavelengthBin SWIR2_AXIS_BIN= new WavelengthBin("SWIR2", 2090, 23500, "useful to measure the moisture content of soil and vegetation",WavelengthAxis.WAVELENGTH_AXIS_NM);
/** LANDSAT7 definition of TIR */
public static final WavelengthBin TIR_AXIS_BIN= new WavelengthBin("TIR", 10400, 12500, "useful to observe temperature",WavelengthAxis.WAVELENGTH_AXIS_NM);
private static final DefaultEngineeringCRS CRS;
static {
final CoordinateSystemAxis csAxis = new DefaultCoordinateSystemAxis(
new SimpleInternationalString("Light"),
"\u03BB", // LAMBDA
AxisDirection.OTHER,
RangeUtilities.WAVELENGTH_UOM);
final DefaultLinearCS lightCS = new DefaultLinearCS("Light",csAxis);
final Map<String,Object> datumProperties = new HashMap<String,Object>();
datumProperties.put("name", "light");
final EngineeringDatum lightDatum = new DefaultEngineeringDatum( datumProperties );
CRS = new DefaultEngineeringCRS("Wave Length", lightDatum, lightCS );
}
/**
*
*/
public WavelengthAxis(final String name, final Unit<Length> uom) {
super(new NameImpl(name),new SimpleInternationalString(name),uom);
}
/**
* These are units of length; as such the are
* not restricted to a coordinate reference system.
*/
public SingleCRS getCoordinateReferenceSystem() {
return CRS;
}
public InternationalString getDescription() {
return new SimpleInternationalString("Spectral Information");
}
public Measure<MeasurementRange<Double>, Length> getKey(int keyIndex) {
return this.keys.get(keyIndex);
}
public List<Measure<MeasurementRange<Double>, Length>> getKeys() {
return Collections.unmodifiableList(keys);
}
public Name getName() {
return name;
}
public int getNumKeys() {
return keys.size();
}
public Unit<Length> getUnitOfMeasure() {
return SI.MICRO(SI.METER);
}
}
private InternationalString description;
private Name name;
private Unit<?> unit;
// private Direction direction;
// private Domain defaultDomain;
public RangeAxis( final String name, final Unit<?> unit){
this( new NameImpl( name ), new SimpleInternationalString( name ),unit );
}
public RangeAxis( final String name, final String description,final Unit<?> unit){
this( new NameImpl( name ), new SimpleInternationalString( description ),unit );
}
public RangeAxis( final Name name, final InternationalString description, final Unit<?> unit){
this.name = name;
this.unit = unit;
this.description = description;
}
/**
* Retrieves the description of the {@link RangeAxis}
*
* @return description of the {@link RangeAxis}
*/
public InternationalString getDescription() {
return description;
}
/**
* Retrieves the {@link RangeAxis} name
*
* @return {@link org.opengis.feature.type.Name} of the {@link RangeAxis}s
*/
public Name getName() {
return name;
}
/**
* Retrieves the Unit of measure for the various keys of this axis.
*
* In case this {@link RangeAxis} is not made of measurable quantities
*
* @return the Unit of measure for the various keys of this axis.
*/
public Unit<?> getUnitOfMeasure() {
return unit;
}
public <V> boolean isBinCompatible(final RangeAxisBin<V> bin){
return bin.getAxis().equals(this);
}
@Override
public String toString() {
final StringBuilder builder= new StringBuilder();
builder.append("RangeAxis description").append("\n");
builder.append("Name:").append("\t\t\t\t\t").append(name.toString()).append("\n");
builder.append("Description:").append("\t\t\t\t").append(description.toString()).append("\n");
builder.append("Unit:").append("\t\t\t\t\t").append(unit!=null?unit.toString():"null uom").append("\n");
return builder.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((unit == null) ? 0 : unit.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RangeAxis that = (RangeAxis) obj;
if (description == null) {
if (that.description != null)
return false;
} else if (!description.toString().equalsIgnoreCase(that.description.toString()))
return false;
if (name == null) {
if (that.name != null)
return false;
} else if (!name.toString().equalsIgnoreCase(that.name.toString()))
return false;
if (unit == null) {
if (that.unit != null)
return false;
} else if (!unit.equals(that.unit))
return false;
return true;
}
public boolean compatibleWith(final RangeAxis that){
// if the two axis are equals then we have compatibility
if(equals(that))
return true;
if (unit == null) {
if (that.unit != null)
return false;
} else if (!unit.equals(that.unit))
return false;
return false;
}
}