package org.esa.snap.ui.product; import com.bc.ceres.binding.PropertySet; import com.bc.ceres.grender.Rendering; import com.bc.ceres.swing.figure.support.DefaultFigureStyle; import com.vividsolutions.jts.geom.Geometry; import org.esa.snap.core.datamodel.RasterDataNode; import org.esa.snap.core.datamodel.SceneTransformProvider; import org.esa.snap.core.datamodel.VectorDataNode; import org.opengis.feature.simple.SimpleFeature; import org.opengis.referencing.operation.TransformException; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.geom.AffineTransform; import java.awt.geom.Line2D; import java.awt.geom.Point2D; /** * A special layer type that is used to create layers for {@link VectorDataNode}s that * have a special feature type. In this case "org.esa.snap.TrackPoint". * <p> * <i>Note: this is experimental code.</i> * * @author Norman Fomferra * @since BEAM 4.10 */ public class TrackLayerType extends VectorDataLayerType { public static boolean isTrackPointNode(VectorDataNode node) { final Object trackPoints = node.getFeatureType().getUserData().get("trackPoints"); return trackPoints != null && trackPoints.toString().equals("true"); } @Override protected VectorDataLayer createLayer(VectorDataNode vectorDataNode, RasterDataNode rasterDataNode, PropertySet configuration) { return new TrackLayer(this, vectorDataNode, rasterDataNode, configuration); } public static class TrackLayer extends VectorDataLayer { public static final Color STROKE_COLOR = Color.ORANGE; public static final double STROKE_OPACITY = 0.8; public static final double STROKE_WIDTH = 2.0; public static final double FILL_OPACITY = 0.5; public static final Color FILL_COLOR = Color.WHITE; private final Paint strokePaint; private final SceneTransformProvider sceneTransformProvider; public TrackLayer(VectorDataLayerType vectorDataLayerType, VectorDataNode vectorDataNode, SceneTransformProvider provider, PropertySet configuration) { super(vectorDataLayerType, vectorDataNode, provider, configuration); String styleCss = vectorDataNode.getDefaultStyleCss(); DefaultFigureStyle style = new DefaultFigureStyle(styleCss); style.fromCssString(styleCss); style.setSymbolName("circle"); style.setStrokeColor(STROKE_COLOR); style.setStrokeWidth(STROKE_WIDTH); style.setStrokeOpacity(STROKE_OPACITY); style.setFillColor(FILL_COLOR); style.setFillOpacity(FILL_OPACITY); strokePaint = style.getStrokePaint(); vectorDataNode.setDefaultStyleCss(style.toCssString()); sceneTransformProvider = provider; } @Override protected void renderLayer(Rendering rendering) { drawTrackPointConnections(rendering); super.renderLayer(rendering); } private void drawTrackPointConnections(Rendering rendering) { Graphics2D g = rendering.getGraphics(); AffineTransform oldTransform = g.getTransform(); try { g.transform(rendering.getViewport().getModelToViewTransform()); drawTrackPointConnections0(rendering); } finally { g.setTransform(oldTransform); } } private void drawTrackPointConnections0(Rendering rendering) { // todo - get these styles from vector data node. (nf) rendering.getGraphics().setPaint(strokePaint); float scalingFactor = (float) rendering.getViewport().getViewToModelTransform().getScaleX(); float effectiveStrokeWidth = (float) (scalingFactor * STROKE_WIDTH); float effectiveDash = Math.max(1.0F, scalingFactor * 5.0F); float effectiveMeterLimit = Math.max(1.0F, scalingFactor * 10.0F); BasicStroke basicStroke = new BasicStroke(effectiveStrokeWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, effectiveMeterLimit, new float[]{ effectiveDash, effectiveDash}, 0.0f); rendering.getGraphics().setStroke(basicStroke); // FeatureCollection.toArray() returns the feature in original order // todo - must actually sort using some (timestamp) attribute (nf) SimpleFeature[] features = getVectorDataNode().getFeatureCollection().toArray(new SimpleFeature[0]); double lastX = 0; double lastY = 0; for (int i = 0; i < features.length; i++) { SimpleFeature feature = features[i]; Geometry geometry = (Geometry) feature.getDefaultGeometry(); com.vividsolutions.jts.geom.Point centroid = geometry.getCentroid(); try { final Point2D.Double sceneCoords = new Point2D.Double(centroid.getX(), centroid.getY()); final Point2D.Double modelCoords = new Point2D.Double(); sceneTransformProvider.getSceneToModelTransform().transform(sceneCoords, modelCoords); if (i > 0) { rendering.getGraphics().draw(new Line2D.Double(lastX, lastY, centroid.getX(), centroid.getY())); } lastX = modelCoords.getX(); lastY = modelCoords.getY(); } catch (TransformException e) { //continue loop } } } } }