/* * $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.Inline; import org.eclipse.xtext.xbase.lib.Pure; import org.arakhne.afc.math.geometry.d2.ImmutableVector2D; import org.arakhne.afc.math.geometry.d2.Point2D; import org.arakhne.afc.math.geometry.d2.Transform2D; import org.arakhne.afc.math.geometry.d2.Vector2D; import org.arakhne.afc.vmutil.asserts.AssertMessages; /** * Represents the different kind of 2D referencials * and provides the convertion utilities. * * <p>A referencial axis is expressed by the front and left directions. * For example <code>XY_LEFT_HAND</code> is for the coordinate system * with front direction along <code>+X</code> axis, * and left direction along the <code>-Y</code> axis according to * a "left-hand" heuristic. * * <p>The default coordinate system is: * <ul> * <li>front: <code>(1, 0)</code></li> * <li>left: <code>(0, 1)</code></li> * </ul> * * @author $Author: cbohrhauer$ * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ * @since 13.0 */ public enum CoordinateSystem2D implements CoordinateSystem { /** Right handed XY coordinate system. * * <p><a href="doc-files/xy_right.png"><img border="0" src="doc-files/xy_right.png" width="200" * alt="[Right Handed XY Coordinate System]"></a> */ XY_RIGHT_HAND, /** Left handed XY coordinate system. * * <p><a href="doc-files/xy_left.png"><img border="0" src="doc-files/xy_left.png" width="200" * alt="[Left Handed XY Coordinate System]"></a> */ XY_LEFT_HAND; private static CoordinateSystem2D defaultCoordinateSystem; @Pure @Override public final int getDimensions() { return 2; } /** Convert the specified point from the current coordinate system * to the specified coordinate system. * * @param point is the point to convert * @param targetCoordinateSystem is the target coordinate system. */ public void toSystem(Point2D<?, ?> point, CoordinateSystem2D targetCoordinateSystem) { assert point != null : AssertMessages.notNullParameter(0); assert targetCoordinateSystem != null : AssertMessages.notNullParameter(1); if (this != targetCoordinateSystem) { point.setY(-point.getY()); } } /** Convert the specified point from the current coordinate system * to the specified coordinate system. * * @param point is the point to convert * @param targetCoordinateSystem is the target coordinate system. */ public void toSystem(Vector2D<?, ?> point, CoordinateSystem2D targetCoordinateSystem) { assert point != null : AssertMessages.notNullParameter(0); assert targetCoordinateSystem != null : AssertMessages.notNullParameter(1); if (this != targetCoordinateSystem) { point.setY(-point.getY()); } } /** Convert the specified rotation from the current coordinate system * to the specified coordinate system. * * @param rotation is the rotation to convert * @param targetCoordinateSystem is the target coordinate system. * @return the converted rotation */ @Pure public double toSystem(double rotation, CoordinateSystem2D targetCoordinateSystem) { assert targetCoordinateSystem != null : AssertMessages.notNullParameter(1); if (this != targetCoordinateSystem) { return -rotation; } return rotation; } /** Convert the specified transformation matrix into from the current coordinate system * to the specified coordinate system. * * @param matrix is the matrix to convert * @param targetCoordinateSystem is the target coordinate system. */ public void toSystem(Transform2D matrix, CoordinateSystem2D targetCoordinateSystem) { assert matrix != null : AssertMessages.notNullParameter(0); assert targetCoordinateSystem != null : AssertMessages.notNullParameter(1); if (this != targetCoordinateSystem) { final double r = -matrix.getRotation(); matrix.setRotation(r); matrix.setM12(-matrix.getM12()); } } /** Convert the specified point into the default coordinate system. * * @param point is the point to convert */ public void toDefault(Point2D<?, ?> point) { if (this != getDefaultCoordinateSystem()) { point.setY(-point.getY()); } } /** Convert the specified vector from the default coordinate system. * * @param vector is the vector to convert */ public void toDefault(Vector2D<?, ?> vector) { if (this != getDefaultCoordinateSystem()) { vector.setY(-vector.getY()); } } /** Convert the specified transformation matrix from the default coordinate system. * * @param matrix is the matrix to convert */ public void toDefault(Transform2D matrix) { if (this != getDefaultCoordinateSystem()) { final double r = -matrix.getRotation(); matrix.setRotation(r); matrix.setM21(-matrix.getM21()); } } /** Convert the specified rotation into the default coordinate system. * * @param rotation is the rotation to convert * @return the converted rotation */ @Pure public double toDefault(double rotation) { if (this != getDefaultCoordinateSystem()) { return -rotation; } return rotation; } /** Convert the specified point from the default coordinate system. * * @param point is the point to convert */ public void fromDefault(Point2D<?, ?> point) { if (this != getDefaultCoordinateSystem()) { point.setY(-point.getY()); } } /** Convert the specified vector from the default coordinate system. * * @param vector is the vector to convert */ public void fromDefault(Vector2D<?, ?> vector) { if (this != getDefaultCoordinateSystem()) { vector.setY(-vector.getY()); } } /** Convert the specified transformation matrix from the default coordinate system. * * @param matrix is the matrix to convert */ public void fromDefault(Transform2D matrix) { if (this != getDefaultCoordinateSystem()) { final double r = -matrix.getRotation(); matrix.setRotation(r); matrix.setM21(-matrix.getM21()); } } /** Convert the specified rotation from the default coordinate system. * * @param rotation is the rotation to convert * @return the converted rotation */ @Pure public double fromDefault(double rotation) { if (this != getDefaultCoordinateSystem()) { return -rotation; } return rotation; } /** Replies the default coordinate system. * * <p>If it is not changed, the default coordinate system is the one used for 2D simulation: * {@link CoordinateSystemConstants#SIMULATION_2D}. * * @return the default coordinate system. * @see #setDefaultCoordinateSystem(CoordinateSystem2D) */ @Pure public static CoordinateSystem2D getDefaultCoordinateSystem() { if (defaultCoordinateSystem == null) { return CoordinateSystemConstants.SIMULATION_2D; } return defaultCoordinateSystem; } /** Set the default coordinate system. * * @param system is the new default coordinate system. * @see #getDefaultCoordinateSystem() */ public static void setDefaultCoordinateSystem(CoordinateSystem2D system) { defaultCoordinateSystem = system; } /** Replies the coordinate system which is corresponding to the specified * orientation unit vectors. * * <p>The front vector is assumed to be always <code>(1, 0)</code>, * and the left vector is <code>(0, ly)</code>. * * @param ly y coordinate to left. * @return the coordinate system which is corresponding to the specified vector. */ @Pure public static CoordinateSystem2D fromVectors(int ly) { assert ly != 0; return (ly < 0) ? XY_LEFT_HAND : XY_RIGHT_HAND; } /** Replies the coordinate system which is corresponding to the specified * orientation unit vectors. * * <p>The front vector is assumed to be always <code>(1, 0)</code>, * and the left vector is <code>(0, ly)</code>. * If <code>ly</code> is negative, then the corrdinate system is left-handed, otherwise * it is right-handed. * * @param ly y coordinate to the left. * @return the coordinate system which is corresponding to the specified vector. */ @Pure public static CoordinateSystem2D fromVectors(double ly) { assert ly != 0.; return (ly < 0.) ? XY_LEFT_HAND : XY_RIGHT_HAND; } @Pure @Override public boolean isRightHanded() { return this == XY_RIGHT_HAND; } @Pure @Override public boolean isLeftHanded() { return this == XY_LEFT_HAND; } /** Replies the front vector. * * @return the front vector. */ @Pure @Inline(value = "new ImmutableVector2D(1, 0)", imported = {ImmutableVector2D.class}) public static Vector2D<?, ?> getViewVector() { return new ImmutableVector2D(1, 0); } /** Replies the front vector. * * @param <T> the type of the vector. * @param vectorToFill is the vector to set with the front vector values. * @return <code>vectorToFill</code>. */ public static <T extends Vector2D<?, ?>> T getViewVector(T vectorToFill) { assert vectorToFill != null; vectorToFill.set(1, 0); return vectorToFill; } /** Replies the back vector. * * @return the back vector. */ @Pure @Inline(value = "new ImmutableVector2D(-1, 0)", imported = {ImmutableVector2D.class}) public static Vector2D<?, ?> getBackVector() { return new ImmutableVector2D(-1, 0); } /** Replies the back vector. * * @param <T> the type of the vector. * @param vectorToFill is the vector to set with the back vector values. * @return the back vector. */ public static <T extends Vector2D<?, ?>> T getBackVector(T vectorToFill) { assert vectorToFill != null; vectorToFill.set(-1, 0); return vectorToFill; } /** Replies the left vector. * * @return the left vector. */ @Pure public Vector2D<?, ?> getLeftVector() { switch (this) { case XY_LEFT_HAND: return new ImmutableVector2D(0, -1); case XY_RIGHT_HAND: return new ImmutableVector2D(0, 1); default: throw new CoordinateSystemNotFoundException(); } } /** Replies the left vector. * * @param <T> the type of the vector. * @param vectorToFill is the vector to set with the left vector values. * @return the left vector. */ public <T extends Vector2D<?, ?>> T getLeftVector(T vectorToFill) { assert vectorToFill != null; switch (this) { case XY_LEFT_HAND: vectorToFill.set(0, -1); return vectorToFill; case XY_RIGHT_HAND: vectorToFill.set(0, 1); return vectorToFill; default: throw new CoordinateSystemNotFoundException(); } } /** Replies the right vector. * * @return the right vector. */ @Pure public Vector2D<?, ?> getRightVector() { switch (this) { case XY_LEFT_HAND: return new ImmutableVector2D(0, 1); case XY_RIGHT_HAND: return new ImmutableVector2D(0, -1); default: throw new CoordinateSystemNotFoundException(); } } /** Replies the right vector. * * @param <T> the type of the vector. * @param vectorToFill is the vector to set with the right vector values. * @return the right vector. */ public <T extends Vector2D<?, ?>> T getRightVector(T vectorToFill) { assert vectorToFill != null; switch (this) { case XY_LEFT_HAND: vectorToFill.set(0, 1); return vectorToFill; case XY_RIGHT_HAND: vectorToFill.set(0, -1); return vectorToFill; default: throw new CoordinateSystemNotFoundException(); } } /** Replies the 3D coordinate system which is corresponding to * this 2D coordinate system. * * @return the 3D coordinate system */ @Pure public CoordinateSystem3D toCoordinateSystem3D() { switch (this) { case XY_LEFT_HAND: return CoordinateSystem3D.XYZ_LEFT_HAND; case XY_RIGHT_HAND: return CoordinateSystem3D.XYZ_RIGHT_HAND; default: throw new CoordinateSystemNotFoundException(); } } }