2424#include < QPainter>
2525#include < limits>
2626#include < QDomDocument>
27+ #include < QtCore/qmath.h>
2728
2829QgsLineStringV2::QgsLineStringV2 (): QgsCurveV2()
2930{
@@ -573,6 +574,17 @@ double QgsLineStringV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmen
573574 double segmentPtX, segmentPtY;
574575
575576 int size = mX .size ();
577+ if ( size == 0 )
578+ {
579+ vertexAfter = QgsVertexId ( 0 , 0 , 0 );
580+ return sqrDist;
581+ }
582+ else if ( size == 1 )
583+ {
584+ segmentPt = pointN ( 0 );
585+ vertexAfter = QgsVertexId ( 0 , 0 , 1 );
586+ return QgsGeometryUtils::sqrDistance2D ( pt, segmentPt );
587+ }
576588 for ( int i = 1 ; i < size; ++i )
577589 {
578590 double prevX = mX .at ( i - 1 );
@@ -587,28 +599,69 @@ double QgsLineStringV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmen
587599 segmentPt.setY ( segmentPtY );
588600 if ( leftOf )
589601 {
590- *leftOf = ( QgsGeometryUtils::leftOfLine ( segmentPtX, segmentPtY, prevX, prevY, pt.x (), pt.y () ) < 0 );
602+ *leftOf = ( QgsGeometryUtils::leftOfLine ( pt.x (), pt.y (), prevX, prevY, currentX, currentY ) < 0 );
591603 }
592604 vertexAfter.part = 0 ; vertexAfter.ring = 0 ; vertexAfter.vertex = i;
593605 }
594606 }
595607 return sqrDist;
596608}
597609
598- bool QgsLineStringV2::pointAt ( int i , QgsPointV2& vertex , QgsVertexId::VertexType& type ) const
610+ bool QgsLineStringV2::pointAt ( int node , QgsPointV2& point , QgsVertexId::VertexType& type ) const
599611{
600- if ( i >= numPoints () )
612+ if ( node < 0 || node >= numPoints () )
601613 {
602614 return false ;
603615 }
604- vertex = pointN ( i );
616+ point = pointN ( node );
605617 type = QgsVertexId::SegmentVertex;
606618 return true ;
607619}
608620
621+ QgsPointV2 QgsLineStringV2::centroid () const
622+ {
623+ if ( mX .isEmpty () )
624+ return QgsPointV2 ();
625+
626+ int numPoints = mX .count ();
627+ if ( numPoints == 1 )
628+ return QgsPointV2 ( mX .at ( 0 ), mY .at ( 0 ) );
629+
630+ double totalLineLength = 0.0 ;
631+ double prevX = mX .at ( 0 );
632+ double prevY = mY .at ( 0 );
633+ double sumX = 0.0 ;
634+ double sumY = 0.0 ;
635+
636+ for ( int i = 1 ; i < numPoints ; ++i )
637+ {
638+ double currentX = mX .at ( i );
639+ double currentY = mY .at ( i );
640+ double segmentLength = sqrt ( qPow ( currentX - prevX, 2.0 ) +
641+ qPow ( currentY - prevY, 2.0 ) );
642+ if ( qgsDoubleNear ( segmentLength, 0.0 ) )
643+ continue ;
644+
645+ totalLineLength += segmentLength;
646+ sumX += segmentLength * 0.5 * ( currentX + prevX );
647+ sumY += segmentLength * 0.5 * ( currentY + prevY );
648+ prevX = currentX;
649+ prevY = currentY;
650+ }
651+
652+ if ( qgsDoubleNear ( totalLineLength, 0.0 ) )
653+ return QgsPointV2 ( mX .at ( 0 ), mY .at ( 0 ) );
654+ else
655+ return QgsPointV2 ( sumX / totalLineLength, sumY / totalLineLength );
656+
657+ }
658+
609659void QgsLineStringV2::sumUpArea ( double & sum ) const
610660{
611661 int maxIndex = numPoints () - 1 ;
662+ if ( maxIndex == 1 )
663+ return ; // no area, just a single line
664+
612665 for ( int i = 0 ; i < maxIndex; ++i )
613666 {
614667 sum += 0.5 * ( mX .at ( i ) * mY .at ( i + 1 ) - mY .at ( i ) * mX .at ( i + 1 ) );
0 commit comments