28
28
* the specific language governing rights and limitations.
31
#ifndef LIB2GEOM_SEEN_RAY_H
32
#define LIB2GEOM_SEEN_RAY_H
34
35
#include <2geom/point.h>
35
36
#include <2geom/bezier-curve.h> // for LineSegment
36
37
#include <2geom/exception.h>
38
#include <2geom/math-utils.h>
44
* @brief Straight ray from a specific point to infinity.
46
* Rays are "half-lines" - they begin at some specific point and extend in a straight line
48
: m_origin(0,0), m_versor(1,0)
52
Ray(Point const& _origin, Coord angle )
53
: m_origin(_origin), m_versor(std::cos(angle), std::sin(angle))
57
Ray(Point const& A, Point const& B)
72
void origin(Point const& _point)
77
void versor(Point const& _versor)
84
double a = std::atan2(m_versor[Y], m_versor[X]);
85
if (a < 0) a += 2*M_PI;
89
void angle(Coord _angle)
91
m_versor[X] = std::cos(_angle);
92
m_versor[Y] = std::sin(_angle);
95
void setBy2Points(Point const& A, Point const& B)
99
if ( are_near(m_versor, Point(0,0)) )
100
m_versor = Point(0,0);
102
m_versor.normalize();
105
bool isDegenerate() const
107
return ( m_versor[X] == 0 && m_versor[Y] == 0 );
110
Point pointAt(Coord t) const
112
if (t < 0) THROW_RANGEERROR("Ray::pointAt, negative t value passed");
113
return m_origin + m_versor * t;
116
Coord valueAt(Coord t, Dim2 d) const
119
THROW_RANGEERROR("Ray::valueAt, negative t value passed");
121
THROW_RANGEERROR("Ray::valueAt, dimension argument out of range");
122
return m_origin[d] + m_versor[d] * t;
125
std::vector<Coord> roots(Coord v, Dim2 d) const
128
THROW_RANGEERROR("Ray::roots, dimension argument out of range");
129
std::vector<Coord> result;
130
if ( m_versor[d] != 0 )
132
double t = (v - m_origin[d]) / m_versor[d];
133
if (t >= 0) result.push_back(t);
139
// require are_near(_point, *this)
140
// on the contrary the result value is meaningless
141
Coord timeAt(Point const& _point) const
144
if ( m_versor[X] != 0 )
146
t = (_point[X] - m_origin[X]) / m_versor[X];
148
else if ( m_versor[Y] != 0 )
150
t = (_point[Y] - m_origin[Y]) / m_versor[Y];
152
else // degenerate case
159
Coord nearestPoint(Point const& _point) const
161
if ( isDegenerate() ) return 0;
162
double t = dot( _point - m_origin, m_versor );
170
result.origin(m_origin);
171
result.versor(-m_versor);
175
Curve* portion(Coord f, Coord t) const
177
LineSegment* seg = new LineSegment(pointAt(f), pointAt(t));
181
LineSegment segment(Coord f, Coord t) const
183
return LineSegment(pointAt(f), pointAt(t));
186
Ray transformed(Matrix const& m) const
188
return Ray(m_origin * m, (m_origin + m_versor) * m);
57
Ray() : _origin(0,0), _versor(1,0) {}
58
Ray(Point const& origin, Coord angle)
61
sincos(angle, _versor[Y], _versor[X]);
63
Ray(Point const& A, Point const& B) {
66
Point origin() const { return _origin; }
67
Point versor() const { return _versor; }
68
void setOrigin(Point const &o) { _origin = o; }
69
void setVersor(Point const& v) { _versor = v; }
70
Coord angle() const { return std::atan2(_versor[Y], _versor[X]); }
71
void setAngle(Coord a) { sincos(a, _versor[Y], _versor[X]); }
72
void setPoints(Point const &a, Point const &b) {
75
if (are_near(_versor, Point(0,0)) )
80
bool isDegenerate() const {
81
return ( _versor[X] == 0 && _versor[Y] == 0 );
83
Point pointAt(Coord t) const {
84
return _origin + _versor * t;
86
Coord valueAt(Coord t, Dim2 d) const {
87
return _origin[d] + _versor[d] * t;
89
std::vector<Coord> roots(Coord v, Dim2 d) const {
90
std::vector<Coord> result;
91
if ( _versor[d] != 0 ) {
92
double t = (v - _origin[d]) / _versor[d];
93
if (t >= 0) result.push_back(t);
94
} else if (_versor[(d+1)%2] == v) {
95
THROW_INFINITESOLUTIONS();
99
Coord nearestPoint(Point const& point) const {
100
if ( isDegenerate() ) return 0;
101
double t = dot(point - _origin, _versor);
105
Ray reverse() const {
107
result.setOrigin(_origin);
108
result.setVersor(-_versor);
111
Curve *portion(Coord f, Coord t) const {
112
return new LineSegment(pointAt(f), pointAt(t));
114
LineSegment segment(Coord f, Coord t) const {
115
return LineSegment(pointAt(f), pointAt(t));
117
Ray transformed(Affine const& m) const {
118
return Ray(_origin * m, (_origin + _versor) * m);
198
double distance(Point const& _point, Ray const& _ray)
123
double distance(Point const& _point, Ray const& _ray) {
200
124
double t = _ray.nearestPoint(_point);
201
return distance(_point, _ray.pointAt(t));
125
return ::Geom::distance(_point, _ray.pointAt(t));
205
bool are_near(Point const& _point, Ray const& _ray, double eps = EPSILON)
129
bool are_near(Point const& _point, Ray const& _ray, double eps = EPSILON) {
207
130
return are_near(distance(_point, _ray), 0, eps);
211
bool are_same(Ray const& r1, Ray const& r2, double eps = EPSILON)
134
bool are_same(Ray const& r1, Ray const& r2, double eps = EPSILON) {
213
135
return are_near(r1.versor(), r2.versor(), eps)
214
136
&& are_near(r1.origin(), r2.origin(), eps);