@@ -280,7 +280,7 @@ double QgsGeometryUtils::ccwAngle( double dy, double dx )
280
280
281
281
void QgsGeometryUtils::circleCenterRadius ( const QgsPointV2& pt1, const QgsPointV2& pt2, const QgsPointV2& pt3, double & radius, double & centerX, double & centerY )
282
282
{
283
- double temp, bc, cd, det ;
283
+ double dx21, dy21, dx31, dy31, h21, h31, d ;
284
284
285
285
// closed circle
286
286
if ( qgsDoubleNear ( pt1.x (), pt3.x () ) && qgsDoubleNear ( pt1.y (), pt3.y () ) )
@@ -291,22 +291,29 @@ void QgsGeometryUtils::circleCenterRadius( const QgsPointV2& pt1, const QgsPoint
291
291
return ;
292
292
}
293
293
294
- temp = pt2.x () * pt2.x () + pt2.y () * pt2.y ();
295
- bc = ( pt1.x () * pt1.x () + pt1.y () * pt1.y () - temp ) / 2.0 ;
296
- cd = ( temp - pt3.x () * pt3.x () - pt3.y () * pt3.y () ) / 2.0 ;
297
- det = ( pt1.x () - pt2.x () ) * ( pt2.y () - pt3.y () ) - ( pt2.x () - pt3.x () ) * ( pt1.y () - pt2.y () );
294
+ // Using cartesian circumcenter eguations from page https://en.wikipedia.org/wiki/Circumscribed_circle
295
+ dx21 = pt2.x () - pt1.x ();
296
+ dy21 = pt2.y () - pt1.y ();
297
+ dx31 = pt3.x () - pt1.x ();
298
+ dy31 = pt3.y () - pt1.y ();
298
299
299
- /* Check colinearity */
300
- if ( qgsDoubleNear ( fabs ( det ), 0.0 , 0.00000000001 ) )
300
+ h21 = pow ( dx21, 2.0 ) + pow ( dy21, 2.0 );
301
+ h31 = pow ( dx31, 2.0 ) + pow ( dy31, 2.0 );
302
+
303
+ // 2*Cross product, d<0 means clockwise and d>0 counterclockwise sweeping angle
304
+ d = 2 * ( dx21 * dy31 - dx31 * dy21 );
305
+
306
+ // Check colinearity, Cross product = 0
307
+ if ( qgsDoubleNear ( fabs ( d ), 0.0 , 0.00000000001 ) )
301
308
{
302
309
radius = -1.0 ;
303
310
return ;
304
311
}
305
312
306
- det = 1.0 / det;
307
- centerX = ( bc * ( pt2. y () - pt3. y () ) - cd * ( pt1. y () - pt2. y () ) ) * det ;
308
- centerY = (( pt1.x () - pt2. x () ) * cd - ( pt2. x () - pt3. x () ) * bc ) * det ;
309
- radius = sqrt (( centerX - pt1.x () ) * ( centerX - pt1. x () ) + ( centerY - pt1.y () ) * ( centerY - pt1. y () ) );
313
+ // Calculate centroid coordinates and radius
314
+ centerX = pt1. x () + ( h21 * dy31 - h31 * dy21 ) / d ;
315
+ centerY = pt1.y () - ( h21 * dx31 - h31 * dx21 ) / d ;
316
+ radius = sqrt ( pow ( centerX - pt1.x (), 2.0 ) + pow ( centerY - pt1.y (), 2.0 ) );
310
317
}
311
318
312
319
bool QgsGeometryUtils::circleClockwise ( double angle1, double angle2, double angle3 )
@@ -481,7 +488,7 @@ QList<QgsPointV2> QgsGeometryUtils::pointsFromWKT( const QString &wktCoordinateL
481
488
// first scan through for extra unexpected dimensions
482
489
bool foundZ = false ;
483
490
bool foundM = false ;
484
- Q_FOREACH ( const QString& pointCoordinates, coordList )
491
+ Q_FOREACH ( const QString& pointCoordinates, coordList )
485
492
{
486
493
QStringList coordinates = pointCoordinates.split ( ' ' , QString::SkipEmptyParts );
487
494
if ( coordinates.size () == 3 && !foundZ && !foundM && !is3D && !isMeasure )
@@ -499,7 +506,7 @@ QList<QgsPointV2> QgsGeometryUtils::pointsFromWKT( const QString &wktCoordinateL
499
506
}
500
507
}
501
508
502
- Q_FOREACH ( const QString& pointCoordinates, coordList )
509
+ Q_FOREACH ( const QString& pointCoordinates, coordList )
503
510
{
504
511
QStringList coordinates = pointCoordinates.split ( ' ' , QString::SkipEmptyParts );
505
512
if ( coordinates.size () < dim )
@@ -542,7 +549,7 @@ QList<QgsPointV2> QgsGeometryUtils::pointsFromWKT( const QString &wktCoordinateL
542
549
void QgsGeometryUtils::pointsToWKB ( QgsWkbPtr& wkb, const QList<QgsPointV2> &points, bool is3D, bool isMeasure )
543
550
{
544
551
wkb << static_cast <quint32>( points.size () );
545
- Q_FOREACH ( const QgsPointV2& point, points )
552
+ Q_FOREACH ( const QgsPointV2& point, points )
546
553
{
547
554
wkb << point.x () << point.y ();
548
555
if ( is3D )
@@ -559,7 +566,7 @@ void QgsGeometryUtils::pointsToWKB( QgsWkbPtr& wkb, const QList<QgsPointV2> &poi
559
566
QString QgsGeometryUtils::pointsToWKT ( const QList<QgsPointV2>& points, int precision, bool is3D, bool isMeasure )
560
567
{
561
568
QString wkt = " (" ;
562
- Q_FOREACH ( const QgsPointV2& p, points )
569
+ Q_FOREACH ( const QgsPointV2& p, points )
563
570
{
564
571
wkt += qgsDoubleToString ( p.x (), precision );
565
572
wkt += ' ' + qgsDoubleToString ( p.y (), precision );
@@ -581,8 +588,8 @@ QDomElement QgsGeometryUtils::pointsToGML2( const QList<QgsPointV2>& points, QDo
581
588
582
589
QString strCoordinates;
583
590
584
- Q_FOREACH ( const QgsPointV2& p, points )
585
- strCoordinates += qgsDoubleToString ( p.x (), precision ) + ' ,' + qgsDoubleToString ( p.y (), precision ) + ' ' ;
591
+ Q_FOREACH ( const QgsPointV2& p, points )
592
+ strCoordinates += qgsDoubleToString ( p.x (), precision ) + ' ,' + qgsDoubleToString ( p.y (), precision ) + ' ' ;
586
593
587
594
if ( strCoordinates.endsWith ( ' ' ) )
588
595
strCoordinates.chop ( 1 ); // Remove trailing space
@@ -597,7 +604,7 @@ QDomElement QgsGeometryUtils::pointsToGML3( const QList<QgsPointV2>& points, QDo
597
604
elemPosList.setAttribute ( " srsDimension" , is3D ? 3 : 2 );
598
605
599
606
QString strCoordinates;
600
- Q_FOREACH ( const QgsPointV2& p, points )
607
+ Q_FOREACH ( const QgsPointV2& p, points )
601
608
{
602
609
strCoordinates += qgsDoubleToString ( p.x (), precision ) + ' ' + qgsDoubleToString ( p.y (), precision ) + ' ' ;
603
610
if ( is3D )
@@ -613,7 +620,7 @@ QDomElement QgsGeometryUtils::pointsToGML3( const QList<QgsPointV2>& points, QDo
613
620
QString QgsGeometryUtils::pointsToJSON ( const QList<QgsPointV2>& points, int precision )
614
621
{
615
622
QString json = " [ " ;
616
- Q_FOREACH ( const QgsPointV2& p, points )
623
+ Q_FOREACH ( const QgsPointV2& p, points )
617
624
{
618
625
json += ' [' + qgsDoubleToString ( p.x (), precision ) + " , " + qgsDoubleToString ( p.y (), precision ) + " ], " ;
619
626
}
0 commit comments