| /******************************************************************************* |
| * 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 org.eclipse.apogy.addons.sensors.fov.ApogyAddonsSensorsFOVPackage; |
| import org.eclipse.apogy.addons.sensors.fov.ConicalFieldOfView; |
| import org.eclipse.apogy.addons.sensors.fov.DistanceRange; |
| import org.eclipse.apogy.common.emf.transaction.ApogyCommonTransactionFacade; |
| import org.eclipse.apogy.core.ApogyCorePackage; |
| import org.eclipse.apogy.core.environment.earth.ApogyEarthEnvironmentPackage; |
| import org.eclipse.apogy.core.environment.earth.EarthSurfaceLocation; |
| import org.eclipse.apogy.core.environment.earth.GeographicCoordinates; |
| import org.eclipse.apogy.core.environment.earth.ui.utils.WorldWindUtils; |
| import org.eclipse.apogy.core.environment.orbit.earth.ApogyCoreEnvironmentOrbitEarthPackage; |
| import org.eclipse.apogy.core.environment.orbit.earth.ConstantElevationMask; |
| import org.eclipse.apogy.core.environment.orbit.earth.ElevationMask; |
| import org.eclipse.apogy.core.environment.orbit.earth.GroundStation; |
| import org.eclipse.apogy.core.environment.orbit.earth.ui.utils.MultiEObjectsAdapter; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.ecore.EObject; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import gov.nasa.worldwind.avlist.AVKey; |
| import gov.nasa.worldwind.geom.Angle; |
| import gov.nasa.worldwind.geom.Position; |
| import gov.nasa.worldwind.globes.Earth; |
| import gov.nasa.worldwind.layers.RenderableLayer; |
| import gov.nasa.worldwind.render.BasicShapeAttributes; |
| import gov.nasa.worldwind.render.Cone; |
| import gov.nasa.worldwind.render.Material; |
| import gov.nasa.worldwind.render.SurfaceCircle; |
| |
| public abstract class AbstractGroundStationWorldWindLayerCustomImpl extends AbstractGroundStationWorldWindLayerImpl { |
| |
| private static final Logger Logger = LoggerFactory.getLogger(AbstractGroundStationWorldWindLayerImpl.class); |
| |
| private MultiEObjectsAdapter groundStationAdapter = null; |
| |
| @Override |
| public void setGroundStation(GroundStation newGroundStation) { |
| // Unregister from previous objects. |
| getGroundStationAdapter().unregisterFromAllObjects(); |
| |
| super.setGroundStation(newGroundStation); |
| |
| if (newGroundStation != null) { |
| getGroundStationAdapter().registerToEObject(newGroundStation); |
| } |
| |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| } |
| |
| @Override |
| public void setReferenceAltitude(double newReferenceAltitude) { |
| super.setReferenceAltitude(newReferenceAltitude); |
| |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| } |
| |
| @Override |
| public void setShowVisibilityCircle(boolean newShowVisibilityCircle) { |
| super.setShowVisibilityCircle(newShowVisibilityCircle); |
| |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| } |
| |
| @Override |
| public void setShowVisibilityCone(boolean newShowVisibilityCone) { |
| super.setShowVisibilityCone(newShowVisibilityCone); |
| |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| } |
| |
| @Override |
| public void setShowOutline(boolean newShowOutline) { |
| super.setShowOutline(newShowOutline); |
| |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| } |
| |
| @Override |
| public void setName(String newName) { |
| super.setName(newName); |
| |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| } |
| |
| @Override |
| public boolean getDefaultAutoUpdateEnabled() { |
| return true; |
| } |
| |
| @Override |
| public EarthSurfaceLocation getEarthSurfaceLocation() { |
| return getGroundStation(); |
| } |
| |
| @Override |
| public void dispose() { |
| // Unregister from all objects. |
| getGroundStationAdapter().unregisterFromAllObjects(); |
| |
| super.dispose(); |
| } |
| |
| @Override |
| protected void updateRenderableLayer() { |
| if (!isUpdating() && eContainer() != null) { |
| ApogyCommonTransactionFacade.INSTANCE.basicSet(this, ApogyCorePackage.Literals.UPDATABLE__UPDATING, true, |
| true); |
| |
| RenderableLayer layer = getRenderableLayer(); |
| layer.removeAllRenderables(); |
| |
| if (isVisible() && !isDisposed() && getGroundStation() != null) { |
| // Adds renderable from super; |
| AbstractGroundStationWorldWindLayerCustomImpl.super.addRenderable(layer); |
| |
| GeographicCoordinates coord = getGroundStation(); |
| |
| Angle latitude = Angle.fromRadiansLatitude(coord.getLatitude()); |
| Angle longitude = Angle.fromRadiansLongitude(coord.getLongitude()); |
| double elevation = coord.getElevation(); |
| Position position = new Position(latitude, longitude, elevation); |
| |
| // Adds the FOV. |
| if (getGroundStation().getElevationMask() instanceof ConstantElevationMask) { |
| ConstantElevationMask cFOV = (ConstantElevationMask) getGroundStation().getElevationMask(); |
| |
| // Gets the outer circle radius. |
| double refAltitude = getReferenceAltitude() * 1000.0; |
| double radius = computeGroundCircle(cFOV, refAltitude); |
| |
| BasicShapeAttributes fovAttributes = new BasicShapeAttributes(); |
| fovAttributes.setDrawInterior(true); |
| fovAttributes.setOutlineOpacity(0.95); |
| fovAttributes.setDrawOutline(isShowOutline()); |
| |
| Material interiorMat = new Material(WorldWindUtils.convertFrom(getColor())); |
| fovAttributes.setInteriorMaterial(interiorMat); |
| fovAttributes.setDrawInterior(true); |
| fovAttributes.setInteriorOpacity(getOpacity()); |
| |
| Material outlineMat = new Material(WorldWindUtils.convertFrom(getColor())); |
| fovAttributes.setOutlineMaterial(outlineMat); |
| |
| if (isShowVisibilityCircle()) { |
| SurfaceCircle visibilityCircle = new SurfaceCircle(fovAttributes, position, radius, 36); |
| visibilityCircle.setVisible(true); |
| layer.addRenderable(visibilityCircle); |
| } |
| |
| if (isShowVisibilityCone() && cFOV.getConstantElevation() > 0) { |
| double h = getReferenceAltitude() * 1000; |
| double r = h / Math.tan(cFOV.getConstantElevation()); |
| if (r > 0) { |
| double northSouthRadius = r; |
| double verticalRadius = h; |
| double eastWestRadius = r; |
| |
| Angle heading = Angle.fromDegrees(0); |
| Angle tilt = Angle.fromDegrees(180); |
| Angle roll = Angle.fromDegrees(0); |
| |
| Cone cone = new Cone(new Position(latitude, longitude, elevation + verticalRadius), |
| northSouthRadius, verticalRadius, eastWestRadius, heading, tilt, roll); |
| cone.setAttributes(fovAttributes); |
| layer.addRenderable(cone); |
| } |
| } |
| } |
| } |
| |
| getRenderableLayer().firePropertyChange(AVKey.LAYER, null, this); |
| ApogyCommonTransactionFacade.INSTANCE.basicSet(AbstractGroundStationWorldWindLayerCustomImpl.this, |
| ApogyCorePackage.Literals.UPDATABLE__UPDATING, false, true); |
| } |
| } |
| |
| protected double computeGroundCircle(ConstantElevationMask constantElevationMask, double range) { |
| double radius = 0; |
| |
| double A = (Math.PI / 2.0) + constantElevationMask.getConstantElevation(); |
| double a = Earth.WGS84_EQUATORIAL_RADIUS + range; |
| double b = Earth.WGS84_EQUATORIAL_RADIUS; |
| double B = Math.asin(b / a * Math.sin(A)); |
| double C = Math.PI - A - B; |
| radius = C * Earth.WGS84_EQUATORIAL_RADIUS; |
| |
| return radius; |
| } |
| |
| protected MultiEObjectsAdapter getGroundStationAdapter() { |
| if (this.groundStationAdapter == null) { |
| this.groundStationAdapter = new MultiEObjectsAdapter() { |
| @Override |
| public void registerToEObject(EObject eObject) { |
| if (eObject instanceof GroundStation) { |
| GroundStation newGroundStation = (GroundStation) eObject; |
| super.registerToEObject(newGroundStation); |
| if (newGroundStation.getElevationMask() != null) { |
| newGroundStation.getElevationMask().eAdapters().add(this); |
| } |
| } else { |
| eObject.eAdapters().add(this); |
| } |
| } |
| |
| @Override |
| public void notifyChanged(Notification msg) { |
| if (msg.getNotifier() instanceof GroundStation) { |
| int featureId = msg.getFeatureID(GroundStation.class); |
| switch (featureId) { |
| case ApogyCoreEnvironmentOrbitEarthPackage.GROUND_STATION__NAME: |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| break; |
| |
| case ApogyCoreEnvironmentOrbitEarthPackage.GROUND_STATION__ELEVATION_MASK: |
| |
| if (msg.getOldValue() instanceof ElevationMask) { |
| ((ElevationMask) msg.getOldValue()).eAdapters().remove(this); |
| } |
| |
| if (msg.getNewValue() instanceof ElevationMask) { |
| ((ElevationMask) msg.getNewValue()).eAdapters().add(this); |
| } |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| // TODO Auto-generated catch block |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| break; |
| |
| case ApogyEarthEnvironmentPackage.EARTH_SURFACE_LOCATION__ELEVATION: |
| case ApogyEarthEnvironmentPackage.EARTH_SURFACE_LOCATION__LATITUDE: |
| case ApogyEarthEnvironmentPackage.EARTH_SURFACE_LOCATION__LONGITUDE: |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| // TODO Auto-generated catch block |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } else if (msg.getNotifier() instanceof ElevationMask) { |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| // TODO Auto-generated catch block |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| } else if (msg.getNotifier() instanceof GeographicCoordinates) { |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| // TODO Auto-generated catch block |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| } else if (msg.getNotifier() instanceof DistanceRange) { |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| // TODO Auto-generated catch block |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| } else if (msg.getNotifier() instanceof ConicalFieldOfView) { |
| int featureId = msg.getFeatureID(ConicalFieldOfView.class); |
| |
| switch (featureId) { |
| case ApogyAddonsSensorsFOVPackage.CONICAL_FIELD_OF_VIEW__RANGE: |
| if (msg.getOldValue() instanceof DistanceRange) { |
| getGroundStationAdapter().unregisterFromEObject((DistanceRange) msg.getOldValue()); |
| } |
| |
| if (msg.getNewValue() instanceof DistanceRange) { |
| getGroundStationAdapter().registerToEObject((DistanceRange) msg.getNewValue()); |
| } |
| |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| // TODO Auto-generated catch block |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| |
| break; |
| |
| default: |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| // TODO Auto-generated catch block |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| break; |
| } |
| } else { |
| if (isAutoUpdateEnabled()) { |
| try { |
| update(); |
| } catch (Exception e) { |
| // TODO Auto-generated catch block |
| Logger.error(e.getMessage(), e); |
| } |
| } |
| } |
| } |
| }; |
| } |
| return this.groundStationAdapter; |
| } |
| |
| } // AbstractGroundStationWorldWindLayerImpl |