/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.beam.smos.dgg;
import com.bc.ceres.glevel.MultiLevelImage;
import com.bc.ceres.glevel.MultiLevelSource;
import com.bc.ceres.glevel.support.DefaultMultiLevelImage;
import org.esa.beam.glevel.TiledFileMultiLevelSource;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.MessageFormat;
/**
* Provides a {@link com.bc.ceres.glevel.MultiLevelImage multi level image} of
* the SMOS Discrete global grid.
*
* @author Marco Peters
* @author Ralf Quast
* @version $Revision: $ $Date: $
* @since SMOS-Box 1.0
*/
public class SmosDgg {
private static final String SMOS_DGG_DIR_PROPERTY_NAME = "org.esa.beam.smos.dggDir";
private static final int A = 1000000;
private static final int B = 262144;
private static final int C = B + 1;
private static final int D = A - B;
public static final int MIN_GRID_POINT_ID = 1;
public static final int MAX_GRID_POINT_ID = 9262145;
public static final int MAX_SEQNUM = 2621442;
public static final int MAX_ZONE_ID = 10;
private volatile MultiLevelImage dggMultiLevelImage;
public static SmosDgg getInstance() {
return Holder.instance;
}
public static int gridPointIdToSeqnum(int gridPointId) {
return gridPointId < A ? gridPointId : gridPointId - D * ((gridPointId - 1) / A) + 1;
}
static int gridPointIdToSeqnumInZone(int gridPointId) {
return gridPointId % A;
}
static int gridPointIdToZoneId(int gridPointId) {
return gridPointId / A + 1;
}
static int seqnumToGridPointId(int seqnum) {
return seqnum <= C ? seqnum : seqnum == MAX_SEQNUM ? MAX_GRID_POINT_ID : seqnum - 1 + ((seqnum - 2) / B) * D;
}
public static int seqnumToSeqnumInZone(int seqnum) {
return seqnum <= C ? seqnum : seqnum == MAX_SEQNUM ? C : (seqnum - 2) % B + 1;
}
public static int seqnumToZoneId(int seqnum) {
return seqnum <= C ? 1 : seqnum == MAX_SEQNUM ? MAX_ZONE_ID : (seqnum - 2) / B + 1;
}
public AffineTransform getImageToMapTransform() {
return getMultiLevelImage().getModel().getImageToModelTransform(0);
}
public MultiLevelImage getMultiLevelImage() {
return dggMultiLevelImage;
}
private SmosDgg() {
try {
String dirPath = getDirPathFromProperty();
if (dirPath == null) {
dirPath = getDirPathFromModule();
}
final File dir = new File(dirPath);
final MultiLevelSource dggMultiLevelSource = TiledFileMultiLevelSource.create(dir);
dggMultiLevelImage = new DefaultMultiLevelImage(dggMultiLevelSource);
} catch (Exception e) {
throw new IllegalStateException(MessageFormat.format(
"Cannot create SMOS DDG multi-level image: {0}", e.getMessage()), e);
}
}
private static String getDirPathFromModule() throws URISyntaxException {
final URL url = SmosDgg.class.getResource("image.properties");
final URI uri = url.toURI();
return new File(uri).getParent();
}
private static String getDirPathFromProperty() throws IOException {
final String dirPath = System.getProperty(SMOS_DGG_DIR_PROPERTY_NAME);
if (dirPath != null) {
final File dir = new File(dirPath);
if (!dir.canRead()) {
throw new IOException(MessageFormat.format(
"Cannot read directory ''{0}''. System property ''{0}'' must point to a readable directory.",
dir.getPath(), SMOS_DGG_DIR_PROPERTY_NAME));
}
}
return dirPath;
}
// Initialization on demand holder idiom
private static class Holder {
private static final SmosDgg instance = new SmosDgg();
}
}