| /******************************************************************************* |
| * 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 |