/*
* 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.snap.ui.product;
import com.bc.ceres.swing.figure.AbstractShapeFigure;
import com.bc.ceres.swing.figure.FigureStyle;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Lineal;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.geom.Polygonal;
import com.vividsolutions.jts.geom.Puntal;
import org.esa.snap.core.datamodel.SceneTransformProvider;
import org.esa.snap.core.util.AwtGeomToJtsGeomConverter;
import org.esa.snap.core.util.Debug;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geometry.jts.LiteShape2;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.TransformException;
import java.awt.Shape;
/**
* A figure representing shape features.
*
* @author Norman Fomferra
*/
public class SimpleFeatureShapeFigure extends AbstractShapeFigure implements SimpleFeatureFigure {
private SimpleFeature simpleFeature;
private Shape shape;
private final Class<?> geometryType;
private SceneTransformProvider sceneTransformProvider;
private static final Shape EMPTY_SHAPE = new java.awt.Polygon(new int[0], new int[0], 0);
public SimpleFeatureShapeFigure(SimpleFeature simpleFeature, SceneTransformProvider provider, FigureStyle style) {
this(simpleFeature, provider, style, style);
}
public SimpleFeatureShapeFigure(SimpleFeature simpleFeature, SceneTransformProvider provider,
FigureStyle normalStyle, FigureStyle selectedStyle) {
super(getRank(simpleFeature), normalStyle, selectedStyle);
this.simpleFeature = simpleFeature;
this.geometryType = simpleFeature.getDefaultGeometry().getClass();
this.shape = null;
sceneTransformProvider = provider;
}
@Override
public Object createMemento() {
return getGeometry().clone();
}
@Override
public void setMemento(Object memento) {
simpleFeature.setDefaultGeometry(memento);
forceRegeneration();
fireFigureChanged();
}
@Override
public SimpleFeature getSimpleFeature() {
return simpleFeature;
}
@Override
public Geometry getGeometry() {
return (Geometry) simpleFeature.getDefaultGeometry();
}
@Override
public void setGeometry(Geometry geometry) {
if (!geometryType.isAssignableFrom(geometry.getClass())) {
Debug.trace("WARNING: Assigning a geometry of type " + geometry.getClass() + ", should actually be a " + geometryType);
}
simpleFeature.setDefaultGeometry(geometry);
forceRegeneration();
fireFigureChanged();
}
@Override
public Shape getShape() {
if (shape == null) {
final Geometry featureGeometry = (Geometry) simpleFeature.getDefaultGeometry();
try {
Geometry modelGeometry = sceneTransformProvider.getSceneToModelTransform().transform(featureGeometry);
shape = new LiteShape2(modelGeometry, null, null, true);
} catch (TransformException | FactoryException e) {
//return empty shape for drawing
return EMPTY_SHAPE;
}
}
return shape;
}
@Override
public void forceRegeneration() {
shape = null;
}
@Override
public void setShape(Shape shape) {
this.shape = shape;
Geometry modelGeometry = getGeometryFromShape(shape);
try {
final Geometry sceneGeometry = sceneTransformProvider.getModelToSceneTransform().transform(modelGeometry);
simpleFeature.setDefaultGeometry(sceneGeometry);
fireFigureChanged();
} catch (TransformException e) {
this.shape = null;
}
}
private Geometry getGeometryFromShape(Shape shape) {
AwtGeomToJtsGeomConverter converter = new AwtGeomToJtsGeomConverter();
Geometry geometry;
// May need to handle more cases here in the future! (nf)
if (Polygon.class.isAssignableFrom(geometryType)) {
geometry = converter.createPolygon(shape);
} else if (MultiPolygon.class.isAssignableFrom(geometryType)) {
geometry = converter.createMultiPolygon(shape);
} else if (LinearRing.class.isAssignableFrom(geometryType)) {
geometry = converter.createLinearRingList(shape).get(0);
} else if (LineString.class.isAssignableFrom(geometryType)) {
geometry = converter.createLineStringList(shape).get(0);
} else {
geometry = converter.createMultiLineString(shape);
}
return geometry;
}
@Override
public Object clone() {
SimpleFeatureShapeFigure clone = (SimpleFeatureShapeFigure) super.clone();
SimpleFeatureBuilder builder = new SimpleFeatureBuilder(simpleFeature.getFeatureType());
builder.init(simpleFeature);
clone.simpleFeature = builder.buildFeature(null);
clone.simpleFeature.setDefaultGeometry(getGeometry().clone());
clone.shape = getShape();
return clone;
}
static Rank getRank(SimpleFeature simpleFeature) {
final Object geometry = simpleFeature.getDefaultGeometry();
if (!(geometry instanceof Geometry)) {
throw new IllegalArgumentException("simpleFeature: geometry type must be a " + Geometry.class);
}
return getRank((Geometry) geometry);
}
static Rank getRank(Geometry geometry) {
if (geometry instanceof Puntal) {
return Rank.POINT;
} else if (geometry instanceof Lineal) {
return Rank.LINE;
} else if (geometry instanceof Polygonal) {
return Rank.AREA;
} else {
return Rank.NOT_SPECIFIED;
}
}
}