All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.algart.math.geometry.StraightLine3D Maven / Gradle / Ivy

Go to download

Open-source Java libraries, supporting generalized smart arrays and matrices with elements of any types, including a wide set of 2D-, 3D- and multidimensional image processing and other algorithms, working with arrays and matrices.

There is a newer version: 1.4.23
Show newest version
package net.algart.math.geometry;

import java.util.Objects;
import java.util.random.RandomGenerator;

/**
 * 

Directional infinite straight line in 3D space. * It is defined as some start point o=(x0,y0,z0), belonging to this straight, * and some direction, represented as a unit vector d=(dx,dy,dz). * The line consists of all point p=o+td, −∞<t<+∞.

* *

This class is not thread-safe, but is thread-compatible * and can be synchronized manually if multithreading access is necessary.

*/ public final class StraightLine3D implements Cloneable { private double x0 = 0.0; private double y0 = 0.0; private double z0 = 0.0; private double dx = 1.0; private double dy = 0.0; private double dz = 0.0; private StraightLine3D() { } /** * Creates some new straight line, passing through the origin (0,0,0). * The direction of this straight is (1,0,0) (x-axis), but you should not use this fact: * in future versions this may change. * * @return new straight line. */ public static StraightLine3D newLine() { return new StraightLine3D(); } /** * Creates new straight line, passing through the origin (0,0,0), with the given direction. * *

If the given d vector is not unit, it is automatically * replaced with a unit vector of the same direction: all components are divided by its length. * But if the vector is shorter than {@link Orthonormal3DBasis#MIN_ALLOWED_LENGTH}, * an exception is thrown. * * @param dx x-component of the direction d. * @param dy y-component of the direction d. * @param dz z-component of the direction d. * @return new straight line. * @throws IllegalArgumentException if the specified vector is zero or extremely short. */ public static StraightLine3D newLineThroughOrigin( double dx, double dy, double dz) { return new StraightLine3D().setDirection(dx, dy, dz); } /** * Creates new straight line, passing through the given start point (x0,y0,z0), with the given direction. * *

If the given d vector is not unit, it is automatically * replaced with a unit vector of the same direction: all components are divided by its length. * But if the vector is shorter than {@link Orthonormal3DBasis#MIN_ALLOWED_LENGTH}, * an exception is thrown. * * @param x0 x-coordinate of the start point o. * @param y0 y-coordinate of the start point o. * @param z0 z-coordinate of the start point o. * @param dx x-component of the direction d. * @param dy y-component of the direction d. * @param dz z-component of the direction d. * @return new straight line. * @throws IllegalArgumentException if the specified vector is zero or extremely short. */ public static StraightLine3D newLine( double x0, double y0, double z0, double dx, double dy, double dz) { return new StraightLine3D().setStart(x0, y0, z0).setDirection(dx, dy, dz); } /** * Creates new straight line, passing through the given start point (x0,y0,z0) * and directed along the unit vector i of the specified basis. * * @param x0 x-coordinate of the start point o. * @param y0 y-coordinate of the start point o. * @param z0 z-coordinate of the start point o. * @param basis some orthonormal basis (i, j, k). * @return new straight line. * @throws NullPointerException if basis is {@code null}. */ public static StraightLine3D newLineAlongI(double x0, double y0, double z0, Orthonormal3DBasis basis) { return new StraightLine3D().setStart(x0, y0, z0).setDirectionAlongI(basis); } /** * Creates new straight line, passing through the given start point (x0,y0,z0) * and directed along the unit vector j of the specified basis. * * @param x0 x-coordinate of the start point o. * @param y0 y-coordinate of the start point o. * @param z0 z-coordinate of the start point o. * @param basis some orthonormal basis (i, j, k). * @return new straight line. * @throws NullPointerException if basis is {@code null}. */ public static StraightLine3D newLineAlongJ(double x0, double y0, double z0, Orthonormal3DBasis basis) { return new StraightLine3D().setStart(x0, y0, z0).setDirectionAlongJ(basis); } /** * Creates new straight line, passing through the given start point (x0,y0,z0) * and directed along the unit vector k of the specified basis. * * @param x0 x-coordinate of the start point o. * @param y0 y-coordinate of the start point o. * @param z0 z-coordinate of the start point o. * @param basis some orthonormal basis (i, j, k). * @return new straight line. * @throws NullPointerException if basis is {@code null}. */ public static StraightLine3D newLineAlongK(double x0, double y0, double z0, Orthonormal3DBasis basis) { return new StraightLine3D().setStart(x0, y0, z0).setDirectionAlongK(basis); } /** * Returns x-coordinate of the start point o. * * @return x-coordinate of the start point o. */ public double x0() { return x0; } /** * Sets x-coordinate of the start point o. * * @param x0 new x-coordinate of the start point o. * @return a reference to this object. */ public StraightLine3D x0(double x0) { this.x0 = x0; return this; } /** * Returns y-coordinate of the start point o. * * @return y-coordinate of the start point o. */ public double y0() { return y0; } /** * Sets y-coordinate of the start point o. * * @param y0 new y-coordinate of the start point o. * @return a reference to this object. */ public StraightLine3D y0(double y0) { this.y0 = y0; return this; } /** * Returns z-coordinate of the start point o. * * @return z-coordinate of the start point o. */ public double z0() { return z0; } /** * Sets z-coordinate of the start point o. * * @param z0 new z-coordinate of the start point o. * @return a reference to this object. */ public StraightLine3D z0(double z0) { this.z0 = z0; return this; } /** * Sets new start point o. * * @param x0 new x-coordinate of the start point o. * @param y0 new y-coordinate of the start point o. * @param z0 new z-coordinate of the start point o. * @return a reference to this object. */ public StraightLine3D setStart(double x0, double y0, double z0) { this.x0 = x0; this.y0 = y0; this.z0 = z0; return this; } /** * Returns x-component of the direction d. * * @return x-component of the direction d. */ public double dx() { return dx; } /** * Returns y-component of the direction d. * * @return y-component of the direction d. */ public double dy() { return dy; } /** * Returns z-component of the direction d. * * @return z-component of the direction d. */ public double dz() { return dz; } /** * Sets new direction d. * *

If the given d vector is not unit, it is automatically * replaced with a unit vector of the same direction: all components are divided by its length. * But if the vector is shorter than {@link Orthonormal3DBasis#MIN_ALLOWED_LENGTH}, * an exception is thrown. * * @param dx new x-component of the direction d. * @param dy new y-component of the direction d. * @param dz new z-component of the direction d. * @return a reference to this object. * @throws IllegalArgumentException if the specified vector is zero or extremely short. */ public StraightLine3D setDirection(double dx, double dy, double dz) { final double length = Orthonormal3DBasis.length(dx, dy, dz); if (length < Orthonormal3DBasis.MIN_ALLOWED_LENGTH) { throw new IllegalArgumentException("Zero or too short direction vector (" + dx + ", " + dy + ", " + dz + ")" + " (vectors with length <" + Orthonormal3DBasis.MIN_ALLOWED_LENGTH + " are not allowed)"); } final double mult = 1.0 / length; setDirectionComponents(dx * mult, dy * mult, dz * mult); return this; } /** * Shift the start point o along the direction d:
* o = o + shift * d.
* Please remember that d vector is unit, so the argument is equal to the actual value * of shifting the start point. * * @param shift value of shifting. * @return a reference to this object. */ public StraightLine3D shiftAlong(double shift) { x0 += shift * dx; y0 += shift * dy; z0 += shift * dz; return this; } /** * Sets new direction d equal to the unit vector i of the specified basis. * * @param basis some orthonormal basis (i, j, k). * @return a reference to this object. * @throws NullPointerException if basis is {@code null}. */ public StraightLine3D setDirectionAlongI(Orthonormal3DBasis basis) { Objects.requireNonNull(basis, "Null basis"); return setDirection(basis.ix(), basis.iy(), basis.iz()); } /** * Sets new direction d equal to the unit vector j of the specified basis. * * @param basis some orthonormal basis (i, j, k). * @return a reference to this object. * @throws NullPointerException if basis is {@code null}. */ public StraightLine3D setDirectionAlongJ(Orthonormal3DBasis basis) { Objects.requireNonNull(basis, "Null basis"); return setDirection(basis.jx(), basis.jy(), basis.jz()); } /** * Sets new direction d equal to the unit vector k of the specified basis. * * @param basis some orthonormal basis (i, j, k). * @return a reference to this object. * @throws NullPointerException if basis is {@code null}. */ public StraightLine3D setDirectionAlongK(Orthonormal3DBasis basis) { Objects.requireNonNull(basis, "Null basis"); return setDirection(basis.kx(), basis.ky(), basis.kz()); } /** * Sets new direction d equal to the unit vector (1,0,0). * * @return a reference to this object. */ public StraightLine3D setDirectionAlongX() { return setDirection(1.0, 0.0, 0.0); } /** * Sets new direction d equal to the unit vector (0,1,0). * * @return a reference to this object. */ public StraightLine3D setDirectionAlongY() { return setDirection(0.0, 1.0, 0.0); } /** * Sets new direction d equal to the unit vector (0,0,1). * * @return a reference to this object. */ public StraightLine3D setDirectionAlongZ() { return setDirection(0.0, 0.0, 1.0); } /** * Sets new direction randomly with uniform distribution in the space. * This is chosen with help of random.nextDouble() method. * * @param random random generator used to create the basis. * @return a reference to this object. */ public StraightLine3D setRandomDirection(RandomGenerator random) { for (; ; ) { final double dx = 2 * random.nextDouble() - 1.0; final double dy = 2 * random.nextDouble() - 1.0; final double dz = 2 * random.nextDouble() - 1.0; final double distanceSqr = dx * dx + dy * dy + dz * dz; if (distanceSqr >= 0.01 && distanceSqr < 1.0) { // Note: the second check is necessary to provide uniform distribution in a sphere (not in a cube). return setDirection(dx, dy, dz); } } } /** * Sets this straight to be identical to the passed straight. * * @param other other straight. * @return a reference to this object. * @throws NullPointerException if the argument is {@code null}. */ public StraightLine3D setTo(StraightLine3D other) { Objects.requireNonNull(other, "Null other"); this.x0 = other.x0; this.y0 = other.y0; this.z0 = other.z0; this.dx = other.dx; this.dy = other.dy; this.dz = other.dz; return this; } /** * Returns {@link #x0() x0} + t * {@link #dx() dx}. * * @param t the shift value from the start point. * @return x-coordinate of a point. */ public double x(double t) { return x0 + t * dx; } /** * Returns {@link #y0() y0} + t * {@link #dy() dy}. * * @param t the shift value from the start point. * @return y-coordinate of a point. */ public double y(double t) { return y0 + t * dy; } /** * Returns {@link #z0() z0} + t * {@link #dz() dz}. * * @param t the shift value from the start point. * @return z-coordinate of a point. */ public double z(double t) { return z0 + t * dz; } /** * Returns projection of the given vector a to this straight: ax * dx + ay * dy + az * dz. * *

Equivalent to * {@link Orthonormal3DBasis#scalarProduct * Orthonormal3DBasis.scalarProduct}(ax, ay, ax, dx, dy, dz).

* * @param ax x-component of the vector. * @param ay y-component of the vector. * @param az z-component of the vector. * @return projection of the given vector to the direction of this straight. */ public double vectorProjection(double ax, double ay, double az) { return ax * dx + ay * dy + az * dz; } /** * Returns (x−x0)*dx + (y−y0)*dy + (z−z0)*dz. * * @param x x-coordinate of the point. * @param y y-coordinate of the point. * @param z z-coordinate of the point. * @return t value for the projection of the given point to this straight. */ public double pointProjection(double x, double y, double z) { return (x - x0) * dx + (y - y0) * dy + (z - z0) * dz; } /** * Returns (x−x0)2 + (y−y0)2 + (z−z0)2. * * @param x x-coordinate of the point. * @param y y-coordinate of the point. * @param z z-coordinate of the point. * @return square of the distance to the start point o. */ public double distanceToStartPointSquare(double x, double y, double z) { return Orthonormal3DBasis.lengthSquare(x - x0, y - y0, z - z0); } /** * Returns the distance from the given point (x,y,z) to the start point (x0,y0,z0). *

Equivalent to * Math.sqrt({@link #distanceToStartPointSquare distanceToStartPointSquare}(x, y, z)).

* * @param x x-coordinate of the point. * @param y y-coordinate of the point. * @param z z-coordinate of the point. * @return square of the distance to the start point o. */ public double distanceToStartPoint(double x, double y, double z) { return Math.sqrt(distanceToStartPointSquare(x, y, z)); } /** * Returns the square of the distance from the given point (x,y,z) to this straight. * *

Equivalent to * {@link StraightLine3D#distanceToStraightSquare(double, double, double, double, double, double) * StraightLine3D.distanceToStraightSquare}({@link #dx()}, {@link #dy()}, {@link #dz()}, x - {@link * #x0()}, y - {@link #y0()}, z - {@link #z0()}).

* * @param x x-coordinate of the point. * @param y y-coordinate of the point. * @param z z-coordinate of the point. * @return square of the distance between the point and this straight. */ public double distanceToStraightSquare(double x, double y, double z) { return distanceToStraightSquare(dx, dy, dz, x - x0, y - y0, z - z0); } /** * Returns the distance from the given point (x,y,z) to this straight. *

Equivalent to * Math.sqrt({@link #distanceToStraightSquare(double, double, double) * distanceToStraightSquare}(x, y, z)).

* * @param x x-coordinate of the point. * @param y y-coordinate of the point. * @param z z-coordinate of the point. * @return distance between the point and this straight. */ public double distanceToStraight(double x, double y, double z) { return Math.sqrt(distanceToStraightSquare(x, y, z)); } /** * Returns a brief string description of this object. * *

The result of this method may depend on implementation. * * @return a brief string description of this object. */ public String toString() { return "straight (" + x0 + "," + y0 + "," + z0 + ")+t*(" + dx + "," + dy + "," + dz + ")"; } /** * Indicates whether some other object is an instance of this class, containing the same straight line * (the same o and d). * The corresponding coordinates are compared as in Double.equals method, * i.e. they are converted to long values by Double.doubleToLongBits method * and the results are compared. * * @param o the object to be compared for equality with this instance. * @return true if and only if the specified object is an instance of {@link StraightLine3D}, * representing the same straight line as this object. */ @Override public boolean equals(Object o) { if (!(o instanceof StraightLine3D that)) { return false; } return (Double.doubleToLongBits(that.x0) == Double.doubleToLongBits(x0) && Double.doubleToLongBits(that.y0) == Double.doubleToLongBits(y0) && Double.doubleToLongBits(that.z0) == Double.doubleToLongBits(z0) && Double.doubleToLongBits(that.dx) == Double.doubleToLongBits(dx) && Double.doubleToLongBits(that.dy) == Double.doubleToLongBits(dy) && Double.doubleToLongBits(that.dz) == Double.doubleToLongBits(dz)); } /** * Returns the hash code of this object. * * @return the hash code of this object. */ @Override public int hashCode() { int result = 0; result = 37 * result + Double.hashCode(x0); result = 37 * result + Double.hashCode(y0); result = 37 * result + Double.hashCode(z0); result = 37 * result + Double.hashCode(dx); result = 37 * result + Double.hashCode(dy); result = 37 * result + Double.hashCode(dz); return result; } /** * Returns an exact copy of this object. * * @return a reference to the clone. */ @Override public StraightLine3D clone() { try { return (StraightLine3D) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(e); } } /** * Returns the square of the distance from the given point (x,y,z) to the straight * {@link #newLineThroughOrigin(double, double, double) getInstanceFromOrigin}(dx, dy, dz), * where d=(dx,dy,dz) is some unit vector. * *

This method works faster than creating a new instance of this class and calling its * {@link #distanceToStraightSquare(double, double, double)} method. * But this method requires that the vector (dx, dy, dz) to be unit: * dx * dx + dy * dy+ dz * dz = 1.0, * otherwise its result will be incorrect. * * @param dx x-component of the unit direction vector d. * @param dy y-component of the unit direction vector d. * @param dz z-component of the unit direction vector d. * @param x x-coordinate of the point. * @param y y-coordinate of the point. * @param z z-coordinate of the point. */ public static double distanceToStraightSquare(double dx, double dy, double dz, double x, double y, double z) { final double t = x * dx + y * dy + z * dz; return Orthonormal3DBasis.lengthSquare(x - t * dx, y - t * dy, z - t * dz); // - more stable solution than x^2+y^2+z^2-t^2 } /** * Returns the distance from the given point (x,y,z) to the straight * {@link #newLineThroughOrigin(double, double, double) getInstanceFromOrigin}(dx, dy, dz), * where d=(dx,dy,dz) is some unit vector. * *

Equivalent to * Math.sqrt({@link #distanceToStraightSquare(double, double, double, double, double, double) * distanceToStraightSquare}(dx, dy, dz, x, y, z)).

* * @param dx x-component of the unit direction vector d. * @param dy y-component of the unit direction vector d. * @param dz z-component of the unit direction vector d. * @param x x-coordinate of the point. * @param y y-coordinate of the point. * @param z z-coordinate of the point. */ public static double distanceToStraight(double dx, double dy, double dz, double x, double y, double z) { return Math.sqrt(distanceToStraightSquare(dx, dy, dz, x, y, z)); } // Called via reflection in the test for debugging needs; must be private private void setDirectionComponents(double dx, double dy, double dz) { this.dx = dx; this.dy = dy; this.dz = dz; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy