Рубрики
Без рубрики

Пересечение вектора со сферой

Проверьте, пересекает ли вектор сферу в одной или двух точках. С тегами тригонометрия, 3d, вектор, java.

Мой хороший друг хотел получить некоторую помощь в проекте виртуальной реальности, чтобы увидеть, пересекается ли raid (вектор движения контроллера) со сферическим видовым экраном пользователя. Вот элементарная java-программа для проверки вектора, пересекающего сферу.

Пользовательский ввод <- Координаты двух точек вектора и координаты центра сферы и радиуса сферы Вывод -> Координаты точки (точек) пересечения

Я не программировал на Java уже пару десятилетий, так что это был интересный и обогащающий опыт, поскольку программа постепенно создавалась, совершенствовалась и перерабатывалась (в меру моих возможностей). Конечно, это неэффективно с точки зрения вычислений, но я надеюсь в какой-то момент сделать его API для использования в Unity!

/** Copyright - Trivikram Prasad
    Date: May 19, 2018
    All Rights Reserved
 */

// Program to calculate the points of intersection of a vector with a Sphere
import java.util.Scanner;


// DEFINE ALL CLASSES

// 3D Point class
class Point3D{
    double x,y,z;   //Coordinates of a point

    public Point3D (double x, double y, double z)
    {
        this.x = x;
        this.y = y; 
        this.z = z;
    }
}

// Sphere Class
class Sphere{
    double cX, cY, cZ; // Coordinates of the sphere center
    double cR;      // Radius of sphere

    public Sphere (double cX, double cY, double cZ, double cR)
    {
        this.cX = cX;
        this.cY = cY;
        this.cZ = cZ;
        this.cR = cR;
    }
}

// String class -- only for formatting output
class StringPoint{
    String pX, pY, pZ; // Converting coordinate values to string values for formatting

    public StringPoint (String pX, String pY, String pZ)
    {
        this.pX = pX;
        this.pY = pY;
        this.pZ = pZ;       
    }
}

// The main class. This is where the real s**t happens
public class lineSphereX {
    public static void main(String[] args){
        double a,b,c;   // Coefficients of the quadratic equation
        double discr;   // Square of the discriminant of the quadratic
        double t1 = 0.0; // parameter 1
        double t2 = 0.0; // parameter 2

        Scanner in = new Scanner(System.in);

        // Read coordinates of the first point on the line
        System.out.print("Enter x, y, z coordinates of the 1st point on the line: ");
        Point3D point1 = readLineInputCoordinates(in);

        // Read coordinates of the second point on the line
        System.out.print("Enter x, y, z coordinates of the 2nd point on the line: ");
        Point3D point2 = readLineInputCoordinates(in);

        // Read center coordinates and radius of sphere
        System.out.print("Enter x, y, z center coordinates and RADIUS 'r' of the sphere: ");
        Sphere sphCenter= readSphereInputCoordinates(in);

        in.close();

        //Calculate coefficients: 'a', 'b', 'c' for the equation 'ax^2 + bx + c = 0
        a = Math.pow(point2.x - point1.x,2) + Math.pow(point2.y - point1.y,2) + Math.pow(point2.z - point1.z,2);
        b = 2 * ((point2.x-point1.x) * (point1.x-sphCenter.cX) + (point2.y-point1.y) * (point1.y-sphCenter.cY)+ (point2.z-point1.z) * (point1.z-sphCenter.cZ));
        c = Math.pow((point1.x - sphCenter.cX),2) +  Math.pow((point1.y - sphCenter.cY),2) +  Math.pow((point1.z - sphCenter.cZ),2) - Math.pow(sphCenter.cR, 2);
        discr = Math.pow(b, 2) - (4*a*c);

        // No intersection points`
        if (discr < 0)
        {
            System.out.println("\nVector does not intersect the sphere");
            return;     
        }
        else if(discr == 0)  // Single intersection point
        {

            System.out.println("\nVector intersects the sphere at a single point:");

            if (a > 0)
            {
                t1 = -b/(2*a);

                StringPoint XPoint = findXPoint(point1, point2, t1);

                System.out.println("The tangent to sphere is at " + XPoint.pX + ","+ XPoint.pY + "," + XPoint.pZ + "\n");
            }
            else{
                System.out.println("Not a line\n");
            }
        }

        else // Two intersection points
        {
            System.out.println("\nVector intersects the sphere at two points");
            t1 = (-b - Math.sqrt(discr))/(2*a); // 1st Vector equation parameter
            t2 = (-b + Math.sqrt(discr))/(2*a); // 2nd Vector equation parameter

            // Find the points of intersection
            StringPoint XPoint1 = findXPoint(point1, point2, t1);
            StringPoint XPoint2 = findXPoint(point1, point2, t2);

            System.out.println("1st point of vector intersection with sphere: " + XPoint1.pX + "," + XPoint1.pY + "," + XPoint1.pZ);
            System.out.println("2nd point of vector intersection with sphere: " + XPoint2.pX + "," + XPoint2.pY + "," + XPoint2.pZ + "\n");
        }

        System.exit(0);     
    }

    // Function for user input of sphere center coordinates and radius
    private static Sphere readSphereInputCoordinates(Scanner input) {

        double sphere_ctr [] = new double[4];
        Sphere input_sphere = new Sphere(0,0,0,0);
        for (int i = 0; i < 4; i++)
        {
            sphere_ctr[i] = input.nextDouble();
        }
        input_sphere.cX= sphere_ctr[0];
        input_sphere.cY = sphere_ctr[1];
        input_sphere.cZ = sphere_ctr[2];
        input_sphere.cR = sphere_ctr[3];

        return input_sphere;        
    }

    // Function for user inputs of point coordinates
    private static Point3D readLineInputCoordinates(Scanner input) {

        double line_pt [] = new double[3];
        Point3D input_coords = new Point3D(0,0,0);  
        for (int i = 0; i < 3; i++)
        {
            line_pt[i] = input.nextDouble();
        }
        input_coords.x = line_pt[0];
        input_coords.y = line_pt[1];
        input_coords.z = line_pt[2];

        return input_coords;    
    }

    // Function to calculate the point of intersection
    private static StringPoint findXPoint(Point3D point1, Point3D point2, double t) {

        Point3D intPoint = new Point3D(0,0,0);
        StringPoint XStrPoint = new StringPoint("","","");

        // Parametric equation of the form L = P + tU
        // where 'L' is the intersection point, 'P' is the point on the line and
        // U is the unit vector (Point2 - Point1)
        intPoint.x = point1.x + t * (point2.x - point1.x);
        intPoint.y = point1.y + t * (point2.y - point1.y);      
        intPoint.z = point1.z + t * (point2.z - point1.z);

        XStrPoint = formatString(intPoint);

        return XStrPoint;   
    }

    // Function to format the coordinates to string for display/output to console
    private static StringPoint formatString(Point3D intPoint) {

        StringPoint strPoint = new StringPoint("","","");

        strPoint.pX = String.format("%.2f", intPoint.x);
        strPoint.pY= String.format("%.2f", intPoint.y);
        strPoint.pZ = String.format("%.2f", intPoint.z);

        return strPoint;
    }
}

Оригинал: “https://dev.to/bacchu/intersection-of-a-vector-with-a-sphere-5b5k”