Code

Super duper mega (fun!) commit: replaced encoding=utf-8 with fileencoding=utf-8 in...
[inkscape.git] / src / 2geom / hvlinesegment.h
1 /**
2  * \file
3  * \brief  Horizontal and Vertical Line Segment
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  */
32 #ifndef _2GEOM_HVLINESEGMENT_H_
33 #define _2GEOM_HVLINESEGMENT_H_
36 #include <2geom/bezier-curve.h>
39 namespace Geom
40 {
42 class HLineSegment : public Curve
43 {
44   public:
45     HLineSegment()
46     {}
48     HLineSegment(Coord _x0, Coord _x1, Coord _y)
49         : m_line_seg(Point(_x0, _y), Point(_x1, _y))
50     {
51     }
53     HLineSegment(Point const& _p, double _length)
54         : m_line_seg(_p, Point(_p[X] + _length, _p[Y]))
55     {
56     }
58     HLineSegment(Point const& _p0, Point const& _p1)
59         : m_line_seg(_p0, _p1)
60     {
61         if ( _p0[Y] != _p1[Y] )
62         {
63             THROW_RANGEERROR("HLineSegment::HLineSegment passed points should "
64                              "have the same Y value");
65         }
66     }
68     Curve* duplicate() const
69     {
70         return new HLineSegment(*this);
71     }
73     bool isDegenerate() const
74     {
75         return m_line_seg.isDegenerate();
76     }
78     Point initialPoint() const
79     {
80         return m_line_seg.initialPoint();
81     }
83     Point finalPoint() const
84     {
85         return m_line_seg.finalPoint();
86     }
88     Coord getY()
89     {
90         return initialPoint()[Y];
91     }
93     void setInitial(Point _p)
94     {
95         m_line_seg.setInitial( Point(_p[X], initialPoint()[Y]) );
96     }
98     void setFinal(Point _p)
99     {
100         m_line_seg.setFinal( Point(_p[X], finalPoint()[Y]) );
101     }
103     void setX0(Coord _x)
104     {
105         m_line_seg.setInitial( Point(_x, initialPoint()[Y]) );
106     }
108     void setX1(Coord _x)
109     {
110         m_line_seg.setFinal( Point(_x, finalPoint()[Y]) );
111     }
113     void setY(Coord _y)
114     {
115         m_line_seg.setInitial( Point(initialPoint()[X], _y) );
116         m_line_seg.setFinal( Point(finalPoint()[X], _y) );
117     }
119     virtual OptRect boundsFast() const
120     {
121         return boundsExact();
122     }
124     virtual OptRect boundsExact() const
125     {
126         return Rect( initialPoint(), finalPoint() );
127     }
129     virtual OptRect boundsLocal(OptInterval i, unsigned deg) const
130     {
131         return m_line_seg.boundsLocal(i, deg);
132     }
134     int winding(Point p) const
135     {
136         return m_line_seg.winding(p);
137     }
139     int degreesOfFreedom() const { return 3;}
141     std::vector<double>
142     roots(double v, Dim2 d) const
143     {
144         if (d < 0 || d > 1)
145         {
146             THROW_RANGEERROR("dimension argument out of range");
147         }
148         std::vector<double> result;
149         if (d == X)
150         {
151             if ( v >= initialPoint()[X] && v <= finalPoint()[X] )
152             {
153                 double t = 0;
154                 if (!isDegenerate())
155                     t = (v - initialPoint()[X]) / (finalPoint()[X] - initialPoint()[X]);
156                 result.push_back(t);
157             }
158         }
159         else
160         {
161             if (v == initialPoint()[Y])
162             {
163                 if (!isDegenerate())
164                     THROW_INFINITESOLUTIONS(0);
165                 result.push_back(0);
166             }
167         }
168         return result;
169     }
171     double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
172     {
173         if ( from > to ) std::swap(from, to);
174         double xfrom = pointAt(from)[X];
175         double xto = pointAt(to)[X];
176         if ( xfrom > xto )
177         {
178             std::swap(xfrom, xto);
179             std::swap(from, to);
180         }
181         if ( p[X] > xfrom && p[X] < xto )
182         {
183             return (p[X] - initialPoint()[X]) / (finalPoint()[X] - initialPoint()[X]);
184         }
185         else if ( p[X] <= xfrom )
186             return from;
187         else
188             return to;
189     }
191     std::pair<HLineSegment, HLineSegment> subdivide(Coord t) const
192     {
193         std::pair<HLineSegment, HLineSegment> result;
194         Point p = pointAt(t);
195         result.first.setInitial(initialPoint());
196         result.first.setFinal(p);
197         result.second.setInitial(p);
198         result.second.setFinal(finalPoint());
199         return result;
200     }
202     Curve* portion(double f, double t) const
203     {
204         Point ip = pointAt(f);
205         Point ep = pointAt(t);
206         return new HLineSegment(ip[X], ep[X], ip[Y]);
207     }
209     Curve* reverse() const
210     {
211         return
212         new HLineSegment(finalPoint()[X], initialPoint()[X], initialPoint()[Y]);
213     }
215     Curve* transformed(Matrix const & m) const
216     {
217         Point ip = initialPoint() * m;
218         Point ep = finalPoint() * m;
219         if (ip[Y] == ep[Y]) {
220             return new HLineSegment(ip[X], ep[X], ip[Y]);
221         } else {
222             return new LineSegment(ip, ep);
223         }
224     }
226     Curve* derivative() const
227     {
228         double x = finalPoint()[X] - initialPoint()[X];
229         return new HLineSegment(x, x, 0);
230     }
232     Point pointAt(double t) const
233     {
234         if ( t < 0 || t > 1 )
235             THROW_RANGEERROR("domain parameter out of range");
236         double x = initialPoint()[X] + t * (finalPoint()[X] - initialPoint()[X]);
237         return Point(x, initialPoint()[Y]);
238     }
240     double valueAt(double t, Dim2 d) const
241     {
242         if (d < 0 || d > 1)
243         {
244             THROW_RANGEERROR("dimension argument out of range");
245         }
246         if ( t < 0 || t > 1 )
247             THROW_RANGEERROR("domain parameter out of range");
249         if (d == Y) return initialPoint()[Y];
251         return initialPoint()[X] + t * (finalPoint()[X] - initialPoint()[X]);
252     }
254     std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const
255     {
256         std::vector<Point> result;
257         result.push_back(pointAt(t));
258         if (n > 0)
259         {
260             double x = finalPoint()[X] - initialPoint()[X];
261             result.push_back( Point(x, 0) );
262         }
263         if (n > 1)
264         {
265             /* higher order derivatives are zero,
266              * so the other n-1 vector elements are (0,0) */
267             result.insert( result.end(), n-1, Point(0, 0) );
268         }
269         return result;
270     }
272     D2<SBasis> toSBasis() const
273     {
274         return m_line_seg.toSBasis();
275     }
277   private:
278     LineSegment m_line_seg;
280 };  // end class HLineSegment
283 class VLineSegment : public Curve
285   public:
286     VLineSegment()
287     {}
289     VLineSegment(Coord _x, Coord _y0, Coord _y1)
290         : m_line_seg(Point(_x, _y0), Point(_x, _y1))
291     {
292     }
294     VLineSegment(Point const& _p, double _length)
295         : m_line_seg(_p, Point(_p[X], _p[Y] + _length))
296     {
297     }
299     VLineSegment(Point const& _p0, Point const& _p1)
300         : m_line_seg(_p0, _p1)
301     {
302         if ( _p0[X] != _p1[X] )
303         {
304             THROW_RANGEERROR("VLineSegment::VLineSegment passed points should "
305                              "have the same X value");
306         }
307     }
309     Curve* duplicate() const
310     {
311         return new VLineSegment(*this);
312     }
314     bool isDegenerate() const
315     {
316         return m_line_seg.isDegenerate();
317     }
319     Point initialPoint() const
320     {
321         return m_line_seg.initialPoint();
322     }
324     Point finalPoint() const
325     {
326         return m_line_seg.finalPoint();
327     }
329     Coord getX()
330     {
331         return initialPoint()[X];
332     }
334     void setInitial(Point _p)
335     {
336         m_line_seg.setInitial( Point(initialPoint()[X], _p[Y]) );
337     }
339     void setFinal(Point _p)
340     {
341         m_line_seg.setFinal( Point(finalPoint()[X], _p[Y]) );
342     }
344     void setY0(Coord _y)
345     {
346         m_line_seg.setInitial( Point(initialPoint()[X], _y) );
347     }
349     void setY1(Coord _y)
350     {
351         m_line_seg.setFinal( Point(finalPoint()[Y], _y) );
352     }
354     void setX(Coord _x)
355     {
356         m_line_seg.setInitial( Point(_x, initialPoint()[Y]) );
357         m_line_seg.setFinal( Point(_x, finalPoint()[Y]) );
358     }
360     virtual OptRect boundsFast() const
361     {
362         return boundsExact();
363     }
365     virtual OptRect boundsExact() const
366     {
367         return Rect( initialPoint(), finalPoint() );
368     }
370     virtual OptRect boundsLocal(OptInterval i, unsigned deg) const
371     {
372         return m_line_seg.boundsLocal(i, deg);
373     }
375     int winding(Point p) const
376     {
377         return m_line_seg.winding(p);
378     }
380     int degreesOfFreedom() const { return 3;}
381     
382     std::vector<double>
383     roots(double v, Dim2 d) const
384     {
385         if (d < 0 || d > 1)
386         {
387             THROW_RANGEERROR("dimension argument out of range");
388         }
389         std::vector<double> result;
390         if (d == Y)
391         {
392             if ( v >= initialPoint()[Y] && v <= finalPoint()[Y] )
393             {
394                 double t = 0;
395                 if (!isDegenerate())
396                     t = (v - initialPoint()[Y]) / (finalPoint()[Y] - initialPoint()[Y]);
397                 result.push_back(t);
398             }
399         }
400         else
401         {
402             if (v == initialPoint()[X])
403             {
404                 if (!isDegenerate())
405                     THROW_INFINITESOLUTIONS(0);
406                 result.push_back(0);
407             }
408         }
409         return result;
410     }
412     double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
413     {
414         if ( from > to ) std::swap(from, to);
415         double yfrom = pointAt(from)[Y];
416         double yto = pointAt(to)[Y];
417         if (yfrom > yto)
418         {
419             std::swap(yfrom, yto);
420             std::swap(from, to);
421         }
422         if ( p[Y] > yfrom && p[Y] < yto )
423         {
424             return (p[Y] - initialPoint()[Y]) / (finalPoint()[Y] - initialPoint()[Y]);
425         }
426         else if ( p[Y] <= yfrom )
427             return from;
428         else
429             return to;
430     }
432     std::pair<VLineSegment, VLineSegment> subdivide(Coord t) const
433     {
434         std::pair<VLineSegment, VLineSegment> result;
435         Point p = pointAt(t);
436         result.first.setInitial(initialPoint());
437         result.first.setFinal(p);
438         result.second.setInitial(p);
439         result.second.setFinal(finalPoint());
440         return result;
441     }
443     Curve* portion(double f, double t) const
444     {
445         Point ip = pointAt(f);
446         Point ep = pointAt(t);
447         return new VLineSegment(ip[X], ip[Y], ep[Y]);
448     }
450     Curve* reverse() const
451     {
452         return
453         new VLineSegment(initialPoint()[X], finalPoint()[Y], initialPoint()[Y]);
454     }
456     Curve* transformed(Matrix const & m) const
457     {
458         Point ip = initialPoint() * m;
459         Point ep = finalPoint() * m;
460         if (ip[X] == ep[X]) {
461             return new VLineSegment(ip[X], ip[Y], ep[Y]);
462         } else {
463             return new LineSegment(ip, ep);
464         }
465     }
467     Curve* derivative() const
468     {
469         double y = finalPoint()[Y] - initialPoint()[Y];
470         return new VLineSegment(0, y, y);
471     }
473     Point pointAt(double t) const
474     {
475         if ( t < 0 || t > 1 )
476             THROW_RANGEERROR("domain parameter out of range");
477         double y = initialPoint()[Y] + t * (finalPoint()[Y] - initialPoint()[Y]);
478         return Point(initialPoint()[X], y);
479     }
481     double valueAt(double t, Dim2 d) const
482     {
483         if (d < 0 || d > 1)
484         {
485             THROW_RANGEERROR("dimension argument out of range");
486         }
487         if ( t < 0 || t > 1 )
488             THROW_RANGEERROR("domain parameter out of range");
490         if (d == X) return initialPoint()[X];
492         return initialPoint()[Y] + t * (finalPoint()[Y] - initialPoint()[Y]);
493     }
495     std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const
496     {
497         std::vector<Point> result;
498         result.push_back(pointAt(t));
499         if (n > 0)
500         {
501             double y = finalPoint()[Y] - initialPoint()[Y];
502             result.push_back( Point(0, y) );
503         }
504         if (n > 1)
505         {
506             /* higher order derivatives are zero,
507              * so the other n-1 vector elements are (0,0) */
508             result.insert( result.end(), n-1, Point(0, 0) );
509         }
510         return result;
511     }
513     D2<SBasis> toSBasis() const
514     {
515         return m_line_seg.toSBasis();
516     }
518   private:
519     LineSegment m_line_seg;
521 }; // end class VLineSegment
525 }  // end namespace Geom
528 #endif // _2GEOM_HVLINESEGMENT_H_
531 /*
532   Local Variables:
533   mode:c++
534   c-file-style:"stroustrup"
535   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
536   indent-tabs-mode:nil
537   fill-column:99
538   End:
539 */
540 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :