1 /***************************************************************************
2                          qgslinesegment.h
3                          -----------------
4     begin                : April 2018
5     copyright            : (C) 2018 by Nyall Dawson
6     email                : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef QGSLINESEGMENT_H
19 #define QGSLINESEGMENT_H
20 
21 #include "qgis_core.h"
22 #include "qgspointxy.h"
23 
24 class QgsLineString;
25 
26 /**
27  * \ingroup core
28  * \brief Represents a single 2D line segment, consisting of a 2D start and end vertex only.
29  * \since QGIS 3.2
30  */
31 class CORE_EXPORT QgsLineSegment2D
32 {
33 
34   public:
35 
36     /**
37      * Constructor for a QgsLineSegment2D from the specified \a start point to
38      * the \a end point.
39      */
QgsLineSegment2D(const QgsPointXY & start,const QgsPointXY & end)40     QgsLineSegment2D( const QgsPointXY &start, const QgsPointXY &end ) SIP_HOLDGIL
41   : mStart( start )
42     , mEnd( end )
43     {}
44 
45     /**
46      * Constructor for a QgsLineSegment2D from the point (\a x1, \a y2) to
47      * (\a x2, \a y2).
48      */
QgsLineSegment2D(double x1,double y1,double x2,double y2)49     QgsLineSegment2D( double x1, double y1, double x2, double y2 ) SIP_HOLDGIL
50   : mStart( QgsPointXY( x1, y1 ) )
51     , mEnd( QgsPointXY( x2, y2 ) )
52     {}
53 
54     /**
55      * Returns the length of the segment.
56      * \see lengthSquared()
57      */
length()58     double length() const SIP_HOLDGIL
59     {
60       return std::sqrt( ( mStart.x() - mEnd.x() ) * ( mStart.x() - mEnd.x() ) + ( mStart.y() - mEnd.y() ) * ( mStart.y() - mEnd.y() ) );
61     }
62 
63     /**
64      * Returns the squared length of the segment.
65      * \see length()
66      */
lengthSquared()67     double lengthSquared() const SIP_HOLDGIL
68     {
69       return ( mStart.x() - mEnd.x() ) * ( mStart.x() - mEnd.x() ) + ( mStart.y() - mEnd.y() ) * ( mStart.y() - mEnd.y() );
70     }
71 
72     /**
73      * Returns the segment's start x-coordinate.
74      * \see start()
75      * \see startY()
76      */
startX()77     double startX() const SIP_HOLDGIL
78     {
79       return mStart.x();
80     }
81 
82     /**
83      * Returns the segment's start y-coordinate.
84      * \see start()
85      * \see startX()
86      */
startY()87     double startY() const SIP_HOLDGIL
88     {
89       return mStart.y();
90     }
91 
92     /**
93      * Returns the segment's end x-coordinate.
94      * \see end()
95      * \see endY()
96      */
endX()97     double endX() const SIP_HOLDGIL
98     {
99       return mEnd.x();
100     }
101 
102     /**
103      * Returns the segment's end y-coordinate.
104      * \see end()
105      * \see endX()
106      */
endY()107     double endY() const SIP_HOLDGIL
108     {
109       return mEnd.y();
110     }
111 
112     /**
113      * Returns the segment's start point.
114      * \see end()
115      * \see startX()
116      * \see startY()
117      */
start()118     QgsPointXY start() const SIP_HOLDGIL
119     {
120       return mStart;
121     }
122 
123     /**
124      * Returns the segment's end point.
125      * \see start()
126      * \see endX()
127      * \see endY()
128      */
end()129     QgsPointXY end() const SIP_HOLDGIL
130     {
131       return mEnd;
132     }
133 
134     /**
135      * Sets the segment's start \a x coordinate.
136      * \see setEndX()
137      * \see setStart()
138      * \see setStartY()
139      */
setStartX(double x)140     void setStartX( double x ) SIP_HOLDGIL
141     {
142       mStart.setX( x );
143     }
144 
145     /**
146      * Sets the segment's start \a y coordinate.
147      * \see setEndY()
148      * \see setStart()
149      * \see setStartX()
150      */
setStartY(double y)151     void setStartY( double y ) SIP_HOLDGIL
152     {
153       mStart.setY( y );
154     }
155 
156     /**
157      * Sets the segment's end \a x coordinate.
158      * \see setStartX()
159      * \see setEnd()
160      * \see setEndY()
161      */
setEndX(double x)162     void setEndX( double x ) SIP_HOLDGIL
163     {
164       mEnd.setX( x );
165     }
166 
167     /**
168      * Sets the segment's end \a y coordinate.
169      * \see setStartY()
170      * \see setEnd()
171      * \see setEndX()
172      */
setEndY(double y)173     void setEndY( double y ) SIP_HOLDGIL
174     {
175       mEnd.setY( y );
176     }
177 
178     /**
179      * Sets the segment's \a start point.
180      * \see setStartX()
181      * \see setStartY()
182      * \see setEnd()
183      */
setStart(const QgsPointXY & start)184     void setStart( const QgsPointXY &start ) SIP_HOLDGIL
185     {
186       mStart = start;
187     }
188 
189     /**
190      * Sets the segment's \a end point.
191      * \see setEndX()
192      * \see setEndY()
193      * \see setStart()
194      */
setEnd(const QgsPointXY & end)195     void setEnd( const QgsPointXY &end ) SIP_HOLDGIL
196     {
197       mEnd = end;
198     }
199 
200     /**
201      * Tests if a \a point is to the left of the line segment.
202      *
203      * Returns -1 if the point falls to the left of the line, or +1 if the point
204      * is to the right.
205      *
206      * If the return value is 0, then the test was unsuccessful (e.g. due to testing a point exactly
207      * on the line, or exactly in line with the segment) and the result is undefined.
208      *
209      * \see QgsGeometryUtils::leftOfLine()
210      */
211     int pointLeftOfLine( const QgsPointXY &point ) const SIP_HOLDGIL;
212 
213     /**
214      * Reverses the line segment, so that the start and end points are flipped.
215      */
reverse()216     void reverse() SIP_HOLDGIL
217     {
218       std::swap( mStart, mEnd );
219     }
220 
221     // TODO c++20 - replace with = default
222 
223     //! Equality operator
224     bool operator==( const QgsLineSegment2D &other ) const SIP_HOLDGIL
225     {
226       return mStart == other.mStart && mEnd == other.mEnd;
227     }
228 
229     //! Inequality operator
230     bool operator!=( const QgsLineSegment2D &other ) const SIP_HOLDGIL
231     {
232       return mStart != other.mStart || mEnd != other.mEnd;
233     }
234 
235   private:
236 
237     QgsPointXY mStart;
238     QgsPointXY mEnd;
239 
240 };
241 
242 #endif // QGSLINESEGMENT_H
243