计算分隔两条线的最小平移量
Calculating the minimum translation to seperate two lines
给定R2中两个相交的线段(AB和CD),求作用于CD的平移量最小,使其不再与AB相交
我已经试过了。我计算每条线上每一点到另一条线上的距离。然后从4个值中选取最小的值并将其应用于直线的垂线。然而,我计算的翻译往往是错误的方向。我该如何解决这个问题?
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iterator>
class Vector2
{
public:
double x;
double y;
Vector2() : x(x), y(y) {}
Vector2(double x, double y) : x(x), y(y) {}
Vector2 operator*(double val) { return Vector2(x*val, y*val);}
Vector2 operator/(double val) { return Vector2(x/val, y/val);}
Vector2 operator+(Vector2 &v) { return Vector2(x+v.x, y+v.y);}
Vector2 operator-(Vector2 &v) { return Vector2(x-v.x, y-v.y);}
Vector2 Perpendicular() { return Vector2(y, -x); }
double Dot( Vector2 &v) {return (x * v.x) + (y * v.y); }
double Magnitude() { return std::sqrt(Dot(*this)); }
Vector2 Normal() { return *this / Magnitude(); }
double GetDistance( Vector2 &v) { Vector2 d = *this - v; return d.Magnitude(); }
};
class Line
{
public:
Line() : a(Vector2()), b(Vector2()) {}
Line( Vector2 a, Vector2 b) : a(a), b(b) {};
double DistanceFromPoint( Vector2 &p) ;
Vector2 GetTranslation( Line &l) ;
Vector2& GetPoint(unsigned i) {if (i==0) return a; else return b;}
double GetLength() { return GetPoint(0).GetDistance(GetPoint(1)); }
Vector2 a;
Vector2 b;
};
double Line::DistanceFromPoint( Vector2 &p)
{
double l2 = GetLength() * GetLength();
Vector2 pv = p - GetPoint(0);
Vector2 wv = GetPoint(1) - GetPoint(0);
double t = std::max(0.d, std::min(1.d, pv.Dot(wv) / l2));
Vector2 projection = (wv * t) + GetPoint(0);
return p.GetDistance(projection);
}
Vector2 Line::GetTranslation( Line &l)
{
// Calculate Distances from each point to rthe opposite line
std::vector<double> dist(4);
dist[0] = DistanceFromPoint(l.GetPoint(0));
dist[1] = DistanceFromPoint(l.GetPoint(1));
dist[2] = l.DistanceFromPoint(GetPoint(0));
dist[3] = l.DistanceFromPoint(GetPoint(1));
//Get the smallest distance
auto it = std::min_element(std::begin(dist), std::end(dist));
double min = *it;
unsigned pos = std::distance(std::begin(dist), it);
// Get the normalized perpendicular of line
Vector2 axis;
if (pos == 2 || pos == 3)
axis = (GetPoint(1) - GetPoint(0)).Perpendicular().Normal();
else
axis = (l.GetPoint(1) - l.GetPoint(0)).Perpendicular().Normal();
std::cout << "min: " << min << std::endl;
std::cout << "axis: (" << axis.x << "," << axis.y << ")" << std::endl;
//Apply that min to the perpendicular
return axis * min;
}
int main()
{
Line A;
Line B;
Vector2 t;
std::cout << "Left" << std::endl;
A = Line(Vector2(0, 4), Vector2(8, 4));
B = Line(Vector2(2, 0), Vector2(2, 6));
t = A.GetTranslation(B);
std::cout << "Expected: (-2, 0)" << std::endl;
std::cout << "Got: (" << t.x << "," << t.y << ")" << std::endl << std::endl;
std::cout << "Right" << std::endl;
B = Line(Vector2(6, 0), Vector2(6, 6));
t = A.GetTranslation(B);
std::cout << "Expected: (2, 0)" << std::endl;
std::cout << "translation: (" << t.x << "," << t.y << ")" << std::endl << std::endl;
std::cout << "Top" << std::endl;
B = Line(Vector2(4, 0), Vector2(4, 6));
t = A.GetTranslation(B);
std::cout << "Expected: (0, -2)" << std::endl;
std::cout << "translation: (" << t.x << "," << t.y << ")" << std::endl << std::endl;
std::cout << "Bottom" << std::endl;
B = Line(Vector2(4, 6), Vector2(4, 8));
t = A.GetTranslation(B);
std::cout << "Expected: (0, -2)" << std::endl;
std::cout << "translation: (" << t.x << "," << t.y << ")" << std::endl;
}
你的想法会成功的。你只需要有一个像@Tommy提到的带符号距离函数。此外,请注意,您还必须使正确垂直方向,这取决于距离函数中的符号约定。
这是一个演示
您的方法是正确的。根据Minkowski和的推理,最短的分离向量将垂直于其中一条线,并且长度足以将其中一个端点推到另一条线的表面。
但是你的DistanceFromPoint
返回一个无符号距离:它总是零或正。然后用一条垂线乘以它。所以你最终会有50%的时间走错路,因为你的距离没有符号。
你可能更喜欢重新排列,尤其是因为它可以节省一些平方根:
- 得到两个轴;
- 对于每条线,从该线上的任何点到另一条线的每个端点的向量投影到该线的轴上。
- 按量级选取最短的结果;
- 将分离轴计算为最短次数的负数乘以计算轴。
…因为如果你沿着q
轴被n
单元嵌入那么解决这个问题的方法就是沿着q
移动-n
单元;所以选择最小的n
相关文章:
- 我不知道这条线是做什么的
- 在两个线程上读/写 64 位,无互斥/锁定/原子
- 如果两个线程相互依赖,则 cpp 线程连接应使用连接导致死锁
- 向量:两条线,需要解释
- 一条线和两行声明之间的差异
- C++ OpenCV:检测两条线而不是一条线(Canny & findContours)
- 如果用像素来给出两条线(外部和内部)之间的边缘(外部和内部)之间的边缘,则如何计算(x,y)坐标
- CSV文件中的两条线的交点的计算返回-1.#IND
- 仅使用整数计算两条线的交点
- 两条线之间的Arduino距离
- 这两条线有什么不同吗
- OpenGL:在两个元素之间画一条线
- 使用增强几何体检查两条线是否有交点
- 查找表示 GPS 路线的两条线(MATLAB、Java、C++ 或 Python)之间的距离
- 为什么这两条线会产生不同的溢出行为
- 将一条线从两个点延伸到一定长度
- 这是检验两条线是否共线的正确方法吗?
- 计算分隔两条线的最小平移量
- 如果我有一条从点x1,y1到x2,y2的线,我怎么能画出两条从点x2,y2成45度角的线来画箭头呢
- 找出两条线是否相交