Reputation: 18675
I have the equation of a 2D line in the General Form a x + b y + c = 0
and I need to convert it to the proper Slope-intercept Form; with proper I mean I can choose between y = m x + q
and x = m y + q
.
My idea is to check if the line appears "more" horizontal or vertical and consequently choose one of the two Slope-intercept Form.
This is a sample code:
#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;
}
And this is the output
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
Any different or better idea? In particular, how can I handle the first two "degenerate" lines?
Upvotes: 1
Views: 879
Reputation: 10242
The equations corresponding to the two degenerated cases do not represent lines but the full plane (ℝ2) and the empty set (∅) respectively. The right thing to do is probably to discard them or to throw an error.
For the non degenerate cases, you are already handling them properly.
Upvotes: 1
Reputation: 14467
You're almost done, just handle the degenerate case. Add the check for a and b to be non-zero.
if(fabs(a) > DBL_EPSILON && fabs(b) > DBL_EPSILON)
{
... non-degenerate line handling
} else
{
// both a and b are machine zeros
degenerate_line = true;
}
Then add the parameter '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;
}
}
And then check for the line to be empty set:
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
}
}
}
If all you need is to draw the line, just use Thorsten's advice - use the rasterization algorithm instead.
Upvotes: 2
Reputation: 1365
If you are looking for a good way to draw these lines, I would recommend using Bresenham's algorithm instead of sampling the result of the slope-intercept form of your line equation. Apologies if this is not what you are trying to do.
Upvotes: 4