Code

updated spanish.nsh and inkscape.nsi to reflect latest file-changes
[inkscape.git] / trunk / src / 2geom / ray.h
1 /**
2  * \file
3  * \brief  Infinite Straight Ray
4  *
5  * Copyright 2008  Marco Cecchetti <mrcekets at gmail.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it either under the terms of the GNU Lesser General Public
9  * License version 2.1 as published by the Free Software Foundation
10  * (the "LGPL") or, at your option, under the terms of the Mozilla
11  * Public License Version 1.1 (the "MPL"). If you do not alter this
12  * notice, a recipient may use your version of this file under either
13  * the MPL or the LGPL.
14  *
15  * You should have received a copy of the LGPL along with this library
16  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  * You should have received a copy of the MPL along with this library
19  * in the file COPYING-MPL-1.1
20  *
21  * The contents of this file are subject to the Mozilla Public License
22  * Version 1.1 (the "License"); you may not use this file except in
23  * compliance with the License. You may obtain a copy of the License at
24  * http://www.mozilla.org/MPL/
25  *
26  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28  * the specific language governing rights and limitations.
29  */
31 #ifndef _2GEOM_RAY_H_
32 #define _2GEOM_RAY_H_
34 #include <2geom/point.h>
35 #include <2geom/bezier-curve.h> // for LineSegment
36 #include <2geom/exception.h>
38 #include <vector>
41 namespace Geom
42 {
44 class Ray
45 {
46 public:
47         Ray()
48                 : m_origin(0,0), m_versor(1,0)
49         {
50         }
52         Ray(Point const& _origin, Coord angle )
53                 : m_origin(_origin), m_versor(std::cos(angle), std::sin(angle))
54         {
55         }
57         Ray(Point const& A, Point const& B)
58         {
59                 setBy2Points(A, B);
60         }
62         Point origin() const
63         {
64                 return m_origin;
65         }
67         Point versor() const
68         {
69                 return m_versor;
70         }
72         void origin(Point const& _point)
73         {
74                 m_origin = _point;
75         }
77         void versor(Point const& _versor)
78         {
79                 m_versor = _versor;
80         }
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         }
89         void angle(Coord _angle)
90         {
91                 m_versor[X] = std::cos(_angle);
92                 m_versor[Y] = std::sin(_angle);
93         }
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         }
105         bool isDegenerate() const
106         {
107                 return ( m_versor[X] == 0 && m_versor[Y] == 0 );
108         }
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         }
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         }
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         }
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         }
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         }
167         Ray reverse() const
168         {
169                 Ray result;
170                 result.origin(m_origin);
171                 result.versor(-m_versor);
172                 return result;
173         }
175         Curve* portion(Coord  f, Coord t) const
176         {
177                 LineSegment* seg = new LineSegment(pointAt(f), pointAt(t));
178                 return seg;
179         }
181         LineSegment segment(Coord  f, Coord t) const
182         {
183                 return LineSegment(pointAt(f), pointAt(t));
184         }
186         Ray transformed(Matrix const& m) const
187         {
188                 return Ray(m_origin * m, (m_origin + m_versor) * m);
189         }
191 private:
192         Point m_origin;
193         Point m_versor;
195 };  // end class ray
197 inline
198 double distance(Point const& _point, Ray const& _ray)
200         double t = _ray.nearestPoint(_point);
201         return distance(_point, _ray.pointAt(t));
204 inline
205 bool are_near(Point const& _point, Ray const& _ray, double eps = EPSILON)
207         return are_near(distance(_point, _ray), 0, eps);
210 inline
211 bool are_same(Ray const& r1, Ray const& r2, double eps = EPSILON)
213         return are_near(r1.versor(), r2.versor(), eps)
214                         && are_near(r1.origin(), r2.origin(), eps);
217 // evaluate the angle between r1 and r2 rotating r1 in cw or ccw direction on r2
218 // the returned value is an angle in the interval [0, 2PI[
219 inline
220 double angle_between(Ray const& r1, Ray const& r2, bool cw = true)
222         double angle = angle_between(r1.versor(), r2.versor());
223         if (angle < 0) angle += 2*M_PI;
224         if (!cw) angle = 2*M_PI - angle;
225         return angle;
229 inline
230 Ray make_angle_bisector_ray(Ray const& r1, Ray const& r2)
232     if ( !are_near(r1.origin(), r2.origin()) )
233     {
234         THROW_RANGEERROR("passed rays have not the same origin");
235     }
237     Point M = middle_point(r1.pointAt(1), r2.pointAt(1) );
238     if (angle_between(r1, r2) > M_PI)  M = 2 * r1.origin() - M;
239     return Ray(r1.origin(), M);
243 }  // end namespace Geom
247 #endif /*_2GEOM_RAY_H_*/
250 /*
251   Local Variables:
252   mode:c++
253   c-file-style:"stroustrup"
254   c-file-offsets:((innamespace . 0)(substatement-open . 0))
255   indent-tabs-mode:nil
256   c-brace-offset:0
257   fill-column:99
258   End:
259   vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
260 */