29#include <nlohmann/json.hpp> 
   34#include <QDomDocument> 
   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() );
 
 
   87QgsLineString::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() );
 
 
  181static 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 )
 
 
  290  const int size = mX.size();
 
  294  const double *x = mX.constData();
 
  295  const double *y = mY.constData();
 
  296  const bool useZ = 
is3D();
 
  298  const double *z = useZ ? mZ.constData() : 
nullptr;
 
  299  const double *m = useM ? mM.constData() : 
nullptr;
 
  301  for ( 
int i = 0; i < size; ++i )
 
 
  323    error = QObject::tr( 
"LineString has less than 2 points and is not empty." );
 
 
  334  bool res = 
snapToGridPrivate( hSpacing, vSpacing, dSpacing, mSpacing, mX, mY, mZ, mM,
 
  335                                result->mX, result->mY, result->mZ, result->mM, removeRedundantPoints );
 
  337    return result.release();
 
 
  344  if ( mX.count() <= 2 )
 
  347  double prevX = mX.at( 0 );
 
  348  double prevY = mY.at( 0 );
 
  350  bool useZ = hasZ && useZValues;
 
  351  double prevZ = useZ ? mZ.at( 0 ) : 0;
 
  353  int remaining = mX.count();
 
  354  while ( i < remaining )
 
  356    double currentX = mX.at( i );
 
  357    double currentY = mY.at( i );
 
  358    double currentZ = useZ ? mZ.at( i ) : 0;
 
 
  395  if ( 
is3D() && closed )
 
  396    closed &= 
qgsDoubleNear( mZ.first(), mZ.last() ) || ( std::isnan( mZ.first() ) && std::isnan( mZ.last() ) );
 
 
  411  const int nb = mX.size();
 
  420    if ( rectangle.
contains( mX.at( 0 ), mY.at( 0 ) ) ||
 
  421         rectangle.
contains( mX.at( 
static_cast< int >( nb * 0.2 ) ), mY.at( 
static_cast< int >( nb * 0.2 ) ) ) ||
 
  422         rectangle.
contains( mX.at( 
static_cast< int >( nb * 0.4 ) ), mY.at( 
static_cast< int >( nb * 0.4 ) ) ) ||
 
  423         rectangle.
contains( mX.at( 
static_cast< int >( nb * 0.6 ) ), mY.at( 
static_cast< int >( nb * 0.6 ) ) ) ||
 
  424         rectangle.
contains( mX.at( 
static_cast< int >( nb * 0.8 ) ), mY.at( 
static_cast< int >( nb * 0.8 ) ) ) ||
 
  425         rectangle.
contains( mX.at( nb - 1 ), mY.at( nb - 1 ) ) )
 
  434  double xmin = std::numeric_limits<double>::max();
 
  435  double ymin = std::numeric_limits<double>::max();
 
  436  double xmax = -std::numeric_limits<double>::max();
 
  437  double ymax = -std::numeric_limits<double>::max();
 
  439  const double *x = mX.constData();
 
  440  const double *y = mY.constData();
 
  441  bool foundPointInRectangle = 
false;
 
  442  for ( 
int i = 0; i < nb; ++i )
 
  444    const double px = *x++;
 
  445    xmin = std::min( xmin, px );
 
  446    xmax = std::max( xmax, px );
 
  447    const double py = *y++;
 
  448    ymin = std::min( ymin, py );
 
  449    ymax = std::max( ymax, py );
 
  451    if ( !foundPointInRectangle && rectangle.
contains( px, py ) )
 
  453      foundPointInRectangle = 
true;
 
  469  if ( foundPointInRectangle )
 
 
  494  const int nb = mX.size();
 
  503    if ( box3d.
contains( mX.at( 0 ), mY.at( 0 ), mZ.at( 0 ) ) ||
 
  504         box3d.
contains( mX.at( 
static_cast< int >( nb * 0.2 ) ), mY.at( 
static_cast< int >( nb * 0.2 ) ), mZ.at( 
static_cast< int >( nb * 0.2 ) ) ) ||
 
  505         box3d.
contains( mX.at( 
static_cast< int >( nb * 0.4 ) ), mY.at( 
static_cast< int >( nb * 0.4 ) ), mZ.at( 
static_cast< int >( nb * 0.4 ) ) ) ||
 
  506         box3d.
contains( mX.at( 
static_cast< int >( nb * 0.6 ) ), mY.at( 
static_cast< int >( nb * 0.6 ) ), mZ.at( 
static_cast< int >( nb * 0.6 ) ) ) ||
 
  507         box3d.
contains( mX.at( 
static_cast< int >( nb * 0.8 ) ), mY.at( 
static_cast< int >( nb * 0.8 ) ), mZ.at( 
static_cast< int >( nb * 0.8 ) ) ) ||
 
  508         box3d.
contains( mX.at( nb - 1 ), mY.at( nb - 1 ), mZ.at( nb - 1 ) ) )
 
  517  double xmin = std::numeric_limits<double>::max();
 
  518  double ymin = std::numeric_limits<double>::max();
 
  519  double zmin = std::numeric_limits<double>::max();
 
  520  double xmax = -std::numeric_limits<double>::max();
 
  521  double ymax = -std::numeric_limits<double>::max();
 
  522  double zmax = -std::numeric_limits<double>::max();
 
  524  const double *x = mX.constData();
 
  525  const double *y = mY.constData();
 
  526  const double *z = mZ.constData();
 
  527  bool foundPointInBox = 
false;
 
  528  for ( 
int i = 0; i < nb; ++i )
 
  530    const double px = *x++;
 
  531    xmin = std::min( xmin, px );
 
  532    xmax = std::max( xmax, px );
 
  533    const double py = *y++;
 
  534    ymin = std::min( ymin, py );
 
  535    ymax = std::max( ymax, py );
 
  536    const double pz = *z++;
 
  537    zmin = std::min( zmin, pz );
 
  538    zmax = std::max( zmax, pz );
 
  540    if ( !foundPointInBox && box3d.
contains( px, py, pz ) )
 
  542      foundPointInBox = 
true;
 
  558  if ( foundPointInBox )
 
 
  571  QVector< QgsVertexId > res;
 
  572  if ( mX.count() <= 1 )
 
  575  const double *x = mX.constData();
 
  576  const double *y = mY.constData();
 
  578  bool useZ = hasZ && useZValues;
 
  579  const double *z = useZ ? mZ.constData() : 
nullptr;
 
  583  double prevZ = z ? *z++ : 0;
 
  586  for ( 
int i = 1; i < mX.count(); ++i )
 
  588    double currentX = *x++;
 
  589    double currentY = *y++;
 
  590    double currentZ = useZ ? *z++ : 0;
 
 
  610  const int nb = mX.size();
 
  613  const double *x = mX.constData();
 
  614  const double *y = mY.constData();
 
  615  QPointF *dest = 
points.data();
 
  616  for ( 
int i = 0; i < nb; ++i )
 
  618    *dest++ = QPointF( *x++, *y++ );
 
 
  624void simplifySection( 
int i, 
int j, 
const double *x, 
const double *y, std::vector< bool > &usePoint, 
const double distanceToleranceSquared, 
const double epsilon )
 
  631  double maxDistanceSquared = -1.0;
 
  636  for ( 
int k = i + 1; k < j; k++ )
 
  639                                     x[k], y[k], x[i], y[i], x[j], y[j], mx, my, epsilon );
 
  641    if ( distanceSquared > maxDistanceSquared )
 
  643      maxDistanceSquared = distanceSquared;
 
  647  if ( maxDistanceSquared <= distanceToleranceSquared )
 
  649    for ( 
int k = i + 1; k < j; k++ )
 
  656    simplifySection( i, maxIndex, x, y, usePoint, distanceToleranceSquared, epsilon );
 
  657    simplifySection( maxIndex, j, x, y, usePoint, distanceToleranceSquared, epsilon );
 
 
  670  const double distanceToleranceSquared = tolerance * tolerance;
 
  671  const double *
xData = mX.constData();
 
  672  const double *
yData = mY.constData();
 
  673  const double *
zData = mZ.constData();
 
  674  const double *
mData = mM.constData();
 
  676  const int size = mX.size();
 
  678  std::vector< bool > usePoint( size, 
true );
 
  680  constexpr double epsilon = 4 * std::numeric_limits<double>::epsilon();
 
  683  QVector< double > newX;
 
  684  newX.reserve( size );
 
  685  QVector< double > newY;
 
  686  newY.reserve( size );
 
  688  const bool hasZ = 
is3D();
 
  690  QVector< double > newZ;
 
  692    newZ.reserve( size );
 
  693  QVector< double > newM;
 
  695    newM.reserve( size );
 
  697  for ( 
int i = 0, n = size; i < n; ++i )
 
  699    if ( usePoint[i] || i == n - 1 )
 
  701      newX.append( 
xData[i ] );
 
  702      newY.append( 
yData[i ] );
 
  704        newZ.append( 
zData[i] );
 
  706        newM.append( 
mData[i] );
 
  710  const bool simplifyRing = 
isRing();
 
  711  const int newSize = newX.size();
 
  712  if ( simplifyRing && newSize > 3 )
 
  717                                     newX[ newSize - 2], newY[ newSize - 2 ],
 
  718                                     newX[ 1 ], newY[ 1], mx, my, epsilon );
 
  720    if ( distanceSquared <= distanceToleranceSquared )
 
  723      newX.last() = newX.first();
 
  725      newY.last() = newY.first();
 
  729        newZ.last() = newZ.first();
 
  734        newM.last() = newM.first();
 
 
  755  importVerticesFromWkb( wkbPtr );
 
 
  766  auto result2D = std::minmax_element( mX.begin(), mX.end() );
 
  767  const double xmin = *result2D.first;
 
  768  const double xmax = *result2D.second;
 
  769  result2D = std::minmax_element( mY.begin(), mY.end() );
 
  770  const double ymin = *result2D.first;
 
  771  const double ymax = *result2D.second;
 
  773  double zmin = std::numeric_limits< double >::quiet_NaN();
 
  774  double zmax = std::numeric_limits< double >::quiet_NaN();
 
  778    auto resultZ = std::minmax_element( mZ.begin(), mZ.end() );
 
  779    zmin = *resultZ.first;
 
  780    zmax = *resultZ.second;
 
  783  return QgsBox3D( xmin, ymin, zmin, xmax, ymax, zmax );
 
 
  793  const int size = mX.size();
 
  794  if ( index < 1 || index >= size - 1 )
 
  797  const bool useZ = 
is3D();
 
  800  QVector<double> newX( size );
 
  801  QVector<double> newY( size );
 
  802  QVector<double> newZ( useZ ? size : 0 );
 
  803  QVector<double> newM( useM ? size : 0 );
 
  804  auto it = std::copy( mX.constBegin() + index, mX.constEnd() - 1, newX.begin() );
 
  805  it = std::copy( mX.constBegin(), mX.constBegin() + index, it );
 
  806  *it = *newX.constBegin();
 
  807  mX = std::move( newX );
 
  809  it = std::copy( mY.constBegin() + index, mY.constEnd() - 1, newY.begin() );
 
  810  it = std::copy( mY.constBegin(), mY.constBegin() + index, it );
 
  811  *it = *newY.constBegin();
 
  812  mY = std::move( newY );
 
  815    it = std::copy( mZ.constBegin() + index, mZ.constEnd() - 1, newZ.begin() );
 
  816    it = std::copy( mZ.constBegin(), mZ.constBegin() + index, it );
 
  817    *it = *newZ.constBegin();
 
  818    mZ = std::move( newZ );
 
  822    it = std::copy( mM.constBegin() + index, mM.constEnd() - 1, newM.begin() );
 
  823    it = std::copy( mM.constBegin(), mM.constBegin() + index, it );
 
  824    *it = *newM.constBegin();
 
  825    mM = std::move( newM );
 
 
  844  QString secondWithoutParentheses = 
parts.second;
 
  845  secondWithoutParentheses = secondWithoutParentheses.remove( 
'(' ).remove( 
')' ).simplified().remove( 
' ' );
 
  846  parts.second = 
parts.second.remove( 
'(' ).remove( 
')' );
 
  847  if ( ( 
parts.second.compare( QLatin1String( 
"EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
 
  848       secondWithoutParentheses.isEmpty() )
 
 
  863  int binarySize = 
sizeof( char ) + 
sizeof( quint32 ) + 
sizeof( quint32 );
 
 
  874  wkb << static_cast<quint32>( 
wkbType() );
 
 
  892    wkt += QLatin1String( 
"EMPTY" );
 
 
  907  QDomElement elemLineString = doc.createElementNS( ns, QStringLiteral( 
"LineString" ) );
 
  910    return elemLineString;
 
  914  return elemLineString;
 
 
  922  QDomElement elemLineString = doc.createElementNS( ns, QStringLiteral( 
"LineString" ) );
 
  925    return elemLineString;
 
  928  return elemLineString;
 
 
  937    {  
"type",  
"LineString" },
 
 
  947    kml.append( QLatin1String( 
"<LinearRing>" ) );
 
  951    kml.append( QLatin1String( 
"<LineString>" ) );
 
  954  kml.append( QLatin1String( 
"<altitudeMode>" ) );
 
  957    kml.append( QLatin1String( 
"absolute" ) );
 
  961    kml.append( QLatin1String( 
"clampToGround" ) );
 
  963  kml.append( QLatin1String( 
"</altitudeMode>" ) );
 
  964  kml.append( QLatin1String( 
"<coordinates>" ) );
 
  966  int nPoints = mX.size();
 
  967  for ( 
int i = 0; i < nPoints; ++i )
 
  971      kml.append( QLatin1String( 
" " ) );
 
  974    kml.append( QLatin1String( 
"," ) );
 
  978      kml.append( QLatin1String( 
"," ) );
 
  983      kml.append( QLatin1String( 
",0" ) );
 
  986  kml.append( QLatin1String( 
"</coordinates>" ) );
 
  989    kml.append( QLatin1String( 
"</LinearRing>" ) );
 
  993    kml.append( QLatin1String( 
"</LineString>" ) );
 
 
 1007  const int size = mX.size();
 
 1011  const double *x = mX.constData();
 
 1012  const double *y = mY.constData();
 
 1015  double prevX = *x++;
 
 1016  double prevY = *y++;
 
 1018  for ( 
int i = 1; i < size; ++i )
 
 1022    total += std::sqrt( dx * dx + dy * dy );
 
 
 1032  const bool useZ = 
is3D();
 
 1035  const int size = mX.size();
 
 1037    return std::make_tuple( std::make_unique< QgsLineString >(), std::make_unique< QgsLineString >() );
 
 1039  index = std::clamp( index, 0, size - 1 );
 
 1041  const int part1Size = index + 1;
 
 1042  QVector< double > x1( part1Size );
 
 1043  QVector< double > y1( part1Size );
 
 1044  QVector< double > z1( useZ ? part1Size : 0 );
 
 1045  QVector< double > m1( useM ? part1Size : 0 );
 
 1047  const double *sourceX = mX.constData();
 
 1048  const double *sourceY = mY.constData();
 
 1049  const double *sourceZ = useZ ? mZ.constData() : 
nullptr;
 
 1050  const double *sourceM = useM ? mM.constData() : 
nullptr;
 
 1052  double *destX = x1.data();
 
 1053  double *destY = y1.data();
 
 1054  double *destZ = useZ ? z1.data() : 
nullptr;
 
 1055  double *destM = useM ? m1.data() : 
nullptr;
 
 1057  std::copy( sourceX, sourceX + part1Size, destX );
 
 1058  std::copy( sourceY, sourceY + part1Size, destY );
 
 1060    std::copy( sourceZ, sourceZ + part1Size, destZ );
 
 1062    std::copy( sourceM, sourceM + part1Size, destM );
 
 1064  const int part2Size = size - index;
 
 1065  if ( part2Size < 2 )
 
 1066    return std::make_tuple( std::make_unique< QgsLineString >( x1, y1, z1, m1 ), std::make_unique< QgsLineString >() );
 
 1068  QVector< double > x2( part2Size );
 
 1069  QVector< double > y2( part2Size );
 
 1070  QVector< double > z2( useZ ? part2Size : 0 );
 
 1071  QVector< double > m2( useM ? part2Size : 0 );
 
 1074  destZ = useZ ? z2.data() : 
nullptr;
 
 1075  destM = useM ? m2.data() : 
nullptr;
 
 1076  std::copy( sourceX + index, sourceX + size, destX );
 
 1077  std::copy( sourceY + index, sourceY + size, destY );
 
 1079    std::copy( sourceZ + index, sourceZ + size, destZ );
 
 1081    std::copy( sourceM + index, sourceM + size, destM );
 
 1083  if ( part1Size < 2 )
 
 1084    return std::make_tuple( std::make_unique< QgsLineString >(), std::make_unique< QgsLineString >( x2, y2, z2, m2 ) );
 
 1086    return std::make_tuple( std::make_unique< QgsLineString >( x1, y1, z1, m1 ), std::make_unique< QgsLineString >( x2, y2, z2, m2 ) );
 
 
 1094    const int size = mX.size();
 
 1098    const double *x = mX.constData();
 
 1099    const double *y = mY.constData();
 
 1100    const double *z = mZ.constData();
 
 1103    double prevX = *x++;
 
 1104    double prevY = *y++;
 
 1105    double prevZ = *z++;
 
 1107    for ( 
int i = 1; i < size; ++i )
 
 1112      total += std::sqrt( dx * dx + dy * dy + dz * dz );
 
 
 1152  Q_UNUSED( tolerance )
 
 1153  Q_UNUSED( toleranceType )
 
 
 1169  if ( i < 0 || i >= mX.size() )
 
 1174  double x = mX.at( i );
 
 1175  double y = mY.at( i );
 
 1176  double z = std::numeric_limits<double>::quiet_NaN();
 
 1177  double m = std::numeric_limits<double>::quiet_NaN();
 
 1195  else if ( hasZ && hasM )
 
 
 1218  if ( index >= 0 && index < mX.size() )
 
 1219    return mX.at( index );
 
 
 1226  if ( index >= 0 && index < mY.size() )
 
 1227    return mY.at( index );
 
 
 1234  if ( index >= 0 && index < mX.size() )
 
 
 1241  if ( index >= 0 && index < mY.size() )
 
 
 1256  pts.reserve( nPoints );
 
 1257  for ( 
int i = 0; i < nPoints; ++i )
 
 1259    pts.push_back( 
pointN( i ) );
 
 
 1273  const bool hasZ = 
static_cast< bool >( z );
 
 1274  const bool hasM = 
static_cast< bool >( m );
 
 1295  double *destX = mX.data();
 
 1296  double *destY = mY.data();
 
 1297  double *destZ = 
nullptr;
 
 1307  double *destM = 
nullptr;
 
 1318  for ( 
size_t i = 0; i < size; ++i )
 
 
 1345  bool hasZ = firstPt.
is3D();
 
 1350  mX.resize( 
points.size() );
 
 1351  mY.resize( 
points.size() );
 
 1354    mZ.resize( 
points.size() );
 
 1362    mM.resize( 
points.size() );
 
 1369  for ( 
int i = 0; i < 
points.size(); ++i )
 
 1371    mX[i] = 
points.at( i ).x();
 
 1372    mY[i] = 
points.at( i ).y();
 
 1375      double z = 
points.at( i ).z();
 
 1376      mZ[i] = std::isnan( z ) ? 0 : z;
 
 1380      double m = 
points.at( i ).m();
 
 1381      mM[i] = std::isnan( m ) ? 0 : m;
 
 
 1434      mZ.insert( mZ.count(), mX.size() - mZ.size(), std::numeric_limits<double>::quiet_NaN() );
 
 1447      mM.insert( mM.count(), mX.size() - mM.size(), std::numeric_limits<double>::quiet_NaN() );
 
 
 1457  std::reverse( copy->mX.begin(), copy->mX.end() );
 
 1458  std::reverse( copy->mY.begin(), copy->mY.end() );
 
 1461    std::reverse( copy->mZ.begin(), copy->mZ.end() );
 
 1465    std::reverse( copy->mM.begin(), copy->mM.end() );
 
 
 1470void QgsLineString::visitPointsByRegularDistance( 
const double distance, 
const std::function<
bool ( 
double, 
double, 
double, 
double, 
double, 
double, 
double, 
double, 
double, 
double, 
double, 
double )> &visitPoint )
 const 
 1475  double distanceTraversed = 0;
 
 1477  if ( totalPoints == 0 )
 
 1480  const double *x = mX.constData();
 
 1481  const double *y = mY.constData();
 
 1482  const double *z = 
is3D() ? mZ.constData() : 
nullptr;
 
 1483  const double *m = 
isMeasure() ? mM.constData() : 
nullptr;
 
 1485  double prevX = *x++;
 
 1486  double prevY = *y++;
 
 1487  double prevZ = z ? *z++ : 0.0;
 
 1488  double prevM = m ? *m++ : 0.0;
 
 1492    visitPoint( prevX, prevY, prevZ, prevM, prevX, prevY, prevZ, prevM, prevX, prevY, prevZ, prevM );
 
 1496  double pZ = std::numeric_limits<double>::quiet_NaN();
 
 1497  double pM = std::numeric_limits<double>::quiet_NaN();
 
 1498  double nextPointDistance = distance;
 
 1499  for ( 
int i = 1; i < totalPoints; ++i )
 
 1501    double thisX = *x++;
 
 1502    double thisY = *y++;
 
 1503    double thisZ = z ? *z++ : 0.0;
 
 1504    double thisM = m ? *m++ : 0.0;
 
 1510      const double distanceToPoint = std::min( nextPointDistance - distanceTraversed, 
segmentLength );
 
 1513          z ? &prevZ : 
nullptr, z ? &thisZ : 
nullptr, z ? &pZ : 
nullptr,
 
 1514          m ? &prevM : 
nullptr, m ? &thisM : 
nullptr, m ? &pM : nullptr );
 
 1516      if ( !visitPoint( pX, pY, pZ, pM, prevX, prevY, prevZ, prevM, thisX, thisY, thisZ, thisM ) )
 
 1519      nextPointDistance += distance;
 
 
 1541  std::unique_ptr< QgsPoint > res;
 
 1542  visitPointsByRegularDistance( distance, [ & ]( 
double x, 
double y, 
double z, 
double m, 
double, 
double, 
double, 
double, 
double, 
double, 
double, 
double )->
bool 
 1544    res = std::make_unique< QgsPoint >( pointType, x, y, z, m );
 
 1547  return res.release();
 
 
 1552  if ( startDistance < 0 && endDistance < 0 )
 
 1555  endDistance = std::max( startDistance, endDistance );
 
 1558  if ( totalPoints == 0 )
 
 1561  QVector< QgsPoint > substringPoints;
 
 1562  substringPoints.reserve( totalPoints );
 
 1570  const double *x = mX.constData();
 
 1571  const double *y = mY.constData();
 
 1572  const double *z = 
is3D() ? mZ.constData() : 
nullptr;
 
 1573  const double *m = 
isMeasure() ? mM.constData() : 
nullptr;
 
 1575  double distanceTraversed = 0;
 
 1576  double prevX = *x++;
 
 1577  double prevY = *y++;
 
 1578  double prevZ = z ? *z++ : 0.0;
 
 1579  double prevM = m ? *m++ : 0.0;
 
 1580  bool foundStart = 
false;
 
 1582  if ( startDistance < 0 )
 
 1585  for ( 
int i = 1; i < totalPoints; ++i )
 
 1587    double thisX = *x++;
 
 1588    double thisY = *y++;
 
 1589    double thisZ = z ? *z++ : 0.0;
 
 1590    double thisM = m ? *m++ : 0.0;
 
 1594    if ( distanceTraversed <= startDistance && startDistance < distanceTraversed + 
segmentLength )
 
 1597      const double distanceToStart = startDistance - distanceTraversed;
 
 1598      double startX, startY;
 
 1602          z ? &prevZ : 
nullptr, z ? &thisZ : 
nullptr, z ? &startZ : 
nullptr,
 
 1603          m ? &prevM : 
nullptr, m ? &thisM : 
nullptr, m ? &startM : nullptr );
 
 1604      substringPoints << 
QgsPoint( pointType, startX, startY, startZ, startM );
 
 1607    if ( foundStart && ( distanceTraversed + 
segmentLength > endDistance ) )
 
 1610      const double distanceToEnd = endDistance - distanceTraversed;
 
 1615          z ? &prevZ : 
nullptr, z ? &thisZ : 
nullptr, z ? &endZ : 
nullptr,
 
 1616          m ? &prevM : 
nullptr, m ? &thisM : 
nullptr, m ? &endM : nullptr );
 
 1617      substringPoints << 
QgsPoint( pointType, endX, endY, endZ, endM );
 
 1619    else if ( foundStart )
 
 1621      substringPoints << 
QgsPoint( pointType, thisX, thisY, thisZ, thisM );
 
 1629    if ( distanceTraversed >= endDistance )
 
 1634  if ( !foundStart && 
qgsDoubleNear( distanceTraversed, startDistance ) )
 
 1636    substringPoints << 
QgsPoint( pointType, prevX, prevY, prevZ, prevM )
 
 1637                    << 
QgsPoint( pointType, prevX, prevY, prevZ, prevM );
 
 
 1662  if ( path.isEmpty() || path.currentPosition() != QPointF( mX.at( 0 ), mY.at( 0 ) ) )
 
 1664    path.moveTo( mX.at( 0 ), mY.at( 0 ) );
 
 1667  for ( 
int i = 1; i < nPoints; ++i )
 
 1669    path.lineTo( mX.at( i ), mY.at( i ) );
 
 
 1682  return compoundCurve;
 
 
 1687  if ( mX.size() < 2 || mY.size() < 2 )
 
 1690  const bool extendStart = startDistance > 0;
 
 1691  const bool extendEnd = endDistance > 0;
 
 1696    const double currentLen = std::sqrt( std::pow( mX.at( 0 ) - mX.at( 1 ), 2 ) +
 
 1697                                         std::pow( mY.at( 0 ) - mY.at( 1 ), 2 ) );
 
 1698    const double newLen = currentLen + startDistance;
 
 1699    mX[ 0 ] = mX.at( 1 ) + ( mX.at( 0 ) - mX.at( 1 ) ) / currentLen * newLen;
 
 1700    mY[ 0 ] = mY.at( 1 ) + ( mY.at( 0 ) - mY.at( 1 ) ) / currentLen * newLen;
 
 1705    const int last = mX.size() - 1;
 
 1706    const double currentLen = std::sqrt( std::pow( mX.at( last ) - mX.at( last - 1 ), 2 ) +
 
 1707                                         std::pow( mY.at( last ) - mY.at( last - 1 ), 2 ) );
 
 1708    const double newLen = currentLen + endDistance;
 
 1709    mX[ last ] = mX.at( last - 1 ) + ( mX.at( last ) - mX.at( last - 1 ) ) / currentLen * newLen;
 
 1710    mY[ last ] = mY.at( last - 1 ) + ( mY.at( last ) - mY.at( last - 1 ) ) / currentLen * newLen;
 
 1713  if ( extendStart || extendEnd )
 
 
 1719  auto result = std::make_unique< QgsLineString >();
 
 1721  return result.release();
 
 
 1726  const QgsLineString *otherLine = qgsgeometry_cast<const QgsLineString *>( other );
 
 1730  const int size = mX.size();
 
 1731  const int otherSize = otherLine->mX.size();
 
 1732  if ( size > otherSize )
 
 1736  else if ( size < otherSize )
 
 1741  if ( 
is3D() && !otherLine->
is3D() )
 
 1743  else if ( !
is3D() && otherLine->
is3D() )
 
 1745  const bool considerZ = 
is3D();
 
 1753  for ( 
int i = 0; i < size; i++ )
 
 1755    const double x = mX[i];
 
 1756    const double otherX = otherLine->mX[i];
 
 1761    else if ( x > otherX )
 
 1766    const double y = mY[i];
 
 1767    const double otherY = otherLine->mY[i];
 
 1772    else if ( y > otherY )
 
 1779      const double z = mZ[i];
 
 1780      const double otherZ = otherLine->mZ[i];
 
 1786      else if ( z > otherZ )
 
 1794      const double m = mM[i];
 
 1795      const double otherM = otherLine->mM[i];
 
 1801      else if ( m > otherM )
 
 
 1812  return QStringLiteral( 
"LineString" );
 
 
 1828  double *zArray = 
nullptr;
 
 1834  std::unique_ptr< double[] > dummyZ;
 
 1835  if ( !hasZ || !transformZ )
 
 1837    dummyZ.reset( 
new double[nPoints]() );
 
 1838    zArray = dummyZ.get();
 
 
 1853  double *x = mX.data();
 
 1854  double *y = mY.data();
 
 1855  double *z = hasZ ? mZ.data() : 
nullptr;
 
 1856  double *m = hasM ? mM.data() : 
nullptr;
 
 1857  for ( 
int i = 0; i < nPoints; ++i )
 
 1860    t.map( *x, *y, &xOut, &yOut );
 
 1865      *z = *z * zScale + zTranslate;
 
 1870      *m = *m * mScale + mTranslate;
 
 
 1885  if ( position.
vertex < 0 || position.
vertex > mX.size() )
 
 1895  mX.insert( position.
vertex, vertex.
x() );
 
 1896  mY.insert( position.
vertex, vertex.
y() );
 
 1899    mZ.insert( position.
vertex, vertex.
z() );
 
 1903    mM.insert( position.
vertex, vertex.
m() );
 
 
 1911  if ( position.
vertex < 0 || position.
vertex >= mX.size() )
 
 1915  mX[position.
vertex] = newPos.
x();
 
 1916  mY[position.
vertex] = newPos.
y();
 
 1919    mZ[position.
vertex] = newPos.
z();
 
 1923    mM[position.
vertex] = newPos.
m();
 
 
 1931  if ( position.
vertex >= mX.size() || position.
vertex < 0 )
 
 1936  mX.remove( position.
vertex );
 
 1937  mY.remove( position.
vertex );
 
 1940    mZ.remove( position.
vertex );
 
 1944    mM.remove( position.
vertex );
 
 
 1969  mX.append( pt.
x() );
 
 1970  mY.append( pt.
y() );
 
 1973    mZ.append( pt.
z() );
 
 1977    mM.append( pt.
m() );
 
 
 1984  double sqrDist = std::numeric_limits<double>::max();
 
 1985  double leftOfDist = std::numeric_limits<double>::max();
 
 1987  double prevLeftOfX = 0.0;
 
 1988  double prevLeftOfY = 0.0;
 
 1989  double testDist = 0;
 
 1990  double segmentPtX, segmentPtY;
 
 1995  int size = mX.size();
 
 1996  if ( size == 0 || size == 1 )
 
 2001  for ( 
int i = 1; i < size; ++i )
 
 2003    double prevX = mX.at( i - 1 );
 
 2004    double prevY = mY.at( i - 1 );
 
 2005    double currentX = mX.at( i );
 
 2006    double currentY = mY.at( i );
 
 2008    if ( testDist < sqrDist )
 
 2011      segmentPt.
setX( segmentPtX );
 
 2012      segmentPt.
setY( segmentPtY );
 
 2013      vertexAfter.
part = 0;
 
 2014      vertexAfter.
ring = 0;
 
 2025        if ( 
qgsDoubleNear( testDist, leftOfDist ) && left != prevLeftOf && prevLeftOf != 0 )
 
 2037        prevLeftOf = *leftOf;
 
 2038        leftOfDist = testDist;
 
 2039        prevLeftOfX = prevX;
 
 2040        prevLeftOfY = prevY;
 
 2042      else if ( testDist < leftOfDist )
 
 2045        leftOfDist = testDist;
 
 
 2077    return QgsPoint( mX.at( 0 ), mY.at( 0 ) );
 
 2079  double totalLineLength = 0.0;
 
 2080  double prevX = mX.at( 0 );
 
 2081  double prevY = mY.at( 0 );
 
 2087    double currentX = mX.at( i );
 
 2088    double currentY = mY.at( i );
 
 2089    double segmentLength = std::sqrt( std::pow( currentX - prevX, 2.0 ) +
 
 2090                                      std::pow( currentY - prevY, 2.0 ) );
 
 2104    return QgsPoint( mX.at( 0 ), mY.at( 0 ) );
 
 2106    return QgsPoint( sumX / totalLineLength, sumY / totalLineLength );
 
 
 2125  const int maxIndex = mX.size();
 
 2132  const double *x = mX.constData();
 
 2133  const double *y = mY.constData();
 
 2134  double prevX = *x++;
 
 2135  double prevY = *y++;
 
 2136  for ( 
int i = 1; i < maxIndex; ++i )
 
 2138    mSummedUpArea += prevX * ( *y - prevY ) - prevY * ( *x - prevX );
 
 
 2148void QgsLineString::importVerticesFromWkb( 
const QgsConstWkbPtr &wkb )
 
 2154  mX.resize( nVertices );
 
 2155  mY.resize( nVertices );
 
 2156  hasZ ? mZ.resize( nVertices ) : mZ.clear();
 
 2157  hasM ? mM.resize( nVertices ) : mM.clear();
 
 2158  double *x = mX.data();
 
 2159  double *y = mY.data();
 
 2160  double *m = hasM ? mM.data() : 
nullptr;
 
 2161  double *z = hasZ ? mZ.data() : 
nullptr;
 
 2162  for ( 
int i = 0; i < nVertices; ++i )
 
 2195  if ( mX.count() < 2 )
 
 2205      double previousX = mX.at( 
numPoints() - 2 );
 
 2206      double previousY = mY.at( 
numPoints() - 2 );
 
 2207      double currentX = mX.at( 0 );
 
 2208      double currentY = mY.at( 0 );
 
 2209      double afterX = mX.at( 1 );
 
 2210      double afterY = mY.at( 1 );
 
 2213    else if ( vertex.
vertex == 0 )
 
 2226    double previousX = mX.at( vertex.
vertex - 1 );
 
 2227    double previousY = mY.at( vertex.
vertex - 1 );
 
 2228    double currentX = mX.at( vertex.
vertex );
 
 2229    double currentY = mY.at( vertex.
vertex );
 
 2230    double afterX = mX.at( vertex.
vertex + 1 );
 
 2231    double afterY = mY.at( vertex.
vertex + 1 );
 
 
 2238  if ( startVertex.
vertex < 0 || startVertex.
vertex >= mX.count() - 1 )
 
 2241  double dx = mX.at( startVertex.
vertex + 1 ) - mX.at( startVertex.
vertex );
 
 2242  double dy = mY.at( startVertex.
vertex + 1 ) - mY.at( startVertex.
vertex );
 
 2243  return std::sqrt( dx * dx + dy * dy );
 
 
 2268  mZ.reserve( nPoints );
 
 2269  for ( 
int i = 0; i < nPoints; ++i )
 
 
 2299  mM.reserve( nPoints );
 
 2300  for ( 
int i = 0; i < nPoints; ++i )
 
 
 2331  std::swap( mX, mY );
 
 
 2345    addZValue( std::numeric_limits<double>::quiet_NaN() );
 
 
 2362  int size = mX.size();
 
 2364  double *srcX = mX.data();
 
 2365  double *srcY = mY.data();
 
 2366  double *srcM = hasM ? mM.data() : 
nullptr;
 
 2367  double *srcZ = hasZ ? mZ.data() : 
nullptr;
 
 2370  for ( 
int i = 0; i < size; ++i )
 
 2374    double z = hasZ ? *srcZ : std::numeric_limits<double>::quiet_NaN();
 
 2375    double m = hasM ? *srcM : std::numeric_limits<double>::quiet_NaN();
 
 
 2403  int size = mX.size();
 
 2405  double *srcX = mX.data();
 
 2406  double *srcY = mY.data();
 
 2407  double *srcM = hasM ? mM.data() : 
nullptr;
 
 2408  double *srcZ = hasZ ? mZ.data() : 
nullptr;
 
 2410  double *destX = srcX;
 
 2411  double *destY = srcY;
 
 2412  double *destM = srcM;
 
 2413  double *destZ = srcZ;
 
 2415  int filteredPoints = 0;
 
 2416  for ( 
int i = 0; i < size; ++i )
 
 2420    double z = hasZ ? *srcZ++ : std::numeric_limits<double>::quiet_NaN();
 
 2421    double m = hasM ? *srcM++ : std::numeric_limits<double>::quiet_NaN();
 
 2423    if ( filter( 
QgsPoint( x, y, z, m ) ) )
 
 2435  mX.resize( filteredPoints );
 
 2436  mY.resize( filteredPoints );
 
 2438    mZ.resize( filteredPoints );
 
 2440    mM.resize( filteredPoints );
 
 
 2449  int size = mX.size();
 
 2451  double *srcX = mX.data();
 
 2452  double *srcY = mY.data();
 
 2453  double *srcM = hasM ? mM.data() : 
nullptr;
 
 2454  double *srcZ = hasZ ? mZ.data() : 
nullptr;
 
 2456  for ( 
int i = 0; i < size; ++i )
 
 2460    double z = hasZ ? *srcZ : std::numeric_limits<double>::quiet_NaN();
 
 2461    double m = hasM ? *srcM : std::numeric_limits<double>::quiet_NaN();
 
 
 2477  std::unique_ptr< QgsLineString > cloned( 
clone() );
 
 2481    return cloned.release();
 
 2484  if ( 
isEmpty() || ( nbpoints < 2 ) )
 
 2486    return cloned.release();
 
 2489  const double range = end - start;
 
 2490  double lineLength = 
length();
 
 2491  double lengthSoFar = 0.0;
 
 2494  double *mOut = cloned->mM.data();
 
 2496  for ( 
int i = 1; i < nbpoints ; ++i )
 
 2499    if ( lineLength > 0.0 )
 
 2500      *mOut++ = start + range * lengthSoFar / lineLength;
 
 2501    else if ( lineLength == 0.0 && nbpoints > 1 )
 
 2502      *mOut++ = start + range * i / ( nbpoints - 1 );
 
 2507  return cloned.release();
 
 
 2516  if ( totalPoints < 2 )
 
 2519  const double *
xData = mX.constData();
 
 2520  const double *
yData = mY.constData();
 
 2521  const double *
mData = mM.constData();
 
 2522  const double *
zData = 
is3D() ? mZ.constData() : 
nullptr;
 
 2523  use3DDistance &= 
is3D();
 
 2525  QVector< double > xOut( totalPoints );
 
 2526  QVector< double > yOut( totalPoints );
 
 2527  QVector< double > mOut( totalPoints );
 
 2528  QVector< double > zOut( 
is3D() ? totalPoints : 0 );
 
 2530  double *xOutData = xOut.data();
 
 2531  double *yOutData = yOut.data();
 
 2532  double *mOutData = mOut.data();
 
 2533  double *zOutData = 
is3D() ? zOut.data() : 
nullptr;
 
 2536  double currentSegmentLength = 0;
 
 2537  double lastValidM = std::numeric_limits< double >::quiet_NaN();
 
 2538  double prevX = *
xData;
 
 2539  double prevY = *
yData;
 
 2541  while ( i < totalPoints )
 
 2543    double thisX = *
xData++;
 
 2544    double thisY = *
yData++;
 
 2546    double thisM = *
mData++;
 
 2548    currentSegmentLength = use3DDistance
 
 2552    if ( !std::isnan( thisM ) )
 
 2554      *xOutData++ = thisX;
 
 2555      *yOutData++ = thisY;
 
 2556      *mOutData++ = thisM;
 
 2558        *zOutData++ = thisZ;
 
 2565      double scanAheadM = thisM;
 
 2566      while ( i + j + 1 < totalPoints && std::isnan( scanAheadM ) )
 
 2568        scanAheadM = 
mData[ j ];
 
 2571      if ( std::isnan( scanAheadM ) )
 
 2576      *xOutData++ = thisX;
 
 2577      *yOutData++ = thisY;
 
 2578      *mOutData++ = scanAheadM;
 
 2580        *zOutData++ = thisZ;
 
 2581      for ( ; i < j; ++i )
 
 2585        *xOutData++ = thisX;
 
 2586        *yOutData++ = thisY;
 
 2587        *mOutData++ = scanAheadM;
 
 2590          *zOutData++ = *
zData++;
 
 2592      lastValidM = scanAheadM;
 
 2598      double scanAheadX = thisX;
 
 2599      double scanAheadY = thisY;
 
 2600      double scanAheadZ = thisZ;
 
 2601      double distanceToNextValidM = currentSegmentLength;
 
 2602      std::vector< double > scanAheadSegmentLengths;
 
 2603      scanAheadSegmentLengths.emplace_back( currentSegmentLength );
 
 2605      double nextValidM = std::numeric_limits< double >::quiet_NaN();
 
 2606      while ( i + j < totalPoints - 1 )
 
 2608        double nextScanAheadX = 
xData[j];
 
 2609        double nextScanAheadY = 
yData[j];
 
 2610        double nextScanAheadZ = 
zData ? 
zData[j] : 0;
 
 2611        double nextScanAheadM = 
mData[ j ];
 
 2612        const double scanAheadSegmentLength = use3DDistance
 
 2615        scanAheadSegmentLengths.emplace_back( scanAheadSegmentLength );
 
 2616        distanceToNextValidM += scanAheadSegmentLength;
 
 2618        if ( !std::isnan( nextScanAheadM ) )
 
 2620          nextValidM = nextScanAheadM;
 
 2624        scanAheadX = nextScanAheadX;
 
 2625        scanAheadY = nextScanAheadY;
 
 2626        scanAheadZ = nextScanAheadZ;
 
 2630      if ( std::isnan( nextValidM ) )
 
 2633        *xOutData++ = thisX;
 
 2634        *yOutData++ = thisY;
 
 2635        *mOutData++ = lastValidM;
 
 2637          *zOutData++ = thisZ;
 
 2639        for ( ; i < totalPoints; ++i )
 
 2641          *xOutData++ = *
xData++;
 
 2642          *yOutData++ = *
yData++;
 
 2643          *mOutData++ = lastValidM;
 
 2645            *zOutData++ = *
zData++;
 
 2652        const double delta = ( nextValidM - lastValidM ) / distanceToNextValidM;
 
 2653        *xOutData++ = thisX;
 
 2654        *yOutData++ = thisY;
 
 2655        *mOutData++ = lastValidM + delta * scanAheadSegmentLengths[0];
 
 2656        double totalScanAheadLength = scanAheadSegmentLengths[0];
 
 2658          *zOutData++ = thisZ;
 
 2659        for ( 
int k = 1; k <= j; ++i, ++k )
 
 2663          *xOutData++ = thisX;
 
 2664          *yOutData++ = thisY;
 
 2665          totalScanAheadLength += scanAheadSegmentLengths[k];
 
 2666          *mOutData++ = lastValidM + delta * totalScanAheadLength;
 
 2669            *zOutData++ = *
zData++;
 
 2671        lastValidM = nextValidM;
 
 
QFlags< GeometryValidityFlag > GeometryValidityFlags
Geometry validity flags.
 
VertexType
Types of vertex.
 
@ Segment
The actual start or end point of a segment.
 
WkbType
The WKB type describes the number of dimensions a geometry has.
 
@ LineString25D
LineString25D.
 
@ LineStringM
LineStringM.
 
@ LineStringZM
LineStringZM.
 
@ LineStringZ
LineStringZ.
 
TransformDirection
Indicates the direction (forward or inverse) of a transform.
 
Abstract base class for all geometries.
 
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
 
virtual bool convertTo(Qgis::WkbType type)
Converts the geometry to a specified type.
 
bool isMeasure() const
Returns true if the geometry contains m values.
 
QFlags< WkbFlag > WkbFlags
 
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
 
AxisOrder
Axis order for GML generation.
 
QString wktTypeStr() const
Returns the WKT type string of the geometry.
 
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
 
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, Qgis::WkbType baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
 
virtual bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
 
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
 
static endian_t endian()
Returns whether this machine uses big or little endian.
 
A 3-dimensional box composed of x, y, z coordinates.
 
bool intersects(const QgsBox3D &other) const
Returns true if box intersects with another box.
 
bool contains(const QgsBox3D &other) const
Returns true when box contains other box.
 
QgsRectangle toRectangle() const
Converts the box to a 2D rectangle.
 
bool isNull() const
Test if the box is null (holding no spatial information).
 
Compound curve geometry type.
 
void addCurve(QgsCurve *c, bool extendPrevious=false)
Adds a curve to the geometry (takes ownership).
 
Qgis::WkbType readHeader() const
readHeader
 
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
 
bool mHasCachedSummedUpArea
 
virtual bool isRing() const
Returns true if the curve is a ring.
 
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
 
bool snapToGridPrivate(double hSpacing, double vSpacing, double dSpacing, double mSpacing, const QVector< double > &srcX, const QVector< double > &srcY, const QVector< double > &srcZ, const QVector< double > &srcM, QVector< double > &outX, QVector< double > &outY, QVector< double > &outZ, QVector< double > &outM, bool removeRedundantPoints) const
Helper function for QgsCurve subclasses to snap to grids.
 
QgsBox3D mBoundingBox
Cached bounding box.
 
Base class for feedback objects to be used for cancellation of something running in a worker thread.
 
bool isCanceled() const
Tells whether the operation has been canceled already.
 
static void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...
 
static double distance2D(double x1, double y1, double x2, double y2)
Returns the 2D distance between (x1, y1) and (x2, y2).
 
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
 
static double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3)
Calculates the average angle (in radians) between the two linear segments from (x1,...
 
static double distance3D(double x1, double y1, double z1, double x2, double y2, double z2)
Returns the 3D distance between (x1, y1, z1) and (x2, y2, z2).
 
static double sqrDistToLine(double ptX, double ptY, double x1, double y1, double x2, double y2, double &minDistX, double &minDistY, double epsilon)
Returns the squared distance between a point and a line.
 
static int leftOfLine(const double x, const double y, const double x1, const double y1, const double x2, const double y2)
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> (x2, y2).
 
static json pointsToJson(const QgsPointSequence &points, int precision)
Returns coordinates as json object.
 
static void pointsToWKB(QgsWkbPtr &wkb, const QgsPointSequence &points, bool is3D, bool isMeasure, QgsAbstractGeometry::WkbFlags flags)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
 
static QPair< Qgis::WkbType, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
 
static QgsPointSequence pointsFromWKT(const QString &wktCoordinateList, bool is3D, bool isMeasure)
Returns a list of points contained in a WKT string.
 
static QDomElement pointsToGML2(const QgsPointSequence &points, QDomDocument &doc, int precision, const QString &ns, QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY)
Returns a gml::coordinates DOM element.
 
static QDomElement pointsToGML3(const QgsPointSequence &points, QDomDocument &doc, int precision, const QString &ns, bool is3D, QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY)
Returns a gml::posList DOM element.
 
static QString pointsToWKT(const QgsPointSequence &points, int precision, bool is3D, bool isMeasure)
Returns a WKT coordinate list.
 
Represents a single 2D line segment, consisting of a 2D start and end vertex only.
 
Line string geometry type, with support for z-dimension and m-values.
 
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
 
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
 
bool pointAt(int node, QgsPoint &point, Qgis::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
 
bool isClosed() const override
Returns true if the curve is closed.
 
void swapXy() override
Swaps the x and y coordinates from the geometry.
 
const double * yData() const
Returns a const pointer to the y vertex data.
 
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
 
const double * xData() const
Returns a const pointer to the x vertex data.
 
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
 
double length() const override
Returns the planar, 2-dimensional length of the geometry.
 
double length3D() const
Returns the length in 3D world of the line string.
 
void points(QgsPointSequence &pt) const override
Returns a list of points within the curve.
 
QgsLineString * simplifyByDistance(double tolerance) const override
Simplifies the geometry by applying the Douglas Peucker simplification by distance algorithm.
 
int dimension() const override
Returns the inherent dimension of the geometry.
 
void sumUpArea(double &sum) const override
Calculates the shoelace/triangle formula sum for the points in the linestring.
 
void clear() override
Clears the geometry, ie reset it to a null geometry.
 
const double * zData() const
Returns a const pointer to the z vertex data, or nullptr if the linestring does not have z values.
 
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
 
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
 
QgsPoint startPoint() const override
Returns the starting point of the curve.
 
void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
 
QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a new line string geometry corresponding to a segmentized approximation of the curve.
 
QgsLineString * interpolateM(bool use3DDistance=true) const
Returns a copy of this line with all missing (NaN) m values interpolated from m values of surrounding...
 
bool isEmpty() const override
Returns true if the geometry is empty.
 
static QgsLineString * fromBezierCurve(const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments=30)
Returns a new linestring created by segmentizing the bezier curve between start and end,...
 
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
 
int numPoints() const override
Returns the number of points in the curve.
 
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
 
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
 
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
 
QgsLineString()
Constructor for an empty linestring geometry.
 
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
 
QString asKml(int precision=17) const override
Returns a KML representation of the geometry.
 
int wkbSize(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns the length of the QByteArray returned by asWkb()
 
void setPoints(size_t size, const double *x, const double *y, const double *z=nullptr, const double *m=nullptr)
Resets the line string to match the specified point data.
 
QgsPoint centroid() const override
Returns the centroid of the geometry.
 
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
 
QPolygonF asQPolygonF() const override
Returns a QPolygonF representing the points.
 
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
 
void scroll(int firstVertexIndex) final
Scrolls the curve vertices so that they start with the vertex at the given index.
 
bool boundingBoxIntersects(const QgsRectangle &rectangle) const override
Returns true if the bounding box of this geometry intersects with a rectangle.
 
QString geometryType() const override
Returns a unique string representing the geometry type.
 
QgsLineString * measuredLine(double start, double end) const
Re-write the measure ordinate (or add one, if it isn't already there) interpolating the measure betwe...
 
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
 
QgsPoint endPoint() const override
Returns the end point of the curve.
 
void setYAt(int index, double y)
Sets the y-coordinate of the specified node in the line string.
 
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
 
QgsLineString * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
 
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
 
static QgsLineString * fromQPolygonF(const QPolygonF &polygon)
Returns a new linestring from a QPolygonF polygon input.
 
void close()
Closes the line string by appending the first point to the end of the line, if it is not already clos...
 
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
 
int indexOf(const QgsPoint &point) const final
Returns the index of the first vertex matching the given point, or -1 if a matching vertex is not fou...
 
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
 
void extend(double startDistance, double endDistance)
Extends the line geometry by extrapolating out the start or end of the line by a specified distance.
 
QgsCompoundCurve * toCurveType() const override
Returns the geometry converted to the more generic curve type QgsCompoundCurve.
 
void append(const QgsLineString *line)
Appends the contents of another line string to the end of this line string.
 
QgsLineString * curveSubstring(double startDistance, double endDistance) const override
Returns a new curve representing a substring of this curve.
 
QgsBox3D calculateBoundingBox3D() const override
Calculates the minimal 3D bounding box for the geometry.
 
std::tuple< std::unique_ptr< QgsCurve >, std::unique_ptr< QgsCurve > > splitCurveAtVertex(int index) const final
Splits the curve at the specified vertex index, returning two curves which represent the portion of t...
 
void addToPainterPath(QPainterPath &path) const override
Adds a curve to a painter path.
 
void visitPointsByRegularDistance(double distance, const std::function< bool(double x, double y, double z, double m, double startSegmentX, double startSegmentY, double startSegmentZ, double startSegmentM, double endSegmentX, double endSegmentY, double endSegmentZ, double endSegmentM) > &visitPoint) const
Visits regular points along the linestring, spaced by distance.
 
void setXAt(int index, double x)
Sets the x-coordinate of the specified node in the line string.
 
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
 
double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *std::numeric_limits< double >::epsilon()) const override
Searches for the closest segment of the geometry to a given point.
 
QVector< QgsVertexId > collectDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) const
Returns a list of any duplicate nodes contained in the geometry, within the specified tolerance.
 
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
 
const double * mData() const
Returns a const pointer to the m vertex data, or nullptr if the linestring does not have m values.
 
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
 
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
 
int compareToSameClass(const QgsAbstractGeometry *other) const final
Compares to an other geometry of the same class, and returns a integer for sorting of the two geometr...
 
bool dropMValue() override
Drops any measure values which exist in the geometry.
 
Q_DECL_DEPRECATED QgsBox3D calculateBoundingBox3d() const
Calculates the minimal 3D bounding box for the geometry.
 
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
 
void filterVertices(const std::function< bool(const QgsPoint &) > &filter) override
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
 
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns a WKB representation of the geometry.
 
void transformVertices(const std::function< QgsPoint(const QgsPoint &) > &transform) override
Transforms the vertices from the geometry in place, applying the transform function to every vertex.
 
QgsLineString * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
 
bool convertTo(Qgis::WkbType type) override
Converts the geometry to a specified type.
 
bool isClosed2D() const override
Returns true if the curve is closed.
 
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
 
QgsPoint * interpolatePoint(double distance) const override
Returns an interpolated point on the curve at the specified distance.
 
QgsLineString * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0, bool removeRedundantPoints=false) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
 
A class to represent a 2D point.
 
Point geometry type, with support for z-dimension and m-values.
 
void setY(double y)
Sets the point's y-coordinate.
 
void setX(double x)
Sets the point's x-coordinate.
 
A rectangle specified with double values.
 
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
 
static Qgis::WkbType dropM(Qgis::WkbType type)
Drops the m dimension (if present) for a WKB type and returns the new type.
 
static Qgis::WkbType zmType(Qgis::WkbType type, bool hasZ, bool hasM)
Returns the modified input geometry type according to hasZ / hasM.
 
static Qgis::WkbType dropZ(Qgis::WkbType type)
Drops the z dimension (if present) for a WKB type and returns the new type.
 
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
 
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
 
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
 
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
 
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
 
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
 
QVector< QgsPoint > QgsPointSequence
 
void simplifySection(int i, int j, const double *x, const double *y, std::vector< bool > &usePoint, const double distanceToleranceSquared, const double epsilon)
 
QLineF segment(int index, QRectF rect, double radius)
 
Utility class for identifying a unique vertex within a geometry.