blob: 8249d185555caf7805062f4dc2961fe24765ebca [file] [log] [blame]
/*******************************************************************************
<<<<<<< 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