Точка в 3d пространство, приближаваща се до самолети в 3d пространство без причина

Java, програма, имам клас Point3d с координати x,y,z и следната средна функция:

public static Point3d average(Point3d a, Point3d b){
    a.add(b);
    a.x/=2;
    a.y/=2;
    a.z/=2;
    return a;
}

Имам и този клас за 2dPlane в 3d пространство, образувано от триъгълник между 3 3d точки:

package com.funguscow.model;

import com.funguscow.obj.Point3d;
import com.funguscow.obj.Vector3d;

public class TriPlane {

    public Point3d a, b, c;
    private Vector3d normal;
    private float d;

    public TriPlane(Point3d x, Point3d y, Point3d z){
        a = x;
        b = y;
        c = z;
        Vector3d ab = Vector3d.Vector3dPMinus(a, b);
        //System.out.println(ab.x + ", " + ab.y + ", " + ab.z);
        normal = Vector3d.crossProduct(
                Vector3d.Vector3dPMinus(a, b),
                Vector3d.Vector3dPMinus(a, c));
        d = Vector3d.dotProduct(normal, Vector3d.VectorFromPoint3d(a));
    }

    public Vector3d getNormal(){
        return normal;
    }

    public float getRelativeOnPlane(Point3d test){
        //System.out.println(normal.x + ", " + normal.y + ", " + normal.z);
        return Vector3d.dotProduct(normal, Vector3d.VectorFromPoint3d(test)) - d;
    }

}

getRelativeOnPlane е да намерите от коя страна на равнината е определена точка. Изглежда ли, че трябва да работи за вас? Виждате ли някакви проблеми с него?

Както и да е, тук е големият проблем, имам следния клас за CubeCollider, разширяващ абстрактния клас Collider, който настройва шест TriPlanes, за да провери дали дадена точка е в рамките на куба или не:

package com.funguscow.model;

import com.funguscow.obj.Point3d;
import com.funguscow.obj.Vector3d;

public class CubeCollider extends Collider{
    public Point3d a, b, c, d, e, f, g, h;

    public CubeCollider(){
        a = new Point3d(0, 0, 0);
        b = new Point3d(0, 0, 0);
        c = new Point3d(0, 0, 0);
        d = new Point3d(0, 0, 0);
        e = new Point3d(0, 0, 0);
        f = new Point3d(0, 0, 0);
        g = new Point3d(0, 0, 0);
        h = new Point3d(0, 0, 0);
    }

    public CubeCollider setCube(Cube cube){
        return setCube((float)cube.lines.get(0).start.x,
                (float)cube.lines.get(0).start.y, (float)cube.lines.get(0).start.z,
                (float)cube.lines.get(11).end.x, (float)cube.lines.get(11).end.y, (float)cube.lines.get(11).end.z);
    }

    public CubeCollider setCube(float x, float y, float z, float m, float n, float o){
        //System.out.println(x + ", " + y + ", " + z + ", " + m + ", " + n + ", " + o);
        a.x = b.x = c.x = d.x = x;
        e.x = f.x = g.x = h.x = m;
        a.y = c.y = e.y = g.y = y;
        b.y = d.y = f.y = h.y = n;
        a.z = b.z = e.z = f.z = z;
        c.z = d.z = g.z = h.z = o;
        return this;
    }

    public boolean shouldBother(Point3d p){
        Point3d center = Point3d.average(a, h);
        float dist = Vector3d.Vector3dPMinus(p, center).getMagnitude();
        if(dist > Vector3d.Vector3dPMinus(center, a).getMagnitude())return false;
        if(dist > Vector3d.Vector3dPMinus(center, d).getMagnitude())return false;
        if(dist > Vector3d.Vector3dPMinus(center, g).getMagnitude())return false;
        return true;
    }

    public boolean isInBounds(Point3d p){
        //System.out.println((a.x - b.x) + ", " + (a.y - b.y) + ", " + (a.z - b.z));
        TriPlane[] collider = new TriPlane[]{new TriPlane(a, b, c),
                new TriPlane(a, b, e),
                new TriPlane(e, f, g),
                new TriPlane(c, d, g),
                new TriPlane(a, c, e),
                new TriPlane(b, d, f)};
        Point3d center = Point3d.average(a, h);

        for(TriPlane plane : collider){
            float should = plane.getRelativeOnPlane(center);
            int sign = (should < 0) ? -1 : (should == 0) ? 0 : 1;
            float real = plane.getRelativeOnPlane(p);
            int rSign = (real < 0) ? -1 : (real == 0) ? 0 : 1;
            System.out.println("Center: " + center.x + ", " + center.y + ", " + center.z);
            System.out.println("Bound check: " + should + ", " + real);
            if(sign != rSign && real != 0 && should != 0)return false;
        }
        return true;
    }
}

Точката „център“ във функцията isInBounds използва средната стойност на точките a и h, но има някакъв проблем. Отстраняването на грешки като "Bound check: " от функцията isInBounds съобщава "трябва" (точковото произведение на нормалния вектор на равнината и центъра на точката), доближава нула, докато след няколко (десетки) повторения на проверката стане точно 0,0. Може ли някой да ми каже защо се случва това? Ако не греша, връщането на нула за функцията getRelativePointOnPlane трябва да означава, че точката е на равнината, но точката, която тества (център), ако не греша, трябва да е междувсички самолети, а ненаникоя от тях. Грешна ли е логиката ми за това как да използвам тези функции или греша в кодирането, което използвах, за да напиша функциите?

Ето какво прочете конзолата:

Center: 100.0, 100.0, 40.0
Bound check: -4000000.0, -1.2E7
Center: 100.0, 100.0, 40.0
Bound check: 4000000.0, 4800000.0
Center: 100.0, 100.0, 40.0
Bound check: 4000000.0, -4000000.0
Center: 50.0, 50.0, -10.0
Bound check: -2000000.0, -1000000.0
Center: 50.0, 50.0, -10.0
Bound check: 2000000.0, 5000000.0
Center: 50.0, 50.0, -10.0
Bound check: 2000000.0, -4000000.0
Center: 25.0, 25.0, -35.0
Bound check: -1000000.0, 5100000.0
Center: 12.5, 12.5, -47.5
Bound check: -500000.0, 8650000.0
Center: 6.25, 6.25, -53.75
Bound check: -250000.0, 1.0875E7
Center: 3.125, 3.125, -56.875
Bound check: -125000.0, 1.24125E7
Center: 1.5625, 1.5625, -58.4375
Bound check: -62500.0, 1.359375E7
Center: 0.78125, 0.78125, -59.21875
Bound check: -31250.0, 1.4590625E7
Center: 0.390625, 0.390625, -59.609375
Bound check: -15625.0, 1.5492187E7
Center: 0.1953125, 0.1953125, -59.8046875
Bound check: -7812.5, 1.6344532E7
Center: 0.09765625, 0.09765625, -59.90234375
Bound check: -3906.25, 1.7171484E7
Center: 0.048828125, 0.048828125, -59.951171875
Bound check: -1953.0, 1.7985352E7
Center: 0.0244140625, 0.0244140625, -59.9755859375
Bound check: -976.5, 1.879248E7
Center: 0.01220703125, 0.01220703125, -59.98779296875
Bound check: -488.25, 1.9596142E7
Center: 0.006103515625, 0.006103515625, -59.993896484375
Bound check: -244.25, 2.0398024E7
Center: 0.0030517578125, 0.0030517578125, -59.9969482421875
Bound check: -122.25, 2.1198986E7
Center: 0.00152587890625, 0.00152587890625, -59.99847412109375
Bound check: -61.0, 2.1999482E7
Center: 7.62939453125E-4, 7.62939453125E-4, -59.999237060546875
Bound check: -30.5, 2.2799734E7
Center: 3.814697265625E-4, 3.814697265625E-4, -59.99961853027344
Bound check: -15.25, 2.3599864E7
Center: 1.9073486328125E-4, 1.9073486328125E-4, -59.99980926513672
Bound check: -7.5, 2.439993E7
Center: 9.5367431640625E-5, 9.5367431640625E-5, -59.99990463256836
Bound check: -4.0, 2.5199964E7
Center: 4.76837158203125E-5, 4.76837158203125E-5, -59.99995231628418
Bound check: -2.0, 2.599998E7
Center: 2.384185791015625E-5, 2.384185791015625E-5, -59.99997615814209
Bound check: -1.0, 2.6799992E7
Center: 1.1920928955078125E-5, 1.1920928955078125E-5, -59.999988079071045
Bound check: -0.5, 2.7599994E7
Center: 5.9604644775390625E-6, 5.9604644775390625E-6, -59.99999403953552
Bound check: 0.0, 2.8399998E7
Center: 5.9604644775390625E-6, 5.9604644775390625E-6, -59.99999403953552
Bound check: 0.25, 2.4399998E7
Center: 5.9604644775390625E-6, 5.9604644775390625E-6, -59.99999403953552
Bound check: 0.23841858, -4000000.0
Center: 2.9802322387695312E-6, 2.9802322387695312E-6, -59.99999701976776
Bound check: 0.0, 2.92E7

person Yaakov Schectman    schedule 18.01.2015    source източник
comment
Това за всеки куб ли се случва или само за определени?   -  person rbennett485    schedule 18.01.2015
comment
Освен това какво имате предвид под итерации на проверката? Може би бихте могли да публикувате тестовия код, който използвате, и резултатите, тъй като нямаме необходимите класове, за да го тестваме сами   -  person rbennett485    schedule 18.01.2015
comment
Добавих System.out.println("Center: " + center.x + ", " + center.y + ", " + center.z); и ето какво прочете конзолата: Център: 100.0, 100.0, 40.0 Обвързана проверка: -4000000.0, -1.2E7 Център: 100.0, 100.0, 40.0 Обвързана проверка: 4000000.0, 4800000.0 Център: 100.0, 100.0, 40 .0 Обвързан чек : 4000000.0, -4000000.0 Център: 50.0, 50.0, -10.0 Обвързана проверка: -2000000.0, -1000000.0 Оттам нататък първата стойност на обвързаната проверка продължи да се доближава до 0.0. Не можах да публикувам повече от това в коментара.   -  person Yaakov Schectman    schedule 18.01.2015


Отговори (1)


Вашият average метод променя стойността на a, за да стане същата като средната точка. Така че вашият куб не е куб, след като сте извикали average - три от лицата са се завъртели в нови позиции. Така че каквото и да се случи в цикъла над collider е грешно.

person Dawood ibn Kareem    schedule 18.01.2015
comment
Благодаря! Добавих Point3d c = new Point3d(a.x, a.y, a.z); и промених a на c във всички следващи препратки в средната функция. Изглежда, че сега работи. - person Yaakov Schectman; 18.01.2015