直线(二维)的表达方式及其相互转化 c++

记录关于二维直线代码的时候遇到的一些常见的问题

直线表达方式有三种如下:
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=(y1y0);B=(x0x1);C=x1y0x0y1
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)=ES; ( 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)的表达方式

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;
	}

这是直线在各个表达方式的相互转化,如果在项目中使用的话,尽量全部统一为一种表达方式。便于计算。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值