blob: bc9c766d4c429625e318ae4dcb3080f90065b70d [file] [log] [blame]
/*******************************************************************************
* 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.core.environment.orbit.earth.ui.composites;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import org.eclipse.apogy.core.environment.orbit.earth.VisibilityPassSpacecraftPosition;
import org.eclipse.apogy.core.environment.orbit.earth.VisibilityPassSpacecraftPositionHistory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.chart.renderer.DefaultPolarItemRenderer;
import org.jfree.data.Range;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.experimental.chart.swt.ChartComposite;
public class VisibilityPassSpacecraftPositionHistoryAzElComposite extends Composite {
private VisibilityPassSpacecraftPositionHistory positionHistory = null;
private JFreeChart chart;
private XYSeriesCollection xySeriesCollection = null;
private XYSeries currentDataSeries = null;
public VisibilityPassSpacecraftPositionHistoryAzElComposite(Composite parent, int style) {
super(parent, style);
setLayout(new FillLayout());
// Adds the chart parentComposite.
new ChartComposite(this, SWT.NONE, getChart(), true);
}
public VisibilityPassSpacecraftPositionHistory getPositionHistory() {
return this.positionHistory;
}
public void setPositionHistory(VisibilityPassSpacecraftPositionHistory positionHistory) {
// Clears current series.
getCurrentDataSeries().clear();
this.positionHistory = positionHistory;
// Populates the series with the new data if applicable.
if (positionHistory != null) {
populateDataSeries(getCurrentDataSeries(), positionHistory);
}
}
protected JFreeChart getChart() {
if (this.chart == null) {
this.chart = ChartFactory.createPolarChart("Elevation vs Azimuth", getXYSeriesCollection(), false, false,
false);
final PolarPlot plot = (PolarPlot) this.chart.getPlot();
plot.setBackgroundPaint(Color.white);
plot.setAngleGridlinePaint(Color.black);
plot.setAngleLabelPaint(Color.black);
plot.setRadiusGridlinePaint(Color.black);
plot.setRadiusGridlinesVisible(true);
plot.setNoDataMessage("No Data.");
plot.getAxis().setAutoRange(false);
plot.getAxis().setInverted(true);
plot.getAxis().setRange(new Range(0, 90.0));
plot.getAxis().setAxisLineStroke(new BasicStroke(2.0f));
plot.getAxis().setAxisLinePaint(Color.black);
DefaultPolarItemRenderer defaultPolarItemRenderer = new DefaultPolarItemRenderer() {
/**
*
*/
private static final long serialVersionUID = 3822995919130258873L;
@Override
public void drawSeries(Graphics2D g2, Rectangle2D dataArea, PlotRenderingInfo info, PolarPlot plot,
XYDataset dataset, int seriesIndex) {
g2.setPaint(lookupSeriesPaint(seriesIndex));
g2.setStroke(lookupSeriesStroke(seriesIndex));
GeneralPath polyline = new GeneralPath();
int numPoints = dataset.getItemCount(seriesIndex);
Point point = null;
Point previousPoint = null;
for (int i = 0; i < numPoints - 1; i++) {
double theta = dataset.getXValue(seriesIndex, i);
double radius = dataset.getYValue(seriesIndex, i);
point = plot.translateValueThetaRadiusToJava2D(theta, radius, dataArea);
if (i == 0) {
polyline.moveTo(point.x, point.y);
} else {
polyline.lineTo(point.x, point.y);
}
if (i + 1 < numPoints - 1) {
previousPoint = point;
}
}
// Draws the data line.
g2.draw(polyline);
// Adds an arrow at the last point.
if (point != null) {
double deltaX = point.x - previousPoint.x;
double deltaY = point.y - previousPoint.y;
double theta = getRotationAngle(deltaX, deltaY);
g2.translate(point.x, point.y);
g2.rotate(theta);
int x1Points[] = { 0, -20, -20 };
int y1Points[] = { 0, 5, -5 };
Polygon polygon = new Polygon(x1Points, y1Points, x1Points.length);
g2.draw(polygon);
g2.fillPolygon(polygon);
// Un-do the transform.
g2.rotate(-theta);
g2.translate(-point.x, -point.y);
}
}
};
plot.setRenderer(defaultPolarItemRenderer);
}
return this.chart;
}
private double getRotationAngle(double deltaX, double deltaY) {
double theta = 0;
if (deltaX > 0) {
if (deltaY > 0) {
theta = Math.atan(Math.abs(deltaY) / Math.abs(deltaX));
} else {
theta = -1.0 * Math.atan(Math.abs(deltaY) / Math.abs(deltaX));
}
} else {
if (deltaY > 0) {
theta = Math.PI - Math.atan(Math.abs(deltaY) / Math.abs(deltaX));
} else {
theta = Math.atan(Math.abs(deltaY) / Math.abs(deltaX)) - Math.PI;
}
}
return theta;
}
protected XYSeriesCollection getXYSeriesCollection() {
if (this.xySeriesCollection == null) {
this.xySeriesCollection = new XYSeriesCollection();
this.xySeriesCollection.addSeries(getCurrentDataSeries());
}
return this.xySeriesCollection;
}
protected XYSeries getCurrentDataSeries() {
if (this.currentDataSeries == null) {
this.currentDataSeries = new XYSeries("Pass", false);
if (getPositionHistory() != null) {
populateDataSeries(this.currentDataSeries, getPositionHistory());
}
}
return this.currentDataSeries;
}
protected void populateDataSeries(XYSeries xySeries, VisibilityPassSpacecraftPositionHistory positionHistory) {
for (VisibilityPassSpacecraftPosition position : positionHistory.getPositions()) {
double azimuth = Math.toDegrees(position.getAzimuth());
double elevation = 90.0 - Math.toDegrees(position.getElevation());
xySeries.add(azimuth, elevation);
}
}
}