~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

Viewing changes to src/2geom/ray.h

  • Committer: JazzyNico
  • Date: 2011-08-29 20:25:30 UTC
  • Revision ID: nicoduf@yahoo.fr-20110829202530-6deuoz11q90usldv
Code refactoring and merging with trunk (revision 10599).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**
2
2
 * \file
3
 
 * \brief  Infinite Straight Ray
4
 
 *
 
3
 * \brief  Infinite straight ray
 
4
 *//*
5
5
 * Copyright 2008  Marco Cecchetti <mrcekets at gmail.com>
6
6
 *
7
7
 * This library is free software; you can redistribute it and/or
28
28
 * the specific language governing rights and limitations.
29
29
 */
30
30
 
31
 
#ifndef _2GEOM_RAY_H_
32
 
#define _2GEOM_RAY_H_
 
31
#ifndef LIB2GEOM_SEEN_RAY_H
 
32
#define LIB2GEOM_SEEN_RAY_H
33
33
 
 
34
#include <vector>
34
35
#include <2geom/point.h>
35
36
#include <2geom/bezier-curve.h> // for LineSegment
36
37
#include <2geom/exception.h>
37
 
 
38
 
#include <vector>
39
 
 
 
38
#include <2geom/math-utils.h>
40
39
 
41
40
namespace Geom
42
41
{
43
42
 
44
 
class Ray
45
 
{
 
43
/**
 
44
 * @brief Straight ray from a specific point to infinity.
 
45
 *
 
46
 * Rays are "half-lines" - they begin at some specific point and extend in a straight line
 
47
 * to infinity.
 
48
 *
 
49
 * @ingroup Primitives
 
50
 */
 
51
class Ray {
 
52
private:
 
53
    Point _origin;
 
54
    Point _versor;
 
55
 
46
56
public:
47
 
        Ray()
48
 
                : m_origin(0,0), m_versor(1,0)
49
 
        {
50
 
        }
51
 
 
52
 
        Ray(Point const& _origin, Coord angle )
53
 
                : m_origin(_origin), m_versor(std::cos(angle), std::sin(angle))
54
 
        {
55
 
        }
56
 
 
57
 
        Ray(Point const& A, Point const& B)
58
 
        {
59
 
                setBy2Points(A, B);
60
 
        }
61
 
 
62
 
        Point origin() const
63
 
        {
64
 
                return m_origin;
65
 
        }
66
 
 
67
 
        Point versor() const
68
 
        {
69
 
                return m_versor;
70
 
        }
71
 
 
72
 
        void origin(Point const& _point)
73
 
        {
74
 
                m_origin = _point;
75
 
        }
76
 
 
77
 
        void versor(Point const& _versor)
78
 
        {
79
 
                m_versor = _versor;
80
 
        }
81
 
 
82
 
        Coord angle() const
83
 
        {
84
 
                double a = std::atan2(m_versor[Y], m_versor[X]);
85
 
                if (a < 0) a += 2*M_PI;
86
 
                return a;
87
 
        }
88
 
 
89
 
        void angle(Coord _angle)
90
 
        {
91
 
                m_versor[X] = std::cos(_angle);
92
 
                m_versor[Y] = std::sin(_angle);
93
 
        }
94
 
 
95
 
        void setBy2Points(Point const& A, Point const& B)
96
 
        {
97
 
                m_origin = A;
98
 
                m_versor = B - A;
99
 
                if ( are_near(m_versor, Point(0,0)) )
100
 
                        m_versor = Point(0,0);
101
 
                else
102
 
                        m_versor.normalize();
103
 
        }
104
 
 
105
 
        bool isDegenerate() const
106
 
        {
107
 
                return ( m_versor[X] == 0 && m_versor[Y] == 0 );
108
 
        }
109
 
 
110
 
        Point pointAt(Coord t) const
111
 
        {
112
 
                if (t < 0)      THROW_RANGEERROR("Ray::pointAt, negative t value passed");
113
 
                return m_origin + m_versor * t;
114
 
        }
115
 
 
116
 
        Coord valueAt(Coord t, Dim2 d) const
117
 
        {
118
 
                if (t < 0)
119
 
                        THROW_RANGEERROR("Ray::valueAt, negative t value passed");
120
 
                if (d < 0 || d > 1)
121
 
                        THROW_RANGEERROR("Ray::valueAt, dimension argument out of range");
122
 
                return m_origin[d] + m_versor[d] * t;
123
 
        }
124
 
 
125
 
        std::vector<Coord> roots(Coord v, Dim2 d) const
126
 
        {
127
 
                if (d < 0 || d > 1)
128
 
                        THROW_RANGEERROR("Ray::roots, dimension argument out of range");
129
 
                std::vector<Coord> result;
130
 
                if ( m_versor[d] != 0 )
131
 
                {
132
 
                        double t = (v - m_origin[d]) / m_versor[d];
133
 
                        if (t >= 0)     result.push_back(t);
134
 
                }
135
 
                // TODO: else ?
136
 
                return result;
137
 
        }
138
 
 
139
 
        // require are_near(_point, *this)
140
 
        // on the contrary the result value is meaningless
141
 
        Coord timeAt(Point const& _point) const
142
 
        {
143
 
                Coord t;
144
 
                if ( m_versor[X] != 0 )
145
 
                {
146
 
                        t = (_point[X] - m_origin[X]) / m_versor[X];
147
 
                }
148
 
                else if ( m_versor[Y] != 0 )
149
 
                {
150
 
                        t = (_point[Y] - m_origin[Y]) / m_versor[Y];
151
 
                }
152
 
                else // degenerate case
153
 
                {
154
 
                        t = 0;
155
 
                }
156
 
                return t;
157
 
        }
158
 
 
159
 
        Coord nearestPoint(Point const& _point) const
160
 
        {
161
 
                if ( isDegenerate() ) return 0;
162
 
                double t = dot( _point - m_origin, m_versor );
163
 
                if (t < 0) t = 0;
164
 
                return t;
165
 
        }
166
 
 
167
 
        Ray reverse() const
168
 
        {
169
 
                Ray result;
170
 
                result.origin(m_origin);
171
 
                result.versor(-m_versor);
172
 
                return result;
173
 
        }
174
 
 
175
 
        Curve* portion(Coord  f, Coord t) const
176
 
        {
177
 
                LineSegment* seg = new LineSegment(pointAt(f), pointAt(t));
178
 
                return seg;
179
 
        }
180
 
 
181
 
        LineSegment segment(Coord  f, Coord t) const
182
 
        {
183
 
                return LineSegment(pointAt(f), pointAt(t));
184
 
        }
185
 
 
186
 
        Ray transformed(Matrix const& m) const
187
 
        {
188
 
                return Ray(m_origin * m, (m_origin + m_versor) * m);
189
 
        }
190
 
 
191
 
private:
192
 
        Point m_origin;
193
 
        Point m_versor;
194
 
 
195
 
};  // end class ray
 
57
    Ray() : _origin(0,0), _versor(1,0) {}
 
58
    Ray(Point const& origin, Coord angle)
 
59
        : _origin(origin)
 
60
    {
 
61
        sincos(angle, _versor[Y], _versor[X]);
 
62
    }
 
63
    Ray(Point const& A, Point const& B) {
 
64
        setPoints(A, B);
 
65
    }
 
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) {
 
73
        _origin = a;
 
74
        _versor = b - a;
 
75
        if (are_near(_versor, Point(0,0)) )
 
76
            _versor = Point(0,0);
 
77
        else
 
78
            _versor.normalize();
 
79
    }
 
80
    bool isDegenerate() const {
 
81
        return ( _versor[X] == 0 && _versor[Y] == 0 );
 
82
    }
 
83
    Point pointAt(Coord t) const {
 
84
        return _origin + _versor * t;
 
85
    }
 
86
    Coord valueAt(Coord t, Dim2 d) const {
 
87
        return _origin[d] + _versor[d] * t;
 
88
    }
 
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();
 
96
        }
 
97
        return result;
 
98
    }
 
99
    Coord nearestPoint(Point const& point) const {
 
100
        if ( isDegenerate() ) return 0;
 
101
        double t = dot(point - _origin, _versor);
 
102
        if (t < 0) t = 0;
 
103
        return t;
 
104
    }
 
105
    Ray reverse() const {
 
106
        Ray result;
 
107
        result.setOrigin(_origin);
 
108
        result.setVersor(-_versor);
 
109
        return result;
 
110
    }
 
111
    Curve *portion(Coord f, Coord t) const {
 
112
        return new LineSegment(pointAt(f), pointAt(t));
 
113
    }
 
114
    LineSegment segment(Coord f, Coord t) const {
 
115
        return LineSegment(pointAt(f), pointAt(t));
 
116
    }
 
117
    Ray transformed(Affine const& m) const {
 
118
        return Ray(_origin * m, (_origin + _versor) * m);
 
119
    }
 
120
}; // end class Ray
196
121
 
197
122
inline
198
 
double distance(Point const& _point, Ray const& _ray)
199
 
{
 
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));
202
126
}
203
127
 
204
128
inline
205
 
bool are_near(Point const& _point, Ray const& _ray, double eps = EPSILON)
206
 
{
 
129
bool are_near(Point const& _point, Ray const& _ray, double eps = EPSILON) {
207
130
        return are_near(distance(_point, _ray), 0, eps);
208
131
}
209
132
 
210
133
inline
211
 
bool are_same(Ray const& r1, Ray const& r2, double eps = EPSILON)
212
 
{
 
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);
215
137
}
217
139
// evaluate the angle between r1 and r2 rotating r1 in cw or ccw direction on r2
218
140
// the returned value is an angle in the interval [0, 2PI[
219
141
inline
220
 
double angle_between(Ray const& r1, Ray const& r2, bool cw = true)
221
 
{
 
142
double angle_between(Ray const& r1, Ray const& r2, bool cw = true) {
222
143
        double angle = angle_between(r1.versor(), r2.versor());
223
144
        if (angle < 0) angle += 2*M_PI;
224
145
        if (!cw) angle = 2*M_PI - angle;
225
146
        return angle;
226
147
}
227
148
 
228
 
 
229
149
inline
230
150
Ray make_angle_bisector_ray(Ray const& r1, Ray const& r2)
231
151
{
239
159
    return Ray(r1.origin(), M);
240
160
}
241
161
 
242
 
 
243
162
}  // end namespace Geom
244
163
 
245
 
 
246
 
 
247
 
#endif /*_2GEOM_RAY_H_*/
248
 
 
 
164
#endif // LIB2GEOM_SEEN_RAY_H
249
165
 
250
166
/*
251
167
  Local Variables:
252
168
  mode:c++
253
169
  c-file-style:"stroustrup"
254
 
  c-file-offsets:((innamespace . 0)(substatement-open . 0))
 
170
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
255
171
  indent-tabs-mode:nil
256
 
  c-brace-offset:0
257
172
  fill-column:99
258
173
  End:
259
 
  vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
260
174
*/
 
175
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :