| /******************************************************************************* |
| * Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Pierre Allard, |
| * Regent L'Archeveque - initial API and implementation |
| * |
| * SPDX-License-Identifier: EPL-1.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.apogy.addons.sensors.imaging.impl; |
| |
| import java.awt.BasicStroke; |
| import java.awt.Color; |
| import java.awt.Font; |
| import java.awt.FontMetrics; |
| import java.awt.Graphics2D; |
| import java.awt.geom.Rectangle2D; |
| import java.awt.image.BufferedImage; |
| |
| import org.eclipse.apogy.addons.sensors.imaging.AzimuthDirection; |
| import org.eclipse.apogy.addons.sensors.imaging.ElevationDirection; |
| import org.eclipse.apogy.addons.sensors.imaging.ImageSnapshot; |
| import org.eclipse.apogy.common.images.AbstractEImage; |
| import org.eclipse.apogy.common.images.ApogyCommonImagesFactory; |
| import org.eclipse.apogy.common.images.EImage; |
| import org.eclipse.apogy.common.images.EImagesUtilities; |
| |
| public class ImagingUtilitiesCustomImpl extends ImagingUtilitiesImpl { |
| |
| @Override |
| public double linearConvertToHorizontalAngle(ImageSnapshot imageSnapshot, int horizontalPixelPosition) { |
| double hCenter = (imageSnapshot.getImage().getWidth()) / 2.0; |
| double ratio = (hCenter - horizontalPixelPosition) / (imageSnapshot.getImage().getWidth()); |
| double angle = ratio * imageSnapshot.getFieldOfView().getHorizontalFieldOfViewAngle(); |
| return angle; |
| } |
| |
| @Override |
| public double linearConvertToVerticalAngle(ImageSnapshot imageSnapshot, int verticalPixelPosition) { |
| double vCenter = (imageSnapshot.getImage().getHeight()) / 2.0; |
| double ratio = (vCenter - verticalPixelPosition) / (imageSnapshot.getImage().getHeight()); |
| double angle = ratio * imageSnapshot.getFieldOfView().getVerticalFieldOfViewAngle(); |
| return angle; |
| } |
| |
| @Override |
| public AbstractEImage getAzimuthElevationOverlay(int imageWidth, int imageHeight, double panAngle, double tiltAngle, |
| double horizontalFOVAngle, double verticalFOVAngle, AzimuthDirection azimuthDirection, |
| ElevationDirection elevationDirection, int angleInterval, String fontName, int fontSize, |
| Color positiveColor, Color negativeColor, int lineWidth) { |
| AbstractEImage abstractImage = EImagesUtilities.INSTANCE.createTransparentImage(imageWidth, imageHeight); |
| |
| BufferedImage image = abstractImage.asBufferedImage(); |
| |
| Graphics2D g2d = image.createGraphics(); |
| Font font = new Font(fontName, Font.BOLD, fontSize); |
| g2d.setFont(font); |
| |
| g2d.setStroke(new BasicStroke(lineWidth)); |
| g2d.setColor(positiveColor); |
| |
| int centerX = (int) Math.round((imageWidth / 2.0)); |
| int centerY = (int) Math.round((imageHeight / 2.0)); |
| |
| // Finds the left and right azimuths. |
| double leftSideAzimuth = 0; |
| double rightSideAzimuth = 0; |
| if (azimuthDirection == AzimuthDirection.POSITIVE_TOWARD_LEFT) { |
| leftSideAzimuth = panAngle + (horizontalFOVAngle / 2.0); |
| rightSideAzimuth = panAngle - (horizontalFOVAngle / 2.0); |
| } else { |
| leftSideAzimuth = panAngle - (horizontalFOVAngle / 2.0); |
| rightSideAzimuth = panAngle + (horizontalFOVAngle / 2.0); |
| } |
| |
| // Finds the top and bottom tilt. |
| double topSideElevation = 0; |
| double bottomSideElevation = 0; |
| if (elevationDirection == ElevationDirection.POSITIVE_UP) { |
| topSideElevation = tiltAngle + (verticalFOVAngle / 2.0); |
| bottomSideElevation = tiltAngle - (verticalFOVAngle / 2.0); |
| } else { |
| topSideElevation = tiltAngle - (verticalFOVAngle / 2.0); |
| bottomSideElevation = tiltAngle + (verticalFOVAngle / 2.0); |
| } |
| |
| double pixelPerAzimuthDegree = (imageWidth / horizontalFOVAngle); |
| double pixelPerElevationDegree = (imageHeight / verticalFOVAngle); |
| |
| // HORIZONTAL |
| |
| // Finds the closest integer on the left side |
| int leftMostAngle = (int) Math.round(leftSideAzimuth); |
| |
| // Adds horizontal ticks |
| double azimuth = leftMostAngle; |
| |
| boolean done = false; |
| while (!done) { |
| // Selects the color. |
| if (azimuth >= 0) |
| g2d.setColor(positiveColor); |
| else |
| g2d.setColor(negativeColor); |
| |
| int x = 0; |
| |
| if (azimuthDirection == AzimuthDirection.POSITIVE_TOWARD_LEFT) { |
| x = (int) Math.round((leftSideAzimuth - azimuth) * pixelPerAzimuthDegree); |
| } else { |
| x = (int) Math.round((azimuth - leftSideAzimuth) * pixelPerAzimuthDegree); |
| } |
| |
| if (Math.IEEEremainder(azimuth, angleInterval) == 0.0) { |
| String text = Double.toString(azimuth); |
| |
| FontMetrics fontMetrics = g2d.getFontMetrics(font); |
| Rectangle2D textArea = fontMetrics.getStringBounds(text, g2d); |
| |
| int xOffset = Math.round(((float) textArea.getWidth() / 2.0f)); |
| |
| g2d.drawLine(x, centerY - 10, x, centerY + 10); |
| g2d.drawString(text, x - xOffset, centerY + 10 + (int) textArea.getHeight()); |
| } else { |
| g2d.drawLine(x, centerY - 5, x, centerY + 5); |
| } |
| |
| // Increment azimuth and checks is azimuth is done. |
| if (azimuthDirection == AzimuthDirection.POSITIVE_TOWARD_LEFT) { |
| azimuth -= 1; |
| done = azimuth <= rightSideAzimuth; |
| } else { |
| azimuth += 1; |
| done = azimuth >= rightSideAzimuth; |
| } |
| } |
| |
| int azimuthZero = -1; |
| |
| // Draws the horizontal line. |
| if (leftSideAzimuth >= 0) { |
| // If the entire interval is positive |
| if (rightSideAzimuth >= 0) { |
| g2d.setColor(positiveColor); |
| g2d.drawLine(0, centerY, imageWidth, centerY); |
| } else { |
| // Find where zero is in pixels. |
| azimuthZero = (int) (pixelPerAzimuthDegree * leftSideAzimuth); |
| |
| // Left side is Positive |
| g2d.setColor(positiveColor); |
| g2d.drawLine(0, centerY, azimuthZero, centerY); |
| |
| // Right Side is negative |
| g2d.setColor(negativeColor); |
| g2d.drawLine(azimuthZero, centerY, imageWidth, centerY); |
| } |
| } else { |
| if (rightSideAzimuth <= 0) { |
| // The entire interval is negative |
| g2d.setColor(negativeColor); |
| g2d.drawLine(0, centerY, imageWidth, centerY); |
| } else { |
| // Find where zero is in pixels. |
| azimuthZero = (int) Math.abs((pixelPerAzimuthDegree * leftSideAzimuth)); |
| |
| // Left side is Negative |
| g2d.setColor(negativeColor); |
| g2d.drawLine(0, centerY, azimuthZero, centerY); |
| |
| // Right Side is Positive |
| g2d.setColor(positiveColor); |
| g2d.drawLine(azimuthZero, centerY, imageWidth, centerY); |
| } |
| } |
| |
| // VERTICAL |
| |
| int topMostAngle = (int) Math.round(topSideElevation); |
| |
| // Adds vertical ticks |
| double elevation = topMostAngle; |
| |
| done = false; |
| while (!done) { |
| // Selects the color. |
| if (elevation >= 0) |
| g2d.setColor(positiveColor); |
| else |
| g2d.setColor(negativeColor); |
| |
| int y = 0; |
| if (elevationDirection == ElevationDirection.POSITIVE_UP) { |
| y = (int) Math.round((topSideElevation - elevation) * pixelPerElevationDegree); |
| } else { |
| y = (int) Math.round((elevation - topSideElevation) * pixelPerElevationDegree); |
| } |
| |
| if (Math.IEEEremainder(elevation, angleInterval) == 0.0) { |
| String text = Double.toString(elevation); |
| |
| FontMetrics fontMetrics = g2d.getFontMetrics(font); |
| Rectangle2D textArea = fontMetrics.getStringBounds(text, g2d); |
| |
| int xOffset = (int) textArea.getWidth() + 14; |
| int yOffset = (int) (textArea.getHeight() / 2.0f); |
| |
| g2d.drawLine(centerX - 10, y, centerX + 10, y); |
| g2d.drawString(text, centerX - xOffset, y + yOffset); |
| } else { |
| g2d.drawLine(centerX - 5, y, centerX + 5, y); |
| } |
| |
| // Increment elevation and checks is azimuth is done. |
| if (elevationDirection == ElevationDirection.POSITIVE_UP) { |
| elevation -= 1; |
| done = elevation <= bottomSideElevation; |
| } else { |
| elevation += 1; |
| done = elevation >= bottomSideElevation; |
| } |
| |
| } |
| |
| // Draws the vertical line. |
| if (topSideElevation >= 0) { |
| // If the entire interval is positive |
| if (bottomSideElevation >= 0) { |
| g2d.setColor(positiveColor); |
| g2d.drawLine(centerX, 0, centerX, imageHeight); |
| } else { |
| int elevationZero = (int) Math.round(pixelPerElevationDegree * topSideElevation); |
| |
| g2d.setColor(positiveColor); |
| g2d.drawLine(centerX, 0, centerX, elevationZero); |
| |
| g2d.setColor(negativeColor); |
| g2d.drawLine(centerX, elevationZero, centerX, imageHeight); |
| } |
| } else { |
| if (bottomSideElevation >= 0) { |
| int elevationZero = (int) Math.abs(pixelPerElevationDegree * topSideElevation); |
| |
| g2d.setColor(negativeColor); |
| g2d.drawLine(centerX, 0, centerX, elevationZero); |
| |
| g2d.setColor(positiveColor); |
| g2d.drawLine(centerX, elevationZero, centerX, imageHeight); |
| } else { |
| // Entire range is negative |
| g2d.setColor(negativeColor); |
| g2d.drawLine(centerX, 0, centerX, imageHeight); |
| } |
| } |
| |
| EImage result = ApogyCommonImagesFactory.eINSTANCE.createEImage(); |
| result.setImageContent(image); |
| g2d.dispose(); |
| |
| return result; |
| } |
| |
| } // ImagingUtilitiesImpl |