Refactor CoordTransform

This commit is contained in:
SiboVG 2023-08-18 02:48:54 +02:00
parent ea59b9d012
commit c38d5f59a6
3 changed files with 189 additions and 71 deletions

View File

@ -4,10 +4,46 @@ package net.sf.openrocket.file.wavefrontobj;
* Representation of an axis in 3D space.
*/
public enum Axis {
X,
X_MIN, // Negative x
Y,
Y_MIN, // Negative y
Z,
Z_MIN // Negative z
X ("X"),
X_MIN ("-X"),
Y ("Y"),
Y_MIN ("-Y"),
Z ("Z"),
Z_MIN ("-Z");
private final String label;
Axis(String label) {
this.label = label;
}
@Override
public String toString() {
return label;
}
public static Axis fromString(String label) {
for (Axis axis : values()) {
if (axis.label.equals(label)) {
return axis;
}
}
throw new IllegalArgumentException("Unknown axis: " + label);
}
public boolean isSameAxis(Axis other) {
return this == other || this == getOppositeAxis(other);
}
public static Axis getOppositeAxis(Axis axis) {
return switch (axis) {
case X -> X_MIN;
case X_MIN -> X;
case Y -> Y_MIN;
case Y_MIN -> Y;
case Z -> Z_MIN;
case Z_MIN -> Z;
default -> throw new IllegalArgumentException("Unknown axis: " + axis);
};
}
}

View File

@ -1,5 +1,6 @@
package net.sf.openrocket.file.wavefrontobj;
import com.sun.istack.NotNull;
import de.javagl.obj.FloatTuple;
import net.sf.openrocket.util.Coordinate;
@ -11,7 +12,73 @@ import net.sf.openrocket.util.Coordinate;
*
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
*/
public interface CoordTransform {
public class CoordTransform {
// OpenRocket coordinate system axes mapping
protected final Axis xAxis;
protected final Axis yAxis;
protected final Axis zAxis;
protected final Axis axialAxis;
// Origin offsets
protected final double origXOffs;
protected final double origYOffs;
protected final double origZOffs;
/**
* Create a new coordinate system converter.
* @param xAxis the OpenRocket axis that corresponds to the transformed x-axis
* @param yAxis the OpenRocket axis that corresponds to the transformed y-axis
* @param zAxis the OpenRocket axis that corresponds to the transformed z-axis
* Example: you want the transformed coordinate system to have the z-axis as the longitudinal axis (= OpenRocket x-axis)
* and want its direction to be from the bottom of the rocket to the tip of the rocket (opposite direction
* of the OpenRocket x-axis), then you must pass Axis.X_MIN as the xAxis parameter.
* You must also add an offset to the origin of the transformed coordinate system, so that it starts
* at the bottom of the rocket => set origZOffs to the length of the rocket.
* @param axialAxis the axial/longitudinal axis <b>in the transformed coordinate system, with the direction
* relative to the OpenRocket x-axis !!</b>
* From the previous example, the longitudinal axis would be Axis.Z_MIN.
* @param origXOffs the x-offset of the origin of the OBJ coordinate system, <b>in the OpenRocket coordinate system</b>
* @param origYOffs the y-offset of the origin of the OBJ coordinate system, <b>in the OpenRocket coordinate system</b>
* @param origZOffs the z-offset of the origin of the OBJ coordinate system, <b>in the OpenRocket coordinate system</b>
*/
public CoordTransform(@NotNull Axis xAxis, @NotNull Axis yAxis, @NotNull Axis zAxis, @NotNull Axis axialAxis,
double origXOffs, double origYOffs, double origZOffs) {
if (xAxis == null || yAxis == null || zAxis == null || axialAxis == null) {
throw new IllegalArgumentException("Axes cannot be null");
}
if (xAxis.isSameAxis(yAxis) || xAxis.isSameAxis(zAxis) || yAxis.isSameAxis(zAxis)) {
throw new IllegalArgumentException("Axes must be different");
}
this.xAxis = xAxis;
this.yAxis = yAxis;
this.zAxis = zAxis;
this.axialAxis = axialAxis;
this.origXOffs = origXOffs;
this.origYOffs = origYOffs;
this.origZOffs = origZOffs;
}
private FloatTuple convertLoc(double x, double y, double z,
double origXOffs, double origYOffs, double origZOffs) {
final double xTrans = getTransformedCoordinate(xAxis, x, y, z);
final double yTrans = getTransformedCoordinate(yAxis, x, y, z);
final double zTrans = getTransformedCoordinate(zAxis, x, y, z);
final double origXTrans = getTransformedOriginOffset(xAxis, origXOffs, origYOffs, origZOffs);
final double origYTrans = getTransformedOriginOffset(yAxis, origXOffs, origYOffs, origZOffs);
final double origZTrans = getTransformedOriginOffset(zAxis, origXOffs, origYOffs, origZOffs);
return new DefaultFloatTuple(
(float) (xTrans + origXTrans),
(float) (yTrans + origYTrans),
(float) (zTrans + origZTrans)
);
}
/**
* Converts the location coordinates from OpenRocket to OBJ coordinates.
* The returned coordinates will also be shifted towards the origin of the OBJ coordinate system.
@ -22,7 +89,9 @@ public interface CoordTransform {
* @param z OpenRocket z-coordinate
* @return the location coordinates in OBJ coordinates
*/
FloatTuple convertLoc(double x, double y, double z);
public FloatTuple convertLoc(double x, double y, double z) {
return convertLoc(x, y, z, origXOffs, origYOffs, origZOffs);
}
/**
* Converts the location coordinates from OpenRocket to OBJ coordinates.
@ -32,7 +101,9 @@ public interface CoordTransform {
* @param coordinate OpenRocket coordinate
* @return the location coordinates in OBJ coordinates
*/
FloatTuple convertLoc(Coordinate coordinate);
public FloatTuple convertLoc(Coordinate coordinate) {
return convertLoc(coordinate.x, coordinate.y, coordinate.z);
}
/**
* Converts the location coordinates from OpenRocket to OBJ coordinates, without the offset of the origin.
@ -49,16 +120,24 @@ public interface CoordTransform {
* @param z OpenRocket z-coordinate
* @return the location coordinates in OBJ coordinates, with the origin set to the OpenRocket origin (the tip of the rocket)
*/
FloatTuple convertLocWithoutOriginOffs(double x, double y, double z);
public FloatTuple convertLocWithoutOriginOffs(double x, double y, double z) {
return convertLoc(x, y, z, 0, 0, 0);
}
/**
* Converts the rotation coordinates from OpenRocket to OBJ coordinates.
* @param x OpenRocket rotation in radians around the x-axis
* @param y OpenRocket rotation in radians around the y-axis
* @param z OpenRocket rotation in radians around the z-axis
* @param xRot OpenRocket rotation in radians around the x-axis
* @param yRot OpenRocket rotation in radians around the y-axis
* @param zRot OpenRocket rotation in radians around the z-axis
* @return the rotation coordinates in OBJ coordinates
*/
FloatTuple convertRot(double x, double y, double z);
public FloatTuple convertRot(double xRot, double yRot, double zRot) {
final double xRotTrans = getTransformedRotation(xAxis, xRot, yRot, zRot);
final double yRotTrans = getTransformedRotation(yAxis, xRot, yRot, zRot);
final double zRotTrans = getTransformedRotation(zAxis, xRot, yRot, zRot);
return new DefaultFloatTuple((float) xRotTrans, (float) yRotTrans, (float) zRotTrans);
}
/**
* Returns the equivalent axis for the x-axis in the OpenRocket coordinate system (axial axis).
@ -67,5 +146,62 @@ public interface CoordTransform {
* must return Axis.Z_MIN.
* @return the equivalent axis for the x-axis in the OpenRocket coordinate system (axial axis)
*/
Axis getAxialAxis();
public Axis getAxialAxis() {
return axialAxis;
}
/**
* Returns the transformed coordinate for the given axis.
* @param axis the OpenRocket axis to transform
* @param x the x-coordinate in the OpenRocket coordinate system
* @param y the y-coordinate in the OpenRocket coordinate system
* @param z the z-coordinate in the OpenRocket coordinate system
* @return the coordinate in the transformed OBJ coordinate system
*/
private double getTransformedCoordinate(Axis axis, double x, double y, double z) {
return switch (axis) {
case X -> x;
case X_MIN -> -x;
case Y -> y;
case Y_MIN -> -y;
case Z -> z;
case Z_MIN -> -z;
default -> throw new IllegalStateException("Unknown axis");
};
}
/**
* Returns the offset of the origin of the OBJ coordinate system for the given axis.
* @param axis the axis to get the offset for
* @return the offset of the origin of the OBJ coordinate system for the given axis
*/
private double getTransformedOriginOffset(Axis axis, double origXOffs, double origYOffs, double origZOffs) {
return switch (axis) {
case X, X_MIN -> origXOffs;
case Y, Y_MIN -> origYOffs;
case Z, Z_MIN -> origZOffs;
default -> throw new IllegalStateException("Unknown axis");
};
}
/**
* Returns the transformed rotation for the given axis.
* @param axis the OpenRocket axis to transform
* @param rotX the rotation in radians around the OpenRocket x-axis
* @param rotY the rotation in radians around the OpenRocket y-axis
* @param rotZ the rotation in radians around the OpenRocket z-axis
* @return the rotation in radians around the transformed OBJ axis
*/
private double getTransformedRotation(Axis axis, double rotX, double rotY, double rotZ) {
// OpenRocket uses left-handed coordinate system, we'll use right-handed
return switch (axis) {
case X -> -rotX;
case X_MIN -> rotX;
case Y -> -rotY;
case Y_MIN -> rotY;
case Z -> -rotZ;
case Z_MIN -> rotZ;
default -> throw new IllegalStateException("Unknown axis");
};
}
}

View File

@ -1,8 +1,5 @@
package net.sf.openrocket.file.wavefrontobj;
import de.javagl.obj.FloatTuple;
import net.sf.openrocket.util.Coordinate;
/**
* Default OpenRocket coordinate system to OBJ coordinate system converter.
* OpenRocket uses a left-handed coordinate system with the y-axis pointing up, the z-axis pointing away from the viewer,
@ -12,59 +9,8 @@ import net.sf.openrocket.util.Coordinate;
* - side view is in the z-x plane, with the x-axis pointing up
* - y-axis is pointing away from the viewer
*/
public class DefaultCoordTransform implements CoordTransform {
private final double rocketLength;
public class DefaultCoordTransform extends CoordTransform {
public DefaultCoordTransform(double rocketLength) {
this.rocketLength = rocketLength;
}
/**
* Converts the location coordinates from OpenRocket to OBJ coordinates.
* @param x OpenRocket x-coordinate (! careful, when translating the component location, some components need an extra
* offset here, such as the component length !)
* @param y OpenRocket y-coordinate
* @param z OpenRocket z-coordinate
* @return the location coordinates in OBJ coordinates
*/
@Override
public FloatTuple convertLoc(double x, double y, double z) {
return convertLocToOBJCoord(x, y, z, this.rocketLength, 0, 0);
}
@Override
public FloatTuple convertLoc(Coordinate coordinate) {
return convertLocToOBJCoord(coordinate.x, coordinate.y, coordinate.z, this.rocketLength, 0, 0);
}
/**
* Converts the location coordinates from OpenRocket to OBJ coordinates, with the offset of the origin.
* @param x OpenRocket x-coordinate
* @param y OpenRocket y-coordinate
* @param z OpenRocket z-coordinate
* @param origXOffs the x-offset of the origin of the OBJ coordinate system, <b>in the OpenRocket coordinate system</b>
* @param origYOffs the y-offset of the origin of the OBJ coordinate system, <b>in the OpenRocket coordinate system</b>
* @param origZOffs the z-offset of the origin of the OBJ coordinate system, <b>in the OpenRocket coordinate system</b>
* @return the location coordinates in OBJ coordinates
*/
private FloatTuple convertLocToOBJCoord(double x, double y, double z,
double origXOffs, double origYOffs, double origZOffs) {
return new DefaultFloatTuple((float) (y + origYOffs), (float) (z + origZOffs), (float) (origXOffs - x));
}
@Override
public FloatTuple convertLocWithoutOriginOffs(double x, double y, double z) {
return convertLocToOBJCoord(x, y, z, 0, 0, 0);
}
@Override
public FloatTuple convertRot(double x, double y, double z) {
// OpenRocket uses left-handed rotations, we need right-handed
return new DefaultFloatTuple((float) -y, (float) -z, (float) x);
}
@Override
public Axis getAxialAxis() {
return Axis.Z_MIN;
super(Axis.Y, Axis.Z, Axis.X_MIN, Axis.Z_MIN, 0, 0, rocketLength);
}
}