vgl_line_2d.hxx
Go to the documentation of this file.
1 // This is core/vgl/vgl_line_2d.hxx
2 #ifndef vgl_line_2d_hxx_
3 #define vgl_line_2d_hxx_
4 //:
5 // \file
6 
7 #include <cmath>
8 #include <iostream>
9 #include "vgl_line_2d.h"
10 #ifdef _MSC_VER
11 # include <vcl_msvc_warnings.h>
12 #endif
13 #include <cassert>
14 #include <vgl/vgl_point_2d.h>
15 #include <vgl/vgl_homg_line_2d.h>
16 
17 //: line through two given points
18 template <class Type>
20 : a_ ( p1.y() - p2.y() )
21 , b_ ( p2.x() - p1.x() )
22 , c_ ( p1.x() * p2.y() - p1.y() * p2.x() )
23 {
24  assert(a_||b_); // two points were distinct
25 }
26 
27 //: line defined by one point and one vector
28 template <class Type>
30 : a_ ( -v.y() )
31 , b_ ( v.x() )
32 , c_ ( -a_*p.x() - b_*p.y() )
33 {
34 }
35 
36 template <class Type>
38  : a_(l.a()) , b_(l.b()) , c_(l.c())
39 {
40  //JLM I see no reason to prohibit lines through the origin
41  // assert(c_);
42 }
43 
44 //: Get two points on the line.
45 // These two points are normally the intersections
46 // with the Y axis and X axis, respectively. When the line is parallel to one
47 // of these, the point with \a y=1 or \a x=1, resp. are taken.
48 // When the line goes through the origin, the second point is \a (b,-a).
49 template <class Type>
51 {
52  if (b() == 0) p1.set(-c()/a(), 1);
53  else p1.set(0, -c()/b());
54  if (a() == 0) p2.set(1, -c()/b());
55  else if ( c() == 0) p2.set(b(), -a());
56  else p2.set(-c()/a(), 0);
57 }
58 
59 template <class Type>
61 {
62  static const double deg_per_rad = 45.0/std::atan2(1.0,1.0);
63  // do special cases separately, to avoid rounding errors:
64  if (a() == 0) return b()<0 ? 0.0 : 180.0;
65  if (b() == 0) return a()<0 ? -90.0 : 90.0;
66  if (a() == b()) return a()<0 ? -45.0 : 135.0;
67  if (a()+b() == 0) return a()<0 ? -135.0 : 45.0;
68  // general case:
69  return deg_per_rad * std::atan2(double(a()),-double(b()));
70 }
71 
72 template <class Type>
74 {
75  return std::atan2(double(a()),-double(b()));
76 }
77 
78 template <class Type>
80 {
81  double mag = a_*a_ + b_*b_;
82  if (mag==1.0) return true;
83  if (mag==0.0) return false;
84  mag = 1.0/std::sqrt(mag);
85  a_ = Type(a_*mag);
86  b_ = Type(b_*mag);
87  c_ = Type(c_*mag);
88  mag = a_*a_ + b_*b_;
89  // return false when normalisation did not succeed, e.g. when Type == int:
90  return mag>0.99 && mag<1.01;
91 }
92 
93 #define vp(os,v,s) { (os)<<' '; if ((v)>0) (os)<<'+'; if ((v)&&!(s)[0]) (os)<<(v); else { \
94  if ((v)==-1) (os)<<'-';\
95  else if ((v)!=0&&(v)!=1) (os)<<(v);\
96  if ((v)!=0) (os)<<' '<<(s); } }
97 
98 //: Write line description to stream: "<vgl_line_2d ax+by+c=0>"
99 template <class Type>
100 std::ostream& operator<<(std::ostream& os, vgl_line_2d<Type> const& l)
101 {
102  os << "<vgl_line_2d"; vp(os,l.a(),"x"); vp(os,l.b(),"y"); vp(os,l.c(),"");
103  return os << " = 0 >";
104 }
105 
106 #undef vp
107 
108 //: Read in three line parameters from stream
109 // Either just reads three blank-separated numbers,
110 // or reads three comma-separated numbers,
111 // or reads three numbers in parenthesized form "(123, 321, 567)"
112 // or reads the formatted form "123x+321y+567=0"
113 template <class Type>
114 std::istream& operator>>(std::istream& is, vgl_line_2d<Type>& line)
115 {
116  if (! is.good()) return is; // (TODO: should throw an exception)
117  bool paren = false;
118  bool formatted = false;
119  Type a, b, c;
120  is >> std::ws; // jump over any leading whitespace
121  if (is.eof()) return is; // nothing to be set because of EOF (TODO: should throw an exception)
122  if (is.peek() == '(') { is.ignore(); paren=true; }
123  is >> std::ws >> a >> std::ws;
124  if (is.eof()) return is;
125  if (is.peek() == ',') is.ignore();
126  else if (is.peek() == 'x') { is.ignore(); formatted=true; }
127  is >> std::ws >> b >> std::ws;
128  if (is.eof()) return is;
129  if (formatted) {
130  if (is.eof()) return is;
131  if (is.peek() == 'y') is.ignore();
132  else return is; // formatted input incorrect (TODO: throw an exception)
133  }
134  else if (is.peek() == ',') is.ignore();
135  is >> std::ws >> c >> std::ws;
136  if (paren) {
137  if (is.eof()) return is;
138  if (is.peek() == ')') is.ignore();
139  else return is; // closing parenthesis is missing (TODO: throw an exception)
140  }
141  if (formatted) {
142  if (is.eof()) return is;
143  if (is.peek() == '=') is.ignore();
144  else return is; // closing parenthesis is missing (TODO: throw an exception)
145  is >> std::ws;
146  if (is.peek() == '0') is.ignore();
147  else return is; // closing parenthesis is missing (TODO: throw an exception)
148  }
149  line.set(a,b,c);
150  return is;
151 }
152 
153 #undef VGL_LINE_2D_INSTANTIATE
154 #define VGL_LINE_2D_INSTANTIATE(T) \
155 template class vgl_line_2d<T >; \
156 template std::ostream& operator<<(std::ostream&, vgl_line_2d<T >const&); \
157 template std::istream& operator>>(std::istream&, vgl_line_2d<T >&)
158 
159 #endif // vgl_line_2d_hxx_
a point in 2D nonhomogeneous space
Represents a homogeneous 2D line.
Definition: vgl_fwd.h:14
#define vp(os, v, s)
Definition: vgl_line_2d.hxx:93
vgl_line_2d()
Default constructor (Line 1.y==0, the X axis).
Definition: vgl_line_2d.h:43
void set(Type ta, Type tb, Type tc)
Set a b c.
Definition: vgl_line_2d.h:117
std::ostream & operator<<(std::ostream &s, vgl_orient_box_3d< Type > const &p)
Write box to stream.
line in projective 2D space
#define v
Definition: vgl_vector_2d.h:74
bool normalize()
normalize the line coefficients s.t. a^2 + b^2 = 1.
Definition: vgl_line_2d.hxx:79
void set(Type px, Type py)
Set x and y.
Definition: vgl_point_2d.h:79
Represents a Euclidean 2D line.
Definition: vgl_fwd.h:16
void get_two_points(vgl_point_2d< Type > &p1, vgl_point_2d< Type > &p2) const
Get two points on the line; normally the intersection with X and Y axes.
Definition: vgl_line_2d.hxx:50
double slope_radians() const
angle with the horizontal line y=0, measured in radians.
Definition: vgl_line_2d.hxx:73
std::istream & operator>>(std::istream &is, vgl_orient_box_3d< Type > &p)
Read box from stream.
#define l
Represents a cartesian 2D point.
Definition: vgl_area.h:7
double slope_degrees() const
angle with the horizontal line y=0, measured in 360-degrees.
Definition: vgl_line_2d.hxx:60