| /******************************************************************************* |
| * 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 - initial API and implementation |
| * Regent L'Archeveque |
| * |
| * SPDX-License-Identifier: EPL-1.0 |
| *******************************************************************************/ |
| package org.eclipse.apogy.common.math.ui.composites; |
| |
| import javax.vecmath.Matrix3d; |
| import javax.vecmath.Vector3d; |
| |
| import org.eclipse.apogy.common.math.ApogyCommonMathFacade; |
| import org.eclipse.apogy.common.math.GeometricUtils; |
| import org.eclipse.apogy.common.math.Matrix3x3; |
| import org.eclipse.apogy.common.math.provider.MathEditUtils; |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| import org.eclipse.emf.edit.domain.EditingDomain; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Slider; |
| |
| public class RotationMatrixSlidersComposite extends Composite { |
| enum RotationAxis { |
| X, Y, Z |
| } |
| |
| private EditingDomain editingDomain; |
| private Matrix3x3 matrix; |
| private boolean disableEvent = false; |
| private Adapter matrixAdapter; |
| |
| private final Slider rxSlider; |
| private final Slider rySlider; |
| private final Slider rzSlider; |
| |
| public RotationMatrixSlidersComposite(Composite parent, int style) { |
| super(parent, style); |
| setLayout(new GridLayout(2, true)); |
| |
| Label rxLabel = new Label(this, SWT.NONE); |
| rxLabel.setAlignment(SWT.LEFT); |
| rxLabel.setText("Rx (deg):"); |
| |
| this.rxSlider = createSlider(this, SWT.BORDER | SWT.SINGLE | SWT.HORIZONTAL, RotationAxis.X); |
| this.rxSlider.setToolTipText("Rotation about X in degrees."); |
| this.rxSlider.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| Label ryLabel = new Label(this, SWT.NONE); |
| ryLabel.setAlignment(SWT.LEFT); |
| ryLabel.setText("Ry (deg):"); |
| |
| this.rySlider = createSlider(this, SWT.BORDER | SWT.SINGLE | SWT.HORIZONTAL, RotationAxis.Y); |
| this.rySlider.setToolTipText("Rotation about Y in degrees."); |
| this.rySlider.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| Label rzLabel = new Label(this, SWT.NONE); |
| rzLabel.setAlignment(SWT.LEFT); |
| rzLabel.setText("Rz (deg):"); |
| |
| this.rzSlider = createSlider(this, SWT.BORDER | SWT.SINGLE | SWT.HORIZONTAL, RotationAxis.Z); |
| this.rzSlider.setToolTipText("Rotation about Z in degrees."); |
| this.rzSlider.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| } |
| |
| public RotationMatrixSlidersComposite(Composite parent, int style, EditingDomain editingDomain) { |
| this(parent, style); |
| this.editingDomain = editingDomain; |
| } |
| |
| public void setMatrix3x3(Matrix3x3 newMatrix3x3) { |
| setMatrix3x3(newMatrix3x3, true); |
| } |
| |
| public void setMatrix3x3(Matrix3x3 newMatrix3x3, boolean update) { |
| if (this.matrix != null) { |
| this.matrix.eAdapters().remove(getMatrixAdapter()); |
| } |
| |
| this.matrix = newMatrix3x3; |
| |
| if (newMatrix3x3 != null) { |
| newMatrix3x3.eAdapters().add(getMatrixAdapter()); |
| |
| // Update the controls. |
| this.disableEvent = true; |
| updateRotations(newMatrix3x3); |
| this.disableEvent = false; |
| } |
| |
| } |
| |
| private Vector3d getRotationVector() { |
| Vector3d rotation = new Vector3d(); |
| rotation.setX((this.rxSlider.getSelection() - 180)); |
| rotation.setY((this.rySlider.getSelection() - 180)); |
| rotation.setZ((this.rzSlider.getSelection() - 180)); |
| |
| return rotation; |
| } |
| |
| private void updateXRotation(double xRotation) { |
| if (this.matrix != null) { |
| Vector3d rotationVector = getRotationVector(); |
| |
| rotationVector.setX(Math.toDegrees(xRotation)); |
| |
| Matrix3d matrix3d = GeometricUtils.packXYZ(Math.toRadians(rotationVector.getX()), |
| Math.toRadians(rotationVector.getY()), Math.toRadians(rotationVector.getZ())); |
| |
| MathEditUtils.updateOrientation(this.matrix, ApogyCommonMathFacade.INSTANCE.createMatrix3x3(matrix3d), |
| this.editingDomain); |
| |
| } |
| } |
| |
| private void updateYRotation(double yRotation) { |
| if (this.matrix != null) { |
| Vector3d rotationVector = getRotationVector(); |
| rotationVector.setY(Math.toDegrees(yRotation)); |
| |
| Matrix3d matrix3d = GeometricUtils.packXYZ(Math.toRadians(rotationVector.getX()), |
| Math.toRadians(rotationVector.getY()), Math.toRadians(rotationVector.getZ())); |
| |
| MathEditUtils.updateOrientation(this.matrix, ApogyCommonMathFacade.INSTANCE.createMatrix3x3(matrix3d), |
| this.editingDomain); |
| |
| } |
| } |
| |
| private void updateZRotation(double zRotation) { |
| if (this.matrix != null) { |
| Vector3d rotationVector = getRotationVector(); |
| rotationVector.setZ(Math.toDegrees(zRotation)); |
| |
| Matrix3d matrix3d = GeometricUtils.packXYZ(Math.toRadians(rotationVector.getX()), |
| Math.toRadians(rotationVector.getY()), Math.toRadians(rotationVector.getZ())); |
| |
| MathEditUtils.updateOrientation(this.matrix, ApogyCommonMathFacade.INSTANCE.createMatrix3x3(matrix3d), |
| this.editingDomain); |
| } |
| } |
| |
| protected Slider createSlider(Composite parent, int style, RotationAxis rotationAxis) { |
| Slider slider = new Slider(parent, style); |
| |
| slider.setMinimum(0); |
| slider.setPageIncrement(1); |
| slider.setMaximum(360); |
| slider.setSelection(180); |
| |
| if (rotationAxis == RotationAxis.X) { |
| slider.addSelectionListener(new SelectionListener() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| RotationMatrixSlidersComposite.this.disableEvent = true; |
| double newValue = Math.toRadians(slider.getSelection() - 180); |
| updateXRotation(newValue); |
| RotationMatrixSlidersComposite.this.disableEvent = false; |
| } |
| |
| @Override |
| public void widgetDefaultSelected(SelectionEvent e) { |
| } |
| }); |
| } else if (rotationAxis == RotationAxis.Y) { |
| slider.addSelectionListener(new SelectionListener() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| RotationMatrixSlidersComposite.this.disableEvent = true; |
| double newValue = Math.toRadians(slider.getSelection() - 180); |
| updateYRotation(newValue); |
| RotationMatrixSlidersComposite.this.disableEvent = false; |
| } |
| |
| @Override |
| public void widgetDefaultSelected(SelectionEvent e) { |
| } |
| }); |
| } else { |
| slider.addSelectionListener(new SelectionListener() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| RotationMatrixSlidersComposite.this.disableEvent = true; |
| double newValue = Math.toRadians(slider.getSelection() - 180); |
| updateZRotation(newValue); |
| RotationMatrixSlidersComposite.this.disableEvent = false; |
| } |
| |
| @Override |
| public void widgetDefaultSelected(SelectionEvent e) { |
| // TODO Auto-generated method stub |
| |
| } |
| }); |
| } |
| |
| return slider; |
| } |
| |
| private void updateRotations(Matrix3x3 matrix) { |
| if (matrix != null) { |
| if (this.rxSlider != null && !this.rxSlider.isDisposed() && this.rySlider != null |
| && !this.rySlider.isDisposed() && this.rzSlider != null && !this.rzSlider.isDisposed()) { |
| Vector3d rotationVector = GeometricUtils.extractRotationFromXYZRotMatrix(matrix.asMatrix3d()); |
| |
| int xRot = (int) Math.floor(Math.toDegrees(GeometricUtils.normalizeAngle(rotationVector.getX()))) + 180; |
| int yRot = (int) Math.floor(Math.toDegrees(GeometricUtils.normalizeAngle(rotationVector.getY()))) + 180; |
| int zRot = (int) Math.floor(Math.toDegrees(GeometricUtils.normalizeAngle(rotationVector.getZ()))) + 180; |
| |
| this.rxSlider.setSelection(xRot); |
| this.rySlider.setSelection(yRot); |
| this.rzSlider.setSelection(zRot); |
| } |
| } |
| } |
| |
| private Adapter getMatrixAdapter() { |
| if (this.matrixAdapter == null) { |
| this.matrixAdapter = new AdapterImpl() { |
| @Override |
| public void notifyChanged(Notification msg) { |
| if (!RotationMatrixSlidersComposite.this.disableEvent) { |
| updateRotations((Matrix3x3) msg.getNotifier()); |
| } |
| }; |
| }; |
| } |
| return this.matrixAdapter; |
| } |
| } |