blob: 90b6fbdb9d4d89cb1cdcae46c16767ba40d30949 [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.impl;
import java.awt.Color;
import java.util.Date;
import java.util.List;
import org.eclipse.apogy.common.emf.ApogyCommonEMFPackage;
import org.eclipse.apogy.common.emf.Timed;
import org.eclipse.apogy.common.emf.transaction.ApogyCommonTransactionFacade;
import org.eclipse.apogy.core.ApogyCorePackage;
import org.eclipse.apogy.core.environment.orbit.OrbitModel;
import org.eclipse.apogy.core.environment.orbit.SpacecraftState;
import org.eclipse.apogy.core.environment.orbit.earth.ui.ApogyCoreEnvironmentOrbitEarthUIPackage;
import org.eclipse.apogy.core.environment.orbit.earth.ui.utils.WorldWindUtils;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.render.Polyline;
public class OrbitModelWorldWindLayerCustomImpl extends OrbitModelWorldWindLayerImpl {
private static final Logger Logger = LoggerFactory.getLogger(OrbitModelWorldWindLayerImpl.class);
public static final short GROUND_TRACE_STIPPLE_PATTERN = 0x00FF;
public static final int GROUND_TRACE_STIPPLE_FACTOR = 1;
private Adapter timedAdapter = null;
@Override
public void setOrbitModel(OrbitModel newOrbitModel) {
super.setOrbitModel(newOrbitModel);
// Update renderableLayer.
if (isAutoUpdateEnabled()) {
try {
update();
} catch (Exception e) {
Logger.error(e.getMessage(), e);
}
}
}
@Override
public void setTimeSource(Timed newTimeSource) {
// Unregister from previous timed if applicable.
if (this.timeSource != null) {
this.timeSource.eAdapters().remove(getTimedAdapter());
}
// Updates timesource
super.setTimeSource(newTimeSource);
// Register to new timed if applicable.
if (newTimeSource != null) {
try {
update();
} catch (Exception e) {
Logger.error(e.getMessage(), e);
}
newTimeSource.eAdapters().add(getTimedAdapter());
}
}
@Override
public void setForwardPropagationDuration(double newForwardPropagationDuration) {
super.setForwardPropagationDuration(newForwardPropagationDuration);
// Update renderableLayer.
if (isAutoUpdateEnabled()) {
try {
update();
} catch (Exception e) {
Logger.error(e.getMessage(), e);
}
}
}
@Override
public void setBackwardPropagationDuration(double newBackwardPropagationDuration) {
super.setBackwardPropagationDuration(newBackwardPropagationDuration);
// Update renderableLayer.
if (isAutoUpdateEnabled())
updateRenderableLayer();
}
@Override
public void setShowGroundTrace(boolean newShowGroundTrace) {
super.setShowGroundTrace(newShowGroundTrace);
if (isAutoUpdateEnabled())
updateRenderableLayer();
}
@Override
public void dispose() {
if (getTimeSource() != null)
getTimeSource().eAdapters().remove(getTimedAdapter());
ApogyCommonTransactionFacade.INSTANCE.basicSet(this,
ApogyCoreEnvironmentOrbitEarthUIPackage.Literals.ORBIT_MODEL_WORLD_WIND_LAYER__ORBIT_MODEL, null, true);
super.dispose();
}
@Override
protected void updateRenderableLayer() {
if (!isUpdating()) {
ApogyCommonTransactionFacade.INSTANCE.basicSet(this, ApogyCorePackage.Literals.UPDATABLE__UPDATING, true);
RenderableLayer layer = getRenderableLayer();
layer.removeAllRenderables();
Job job = new Job("OrbitModelWorldWindLayer updateRenderableLayer") {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
if (isVisible() && !isDisposed() && getOrbitModel() != null && getTimeSource() != null) {
// Generate backward orbit.
if (getBackwardPropagationDuration() > 0) {
long duration = Math.round(getBackwardPropagationDuration() * 1000.0);
Date startDate = new Date(getTimeSource().getTime().getTime() - duration);
Date endDate = getTimeSource().getTime();
List<SpacecraftState> states = getOrbitModel().getSpacecraftStates(startDate, endDate,
getTimeInterval());
List<Polyline> polylines = WorldWindUtils.createPolyLineWithNoWrapAround(states);
if (isShowOrbit()) {
for (Polyline line : polylines) {
line.setColor(Color.YELLOW);
layer.addRenderable(line);
}
}
if (isShowGroundTrace()) {
for (Polyline line : polylines) {
Polyline groundTrace = new Polyline(line.getPositions());
groundTrace.setFollowTerrain(true);
groundTrace.setColor(Color.YELLOW);
groundTrace.setStippleFactor(GROUND_TRACE_STIPPLE_FACTOR);
groundTrace.setStipplePattern(GROUND_TRACE_STIPPLE_PATTERN);
layer.addRenderable(groundTrace);
}
}
}
// Generate forward orbit.
if (getForwardPropagationDuration() > 0) {
long duration = Math.round(getForwardPropagationDuration() * 1000.0);
Date startDate = getTimeSource().getTime();
Date endDate = new Date(getTimeSource().getTime().getTime() + duration);
List<SpacecraftState> states = getOrbitModel().getSpacecraftStates(startDate, endDate,
getTimeInterval());
List<Polyline> polylines = WorldWindUtils.createPolyLineWithNoWrapAround(states);
if (isShowOrbit()) {
for (Polyline line : polylines) {
line.setColor(Color.RED);
layer.addRenderable(line);
}
}
if (isShowGroundTrace()) {
for (Polyline line : polylines) {
Polyline groundTrace = new Polyline(line.getPositions());
groundTrace.setFollowTerrain(true);
groundTrace.setColor(Color.RED);
groundTrace.setStippleFactor(GROUND_TRACE_STIPPLE_FACTOR);
groundTrace.setStipplePattern(GROUND_TRACE_STIPPLE_PATTERN);
layer.addRenderable(groundTrace);
}
}
}
}
} catch (Exception e) {
Logger.error(e.getMessage(), e);
}
// Force layer to update.
getRenderableLayer().firePropertyChange(AVKey.LAYER, null, this);
ApogyCommonTransactionFacade.INSTANCE.basicSet(OrbitModelWorldWindLayerCustomImpl.this,
ApogyCorePackage.Literals.UPDATABLE__UPDATING, false);
return Status.OK_STATUS;
}
};
job.schedule();
}
}
protected Adapter getTimedAdapter() {
if (this.timedAdapter == null) {
this.timedAdapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
if (msg.getNotifier() instanceof Timed) {
int featureId = msg.getFeatureID(Timed.class);
switch (featureId) {
case ApogyCommonEMFPackage.TIMED__TIME:
if (isAutoUpdateEnabled())
updateRenderableLayer();
break;
default:
break;
}
}
}
};
}
return this.timedAdapter;
}
} // OrbitModelWorldWindLayerImpl