Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgscircle.cpp
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 : : #include "qgscircle.h"
19 : : #include "qgslinestring.h"
20 : : #include "qgsgeometryutils.h"
21 : : #include "qgstriangle.h"
22 : :
23 : : #include <memory>
24 : :
25 : 143 : QgsCircle::QgsCircle() :
26 : 143 : QgsEllipse( QgsPoint(), 0.0, 0.0, 0.0 )
27 : 143 : {
28 : :
29 : 143 : }
30 : :
31 : 152 : QgsCircle::QgsCircle( const QgsPoint ¢er, double radius, double azimuth ) :
32 : 152 : QgsEllipse( center, radius, radius, azimuth )
33 : 304 : {
34 : :
35 : 152 : }
36 : :
37 : 15 : QgsCircle QgsCircle::from2Points( const QgsPoint &pt1, const QgsPoint &pt2 )
38 : : {
39 : 15 : QgsPoint center = QgsGeometryUtils::midpoint( pt1, pt2 );
40 : 15 : double azimuth = QgsGeometryUtils::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() ) * 180.0 / M_PI;
41 : 15 : double radius = pt1.distance( pt2 ) / 2.0;
42 : :
43 : 15 : QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, center );
44 : :
45 : 15 : return QgsCircle( center, radius, azimuth );
46 : 15 : }
47 : :
48 : 12 : static bool isPerpendicular( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
49 : : {
50 : : // check the given point are perpendicular to x or y axis
51 : :
52 : 12 : double yDelta_a = pt2.y() - pt1.y();
53 : 12 : double xDelta_a = pt2.x() - pt1.x();
54 : 12 : double yDelta_b = pt3.y() - pt2.y();
55 : 12 : double xDelta_b = pt3.x() - pt2.x();
56 : :
57 : 12 : if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) )
58 : : {
59 : 0 : return false;
60 : : }
61 : :
62 : 12 : if ( std::fabs( yDelta_a ) <= epsilon )
63 : : {
64 : 7 : return true;
65 : : }
66 : 5 : else if ( std::fabs( yDelta_b ) <= epsilon )
67 : : {
68 : 2 : return true;
69 : : }
70 : 3 : else if ( std::fabs( xDelta_a ) <= epsilon )
71 : : {
72 : 0 : return true;
73 : : }
74 : 3 : else if ( std::fabs( xDelta_b ) <= epsilon )
75 : : {
76 : 0 : return true;
77 : : }
78 : :
79 : 3 : return false;
80 : :
81 : 12 : }
82 : :
83 : 4 : QgsCircle QgsCircle::from3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
84 : : {
85 : 4 : QgsPoint p1, p2, p3;
86 : :
87 : 4 : if ( !isPerpendicular( pt1, pt2, pt3, epsilon ) )
88 : : {
89 : 1 : p1 = pt1;
90 : 1 : p2 = pt2;
91 : 1 : p3 = pt3;
92 : 1 : }
93 : 3 : else if ( !isPerpendicular( pt1, pt3, pt2, epsilon ) )
94 : : {
95 : 1 : p1 = pt1;
96 : 1 : p2 = pt3;
97 : 1 : p3 = pt2;
98 : 1 : }
99 : 2 : else if ( !isPerpendicular( pt2, pt1, pt3, epsilon ) )
100 : : {
101 : 1 : p1 = pt2;
102 : 1 : p2 = pt1;
103 : 1 : p3 = pt3;
104 : 1 : }
105 : 1 : else if ( !isPerpendicular( pt2, pt3, pt1, epsilon ) )
106 : : {
107 : 0 : p1 = pt2;
108 : 0 : p2 = pt3;
109 : 0 : p3 = pt1;
110 : 0 : }
111 : 1 : else if ( !isPerpendicular( pt3, pt2, pt1, epsilon ) )
112 : : {
113 : 0 : p1 = pt3;
114 : 0 : p2 = pt2;
115 : 0 : p3 = pt1;
116 : 0 : }
117 : 1 : else if ( !isPerpendicular( pt3, pt1, pt2, epsilon ) )
118 : : {
119 : 0 : p1 = pt3;
120 : 0 : p2 = pt1;
121 : 0 : p3 = pt2;
122 : 0 : }
123 : : else
124 : : {
125 : 1 : return QgsCircle();
126 : : }
127 : 3 : QgsPoint center = QgsPoint();
128 : 3 : double radius = -0.0;
129 : : // Paul Bourke's algorithm
130 : 3 : double yDelta_a = p2.y() - p1.y();
131 : 3 : double xDelta_a = p2.x() - p1.x();
132 : 3 : double yDelta_b = p3.y() - p2.y();
133 : 3 : double xDelta_b = p3.x() - p2.x();
134 : :
135 : 3 : if ( qgsDoubleNear( xDelta_a, 0.0, epsilon ) || qgsDoubleNear( xDelta_b, 0.0, epsilon ) )
136 : : {
137 : 0 : return QgsCircle();
138 : : }
139 : :
140 : 3 : double aSlope = yDelta_a / xDelta_a;
141 : 3 : double bSlope = yDelta_b / xDelta_b;
142 : :
143 : : // set z coordinate for center
144 : 3 : QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << p1 << p2 << p3, center );
145 : :
146 : 3 : if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) )
147 : : {
148 : 0 : center.setX( 0.5 * ( p2.x() + p3.x() ) );
149 : 0 : center.setY( 0.5 * ( p1.y() + p2.y() ) );
150 : 0 : radius = center.distance( pt1 );
151 : :
152 : 0 : return QgsCircle( center, radius );
153 : : }
154 : :
155 : 3 : if ( std::fabs( aSlope - bSlope ) <= epsilon )
156 : : {
157 : 0 : return QgsCircle();
158 : : }
159 : :
160 : 3 : center.setX(
161 : 6 : ( aSlope * bSlope * ( p1.y() - p3.y() ) +
162 : 6 : bSlope * ( p1.x() + p2.x() ) -
163 : 3 : aSlope * ( p2.x() + p3.x() ) ) /
164 : 3 : ( 2.0 * ( bSlope - aSlope ) )
165 : : );
166 : 3 : center.setY(
167 : 3 : -1.0 * ( center.x() - ( p1.x() + p2.x() ) / 2.0 ) /
168 : 6 : aSlope + ( p1.y() + p2.y() ) / 2.0
169 : : );
170 : :
171 : 3 : radius = center.distance( p1 );
172 : :
173 : 3 : return QgsCircle( center, radius );
174 : 4 : }
175 : :
176 : 3 : QgsCircle QgsCircle::fromCenterDiameter( const QgsPoint ¢er, double diameter, double azimuth )
177 : : {
178 : 3 : return QgsCircle( center, diameter / 2.0, azimuth );
179 : : }
180 : :
181 : 3 : QgsCircle QgsCircle::fromCenterPoint( const QgsPoint ¢er, const QgsPoint &pt1 )
182 : : {
183 : 3 : double azimuth = QgsGeometryUtils::lineAngle( center.x(), center.y(), pt1.x(), pt1.y() ) * 180.0 / M_PI;
184 : :
185 : 3 : QgsPoint centerPt( center );
186 : 3 : QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << center << pt1, centerPt );
187 : :
188 : 3 : return QgsCircle( centerPt, centerPt.distance( pt1 ), azimuth );
189 : 3 : }
190 : :
191 : 9 : static QVector<QgsCircle> from2ParallelsLine( const QgsPoint &pt1_par1, const QgsPoint &pt2_par1, const QgsPoint &pt1_par2, const QgsPoint &pt2_par2, const QgsPoint &pt1_line1, const QgsPoint &pt2_line1, QgsPoint pos, double epsilon )
192 : : {
193 : 9 : const double radius = QgsGeometryUtils::perpendicularSegment( pt1_par2, pt1_par1, pt2_par1 ).length() / 2.0;
194 : :
195 : : bool isInter;
196 : 9 : QgsPoint ptInter;
197 : 9 : QVector<QgsCircle> circles;
198 : :
199 : 9 : QgsPoint ptInter_par1line1, ptInter_par2line1;
200 : : double angle1, angle2;
201 : : double x, y;
202 : 9 : QgsGeometryUtils::angleBisector( pt1_par1.x(), pt1_par1.y(), pt2_par1.x(), pt2_par1.y(), pt1_line1.x(), pt1_line1.y(), pt2_line1.x(), pt2_line1.y(), x, y, angle1 );
203 : 9 : ptInter_par1line1.setX( x );
204 : 9 : ptInter_par1line1.setY( y );
205 : :
206 : 9 : QgsGeometryUtils::angleBisector( pt1_par2.x(), pt1_par2.y(), pt2_par2.x(), pt2_par2.y(), pt1_line1.x(), pt1_line1.y(), pt2_line1.x(), pt2_line1.y(), x, y, angle2 );
207 : 9 : ptInter_par2line1.setX( x );
208 : 9 : ptInter_par2line1.setY( y );
209 : :
210 : 9 : QgsPoint center;
211 : 9 : QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 ), center, isInter, epsilon, true );
212 : 9 : if ( isInter )
213 : : {
214 : 1 : if ( !pos.isEmpty() )
215 : : {
216 : 0 : if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
217 : : {
218 : 0 : circles.append( QgsCircle( center, radius ) );
219 : 0 : }
220 : 0 : }
221 : : else
222 : : {
223 : 1 : circles.append( QgsCircle( center, radius ) );
224 : : }
225 : 1 : }
226 : :
227 : 9 : QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 + 90.0 ), center, isInter, epsilon, true );
228 : 9 : if ( isInter )
229 : : {
230 : 9 : if ( !pos.isEmpty() )
231 : : {
232 : 4 : if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
233 : : {
234 : 2 : circles.append( QgsCircle( center, radius ) );
235 : 2 : }
236 : 4 : }
237 : : else
238 : : {
239 : 5 : circles.append( QgsCircle( center, radius ) );
240 : : }
241 : 9 : }
242 : :
243 : 9 : QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 + 90.0 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 ), center, isInter, epsilon, true );
244 : 9 : if ( isInter && !circles.contains( QgsCircle( center, radius ) ) )
245 : : {
246 : 8 : if ( !pos.isEmpty() )
247 : : {
248 : 4 : if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
249 : : {
250 : 2 : circles.append( QgsCircle( center, radius ) );
251 : 2 : }
252 : 4 : }
253 : : else
254 : : {
255 : 4 : circles.append( QgsCircle( center, radius ) );
256 : : }
257 : 8 : }
258 : 9 : QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 + 90.0 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 + 90.0 ), center, isInter, epsilon, true );
259 : 9 : if ( isInter && !circles.contains( QgsCircle( center, radius ) ) )
260 : : {
261 : 0 : if ( !pos.isEmpty() )
262 : : {
263 : 0 : if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
264 : : {
265 : 0 : circles.append( QgsCircle( center, radius ) );
266 : 0 : }
267 : 0 : }
268 : : else
269 : : {
270 : 0 : circles.append( QgsCircle( center, radius ) );
271 : : }
272 : 0 : }
273 : :
274 : 9 : return circles;
275 : 9 : }
276 : :
277 : 12 : QVector<QgsCircle> QgsCircle::from3TangentsMulti( const QgsPoint &pt1_tg1, const QgsPoint &pt2_tg1, const QgsPoint &pt1_tg2, const QgsPoint &pt2_tg2, const QgsPoint &pt1_tg3, const QgsPoint &pt2_tg3, double epsilon, QgsPoint pos )
278 : : {
279 : 12 : QgsPoint p1, p2, p3;
280 : 12 : bool isIntersect_tg1tg2 = false;
281 : 12 : bool isIntersect_tg1tg3 = false;
282 : 12 : bool isIntersect_tg2tg3 = false;
283 : 12 : QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, isIntersect_tg1tg2, epsilon );
284 : 12 : QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, isIntersect_tg1tg3, epsilon );
285 : 12 : QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, isIntersect_tg2tg3, epsilon );
286 : :
287 : 12 : QVector<QgsCircle> circles;
288 : 12 : if ( !isIntersect_tg1tg2 && !isIntersect_tg2tg3 ) // three lines are parallels
289 : 1 : return circles;
290 : :
291 : 11 : if ( !isIntersect_tg1tg2 )
292 : 7 : return from2ParallelsLine( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, pos, epsilon );
293 : 4 : else if ( !isIntersect_tg1tg3 )
294 : 1 : return from2ParallelsLine( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, pt1_tg2, pt2_tg2, pos, epsilon );
295 : 3 : else if ( !isIntersect_tg2tg3 )
296 : 1 : return from2ParallelsLine( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, pt1_tg1, pt1_tg1, pos, epsilon );
297 : :
298 : 2 : if ( p1.is3D() )
299 : : {
300 : 1 : p1.convertTo( QgsWkbTypes::dropZ( p1.wkbType() ) );
301 : 1 : }
302 : :
303 : 2 : if ( p2.is3D() )
304 : : {
305 : 1 : p2.convertTo( QgsWkbTypes::dropZ( p2.wkbType() ) );
306 : 1 : }
307 : :
308 : 2 : if ( p3.is3D() )
309 : : {
310 : 1 : p3.convertTo( QgsWkbTypes::dropZ( p3.wkbType() ) );
311 : 1 : }
312 : :
313 : 2 : circles.append( QgsTriangle( p1, p2, p3 ).inscribedCircle() );
314 : 2 : return circles;
315 : 12 : }
316 : :
317 : 8 : QgsCircle QgsCircle::from3Tangents( const QgsPoint &pt1_tg1, const QgsPoint &pt2_tg1, const QgsPoint &pt1_tg2, const QgsPoint &pt2_tg2, const QgsPoint &pt1_tg3, const QgsPoint &pt2_tg3, double epsilon, QgsPoint pos )
318 : : {
319 : 8 : const QVector<QgsCircle> circles = from3TangentsMulti( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, epsilon, pos );
320 : 8 : if ( circles.length() != 1 )
321 : 4 : return QgsCircle();
322 : 4 : return circles.at( 0 );
323 : 8 : }
324 : :
325 : 3 : QgsCircle QgsCircle::minimalCircleFrom3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
326 : : {
327 : 3 : double l1 = pt2.distance( pt3 );
328 : 3 : double l2 = pt3.distance( pt1 );
329 : 3 : double l3 = pt1.distance( pt2 );
330 : :
331 : 3 : if ( ( l1 * l1 ) - ( l2 * l2 + l3 * l3 ) >= epsilon )
332 : 0 : return QgsCircle().from2Points( pt2, pt3 );
333 : 3 : else if ( ( l2 * l2 ) - ( l1 * l1 + l3 * l3 ) >= epsilon )
334 : 0 : return QgsCircle().from2Points( pt3, pt1 );
335 : 3 : else if ( ( l3 * l3 ) - ( l1 * l1 + l2 * l2 ) >= epsilon )
336 : 1 : return QgsCircle().from2Points( pt1, pt2 );
337 : : else
338 : 2 : return QgsCircle().from3Points( pt1, pt2, pt3, epsilon );
339 : 3 : }
340 : :
341 : 6 : int QgsCircle::intersections( const QgsCircle &other, QgsPoint &intersection1, QgsPoint &intersection2, bool useZ ) const
342 : : {
343 : 6 : if ( useZ && mCenter.is3D() && other.center().is3D() && !qgsDoubleNear( mCenter.z(), other.center().z() ) )
344 : 1 : return 0;
345 : :
346 : 5 : QgsPointXY int1, int2;
347 : :
348 : 10 : int res = QgsGeometryUtils::circleCircleIntersections( QgsPointXY( mCenter ), radius(),
349 : 5 : QgsPointXY( other.center() ), other.radius(),
350 : : int1, int2 );
351 : 5 : if ( res == 0 )
352 : 2 : return 0;
353 : :
354 : 3 : intersection1 = QgsPoint( int1 );
355 : 3 : intersection2 = QgsPoint( int2 );
356 : 3 : if ( useZ && mCenter.is3D() )
357 : : {
358 : 1 : intersection1.addZValue( mCenter.z() );
359 : 1 : intersection2.addZValue( mCenter.z() );
360 : 1 : }
361 : 3 : return res;
362 : 6 : }
363 : :
364 : 2 : bool QgsCircle::tangentToPoint( const QgsPointXY &p, QgsPointXY &pt1, QgsPointXY &pt2 ) const
365 : : {
366 : 2 : return QgsGeometryUtils::tangentPointAndCircle( QgsPointXY( mCenter ), radius(), p, pt1, pt2 );
367 : : }
368 : :
369 : 2 : int QgsCircle::outerTangents( const QgsCircle &other, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2 ) const
370 : : {
371 : 4 : return QgsGeometryUtils::circleCircleOuterTangents( QgsPointXY( mCenter ), radius(),
372 : 2 : QgsPointXY( other.center() ), other.radius(), line1P1, line1P2, line2P1, line2P2 );
373 : 0 : }
374 : :
375 : 4 : int QgsCircle::innerTangents( const QgsCircle &other, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2 ) const
376 : : {
377 : 8 : return QgsGeometryUtils::circleCircleInnerTangents( QgsPointXY( mCenter ), radius(),
378 : 4 : QgsPointXY( other.center() ), other.radius(), line1P1, line1P2, line2P1, line2P2 );
379 : 0 : }
380 : :
381 : 2 : QgsCircle QgsCircle::fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 )
382 : : {
383 : 2 : double delta_x = std::fabs( pt1.x() - pt2.x() );
384 : 2 : double delta_y = std::fabs( pt1.x() - pt2.y() );
385 : 2 : if ( !qgsDoubleNear( delta_x, delta_y ) )
386 : : {
387 : 1 : return QgsCircle();
388 : : }
389 : :
390 : 1 : QgsPoint center = QgsGeometryUtils::midpoint( pt1, pt2 );
391 : 1 : QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, center );
392 : :
393 : 1 : return QgsCircle( center, delta_x / 2.0, 0 );
394 : 2 : }
395 : :
396 : 2 : double QgsCircle::area() const
397 : : {
398 : 2 : return M_PI * mSemiMajorAxis * mSemiMajorAxis;
399 : : }
400 : :
401 : 2 : double QgsCircle::perimeter() const
402 : : {
403 : 2 : return 2.0 * M_PI * mSemiMajorAxis;
404 : : }
405 : :
406 : 1 : void QgsCircle::setSemiMajorAxis( const double semiMajorAxis )
407 : : {
408 : 1 : mSemiMajorAxis = std::fabs( semiMajorAxis );
409 : 1 : mSemiMinorAxis = mSemiMajorAxis;
410 : 1 : }
411 : :
412 : 1 : void QgsCircle::setSemiMinorAxis( const double semiMinorAxis )
413 : : {
414 : 1 : mSemiMajorAxis = std::fabs( semiMinorAxis );
415 : 1 : mSemiMinorAxis = mSemiMajorAxis;
416 : 1 : }
417 : :
418 : 10 : QVector<QgsPoint> QgsCircle::northQuadrant() const
419 : : {
420 : 10 : QVector<QgsPoint> quad;
421 : 10 : quad.append( QgsPoint( mCenter.x(), mCenter.y() + mSemiMajorAxis, mCenter.z() ) );
422 : 10 : quad.append( QgsPoint( mCenter.x() + mSemiMajorAxis, mCenter.y(), mCenter.z() ) );
423 : 10 : quad.append( QgsPoint( mCenter.x(), mCenter.y() - mSemiMajorAxis, mCenter.z() ) );
424 : 10 : quad.append( QgsPoint( mCenter.x() - mSemiMajorAxis, mCenter.y(), mCenter.z() ) );
425 : :
426 : 10 : return quad;
427 : 10 : }
428 : :
429 : 5 : QgsCircularString *QgsCircle::toCircularString( bool oriented ) const
430 : : {
431 : 5 : std::unique_ptr<QgsCircularString> circString( new QgsCircularString() );
432 : 5 : QgsPointSequence points;
433 : 5 : QVector<QgsPoint> quad;
434 : 5 : if ( oriented )
435 : : {
436 : 2 : quad = quadrant();
437 : 2 : }
438 : : else
439 : : {
440 : 3 : quad = northQuadrant();
441 : : }
442 : 5 : quad.append( quad.at( 0 ) );
443 : 30 : for ( QVector<QgsPoint>::const_iterator it = quad.constBegin(); it != quad.constEnd(); ++it )
444 : : {
445 : 25 : points.append( *it );
446 : 25 : }
447 : 5 : circString->setPoints( points );
448 : :
449 : 5 : return circString.release();
450 : 5 : }
451 : :
452 : 46 : bool QgsCircle::contains( const QgsPoint &point, double epsilon ) const
453 : : {
454 : 46 : return ( mCenter.distance( point ) <= mSemiMajorAxis + epsilon );
455 : : }
456 : :
457 : 2 : QgsRectangle QgsCircle::boundingBox() const
458 : : {
459 : 2 : return QgsRectangle( mCenter.x() - mSemiMajorAxis, mCenter.y() - mSemiMajorAxis, mCenter.x() + mSemiMajorAxis, mCenter.y() + mSemiMajorAxis );
460 : : }
461 : :
462 : 3 : QString QgsCircle::toString( int pointPrecision, int radiusPrecision, int azimuthPrecision ) const
463 : : {
464 : 3 : QString rep;
465 : 3 : if ( isEmpty() )
466 : 2 : rep = QStringLiteral( "Empty" );
467 : : else
468 : 6 : rep = QStringLiteral( "Circle (Center: %1, Radius: %2, Azimuth: %3)" )
469 : 2 : .arg( mCenter.asWkt( pointPrecision ), 0, 's' )
470 : 2 : .arg( qgsDoubleToString( mSemiMajorAxis, radiusPrecision ), 0, 'f' )
471 : 2 : .arg( qgsDoubleToString( mAzimuth, azimuthPrecision ), 0, 'f' );
472 : :
473 : 3 : return rep;
474 : :
475 : 3 : }
476 : :
477 : 1 : QDomElement QgsCircle::asGml2( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
478 : : {
479 : : // Gml2 does not support curve. It will be converted to a linestring via CircularString
480 : 1 : std::unique_ptr< QgsCircularString > circularString( toCircularString() );
481 : 1 : QDomElement gml = circularString->asGml2( doc, precision, ns, axisOrder );
482 : 1 : return gml;
483 : 1 : }
484 : :
485 : 1 : QDomElement QgsCircle::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
486 : : {
487 : 1 : QgsPointSequence pts;
488 : 1 : pts << northQuadrant().at( 0 ) << northQuadrant().at( 1 ) << northQuadrant().at( 2 );
489 : :
490 : 2 : QDomElement elemCircle = doc.createElementNS( ns, QStringLiteral( "Circle" ) );
491 : :
492 : 1 : if ( isEmpty() )
493 : 0 : return elemCircle;
494 : :
495 : 1 : elemCircle.appendChild( QgsGeometryUtils::pointsToGML3( pts, doc, precision, ns, mCenter.is3D(), axisOrder ) );
496 : 1 : return elemCircle;
497 : 1 : }
|