use of org.opengis.coverage.grid.RectifiedGrid in project geotoolkit by Geomatys.
the class TiffImageReader method createMetadata.
/**
* {@inheritDoc }.
*/
@Override
protected SpatialMetadata createMetadata(final int imageIndex) throws IOException {
if (imageIndex < 0) {
// stream metadata
return super.createMetadata(imageIndex);
}
checkLayers();
final int layerIndex = getLayerIndex(imageIndex);
if (metaHeads[layerIndex] == null) {
selectLayer(layerIndex);
}
headProperties = metaHeads[layerIndex];
fillRootMetadataNode(layerIndex);
// -- find geotiff extensions
if (extensions == null) {
extensions = Collections.unmodifiableList(Arrays.stream(GeoTiffExtension.getExtensions()).filter(ext -> ext.isPresent(input)).map(GeoTiffExtension::newInstance).collect(Collectors.toList()));
}
final IIOTiffMetadata metadata = new IIOTiffMetadata(roots[layerIndex]);
final GeoTiffMetaDataReader metareader = new GeoTiffMetaDataReader(metadata);
SpatialMetadata spatialMetadata;
/*
* We'll try to fill referencing information from GeoTiff file. If it
* fails, we delay error, because there's a chance that one of the
* declared extensions is able to provide it. For example, user could
* have provided prj and tfw file, transforming the geotiff in a world
* file tiff image.
*/
FactoryException referencingError = null;
try {
spatialMetadata = metareader.readSpatialMetaData();
} catch (FactoryException ex) {
if (extensions.isEmpty()) {
throw new IOException("Bad referencing information found in GeoTiff", ex);
}
LOGGER.log(Level.WARNING, "Bad referencing information found. We'll continue and try to check on potential extensions (Dimap, Worldd file, etc.)", ex);
spatialMetadata = new SpatialMetadata(SpatialMetadataFormat.getImageInstance(SpatialMetadataFormat.GEOTK_FORMAT_NAME));
// Even if geographic information is bad, we try to get other metadata, as it could be important for data description.
new ThirdPartyMetaDataReader(metadata).fillSpatialMetaData(spatialMetadata);
}
// -- fill extensions informations
for (GeoTiffExtension ext : extensions) {
spatialMetadata = ext.fillSpatialMetaData(this, spatialMetadata);
}
final CoordinateReferenceSystem crs = spatialMetadata.getInstanceForType(CoordinateReferenceSystem.class);
final RectifiedGrid rectifiedGrid = spatialMetadata.getInstanceForType(RectifiedGrid.class);
if ((crs == null || rectifiedGrid == null) && referencingError != null) {
// Geotiff referencing is bad, and no extension allowed for proper correction, so we stop reading immediately.
throw new IOException("Bad referencing information found", referencingError);
}
// -- search for the coordinate reference system
if (crs == null) {
LOGGER.log(Level.FINE, "Current data : " + input.toString() + " doesn't contain any Coordinate Reference System.");
}
// -- verify GridToCrs pertinency
if (rectifiedGrid == null) {
LOGGER.log(Level.FINE, "Current data : " + input.toString() + " doesn't contain any Tie Points or GridToCrs transformation function.");
}
return spatialMetadata;
}
use of org.opengis.coverage.grid.RectifiedGrid in project geotoolkit by Geomatys.
the class AsciiGridWriter method prepareHeader.
/**
* Fills the given {@code header} map with values extracted from the given image metadata.
* The {@code "NCOLS"} and {@code "NROWS"} attributes are already defined when this method
* is invoked. This method is responsible for filling the remaining attributes.
*
* @param metadata The metadata.
* @param header The map in which to store the (<var>key</var>, <var>value</var>) pairs
* to be written.
* @return The fill value, or {@code Double#NaN} if none.
* @throws IOException If the metadata can not be prepared.
*/
private String prepareHeader(final SpatialMetadata metadata, final Map<String, String> header, final ImageWriteParam param) throws IOException {
final MetadataHelper helper = new MetadataHelper(this);
final Georectified spatialRp = metadata.getInstanceForType(Georectified.class);
final RectifiedGrid domain = metadata.getInstanceForType(RectifiedGrid.class);
final PixelOrientation ptInPixel = (spatialRp != null) ? spatialRp.getPointInPixel() : null;
final AffineTransform gridToCRS = helper.getAffineTransform(domain, param);
String xll = "XLLCORNER";
String yll = "YLLCORNER";
// reverted (i.e. the corresponding value in OffsetVectors is negative).
if (ptInPixel != null && !ptInPixel.equals(PixelOrientation.UPPER_LEFT)) {
if (ptInPixel.equals(PixelOrientation.CENTER)) {
xll = "XLLCENTER";
yll = "YLLCENTER";
} else if (ptInPixel.equals(PixelOrientation.valueOf("UPPER"))) {
yll = "YLLCENTER";
} else if (ptInPixel.equals(PixelOrientation.valueOf("LEFT"))) {
xll = "XLLCENTER";
} else {
throw new ImageMetadataException(Warnings.message(this, Errors.Keys.IllegalParameterValue_2, "pointInPixel", ptInPixel));
}
}
header.put(xll, String.valueOf(gridToCRS.getTranslateX()));
header.put(yll, String.valueOf(gridToCRS.getTranslateY()));
/*
* Use the CELLSIZE attribute if the pixels are square, or the DX, DY attibutes
* if they are rectangular and we are allowed to use those non-standard attributes.
*/
try {
header.put("CELLSIZE", String.valueOf(helper.getCellSize(gridToCRS)));
} catch (IIOException e) {
final Dimension2D size;
if (strictCellSize || (size = helper.getCellDimension(gridToCRS)) == null) {
throw e;
}
Warnings.log(this, null, AsciiGridWriter.class, "writeHeader", e);
header.put("DX", String.valueOf(size.getWidth()));
header.put("DY", String.valueOf(size.getHeight()));
}
/*
* Get the fill sample value, which is optional. The default defined by
* the ASCII grid format is -9999.
*/
String fillValue = DEFAULT_FILL;
final List<SampleDimension> dimensions = metadata.getListForType(SampleDimension.class);
if (!isNullOrEmpty(dimensions)) {
final SampleDimension dim = dimensions.get(0);
if (dim != null) {
final double[] fillValues = dim.getFillSampleValues();
if (fillValues != null && fillValues.length != 0) {
final double value = fillValues[0];
if (!Double.isNaN(value)) {
fillValue = CharSequences.trimFractionalPart(String.valueOf(value)).toString();
header.put("NODATA_VALUE", fillValue);
}
}
}
}
return fillValue;
}
use of org.opengis.coverage.grid.RectifiedGrid in project geotoolkit by Geomatys.
the class ImageCoverageReader method getGridGeometry.
/**
* Returns the grid geometry for the {@link GridCoverage2D} to be read at the given index.
* The default implementation performs the following:
* <p>
* <ul>
* <li>The {@link GridExtent} is determined from the
* {@linkplain SpatialImageReader#getGridEnvelope(int) spatial image reader}
* if possible, or from the image {@linkplain ImageReader#getWidth(int) width}
* and {@linkplain ImageReader#getHeight(int) height} otherwise.</li>
* <li>The {@link CoordinateReferenceSystem} and the "<cite>grid to CRS</cite>" conversion
* are determined from the {@link SpatialMetadata} if any.</li>
* </ul>
*
* @return The grid geometry for the {@link GridCoverage} at the specified index.
* @throws IllegalStateException If the input source has not been set.
* @throws IndexOutOfBoundsException If the supplied index is out of bounds.
* @throws CoverageStoreException If an error occurs while reading the information from the input source.
* @throws CancellationException If {@link #abort()} has been invoked in an other thread during
* the execution of this method.
*
* @see ImageReader#getWidth(int)
* @see ImageReader#getHeight(int)
*/
public GridGeometry getGridGeometry() throws DataStoreException {
final int index = 0;
GridGeometry gridGeometry = getCached(gridGeometries, index);
if (gridGeometry == null) {
// Protect from changes.
final ImageReader imageReader = this.imageReader;
if (imageReader == null) {
throw new IllegalStateException(formatErrorMessage(Errors.Keys.NoImageInput));
}
/*
* Get the required information from the SpatialMetadata, if any.
* For now we just collect them - they will be processed later.
*/
CoordinateReferenceSystem crs = null;
MathTransform gridToCRS = null;
PixelOrientation pointInPixel = null;
final int width, height;
try {
width = imageReader.getWidth(index);
height = imageReader.getHeight(index);
final SpatialMetadata metadata = getImageMetadata(imageReader, index);
if (metadata != null) {
crs = metadata.getInstanceForType(CoordinateReferenceSystem.class);
if (crs == null) {
crs = PredefinedCRS.GRID_2D;
}
if (crs instanceof GridGeometry) {
// Some formats (e.g. NetCDF) do that.
gridToCRS = ((GridGeometry) crs).getGridToCRS(PixelInCell.CELL_CENTER);
} else {
final RectifiedGrid grid = metadata.getInstanceForType(RectifiedGrid.class);
if (grid != null) {
gridToCRS = getMetadataHelper().getGridToCRS(grid);
}
final Georectified georect = metadata.getInstanceForType(Georectified.class);
if (georect != null) {
pointInPixel = georect.getPointInPixel();
}
}
}
} catch (IOException e) {
throw new CoverageStoreException(formatErrorMessage(e), e);
}
/*
* If any metadata are still null, replace them by their default values. Those default
* values are selected in order to be as neutral as possible: An ImageCRS which is not
* convertible to GeodeticCRS, an identity "grid to CRS" conversion, a PixelOrientation
* equivalent to performing no shift at all in the "grid to CRS" conversion.
*/
if (crs == null) {
crs = PredefinedCRS.GRID_2D;
}
final int dimension = crs.getCoordinateSystem().getDimension();
if (gridToCRS == null) {
gridToCRS = MathTransforms.identity(dimension);
}
if (pointInPixel == null) {
pointInPixel = PixelOrientation.CENTER;
}
/*
* Now build the grid geometry. Note that the grid extent spans shall be set to 1
* for all dimensions other than X and Y, even if the original file has more data,
* since this is a GridGeometry2D requirement.
*/
final long[] lower = new long[dimension];
final long[] upper = new long[dimension];
Arrays.fill(upper, 1);
upper[X_DIMENSION] = width;
upper[Y_DIMENSION] = height;
final GridExtent gridExtent = new GridExtent(null, lower, upper, false);
final PixelInCell pixelInCell = pointInPixel == PixelOrientation.CENTER ? PixelInCell.CELL_CENTER : PixelInCell.CELL_CORNER;
gridGeometry = new GridGeometry(gridExtent, pixelInCell, gridToCRS, crs);
Map.Entry<Map<Integer, GridGeometry>, GridGeometry> entry = setCached(gridGeometry, gridGeometries, index);
gridGeometries = entry.getKey();
gridGeometry = entry.getValue();
}
return gridGeometry;
}
use of org.opengis.coverage.grid.RectifiedGrid in project geotoolkit by Geomatys.
the class MetadataHelperTest method testUniformTransform.
/**
* Same as {@link #testAffineTransform}, but with a uniform scale.
*
* @throws ImageMetadataException Should not happen.
*/
@Test
public void testUniformTransform() throws ImageMetadataException {
// Creates a simple metadata.
final SpatialMetadata metadata = new SpatialMetadata(SpatialMetadataFormat.getImageInstance(GEOTK_FORMAT_NAME));
final GridDomainAccessor accessor = new GridDomainAccessor(metadata);
accessor.setOrigin(-10, -20);
accessor.addOffsetVector(4, 0);
accessor.addOffsetVector(0, -4);
// Tests the metadata.
final MetadataHelper hlp = new MetadataHelper(this);
final RectifiedGrid grid = metadata.getInstanceForType(RectifiedGrid.class);
final AffineTransform tr = hlp.getAffineTransform(grid, null);
assertEquals(-10, tr.getTranslateX(), EPS);
assertEquals(-20, tr.getTranslateY(), EPS);
assertEquals(4, tr.getScaleX(), EPS);
assertEquals(-4, tr.getScaleY(), EPS);
assertEquals(0, tr.getShearX(), EPS);
assertEquals(0, tr.getShearY(), EPS);
assertEquals(4, hlp.getCellSize(tr), EPS);
assertEquals(new DoubleDimension2D(4, 4), hlp.getCellDimension(tr));
assertEquals("4", hlp.formatCellDimension(grid, null));
}
use of org.opengis.coverage.grid.RectifiedGrid in project geotoolkit by Geomatys.
the class SpatialMetadataTest method testRectifiedGrid.
/**
* Tests the {@link SpatialMetadata#getInstanceForType} method for an {@link RectifiedGrid}
* metadata.
*/
@Test
public void testRectifiedGrid() {
final SpatialMetadata metadata = new SpatialMetadata(SpatialMetadataFormat.getImageInstance(GEOTK_FORMAT_NAME));
/*
* Write a few data using the accessor.
*/
final int[] limitsLow = new int[] { 4, 10, 16 };
final int[] limitsHigh = new int[] { 6, 2, 8 };
final double[] vector0 = new double[] { 2, 5, 8 };
final double[] vector1 = new double[] { 3, 1, 4 };
MetadataNodeAccessor accessor = new MetadataNodeAccessor(metadata, null, "RectifiedGridDomain/Limits", null);
accessor.setAttribute("low", limitsLow);
accessor.setAttribute("high", limitsHigh);
accessor = new MetadataNodeAccessor(metadata, null, "RectifiedGridDomain/OffsetVectors", "OffsetVector");
accessor.selectChild(accessor.appendChild());
accessor.setAttribute("values", vector0);
accessor.selectChild(accessor.appendChild());
accessor.setAttribute("values", vector1);
/*
* Read the RectifiedGrid metadata.
*/
final RectifiedGrid grid = metadata.getInstanceForType(RectifiedGrid.class);
final GridEnvelope ge = grid.getExtent();
// assertArrayEquals(limitsLow, ge.getLow ().getCoordinateValues());
// assertArrayEquals(limitsHigh, ge.getHigh().getCoordinateValues());
final List<double[]> vectors = grid.getOffsetVectors();
assertEquals(2, vectors.size());
assertTrue(Arrays.equals(vector0, vectors.get(0)));
assertTrue(Arrays.equals(vector1, vectors.get(1)));
}
Aggregations