Рассчитать 4 точки квадрата на основе 2 точек линии

1

Я не новичок в этом сайте, как я использовал его раньше, но я впервые задал вопрос: D

Во-первых, я использую ось Y как вверх, так и вниз.

Я пытаюсь вычислить 4 точки квадрата в трехмерном пространстве, перпендикулярном линии, образованной двумя заданными точками. Эта площадь должна быть:

  1. Перпендикулярно линии, заданной двумя заданными точками
  2. Толщина (или ширина/длина) 1
  3. выровнены так, что две стороны всегда перпендикулярны оси Y

Я пробовал кодировать это сам, и я несколько преуспел, но это не совсем то, что я хотел. Вот фрагмент кода, который у меня есть:

Примечание: Vert - это класс, который хранит координату в трех переменных x, y и z. FourVert - это класс, в котором хранятся 4 Verts, и конструктор - это то, что я пытаюсь разработать. Два параметра Vert - это заданные точки, а float t - толщина или разделение между выходными 4 точками. Add - это функция, которая добавляет заданное значение координаты Vert в качестве смещения ко всем 4 точкам FourVert. Это используется только для перестановки точек в нужном месте, первого Vert. У меня могут быть странные соглашения об именах, но я пишу их так, чтобы это понять.

EDIT: Добавлены комментарии в соответствии с запросами. (Каламбур не предназначен)

public FourVert(Vert V1, Vert V2, float t)
{
    float dx = V2.x - V1.x; //Position our points at the origin to convert into
    float dy = V2.y - V1.y; //polar coordinates using Math.atan2();
    float dz = V2.z - V1.z;
    float d = (float) Math.sqrt(dx*dx+dz*dz); //Get the lateral distance to use
    float axz = (float) -Math.atan2(dx, dz);  //in relation with the y value to
    float ady = (float) Math.atan2(d, dy);    //calculate the altitude angle
    float px = (float) (Math.cos(axz) * t);
    float py = (float) (Math.cos(ady + 1.570796327) * t); //add half PI
    float ny = (float) (Math.cos(ady - 1.570796327) * t);
    float pz = (float) (Math.sin(axz) * t);
    v1 = new Vert(px, py, pz);   //Use the calculated values to produce 4 points
    v2 = new Vert(-px, py, -pz); //v1, v2, v3, and v4 are our Vert fields of the
    v3 = new Vert(-px, ny, -pz); //FourVert class
    v4 = new Vert(px, ny, pz);
    add(V1); //take our FourVert back to where we want it, not on the origin.
}

У меня уже есть уход, и я знаю, что он работает хорошо, потому что я тестировал его с помощью givens.

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

Проблема/часть, которая не работает, здесь я думаю:

    float py = (float) (Math.cos(ady + 1.570796327) * t);
    float ny = (float) (Math.cos(ady - 1.570796327) * t);

Для меня это много тригонометрия, и я свожу с ума. Заранее спасибо.

Мой код может выглядеть неэффективным, но оптимизация приходит потом, мне нужно сначала запустить его, а затем я могу оптимизировать, что хочу.

  • 0
    Просто предложение, попробуйте немного прокомментировать ваш код, чтобы дать себе и другим понять, что вы делаете в определенной строке или разделе кода. Комментарий в 3-4 строки может быть полезен для такого рода кода.
  • 0
    @mrjoltcola Готово. :)
Показать ещё 1 комментарий
Теги:
line
geometry
point
trigonometry

1 ответ

0
Лучший ответ

Я бы избегал этой тригонометрии. Для одного из направлений кромки вам нужен вектор, который в то же время перпендикулярен V 1 - V 2 и оси Y. Перекрестное произведение может быть использовано для получения вектора, который перпендикулярен двум заданным. Итак, вы вычисляете это так:

[ 0 ]   [ x2 − x1 ]   [ z2 − z1 ]   [  dz ]
[ 1 ] × [ y2 - y1 ] = [    0    ] = [  0  ] = w₁
[ 0 ]   [ z2 - z1 ]   [ x1 − x2 ]   [ −dx ]

Для второго направления кромки вы хотите перпендикулярно первому, а также перпендикулярно V 1 - V 2. Итак, та же история:

[  dz ]   [ dx ]   [    dx*dy    ]    [ ex ]
[  0  ] × [ dy ] = [ − dx² − dz² ] =: [ ey ] = w₂
[ −dx ]   [ dz ]   [    dz*dy    ]    [ ez ]

Вам нужно будет нормализовать эти векторы, чтобы они имели длину 1, затем вы закончили. В. факт, что я нормализовал их до длины ½, потому что тогда вы можете использовать ± этот вектор для описания позиций, которые являются симметричными вокруг источника, как ваш собственный код также делает это. Для углов вам понадобится ± w 1 ± w 2, что дает четыре возможных знаковых комбинации.

public FourVert(Vert V1, Vert V2, float t)
{
    float dx = V2.x - V1.x;
    float dy = V2.y - V1.y;
    float dz = V2.z - V1.z;
    float ex = dx*dz;
    float ey = -dx*dx-dz*dz;
    float ez = dz*dy;
    float d = (float)(t/(2*Math.sqrt(dx*dx+dz*dz)));
    float e = (float)(t/(2*Math.sqrt(ex*ex+ey*ey+ez*ez)));
    dx *= d; dz *= d;
    ex *= e; ey *= e; ez *= e;
    v1 = new Vert( dz+ex,  ey, -dx+ez);
    v2 = new Vert( dz-ex, -ey, -dx-ez);
    v3 = new Vert(-dz-ex, -ey,  dx-ez);
    v4 = new Vert(-dz+ex,  ey,  dx+ez);
    add(V1);
}

Вероятно, вам это больше не понадобится, но ради полноты: вместо

float py = (float) (Math.cos(ady + 1.570796327) * t);
float ny = (float) (Math.cos(ady - 1.570796327) * t);

Я бы написал

float py = (float) (-Math.sin(ady) * t);
float ny = (float) ( Math.sin(ady) * t);

Это использует тот факт, что sin и cos отличаются фазой π/2.

  • 0
    Большое спасибо! Это работает почти идеально. Существует небольшая проблема, хотя при приближении к отрицательной стороне оси Y не горизонтальные стороны квадрата огибают при вращении вокруг оси Y. Они делают движение, как \ = \ | = | знак равно Я попытался исправить это, но это довольно неуловимо, я подозреваю, что это где-то в коде перевернутый знак (положительный / отрицательный), но я не уверен.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню