Вот пример (см. Изображение): -
- 2 красноватых прямоугольника являются статическими объектами (т.е. он не может двигаться).
- Голубоватый шар - это динамический объект.
Пока мне удается получить всю проникающую информацию.Давайте рассмотрим это как наш ввод: -
- Чтобы разрешить проникновение между
A
и мячом, я могу переместить шар либо на Vec3(1,0,0)
ИЛИ Vec3(0,2,0)
. - Чтобы разрешить проникновение между
B
и мячом, я могу переместить мяч на Vec3(0,1,0)
.
^ Я сохраняю его как двумерный массив Vec3 problem = {{Vec3{1,0,0},Vec3{0,2,0}},{Vec3{0,1,0}}}
.
Как найти наилучшее движение (минимальный размер) физического объекта (например, шара)в примере), чтобы минимизировать как можно большее проникновение?
Лучшее решение в этом примере - «переместить шар на Vec3(1,1,0)
: размер = 1,414».
В реальном случае ситуация может быть более сложной и безобразной,
например, возможно, что и A & B (и другиеФизика объекта) попробуйте толкнуть мяч в почти противоположном направлении.(изображения ниже)
^ В некоторых сценах двумерный массив problem
может не обладать некоторыми деталями, но для простоты, давайте представим, что это объясняет всю информацию точно.
C ++ Код
Вот мой MCVE (coliru) : -
#include<iostream>
#include <utility>
#include <vector>
#include <array>
#include <math.h>
using Vec3=std::array<float, 3>;
float dotProduct(Vec3 vec1,Vec3 vec2){
return vec1[0]*vec2[0]+vec1[1]*vec2[1]+vec1[2]*vec2[2];
}
float size2(Vec3 vec1){
return vec1[0]*vec1[0]+vec1[1]*vec1[1]+vec1[2]*vec1[2];
}
Vec3 mulFloat(Vec3 vec1,float m){
return Vec3{vec1[0]*m,vec1[1]*m,vec1[2]*m};
}
Vec3 normalize(Vec3 vec1){
return mulFloat(vec1,1/sqrt(size2(vec1)));
}
Вот main()
: -
int main() {
std::vector<std::vector<Vec3>> problem;
std::vector<Vec3> location1;
location1.push_back(Vec3{0,2,0});
location1.push_back(Vec3{1,0,0});
problem.push_back(location1);
std::vector<Vec3> location2;
location2.push_back(Vec3{0,1,0});
problem.push_back(location2);
//^ INPUT
//----- insert YOUR ALGORITHM here ------
Vec3 solution=Vec3{0,2,0};
float totalResidual=0;
for(auto& location : problem){
float residualRemainMin=1000000;//numerical limit
for(auto& orgResidual : location){
Vec3 orgResidualNormalize=normalize(orgResidual);
float orgResidualSize=sqrt(size2(orgResidual));
float residualModifyBy=-dotProduct(orgResidualNormalize,solution);//#1
//"residualModifyBy" is usually negative
float remainResidual=std::max(0.0f,orgResidualSize+residualModifyBy);
//^ "max" because it has no advantage to reduce residual to < 0
residualRemainMin=std::min(residualRemainMin,remainResidual);
//^ "min" because the "OR" word
}
totalResidual+=residualRemainMin;
}
std::cout<<"totalResidual="<<totalResidual;
return 0;
}
Примечание (#1)
в коде: остаток уменьшается на dotProduct(solution,normalize(orgResidual) )
.
Мой вывод этой формулы происходит из этого изображения: -
Примечание:
Я чувствую, что будет слишком медленно переставлять каждую комбинацию (что я точно не знаю, как).
Iтакже считаю, что общий итерационный подход слишком медленный, чтобы сходиться.
Мне просто нужна инструкция;Я не возражаю против ответа без кода.
Редактировать (29 июня 2019 г.)
Больше тестов: -
{{(0,3,0)},{(2,2,0)}} ===> (1,3,0)
{{(0,1,1),(10,0,0)},{(0,2,3)}} ===> (0,2,3)
{{(99,1,0),(99,-1,0),(100,0,0)}} ===> (99,1,0) OR (99,-1,0) (equally good)