Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
line.h
Go to the documentation of this file.
1/*
5 * Authors:
6 * Marco Cecchetti <mrcekets at gmail.com>
7 * Krzysztof KosiƄski <tweenk.pl@gmail.com>
8 * Copyright 2008-2011 Authors
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it either under the terms of the GNU Lesser General Public
12 * License version 2.1 as published by the Free Software Foundation
13 * (the "LGPL") or, at your option, under the terms of the Mozilla
14 * Public License Version 1.1 (the "MPL"). If you do not alter this
15 * notice, a recipient may use your version of this file under either
16 * the MPL or the LGPL.
17 *
18 * You should have received a copy of the LGPL along with this library
19 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * You should have received a copy of the MPL along with this library
22 * in the file COPYING-MPL-1.1
23 *
24 * The contents of this file are subject to the Mozilla Public License
25 * Version 1.1 (the "License"); you may not use this file except in
26 * compliance with the License. You may obtain a copy of the License at
27 * http://www.mozilla.org/MPL/
28 *
29 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
30 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
31 * the specific language governing rights and limitations.
32 */
33
34#ifndef LIB2GEOM_SEEN_LINE_H
35#define LIB2GEOM_SEEN_LINE_H
36
37#include <cmath>
38#include <optional>
39#include <2geom/bezier-curve.h> // for LineSegment
40#include <2geom/rect.h>
41#include <2geom/crossing.h>
42#include <2geom/exception.h>
43#include <2geom/ray.h>
44#include <2geom/angle.h>
45#include <2geom/intersection.h>
46
47namespace Geom
48{
49
50// class docs in cpp file
51class Line
52 : boost::equality_comparable< Line >
53{
54private:
57public:
60
63 : _initial(0,0), _final(1,0)
64 {}
70 {
71 Point v;
72 sincos(angle, v[Y], v[X]);
73 _final = _initial + v;
74 }
75
81 Line(Point const &a, Point const &b)
82 : _initial(a)
83 , _final(b)
84 {}
85
88 Line(double a, double b, double c) {
89 setCoefficients(a, b, c);
90 }
91
93 explicit Line(LineSegment const &seg)
94 : _initial(seg.initialPoint())
95 , _final(seg.finalPoint())
96 {}
97
99 explicit Line(Ray const &r)
100 : _initial(r.origin())
101 , _final(r.origin() + r.vector())
102 {}
103
106 Point start = c * n.normalized();
107 Line l(start, start + rot90(n));
108 return l;
109 }
114 static Line from_origin_and_vector(Point const &o, Point const &v) {
115 Line l(o, o + v);
116 return l;
117 }
118
119 Line* duplicate() const {
120 return new Line(*this);
121 }
123
126
128 Point origin() const { return _initial; }
132 Point vector() const { return _final - _initial; }
135 Point versor() const { return (_final - _initial).normalized(); }
137 Coord angle() const {
138 Point d = _final - _initial;
139 double a = std::atan2(d[Y], d[X]);
140 if (a < 0) a += M_PI;
141 if (a == M_PI) a = 0;
142 return a;
143 }
144
147 void setOrigin(Point const &p) {
148 Point d = p - _initial;
149 _initial = p;
150 _final += d;
151 }
154 void setVector(Point const &v) {
155 _final = _initial + v;
156 }
157
161 Point v;
162 sincos(angle, v[Y], v[X]);
163 v *= distance(_initial, _final);
164 _final = _initial + v;
165 }
166
168 void setPoints(Point const &a, Point const &b) {
169 _initial = a;
170 _final = b;
171 }
172
176 void setCoefficients(double a, double b, double c);
177
181 std::vector<double> coefficients() const;
182
184 void coefficients(Coord &a, Coord &b, Coord &c) const;
185
190 bool isDegenerate() const {
191 return _initial == _final;
192 }
194 bool isHorizontal() const {
195 return _initial[Y] == _final[Y];
196 }
198 bool isVertical() const {
199 return _initial[X] == _final[X];
200 }
201
204 void normalize() {
205 // this helps with the nasty case of a line that starts somewhere far
206 // and ends very close to the origin
207 if (L2sq(_final) < L2sq(_initial)) {
208 std::swap(_initial, _final);
209 }
210 Point v = _final - _initial;
211 v.normalize();
212 _final = _initial + v;
213 }
215 Line normalized() const {
216 Point v = _final - _initial;
217 v.normalize();
218 Line ret(_initial, _initial + v);
219 return ret;
220 }
222
226 return _initial;
227 }
229 return _final;
230 }
231 Point pointAt(Coord t) const {
232 return lerp(t, _initial, _final);;
233 }
234
235 Coord valueAt(Coord t, Dim2 d) const {
236 return lerp(t, _initial[d], _final[d]);
237 }
238
239 Coord timeAt(Point const &p) const;
240
244 Coord timeAtProjection(Point const& p) const {
245 if ( isDegenerate() ) return 0;
246 Point v = vector();
247 return dot(p - _initial, v) / dot(v, v);
248 }
249
252 Coord nearestTime(Point const &p) const {
253 return timeAtProjection(p);
254 }
255
256 std::vector<Coord> roots(Coord v, Dim2 d) const;
257 Coord root(Coord v, Dim2 d) const;
259
262 void reverse() {
263 std::swap(_final, _initial);
264 }
267 Line reversed() const {
269 return result;
270 }
271
273 // TODO remove this?
274 Curve* portion(Coord f, Coord t) const {
275 LineSegment* seg = new LineSegment(pointAt(f), pointAt(t));
276 return seg;
277 }
278
284 return LineSegment(pointAt(f), pointAt(t));
285 }
286
288 std::optional<LineSegment> clip(Rect const &r) const;
289
296 Ray result;
298 result.setVector(vector());
299 return result;
300 }
301
305 Line derivative() const {
306 Point v = vector();
307 Line result(v, v);
308 return result;
309 }
310
312 Line transformed(Affine const& m) const {
313 Line l(_initial * m, _final * m);
314 return l;
315 }
316
320 Point normal() const {
321 return rot90(vector()).normalized();
322 }
323
324 // what does this do?
325 Point normalAndDist(double & dist) const {
326 Point n = normal();
327 dist = -dot(n, _initial);
328 return n;
329 }
330
333 Point v = versor();
334 Coord x2 = v[X]*v[X], y2 = v[Y]*v[Y], xy = v[X]*v[Y];
335 Affine m(x2-y2, 2.*xy,
336 2.*xy, y2-x2,
337 _initial[X], _initial[Y]);
338 m = Translate(-_initial) * m;
339 return m;
340 }
341
351 Point v = vector();
352 if (d == X) {
353 std::swap(v[X], v[Y]);
354 } else {
355 v[Y] = -v[Y];
356 }
357 Affine m = Translate(-_initial) * Rotate(v);
358 return m;
359 }
364 return m;
365 }
366
367 Affine transformTo(Line const &other) const;
369
370 std::vector<ShapeIntersection> intersect(Line const &other) const;
371 std::vector<ShapeIntersection> intersect(Ray const &r) const;
372 std::vector<ShapeIntersection> intersect(LineSegment const &ls) const;
373
374 template <typename T>
375 Line &operator*=(T const &tr) {
376 BOOST_CONCEPT_ASSERT((TransformConcept<T>));
377 _initial *= tr;
378 _final *= tr;
379 return *this;
380 }
381
382 bool operator==(Line const &other) const {
383 if (distance(pointAt(nearestTime(other._initial)), other._initial) != 0) return false;
384 if (distance(pointAt(nearestTime(other._final)), other._final) != 0) return false;
385 return true;
386 }
387
388 template <typename T>
389 friend Line operator*(Line const &l, T const &tr) {
390 BOOST_CONCEPT_ASSERT((TransformConcept<T>));
391 Line result(l);
392 result *= tr;
393 return result;
394 }
395}; // end class Line
396
403void filter_line_segment_intersections(std::vector<ShapeIntersection> &xs, bool a=false, bool b=true);
404void filter_ray_intersections(std::vector<ShapeIntersection> &xs, bool a=false, bool b=true);
405
408inline
409double distance(Point const &p, Line const &line)
410{
411 if (line.isDegenerate()) {
412 return ::Geom::distance(p, line.initialPoint());
413 } else {
414 Coord t = line.nearestTime(p);
415 return ::Geom::distance(line.pointAt(t), p);
416 }
417}
418
419inline
420bool are_near(Point const &p, Line const &line, double eps = EPSILON)
421{
422 return are_near(distance(p, line), 0, eps);
423}
424
425inline
426bool are_parallel(Line const &l1, Line const &l2, double eps = EPSILON)
427{
428 return are_near(cross(l1.vector(), l2.vector()), 0, eps);
429}
430
438inline
439bool are_same(Line const &l1, Line const &l2, double eps = EPSILON)
440{
441 return are_parallel(l1, l2, eps) && are_near(l1.origin(), l2, eps);
442}
443
446inline
447bool are_orthogonal(Line const &l1, Line const &l2, double eps = EPSILON)
448{
449 return are_near(dot(l1.vector(), l2.vector()), 0, eps);
450}
451
452// evaluate the angle between l1 and l2 rotating l1 in cw direction
453// until it overlaps l2
454// the returned value is an angle in the interval [0, PI[
455inline
456double angle_between(Line const& l1, Line const& l2)
457{
458 double angle = angle_between(l1.vector(), l2.vector());
459 if (angle < 0) angle += M_PI;
460 if (angle == M_PI) angle = 0;
461 return angle;
462}
463
464inline
465double distance(Point const &p, LineSegment const &seg)
466{
467 double t = seg.nearestTime(p);
468 return distance(p, seg.pointAt(t));
469}
470
471inline
472bool are_near(Point const &p, LineSegment const &seg, double eps = EPSILON)
473{
474 return are_near(distance(p, seg), 0, eps);
475}
476
477// build a line passing by _point and orthogonal to _line
478inline
479Line make_orthogonal_line(Point const &p, Line const &line)
480{
481 Point d = line.vector().cw();
482 Line l(p, p + d);
483 return l;
484}
485
486// build a line passing by _point and parallel to _line
487inline
488Line make_parallel_line(Point const &p, Line const &line)
489{
490 Line result(line);
491 result.setOrigin(p);
492 return result;
493}
494
495// build a line passing by the middle point of _segment and orthogonal to it.
496inline
498{
499 return make_orthogonal_line( middle_point(_segment), Line(_segment) );
500}
501
502// build the bisector line of the angle between ray(O,A) and ray(O,B)
503inline
504Line make_angle_bisector_line(Point const &A, Point const &O, Point const &B)
505{
506 AngleInterval ival(Angle(A-O), Angle(B-O));
507 Angle bisect = ival.angleAt(0.5);
508 return Line(O, bisect);
509}
510
511// prj(P) = rot(v, Point( rot(-v, P-O)[X], 0 )) + O
512inline
513Point projection(Point const &p, Line const &line)
514{
515 return line.pointAt(line.nearestTime(p));
516}
517
518inline
519LineSegment projection(LineSegment const &seg, Line const &line)
520{
521 return line.segment(line.nearestTime(seg.initialPoint()),
522 line.nearestTime(seg.finalPoint()));
523}
524
525inline
526std::optional<LineSegment> clip(Line const &l, Rect const &r) {
527 return l.clip(r);
528}
529
530
531namespace detail
532{
533
534OptCrossing intersection_impl(Ray const& r1, Line const& l2, unsigned int i);
536 Line const& l2,
537 unsigned int i );
539 Ray const& r2,
540 unsigned int i );
541}
542
543
544inline
545OptCrossing intersection(Ray const& r1, Line const& l2)
546{
547 return detail::intersection_impl(r1, l2, 0);
548
549}
550
551inline
552OptCrossing intersection(Line const& l1, Ray const& r2)
553{
554 return detail::intersection_impl(r2, l1, 1);
555}
556
557inline
559{
560 return detail::intersection_impl(ls1, l2, 0);
561}
562
563inline
565{
566 return detail::intersection_impl(ls2, l1, 1);
567}
568
569inline
571{
572 return detail::intersection_impl(ls1, r2, 0);
573
574}
575
576inline
578{
579 return detail::intersection_impl(ls2, r1, 1);
580}
581
582
583OptCrossing intersection(Line const& l1, Line const& l2);
584
585OptCrossing intersection(Ray const& r1, Ray const& r2);
586
587OptCrossing intersection(LineSegment const& ls1, LineSegment const& ls2);
588
589
590} // end namespace Geom
591
592
593#endif // LIB2GEOM_SEEN_LINE_H
594
595
596/*
597 Local Variables:
598 mode:c++
599 c-file-style:"stroustrup"
600 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
601 indent-tabs-mode:nil
602 fill-column:99
603 End:
604*/
605// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Defines the different types of exceptions that 2geom can throw.
Various trigoniometric helper functions.
Bezier curve.
3x3 matrix representing an affine transformation.
Definition affine.h:70
Directed angular interval.
Definition angle.h:188
Angle angleAt(Coord t) const
Get an angle corresponding to the specified time value.
Definition angle.h:288
Wrapper for angular values.
Definition angle.h:73
Coord nearestTime(Point const &p, Coord from=0, Coord to=1) const override
Compute a time value at which the curve comes closest to a specified point.
Point finalPoint() const override
Retrieve the end of the curve.
Point pointAt(Coord t) const override
Evaluate the curve at a specified time value.
Point initialPoint() const override
Retrieve the start of the curve.
Abstract continuous curve on a plane defined on [0,1].
Definition curve.h:78
Infinite line on a plane.
Definition line.h:53
bool are_same(Line const &l1, Line const &l2, double eps=EPSILON)
Test whether two lines are approximately the same.
Definition line.h:439
Line(double a, double b, double c)
Create a line based on the coefficients of its equation.
Definition line.h:88
void setCoefficients(double a, double b, double c)
Set the coefficients of the line equation.
Definition line.cpp:62
std::vector< double > coefficients() const
Get the coefficients of the line equation as a vector.
Definition line.cpp:120
Coord timeAt(Point const &p) const
Get a time value corresponding to a point.
Definition line.cpp:223
Affine rotationToZero(Dim2 d) const
Compute an affine which transforms all points on the line to zero X or Y coordinate.
Definition line.h:350
Affine reflection() const
Compute an affine matrix representing a reflection about the line.
Definition line.h:332
Line(Point const &a, Point const &b)
Create a line going through two points.
Definition line.h:81
Line transformed(Affine const &m) const
Create a line transformed by an affine transformation.
Definition line.h:312
void setAngle(Coord angle)
Set the angle the line makes with the X axis.
Definition line.h:160
void setOrigin(Point const &p)
Set the point at zero time.
Definition line.h:147
bool isDegenerate() const
Check if the line has more than one point.
Definition line.h:190
Point origin() const
Get the line's origin point.
Definition line.h:128
Line derivative() const
Create a derivative of the line.
Definition line.h:305
void setPoints(Point const &a, Point const &b)
Set a line based on two points it should pass through.
Definition line.h:168
Line(LineSegment const &seg)
Create a line by extending a line segment.
Definition line.h:93
void reverse()
Definition line.h:262
Point vector() const
Get the line's raw direction vector.
Definition line.h:132
Affine rotationToAxis(Dim2 d) const
Compute a rotation affine which transforms the line to one of the axes.
Definition line.h:362
Line(Point const &origin, Coord angle)
Create a line with the specified inclination.
Definition line.h:68
void normalize()
Reparametrize the line so that it has unit speed.
Definition line.h:204
friend Line operator*(Line const &l, T const &tr)
Definition line.h:389
void setVector(Point const &v)
Set the speed of the line.
Definition line.h:154
Line * duplicate() const
Definition line.h:119
Line reversed() const
Create a line containing the same points, but in opposite direction.
Definition line.h:267
Line normalized() const
Return a new line reparametrized for unit speed.
Definition line.h:215
std::vector< Coord > roots(Coord v, Dim2 d) const
Find intersection with an axis-aligned line.
Definition line.cpp:131
std::optional< LineSegment > clip(Rect const &r) const
Return the portion of the line that is inside the given rectangle.
Definition line.cpp:151
bool isVertical() const
Check if the line is vertical (x is constant).
Definition line.h:198
Affine transformTo(Line const &other) const
Create a transformation that maps one line to another.
Definition line.cpp:244
Point _final
Definition line.h:56
Coord timeAtProjection(Point const &p) const
Get a time value corresponding to a projection of a point on the line.
Definition line.h:244
Ray ray(Coord t)
Create a ray starting at the specified time value.
Definition line.h:295
Point normalAndDist(double &dist) const
Definition line.h:325
Line & operator*=(T const &tr)
Definition line.h:375
bool are_orthogonal(Line const &l1, Line const &l2, double eps=EPSILON)
Test whether two lines are perpendicular.
Definition line.h:447
Coord valueAt(Coord t, Dim2 d) const
Definition line.h:235
Point finalPoint() const
Definition line.h:228
Curve * portion(Coord f, Coord t) const
Same as segment(), but allocate the line segment dynamically.
Definition line.h:274
static Line from_normal_distance(Point const &n, Coord c)
Create a line normal to a vector at a specified distance from origin.
Definition line.h:105
static Line from_origin_and_vector(Point const &o, Point const &v)
Create a line from origin and unit vector.
Definition line.h:114
Coord nearestTime(Point const &p) const
Find a point on the line closest to the query point.
Definition line.h:252
Point initialPoint() const
Definition line.h:225
Line(Ray const &r)
Create a line by extending a ray.
Definition line.h:99
std::vector< ShapeIntersection > intersect(Line const &other) const
Definition line.cpp:253
bool operator==(Line const &other) const
Definition line.h:382
Coord angle() const
Angle the line makes with the X axis, in mathematical convention.
Definition line.h:137
Point pointAt(Coord t) const
Definition line.h:231
Point versor() const
Get the line's normalized direction vector.
Definition line.h:135
Point normal() const
Get a unit vector normal to the line.
Definition line.h:320
double distance(Point const &p, Line const &line)
Compute distance from point to line.
Definition line.h:409
Line()
Create a default horizontal line.
Definition line.h:62
LineSegment segment(Coord f, Coord t) const
Create a segment of this line.
Definition line.h:283
Point _initial
Definition line.h:55
bool isHorizontal() const
Check if the line is horizontal (y is constant).
Definition line.h:194
Two-dimensional point that doubles as a vector.
Definition point.h:66
Point normalized() const
Definition point.h:121
constexpr Point cw() const
Return a point like this point but rotated +90 degrees.
Definition point.h:137
Straight ray from a specific point to infinity.
Definition ray.h:53
void setOrigin(Point const &o)
Definition ray.h:71
Axis aligned, non-empty rectangle.
Definition rect.h:92
Rotation around the origin.
Definition transforms.h:187
Translation by a vector.
Definition transforms.h:115
RootCluster root
Structure representing the intersection of two curves.
Css & result
double c[8][4]
BezierCurveN< 1 > LineSegment
Line segment.
constexpr Coord lerp(Coord t, Coord a, Coord b)
Numerically stable linear interpolation.
Definition coord.h:97
Dim2
2D axis enumeration (X or Y).
Definition coord.h:48
constexpr Dim2 other_dimension(Dim2 d)
Get the other (perpendicular) dimension.
Definition coord.h:52
double Coord
Floating point type used to store coordinates.
Definition coord.h:76
constexpr Coord EPSILON
Default "acceptably small" value.
Definition coord.h:84
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
Intersection utilities.
Geom::Point start
OptCrossing intersection_impl(Ray const &r1, Line const &l2, unsigned int i)
Definition line.cpp:332
Various utility functions.
Definition affine.h:22
void sincos(double angle, double &sin_, double &cos_)
Simultaneously compute a sine and a cosine of the same angle.
Definition math-utils.h:89
void filter_ray_intersections(std::vector< ShapeIntersection > &xs, bool a=false, bool b=true)
Definition line.cpp:300
Point projection(Point const &p, Line const &line)
Definition line.h:513
Line make_parallel_line(Point const &p, Line const &line)
Definition line.h:488
Angle distance(Angle const &a, Angle const &b)
Definition angle.h:163
std::optional< Crossing > OptCrossing
Definition crossing.h:64
OptCrossing intersection(Ray const &r1, Line const &l2)
Definition line.h:545
Line make_bisector_line(LineSegment const &_segment)
Definition line.h:497
double angle_between(Line const &l1, Line const &l2)
Definition line.h:456
void filter_line_segment_intersections(std::vector< ShapeIntersection > &xs, bool a=false, bool b=true)
Removes intersections outside of the unit interval.
Definition line.cpp:287
Line make_orthogonal_line(Point const &p, Line const &line)
Definition line.h:479
bool clip(std::vector< RatQuad > &rq, const xAx &cs, const Rect &R)
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
bool are_parallel(Line const &l1, Line const &l2, double eps=EPSILON)
Definition line.h:426
Line make_angle_bisector_line(Point const &A, Point const &O, Point const &B)
Definition line.h:504
T dot(D2< T > const &a, D2< T > const &b)
Definition d2.h:355
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
D2< T > rot90(D2< T > const &a)
Definition d2.h:397
Point middle_point(LineSegment const &_segment)
Infinite straight ray.
Axis-aligned rectangle.
Type requirements for transforms.
Definition transforms.h:50