1 /*************************************************************************** 2 qgscircle.h 3 -------------- 4 begin : March 2017 5 copyright : (C) 2017 by Loîc Bartoletti 6 email : lbartoletti at tuxfamily dot org 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 QGSCIRCLE_H 19 #define QGSCIRCLE_H 20 21 #include <QString> 22 23 #include "qgis_core.h" 24 #include "qgsellipse.h" 25 #include "qgspolygon.h" 26 #include "qgsrectangle.h" 27 #include "qgscircularstring.h" 28 29 30 class QgsPoint; 31 32 /** 33 * \ingroup core 34 * \class QgsCircle 35 * \brief Circle geometry type. 36 * 37 * A circle is defined by a center point with a radius and an azimuth. 38 * The azimuth is the north angle to the semi-major axis, in degrees. By default, the semi-major axis is oriented to the north (0 degrees). 39 * \since QGIS 3.0 40 */ 41 42 43 class CORE_EXPORT QgsCircle : public QgsEllipse 44 { 45 public: 46 QgsCircle(); 47 48 /** 49 * Constructs a circle by defining all the members. 50 * \param center The center of the circle. 51 * \param radius The radius of the circle. 52 * \param azimuth Angle in degrees started from the North to the first quadrant. 53 */ 54 QgsCircle( const QgsPoint ¢er, double radius, double azimuth = 0 ) SIP_HOLDGIL; 55 56 /** 57 * Constructs a circle by 2 points on the circle. 58 * The center point can have m value which is the result from the midpoint 59 * operation between \a pt1 and \a pt2. Z dimension is also supported and 60 * is retrieved from the first 3D point amongst \a pt1 and \a pt2. 61 * The radius is calculated from the 2D distance between \a pt1 and \a pt2. 62 * The azimuth is the angle between \a pt1 and \a pt2. 63 * \param pt1 First point. 64 * \param pt2 Second point. 65 */ 66 static QgsCircle from2Points( const QgsPoint &pt1, const QgsPoint &pt2 ) SIP_HOLDGIL; 67 68 /** 69 * Constructs a circle by 3 points on the circle. 70 * M value is dropped for the center point. 71 * Z dimension is supported and is retrieved from the first 3D point 72 * amongst \a pt1, \a pt2 and \a pt3. 73 * The azimuth always takes the default value. 74 * If the points are colinear an empty circle is returned. 75 * \param pt1 First point. 76 * \param pt2 Second point. 77 * \param pt3 Third point. 78 * \param epsilon Value used to compare point. 79 */ 80 static QgsCircle from3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon = 1E-8 ) SIP_HOLDGIL; 81 82 /** 83 * Constructs a circle by a center point and a diameter. 84 * The center point keeps z and m values from \a center. 85 * \param center Center point. 86 * \param diameter Diameter of the circle. 87 * \param azimuth Azimuth of the circle. 88 */ 89 static QgsCircle fromCenterDiameter( const QgsPoint ¢er, double diameter, double azimuth = 0 ) SIP_HOLDGIL; 90 91 92 /** 93 * Constructs a circle by a center point and another point. 94 * The center point keeps z and m values from \a center. 95 * Axes are calculated from the 2D distance between \a center and \a pt1. 96 * The azimuth is the angle between \a center and \a pt1. 97 * \param center Center point. 98 * \param pt1 A point on the circle. 99 */ 100 static QgsCircle fromCenterPoint( const QgsPoint ¢er, const QgsPoint &pt1 ) SIP_HOLDGIL; 101 102 103 /** 104 * Constructs a circle by 3 tangents on the circle (aka inscribed circle of a triangle). 105 * Z and m values are dropped for the center point. 106 * The azimuth always takes the default value. 107 * \param pt1_tg1 First point of the first tangent. 108 * \param pt2_tg1 Second point of the first tangent. 109 * \param pt1_tg2 First point of the second tangent. 110 * \param pt2_tg2 Second point of the second tangent. 111 * \param pt1_tg3 First point of the third tangent. 112 * \param pt2_tg3 Second point of the third tangent. 113 * \param epsilon Value used to compare point. 114 */ 115 static QgsCircle from3Tangents( const QgsPoint &pt1_tg1, const QgsPoint &pt2_tg1, 116 const QgsPoint &pt1_tg2, const QgsPoint &pt2_tg2, 117 const QgsPoint &pt1_tg3, const QgsPoint &pt2_tg3, double epsilon = 1E-8 ) SIP_HOLDGIL; 118 119 /** 120 * Constructs a circle by an extent (aka bounding box / QgsRectangle). 121 * The center point can have m value which is the result from the midpoint 122 * operation between \a pt1 and \a pt2. Z dimension is also supported and 123 * is retrieved from the first 3D point amongst \a pt1 and \a pt2. 124 * Axes are calculated from the 2D distance between \a pt1 and \a pt2. 125 * The azimuth always takes the default value. 126 * \param pt1 First corner. 127 * \param pt2 Second corner. 128 */ 129 static QgsCircle fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 ) SIP_HOLDGIL; 130 131 /** 132 * Constructs the smallest circle from 3 points. 133 * Z and m values are dropped for the center point. 134 * The azimuth always takes the default value. 135 * If the points are colinear an empty circle is returned. 136 * \param pt1 First point. 137 * \param pt2 Second point. 138 * \param pt3 Third point. 139 * \param epsilon Value used to compare point. 140 */ 141 static QgsCircle minimalCircleFrom3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon = 1E-8 ) SIP_HOLDGIL; 142 143 /** 144 * Calculates the intersections points between this circle and an \a other circle. 145 * 146 * If found, the intersection points will be stored in \a intersection1 and \a intersection2. 147 * 148 * By default this method does not consider any z values and instead treats the circles as 2-dimensional. 149 * If \a useZ is set to TRUE, then an intersection will only occur if the z values of both circles are 150 * equal. In this case the points returned for \a intersection1 and \a intersection2 will contain 151 * the z value of the circle intersections. 152 * 153 * \returns number of intersection points found. 154 * 155 * \since QGIS 3.2 156 */ 157 int intersections( const QgsCircle &other, QgsPoint &intersection1 SIP_OUT, QgsPoint &intersection2 SIP_OUT, bool useZ = false ) const; 158 159 /** 160 * Calculates the tangent points between this circle and the point \a p. 161 * 162 * If found, the tangent points will be stored in \a pt1 and \a pt2. 163 * 164 * Note that this method is 2D only and does not consider the z-value of the circle. 165 * 166 * \returns TRUE if tangent was found. 167 * 168 * 169 * \see outerTangents() and innerTangents() 170 * \since QGIS 3.2 171 */ 172 bool tangentToPoint( const QgsPointXY &p, QgsPointXY &pt1 SIP_OUT, QgsPointXY &pt2 SIP_OUT ) const; 173 174 /** 175 * Calculates the outer tangent points between this circle 176 * and an \a other circle. 177 * 178 * The outer tangent points correspond to the points at which the two lines 179 * which are drawn so that they are tangential to both circles touch 180 * the circles. 181 * 182 * The first tangent line is described by the points 183 * stored in \a line1P1 and \a line1P2, 184 * and the second line is described by the points stored in \a line2P1 185 * and \a line2P2. 186 * 187 * Returns the number of tangents (either 0 or 2). 188 * 189 * Note that this method is 2D only and does not consider the z-value of the circle. 190 * 191 * 192 * \see tangentToPoint() and innerTangents() 193 * \since QGIS 3.2 194 */ 195 int outerTangents( const QgsCircle &other, 196 QgsPointXY &line1P1 SIP_OUT, QgsPointXY &line1P2 SIP_OUT, 197 QgsPointXY &line2P1 SIP_OUT, QgsPointXY &line2P2 SIP_OUT ) const; 198 199 /** 200 * Calculates the inner tangent points between this circle 201 * and an \a other circle. 202 * 203 * The inner tangent points correspond to the points at which the two lines 204 * which are drawn so that they are tangential to both circles but on 205 * different sides, touching the circles and crossing each other. 206 * 207 * The first tangent line is described by the points 208 * stored in \a line1P1 and \a line1P2, 209 * and the second line is described by the points stored in \a line2P1 210 * and \a line2P2. 211 * 212 * Returns the number of tangents (either 0 or 2). 213 * 214 * Note that this method is 2D only and does not consider the z-value of the circle. 215 * 216 * 217 * \see tangentToPoint() and outerTangents() 218 * \since QGIS 3.6 219 */ 220 int innerTangents( const QgsCircle &other, 221 QgsPointXY &line1P1 SIP_OUT, QgsPointXY &line1P2 SIP_OUT, 222 QgsPointXY &line2P1 SIP_OUT, QgsPointXY &line2P2 SIP_OUT ) const; 223 224 double area() const override SIP_HOLDGIL; 225 double perimeter() const override SIP_HOLDGIL; 226 227 //inherited 228 // void setAzimuth(const double azimuth); 229 // double azimuth() const {return mAzimuth; } 230 231 232 /** 233 * Inherited method. Use setRadius instead. 234 * \see radius() 235 * \see setRadius() 236 */ 237 void setSemiMajorAxis( double semiMajorAxis ) override SIP_HOLDGIL; 238 239 /** 240 * Inherited method. Use setRadius instead. 241 * \see radius() 242 * \see setRadius() 243 */ 244 void setSemiMinorAxis( double semiMinorAxis ) override SIP_HOLDGIL; 245 246 //! Returns the radius of the circle radius()247 double radius() const SIP_HOLDGIL {return mSemiMajorAxis;} 248 //! Sets the radius of the circle setRadius(double radius)249 void setRadius( double radius ) SIP_HOLDGIL 250 { 251 mSemiMajorAxis = std::fabs( radius ); 252 mSemiMinorAxis = mSemiMajorAxis; 253 } 254 255 /** 256 * The four quadrants of the ellipse. 257 * They are oriented and started from North. 258 * \return quadrants defined by four points. 259 * \see quadrant() 260 */ 261 QVector<QgsPoint> northQuadrant() const SIP_FACTORY; 262 263 /** 264 * Returns a circular string from the circle. 265 * \param oriented If oriented is TRUE the start point is from azimuth instead from north. 266 */ 267 QgsCircularString *toCircularString( bool oriented = false ) const; 268 269 //! Returns TRUE if the circle contains the \a point. 270 bool contains( const QgsPoint &point, double epsilon = 1E-8 ) const; 271 272 QgsRectangle boundingBox() const override; 273 274 QString toString( int pointPrecision = 17, int radiusPrecision = 17, int azimuthPrecision = 2 ) const override; 275 276 #ifdef SIP_RUN 277 SIP_PYOBJECT __repr__(); 278 % MethodCode 279 QString str = QStringLiteral( "<QgsCircle: %1>" ).arg( sipCpp->toString() ); 280 sipRes = PyUnicode_FromString( str.toUtf8().constData() ); 281 % End 282 #endif 283 }; 284 285 #endif // QGSCIRCLE_H 286