如何在 C++ 中将一般形式的二维直线方程转换为斜截距形式

Posted

技术标签:

【中文标题】如何在 C++ 中将一般形式的二维直线方程转换为斜截距形式【英文标题】:How to convert a 2D line equation in General Form to a Slope-intercept Form, in C++ 【发布时间】:2012-06-27 09:52:30 【问题描述】:

我有一般形式a x + b y + c = 0 中的二维线方程,我需要将其转换为正确的斜率截距形式;我的意思是我可以在y = m x + qx = m y + q 之间进行选择。

我的想法是检查线条是否出现“更多”水平或垂直,然后选择两种斜率截距形式之一。

这是一个示例代码:

#include <iostream>
#include <cmath>

void abc2mq( double a, double b, double c, double& m, double& q, bool& x2y )

   if ( fabs(b) >= fabs(a) ) 
      x2y = true;
      m = -a/b;
      q = -c/b;
    else 
      x2y = false;
      m = -b/a;
      q = -c/a;
   


void test(double a, double b, double c)

   double m,q;
   bool x2y;
   abc2mq( a, b, c, m, q, x2y );
   std::cout << a << " x + " << b << " y + " << c << " = 0\t";
   if ( x2y ) 
      std::cout << "y = " << m << " x + " << q << "\n";
    else 
      std::cout << "x = " << m << " y + " << q << "\n";
   


int main(int argc, char* argv[])

   test(0,0,0);
   test(0,0,1);
   test(0,1,0);
   test(0,1,1);
   test(1,0,0);
   test(1,0,1);
   test(1,1,0);
   test(1,1,1);

   return 0;

这是输出

0 x + 0 y + 0 = 0       y = -1.#IND x + -1.#IND
0 x + 0 y + 1 = 0       y = -1.#IND x + -1.#INF
0 x + 1 y + 0 = 0       y = -0 x + -0
0 x + 1 y + 1 = 0       y = -0 x + -1
1 x + 0 y + 0 = 0       x = -0 y + -0
1 x + 0 y + 1 = 0       x = -0 y + -1
1 x + 1 y + 0 = 0       y = -1 x + -0
1 x + 1 y + 1 = 0       y = -1 x + -1

有什么不同或更好的想法吗?特别是,我该如何处理前两个“退化”行?

【问题讨论】:

@AndreasBrinck 我需要画线,而用于画线的旧代码可以同时接受斜截距形式,因此我需要选择合适的形式。不幸的是,我无法更改旧代码。 【参考方案1】:

如果您正在寻找绘制这些线条的好方法,我建议您使用Bresenham's algorithm,而不是对线条方程的斜率截距形式的结果进行采样。 如果这不是您想要做的,请道歉。

【讨论】:

+1,谢谢你记住了 Bresenham 的线算法。【参考方案2】:

你差不多完成了,只需处理退化的情况。 添加检查 a 和 b 是否为非零。

if(fabs(a) > DBL_EPSILON && fabs(b) > DBL_EPSILON)

    ... non-degenerate line handling
 else

    // both a and b are machine zeros
    degenerate_line = true;

然后添加参数'degenerate_line':

void abc2mq( double a, double b, double c, double& m, double& q, bool& x2y, bool& degenerate_line)

    if(fabs(a) > DBL_EPSILON && fabs(b) > DBL_EPSILON)
    
       if ( fabs(b) >= fabs(a) ) 
           x2y = true;
           m = -a/b;
           q = -c/b;
         else 
           x2y = false;
           m = -b/a;
           q = -c/a;
        

        degenerate_line = false;
     else
    
        degenerate_line = true;
    

然后检查该行是否为空集:

void test(double a, double b, double c)

    double m,q;
    bool x2y, degenerate;
    abc2mq( a, b, c, m, q, x2y, degenerate );
    std::cout << a << " x + " << b << " y + " << c << " = 0\t";
    if(!degenerate)
    
       if ( x2y ) 
           std::cout << "y = " << m << " x + " << q << std::endl;
        else 
           std::cout << "x = " << m << " y + " << q << std::endl;
       
     else
    
       if(fabs(c) > DBL_EPSILON)
       
          std::cout << "empty set" << std::endl
        else
       
          std::cout << "entire plane" << std::endl
       
    

如果您只需要画线,只需使用 Thorsten 的建议 - 改用光栅化算法。

【讨论】:

【参考方案3】:

两种退化情况对应的方程不代表直线,而是分别代表全平面(ℝ2)和空集(∅)。正确的做法可能是丢弃它们或抛出错误。

对于非退化的情况,你已经在正确处理它们了。

【讨论】:

以上是关于如何在 C++ 中将一般形式的二维直线方程转换为斜截距形式的主要内容,如果未能解决你的问题,请参考以下文章

一起复习几何

平面解析几何初步--直线的方程

空间平面及其方程

如何在三维坐标中确定一条直线,一个平面

线性回归方程是如何求得的?

在 C++ 中将指针转换为数组形式的问题?