29 #include <nlohmann/json.hpp>
34 #include <QDomDocument>
35 #include <QJsonObject>
59 mX.resize(
points.count() );
60 mY.resize(
points.count() );
61 double *x = mX.data();
62 double *y = mY.data();
67 mZ.resize(
points.count() );
72 mM.resize(
points.count() );
87 QgsLineString::QgsLineString(
const QVector<double> &x,
const QVector<double> &y,
const QVector<double> &z,
const QVector<double> &m,
bool is25DType )
90 int pointCount = std::min( x.size(), y.size() );
91 if ( x.size() == pointCount )
97 mX = x.mid( 0, pointCount );
99 if ( y.size() == pointCount )
105 mY = y.mid( 0, pointCount );
107 if ( !z.isEmpty() && z.count() >= pointCount )
110 if ( z.size() == pointCount )
116 mZ = z.mid( 0, pointCount );
119 if ( !m.isEmpty() && m.count() >= pointCount )
122 if ( m.size() == pointCount )
128 mM = m.mid( 0, pointCount );
161 mX.reserve(
points.size() );
162 mY.reserve(
points.size() );
181 static double cubicInterpolate(
double a,
double b,
182 double A,
double B,
double C,
double D )
184 return A * b * b * b + 3 * B * b * b * a + 3 * C * b * a * a + D * a * a * a;
193 x.resize( segments + 1 );
195 y.resize( segments + 1 );
197 double *
zData =
nullptr;
198 if ( start.
is3D() && end.
is3D() && controlPoint1.
is3D() && controlPoint2.
is3D() )
200 z.resize( segments + 1 );
204 double *
mData =
nullptr;
207 m.resize( segments + 1 );
211 double *
xData = x.data();
212 double *
yData = y.data();
213 const double step = 1.0 / segments;
216 for (
int i = 0; i < segments; i++, a += step, b -= step )
229 *
xData++ = cubicInterpolate( a, b, start.
x(), controlPoint1.
x(), controlPoint2.
x(), end.
x() );
230 *
yData++ = cubicInterpolate( a, b, start.
y(), controlPoint1.
y(), controlPoint2.
y(), end.
y() );
232 *
zData++ = cubicInterpolate( a, b, start.
z(), controlPoint1.
z(), controlPoint2.
z(), end.
z() );
234 *
mData++ = cubicInterpolate( a, b, start.
m(), controlPoint1.
m(), controlPoint2.
m(), end.
m() );
252 x.resize( polygon.count() );
253 y.resize( polygon.count() );
254 double *
xData = x.data();
255 double *
yData = y.data();
257 const QPointF *src = polygon.data();
258 for (
int i = 0 ; i < polygon.size(); ++ i )
270 const QgsLineString *otherLine = qgsgeometry_cast< const QgsLineString * >( &other );
277 if ( mX.count() != otherLine->mX.count() )
280 for (
int i = 0; i < mX.count(); ++i )
318 const int size = mX.size();
322 const double *x = mX.constData();
323 const double *y = mY.constData();
324 const bool useZ =
is3D();
326 const double *z = useZ ? mZ.constData() :
nullptr;
327 const double *m = useM ? mM.constData() :
nullptr;
329 for (
int i = 0; i < size; ++i )
351 error = QObject::tr(
"LineString has less than 2 points and is not empty." );
362 bool res =
snapToGridPrivate( hSpacing, vSpacing, dSpacing, mSpacing, mX, mY, mZ, mM,
363 result->mX, result->mY, result->mZ, result->mM );
365 return result.release();
372 if ( mX.count() <= 2 )
375 double prevX = mX.at( 0 );
376 double prevY = mY.at( 0 );
378 bool useZ = hasZ && useZValues;
379 double prevZ = useZ ? mZ.at( 0 ) : 0;
381 int remaining = mX.count();
382 while ( i < remaining )
384 double currentX = mX.at( i );
385 double currentY = mY.at( i );
386 double currentZ = useZ ? mZ.at( i ) : 0;
423 if (
is3D() && closed )
424 closed &=
qgsDoubleNear( mZ.first(), mZ.last() ) || ( std::isnan( mZ.first() ) && std::isnan( mZ.last() ) );
437 const int nb = mX.size();
446 if ( rectangle.
contains( mX.at( 0 ), mY.at( 0 ) ) ||
447 rectangle.
contains( mX.at(
static_cast< int >( nb * 0.2 ) ), mY.at(
static_cast< int >( nb * 0.2 ) ) ) ||
448 rectangle.
contains( mX.at(
static_cast< int >( nb * 0.4 ) ), mY.at(
static_cast< int >( nb * 0.4 ) ) ) ||
449 rectangle.
contains( mX.at(
static_cast< int >( nb * 0.6 ) ), mY.at(
static_cast< int >( nb * 0.6 ) ) ) ||
450 rectangle.
contains( mX.at(
static_cast< int >( nb * 0.8 ) ), mY.at(
static_cast< int >( nb * 0.8 ) ) ) ||
451 rectangle.
contains( mX.at( nb - 1 ), mY.at( nb - 1 ) ) )
460 double xmin = std::numeric_limits<double>::max();
461 double ymin = std::numeric_limits<double>::max();
462 double xmax = -std::numeric_limits<double>::max();
463 double ymax = -std::numeric_limits<double>::max();
465 const double *x = mX.constData();
466 const double *y = mY.constData();
467 bool foundPointInRectangle =
false;
468 for (
int i = 0; i < nb; ++i )
470 const double px = *x++;
471 xmin = std::min( xmin, px );
472 xmax = std::max( xmax, px );
473 const double py = *y++;
474 ymin = std::min( ymin, py );
475 ymax = std::max( ymax, py );
477 if ( !foundPointInRectangle && rectangle.
contains( px, py ) )
479 foundPointInRectangle =
true;
495 if ( foundPointInRectangle )
508 QVector< QgsVertexId > res;
509 if ( mX.count() <= 1 )
512 const double *x = mX.constData();
513 const double *y = mY.constData();
515 bool useZ = hasZ && useZValues;
516 const double *z = useZ ? mZ.constData() :
nullptr;
520 double prevZ = z ? *z++ : 0;
523 for (
int i = 1; i < mX.count(); ++i )
525 double currentX = *x++;
526 double currentY = *y++;
527 double currentZ = useZ ? *z++ : 0;
547 const int nb = mX.size();
550 const double *x = mX.constData();
551 const double *y = mY.constData();
552 QPointF *dest =
points.data();
553 for (
int i = 0; i < nb; ++i )
555 *dest++ = QPointF( *x++, *y++ );
573 importVerticesFromWkb( wkbPtr );
583 auto result = std::minmax_element( mX.begin(), mX.end() );
584 const double xmin = *result.first;
585 const double xmax = *result.second;
586 result = std::minmax_element( mY.begin(), mY.end() );
587 const double ymin = *result.first;
588 const double ymax = *result.second;
608 auto result = std::minmax_element( mZ.begin(), mZ.end() );
609 const double zmin = *result.first;
610 const double zmax = *result.second;
622 const int size = mX.size();
623 if ( index < 1 || index >= size - 1 )
626 const bool useZ =
is3D();
629 QVector<double> newX( size );
630 QVector<double> newY( size );
631 QVector<double> newZ( useZ ? size : 0 );
632 QVector<double> newM( useM ? size : 0 );
633 auto it = std::copy( mX.constBegin() + index, mX.constEnd() - 1, newX.begin() );
634 it = std::copy( mX.constBegin(), mX.constBegin() + index, it );
635 *it = *newX.constBegin();
636 mX = std::move( newX );
638 it = std::copy( mY.constBegin() + index, mY.constEnd() - 1, newY.begin() );
639 it = std::copy( mY.constBegin(), mY.constBegin() + index, it );
640 *it = *newY.constBegin();
641 mY = std::move( newY );
644 it = std::copy( mZ.constBegin() + index, mZ.constEnd() - 1, newZ.begin() );
645 it = std::copy( mZ.constBegin(), mZ.constBegin() + index, it );
646 *it = *newZ.constBegin();
647 mZ = std::move( newZ );
651 it = std::copy( mM.constBegin() + index, mM.constEnd() - 1, newM.begin() );
652 it = std::copy( mM.constBegin(), mM.constBegin() + index, it );
653 *it = *newM.constBegin();
654 mM = std::move( newM );
673 QString secondWithoutParentheses =
parts.second;
674 secondWithoutParentheses = secondWithoutParentheses.remove(
'(' ).remove(
')' ).simplified().remove(
' ' );
675 parts.second =
parts.second.remove(
'(' ).remove(
')' );
676 if ( (
parts.second.compare( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
677 secondWithoutParentheses.isEmpty() )
692 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
703 wkb << static_cast<quint32>(
wkbType() );
721 wkt += QLatin1String(
"EMPTY" );
736 QDomElement elemLineString = doc.createElementNS( ns, QStringLiteral(
"LineString" ) );
739 return elemLineString;
743 return elemLineString;
751 QDomElement elemLineString = doc.createElementNS( ns, QStringLiteral(
"LineString" ) );
754 return elemLineString;
757 return elemLineString;
766 {
"type",
"LineString" },
776 kml.append( QLatin1String(
"<LinearRing>" ) );
780 kml.append( QLatin1String(
"<LineString>" ) );
783 kml.append( QLatin1String(
"<altitudeMode>" ) );
786 kml.append( QLatin1String(
"absolute" ) );
790 kml.append( QLatin1String(
"clampToGround" ) );
792 kml.append( QLatin1String(
"</altitudeMode>" ) );
793 kml.append( QLatin1String(
"<coordinates>" ) );
795 int nPoints = mX.size();
796 for (
int i = 0; i < nPoints; ++i )
800 kml.append( QLatin1String(
" " ) );
803 kml.append( QLatin1String(
"," ) );
807 kml.append( QLatin1String(
"," ) );
812 kml.append( QLatin1String(
",0" ) );
815 kml.append( QLatin1String(
"</coordinates>" ) );
818 kml.append( QLatin1String(
"</LinearRing>" ) );
822 kml.append( QLatin1String(
"</LineString>" ) );
836 const int size = mX.size();
840 const double *x = mX.constData();
841 const double *y = mY.constData();
847 for (
int i = 1; i < size; ++i )
851 total += std::sqrt( dx * dx + dy * dy );
861 const bool useZ =
is3D();
864 const int size = mX.size();
866 return std::make_tuple( std::make_unique< QgsLineString >(), std::make_unique< QgsLineString >() );
868 index = std::clamp( index, 0, size - 1 );
870 const int part1Size = index + 1;
871 QVector< double > x1( part1Size );
872 QVector< double > y1( part1Size );
873 QVector< double > z1( useZ ? part1Size : 0 );
874 QVector< double > m1( useM ? part1Size : 0 );
876 const double *sourceX = mX.constData();
877 const double *sourceY = mY.constData();
878 const double *sourceZ = useZ ? mZ.constData() :
nullptr;
879 const double *sourceM = useM ? mM.constData() :
nullptr;
881 double *destX = x1.data();
882 double *destY = y1.data();
883 double *destZ = useZ ? z1.data() :
nullptr;
884 double *destM = useM ? m1.data() :
nullptr;
886 std::copy( sourceX, sourceX + part1Size, destX );
887 std::copy( sourceY, sourceY + part1Size, destY );
889 std::copy( sourceZ, sourceZ + part1Size, destZ );
891 std::copy( sourceM, sourceM + part1Size, destM );
893 const int part2Size = size - index;
895 return std::make_tuple( std::make_unique< QgsLineString >( x1, y1, z1, m1 ), std::make_unique< QgsLineString >() );
897 QVector< double > x2( part2Size );
898 QVector< double > y2( part2Size );
899 QVector< double > z2( useZ ? part2Size : 0 );
900 QVector< double > m2( useM ? part2Size : 0 );
903 destZ = useZ ? z2.data() :
nullptr;
904 destM = useM ? m2.data() :
nullptr;
905 std::copy( sourceX + index, sourceX + size, destX );
906 std::copy( sourceY + index, sourceY + size, destY );
908 std::copy( sourceZ + index, sourceZ + size, destZ );
910 std::copy( sourceM + index, sourceM + size, destM );
913 return std::make_tuple( std::make_unique< QgsLineString >(), std::make_unique< QgsLineString >( x2, y2, z2, m2 ) );
915 return std::make_tuple( std::make_unique< QgsLineString >( x1, y1, z1, m1 ), std::make_unique< QgsLineString >( x2, y2, z2, m2 ) );
923 const int size = mX.size();
927 const double *x = mX.constData();
928 const double *y = mY.constData();
929 const double *z = mZ.constData();
936 for (
int i = 1; i < size; ++i )
941 total += std::sqrt( dx * dx + dy * dy + dz * dz );
981 Q_UNUSED( tolerance )
982 Q_UNUSED( toleranceType )
998 if ( i < 0 || i >= mX.size() )
1003 double x = mX.at( i );
1004 double y = mY.at( i );
1005 double z = std::numeric_limits<double>::quiet_NaN();
1006 double m = std::numeric_limits<double>::quiet_NaN();
1024 else if ( hasZ && hasM )
1047 if ( index >= 0 && index < mX.size() )
1048 return mX.at( index );
1055 if ( index >= 0 && index < mY.size() )
1056 return mY.at( index );
1063 if ( index >= 0 && index < mX.size() )
1070 if ( index >= 0 && index < mY.size() )
1085 pts.reserve( nPoints );
1086 for (
int i = 0; i < nPoints; ++i )
1088 pts.push_back(
pointN( i ) );
1102 const bool hasZ =
static_cast< bool >( z );
1103 const bool hasM =
static_cast< bool >( m );
1124 double *destX = mX.data();
1125 double *destY = mY.data();
1126 double *destZ =
nullptr;
1136 double *destM =
nullptr;
1147 for (
size_t i = 0; i < size; ++i )
1174 bool hasZ = firstPt.
is3D();
1179 mX.resize(
points.size() );
1180 mY.resize(
points.size() );
1183 mZ.resize(
points.size() );
1191 mM.resize(
points.size() );
1198 for (
int i = 0; i <
points.size(); ++i )
1200 mX[i] =
points.at( i ).x();
1201 mY[i] =
points.at( i ).y();
1204 double z =
points.at( i ).z();
1205 mZ[i] = std::isnan( z ) ? 0 : z;
1209 double m =
points.at( i ).m();
1210 mM[i] = std::isnan( m ) ? 0 : m;
1263 mZ.insert( mZ.count(), mX.size() - mZ.size(), std::numeric_limits<double>::quiet_NaN() );
1276 mM.insert( mM.count(), mX.size() - mM.size(), std::numeric_limits<double>::quiet_NaN() );
1286 std::reverse( copy->mX.begin(), copy->mX.end() );
1287 std::reverse( copy->mY.begin(), copy->mY.end() );
1290 std::reverse( copy->mZ.begin(), copy->mZ.end() );
1294 std::reverse( copy->mM.begin(), copy->mM.end() );
1299 void QgsLineString::visitPointsByRegularDistance(
const double distance,
const std::function<
bool (
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double,
double )> &visitPoint )
const
1304 double distanceTraversed = 0;
1306 if ( totalPoints == 0 )
1309 const double *x = mX.constData();
1310 const double *y = mY.constData();
1311 const double *z =
is3D() ? mZ.constData() :
nullptr;
1312 const double *m =
isMeasure() ? mM.constData() :
nullptr;
1314 double prevX = *x++;
1315 double prevY = *y++;
1316 double prevZ = z ? *z++ : 0.0;
1317 double prevM = m ? *m++ : 0.0;
1321 visitPoint( prevX, prevY, prevZ, prevM, prevX, prevY, prevZ, prevM, prevX, prevY, prevZ, prevM );
1325 double pZ = std::numeric_limits<double>::quiet_NaN();
1326 double pM = std::numeric_limits<double>::quiet_NaN();
1327 double nextPointDistance = distance;
1328 for (
int i = 1; i < totalPoints; ++i )
1330 double thisX = *x++;
1331 double thisY = *y++;
1332 double thisZ = z ? *z++ : 0.0;
1333 double thisM = m ? *m++ : 0.0;
1335 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1339 const double distanceToPoint = std::min( nextPointDistance - distanceTraversed,
segmentLength );
1342 z ? &prevZ :
nullptr, z ? &thisZ :
nullptr, z ? &pZ :
nullptr,
1343 m ? &prevM :
nullptr, m ? &thisM :
nullptr, m ? &pM :
nullptr );
1345 if ( !visitPoint( pX, pY, pZ, pM, prevX, prevY, prevZ, prevM, thisX, thisY, thisZ, thisM ) )
1348 nextPointDistance += distance;
1370 std::unique_ptr< QgsPoint > res;
1371 visitPointsByRegularDistance( distance, [ & ](
double x,
double y,
double z,
double m,
double,
double,
double,
double,
double,
double,
double,
double )->
bool
1373 res = std::make_unique< QgsPoint >( pointType, x, y, z, m );
1376 return res.release();
1381 if ( startDistance < 0 && endDistance < 0 )
1384 endDistance = std::max( startDistance, endDistance );
1387 if ( totalPoints == 0 )
1390 QVector< QgsPoint > substringPoints;
1391 substringPoints.reserve( totalPoints );
1399 const double *x = mX.constData();
1400 const double *y = mY.constData();
1401 const double *z =
is3D() ? mZ.constData() :
nullptr;
1402 const double *m =
isMeasure() ? mM.constData() :
nullptr;
1404 double distanceTraversed = 0;
1405 double prevX = *x++;
1406 double prevY = *y++;
1407 double prevZ = z ? *z++ : 0.0;
1408 double prevM = m ? *m++ : 0.0;
1409 bool foundStart =
false;
1411 if ( startDistance < 0 )
1414 for (
int i = 1; i < totalPoints; ++i )
1416 double thisX = *x++;
1417 double thisY = *y++;
1418 double thisZ = z ? *z++ : 0.0;
1419 double thisM = m ? *m++ : 0.0;
1421 const double segmentLength = std::sqrt( ( thisX - prevX ) * ( thisX - prevX ) + ( thisY - prevY ) * ( thisY - prevY ) );
1423 if ( distanceTraversed <= startDistance && startDistance < distanceTraversed +
segmentLength )
1426 const double distanceToStart = startDistance - distanceTraversed;
1427 double startX, startY;
1431 z ? &prevZ :
nullptr, z ? &thisZ :
nullptr, z ? &startZ :
nullptr,
1432 m ? &prevM :
nullptr, m ? &thisM :
nullptr, m ? &startM :
nullptr );
1433 substringPoints <<
QgsPoint( pointType, startX, startY, startZ, startM );
1436 if ( foundStart && ( distanceTraversed +
segmentLength > endDistance ) )
1439 const double distanceToEnd = endDistance - distanceTraversed;
1444 z ? &prevZ :
nullptr, z ? &thisZ :
nullptr, z ? &endZ :
nullptr,
1445 m ? &prevM :
nullptr, m ? &thisM :
nullptr, m ? &endM :
nullptr );
1446 substringPoints <<
QgsPoint( pointType, endX, endY, endZ, endM );
1448 else if ( foundStart )
1450 substringPoints <<
QgsPoint( pointType, thisX, thisY, thisZ, thisM );
1458 if ( distanceTraversed >= endDistance )
1463 if ( !foundStart &&
qgsDoubleNear( distanceTraversed, startDistance ) )
1465 substringPoints <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM )
1466 <<
QgsPoint( pointType, prevX, prevY, prevZ, prevM );
1491 if ( path.isEmpty() || path.currentPosition() != QPointF( mX.at( 0 ), mY.at( 0 ) ) )
1493 path.moveTo( mX.at( 0 ), mY.at( 0 ) );
1496 for (
int i = 1; i < nPoints; ++i )
1498 path.lineTo( mX.at( i ), mY.at( i ) );
1511 return compoundCurve;
1516 if ( mX.size() < 2 || mY.size() < 2 )
1520 if ( startDistance > 0 )
1522 double currentLen = std::sqrt( std::pow( mX.at( 0 ) - mX.at( 1 ), 2 ) +
1523 std::pow( mY.at( 0 ) - mY.at( 1 ), 2 ) );
1524 double newLen = currentLen + startDistance;
1525 mX[ 0 ] = mX.at( 1 ) + ( mX.at( 0 ) - mX.at( 1 ) ) / currentLen * newLen;
1526 mY[ 0 ] = mY.at( 1 ) + ( mY.at( 0 ) - mY.at( 1 ) ) / currentLen * newLen;
1529 if ( endDistance > 0 )
1531 int last = mX.size() - 1;
1532 double currentLen = std::sqrt( std::pow( mX.at( last ) - mX.at( last - 1 ), 2 ) +
1533 std::pow( mY.at( last ) - mY.at( last - 1 ), 2 ) );
1534 double newLen = currentLen + endDistance;
1535 mX[ last ] = mX.at( last - 1 ) + ( mX.at( last ) - mX.at( last - 1 ) ) / currentLen * newLen;
1536 mY[ last ] = mY.at( last - 1 ) + ( mY.at( last ) - mY.at( last - 1 ) ) / currentLen * newLen;
1542 auto result = std::make_unique< QgsLineString >();
1544 return result.release();
1549 const QgsLineString *otherLine = qgsgeometry_cast<const QgsLineString *>( other );
1553 const int size = mX.size();
1554 const int otherSize = otherLine->mX.size();
1555 if ( size > otherSize )
1559 else if ( size < otherSize )
1564 if (
is3D() && !otherLine->
is3D() )
1566 else if ( !
is3D() && otherLine->
is3D() )
1568 const bool considerZ =
is3D();
1576 for (
int i = 0; i < size; i++ )
1578 const double x = mX[i];
1579 const double otherX = otherLine->mX[i];
1584 else if ( x > otherX )
1589 const double y = mY[i];
1590 const double otherY = otherLine->mY[i];
1595 else if ( y > otherY )
1602 const double z = mZ[i];
1603 const double otherZ = otherLine->mZ[i];
1609 else if ( z > otherZ )
1617 const double m = mM[i];
1618 const double otherM = otherLine->mM[i];
1624 else if ( m > otherM )
1635 return QStringLiteral(
"LineString" );
1651 double *zArray =
nullptr;
1657 std::unique_ptr< double[] > dummyZ;
1658 if ( !hasZ || !transformZ )
1660 dummyZ.reset(
new double[nPoints]() );
1661 zArray = dummyZ.get();
1676 double *x = mX.data();
1677 double *y = mY.data();
1678 double *z = hasZ ? mZ.data() :
nullptr;
1679 double *m = hasM ? mM.data() :
nullptr;
1680 for (
int i = 0; i < nPoints; ++i )
1683 t.map( *x, *y, &xOut, &yOut );
1688 *z = *z * zScale + zTranslate;
1693 *m = *m * mScale + mTranslate;
1708 if ( position.
vertex < 0 || position.
vertex > mX.size() )
1718 mX.insert( position.
vertex, vertex.
x() );
1719 mY.insert( position.
vertex, vertex.
y() );
1722 mZ.insert( position.
vertex, vertex.
z() );
1726 mM.insert( position.
vertex, vertex.
m() );
1734 if ( position.
vertex < 0 || position.
vertex >= mX.size() )
1738 mX[position.
vertex] = newPos.
x();
1739 mY[position.
vertex] = newPos.
y();
1742 mZ[position.
vertex] = newPos.
z();
1746 mM[position.
vertex] = newPos.
m();
1754 if ( position.
vertex >= mX.size() || position.
vertex < 0 )
1759 mX.remove( position.
vertex );
1760 mY.remove( position.
vertex );
1763 mZ.remove( position.
vertex );
1767 mM.remove( position.
vertex );
1792 mX.append( pt.
x() );
1793 mY.append( pt.
y() );
1796 mZ.append( pt.
z() );
1800 mM.append( pt.
m() );
1807 double sqrDist = std::numeric_limits<double>::max();
1808 double leftOfDist = std::numeric_limits<double>::max();
1810 double prevLeftOfX = 0.0;
1811 double prevLeftOfY = 0.0;
1812 double testDist = 0;
1813 double segmentPtX, segmentPtY;
1818 int size = mX.size();
1819 if ( size == 0 || size == 1 )
1824 for (
int i = 1; i < size; ++i )
1826 double prevX = mX.at( i - 1 );
1827 double prevY = mY.at( i - 1 );
1828 double currentX = mX.at( i );
1829 double currentY = mY.at( i );
1831 if ( testDist < sqrDist )
1834 segmentPt.
setX( segmentPtX );
1835 segmentPt.
setY( segmentPtY );
1836 vertexAfter.
part = 0;
1837 vertexAfter.
ring = 0;
1848 if (
qgsDoubleNear( testDist, leftOfDist ) && left != prevLeftOf && prevLeftOf != 0 )
1861 leftOfDist = testDist;
1862 prevLeftOfX = prevX;
1863 prevLeftOfY = prevY;
1865 else if ( testDist < leftOfDist )
1868 leftOfDist = testDist;
1889 type = Qgis::VertexType::Segment;
1900 return QgsPoint( mX.at( 0 ), mY.at( 0 ) );
1902 double totalLineLength = 0.0;
1903 double prevX = mX.at( 0 );
1904 double prevY = mY.at( 0 );
1910 double currentX = mX.at( i );
1911 double currentY = mY.at( i );
1912 double segmentLength = std::sqrt( std::pow( currentX - prevX, 2.0 ) +
1913 std::pow( currentY - prevY, 2.0 ) );
1925 return QgsPoint( mX.at( 0 ), mY.at( 0 ) );
1927 return QgsPoint( sumX / totalLineLength, sumY / totalLineLength );
1941 for (
int i = 0; i < maxIndex; ++i )
1943 sum += 0.5 * ( mX.at( i ) * mY.at( i + 1 ) - mY.at( i ) * mX.at( i + 1 ) );
1947 void QgsLineString::importVerticesFromWkb(
const QgsConstWkbPtr &wkb )
1953 mX.resize( nVertices );
1954 mY.resize( nVertices );
1955 hasZ ? mZ.resize( nVertices ) : mZ.clear();
1956 hasM ? mM.resize( nVertices ) : mM.clear();
1957 double *x = mX.data();
1958 double *y = mY.data();
1959 double *m = hasM ? mM.data() :
nullptr;
1960 double *z = hasZ ? mZ.data() :
nullptr;
1961 for (
int i = 0; i < nVertices; ++i )
1994 if ( mX.count() < 2 )
2004 double previousX = mX.at(
numPoints() - 2 );
2005 double previousY = mY.at(
numPoints() - 2 );
2006 double currentX = mX.at( 0 );
2007 double currentY = mY.at( 0 );
2008 double afterX = mX.at( 1 );
2009 double afterY = mY.at( 1 );
2012 else if ( vertex.
vertex == 0 )
2025 double previousX = mX.at( vertex.
vertex - 1 );
2026 double previousY = mY.at( vertex.
vertex - 1 );
2027 double currentX = mX.at( vertex.
vertex );
2028 double currentY = mY.at( vertex.
vertex );
2029 double afterX = mX.at( vertex.
vertex + 1 );
2030 double afterY = mY.at( vertex.
vertex + 1 );
2037 if ( startVertex.
vertex < 0 || startVertex.
vertex >= mX.count() - 1 )
2040 double dx = mX.at( startVertex.
vertex + 1 ) - mX.at( startVertex.
vertex );
2041 double dy = mY.at( startVertex.
vertex + 1 ) - mY.at( startVertex.
vertex );
2042 return std::sqrt( dx * dx + dy * dy );
2067 mZ.reserve( nPoints );
2068 for (
int i = 0; i < nPoints; ++i )
2098 mM.reserve( nPoints );
2099 for (
int i = 0; i < nPoints; ++i )
2130 std::swap( mX, mY );
2144 addZValue( std::numeric_limits<double>::quiet_NaN() );
2161 int size = mX.size();
2163 double *srcX = mX.data();
2164 double *srcY = mY.data();
2165 double *srcM = hasM ? mM.data() :
nullptr;
2166 double *srcZ = hasZ ? mZ.data() :
nullptr;
2169 for (
int i = 0; i < size; ++i )
2173 double z = hasZ ? *srcZ : std::numeric_limits<double>::quiet_NaN();
2174 double m = hasM ? *srcM : std::numeric_limits<double>::quiet_NaN();
2202 int size = mX.size();
2204 double *srcX = mX.data();
2205 double *srcY = mY.data();
2206 double *srcM = hasM ? mM.data() :
nullptr;
2207 double *srcZ = hasZ ? mZ.data() :
nullptr;
2209 double *destX = srcX;
2210 double *destY = srcY;
2211 double *destM = srcM;
2212 double *destZ = srcZ;
2214 int filteredPoints = 0;
2215 for (
int i = 0; i < size; ++i )
2219 double z = hasZ ? *srcZ++ : std::numeric_limits<double>::quiet_NaN();
2220 double m = hasM ? *srcM++ : std::numeric_limits<double>::quiet_NaN();
2222 if ( filter(
QgsPoint( x, y, z, m ) ) )
2234 mX.resize( filteredPoints );
2235 mY.resize( filteredPoints );
2237 mZ.resize( filteredPoints );
2239 mM.resize( filteredPoints );
2248 int size = mX.size();
2250 double *srcX = mX.data();
2251 double *srcY = mY.data();
2252 double *srcM = hasM ? mM.data() :
nullptr;
2253 double *srcZ = hasZ ? mZ.data() :
nullptr;
2255 for (
int i = 0; i < size; ++i )
2259 double z = hasZ ? *srcZ : std::numeric_limits<double>::quiet_NaN();
2260 double m = hasM ? *srcM : std::numeric_limits<double>::quiet_NaN();