mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	[FEATURE][delimiter text] Add Point{Z,M,ZM} geometry support (fixes #25645)
			
			
This commit is contained in:
		
							parent
							
								
									87b1aa9a5d
								
							
						
					
					
						commit
						5df309447e
					
				@ -431,13 +431,25 @@ QgsGeometry QgsDelimitedTextFeatureIterator::loadGeometryXY( const QStringList &
 | 
			
		||||
    isNull = true;
 | 
			
		||||
    return QgsGeometry();
 | 
			
		||||
  }
 | 
			
		||||
  isNull = false;
 | 
			
		||||
  QgsPointXY pt;
 | 
			
		||||
  bool ok = QgsDelimitedTextProvider::pointFromXY( sX, sY, pt, mSource->mDecimalPoint, mSource->mXyDms );
 | 
			
		||||
 | 
			
		||||
  if ( ok && wantGeometry( pt ) )
 | 
			
		||||
  isNull = false;
 | 
			
		||||
  QgsPoint *pt = new QgsPoint();
 | 
			
		||||
  bool ok = QgsDelimitedTextProvider::pointFromXY( sX, sY, *pt, mSource->mDecimalPoint, mSource->mXyDms );
 | 
			
		||||
 | 
			
		||||
  QString sZ, sM;
 | 
			
		||||
  if ( mSource->mZFieldIndex > -1 )
 | 
			
		||||
    sZ = tokens[mSource->mZFieldIndex];
 | 
			
		||||
  if ( mSource->mMFieldIndex > -1 )
 | 
			
		||||
    sM = tokens[mSource->mMFieldIndex];
 | 
			
		||||
 | 
			
		||||
  if ( !sZ.isEmpty() || !sM.isEmpty() )
 | 
			
		||||
  {
 | 
			
		||||
    return QgsGeometry::fromPointXY( pt );
 | 
			
		||||
    QgsDelimitedTextProvider::appendZM( sZ, sM, *pt, mSource->mDecimalPoint );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if ( ok && wantGeometry( *pt ) )
 | 
			
		||||
  {
 | 
			
		||||
    return QgsGeometry( pt );
 | 
			
		||||
  }
 | 
			
		||||
  return QgsGeometry();
 | 
			
		||||
}
 | 
			
		||||
@ -511,6 +523,8 @@ QgsDelimitedTextFeatureSource::QgsDelimitedTextFeatureSource( const QgsDelimited
 | 
			
		||||
  , mFieldCount( p->mFieldCount )
 | 
			
		||||
  , mXFieldIndex( p->mXFieldIndex )
 | 
			
		||||
  , mYFieldIndex( p->mYFieldIndex )
 | 
			
		||||
  , mZFieldIndex( p->mZFieldIndex )
 | 
			
		||||
  , mMFieldIndex( p->mMFieldIndex )
 | 
			
		||||
  , mWktFieldIndex( p->mWktFieldIndex )
 | 
			
		||||
  , mWktHasPrefix( p->mWktHasPrefix )
 | 
			
		||||
  , mGeometryType( p->mGeometryType )
 | 
			
		||||
 | 
			
		||||
@ -43,6 +43,8 @@ class QgsDelimitedTextFeatureSource : public QgsAbstractFeatureSource
 | 
			
		||||
    int mFieldCount;  // Note: this includes field count for wkt field
 | 
			
		||||
    int mXFieldIndex;
 | 
			
		||||
    int mYFieldIndex;
 | 
			
		||||
    int mZFieldIndex;
 | 
			
		||||
    int mMFieldIndex;
 | 
			
		||||
    int mWktFieldIndex;
 | 
			
		||||
    bool mWktHasPrefix;
 | 
			
		||||
    QgsWkbTypes::GeometryType mGeometryType;
 | 
			
		||||
 | 
			
		||||
@ -101,8 +101,14 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( const QString &uri, const Pr
 | 
			
		||||
      mGeometryType = QgsWkbTypes::PointGeometry;
 | 
			
		||||
      mXFieldName = url.queryItemValue( QStringLiteral( "xField" ) );
 | 
			
		||||
      mYFieldName = url.queryItemValue( QStringLiteral( "yField" ) );
 | 
			
		||||
      if ( url.hasQueryItem( QStringLiteral( "zField" ) ) )
 | 
			
		||||
        mZFieldName = url.queryItemValue( QStringLiteral( "zField" ) );
 | 
			
		||||
      if ( url.hasQueryItem( QStringLiteral( "mField" ) ) )
 | 
			
		||||
        mMFieldName = url.queryItemValue( QStringLiteral( "mField" ) );
 | 
			
		||||
      QgsDebugMsg( "xField is: " + mXFieldName );
 | 
			
		||||
      QgsDebugMsg( "yField is: " + mYFieldName );
 | 
			
		||||
      QgsDebugMsg( "zField is: " + mZFieldName );
 | 
			
		||||
      QgsDebugMsg( "mField is: " + mMFieldName );
 | 
			
		||||
 | 
			
		||||
      if ( url.hasQueryItem( QStringLiteral( "xyDms" ) ) )
 | 
			
		||||
      {
 | 
			
		||||
@ -336,11 +342,27 @@ void QgsDelimitedTextProvider::scanFile( bool buildIndexes )
 | 
			
		||||
    mYFieldIndex = mFile->fieldIndex( mYFieldName );
 | 
			
		||||
    if ( mXFieldIndex < 0 )
 | 
			
		||||
    {
 | 
			
		||||
      messages.append( tr( "%0 field %1 is not defined in delimited text file" ).arg( QStringLiteral( "X" ), mWktFieldName ) );
 | 
			
		||||
      messages.append( tr( "%0 field %1 is not defined in delimited text file" ).arg( QStringLiteral( "X" ), mXFieldName ) );
 | 
			
		||||
    }
 | 
			
		||||
    if ( mYFieldIndex < 0 )
 | 
			
		||||
    {
 | 
			
		||||
      messages.append( tr( "%0 field %1 is not defined in delimited text file" ).arg( QStringLiteral( "Y" ), mWktFieldName ) );
 | 
			
		||||
      messages.append( tr( "%0 field %1 is not defined in delimited text file" ).arg( QStringLiteral( "Y" ), mYFieldName ) );
 | 
			
		||||
    }
 | 
			
		||||
    if ( !mZFieldName.isEmpty() )
 | 
			
		||||
    {
 | 
			
		||||
      mZFieldIndex = mFile->fieldIndex( mZFieldName );
 | 
			
		||||
      if ( mZFieldIndex < 0 )
 | 
			
		||||
      {
 | 
			
		||||
        messages.append( tr( "%0 field %1 is not defined in delimited text file" ).arg( QStringLiteral( "Z" ), mZFieldName ) );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if ( !mMFieldName.isEmpty() )
 | 
			
		||||
    {
 | 
			
		||||
      mMFieldIndex = mFile->fieldIndex( mMFieldName );
 | 
			
		||||
      if ( mMFieldIndex < 0 )
 | 
			
		||||
      {
 | 
			
		||||
        messages.append( tr( "%0 field %1 is not defined in delimited text file" ).arg( QStringLiteral( "M" ), mMFieldName ) );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if ( !messages.isEmpty() )
 | 
			
		||||
@ -466,6 +488,11 @@ void QgsDelimitedTextProvider::scanFile( bool buildIndexes )
 | 
			
		||||
 | 
			
		||||
      QString sX = mXFieldIndex < parts.size() ? parts[mXFieldIndex] : QString();
 | 
			
		||||
      QString sY = mYFieldIndex < parts.size() ? parts[mYFieldIndex] : QString();
 | 
			
		||||
      QString sZ, sM;
 | 
			
		||||
      if ( mZFieldIndex > -1 )
 | 
			
		||||
        sZ = mZFieldIndex < parts.size() ? parts[mZFieldIndex] : QString();
 | 
			
		||||
      if ( mMFieldIndex > -1 )
 | 
			
		||||
        sM = mMFieldIndex < parts.size() ? parts[mMFieldIndex] : QString();
 | 
			
		||||
      if ( sX.isEmpty() && sY.isEmpty() )
 | 
			
		||||
      {
 | 
			
		||||
        nEmptyGeometry++;
 | 
			
		||||
@ -473,11 +500,14 @@ void QgsDelimitedTextProvider::scanFile( bool buildIndexes )
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
        QgsPointXY pt;
 | 
			
		||||
        QgsPoint pt;
 | 
			
		||||
        bool ok = pointFromXY( sX, sY, pt, mDecimalPoint, mXyDms );
 | 
			
		||||
 | 
			
		||||
        if ( ok )
 | 
			
		||||
        {
 | 
			
		||||
          if ( !sZ.isEmpty() || sM.isEmpty() )
 | 
			
		||||
            appendZM( sZ, sM, pt, mDecimalPoint );
 | 
			
		||||
 | 
			
		||||
          if ( foundFirstGeometry )
 | 
			
		||||
          {
 | 
			
		||||
            mExtent.combineExtentWith( pt.x(), pt.y() );
 | 
			
		||||
@ -487,6 +517,10 @@ void QgsDelimitedTextProvider::scanFile( bool buildIndexes )
 | 
			
		||||
            // Extent for the first point is just the first point
 | 
			
		||||
            mExtent.set( pt.x(), pt.y(), pt.x(), pt.y() );
 | 
			
		||||
            mWkbType = QgsWkbTypes::Point;
 | 
			
		||||
            if ( mZFieldIndex > -1 )
 | 
			
		||||
              mWkbType = QgsWkbTypes::addZ( mWkbType );
 | 
			
		||||
            if ( mMFieldIndex > -1 )
 | 
			
		||||
              mWkbType = QgsWkbTypes::addM( mWkbType );
 | 
			
		||||
            mGeometryType = QgsWkbTypes::PointGeometry;
 | 
			
		||||
            foundFirstGeometry = true;
 | 
			
		||||
          }
 | 
			
		||||
@ -841,7 +875,31 @@ double QgsDelimitedTextProvider::dmsStringToDouble( const QString &sX, bool *xOk
 | 
			
		||||
  return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsDelimitedTextProvider::pointFromXY( QString &sX, QString &sY, QgsPointXY &pt, const QString &decimalPoint, bool xyDms )
 | 
			
		||||
void QgsDelimitedTextProvider::appendZM( QString &sZ, QString &sM, QgsPoint &point, const QString &decimalPoint )
 | 
			
		||||
{
 | 
			
		||||
  if ( ! decimalPoint.isEmpty() )
 | 
			
		||||
  {
 | 
			
		||||
    sZ.replace( decimalPoint, QLatin1String( "." ) );
 | 
			
		||||
    sM.replace( decimalPoint, QLatin1String( "." ) );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool zOk, mOk;
 | 
			
		||||
  double z, m;
 | 
			
		||||
  if ( !sZ.isEmpty() )
 | 
			
		||||
  {
 | 
			
		||||
    z = sZ.toDouble( &zOk );
 | 
			
		||||
    if ( zOk )
 | 
			
		||||
      point.addZValue( z );
 | 
			
		||||
  }
 | 
			
		||||
  if ( !sM.isEmpty() )
 | 
			
		||||
  {
 | 
			
		||||
    m = sM.toDouble( &mOk );
 | 
			
		||||
    if ( mOk )
 | 
			
		||||
      point.addMValue( m );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsDelimitedTextProvider::pointFromXY( QString &sX, QString &sY, QgsPoint &pt, const QString &decimalPoint, bool xyDms )
 | 
			
		||||
{
 | 
			
		||||
  if ( ! decimalPoint.isEmpty() )
 | 
			
		||||
  {
 | 
			
		||||
 | 
			
		||||
@ -211,7 +211,8 @@ class QgsDelimitedTextProvider : public QgsVectorDataProvider
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    static QgsGeometry geomFromWkt( QString &sWkt, bool wktHasPrefixRegexp );
 | 
			
		||||
    static bool pointFromXY( QString &sX, QString &sY, QgsPointXY &point, const QString &decimalPoint, bool xyDms );
 | 
			
		||||
    static bool pointFromXY( QString &sX, QString &sY, QgsPoint &point, const QString &decimalPoint, bool xyDms );
 | 
			
		||||
    static void appendZM( QString &sZ, QString &sM, QgsPoint &point, const QString &decimalPoint );
 | 
			
		||||
    static double dmsStringToDouble( const QString &sX, bool *xOk );
 | 
			
		||||
 | 
			
		||||
    // mLayerValid defines whether the layer has been loaded as a valid layer
 | 
			
		||||
@ -232,10 +233,14 @@ class QgsDelimitedTextProvider : public QgsVectorDataProvider
 | 
			
		||||
    QString mWktFieldName;
 | 
			
		||||
    QString mXFieldName;
 | 
			
		||||
    QString mYFieldName;
 | 
			
		||||
    QString mZFieldName;
 | 
			
		||||
    QString mMFieldName;
 | 
			
		||||
    bool mDetectTypes = true;
 | 
			
		||||
 | 
			
		||||
    mutable int mXFieldIndex = -1;
 | 
			
		||||
    mutable int mYFieldIndex = -1;
 | 
			
		||||
    mutable int mZFieldIndex = -1;
 | 
			
		||||
    mutable int mMFieldIndex = -1;
 | 
			
		||||
    mutable int mWktFieldIndex = -1;
 | 
			
		||||
 | 
			
		||||
    // mWktPrefix regexp is used to clean up
 | 
			
		||||
 | 
			
		||||
@ -152,13 +152,24 @@ void QgsDelimitedTextSourceSelect::addButtonClicked()
 | 
			
		||||
  bool haveGeom = true;
 | 
			
		||||
  if ( geomTypeXY->isChecked() )
 | 
			
		||||
  {
 | 
			
		||||
    QString field;
 | 
			
		||||
    if ( !cmbXField->currentText().isEmpty() && !cmbYField->currentText().isEmpty() )
 | 
			
		||||
    {
 | 
			
		||||
      QString field = cmbXField->currentText();
 | 
			
		||||
      field = cmbXField->currentText();
 | 
			
		||||
      url.addQueryItem( QStringLiteral( "xField" ), field );
 | 
			
		||||
      field = cmbYField->currentText();
 | 
			
		||||
      url.addQueryItem( QStringLiteral( "yField" ), field );
 | 
			
		||||
    }
 | 
			
		||||
    if ( !cmbZField->currentText().isEmpty() )
 | 
			
		||||
    {
 | 
			
		||||
      field = cmbZField->currentText();
 | 
			
		||||
      url.addQueryItem( QStringLiteral( "zField" ), field );
 | 
			
		||||
    }
 | 
			
		||||
    if ( !cmbMField->currentText().isEmpty() )
 | 
			
		||||
    {
 | 
			
		||||
      field = cmbMField->currentText();
 | 
			
		||||
      url.addQueryItem( QStringLiteral( "mField" ), field );
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else if ( geomTypeWKT->isChecked() )
 | 
			
		||||
  {
 | 
			
		||||
@ -407,11 +418,15 @@ void QgsDelimitedTextSourceSelect::updateFieldLists()
 | 
			
		||||
 | 
			
		||||
  QString columnX = cmbXField->currentText();
 | 
			
		||||
  QString columnY = cmbYField->currentText();
 | 
			
		||||
  QString columnZ = cmbZField->currentText();
 | 
			
		||||
  QString columnM = cmbMField->currentText();
 | 
			
		||||
  QString columnWkt = cmbWktField->currentText();
 | 
			
		||||
 | 
			
		||||
  // clear the field lists
 | 
			
		||||
  cmbXField->clear();
 | 
			
		||||
  cmbYField->clear();
 | 
			
		||||
  cmbZField->clear();
 | 
			
		||||
  cmbMField->clear();
 | 
			
		||||
  cmbWktField->clear();
 | 
			
		||||
 | 
			
		||||
  // clear the sample text box
 | 
			
		||||
@ -532,6 +547,8 @@ void QgsDelimitedTextSourceSelect::updateFieldLists()
 | 
			
		||||
    if ( field.isEmpty() ) continue;
 | 
			
		||||
    cmbXField->addItem( field );
 | 
			
		||||
    cmbYField->addItem( field );
 | 
			
		||||
    cmbZField->addItem( field );
 | 
			
		||||
    cmbMField->addItem( field );
 | 
			
		||||
    cmbWktField->addItem( field );
 | 
			
		||||
    fieldNo++;
 | 
			
		||||
  }
 | 
			
		||||
@ -541,6 +558,8 @@ void QgsDelimitedTextSourceSelect::updateFieldLists()
 | 
			
		||||
  cmbWktField->setCurrentIndex( cmbWktField->findText( columnWkt ) );
 | 
			
		||||
  cmbXField->setCurrentIndex( cmbXField->findText( columnX ) );
 | 
			
		||||
  cmbYField->setCurrentIndex( cmbYField->findText( columnY ) );
 | 
			
		||||
  cmbZField->setCurrentIndex( cmbYField->findText( columnZ ) );
 | 
			
		||||
  cmbMField->setCurrentIndex( cmbYField->findText( columnM ) );
 | 
			
		||||
 | 
			
		||||
  // Now try setting optional X,Y fields - will only reset the fields if
 | 
			
		||||
  // not already set.
 | 
			
		||||
 | 
			
		||||
@ -879,7 +879,7 @@
 | 
			
		||||
              </property>
 | 
			
		||||
              <item>
 | 
			
		||||
               <layout class="QGridLayout" name="gridLayout_5" columnstretch="0,0">
 | 
			
		||||
                <item row="4" column="1">
 | 
			
		||||
                <item row="3" column="1" colspan="3">
 | 
			
		||||
                 <widget class="QCheckBox" name="cbxXyDms">
 | 
			
		||||
                  <property name="toolTip">
 | 
			
		||||
                   <string>X and Y coordinates are expressed in degrees/minutes/seconds</string>
 | 
			
		||||
@ -957,8 +957,70 @@
 | 
			
		||||
                  </property>
 | 
			
		||||
                 </widget>
 | 
			
		||||
                </item>
 | 
			
		||||
                <item row="1" column="3">
 | 
			
		||||
                 <widget class="QComboBox" name="cmbZField">
 | 
			
		||||
                  <property name="enabled">
 | 
			
		||||
                   <bool>true</bool>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="sizePolicy">
 | 
			
		||||
                   <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
 | 
			
		||||
                    <horstretch>0</horstretch>
 | 
			
		||||
                    <verstretch>0</verstretch>
 | 
			
		||||
                   </sizepolicy>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="minimumSize">
 | 
			
		||||
                   <size>
 | 
			
		||||
                    <width>120</width>
 | 
			
		||||
                    <height>0</height>
 | 
			
		||||
                   </size>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="toolTip">
 | 
			
		||||
                   <string>Name of the field containing z values</string>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="statusTip">
 | 
			
		||||
                   <string>Name of the field containing z values</string>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="whatsThis">
 | 
			
		||||
                   <string>Name of the field containing z values</string>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="editable">
 | 
			
		||||
                   <bool>false</bool>
 | 
			
		||||
                  </property>
 | 
			
		||||
                 </widget>
 | 
			
		||||
                </item>
 | 
			
		||||
                <item row="2" column="3">
 | 
			
		||||
                 <widget class="QComboBox" name="cmbMField">
 | 
			
		||||
                  <property name="enabled">
 | 
			
		||||
                   <bool>true</bool>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="sizePolicy">
 | 
			
		||||
                   <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
 | 
			
		||||
                    <horstretch>0</horstretch>
 | 
			
		||||
                    <verstretch>0</verstretch>
 | 
			
		||||
                   </sizepolicy>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="minimumSize">
 | 
			
		||||
                   <size>
 | 
			
		||||
                    <width>120</width>
 | 
			
		||||
                    <height>0</height>
 | 
			
		||||
                   </size>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="toolTip">
 | 
			
		||||
                   <string>Name of the field containing m values</string>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="statusTip">
 | 
			
		||||
                   <string>Name of the field containing m values</string>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="whatsThis">
 | 
			
		||||
                   <string>Name of the field containing m values</string>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="editable">
 | 
			
		||||
                   <bool>false</bool>
 | 
			
		||||
                  </property>
 | 
			
		||||
                 </widget>
 | 
			
		||||
                </item>
 | 
			
		||||
                <item row="1" column="0">
 | 
			
		||||
                 <widget class="QLabel" name="textLabelx">
 | 
			
		||||
                 <widget class="QLabel" name="textLabelX">
 | 
			
		||||
                  <property name="enabled">
 | 
			
		||||
                   <bool>true</bool>
 | 
			
		||||
                  </property>
 | 
			
		||||
@ -974,7 +1036,7 @@
 | 
			
		||||
                 </widget>
 | 
			
		||||
                </item>
 | 
			
		||||
                <item row="2" column="0">
 | 
			
		||||
                 <widget class="QLabel" name="textLabely">
 | 
			
		||||
                 <widget class="QLabel" name="textLabelY">
 | 
			
		||||
                  <property name="enabled">
 | 
			
		||||
                   <bool>true</bool>
 | 
			
		||||
                  </property>
 | 
			
		||||
@ -992,6 +1054,44 @@
 | 
			
		||||
                  </property>
 | 
			
		||||
                 </widget>
 | 
			
		||||
                </item>
 | 
			
		||||
                <item row="1" column="2">
 | 
			
		||||
                 <widget class="QLabel" name="textLabelZ">
 | 
			
		||||
                  <property name="enabled">
 | 
			
		||||
                   <bool>true</bool>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="sizePolicy">
 | 
			
		||||
                   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
 | 
			
		||||
                    <horstretch>0</horstretch>
 | 
			
		||||
                    <verstretch>0</verstretch>
 | 
			
		||||
                   </sizepolicy>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="text">
 | 
			
		||||
                   <string><p align="left">Z field</p></string>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="buddy">
 | 
			
		||||
                   <cstring>cmbZField</cstring>
 | 
			
		||||
                  </property>
 | 
			
		||||
                 </widget>
 | 
			
		||||
                </item>
 | 
			
		||||
                <item row="2" column="2">
 | 
			
		||||
                 <widget class="QLabel" name="textLabelM">
 | 
			
		||||
                  <property name="enabled">
 | 
			
		||||
                   <bool>true</bool>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="sizePolicy">
 | 
			
		||||
                   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
 | 
			
		||||
                    <horstretch>0</horstretch>
 | 
			
		||||
                    <verstretch>0</verstretch>
 | 
			
		||||
                   </sizepolicy>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="text">
 | 
			
		||||
                   <string><p align="left">M field</p></string>
 | 
			
		||||
                  </property>
 | 
			
		||||
                  <property name="buddy">
 | 
			
		||||
                   <cstring>cmbMField</cstring>
 | 
			
		||||
                  </property>
 | 
			
		||||
                 </widget>
 | 
			
		||||
                </item>
 | 
			
		||||
               </layout>
 | 
			
		||||
              </item>
 | 
			
		||||
             </layout>
 | 
			
		||||
 | 
			
		||||
@ -41,7 +41,8 @@ from qgis.core import (
 | 
			
		||||
    QgsFeatureRequest,
 | 
			
		||||
    QgsRectangle,
 | 
			
		||||
    QgsApplication,
 | 
			
		||||
    QgsFeature)
 | 
			
		||||
    QgsFeature,
 | 
			
		||||
    QgsWkbTypes)
 | 
			
		||||
 | 
			
		||||
from qgis.testing import start_app, unittest
 | 
			
		||||
from utilities import unitTestDataPath, compareWkt
 | 
			
		||||
@ -826,6 +827,67 @@ class TestQgsDelimitedTextProviderOther(unittest.TestCase):
 | 
			
		||||
        components = registry.decodeUri('delimitedtext', uri)
 | 
			
		||||
        self.assertEqual(components['path'], filename)
 | 
			
		||||
 | 
			
		||||
    def test_044_ZM(self):
 | 
			
		||||
        # Create test layer
 | 
			
		||||
        srcpath = os.path.join(TEST_DATA_DIR, 'provider')
 | 
			
		||||
        basetestfile = os.path.join(srcpath, 'delimited_xyzm.csv')
 | 
			
		||||
 | 
			
		||||
        url = MyUrl.fromLocalFile(basetestfile)
 | 
			
		||||
        url.addQueryItem("crs", "epsg:4326")
 | 
			
		||||
        url.addQueryItem("type", "csv")
 | 
			
		||||
        url.addQueryItem("xField", "X")
 | 
			
		||||
        url.addQueryItem("yField", "Y")
 | 
			
		||||
        url.addQueryItem("zField", "Z")
 | 
			
		||||
        url.addQueryItem("mField", "M")
 | 
			
		||||
        url.addQueryItem("spatialIndex", "no")
 | 
			
		||||
        url.addQueryItem("subsetIndex", "no")
 | 
			
		||||
        url.addQueryItem("watchFile", "no")
 | 
			
		||||
 | 
			
		||||
        vl = QgsVectorLayer(url.toString(), 'test', 'delimitedtext')
 | 
			
		||||
        assert vl.isValid(), "{} is invalid".format(basetestfile)
 | 
			
		||||
        assert vl.wkbType() == QgsWkbTypes.PointZM, "wrong wkb type, should be PointZM"
 | 
			
		||||
        assert vl.getFeature(2).geometry().asWkt() == "PointZM (-71.12300000000000466 78.23000000000000398 1 2)", "wrong PointZM geometry"
 | 
			
		||||
 | 
			
		||||
    def test_045_Z(self):
 | 
			
		||||
        # Create test layer
 | 
			
		||||
        srcpath = os.path.join(TEST_DATA_DIR, 'provider')
 | 
			
		||||
        basetestfile = os.path.join(srcpath, 'delimited_xyzm.csv')
 | 
			
		||||
 | 
			
		||||
        url = MyUrl.fromLocalFile(basetestfile)
 | 
			
		||||
        url.addQueryItem("crs", "epsg:4326")
 | 
			
		||||
        url.addQueryItem("type", "csv")
 | 
			
		||||
        url.addQueryItem("xField", "X")
 | 
			
		||||
        url.addQueryItem("yField", "Y")
 | 
			
		||||
        url.addQueryItem("zField", "Z")
 | 
			
		||||
        url.addQueryItem("spatialIndex", "no")
 | 
			
		||||
        url.addQueryItem("subsetIndex", "no")
 | 
			
		||||
        url.addQueryItem("watchFile", "no")
 | 
			
		||||
 | 
			
		||||
        vl = QgsVectorLayer(url.toString(), 'test', 'delimitedtext')
 | 
			
		||||
        assert vl.isValid(), "{} is invalid".format(basetestfile)
 | 
			
		||||
        assert vl.wkbType() == QgsWkbTypes.PointZ, "wrong wkb type, should be PointZ"
 | 
			
		||||
        assert vl.getFeature(2).geometry().asWkt() == "PointZ (-71.12300000000000466 78.23000000000000398 1)", "wrong PointZ geometry"
 | 
			
		||||
 | 
			
		||||
    def test_046_M(self):
 | 
			
		||||
        # Create test layer
 | 
			
		||||
        srcpath = os.path.join(TEST_DATA_DIR, 'provider')
 | 
			
		||||
        basetestfile = os.path.join(srcpath, 'delimited_xyzm.csv')
 | 
			
		||||
 | 
			
		||||
        url = MyUrl.fromLocalFile(basetestfile)
 | 
			
		||||
        url.addQueryItem("crs", "epsg:4326")
 | 
			
		||||
        url.addQueryItem("type", "csv")
 | 
			
		||||
        url.addQueryItem("xField", "X")
 | 
			
		||||
        url.addQueryItem("yField", "Y")
 | 
			
		||||
        url.addQueryItem("mField", "M")
 | 
			
		||||
        url.addQueryItem("spatialIndex", "no")
 | 
			
		||||
        url.addQueryItem("subsetIndex", "no")
 | 
			
		||||
        url.addQueryItem("watchFile", "no")
 | 
			
		||||
 | 
			
		||||
        vl = QgsVectorLayer(url.toString(), 'test', 'delimitedtext')
 | 
			
		||||
        assert vl.isValid(), "{} is invalid".format(basetestfile)
 | 
			
		||||
        assert vl.wkbType() == QgsWkbTypes.PointM, "wrong wkb type, should be PointM"
 | 
			
		||||
        assert vl.getFeature(2).geometry().asWkt() == "PointM (-71.12300000000000466 78.23000000000000398 2)", "wrong PointM geometry"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								tests/testdata/provider/delimited_xyzm.csv
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tests/testdata/provider/delimited_xyzm.csv
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
pk,cnt,name,name2,num_char,X,Y,Z,M
 | 
			
		||||
5,-200,,NuLl,5,-71.123,78.23,1,2
 | 
			
		||||
3,300,Pear,PEaR,3,,,3,4
 | 
			
		||||
1,100,Orange,oranGe,1,-70.332,66.33,3,4
 | 
			
		||||
2,200,Apple,Apple,2,-68.2,70.8,3,4
 | 
			
		||||
4,400,Honey,Honey,4,-65.32,78.3,3,4
 | 
			
		||||
		
		
			
  | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user