/* * Copyright (C) 2015 by Array Systems Computing Inc. http://www.array.ca * * 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.s1tbx.fex.rcp.layersrc; import com.bc.ceres.binding.PropertySet; import com.bc.ceres.glayer.Layer; import com.bc.ceres.glayer.LayerTypeRegistry; import com.bc.ceres.grender.Rendering; import com.bc.ceres.grender.Viewport; import org.esa.s1tbx.dat.graphics.GraphicShape; import org.esa.s1tbx.dat.graphics.GraphicText; import org.esa.s1tbx.dat.layers.ScreenPixelConverter; import org.esa.s1tbx.fex.gpf.oceantools.ObjectDiscriminationOp; import org.esa.snap.core.datamodel.Band; import org.esa.snap.core.datamodel.GeoCoding; import org.esa.snap.core.datamodel.GeoPos; import org.esa.snap.core.datamodel.MetadataElement; import org.esa.snap.core.datamodel.PixelPos; import org.esa.snap.core.datamodel.Product; import org.esa.snap.core.datamodel.RasterDataNode; import org.esa.snap.core.datamodel.VectorDataNode; import org.esa.snap.core.dataop.downloadable.XMLSupport; import org.esa.snap.engine_utilities.datamodel.AbstractMetadata; import org.geotools.feature.FeatureIterator; import org.jdom2.Attribute; import org.jdom2.Content; import org.jdom2.Document; import org.jdom2.Element; import org.opengis.feature.simple.SimpleFeature; import java.awt.*; import java.io.File; import java.io.IOException; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; /** * Shows a detected object */ public class ObjectDetectionLayer extends Layer { private final Product product; private final Band band; private final List<ObjectDiscriminationOp.ShipRecord> targetList = new ArrayList<>(200); private double rangeSpacing; private double azimuthSpacing; private final static float lineThickness = 2.0f; private final static double border = 5.0; private final DecimalFormat frmt = new DecimalFormat("0.00"); public ObjectDetectionLayer(PropertySet configuration) { super(LayerTypeRegistry.getLayerType(ObjectDetectionLayerType.class.getName()), configuration); setName("Object Detection"); product = (Product) configuration.getValue("product"); band = (Band) configuration.getValue("band"); getPixelSize(); LoadTargets(); } private void getPixelSize() { final MetadataElement absMetadata = AbstractMetadata.getAbstractedMetadata(product); if (absMetadata != null) { rangeSpacing = absMetadata.getAttributeDouble(AbstractMetadata.range_spacing, 0); azimuthSpacing = absMetadata.getAttributeDouble(AbstractMetadata.azimuth_spacing, 0); } } public static File getTargetFile(final Product product) { final MetadataElement absMetadata = AbstractMetadata.getAbstractedMetadata(product); if (absMetadata != null) { final String shipFilePath = absMetadata.getAttributeString(AbstractMetadata.target_report_file, null); if (shipFilePath != null) { final File file = new File(shipFilePath); if (file.exists()) return file; } } return null; } private void LoadTargets() { VectorDataNode vectorDataNode = product.getVectorDataGroup().get(ObjectDiscriminationOp.VECTOR_NODE_NAME); if (vectorDataNode == null) { LoadTargetsFromFile(getTargetFile(product)); return; } targetList.clear(); final FeatureIterator itr = vectorDataNode.getFeatureCollection().features(); while (itr.hasNext()) { final SimpleFeature feature = (SimpleFeature) itr.next(); Integer x = (Integer)feature.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_X); Integer y = (Integer)feature.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_Y); Double lat = (Double)feature.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_LAT); if(lat == null) continue; Double lon = (Double)feature.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_LON); if(lon == null) continue; Double width = (Double)feature.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_WIDTH); if(width == null) continue; Double length = (Double)feature.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_LENGTH); if(length == null) continue; ObjectDiscriminationOp.ShipRecord shipRecord = new ObjectDiscriminationOp.ShipRecord( x, y, lat, lon, (width / rangeSpacing) + border, (length / azimuthSpacing) + border); Double corr_lat = (Double)feature.getAttribute(ObjectDiscriminationOp.ATTRIB_CORR_SHIP_LAT); if(corr_lat != null) { shipRecord.corr_lat = corr_lat; } Double corr_lon = (Double)feature.getAttribute(ObjectDiscriminationOp.ATTRIB_CORR_SHIP_LON); if(corr_lon != null) { shipRecord.corr_lon = corr_lon; } Integer mmsi = (Integer)feature.getAttribute(ObjectDiscriminationOp.ATTRIB_AIS_MMSI); if(mmsi != null) { shipRecord.mmsi = mmsi; } String shipName = (String)feature.getAttribute(ObjectDiscriminationOp.ATTRIB_AIS_SHIP_NAME); if(shipName != null) { shipRecord.shipName = shipName; } targetList.add(shipRecord); } } private void LoadTargetsFromFile(final File file) { if (file == null) return; Document doc; try { doc = XMLSupport.LoadXML(file.getAbsolutePath()); } catch (IOException e) { return; } targetList.clear(); final Element root = doc.getRootElement(); final List<Content> children = root.getContent(); for (Object aChild : children) { if (aChild instanceof Element) { final Element targetsDetectedElem = (Element) aChild; if (targetsDetectedElem.getName().equals("targetsDetected")) { final Attribute attrib = targetsDetectedElem.getAttribute("bandName"); if (attrib != null ) { final List<Content> content = targetsDetectedElem.getContent(); for (Object det : content) { if (det instanceof Element) { final Element targetElem = (Element) det; if (targetElem.getName().equals("target")) { Attribute x = targetElem.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_X); if (x == null) x = new Attribute(ObjectDiscriminationOp.ATTRIB_DETECTED_X, "0"); Attribute y = targetElem.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_Y); if (y == null) y = new Attribute(ObjectDiscriminationOp.ATTRIB_DETECTED_Y, "0"); final Attribute lat = targetElem.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_LAT); if (lat == null) continue; final Attribute lon = targetElem.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_LON); if (lon == null) continue; final Attribute width = targetElem.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_WIDTH); if (width == null) continue; final Attribute length = targetElem.getAttribute(ObjectDiscriminationOp.ATTRIB_DETECTED_LENGTH); if (length == null) continue; ObjectDiscriminationOp.ShipRecord shipRecord = new ObjectDiscriminationOp.ShipRecord( Integer.parseInt(x.getValue()), Integer.parseInt(y.getValue()), Double.parseDouble(lat.getValue()), Double.parseDouble(lon.getValue()), (Double.parseDouble(width.getValue()) / rangeSpacing) + border, (Double.parseDouble(length.getValue()) / azimuthSpacing) + border); final Attribute corr_lat = targetElem.getAttribute(ObjectDiscriminationOp.ATTRIB_CORR_SHIP_LAT); if (corr_lat != null) { shipRecord.corr_lat = Double.parseDouble(corr_lat.getValue()); } final Attribute corr_lon = targetElem.getAttribute(ObjectDiscriminationOp.ATTRIB_CORR_SHIP_LON); if (corr_lon != null) { shipRecord.corr_lon = Double.parseDouble(corr_lon.getValue()); } final Attribute mmsi = targetElem.getAttribute(ObjectDiscriminationOp.ATTRIB_AIS_MMSI); if (mmsi != null) { shipRecord.mmsi = Integer.parseInt(mmsi.getValue()); } final Attribute shipName = targetElem.getAttribute(ObjectDiscriminationOp.ATTRIB_AIS_SHIP_NAME); if (shipName != null) { shipRecord.shipName = shipName.getValue(); } targetList.add(shipRecord); } } } } } } } } @Override protected void renderLayer(Rendering rendering) { if (band == null || targetList.isEmpty()) return; final Viewport vp = rendering.getViewport(); final RasterDataNode raster = product.getRasterDataNode(product.getBandAt(0).getName()); final ScreenPixelConverter screenPixel = new ScreenPixelConverter(vp, raster); if (!screenPixel.withInBounds()) { return; } final GeoCoding geoCoding = product.getSceneGeoCoding(); final GeoPos geo = new GeoPos(); final PixelPos pix = new PixelPos(); final Graphics2D graphics = rendering.getGraphics(); graphics.setStroke(new BasicStroke(lineThickness)); GraphicText.setHighQuality(graphics); for (ObjectDiscriminationOp.ShipRecord target : targetList) { geo.setLocation(target.lat, target.lon); geoCoding.getPixelPos(geo, pix); if(!pix.isValid()) continue; Point.Double p = GraphicShape.drawCircle(graphics, screenPixel, pix.getX(), pix.getY(), (int)target.length, Color.RED); geo.setLocation(target.corr_lat, target.corr_lon); geoCoding.getPixelPos(geo, pix); if(pix.isValid()) { GraphicShape.drawX(graphics, screenPixel, pix.getX(), pix.getY(), 8, Color.RED); if(target.shipName != null && !target.shipName.isEmpty()) { GraphicText.outlineText(graphics, Color.RED, target.shipName, (int) p.x, (int) p.y); } } //final double targetWidthInMeter = (target.width - border) * rangeSpacing; final double targetLengthInMeter = (target.length - border) * azimuthSpacing; //final double size = Math.sqrt(targetWidthInMeter * targetWidthInMeter + targetLengthInMeter * targetLengthInMeter); final double size = targetLengthInMeter; graphics.drawString(frmt.format(size) + 'm', (int) p.x, (int) p.y); } } }