| /******************************************************************************* |
| <<<<<<< HEAD |
| * Copyright (c) 2018 IBM Corporation and others. |
| * 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: |
| * IBM Corporation - initial API and implementation |
| ======= |
| * 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 |
| * |
| >>>>>>> refs/heads/eclipse_pa |
| *******************************************************************************/ |
| package org.eclipse.apogy.addons.sensors.imaging.camera.impl; |
| |
| import java.text.DecimalFormat; |
| import java.util.Date; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import javax.vecmath.Color3f; |
| import javax.vecmath.Matrix3d; |
| import javax.vecmath.Matrix4d; |
| import javax.vecmath.Vector3d; |
| |
| import org.eclipse.apogy.addons.sensors.fov.ApogyAddonsSensorsFOVPackage; |
| import org.eclipse.apogy.addons.sensors.fov.RectangularFrustrumFieldOfView; |
| import org.eclipse.apogy.addons.sensors.fov.bindings.RectangularFrustrumFieldOfViewBinding; |
| import org.eclipse.apogy.addons.sensors.imaging.AbstractCamera; |
| import org.eclipse.apogy.addons.sensors.imaging.ImageSnapshot; |
| import org.eclipse.apogy.addons.sensors.imaging.camera.ApogyAddonsSensorsImagingCameraPackage; |
| import org.eclipse.apogy.addons.sensors.imaging.camera.CameraToolList; |
| import org.eclipse.apogy.addons.sensors.imaging.camera.CameraViewConfiguration; |
| import org.eclipse.apogy.common.emf.transaction.ApogyCommonTransactionFacade; |
| import org.eclipse.apogy.common.geometry.data3d.ApogyCommonGeometryData3DPackage; |
| import org.eclipse.apogy.common.images.AbstractEImage; |
| import org.eclipse.apogy.common.math.ApogyCommonMathFacade; |
| import org.eclipse.apogy.common.math.Matrix4x4; |
| import org.eclipse.apogy.common.topology.ApogyCommonTopologyFacade; |
| import org.eclipse.apogy.common.topology.ApogyCommonTopologyPackage; |
| import org.eclipse.apogy.common.topology.GroupNode; |
| import org.eclipse.apogy.common.topology.TransformNode; |
| import org.eclipse.apogy.common.topology.addons.primitives.ApogyCommonTopologyAddonsPrimitivesFactory; |
| import org.eclipse.apogy.common.topology.addons.primitives.ApogyCommonTopologyAddonsPrimitivesPackage; |
| import org.eclipse.apogy.common.topology.bindings.AbstractTopologyBinding; |
| import org.eclipse.apogy.common.topology.ui.NodePresentation; |
| import org.eclipse.apogy.core.ApogyCorePackage; |
| import org.eclipse.apogy.core.invocator.Context; |
| import org.eclipse.apogy.core.invocator.TypeApiAdapter; |
| import org.eclipse.apogy.core.invocator.Variable; |
| import org.eclipse.apogy.core.invocator.listeners.AbstractVariableFeatureReferenceListener; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.swt.graphics.RGB; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class PointerCameraToolCustomImpl extends PointerCameraToolImpl { |
| |
| private static final Logger Logger = LoggerFactory.getLogger(PointerCameraToolImpl.class); |
| |
| private AbstractVariableFeatureReferenceListener abstractVariableFeatureReferenceListener = null; |
| |
| private String toolTipText = "No intersection"; |
| private RectangularFrustrumFieldOfView fov = null; |
| private org.eclipse.apogy.common.topology.addons.primitives.PickVector vector; |
| private TransformNode vectorTransformNode = null; |
| private ImageSnapshot imageSnapshot; |
| private final DecimalFormat distanceFormat = new DecimalFormat("0.00"); |
| |
| public void setFov(RectangularFrustrumFieldOfView newFov) { |
| // Remove Vector from previous FOV if applicable. |
| if (this.fov != null) { |
| GroupNode parent = (GroupNode) this.fov.getParent(); |
| if (parent != null) |
| parent.getChildren().remove(getVectorTransformNode()); |
| } |
| |
| this.fov = newFov; |
| |
| // Adds Vector to new FOV if applicable. |
| if (newFov != null) { |
| GroupNode parent = (GroupNode) newFov.getParent(); |
| if (parent != null) { |
| parent.getChildren().add(getVectorTransformNode()); |
| } |
| } |
| } |
| |
| @Override |
| public void setVectorColor(Color3f newVectorColor) { |
| super.setVectorColor(newVectorColor); |
| updateVectorColor(newVectorColor); |
| } |
| |
| @Override |
| public void setCameraToolList(CameraToolList newCameraToolList) { |
| super.setCameraToolList(newCameraToolList); |
| |
| if (newCameraToolList != null) { |
| try { |
| getAbstractVariableFeatureReferenceListener() |
| .setVariableFeatureReference(newCameraToolList.getCameraViewConfiguration()); |
| setFov(resolveFOV()); |
| } catch (Throwable t) { |
| Logger.error("Error occured while setting the CameraToolList.", t); |
| } |
| } |
| } |
| |
| @Override |
| public void setVisible(boolean newVisible) { |
| super.setVisible(newVisible); |
| updateVectorVisibility(newVisible); |
| } |
| |
| @Override |
| public String getToolTipText(AbstractCamera camera, ImageSnapshot imageSnapshot, int mouseButton, int x, int y) { |
| return this.toolTipText; |
| } |
| |
| @Override |
| public void initializeCamera(AbstractCamera camera) { |
| setFov(resolveFOV(camera)); |
| |
| // Sets the inital ImageSnapshot. |
| if (camera != null) { |
| updateImageSnapshot(camera.getLatestImageSnapshot()); |
| } |
| |
| // Sets color of vector. |
| updateVectorColor(getVectorColor()); |
| } |
| |
| @Override |
| public void updateImageSnapshot(ImageSnapshot imageSnapshot) { |
| this.imageSnapshot = imageSnapshot; |
| } |
| |
| @Override |
| public void mouseMoved(AbstractEImage cameraImage, int mouseButton, int x, int y) { |
| double distance = Double.NaN; |
| |
| if (mouseButton == 1) { |
| updatePointer(cameraImage, this.imageSnapshot, x, y); |
| distance = getVector().getIntersectionDistance(); |
| |
| if (!Double.isNaN(getIntersectionDistance())) { |
| this.toolTipText = "distance = " + this.distanceFormat.format(distance); |
| } else { |
| this.toolTipText = "No intersection"; |
| } |
| } else { |
| this.toolTipText = null; |
| } |
| |
| // Update the distance. |
| ApogyCommonTransactionFacade.INSTANCE.basicSet(PointerCameraToolCustomImpl.this, |
| ApogyAddonsSensorsImagingCameraPackage.Literals.POINTER_CAMERA_TOOL__INTERSECTION_DISTANCE, distance); |
| } |
| |
| @Override |
| public void positionSelected(AbstractEImage cameraImage, int mouseButton, int x, int y) { |
| updatePointer(cameraImage, this.imageSnapshot, x, y); |
| double distance = getVector().getIntersectionDistance(); |
| ; |
| |
| if (!Double.isNaN(getIntersectionDistance())) { |
| this.toolTipText = "distance = " + this.distanceFormat.format(distance); |
| } else { |
| this.toolTipText = "No intersection"; |
| } |
| |
| ApogyCommonTransactionFacade.INSTANCE.basicSet(PointerCameraToolCustomImpl.this, |
| ApogyAddonsSensorsImagingCameraPackage.Literals.POINTER_CAMERA_TOOL__INTERSECTION_DISTANCE, distance); |
| } |
| |
| @Override |
| public void dispose() { |
| if (this.vectorTransformNode != null && this.vectorTransformNode.getParent() != null) { |
| // FIXME : Temporary fix because the PickVector is never removed from the JME3 |
| // Topology. |
| try { |
| NodePresentation nodePresentation = org.eclipse.apogy.common.topology.ui.Activator |
| .getTopologyPresentationRegistry().getPresentationNode(this.vectorTransformNode); |
| if (nodePresentation != null) |
| nodePresentation.setVisible(false); |
| |
| if (this.vector != null) { |
| org.eclipse.apogy.common.topology.ui.Activator.getTopologyPresentationRegistry() |
| .getPresentationNode(this.vector); |
| if (nodePresentation != null) |
| nodePresentation.setVisible(false); |
| } |
| } catch (Exception e) { |
| } |
| |
| // Detach vector from transform node. |
| if (this.vector != null) { |
| this.vectorTransformNode.getAggregatedChildren().remove(this.vector); |
| this.vector = null; |
| } |
| |
| GroupNode gp = (GroupNode) this.vectorTransformNode.getParent(); |
| gp.getChildren().remove(this.vectorTransformNode); |
| this.vectorTransformNode.setParent(null); |
| } |
| |
| // Unregister Variable feature reference listener. |
| getAbstractVariableFeatureReferenceListener().setVariableFeatureReference(null); |
| |
| super.dispose(); |
| } |
| |
| public RGB convert(Color3f color) { |
| int red = Math.round((color.getX() * 255)); |
| int green = Math.round((color.getY() * 255)); |
| int blue = Math.round((color.getZ() * 255)); |
| return new RGB(red, green, blue); |
| } |
| |
| protected void updateVectorColor(Color3f color) { |
| NodePresentation nodePresentation = org.eclipse.apogy.common.topology.ui.Activator |
| .getTopologyPresentationRegistry().getPresentationNode(getVector()); |
| if (nodePresentation != null) { |
| nodePresentation.setColor(convert(color)); |
| } |
| } |
| |
| protected void updateVectorVisibility(boolean visible) { |
| // Sets the visibility of the Vector. |
| NodePresentation nodePresentation = org.eclipse.apogy.common.topology.ui.Activator |
| .getTopologyPresentationRegistry().getPresentationNode(getVector()); |
| if (nodePresentation != null) { |
| nodePresentation.setVisible(visible); |
| } |
| } |
| |
| protected void updatePointer(AbstractEImage cameraImage, ImageSnapshot imageSnapshot, int x, int y) { |
| if (imageSnapshot != null && cameraImage != null) { |
| double xRotation = -imageSnapshot.convertToHorizontalAngle(x); |
| double yRotation = imageSnapshot.convertToVerticalAngle(y); |
| |
| Matrix3d xRot = new Matrix3d(); |
| xRot.setIdentity(); |
| xRot.rotX(xRotation); |
| |
| Matrix3d yRot = new Matrix3d(); |
| yRot.setIdentity(); |
| yRot.rotY(yRotation); |
| |
| Matrix3d rotation = new Matrix3d(); |
| rotation.setIdentity(); |
| |
| rotation.mul(xRot); |
| rotation.mul(yRot); |
| |
| // Updates the Vector. |
| Vector3d v = new Vector3d(0, 0, 100.0); |
| rotation.transform(v); |
| double vx = v.x; |
| double vy = v.y; |
| double vz = v.z; |
| |
| this.vector.setCoordinates(ApogyCommonMathFacade.INSTANCE.createTuple3d(vx, vy, vz)); |
| |
| // Force update of vector. |
| this.vector.setLength(100); |
| |
| // Updates the absolute pose. |
| if (this.vector.getAbsoluteIntersectionPosition() != null) { |
| Matrix4d m = new Matrix4d(); |
| m.setIdentity(); |
| m.set(new Vector3d(this.vector.getAbsoluteIntersectionPosition())); |
| Matrix4x4 pose = ApogyCommonMathFacade.INSTANCE.createMatrix4x4(m); |
| |
| ApogyCommonTransactionFacade.INSTANCE.basicSet(PointerCameraToolCustomImpl.this, |
| ApogyCorePackage.Literals.POSE_PROVIDER__POSE_TRANSFORM, pose); |
| } else { |
| ApogyCommonTransactionFacade.INSTANCE.basicSet(PointerCameraToolCustomImpl.this, |
| ApogyCorePackage.Literals.POSE_PROVIDER__POSE_TRANSFORM, null); |
| } |
| |
| // FIXME Forces the vector color to udpate. |
| Color3f newColor = getVectorColor(); |
| ApogyCommonTransactionFacade.INSTANCE.basicSet(PointerCameraToolCustomImpl.this, |
| ApogyAddonsSensorsImagingCameraPackage.Literals.POINTER_CAMERA_TOOL__VECTOR_COLOR, newColor); |
| } |
| } |
| |
| protected RectangularFrustrumFieldOfView resolveFOV(AbstractCamera camera) { |
| if (camera == null) { |
| return null; |
| } else { |
| RectangularFrustrumFieldOfView fov = null; |
| List<AbstractTopologyBinding> bindings = org.eclipse.apogy.common.topology.bindings.Activator |
| .getBindedBindings(); |
| Iterator<AbstractTopologyBinding> it = bindings.iterator(); |
| |
| /* |
| * Searches the list of topology bindings for the |
| * RectangularFrustrumFieldOfViewBinding that binds the camera FOV to a FOV in |
| * the topology. |
| */ |
| while (it.hasNext() && fov == null) { |
| AbstractTopologyBinding next = it.next(); |
| |
| if (next instanceof RectangularFrustrumFieldOfViewBinding) { |
| RectangularFrustrumFieldOfViewBinding fovBinding = (RectangularFrustrumFieldOfViewBinding) next; |
| |
| // Gets the fov to which the fovBinding is binded. |
| if (fovBinding.getFeatureNodeAdapter() |
| .getCurrentValue() instanceof RectangularFrustrumFieldOfView) { |
| RectangularFrustrumFieldOfView bindedFOV = (RectangularFrustrumFieldOfView) fovBinding |
| .getFeatureNodeAdapter().getCurrentValue(); |
| |
| // If the binded FOV is the one of the camera, we have found the FOV (in the |
| // topology) associated with the camera. |
| if (bindedFOV == camera.getFieldOfView()) { |
| fov = fovBinding.getFov(); |
| } |
| } |
| } |
| } |
| |
| return fov; |
| } |
| } |
| |
| protected TransformNode getVectorTransformNode() { |
| if (this.vectorTransformNode == null) { |
| Matrix4d m = new Matrix4d(); |
| m.setIdentity(); |
| |
| Vector3d position = new Vector3d(0, 0, 0.01); |
| m.set(position); |
| |
| // DEBUG |
| Date date = new Date(); |
| |
| this.vectorTransformNode = ApogyCommonTopologyFacade.INSTANCE.createTransformNode(m); |
| this.vectorTransformNode.setNodeId("VECTOR_" + getName() + "_" + date.getTime()); |
| this.vectorTransformNode.setDescription("PointerCamera Vector Transform"); |
| this.vectorTransformNode.getChildren().add(getVector()); |
| } |
| return this.vectorTransformNode; |
| } |
| |
| protected org.eclipse.apogy.common.topology.addons.primitives.PickVector getVector() { |
| if (this.vector == null) { |
| // Creates a vector of length 100 along the Z axis. |
| this.vector = ApogyCommonTopologyAddonsPrimitivesFactory.eINSTANCE.createPickVector(); |
| this.vector.getNodeTypesInIntersection() |
| .add(ApogyCommonGeometryData3DPackage.eINSTANCE.getCartesianCoordinatesMesh()); |
| this.vector.getNodeTypesInIntersection().add(ApogyCommonTopologyPackage.eINSTANCE.getContentNode()); |
| this.vector.setNodeId("PICKVECTOR_" + getName()); |
| this.vector.setDescription("Pick Vector used by Pointer Camera Tool."); |
| |
| this.vector.setCoordinates(ApogyCommonMathFacade.INSTANCE.createTuple3d(0, 0, 1.0)); |
| this.vector.setLength(100.0); |
| |
| // Exclude RectangularFrustrumFieldOfView from selected objects. |
| this.vector.getNodeTypesToExcludeFromIntersection() |
| .add(ApogyAddonsSensorsFOVPackage.Literals.RECTANGULAR_FRUSTRUM_FIELD_OF_VIEW); |
| this.vector.getNodeTypesToExcludeFromIntersection() |
| .add(ApogyCommonTopologyAddonsPrimitivesPackage.Literals.PICK_VECTOR); |
| |
| // Adds all types of node to the list of possible intersections. |
| this.vector.getNodeTypesInIntersection().add(ApogyCommonTopologyPackage.Literals.NODE); |
| |
| // Updates the Vector color. |
| Color3f newColor = getVectorColor(); |
| ApogyCommonTransactionFacade.INSTANCE.basicSet(PointerCameraToolCustomImpl.this, |
| ApogyAddonsSensorsImagingCameraPackage.Literals.POINTER_CAMERA_TOOL__VECTOR_COLOR, newColor); |
| } |
| |
| return this.vector; |
| } |
| |
| protected RectangularFrustrumFieldOfView resolveFOV() { |
| RectangularFrustrumFieldOfView fov = null; |
| |
| if (getCameraToolList() != null) { |
| CameraViewConfiguration cameraViewConfiguration = getCameraToolList().getCameraViewConfiguration(); |
| if (cameraViewConfiguration != null) { |
| AbstractCamera abstractCamera = cameraViewConfiguration.getCamera(); |
| if (abstractCamera != null) { |
| fov = abstractCamera.getFieldOfView(); |
| } |
| } |
| } |
| |
| return fov; |
| } |
| |
| protected AbstractVariableFeatureReferenceListener getAbstractVariableFeatureReferenceListener() { |
| if (this.abstractVariableFeatureReferenceListener == null) { |
| this.abstractVariableFeatureReferenceListener = new AbstractVariableFeatureReferenceListener( |
| getCameraToolList().getCameraViewConfiguration()) { |
| @Override |
| protected void instanceChanged(EObject oldInstance, EObject newInstance) { |
| |
| // ApogyCommonEmfTransactionFacade.INSTANCE.basicSet(PointerCameraToolImpl.this, |
| // ApogyAddonsSensorsImagingCameraPackage.Literals.POINTER_CAMERA_TOOL__FOV, |
| // resolveFOV()); |
| setFov(resolveFOV()); |
| } |
| |
| @Override |
| protected void contextChanged(Context oldContext, Context newContext) { |
| // ApogyCommonEmfTransactionFacade.INSTANCE.basicSet(PointerCameraToolImpl.this, |
| // ApogyAddonsSensorsImagingCameraPackage.Literals.POINTER_CAMERA_TOOL__FOV, |
| // resolveFOV()); |
| setFov(resolveFOV()); |
| } |
| |
| @Override |
| protected void typeApiAdapterChanged(TypeApiAdapter oldTypeApiAdapter, |
| TypeApiAdapter newTypeApiAdapter) { |
| // ApogyCommonEmfTransactionFacade.INSTANCE.basicSet(PointerCameraToolImpl.this, |
| // ApogyAddonsSensorsImagingCameraPackage.Literals.POINTER_CAMERA_TOOL__FOV, |
| // resolveFOV()); |
| setFov(resolveFOV()); |
| } |
| |
| @Override |
| protected void variableChanged(Variable oldVariable, Variable newVariable) { |
| // ApogyCommonEmfTransactionFacade.INSTANCE.basicSet(PointerCameraToolImpl.this, |
| // ApogyAddonsSensorsImagingCameraPackage.Literals.POINTER_CAMERA_TOOL__FOV, |
| // resolveFOV()); |
| setFov(resolveFOV()); |
| } |
| |
| @Override |
| protected void listRootNodeChanged() { |
| // ApogyCommonEmfTransactionFacade.INSTANCE.basicSet(PointerCameraToolImpl.this, |
| // ApogyAddonsSensorsImagingCameraPackage.Literals.POINTER_CAMERA_TOOL__FOV, |
| // resolveFOV()); |
| setFov(resolveFOV()); |
| } |
| }; |
| } |
| return this.abstractVariableFeatureReferenceListener; |
| } |
| |
| } // PointerCameraToolImpl |