| /******************************************************************************* |
| * 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.earth.surface.impl; |
| |
| import java.util.Date; |
| |
| import javax.vecmath.Matrix3d; |
| import javax.vecmath.Point3d; |
| |
| import org.eclipse.apogy.common.math.ApogyCommonMathFacade; |
| import org.eclipse.apogy.common.topology.TransformNode; |
| import org.eclipse.apogy.core.environment.ApogyCoreEnvironmentPackage; |
| import org.eclipse.apogy.core.environment.Moon; |
| import org.eclipse.apogy.core.environment.Sky; |
| import org.eclipse.apogy.core.environment.StarField; |
| import org.eclipse.apogy.core.environment.Sun; |
| import org.eclipse.apogy.core.environment.earth.EarthWorksite; |
| import org.eclipse.apogy.core.environment.earth.HorizontalCoordinates; |
| import org.eclipse.apogy.core.environment.earth.surface.ApogyEarthSurfaceEnvironmentPackage; |
| import org.eclipse.apogy.core.environment.earth.surface.AstronomyUtils; |
| import org.eclipse.apogy.core.environment.earth.surface.EarthSky; |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| |
| public class EarthSkyNodeCustomImpl extends EarthSkyNodeImpl { |
| |
| private Adapter earthSkyAdapter = null; |
| |
| @Override |
| public void setSky(Sky newSky) { |
| // Unregister from previous Sky if applicable. |
| if (getSky() != null) |
| getSky().eAdapters().remove(getEarthSkyAdapter()); |
| |
| // Register to new Sky if applicable. |
| if (newSky != null) |
| newSky.eAdapters().add(getEarthSkyAdapter()); |
| |
| // Updates sky. |
| super.setSky(newSky); |
| } |
| |
| protected Adapter getEarthSkyAdapter() { |
| if (this.earthSkyAdapter == null) { |
| this.earthSkyAdapter = new AdapterImpl() { |
| @Override |
| public void notifyChanged(Notification msg) { |
| // Process events from the EarthSky |
| if (msg.getNotifier() instanceof EarthSky) { |
| EarthSky earthSky = (EarthSky) msg.getNotifier(); |
| |
| if (msg.getFeatureID( |
| EarthSky.class) == ApogyEarthSurfaceEnvironmentPackage.EARTH_SKY__SUN_HORIZONTAL_COORDINATES) { |
| // Sun has moved, update the Sun transform |
| HorizontalCoordinates sunHorizontalCoordinates = (HorizontalCoordinates) msg.getNewValue(); |
| |
| Sun sun = earthSky.getSun(); |
| |
| Point3d sunPosition = AstronomyUtils.INSTANCE |
| .convertFromHorizontalCoordinatesToHorizontalRectangular(sunHorizontalCoordinates); |
| |
| // Updates the Sun TransformNode |
| if (sun != null) { |
| TransformNode sunTransformNode = (TransformNode) sun.getParent(); |
| sunTransformNode.setPosition(ApogyCommonMathFacade.INSTANCE.createTuple3d(sunPosition)); |
| } |
| } else if (msg.getFeatureID( |
| EarthSky.class) == ApogyEarthSurfaceEnvironmentPackage.EARTH_SKY__MOON_HORIZONTAL_COORDINATES) { |
| // Moon has moved, updates the Moon transform |
| HorizontalCoordinates moonHorizontalCoordinates = (HorizontalCoordinates) msg.getNewValue(); |
| |
| Moon moon = earthSky.getMoon(); |
| |
| Point3d moonPosition = AstronomyUtils.INSTANCE |
| .convertFromHorizontalCoordinatesToHorizontalRectangular(moonHorizontalCoordinates); |
| |
| // Updates the Moon TransformNode. |
| if (moon != null) { |
| TransformNode moonTransformNode = (TransformNode) moon.getParent(); |
| moonTransformNode |
| .setPosition(ApogyCommonMathFacade.INSTANCE.createTuple3d(moonPosition)); |
| } |
| } else if (msg.getFeatureID(EarthSky.class) == ApogyCoreEnvironmentPackage.SKY__TIME) { |
| // Time has changed, update the Star position. |
| Date newTime = (Date) msg.getNewValue(); |
| |
| if (newTime != null) { |
| StarField starField = earthSky.getStarField(); |
| |
| // Computes the new star field rotation matrix. |
| EarthWorksite worksite = (EarthWorksite) earthSky.getWorksite(); |
| Matrix3d m = updateStarsRotationMatrix(worksite, newTime.getTime()); |
| |
| // Updates the StarField TransformNode. |
| if (starField != null) { |
| TransformNode starFieldTransformNode = (TransformNode) starField.getParent(); |
| starFieldTransformNode |
| .setRotationMatrix(ApogyCommonMathFacade.INSTANCE.createMatrix3x3(m)); |
| } |
| } |
| } |
| } |
| } |
| }; |
| } |
| return this.earthSkyAdapter; |
| } |
| |
| private Matrix3d updateStarsRotationMatrix(EarthWorksite worksite, long newTime) { |
| Date date = new Date(newTime); |
| double observerLongitude = 0.0d; |
| double observerLatitude = 0.0d; |
| |
| if (worksite.getGeographicalCoordinates() != null) { |
| observerLongitude = worksite.getGeographicalCoordinates().getLongitude(); |
| observerLatitude = worksite.getGeographicalCoordinates().getLatitude(); |
| } |
| // Computes the rotation matrix that represents the rotation axis of the |
| // earth |
| // in the local horizontal frame. |
| Matrix3d earthRotationAxisMatrix = new Matrix3d(); |
| earthRotationAxisMatrix.rotY(Math.toRadians(90) - observerLatitude); |
| |
| // Computes the rotation matrix that take into account the rotation of the earth |
| // at the specified time |
| double localSideralTime = AstronomyUtils.INSTANCE.getLocalSideralTime(date, observerLongitude); |
| Matrix3d earthRotationMatrix = new Matrix3d(); |
| earthRotationMatrix.rotZ(-localSideralTime + Math.toRadians(180)); |
| |
| // Multiply both matrix together. |
| Matrix3d m = new Matrix3d(); |
| m.mul(earthRotationAxisMatrix, earthRotationMatrix); |
| |
| return m; |
| } |
| } // EarthSkyNodeImpl |