/* * Copyright (C) 2011 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.snap.ui.crs; import com.bc.ceres.binding.Property; import com.bc.ceres.binding.PropertyContainer; import com.bc.ceres.binding.PropertySet; import com.bc.ceres.binding.ValueSet; import org.esa.snap.core.datamodel.ImageGeometry; import org.esa.snap.core.datamodel.Product; import org.opengis.referencing.crs.CoordinateReferenceSystem; import java.awt.Rectangle; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; /** * @author Marco Zuehlke * @since BEAM 4.7 */ public class OutputGeometryFormModel { private static final int REFERENCE_PIXEL_DEFAULT = 1; private static final boolean FIT_PRODUCT_SIZE_DEFAULT = true; private int referencePixelLocation; private boolean fitProductSize; private transient Product sourceProduct; private transient CoordinateReferenceSystem targetCrs; private transient PropertySet propertyContainer; public OutputGeometryFormModel(PropertySet sourcePropertySet) { init(null, null, FIT_PRODUCT_SIZE_DEFAULT, REFERENCE_PIXEL_DEFAULT, sourcePropertySet); } public OutputGeometryFormModel(Product sourceProduct, Product collocationProduct) { this(sourceProduct, ImageGeometry.createCollocationTargetGeometry(sourceProduct, collocationProduct)); } public OutputGeometryFormModel(Product sourceProduct, CoordinateReferenceSystem targetCrs) { this(sourceProduct, ImageGeometry.createTargetGeometry(sourceProduct, targetCrs, null, null, null, null, null, null, null, null, null)); } public OutputGeometryFormModel(OutputGeometryFormModel formModel) { init(formModel.sourceProduct, formModel.targetCrs, formModel.fitProductSize, formModel.referencePixelLocation, formModel.getPropertySet()); } private OutputGeometryFormModel(Product sourceProduct, ImageGeometry imageGeometry) { init(sourceProduct, imageGeometry.getMapCrs(), FIT_PRODUCT_SIZE_DEFAULT, REFERENCE_PIXEL_DEFAULT, PropertyContainer.createObjectBacked(imageGeometry)); } private void init(Product sourceProduct, CoordinateReferenceSystem targetCrs, boolean fitProductSize, int referencePixelLocation, PropertySet sourcePropertySet) { this.sourceProduct = sourceProduct; this.targetCrs = targetCrs; this.fitProductSize = fitProductSize; this.referencePixelLocation = referencePixelLocation; this.propertyContainer = PropertyContainer.createValueBacked(ImageGeometry.class); configurePropertyContainer(propertyContainer); Property[] properties = sourcePropertySet.getProperties(); for (Property property : properties) { if (propertyContainer.isPropertyDefined(property.getName())) { propertyContainer.setValue(property.getName(), property.getValue()); } } } public PropertySet getPropertySet() { return propertyContainer; } public void setSourceProduct(Product sourceProduct) { this.sourceProduct = sourceProduct; updateProductSize(); } public void setTargetCrs(CoordinateReferenceSystem targetCrs) { this.targetCrs = targetCrs; updateProductSize(); setAxisUnits(propertyContainer); } public void resetToDefaults(ImageGeometry ig) { PropertyContainer pc = PropertyContainer.createObjectBacked(ig); Property[] properties = pc.getProperties(); for (Property property : properties) { propertyContainer.setValue(property.getName(), property.getValue()); } propertyContainer.setValue("referencePixelLocation", REFERENCE_PIXEL_DEFAULT); propertyContainer.setValue("fitProductSize", FIT_PRODUCT_SIZE_DEFAULT); } private void configurePropertyContainer(PropertySet ps) { PropertySet thisPS = PropertyContainer.createObjectBacked(this); ps.addProperties(thisPS.getProperties()); ps.getDescriptor("referencePixelLocation").setValueSet(new ValueSet(new Integer[]{0, 1, 2})); setAxisUnits(ps); ps.getDescriptor("orientation").setUnit("°"); ps.addPropertyChangeListener(new ChangeListener()); } private void setAxisUnits(PropertySet pc) { if (targetCrs != null) { String crsAxisUnit = targetCrs.getCoordinateSystem().getAxis(0).getUnit().toString(); pc.getDescriptor("easting").setUnit(crsAxisUnit); pc.getDescriptor("northing").setUnit(crsAxisUnit); pc.getDescriptor("pixelSizeX").setUnit(crsAxisUnit); pc.getDescriptor("pixelSizeY").setUnit(crsAxisUnit); } } private void updateProductSize() { if (targetCrs != null && sourceProduct != null) { Double pixelSizeX = (Double) propertyContainer.getValue("pixelSizeX"); Double pixelSizeY = (Double) propertyContainer.getValue("pixelSizeY"); Rectangle productSize = ImageGeometry.calculateProductSize(sourceProduct, targetCrs, pixelSizeX, pixelSizeY); propertyContainer.setValue("width", productSize.width); propertyContainer.setValue("height", productSize.height); } } private void updateReferencePixel() { double referencePixelX = (Double) propertyContainer.getValue("referencePixelX"); double referencePixelY = (Double) propertyContainer.getValue("referencePixelY"); if (referencePixelLocation == 0) { referencePixelX = 0.5; referencePixelY = 0.5; } else if (referencePixelLocation == 1) { referencePixelX = 0.5 * (Integer) propertyContainer.getValue("width"); referencePixelY = 0.5 * (Integer) propertyContainer.getValue("height"); } propertyContainer.setValue("referencePixelX", referencePixelX); propertyContainer.setValue("referencePixelY", referencePixelY); } private class ChangeListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent event) { String propertyName = event.getPropertyName(); if (fitProductSize && propertyName.startsWith("pixelSize")) { updateProductSize(); updateReferencePixel(); } if (propertyName.startsWith("referencePixelLocation")) { updateReferencePixel(); } } } }