/*
* $Id$
* This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc
*
* Copyright (c) 2000-2012 Stephane GALLAND.
* Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports,
* Universite de Technologie de Belfort-Montbeliard.
* Copyright (c) 2013-2016 The original authors, and other authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.arakhne.afc.math.geometry.coordinatesystem;
import org.eclipse.xtext.xbase.lib.Pure;
/**
* Represents the different kind of 3D referencials and provides the convertion utilities.
*
* <p>A referencial axis is expressed by the front, left and top directions. For example <code>XYZ_LEFT_HAND</code> is for the
* coordinate system with front direction along <code>+/-X</code> axis, left direction along the <code>+/-Y</code> axis and top
* direction along the <code>+/-Z</code> axis according to a "left-hand" heuristic.
*
* <p>The default coordinate system is:
* <ul>
* <li>front: <code>(1, 0, 0)</code></li>
* <li>left: <code>(0, 1, 0)</code></li>
* <li>top: <code>(0, 0, 1)</code></li>
* </ul>
*
* <h3>Rotations</h3>
*
* <p>Rotations in a 3D coordinate system follow the right/left hand rules
* (assuming that <code>OX</code>, <code>OY</code> and <code>OZ</code> are the three axis of the coordinate system):
* <table border="1" width="100%" summary="Rotations">
* <tr>
* <td>Right-handed rule:</td>
* <td>
* <ul>
* <li>axis cycle is: <code>OX</code> > <code>OY</code> > <code>OZ</code> > <code>OX</code> > <code>OY</code>;</li>
* <li>when rotating around <code>OX</code>, positive rotation angle is going from <code>OY</code> to <code>OZ</code></li>
* <li>when rotating around <code>OY</code>, positive rotation angle is going from <code>OZ</code> to <code>OX</code></li>
* <li>when rotating around <code>OZ</code>, positive rotation angle is going from <code>OX</code> to <code>OY</code></li>
* </ul><br>
* <img border="0" width="200" src="doc-files/rotation_right.png" alt="[Right-handed Rotation Rule]">
* </td>
* </tr><tr>
* <td>Left-handed rule:</td>
* <td>
* <ul>
* <li>axis cycle is: <code>OX</code> > <code>OY</code> > <code>OZ</code> > <code>OX</code> > <code>OY</code>;</li>
* <li>when rotating around <code>OX</code>, positive rotation angle is going from <code>OY</code> to <code>OZ</code></li>
* <li>when rotating around <code>OY</code>, positive rotation angle is going from <code>OZ</code> to <code>OX</code></li>
* <li>when rotating around <code>OZ</code>, positive rotation angle is going from <code>OX</code> to <code>OY</code></li>
* </ul><br>
* <img border="0" width="200" src="doc-files/rotation_left.png" alt="[Left-handed Rotation Rule]">
* </td>
* </tr></table>
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @since 13.0
*/
public enum CoordinateSystem3D implements CoordinateSystem {
/**
* Left handed XZY coordinate system.
*
* <p><a hef="doc-files/xzy_left.png"><img src="doc-files/xzy_left.png" border="0" width="200" alt=
* "[Left Handed XZY Coordinate System]"></a>
*/
XZY_LEFT_HAND(0, 1, 1, 0),
/**
* Left handed XYZ coordinate system.
*
* <p><a hef="doc-files/xyz_left.png"><img src="doc-files/xyz_left.png" border="0" width="200" alt=
* "[Left Handed XYZ Coordinate System]"></a>
*/
XYZ_LEFT_HAND(-1, 0, 0, 1),
/**
* Right handed XZY coordinate system.
*
* <p><a hef="doc-files/xzy_right.png"><img src="doc-files/xzy_right.png" border="0" width="200" alt=
* "[Right Handed XZY Coordinate System]"></a>
*/
XZY_RIGHT_HAND(0, -1, 1, 0),
/**
* Right handed XYZ coordinate system.
*
* <p><a hef="doc-files/xyz_right.png"><img src="doc-files/xyz_right.png" border="0" width="200" alt=
* "[Right Handed XYZ Coordinate System]"></a>
*/
XYZ_RIGHT_HAND(1, 0, 0, 1);
//TODDO: private static final byte PIVOT_SYSTEM = 0;
private static CoordinateSystem3D userDefault;
//TODO: private final byte system;
CoordinateSystem3D(int lefty, int leftz, int topy, int topz) {
//TODO: this.system = toSystemIndex(lefty, leftz, topy, topz);
}
@Pure
@SuppressWarnings({ "checkstyle:returncount", "checkstyle:cyclomaticcomplexity", "magicnumber" })
private static byte toSystemIndex(int lefty, int leftz, int topy, int topz) {
if (lefty < 0) {
if (leftz == 0 && topy == 0 && topz != 0) {
if (topz < 0) {
return 1;
}
return 2;
}
} else if (lefty > 0) {
if (leftz == 0 && topy == 0 && topz != 0) {
if (topz < 0) {
return 3;
}
return 0;
}
} else {
if (lefty == 0 && leftz != 0) {
if (leftz < 0) {
if (topz == 0 && topy != 0) {
if (topy < 0) {
return 4;
}
return 5;
}
} else {
if (topz == 0 && topy != 0) {
if (topy < 0) {
return 6;
}
return 7;
}
}
}
}
throw new CoordinateSystemNotFoundException();
}
@Pure
@SuppressWarnings("magicnumber")
private static double[] fromSystemIndex(int index) {
// Compute the lower right sub-matrix
final double c1;
final double c2;
final double c3;
final double c4;
switch (index) {
case 1:
c1 = -1;
c2 = 0;
c3 = 0;
c4 = -1;
break;
case 2:
c1 = -1;
c2 = 0;
c3 = 0;
c4 = 1;
break;
case 3:
c1 = 1;
c2 = 0;
c3 = 0;
c4 = -1;
break;
case 4:
c1 = 0;
c2 = -1;
c3 = -1;
c4 = 0;
break;
case 5:
c1 = 0;
c2 = -1;
c3 = 1;
c4 = 0;
break;
case 6:
c1 = 0;
c2 = 1;
c3 = -1;
c4 = 0;
break;
case 7:
c1 = 0;
c2 = 1;
c3 = 1;
c4 = 0;
break;
default:
c1 = 1;
c2 = 0;
c3 = 0;
c4 = 1;
break;
}
return new double[] {c1, c2, c3, c4 };
}
/**
* {@inheritDoc}.
*/
@Pure
@Override
public boolean isRightHanded() {
return this == XYZ_RIGHT_HAND || this == XZY_RIGHT_HAND;
}
/**
* {@inheritDoc}.
*/
@Pure
@Override
public boolean isLeftHanded() {
return this == XYZ_LEFT_HAND || this == XZY_LEFT_HAND;
}
/**
* Replies the preferred coordinate system.
*
* @return the preferred coordinate system.
*/
@Pure
public static CoordinateSystem3D getDefaultCoordinateSystem() {
if (userDefault != null) {
return userDefault;
}
return CoordinateSystemConstants.SIMULATION_3D;
}
/**
* {@inheritDoc}.
*/
@Pure
@Override
public final int getDimensions() {
return 3;
}
/** Set the default coordinate system.
*
* @param system is the new default coordinate system.
* @see #getDefaultCoordinateSystem()
*/
public static void setDefaultCoordinateSystem(CoordinateSystem3D system) {
CoordinateSystem3D.userDefault = system;
}
}