use of org.opengis.metadata.identification.Resolution in project geotoolkit by Geomatys.
the class ImageCoverageReaderTest method testMetadata.
/**
* Tests the reading of ISO 19115 metadata. This also tests indirectly the reading of stream
* and image metadata. Note that correct metadata are required for correct working of read
* operations.
*
* @throws IOException If the text file can not be open (should not happen).
* @throws CoverageStoreException Should not happen.
* @throws JAXBException If the metadata can not be marshalled to XML (should not happen).
*
* @since 3.18
*/
@Test
@Ignore("Need to be revisited during the migration to Apache SIS.")
public void testMetadata() throws IOException, DataStoreException, JAXBException {
final ImageCoverageReaderInspector reader = new ImageCoverageReaderInspector("readFull");
reader.setInput(TestData.file(TextMatrixImageReaderTest.class, "matrix.txt"));
assertEquals(WorldFileImageReader.class, reader.imageReader.getClass());
final Metadata metadata = reader.getMetadata();
final Identification identification = getSingleton(metadata.getIdentificationInfo());
final Resolution resolution = getSingleton(((DataIdentification) identification).getSpatialResolutions());
assertEquals(Double.valueOf(1000), resolution.getDistance());
final String xml = XML.marshal(metadata);
assertFalse("Nothing to write.", xml.isEmpty());
assertXmlEquals(TestData.url(ImageCoverageReaderTest.class, "MatrixMetadata.xml"), xml, 0.0001, null, new String[] { "xmlns:*", "xsi:schemaLocation" });
}
use of org.opengis.metadata.identification.Resolution in project geotoolkit by Geomatys.
the class ImageCoverageReader method getMetadata.
/**
* Returns the ISO 19115 metadata object associated with the input source as a whole
* and each coverages. The default implementation constructs the metadata from the
* {@linkplain #getStreamMetadata() stream metadata} and the
* {@linkplain #getCoverageMetadata(int) coverage metadata},
* eventually completed by the {@link #getGridGeometry(int)}.
* <p>
* Since the relationship between Image I/O metadata and ISO 19115 is not always a
* "<cite>one-to-one</cite>" relationship, this method works on a best effort basis.
*
* @return The ISO 19115 metadata (never {@code null}).
* @throws CoverageStoreException If an error occurs while reading the information from the input source.
*
* @see <a href="../../image/io/metadata/SpatialMetadataFormat.html#default-formats">Metadata formats</a>
*
* @since 3.18
*/
public Metadata getMetadata() throws DataStoreException {
final SpatialMetadata streamMetadata = getStreamMetadata();
final DefaultMetadata metadata = createMetadata(streamMetadata);
/*
* Extract all information available from the stream metadata, provided that metadata
* elements were not already provided by the above call to createMetadata(...). Since
* createMetadata(...) typically get its information from the stream metadata as well,
* we assume that creating here new objects from stream metadata would be redundant.
*/
DataIdentification identification = null;
if (streamMetadata != null) {
final Collection<DataQuality> quality = metadata.getDataQualityInfo();
if (quality.isEmpty()) {
addIfNonNull(quality, streamMetadata.getInstanceForType(DataQuality.class));
}
final Collection<AcquisitionInformation> acquisition = metadata.getAcquisitionInformation();
if (acquisition.isEmpty()) {
addIfNonNull(acquisition, streamMetadata.getInstanceForType(AcquisitionInformation.class));
}
/*
* Get the existing identification info if any, or create a new one otherwise.
* If an identification info is found, remove it from the metadata (it will be
* added back at the end of this method, or a copy of it will be added).
*/
final Iterator<Identification> it = metadata.getIdentificationInfo().iterator();
while (it.hasNext()) {
final Identification candidate = it.next();
if (candidate instanceof DataIdentification) {
identification = (DataIdentification) candidate;
it.remove();
break;
}
}
if (identification == null) {
identification = streamMetadata.getInstanceForType(DataIdentification.class);
}
}
/*
* Check if we should complete the extents and resolutions. We will do so only
* if the vertical/temporal extent, geographic bounding box and resolution are
* not already provided in the metadata. If the geographic extent is declared
* by an other kind of object than GeographicBoundingBox, we will still add the
* bounding box because the existing extent could be only a textual description.
*/
// For logging warning only once.
boolean failed = false;
// 'false' if extents are already present.
boolean computeExtents = true;
// 'false' is resolutions are already present.
boolean computeResolutions = true;
// The extent to compute, if needed.
DefaultExtent extent = null;
// The extents already provided in the metadata.
List<Extent> extents = null;
// The resolutions to compute, if needed.
Set<Resolution> resolutions = null;
if (identification != null) {
computeResolutions = isNullOrEmpty(identification.getSpatialResolutions());
final Collection<? extends Extent> existings = identification.getExtents();
if (!isNullOrEmpty(existings)) {
extents = new ArrayList<>(existings);
extent = UniqueExtents.getIncomplete(extents);
if (extent == null) {
// The plugin-provided Metadata instance seems to contain Extents
// that are complete enough, so we will not try to complete them.
computeExtents = false;
extents = null;
}
}
}
/*
* Check if we should complete the content info and the spatial representation info.
* If the plugin-provided metadata declare explicitly such information, we will not
* compute them in this method (the plugin information will have precedence).
*/
final Collection<ContentInformation> contentInfo = metadata.getContentInfo();
final Collection<SpatialRepresentation> spatialInfo = metadata.getSpatialRepresentationInfo();
final boolean computeContent = (contentInfo != null) && contentInfo.isEmpty();
final boolean computeSpatial = (spatialInfo != null) && spatialInfo.isEmpty();
if (computeContent || computeSpatial || computeResolutions || computeExtents) {
final GenericName coverageName = getCoverageName();
if (computeContent || computeSpatial) {
CoverageDescription ci = null;
final SpatialMetadata coverageMetadata = getCoverageMetadata();
if (coverageMetadata != null) {
if (computeContent) {
ci = coverageMetadata.getInstanceForType(ImageDescription.class);
if (ci != null) {
contentInfo.add(ci);
}
}
if (computeSpatial) {
final Georectified rectified = coverageMetadata.getInstanceForType(Georectified.class);
if (rectified != null) {
metadata.getSpatialRepresentationInfo().add(rectified);
}
}
}
/*
* Get or create the content info to store sample dimensions
*/
if (ci == null) {
// get or create it
if (contentInfo.size() > 0) {
CoverageDescription cd = contentInfo.stream().limit(1).filter(CoverageDescription.class::isInstance).map(CoverageDescription.class::cast).findFirst().orElse(null);
if (cd instanceof ModifiableMetadata && ((ModifiableMetadata) cd).state() != ModifiableMetadata.State.FINAL) {
ci = cd;
}
} else {
ci = new DefaultCoverageDescription();
contentInfo.add(ci);
}
}
if (ci != null && ci.getAttributeGroups() != null && ci.getAttributeGroups().isEmpty() && ci.getDimensions().isEmpty()) {
final List<SampleDimension> sampleDimensions = getSampleDimensions();
if (sampleDimensions != null) {
final MetadataBuilder mb = new MetadataBuilder();
for (int idx = 0, n = sampleDimensions.size(); idx < n; idx++) {
SampleDimension gsd = sampleDimensions.get(idx).forConvertedValues(true);
final Unit<? extends Quantity<?>> units = gsd.getUnits().orElse(null);
mb.newSampleDimension();
mb.setBandIdentifier(Names.createMemberName(null, null, "" + idx, Integer.class));
mb.addBandDescription(gsd.getName().toString());
if (units != null)
mb.setSampleUnits(units);
mb.addMinimumSampleValue(SampleDimensionUtils.getMinimumValue(gsd));
mb.addMaximumSampleValue(SampleDimensionUtils.getMaximumValue(gsd));
gsd = gsd.forConvertedValues(false);
gsd.getTransferFunctionFormula().ifPresent((f) -> {
mb.setTransferFunction(f.getScale(), f.getOffset());
});
}
final DefaultMetadata meta = mb.build();
final CoverageDescription imgDesc = (CoverageDescription) meta.getContentInfo().iterator().next();
ci.getAttributeGroups().addAll((Collection) imgDesc.getAttributeGroups());
}
}
}
if (computeResolutions || computeExtents) {
/*
* Resolution along the horizontal axes only, ignoring all other axes. For linear units (feet,
* kilometres, etc.), we convert the units to metres for compliance with a current limitation
* of Apache SIS, which can handle only metres. For angular resolution (typically in degrees),
* we perform an APPROXIMATE conversion to metres using the nautical mile definition. This
* conversion is only valid along the latitudes axis (the number is wrong along the longitude
* axis), and more accurate for mid-latitude (the numbers are differents close to equator or
* to the poles).
*/
final GridGeometry gg = getGridGeometry();
if (computeResolutions && gg.isDefined(GridGeometry.CRS)) {
double[] res = null;
try {
res = gg.getResolution(false);
} catch (IncompleteGridGeometryException ex) {
}
final Quantity<?> m = CRSUtilities.getHorizontalResolution(gg.getCoordinateReferenceSystem(), res);
if (m != null) {
double measureValue = m.getValue().doubleValue();
final Unit<?> unit = m.getUnit();
Unit<?> standardUnit = null;
double scaleFactor = 1;
if (Units.isAngular(unit)) {
standardUnit = Units.DEGREE;
// From definition of nautical miles.
scaleFactor = (1852 * 60);
} else if (Units.isLinear(unit)) {
standardUnit = Units.METRE;
}
if (standardUnit != null)
try {
measureValue = unit.getConverterToAny(standardUnit).convert(measureValue) * scaleFactor;
final DefaultResolution resolution = new DefaultResolution();
resolution.setDistance(measureValue);
if (resolutions == null) {
resolutions = new LinkedHashSet<>();
}
resolutions.add(resolution);
} catch (IncommensurableException e) {
// In case of failure, do not create a Resolution object.
Logging.recoverableException(LOGGER, ImageCoverageReader.class, "getMetadata", e);
}
}
}
/*
* Horizontal, vertical and temporal extents. The horizontal extents is
* represented as a geographic bounding box, which may require a reprojection.
*/
if (computeExtents && gg.isDefined(GridGeometry.ENVELOPE)) {
if (extent == null) {
extent = new UniqueExtents();
}
try {
extent.addElements(gg.getEnvelope());
} catch (TransformException e) {
// Not a big deal if we fail. We will just let the identification section unchanged.
if (!failed) {
// Log only once.
failed = true;
Logging.recoverableException(LOGGER, ImageCoverageReader.class, "getMetadata", e);
}
}
}
}
}
/*
* At this point, we have computed extents and resolutions from every images
* in the stream. Now store the result. Note that we unconditionally create
* a copy of the identification info, even if the original object was already
* an instance of DefaultDataIdentification, because the original object may
* be cached in the ImageReader.
*/
if (extent != null || resolutions != null) {
final DefaultDataIdentification copy = new DefaultDataIdentification(identification);
if (extent != null) {
if (extents != null) {
copy.setExtents(extents);
} else {
copy.getExtents().add(extent);
}
}
if (resolutions != null) {
copy.setSpatialResolutions(resolutions);
}
identification = copy;
}
if (identification != null) {
metadata.getIdentificationInfo().add(identification);
}
return metadata;
}
use of org.opengis.metadata.identification.Resolution in project sis by apache.
the class DefaultSource method setScaleDenominator.
/**
* Sets the denominator of the representative fraction on a source map.
* This method stores the value in the
* {@linkplain #setSourceSpatialResolution(Resolution) source spatial resolution}.
*
* @param newValue the new scale denominator.
*
* @deprecated As of ISO 19115:2014, moved to {@link DefaultResolution#setEquivalentScale(RepresentativeFraction)}.
*/
@Deprecated
public void setScaleDenominator(final RepresentativeFraction newValue) {
checkWritePermission(sourceSpatialResolution);
Resolution resolution = null;
if (newValue != null) {
resolution = sourceSpatialResolution;
if (resolution instanceof DefaultResolution) {
((DefaultResolution) resolution).setEquivalentScale(newValue);
} else {
resolution = new DefaultResolution(newValue);
}
}
/*
* Invoke the non-deprecated setter method only if the reference changed,
* for consistency with other deprecated setter methods in metadata module.
*/
if (resolution != sourceSpatialResolution) {
setSourceSpatialResolution(resolution);
}
}
use of org.opengis.metadata.identification.Resolution in project geotoolkit by Geomatys.
the class LandsatMetadataParser method getMetadata.
/**
* Returns Landsat ISO19115 metadatas.
*/
public final DefaultMetadata getMetadata(final LandsatConstants.CoverageGroup group) throws FactoryException, ParseException {
ArgumentChecks.ensureNonNull("Metadata group name", group);
if (isoMetadata == null) {
// generate metadata
final DefaultMetadata baseMetadata = new DefaultMetadata();
assert metaGroups != null;
// ----------------------------------------------------------------------//
// ------------------------ Mandatory metadata --------------------------//
// ----------------------------------------------------------------------//
// -- set CRS
baseMetadata.setReferenceSystemInfo(Collections.singleton(getCRS()));
final Date metadataPublicationDate = getDateInfo();
if (metadataPublicationDate != null)
baseMetadata.setDateStamp(metadataPublicationDate);
// -- unique file identifier
baseMetadata.setFileIdentifier(UUID.randomUUID().toString());
// -- Iso metadatas 19115 generation date.
baseMetadata.setDateStamp(new Date());
// -- set bounding box
final double[] bbCoords = getProjectedBound2D();
final DefaultGeographicBoundingBox geo = new // -- long
DefaultGeographicBoundingBox(// -- long
bbCoords[0], // -- long
bbCoords[1], bbCoords[2], // -- lat
bbCoords[3]);
// -- geographic extent
final DefaultExtent ex = new DefaultExtent();
ex.setGeographicElements(Arrays.asList(geo));
// -- acquisition date
final DefaultTemporalExtent tex = new DefaultTemporalExtent();
final Date acquisitionDate = getAcquisitionDate();
tex.setBounds(acquisitionDate, acquisitionDate);
ex.setTemporalElements(Arrays.asList(tex));
// -- temporal extent
final NamedIdentifier extentName = new NamedIdentifier(null, "Landsat extent");
final Map<String, Object> propertiesExtent = new HashMap<>();
propertiesExtent.put(IdentifiedObject.NAME_KEY, extentName);
final NamedIdentifier extentBeginName = new NamedIdentifier(null, "Landsat extent");
final Map<String, Object> propertiesBegin = new HashMap<>();
propertiesBegin.put(IdentifiedObject.NAME_KEY, extentBeginName);
final NamedIdentifier extentEnd = new NamedIdentifier(null, "Landsat extent");
final Map<String, Object> propertiesEnd = new HashMap<>();
propertiesEnd.put(IdentifiedObject.NAME_KEY, extentEnd);
tex.setExtent(new DefaultPeriod(propertiesExtent, new DefaultInstant(propertiesBegin, acquisitionDate), new DefaultInstant(propertiesEnd, acquisitionDate)));
// -- Resolution
final String reres = getValue(false, RESOLUTION_LABEL + group);
final Set<Resolution> res = new HashSet<>();
if (reres != null) {
final DefaultResolution defaultResolution = new DefaultResolution();
defaultResolution.setDistance(Double.valueOf(reres));
res.add(defaultResolution);
}
/**
* Three different Images Descriptions.
* - Reflective
* - Panchromatic
* - Thermal
*/
// -- Reflective description.
final DefaultImageDescription reflectiveImgDesc = new DefaultImageDescription();
final DefaultAttributeGroup dAGReflectiveRef = new DefaultAttributeGroup();
dAGReflectiveRef.setAttributes(getBandsInfos(CoverageGroup.REFLECTIVE, "REFLECTANCE"));
final DefaultAttributeGroup dAGReflectiveRad = new DefaultAttributeGroup();
dAGReflectiveRad.setAttributes(getBandsInfos(CoverageGroup.REFLECTIVE, "RADIANCE"));
final Set<AttributeGroup> reflectiveInfos = new HashSet<>();
reflectiveInfos.add(dAGReflectiveRef);
reflectiveInfos.add(dAGReflectiveRad);
reflectiveImgDesc.setAttributeGroups(reflectiveInfos);
// -- Panchromatic image description.
final DefaultImageDescription panchroImgDesc = new DefaultImageDescription();
final DefaultAttributeGroup dAGPanchromaRef = new DefaultAttributeGroup();
dAGPanchromaRef.setAttributes(getBandsInfos(CoverageGroup.PANCHROMATIC, "REFLECTANCE"));
final DefaultAttributeGroup dAGPanchromaRad = new DefaultAttributeGroup();
dAGPanchromaRad.setAttributes(getBandsInfos(CoverageGroup.PANCHROMATIC, "RADIANCE"));
final Set<AttributeGroup> panchroInfos = new HashSet<>();
panchroInfos.add(dAGPanchromaRef);
panchroInfos.add(dAGPanchromaRad);
panchroImgDesc.setAttributeGroups(panchroInfos);
// -- Thermal descriptions. (only define with Radiance)
final DefaultImageDescription thermalImgDesc = new DefaultImageDescription();
final DefaultAttributeGroup dAGThermalRad = new DefaultAttributeGroup();
dAGThermalRad.setAttributes(getBandsInfos(CoverageGroup.THERMAL, "RADIANCE"));
thermalImgDesc.setAttributeGroups(Collections.singleton(dAGThermalRad));
// -- image description
final String cloud = getValue(false, "CLOUD_COVER");
if (cloud != null) {
final double val = Double.valueOf(cloud);
reflectiveImgDesc.setCloudCoverPercentage(val);
panchroImgDesc.setCloudCoverPercentage(val);
thermalImgDesc.setCloudCoverPercentage(val);
}
final String sunAz = getValue(false, "SUN_AZIMUTH");
if (sunAz != null) {
final double val = Double.valueOf(sunAz);
reflectiveImgDesc.setIlluminationAzimuthAngle(val);
panchroImgDesc.setIlluminationAzimuthAngle(val);
thermalImgDesc.setIlluminationAzimuthAngle(val);
}
final String sunEl = getValue(false, "SUN_ELEVATION");
if (sunEl != null) {
final double val = Double.valueOf(sunEl);
reflectiveImgDesc.setIlluminationElevationAngle(val);
panchroImgDesc.setIlluminationElevationAngle(val);
thermalImgDesc.setIlluminationElevationAngle(val);
}
// ----------------------------------------------------------------------//
// ------------------------- optional metadatas -------------------------//
// ----------------------------------------------------------------------//
// -- set metadata Date publication
baseMetadata.setDateInfo(Collections.singleton(new DefaultCitationDate(metadataPublicationDate, DateType.PUBLICATION)));
// -- Distribution informations
final DefaultDistribution distribution = new DefaultDistribution();
final String origin = getValue(false, "ORIGIN");
if (origin != null)
distribution.setDescription(new DefaultInternationalString(origin));
final String outputFormat = getValue(false, "OUTPUT_FORMAT");
final String processSoftVersion = getValue(false, "PROCESSING_SOFTWARE_VERSION");
if ((outputFormat != null) && (processSoftVersion != null)) {
DefaultFormat f = new DefaultFormat();
f.setName(new SimpleInternationalString(outputFormat));
f.setVersion(new SimpleInternationalString(processSoftVersion));
distribution.setDistributionFormats(Collections.singleton(f));
}
baseMetadata.setDistributionInfo(Collections.singleton(distribution));
// -- Aquisition informations
final DefaultAcquisitionInformation dAI = new DefaultAcquisitionInformation();
// -- platform
final DefaultPlatform platform = new DefaultPlatform();
final String platF = getValue(false, "SPACECRAFT_ID");
if (platF != null) {
platform.setCitation(new DefaultCitation());
}
// -- instrument
final DefaultInstrument instru = new DefaultInstrument();
final String instrum = getValue(false, "SENSOR_ID");
if (instrum != null) {
instru.setType(new DefaultInternationalString(instrum));
}
if (platF != null && instrum != null) {
// -- set related founded instrument and platform
// *****************************************************************//
// -- a cycle is define here, platform -> instru and instru -> platform
// -- like a dad know his son and a son know his dad.
// -- during xml binding a cycle is not supported for the current Apach SIS version
// -- decomment this row when upgrade SIS version
// instru.setMountedOn(platform);
// *****************************************************************//
platform.setInstruments(Collections.singleton(instru));
dAI.setPlatforms(Collections.singleton(platform));
dAI.setInstruments(Collections.singleton(instru));
baseMetadata.setAcquisitionInformation(Collections.singleton(dAI));
}
// build each specific metadata
isoMetadata = new DefaultMetadata(baseMetadata);
panchromaticMetadatas = new DefaultMetadata(baseMetadata);
reflectiveMetadatas = new DefaultMetadata(baseMetadata);
thermalMetadatas = new DefaultMetadata(baseMetadata);
// -- all minimum mandatory metadatas.
// -- comment about data
final InternationalString abstractComment = new DefaultInternationalString(getValue(true, "ORIGIN"));
// -- dates
final Set<DefaultCitationDate> dateset = new HashSet<>();
dateset.add(new DefaultCitationDate(acquisitionDate, DateType.CREATION));
dateset.add(new DefaultCitationDate(metadataPublicationDate, DateType.PUBLICATION));
{
// general metadata
final NamedIdentifier identifier = CoverageGroup.ALL.createName(getValue(false, LandsatConstants.SCENE_ID));
final DefaultCitation titleCitation = new DefaultCitation(identifier.toString());
titleCitation.setIdentifiers(Collections.singleton(identifier));
titleCitation.setDates(dateset);
final DefaultDataIdentification ddii = new DefaultDataIdentification();
ddii.setExtents(Arrays.asList(ex));
ddii.setAbstract(abstractComment);
ddii.setCitation(titleCitation);
isoMetadata.setIdentificationInfo(Arrays.asList(ddii));
}
{
// panchromatic
final NamedIdentifier identifier = CoverageGroup.PANCHROMATIC.createName(getValue(false, LandsatConstants.SCENE_ID));
final DefaultCitation titleCitation = new DefaultCitation(identifier.toString());
titleCitation.setIdentifiers(Collections.singleton(identifier));
titleCitation.setDates(dateset);
final DefaultDataIdentification ddii = new DefaultDataIdentification();
ddii.setExtents(Arrays.asList(ex));
ddii.setAbstract(abstractComment);
ddii.setCitation(titleCitation);
ddii.setSpatialResolutions(res);
panchromaticMetadatas.setIdentificationInfo(Arrays.asList(ddii));
panchromaticMetadatas.setContentInfo(Arrays.asList(panchroImgDesc));
}
{
// reflective
final NamedIdentifier identifier = CoverageGroup.REFLECTIVE.createName(getValue(false, LandsatConstants.SCENE_ID));
final DefaultCitation titleCitation = new DefaultCitation(identifier.toString());
titleCitation.setIdentifiers(Collections.singleton(identifier));
titleCitation.setDates(dateset);
final DefaultDataIdentification ddii = new DefaultDataIdentification();
ddii.setExtents(Arrays.asList(ex));
ddii.setAbstract(abstractComment);
ddii.setCitation(titleCitation);
ddii.setSpatialResolutions(res);
reflectiveMetadatas.setIdentificationInfo(Arrays.asList(ddii));
reflectiveMetadatas.setContentInfo(Arrays.asList(reflectiveImgDesc));
}
{
// thermal
final NamedIdentifier identifier = CoverageGroup.THERMAL.createName(getValue(false, LandsatConstants.SCENE_ID));
final DefaultCitation titleCitation = new DefaultCitation(identifier.toString());
titleCitation.setIdentifiers(Collections.singleton(identifier));
titleCitation.setDates(dateset);
final DefaultDataIdentification ddii = new DefaultDataIdentification();
ddii.setExtents(Arrays.asList(ex));
ddii.setAbstract(abstractComment);
ddii.setCitation(titleCitation);
ddii.setSpatialResolutions(res);
thermalMetadatas.setIdentificationInfo(Arrays.asList(ddii));
thermalMetadatas.setContentInfo(Arrays.asList(thermalImgDesc));
final Set<ProcessStep> extendedInfos = getThermicInfos();
if (!extendedInfos.isEmpty()) {
final DefaultLineage defaultLineage = new DefaultLineage();
defaultLineage.setProcessSteps(extendedInfos);
thermalMetadatas.setResourceLineages(Collections.singleton(defaultLineage));
}
}
}
switch(group) {
case ALL:
return isoMetadata;
case PANCHROMATIC:
return panchromaticMetadatas;
case REFLECTIVE:
return reflectiveMetadatas;
case THERMAL:
return thermalMetadatas;
default:
throw new IllegalArgumentException("Unknown coverage " + group);
}
}
Aggregations