最近一直在写关于几何方面的代码。涉及到一些非常基础的计算。如在二维世界中,直线和直线的交点。之前一直没有太多优化这段代码。
直线表达:一般直线的表达为 A x + B y + C = 0 Ax+By+C=0 Ax+By+C=0
两个直线的表达:
A 1 x + B 1 y + C 1 = 0 A 2 x + B 2 y + C 2 = 0 A_1x+B_1y+C_1=0 \\ A_2x+B_2y+C_2=0 A1x+B1y+C1=0A2x+B2y+C2=0
一般情况下直接计算方程组即可。使用高斯消元法得到:
x = B 1 ∗ C 2 − B 2 ∗ C 1 A 1 ∗ B 2 − A 2 ∗ B 1 y = A 2 ∗ C 1 − A 1 ∗ C 2 A 1 ∗ B 2 − A 2 ∗ B 1 x = \frac{ B_1 * C_2 - B_2 * C_1}{A_1 * B_2 - A_2 * B_1} \\ y = \frac{ A_2 * C_1 - A_1 * C_2}{A_1 * B_2 - A_2 * B_1} x=A1∗B2−A2∗B1B1∗C2−B2∗C1y=A1∗B2−A2∗B1A2∗C1−A1∗C2
c++代码如下:
#include <iostream>
#include<Eigen/Eigen>
const double KMIN_DOUBLE_LINE_THRESHOLD = 1e-8;
bool ComputeLine2LineIntersection(const Eigen::Vector3d& f1, const Eigen::Vector3d& f2, Eigen::Vector2d& pnt)
{
double det = f1[0]*f2[1] - f2[0]*f1[1];
if(std::abs(det) < KMIN_DOUBLE_LINE_THRESHOLD)
{
return false;
}
else
{
double x = (f1[1]*f2[2] - f2[1]*f1[2]) / det;
double y = (f2[0]*f1[2] - f1[0]*f2[2]) / det;
pnt[0] = x;
pnt[1] = y;
return true;
}
}
int main(int argc, char** argv)
{
Eigen::Vector3d a(1,2,3);
Eigen::Vector3d b(4,5,6);
Eigen::Vector2d p;
ComputeLine2LineIntersection(a, b, p);
std::cerr <<"pnt: " << p.transpose() << std::endl;
return 0;
}
测试的结果(正确):
补充:如果线段的表达方式为:(用首位顶点表达方式)
l 1 : ( x 0 , y 0 ) − > ( x 1 , y 1 ) l_1: (x_0, y_0) -> (x_1,y_1) l1:(x0,y0)−>(x1,y1)
l 2 : ( x 2 , y 2 ) − > ( x 3 , y 3 ) l_2: (x_2, y_2) -> (x_3,y_3) l2:(x2,y2)−>(x3,y3)
需要转化到上面的通用表达方式表示为:
A = y 1 − y 0 B = x 0 − x 1 C = − ( A x 0 + B y 0 ) A = y_1-y_0 \\ B = x_0-x_1 \\ C =-( Ax_0+By_0) A=y1−y0B=x0−x1C=−(Ax0+By0)
转化函数如下:
//Ax+By+C=0(A,B,C)
Eigen::Vector3d ComputeFunctionFromPnts(const Eigen::Vector2d& s, const Eigen::Vector2d& e)
{
double A = e[1] - s[1];
double B = s[0] - e[0];
double C = -(A*s[0] + B*s[1]);
return Eigen::Vector3d(A,B,C);
}
融合到上面得到:
#include <iostream>
#include<Eigen/Eigen>
const double KMIN_DOUBLE_LINE_THRESHOLD = 1e-8;
bool ComputeLine2LineIntersection(const Eigen::Vector3d& f1, const Eigen::Vector3d& f2, Eigen::Vector2d& pnt)
{
double det = f1[0]*f2[1] - f2[0]*f1[1];
if(std::abs(det) < KMIN_DOUBLE_LINE_THRESHOLD)
{
return false;
}
else
{
double x = (f1[1]*f2[2] - f2[1]*f1[2]) / det;
double y = (f2[0]*f1[2] - f1[0]*f2[2]) / det;
pnt[0] = x;
pnt[1] = y;
return true;
}
}
//Ax+By+C=0(A,B,C)
Eigen::Vector3d ComputeFunctionFromPnts(const Eigen::Vector2d& s, const Eigen::Vector2d& e)
{
double A = e[1] - s[1];
double B = s[0] - e[0];
double C = -(A*s[0] + B*s[1]);
return Eigen::Vector3d(A,B,C);
}
int main(int argc, char** argv)
{
Eigen::Vector2d s0(0.0,0.0);
Eigen::Vector2d e0(1.0,1.0);
Eigen::Vector2d s1(1.0,0.0);
Eigen::Vector2d e1(0.0,1.0);
Eigen::Vector3d a = ComputeFunctionFromPnts(s0,e0);
Eigen::Vector3d b = ComputeFunctionFromPnts(s1,e1);
Eigen::Vector2d p;
ComputeLine2LineIntersection(a, b, p);
std::cerr <<"pnt: " << p.transpose() << std::endl;
return 0;
}
测试的结果(正确):