Skip to content

Commit 5fcd470

Browse files
committed
Backport fix for segmentation to 2.14
1 parent 88c3d4e commit 5fcd470

File tree

1 file changed

+45
-37
lines changed

1 file changed

+45
-37
lines changed

src/core/geometry/qgscircularstringv2.cpp

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -475,51 +475,44 @@ void QgsCircularStringV2::setPoints( const QgsPointSequenceV2 &points )
475475

476476
void QgsCircularStringV2::segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QgsPointSequenceV2 &points ) const
477477
{
478+
bool clockwise = false;
479+
int segSide = segmentSide( p1, p3, p2 );
480+
if ( segSide == -1 )
481+
{
482+
clockwise = true;
483+
}
484+
485+
QgsPointV2 circlePoint1 = clockwise ? p3 : p1;
486+
QgsPointV2 circlePoint2 = p2;
487+
QgsPointV2 circlePoint3 = clockwise ? p1 : p3 ;
488+
478489
//adapted code from postgis
479490
double radius = 0;
480491
double centerX = 0;
481492
double centerY = 0;
482-
QgsGeometryUtils::circleCenterRadius( p1, p2, p3, radius, centerX, centerY );
483-
int segSide = segmentSide( p1, p3, p2 );
493+
QgsGeometryUtils::circleCenterRadius( circlePoint1, circlePoint2, circlePoint3, radius, centerX, centerY );
484494

485-
if ( p1 != p3 && ( radius < 0 || qgsDoubleNear( segSide, 0.0 ) ) ) //points are colinear
495+
496+
if ( circlePoint1 != circlePoint3 && ( radius < 0 || qgsDoubleNear( segSide, 0.0 ) ) ) //points are colinear
486497
{
487498
points.append( p1 );
488499
points.append( p2 );
489500
points.append( p3 );
490501
return;
491502
}
492503

493-
bool clockwise = false;
494-
if ( segSide == -1 )
495-
{
496-
clockwise = true;
497-
}
498-
499504
double increment = fabs( M_PI_2 / 90 ); //one segment per degree
500505

501506
//angles of pt1, pt2, pt3
502-
double a1 = atan2( p1.y() - centerY, p1.x() - centerX );
503-
double a2 = atan2( p2.y() - centerY, p2.x() - centerX );
504-
double a3 = atan2( p3.y() - centerY, p3.x() - centerX );
507+
double a1 = atan2( circlePoint1.y() - centerY, circlePoint1.x() - centerX );
508+
double a2 = atan2( circlePoint2.y() - centerY, circlePoint2.x() - centerX );
509+
double a3 = atan2( circlePoint3.y() - centerY, circlePoint3.x() - centerX );
505510

506-
if ( clockwise )
507-
{
508-
increment *= -1;
509-
/* Adjust a3 down so we can decrement from a1 to a3 cleanly */
510-
if ( a3 >= a1 )
511-
a3 -= 2.0 * M_PI;
512-
if ( a2 > a1 )
513-
a2 -= 2.0 * M_PI;
514-
}
515-
else
516-
{
517-
/* Adjust a3 up so we can increment from a1 to a3 cleanly */
518-
if ( a3 <= a1 )
519-
a3 += 2.0 * M_PI;
520-
if ( a2 < a1 )
521-
a2 += 2.0 * M_PI;
522-
}
511+
/* Adjust a3 up so we can increment from a1 to a3 cleanly */
512+
if ( a3 <= a1 )
513+
a3 += 2.0 * M_PI;
514+
if ( a2 < a1 )
515+
a2 += 2.0 * M_PI;
523516

524517
bool hasZ = is3D();
525518
bool hasM = isMeasure();
@@ -528,39 +521,54 @@ void QgsCircularStringV2::segmentize( const QgsPointV2& p1, const QgsPointV2& p2
528521
double z = 0;
529522
double m = 0;
530523

531-
points.append( p1 );
532-
if ( p2 != p3 && p1 != p2 ) //draw straight line segment if two points have the same position
524+
QList<QgsPointV2> stringPoints;
525+
stringPoints.insert( clockwise ? 0 : stringPoints.size(), circlePoint1 );
526+
if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 ) //draw straight line segment if two points have the same position
533527
{
534528
QgsWKBTypes::Type pointWkbType = QgsWKBTypes::Point;
535529
if ( hasZ )
536530
pointWkbType = QgsWKBTypes::addZ( pointWkbType );
537531
if ( hasM )
538532
pointWkbType = QgsWKBTypes::addM( pointWkbType );
539533

540-
for ( double angle = a1 + increment; clockwise ? angle > a3 : angle < a3; angle += increment )
534+
//make sure the curve point p2 is part of the segmentized vertices. But only if p1 != p3
535+
bool addP2 = true;
536+
if ( qgsDoubleNear( circlePoint1.x(), circlePoint3.x() ) && qgsDoubleNear( circlePoint1.y(), circlePoint3.y() ) )
541537
{
538+
addP2 = false;
539+
}
540+
541+
for ( double angle = a1 + increment; angle < a3; angle += increment )
542+
{
543+
if (( addP2 && angle > a2 ) )
544+
{
545+
stringPoints.insert( clockwise ? 0 : stringPoints.size(), circlePoint2 );
546+
addP2 = false;
547+
}
548+
542549
x = centerX + radius * cos( angle );
543550
y = centerY + radius * sin( angle );
544551

545552
if ( !hasZ && !hasM )
546553
{
547-
points.append( QgsPointV2( x, y ) );
554+
stringPoints.insert( clockwise ? 0 : stringPoints.size(), QgsPointV2( x, y ) );
548555
continue;
549556
}
550557

551558
if ( hasZ )
552559
{
553-
z = interpolateArc( angle, a1, a2, a3, p1.z(), p2.z(), p3.z() );
560+
z = interpolateArc( angle, a1, a2, a3, circlePoint1.z(), circlePoint2.z(), circlePoint3.z() );
554561
}
555562
if ( hasM )
556563
{
557-
m = interpolateArc( angle, a1, a2, a3, p1.m(), p2.m(), p3.m() );
564+
m = interpolateArc( angle, a1, a2, a3, circlePoint1.m(), circlePoint2.m(), circlePoint3.m() );
558565
}
559566

560-
points.append( QgsPointV2( pointWkbType, x, y, z, m ) );
567+
stringPoints.insert( clockwise ? 0 : stringPoints.size(), QgsPointV2( pointWkbType, x, y, z, m ) );
561568
}
562569
}
563-
points.append( p3 );
570+
stringPoints.insert( clockwise ? 0 : stringPoints.size(), circlePoint3 );
571+
points.append( stringPoints );
564572
}
565573

566574
int QgsCircularStringV2::segmentSide( const QgsPointV2& pt1, const QgsPointV2& pt3, const QgsPointV2& pt2 ) const

0 commit comments

Comments
 (0)