/* * 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.rcp.layermanager.layersrc.shapefile; import com.bc.ceres.binding.PropertySet; import com.bc.ceres.core.ProgressMonitor; import com.bc.ceres.glayer.Layer; import com.bc.ceres.glayer.LayerType; import com.bc.ceres.glayer.LayerTypeRegistry; import com.bc.ceres.swing.progress.ProgressMonitorSwingWorker; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; import org.esa.snap.core.util.FeatureUtils; import org.esa.snap.rcp.SnapApp; import org.esa.snap.ui.layer.LayerSourcePageContext; import org.esa.snap.ui.product.ProductSceneView; import org.geotools.factory.CommonFactoryFinder; import org.geotools.feature.FeatureCollection; import org.geotools.styling.FeatureTypeStyle; import org.geotools.styling.Fill; import org.geotools.styling.LineSymbolizer; import org.geotools.styling.PointSymbolizer; import org.geotools.styling.PolygonSymbolizer; import org.geotools.styling.Rule; import org.geotools.styling.SLD; import org.geotools.styling.Stroke; import org.geotools.styling.Style; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.FeatureType; import org.opengis.filter.FilterFactory; import org.opengis.referencing.crs.CoordinateReferenceSystem; import java.awt.Color; import java.io.File; import java.io.IOException; /** * @author Marco Peters * @since BEAM 4.6 */ class ShapefileLoader extends ProgressMonitorSwingWorker<Layer, Object> { private static final org.geotools.styling.StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(null); private static final FilterFactory filterFactory = CommonFactoryFinder.getFilterFactory(null); private final LayerSourcePageContext context; ShapefileLoader(LayerSourcePageContext context) { super(context.getWindow(), "Loading Shapefile"); this.context = context; } protected LayerSourcePageContext getContext() { return context; } @Override protected Layer doInBackground(ProgressMonitor pm) throws Exception { try { pm.beginTask("Reading shapes", ProgressMonitor.UNKNOWN); final ProductSceneView sceneView = SnapApp.getDefault().getSelectedProductSceneView(); final Geometry clipGeometry = FeatureUtils.createGeoBoundaryPolygon(sceneView.getProduct()); File file = new File((String) context.getPropertyValue(ShapefileLayerSource.PROPERTY_NAME_FILE_PATH)); FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection = getFeatureCollection(file); CoordinateReferenceSystem featureCrs = (CoordinateReferenceSystem) context.getPropertyValue( ShapefileLayerSource.PROPERTY_NAME_FEATURE_COLLECTION_CRS); Style[] styles = getStyles(file, featureCollection); Style selectedStyle = getSelectedStyle(styles); final LayerType type = LayerTypeRegistry.getLayerType(FeatureLayerType.class.getName()); final PropertySet configuration = type.createLayerConfig(sceneView); configuration.setValue(FeatureLayerType.PROPERTY_NAME_FEATURE_COLLECTION_URL, file.toURI().toURL()); configuration.setValue(FeatureLayerType.PROPERTY_NAME_FEATURE_COLLECTION, featureCollection); configuration.setValue(FeatureLayerType.PROPERTY_NAME_FEATURE_COLLECTION_CRS, featureCrs); configuration.setValue(FeatureLayerType.PROPERTY_NAME_FEATURE_COLLECTION_CLIP_GEOMETRY, clipGeometry); configuration.setValue(FeatureLayerType.PROPERTY_NAME_SLD_STYLE, selectedStyle); Layer featureLayer = type.createLayer(sceneView, configuration); featureLayer.setName(file.getName()); featureLayer.setVisible(true); return featureLayer; } finally { pm.done(); } } private FeatureCollection<SimpleFeatureType, SimpleFeature> getFeatureCollection(File file) throws IOException { Object featureCollectionValue = context.getPropertyValue(ShapefileLayerSource.PROPERTY_NAME_FEATURE_COLLECTION); FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection; if (featureCollectionValue == null) { featureCollection = FeatureUtils.getFeatureSource(file.toURI().toURL()).getFeatures(); } else { featureCollection = (FeatureCollection<SimpleFeatureType, SimpleFeature>) featureCollectionValue; } return featureCollection; } private Style getSelectedStyle(Style[] styles) { Style selectedStyle = (Style) context.getPropertyValue(ShapefileLayerSource.PROPERTY_NAME_SELECTED_STYLE); if (selectedStyle == null) { selectedStyle = styles[0]; context.setPropertyValue(ShapefileLayerSource.PROPERTY_NAME_SELECTED_STYLE, styles[0]); } return selectedStyle; } private Style[] getStyles(File file, FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection) { Style[] styles = (Style[]) context.getPropertyValue(ShapefileLayerSource.PROPERTY_NAME_STYLES); if (styles == null || styles.length == 0) { styles = createStyle(file, featureCollection.getSchema()); context.setPropertyValue(ShapefileLayerSource.PROPERTY_NAME_STYLES, styles); } return styles; } private static Style[] createStyle(File shapeFile, FeatureType schema) { final Style[] styles = SLDUtils.loadSLD(shapeFile); if (styles != null && styles.length > 0) { return styles; } Class<?> type = schema.getGeometryDescriptor().getType().getBinding(); if (type.isAssignableFrom(Polygon.class) || type.isAssignableFrom(MultiPolygon.class)) { return new Style[]{createPolygonStyle()}; } else if (type.isAssignableFrom(LineString.class) || type.isAssignableFrom(MultiLineString.class)) { return new Style[]{createLineStyle()}; } else { return new Style[]{createPointStyle()}; } } private static Style createPointStyle() { PointSymbolizer symbolizer = styleFactory.createPointSymbolizer(); symbolizer.getGraphic().setSize(filterFactory.literal(1)); Rule rule = styleFactory.createRule(); rule.symbolizers().add(symbolizer); FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(); fts.rules().add(rule); Style style = styleFactory.createStyle(); style.featureTypeStyles().add(fts); return style; } private static Style createLineStyle() { LineSymbolizer symbolizer = styleFactory.createLineSymbolizer(); SLD.setLineColour(symbolizer, Color.BLUE); symbolizer.getStroke().setWidth(filterFactory.literal(1)); symbolizer.getStroke().setColor(filterFactory.literal(Color.BLUE)); Rule rule = styleFactory.createRule(); rule.symbolizers().add(symbolizer); FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(); fts.rules().add(rule); Style style = styleFactory.createStyle(); style.featureTypeStyles().add(fts); return style; } private static Style createPolygonStyle() { PolygonSymbolizer symbolizer = styleFactory.createPolygonSymbolizer(); Fill fill = styleFactory.createFill( filterFactory.literal("#FFAA00"), filterFactory.literal(0.5) ); final Stroke stroke = styleFactory.createStroke(filterFactory.literal(Color.BLACK), filterFactory.literal(1)); symbolizer.setFill(fill); symbolizer.setStroke(stroke); Rule rule = styleFactory.createRule(); rule.symbolizers().add(symbolizer); FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(); fts.rules().add(rule); Style style = styleFactory.createStyle(); style.featureTypeStyles().add(fts); return style; } }