记录关于二维直线代码的时候遇到的一些常见的问题
直线表达方式有三种如下:
1)
a
x
+
b
y
+
c
=
0
(
1
)
ax+by+c=0 \space \space(1)
ax+by+c=0 (1) 这是代数表达方式,也是通用的表达方式,其中法向量为
s
=
(
−
b
,
a
)
s=(-b, a)
s=(−b,a)。
2)
y
=
k
x
+
b
y=kx+b
y=kx+b 这是点斜方式。它很好理解,但是它不能表达垂直于
x
x
x轴的直线。这个特例用
x
=
b
x=b
x=b 表示,会特殊处理。它也有一通用方式。就是点和方向表示法:
(
x
0
+
y
0
)
+
t
(
d
0
,
d
1
)
=
(
x
,
y
)
(
2
)
(x_0 + y_0) + t(d_0, d_1)=(x,y) \space\space (2)
(x0+y0)+t(d0,d1)=(x,y) (2), 其中
(
x
0
+
y
0
)
(x_0 + y_0)
(x0+y0)为直线上的一个顶点,
(
d
0
,
d
1
)
(d_0, d_1)
(d0,d1)为直线的方向。
3)
S
(
x
0
,
y
0
)
,
E
(
x
1
,
y
1
)
(
3
)
S(x_0,y_0), E(x_1,y_1) \space \space (3)
S(x0,y0),E(x1,y1) (3) 这是两点表达方式。它也是通用的表达方式。
下面是它们的相互表达以及c++源码。
常用到的是
(
1
)
(1)
(1)到
(
2
)
(
3
)
(2)(3)
(2)(3)的转化,
(
3
)
−
>
(
1
)
(3)->(1)
(3)−>(1)
设置
A
,
B
,
C
A,B,C
A,B,C的值使得
(
3
)
(3)
(3)在两个
S
,
E
S,E
S,E恒成立。通过简单的转换得到:
A
=
(
y
1
−
y
0
)
;
B
=
(
x
0
−
x
1
)
;
C
=
x
1
∗
y
0
−
x
0
∗
y
1
A=(y_1-y_0); B=(x_0-x_1); C=x_1*y_0-x_0*y1
A=(y1−y0);B=(x0−x1);C=x1∗y0−x0∗y1
C++代码实现如下:
const float KMIN_FLOAT_THRESHOLD_REFINED = 1e-8;
bool ConvertEndPntsToLineFun2D(const Eigen::Vector2f& ls2d, const Eigen::Vector2f& le2d, Eigen::Vector3f& line_fun)
{
if (std::abs((le2d - ls2d).norm()) < KMIN_FLOAT_THRESHOLD_REFINED)
return false;
line_fun[0] = le2d[1] - ls2d[1];
line_fun[1] = ls2d[0] - le2d[0];
line_fun[2] = le2d[0] * ls2d[1] - ls2d[0] * le2d[1];
return true;
}
(
3
)
−
>
(
2
)
(3)->(2)
(3)−>(2)
它很简单,直接通过两个端点计算直线的方向,然后将其中的一个点作为直线上的点。本篇文章使用
(
d
0
,
d
1
)
=
E
−
S
(d_0,d_1) = E-S
(d0,d1)=E−S;
(
x
0
,
y
0
)
=
S
(x_0,y_0) = S
(x0,y0)=S。
C++代码如下:
bool ConvertEndPntsToSPntLineDir2D(const Eigen::Vector2f& ls2d, const Eigen::Vector2f& le2d,
Eigen::Vector2f& lpnt, Eigen::Vector2f& ldir)
{
if ((le2d - ls2d).norm() < KMIN_FLOAT_THRESHOLD_REFINED)
{
ldir = Eigen::Vector2f(0.0, 0.0);
lpnt = Eigen::Vector2f(0.0, 0.0);
return false;
}
ldir = le2d - ls2d;
ldir.normalize();
lpnt = ls2d;
return true;
}
(
1
)
−
>
(
2
)
(1)->(2)
(1)−>(2)
它也很简单,通过
(
1
)
(1)
(1)的表示方式直接计算直线的法线,然后将直线上取一点。
bool ComputeLineFunLinedir2D(const Eigen::Vector3f& line_fun, Eigen::Vector2f& ldir)
{
Eigen::Vector2f line_normal = Eigen::Vector2f(line_fun[0], line_fun[1]);
float line_denom = line_normal.norm();
if (line_denom < KMIN_FLOAT_THRESHOLD_REFINED)
{
return false;
}
line_normal.normalize();
ldir[0] = -line_normal[1];
ldir[1] = line_normal[0];
return true;
}
bool SampleSpntFromFunLineFun2D(const Eigen::Vector3f& line_fun, Eigen::Vector2f& lpnt)
{
if (std::abs(line_fun[0]) < KMIN_FLOAT_THRESHOLD_REFINED
&& std::abs(line_fun[1]) < KMIN_FLOAT_THRESHOLD_REFINED)
{
return false;
}
if (std::abs(line_fun[0]) > std::abs(line_fun[1]))
{
lpnt[0] = -line_fun[2] / line_fun[0];
lpnt[1] = 0;
}
else
{
lpnt[0] = 0;
lpnt[1] = -line_fun[2] / line_fun[1];
}
return true;
}
bool ConvertLineFunToSPntLineDir2D(const Eigen::Vector3f& line_fun, Eigen::Vector2f& lpnt, Eigen::Vector2f& ldir)
{
//SamplePntsFromLineEndPnts2D
bool lp_flag = SampleSpntFromFunLineFun2D(line_fun, lpnt);
bool ld_flag = ComputeLineFunLinedir2D(line_fun, ldir);
if (lp_flag&&ld_flag)
{
return true;
}
return false;
}
(
2
)
−
>
(
1
)
(2)->(1)
(2)−>(1)
这个更加简单,直接先转化为两点表示法,然后再转化为
(
1
)
(1)
(1)的表达方式文章来源:https://www.toymoban.com/news/detail-532433.html
bool ConvertSPntLineToLineFun2D(const Eigen::Vector2f& lpnt, const Eigen::Vector2f& ldir, Eigen::Vector3f& line_fun)
{
if (ldir[0] < KMIN_FLOAT_THRESHOLD_REFINED
&& ldir[1] < KMIN_FLOAT_THRESHOLD_REFINED)
{
return false;
}
Eigen::Vector2f end_pnt = lpnt + ldir;
bool line_flag = ConvertEndPntsToLineFun2D(lpnt, end_pnt, line_fun);
return line_flag;
}
这是直线在各个表达方式的相互转化,如果在项目中使用的话,尽量全部统一为一种表达方式。便于计算。文章来源地址https://www.toymoban.com/news/detail-532433.html
到了这里,关于直线(二维)的表达方式及其相互转化 c++的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!