JavaPhysics новий физический движок на Java с изменениями плотности воздуха и гравитации на висоте и со lift/drag силой та 1D, 2D, 3D и 4D расчетами

12 апреля, 10:41 Технологии 3124 0

Короче говоря, я разрабатываю свой физический движок (ссылка: bitbucket.org/javaphysics/javaphysicsengine). Он поддерживает 1D, 2D, 3D и 4D физику и коллизии. (P.S. На данный момент коллизии не реализованы только для сфер и одиночных объектов). Движок бесплатный и можно адаптировать под свои нужды. Также его можно интегрировать с другими проектами, а визуализацию можно реализовать самостоятельно. Движок написан на Java.

СРАВНЕНИЯ
Критерий                       JavaPhysics     Unity PhysX             Box2D

1D/2D/3D/4D                 ✅ Все              ✅ 3D /2D                 ✅2D
Атмосфера по высоте ✅                     ❌                               ❌

Гравитация по высоте ✅                    ❌                               ❌

Коллизии                         ⚠️ Частично ✅ Мощно                ✅ Есть
Lift/Drag силы                 ✅ Все             ⚠️Lift через Rigid  ❌ Нет
Оптимизация                 ⚠️ 3 метода   ✅ Мощная              ✅ Есть
Real-Time игры               ❌                     ✅ Адаптировано  ❌
Научные симуляции     ✅ Точный      ⚠️ Не очень точн  ❌
Платформы                      ✅ На все IDE⚠️ PC/Telephone    ⚠️ Хз
Простота                          ⚠️ Сложно     ✅ Есть куча инфи ✅ Прост
 

 Вот код если физику прям сейчас хотите в код вставить:
package lmtech.javaphysics.physics;


 

import java.util.concurrent.ForkJoinPool;

import java.util.concurrent.RecursiveTask;

import lmtech.javaphysics.PhysicsOutOfRange;

import lmtech.javaphysics.math.Vector1D;

import lmtech.javaphysics.math.Vector2D;

import lmtech.javaphysics.math.Vector3D;

import lmtech.javaphysics.math.Vector4D;


 

/**

 * The main class with JavaPhysics Core Module.

 * <p>This class provided main physics and other methods to simulate realistic physics.</p>

 *

 * <p>In this class have a 16 methods for simulate physics. This physics engine realize a Aerodynamic, Air density, Gravity (changing at height), Atmosphere (changing at height) and Ballisitic trajectories with Drag/Lift forces</p>

 * <p>JavaPhysics provided collisions, this class provided one-object 1D, 2D, 3D and 4D collisions. Main collisions in {@link PhysicsCollider Collision segment}</p>

 */

public class Physics {

    /**

     * Free falling acceleration (m/c²)

     */

    public static final double GRAVITY = 9.80655; // Free falling acceleration (m/c²)

    /**

     * Speed of light

     */

    public static final double C = 299792458; // Speed of light

    /**

     * Air density

     */

    public static final double AIR_DENSITY = 1.225; // Air density

    /**

     * Temparature gradient (K/m)

     */

    public static final double L = -0.0065; // Temparature gradient (K/m)

    /**

     * Temparature in sea level (K)

     */

    public static final double T_0 = 288.15;  // Temparature in sea level (K)

    /**

     * Molecular air mass (kg/mol)

     */

    public static final double M = 0.0289644;  // Molecular air mass (kg/mol)

    /**

     * Uniniversal gas static (J/(mol·K))

     */

    public static final double R = 8.314;  // Uniniversal gas static (J/(mol·K))

    /**

     * Gravitational constant (m³/kg·s²)

     */

    public static final double G = 6.67430e-11; // Gravitational constant (m³/kg·s²)

    /**

     * Pressure in sea level (Pa)

     */

    public static final double P0 = 101325; // Pressure in sea level (Pa)

    /**

     * Sea level density (kg/m³)

     */

    private static final double SEA_LEVEL_DENSITY = 1.225; // kg/m³

    /**

     * Sea level temperature Kelvin

     */

    private static final double SEA_LEVEL_TEMPERATURE = 288.15; // K

    /**

     * Air gas constant J/(kg·K)

     */

    private static final double AIR_GAS_CONSTANT = 287.05; // J/(kg·K)

    /**

     * K/m (in tropesphere)

     */

    private static final double TEMP_LAPSE_RATE_T = 0.0065; // K/m (in tropesphere)

    /**

     * K/m (in stratophere)

     */

    private static final double TEMP_LAPSE_RATE_S = 0.0010; // K/m (in stratophere)

    /**

     * K/m (in mesosphere)

     */

    private static final double TEMP_LAPSE_RATE_M = 0.0000; // K/m (in mesosphere)

    /**

     * Earth radius in meters

     */

    public static final double EARTH_RADIUS = 6371000; // Earth radius in meters

   

    /**

     * Normalize angle from 0 to 360

     * @param angle Angle to normalize

     * @return Normalized angle

     */

    public static double normalizeAngle(double angle) {

        angle = angle % 360;  // Range of -360 to 360

        if (angle < 0) {

            angle += 360; // If angle smaller than zero, add 360, for range from 0 to 360

        }

        return angle;

    }

   

    /**

     * TEST

     */

    public Physics() {}

   

    /**

     * Calculate air density on height

     * <p>This method used accuraty-formula for calculate air density</p>

     * <pre>

     *      1st formula

     *      Th = S-T*h

     *      Th - Temparature at height

     *      S - Sea level temparature 288.15 Kelvin

     *      T - Temparature lapse rate 0.0065 Kelvin/m

     *      h - Height

     *

     *      2nd formula

     *      Ad = S*(Th/S)^(-G/(Ag*T))

     *      Ad - Air density

     *      S - Sea level temparature 288.15 Kelvin

     *      T - Temparature lapse rate 0.0065 Kelvin/m

     *      Th - Temparature at height

     *      G - Free-falling acceleration 9.81 m/c²

     *      Ag - Air gas constant 287.05 Joules/(kg·K)

     * </pre>

     * @param h Height (m)

     * @return Air density (kg/m³)

     * @throws PhysicsOutOfRange If height is negative, air density is uncorrect calculated and physics is breaked.

     */

    public static double airDensityAtHeight(double h) throws PhysicsOutOfRange {

        if (h < 0) throw new PhysicsOutOfRange("Height: " + h + " is negative. Air density cannot be calculated!");


 

        double tempAtHeight;

        double lapseRate;

   

        // First, check for the first layer (up to 20 km)

        if (h < 20000) {

            tempAtHeight = SEA_LEVEL_TEMPERATURE - TEMP_LAPSE_RATE_T * h;

            lapseRate = TEMP_LAPSE_RATE_T;

        }

        // Second, between 20-50 km (tropopause layer)

        else if (h < 50000) {

            double tropopauseTemp = SEA_LEVEL_TEMPERATURE - TEMP_LAPSE_RATE_T * 20000;

            tempAtHeight = tropopauseTemp - TEMP_LAPSE_RATE_S * (h - 20000);

            lapseRate = TEMP_LAPSE_RATE_S;

        }

        // Third, between 50-85 km (stratopause layer)

        else if (h < 85000) {

            double stratopauseTemp = (SEA_LEVEL_TEMPERATURE - TEMP_LAPSE_RATE_T * 20000) - TEMP_LAPSE_RATE_S * 30000;

            tempAtHeight = stratopauseTemp - TEMP_LAPSE_RATE_M * (h - 50000);

            lapseRate = TEMP_LAPSE_RATE_M;

        } else {

            // Above 85 km

            return SEA_LEVEL_DENSITY * Math.exp(-h / 55000);

        }


 

        // If temperature at height is less than 0, set density to 0

        if (tempAtHeight <= 0) return 0;


 

        // Ensure that the computed density does not go to infinity

        double exponent = (-GRAVITY / (AIR_GAS_CONSTANT * lapseRate)) * Math.log(tempAtHeight / SEA_LEVEL_TEMPERATURE);

        if (exponent < -1000) return 0;  // Prevent overflow to infinity


 

        // Compute air density

        return SEA_LEVEL_DENSITY * Math.pow(tempAtHeight / SEA_LEVEL_TEMPERATURE, exponent);

    }

   

    /**

     * Calculate aerodynamic forces: lift and drag

     * <p>This method used accuraty-formula for calculate aerodynamic force</p>

     * <pre>

     *      1st formula:

     *      Dp = 0.5*Ad*v^2

     *      Dp - Dynamic pressure

     *      Ad - Air density

     *      v - Velocity

     *

     *      2nd formula

     *      Lf = Dp*a*lC

     *      Lf - Lift force

     *      Dp - Dynamic pressure

     *      a - Cross-Sectional area (m²)

     *      lC - Lift coeficient

     *

     *      3d formula:

     *      Df = Dp*a*dC

     *      Df - Drag force

     *      a - Cross-Sectional area (m²)

     *      dC - Drag coeficient

     * </pre>

     * @param velocity Object velocity

     * @param angleOfAttack Angle of attack

     * @param height Height of pbject

     * @param area Cross-Sectional area (m²)

     * @param liftCoef Lift coeficient

     * @param dragCoef Drag coeficient

     * @return Vector2D x - lift force, y - drag force

     * @throws lmtech.javaphysics.PhysicsOutOfRange If angle of attack smaller of zero of bigger of 360

     */

    public static Vector2D calcAerodynamicForces(double velocity, double height, double angleOfAttack, double area, double liftCoef, double dragCoef) throws PhysicsOutOfRange {

        if (angleOfAttack < 0 || angleOfAttack > 360) throw new PhysicsOutOfRange("Angle of attack out of range!");

        double dynamicPressure = 0.5 * airDensityAtHeight(height) * velocity * velocity;

        double lift = dynamicPressure * area * liftCoef;

        double drag = dynamicPressure * area * dragCoef;

       

        return new Vector2D(lift, drag);

    }

   

    /**

     * Calculate drag force

     * <pre>

     *      Formula:

     *      Df = 0.5*Ad*v^2*dC*a

     *      Df - Drag coeficient

     *      Ad - Air density

     *      v - Velocity

     *      dC - Drag coeficient

     *      a - Cross-Sectional area (m²)

     * </pre>

     * @param velocity Object velocity

     * @param dragCoefficient Drag coeficient

     * @param area Cross-Sectional area (m²)

     * @param altitude Height of object (meters)

     * @return Drag force

     * @throws PhysicsOutOfRange If altitude is negative

     */

    public static double calculateDragForce(double velocity, double dragCoefficient, double area, double altitude) throws PhysicsOutOfRange {

        double airDensity = airDensityAtHeight(altitude);

        return 0.5 * airDensity * velocity * velocity * dragCoefficient * area;

    }

    /**

     * Calculate free falling acceleration (gravity) on height

     * <pre>

     *      Formula:

     *      G = Gs*Er/((Er+h>-1)^2)

     *      G - Gravity

     *      Gs - Free-falling acceleration 9.81 m/c²

     *      Er - Earth radius 6371000 m

     *      h - Height

     *      >-1 This is a indicator of h small of 0 thr PhysicsOutOfRange(...)

     * </pre>

     * @param height Height (m)

     * @return Free Falling Acceleration (m/c²)

     * @throws PhysicsOutOfRange If height is negative, air density is uncorrect calculated and physics is breaked.

     */

    public static double gravityAtHeight(double height) throws PhysicsOutOfRange {

        if (height < 0) throw new PhysicsOutOfRange("Height: " + height + " is negative. Graivty force match not calculate!");

        return GRAVITY * Math.pow(EARTH_RADIUS / (EARTH_RADIUS + height), 2);

    }

   

    /**

     * Calculate falling speed of object with air density

     * <pre>

     *      Formula:

     *      Fa = sqrt((2*m*G)/(Ad*Dc*a))*(1 - exp(-G*t/sqrt((2*m*G)/(Ad*Dc*a)))) small of C

     *      Fa - Falling acceleration

     *      m - Mass

     *      G - Gravity

     *      Ad - Air density

     *      Dc - Drag coeficient

     *      a - Cross-Sectional area

     *      C - Speed of light 299792458 m/s

     * </pre>

     * @param time Falling time seconds

     * @param dragCoef Density coeficient

     * @param area Cross-Sectional area (m²)

     * @param mass Object mass (kg)

     * @param height Falling height meters

     * @return Vector1D with x is a falling speed (m/s)

     * @throws lmtech.javaphysics.PhysicsOutOfRange If height is negative

     */

    public static Vector1D calcFreeFallWithDrag(double time, double dragCoef, double area, double mass, double height) throws PhysicsOutOfRange {

        double termVel = Math.sqrt((2 * mass * gravityAtHeight(height)) / (airDensityAtHeight(height) * dragCoef * area));

        double temp = termVel * (1 - Math.exp(-gravityAtHeight(height) * time / termVel));

        if (temp > C) {

            temp = C;

        }

        return new Vector1D(temp);

    }

   

    /**

     * Advanced version of {@link #calcProjectileMotionWithDrag(double, double, double, double, double, double, double, double) } with advanced aero-braking algoritm

     * @param vel Object velocity (m/s)

     * @param angle Angle of attack (deg)

     * @param mass Object mass (kg)

     * @param lC Lift force

     * @param dC Drag force

     * @param area Cross-Sectional area (m²)

     * @param timeStep Time for one motion

     * @param totalTime Time for object motion

     * @param flatPos Position of ground

     * @return Vector2D with object stop position

     * @throws lmtech.javaphysics.PhysicsOutOfRange If y is negative

     */

    public static Vector2D calcProjectileMotionAero(double vel, double angle, double mass, double lC, double dC, double area, double timeStep, double totalTime, double flatPos) throws PhysicsOutOfRange {

        if (vel > C) return new Vector2D(0, 0);

        angle = normalizeAngle(angle);

        double vx = vel * Math.cos(Math.toRadians(angle));

        double vy = vel * Math.sin(Math.toRadians(angle));

        double x = 0, y = 0;

       

        for (double t = 0; t < totalTime; t += timeStep) {

            double speed = Math.sqrt(vx * vx + vy * vy);

            Vector2D aF = calcAerodynamicForces(speed, y, angle, area, lC, dC);

            double ax = (-aF.getX() / mass) * Math.cos(Math.toRadians(angle));

            double ay = (-aF.getY() / mass) * Math.sin(Math.toRadians(angle)) - gravityAtHeight(y) + (aF.getX() / mass);

           

            vx += ax * timeStep;

            vy += ay * timeStep;

            x += vx * timeStep;

            y += vy * timeStep;

           

            if (y <= flatPos) break; // Object has hit the ground

        }

        return new Vector2D(x, y);

    }

   

    /**

     * Calculate projectile motion with air density and gravity

     * @param velocity Velocity of object (m/s)

     * @param angle Angle of object (deg)

     * @param mass Object mass (kg)

     * @param dragCoef Drag coeficient

     * @param area Cross-Sectional area (m²)

     * @param timeStep Value to calculate object falling

     * @param totalTime Value to stop algoritm if t >= totalTime

     * @param flatPos Pos to stop algoritm

     * @return Returns two-direct vector ({@link Vector2D}) with object x, y coordinates

     * @throws lmtech.javaphysics.PhysicsOutOfRange TEST

     */

    public static Vector2D calcProjectileMotionWithDrag(

            double velocity, double angle, double mass, double dragCoef, double area, double timeStep, double totalTime, double flatPos) throws PhysicsOutOfRange {

        if (velocity > C) return new Vector2D(0, 0);

        angle = normalizeAngle(angle);

        double vx = velocity * Math.cos(Math.toRadians(angle));

        double vy = velocity * Math.sin(Math.toRadians(angle));

        double x = 0, y = 0;

       

        ForkJoinPool optimize = new ForkJoinPool();

        return optimize.invoke(new ProjTask(vx, vy, x, y, timeStep, totalTime, flatPos, dragCoef, area, mass));

    }

   

    /**

     * Calculate projectile motion from change mass (example, rocket)

     * @param velocity Object speed (m)

     * @param mass0 Object mass (kg)

     * @param massLossRate Mass lost rate

     * @param timeStep Time for 1-st operation (s)

     * @param totalTime Falling time (s)

     * @param flatPos If object 'y' coordinate equals of smallest for flatPos, algoritm stop and return coords

     * @param height Height of object to calculate gravity and air density

     * @return Coords of object

     * @throws lmtech.javaphysics.PhysicsOutOfRange TEST

     */

    public static Vector3D calcMotionWithMassChange(

        Vector3D velocity, double mass0, double massLossRate, double timeStep, double totalTime, double flatPos, double height) throws PhysicsOutOfRange {

        if (velocity.x > C || velocity.y > C || velocity.z > C) return new Vector3D(0, 0, 0);


 

        Vector3D pos = new Vector3D(0, 0, 0);

        Vector3D gravity = new Vector3D(0, 0, -gravityAtHeight(height));

   

        double mass = mass0;


 

        ForkJoinPool forkJoinPool = new ForkJoinPool();

        return forkJoinPool.invoke(new MassChangeTask(velocity, pos, gravity, mass, massLossRate, timeStep, totalTime, flatPos));

    }

   

    /**

     * Calculate 3D motion with drag

     * @param velocity Velocity

     * @param mass0 Mass

     * @param dragCoef Drag coeficient

     * @param area Cross-Sectional Area

     * @param timeStep Time for one operation

     * @param totalTime Total calculations time

     * @param flatPos Position of the ground

     * @param height Height of object

     * @return Vector3D with end coordinates

     * @throws PhysicsOutOfRange TEST

     */

    public static Vector3D calc3DMotionWithDrag(Vector3D velocity, double mass0, double dragCoef, double area, double timeStep, double totalTime, double flatPos, double height) throws PhysicsOutOfRange {

        if (velocity.x > C || velocity.y > C || velocity.z > C) return new Vector3D(0, 0, 0);

   

        Vector3D pos = new Vector3D(0, 0, 0);

        Vector3D gravity = new Vector3D(0, 0, -gravityAtHeight(height));

       

        ForkJoinPool forkJoinPool = new ForkJoinPool();

        return forkJoinPool.invoke(new MotionWithDragTask(velocity, pos, gravity, mass0, dragCoef, area, timeStep, totalTime, flatPos));

    }

   

    /**

     * Calculate relativistic effect of time diliation

     * @param velocity Object speed (m/s)

     * @return Time diliation coeficient

     */

    public static double calculateRelativisticTimeDilation(double velocity) {

        if (velocity > C) return 1 / Math.sqrt(1 - (C * C) / (C * C));

        return 1 / Math.sqrt(1 - (velocity * velocity) / (C * C));

    }

   

    /**

     * Calculate 4D motion with drag

     * @param velocity Velocity

     * @param mass0 Mass

     * @param dragCoefficient Drag coeficient

     * @param area Cross-Sectional Area

     * @param timeStep Time for one operation

     * @param totalTime Total calculations time

     * @param flatPos Position of the ground

     * @param height Height of object

     * @return Vector3D with end coordinates

     * @throws PhysicsOutOfRange TEST

     */

    public static Vector4D calculate4DMotion(

            Vector4D velocity, double mass0, double dragCoefficient, double area, double timeStep, double totalTime, double flatPos, double height) throws PhysicsOutOfRange {

        if (velocity.x > C || velocity.y > C || velocity.z > C || velocity.w > C) return new Vector4D(0, 0, 0, 0);

        Vector4D position = new Vector4D(0, 0, 0, 0);

        Vector4D gravity = new Vector4D(0, 0, -gravityAtHeight(height), 0);


 

        for (double t = 0; t < totalTime; t += timeStep) {

            double speed = Math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y + velocity.z * velocity.z + velocity.w * velocity.w);

            double dragForce = 0.5 * dragCoefficient * airDensityAtHeight(position.y) * area * speed * speed;

            double mass = mass0 * (1 / calculateRelativisticTimeDilation(speed));


 

            Vector4D acceleration = new Vector4D(

                -dragForce * (velocity.x / speed) / mass,

                -dragForce * (velocity.y / speed) / mass,

                gravity.z - (dragForce * (velocity.z / speed) / mass),

                -dragForce * (velocity.w / speed) / mass // W-coordinate density motion

            );


 

            velocity.x += acceleration.x * timeStep;

            velocity.y += acceleration.y * timeStep;

            velocity.z += acceleration.z * timeStep;

            velocity.w += acceleration.w * timeStep;

           

            position.x += velocity.x * timeStep;

            position.y += velocity.y * timeStep;

            position.z += velocity.z * timeStep;

            position.w += velocity.w * timeStep;

           

            if (position.z <= flatPos) break;

        }


 

        return position;

    }

   

    /* ----------------------------------- Collision segment ----------------------------------- */

    /**

     * Check collision with 1D objects

     * @param v Object velocity

     * @param m Object mass

     * @param dC Drag coefficient

     * @param a Cross-Sectional area

     * @param tS Time step

     * @param tT Total time

     * @param sP Stop position

     * @return Vector1D with collision coords

     * @throws PhysicsOutOfRange If airDensity detect negative height

     */

    public static Vector1D calcCollision1D(double v, double m, double dC, double a, double tS, double tT, double sP) throws PhysicsOutOfRange {

        Vector1D pos = new Vector1D(0);

        double vx = v;

       

        for (double t = 0; t < tT; t += tS) {

            double dF = calculateDragForce(vx, dC, a, pos.getX());

            double ac = -dF / m;

            vx += ac * tS;

            pos.x += vx * tS;

           

            if (pos.getX() <= sP) return pos;

        }

       

        return pos;

    }

   

    /**

     * Check collision with 2D objects

     * @param v Object velocity

     * @param angle Angle

     * @param m Object mass

     * @param dC Drag coefficient

     * @param a Cross-Sectional area

     * @param tS Time step

     * @param tT Total time

     * @param sP Stop position

     * @return Vector1D with collision coords

     * @throws PhysicsOutOfRange If airDensity detect negative height

     */

    public static Vector2D calcCollision2D(double v, double angle, double m, double dC, double a, double tS, double tT, double sP) throws PhysicsOutOfRange {

        double vx = v * Math.cos(Math.toRadians(angle));

        double vy = v * Math.sin(Math.toRadians(angle));

        double x = 0, y = 0;

       

        for (double t = 0; t < tT; t += tS) {

            double dF = calculateDragForce(vx, dC, a, y);

            double aX = -dF * (vx / Math.sqrt(vx * vx + vy * vy)) / m;

            double aY = -gravityAtHeight(y) - (dF * (vy / Math.sqrt(vx * vx + vy * vy)) / m);

           

            vx += aX * tS;

            vy += aY * tS;

            x += vx * tS;

            y += vy * tS;

           

            if (y <= sP) return new Vector2D(x, y);

        }

        return new Vector2D(x, y);

    }

   

    /**

     * Check collision in 3D

     * @param velocity Velocity

     * @param angleX Angle in X

     * @param angleY Angle in Y

     * @param mass Mass

     * @param dragCoefficient Drag coefficient

     * @param area Cross-Sectional area

     * @param timeStep Time for one operation

     * @param totalTime Total time of calculations

     * @param stopPosition Ground position

     * @return Vector3D with end coordinates of object

     * @throws PhysicsOutOfRange TEST

     */

    public static Vector3D calcCollision3D(double velocity, double angleX, double angleY, double mass, double dragCoefficient, double area, double timeStep, double totalTime, double stopPosition) throws PhysicsOutOfRange {

        double vx = velocity * Math.cos(Math.toRadians(angleX)) * Math.cos(Math.toRadians(angleY));

        double vy = velocity * Math.sin(Math.toRadians(angleX)) * Math.cos(Math.toRadians(angleY));

        double vz = velocity * Math.sin(Math.toRadians(angleY));

        double x = 0, y = 0, z = 0;

       

        for (double t = 0; t < totalTime; t += timeStep) {

            double dF = calculateDragForce(vx, dragCoefficient, area, z);

            double ax = -dF * (vx / Math.sqrt(vx * vx + vy * vy + vz * vz)) / mass;

            double ay = -gravityAtHeight(z) - (dF * (vy / Math.sqrt(vx * vx + vy * vy + vz * vz)) / mass);

            double az = -dF * (vz / Math.sqrt(vx * vx + vy * vy + vz * vz)) / mass;

           

            vx += ax * timeStep;

            vy += ay * timeStep;

            vz += az * timeStep;

            x += vx * timeStep;

            y += vy * timeStep;

            z += vz * timeStep;

           

            if (z <= stopPosition) return new Vector3D(x, y, z);

        }

        return new Vector3D(x, y, z);

    }

   

    /**

     * Check collision in 4D

     * @param velocity Velocity

     * @param angleX Angle in X

     * @param angleY Angle in Y

     * @param angleZ Angle in Z

     * @param mass Mass

     * @param dragCoefficient Drag coefficient

     * @param area Cross-Sectional area

     * @param timeStep Time for one operation

     * @param totalTime Total time of calculations

     * @param stopPosition Ground position

     * @return Vector4D with end coordinates of object

     * @throws PhysicsOutOfRange TEST

     */

    public static Vector4D calcCollision4D(double velocity, double angleX, double angleY, double angleZ, double mass, double dragCoefficient, double area, double timeStep, double totalTime, double stopPosition) throws PhysicsOutOfRange {

        double vx = velocity * Math.cos(Math.toRadians(angleX)) * Math.cos(Math.toRadians(angleY)) * Math.cos(Math.toRadians(angleZ));

        double vy = velocity * Math.sin(Math.toRadians(angleX)) * Math.cos(Math.toRadians(angleY)) * Math.cos(Math.toRadians(angleZ));

        double vz = velocity * Math.sin(Math.toRadians(angleY)) * Math.cos(Math.toRadians(angleZ));

        double vw = velocity * Math.sin(Math.toRadians(angleZ));

        double x = 0, y = 0, z = 0, w = 0;

   

        for (double t = 0; t < totalTime; t += timeStep) {

            double dragForce = calculateDragForce(vx, dragCoefficient, area, z);

            double ax = -dragForce * (vx / Math.sqrt(vx * vx + vy * vy + vz * vz + vw * vw)) / mass;

            double ay = -gravityAtHeight(z) - (dragForce * (vy / Math.sqrt(vx * vx + vy * vy + vz * vz + vw * vw)) / mass);

            double az = -dragForce * (vz / Math.sqrt(vx * vx + vy * vy + vz * vz + vw * vw)) / mass;

            double aw = -dragForce * (vw / Math.sqrt(vx * vx + vy * vy + vz * vz + vw * vw)) / mass;

       

            vx += ax * timeStep;

            vy += ay * timeStep;

            vz += az * timeStep;

            vw += aw * timeStep;

            x += vx * timeStep;

            y += vy * timeStep;

            z += vz * timeStep;

            w += vw * timeStep;

       

            if (z <= stopPosition) {

                return new Vector4D(x, y, z, w);

            }

        }

        return new Vector4D(x, y, z, w);

    }


 

    static class ProjTask extends RecursiveTask<Vector2D> {

        private double vx, vy, x, y, timeStep, totalTime, flatPos, dragCoef, area, mass;

       

        public ProjTask(double vx, double vy, double x, double y, double timeStep, double totalTime, double flatPos, double dragCoef, double area, double mass) {

            this.vx = vx;

            this.vy = vy;

            this.x = x;

            this.y = y;

            this.timeStep = timeStep;

            this.totalTime = totalTime;

            this.flatPos = flatPos;

            this.dragCoef = dragCoef;

            this.area = area;

            this.mass = mass;

        }

       

        @Override

        protected Vector2D compute() {

            try {

            for (double t = 0; t < totalTime; t += timeStep) {

                double speed = Math.sqrt(vx * vx + vy * vy);

                double dragF = 0.5 * dragCoef * airDensityAtHeight(y) * area * speed * speed;

                double ax = -dragF * (vx / speed) / mass;

                double ay = -gravityAtHeight(y) - (dragF * (vy / speed) / mass);


 

                vx += ax * timeStep;

                vy += ay * timeStep;

                x += vx * timeStep;

                y += vy * timeStep;


 

                if (y <= flatPos) break; // Object falled and collided with flat

            }

            return new Vector2D(x, y);

            } catch (PhysicsOutOfRange e) {

            }

           

            return new Vector2D(0, 0);

        }

    }

   

    static class MassChangeTask extends RecursiveTask<Vector3D> {

        private Vector3D velocity, pos, gravity;

        private double mass, massLossRate, timeStep, totalTime, flatPos;


 

        public MassChangeTask(Vector3D velocity, Vector3D pos, Vector3D gravity, double mass, double massLossRate, double timeStep, double totalTime, double flatPos) {

            this.velocity = velocity;

            this.pos = pos;

            this.gravity = gravity;

            this.mass = mass;

            this.massLossRate = massLossRate;

            this.timeStep = timeStep;

            this.totalTime = totalTime;

            this.flatPos = flatPos;

        }


 

        @Override

        protected Vector3D compute() {

            try {

            for (double t = 0; t < totalTime; t += timeStep) {

                if (mass <= 0) break;


 

                double speed = Math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y + velocity.z * velocity.z);

                double dragF = 0.5 * airDensityAtHeight(pos.y) * speed * speed;


 

                Vector3D acc1 = new Vector3D(

                    -dragF * (velocity.x / speed) / mass,

                    -dragF * (velocity.y / speed) / mass,

                    gravity.z - (dragF * (velocity.z / speed) / mass)

                );


 

                Vector3D velMid = new Vector3D(

                    velocity.x + acc1.x * (timeStep / 2),

                    velocity.y + acc1.y * (timeStep / 2),

                    velocity.z + acc1.z * (timeStep / 2)

                );


 

                Vector3D acc2 = new Vector3D(

                    -dragF * (velMid.x / speed) / mass,

                    -dragF * (velMid.y / speed) / mass,

                    gravity.z - (dragF * (velMid.z / speed) / mass)

                );


 

                velocity.x += acc2.x * timeStep + velocity.x * (massLossRate / mass) * timeStep;

                velocity.y += acc2.y * timeStep + velocity.y * (massLossRate / mass) * timeStep;

                velocity.z += acc2.z * timeStep + velocity.z * (massLossRate / mass) * timeStep;


 

                pos.x += velocity.x * timeStep;

                pos.y += velocity.y * timeStep;

                pos.z += velocity.z * timeStep;


 

                mass -= massLossRate * timeStep;


 

                if (pos.z <= flatPos) break;

            }


 

            return pos;

            } catch (PhysicsOutOfRange e) {

                e.printStackTrace();

            }

           

            return new Vector3D(0, 0, 0);

        }

    }

   

    static class MotionWithDragTask extends RecursiveTask<Vector3D> {

        private Vector3D velocity, pos, gravity;

        private double mass0, dragCoef, area, timeStep, totalTime, flatPos;


 

        public MotionWithDragTask(Vector3D velocity, Vector3D pos, Vector3D gravity, double mass0, double dragCoef, double area, double timeStep, double totalTime, double flatPos) {

            this.velocity = velocity;

            this.pos = pos;

            this.gravity = gravity;

            this.mass0 = mass0;

            this.dragCoef = dragCoef;

            this.area = area;

            this.timeStep = timeStep;

            this.totalTime = totalTime;

            this.flatPos = flatPos;

        }


 

        @Override

        protected Vector3D compute() {

            try {

                for (double t = 0; t < totalTime; t += timeStep) {

                    double speed = Math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y + velocity.z * velocity.z);

                    double dragF = 0.5 * dragCoef * airDensityAtHeight(pos.y) * area * speed * speed;

                    double mass = mass0 * (1 / calculateRelativisticTimeDilation(speed));


 

                    Vector3D acc1 = new Vector3D(

                        -dragF * (velocity.x / speed) / mass,

                        -dragF * (velocity.y / speed) / mass,

                        gravity.z - (dragF * (velocity.z / speed) / mass)

                    );


 

                    Vector3D velMid = new Vector3D(

                        velocity.x + acc1.x * (timeStep / 2),

                        velocity.y + acc1.y * (timeStep / 2),

                        velocity.z + acc1.z * (timeStep / 2)

                    );


 

                    Vector3D acc2 = new Vector3D(

                        -dragF * (velMid.x / speed) / mass,

                        -dragF * (velMid.y / speed) / mass,

                        gravity.z - (dragF * (velMid.z / speed) / mass)

                    );


 

                    velocity.x += acc2.x * timeStep;

                    velocity.y += acc2.y * timeStep;

                    velocity.z += acc2.z * timeStep;

                    pos.x += velocity.x * timeStep;

                    pos.y += velocity.y * timeStep;

                    pos.z += velocity.z * timeStep;

               

                    if (pos.z <= flatPos) break;

                }


 

                return pos;

            } catch (PhysicsOutOfRange e) {

                e.printStackTrace();

            }

           

            return new Vector3D(0, 0, 0);

        }

    }

}


 

0 комментариев
Сортировка:
Добавить комментарий

IT Новости

Смотреть все