Exemple #1
0
bool QgsLabelSearchTree::insertLabel( LabelPosition* labelPos, int featureId, const QString& layerName, bool diagram, bool frozen )
{
  if ( !labelPos )
  {
    return false;
  }

  double c_min[2];
  double c_max[2];
  labelPos->getBoundingBox( c_min, c_max );

  QVector<QgsPoint> cornerPoints;
  for ( int i = 0; i < 4; ++i )
  {
    cornerPoints.push_back( QgsPoint( labelPos->getX( i ), labelPos->getY( i ) ) );
  }
  QgsLabelPosition* newEntry = new QgsLabelPosition( featureId, labelPos->getAlpha(), cornerPoints, QgsRectangle( c_min[0], c_min[1], c_max[0], c_max[1] ),
      labelPos->getWidth(), labelPos->getHeight(), layerName, labelPos->getUpsideDown(), diagram, frozen );
  mSpatialIndex.Insert( c_min, c_max, newEntry );
  return true;
}
QgsRectangle QgsRasterCalcDialog::outputRectangle() const
{
  return QgsRectangle( mXMinSpinBox->value(), mYMinSpinBox->value(), mXMaxSpinBox->value(), mYMaxSpinBox->value() );
}
QgsGrassRasterProvider::QgsGrassRasterProvider( QString const &uri )
  : QgsRasterDataProvider( uri )
  , mValid( false )
  , mGrassDataType( 0 )
  , mCols( 0 )
  , mRows( 0 )
  , mYBlockSize( 0 )
  , mNoDataValue( std::numeric_limits<double>::quiet_NaN() )
{
  QgsDebugMsg( "QgsGrassRasterProvider: constructing with uri '" + uri + "'." );

  if ( !QgsGrass::init() )
  {
    return;
  }

  // Parse URI, it is the same like using GDAL, i.e. path to raster cellhd, i.e.
  // /path/to/gisdbase/location/mapset/cellhd/map
  QFileInfo fileInfo( uri );
  if ( !fileInfo.exists() ) // then we keep it valid forever
  {
    appendError( ERR( tr( "cellhd file %1 does not exist" ).arg( uri ) ) );
    return;
  }

  mMapName = fileInfo.fileName();
  QDir dir = fileInfo.dir();
  QString element = dir.dirName();
  if ( element != QLatin1String( "cellhd" ) )
  {
    appendError( ERR( tr( "Groups not yet supported" ) ) );
    return;
  }
  dir.cdUp(); // skip cellhd
  mMapset = dir.dirName();
  dir.cdUp();
  mLocation = dir.dirName();
  dir.cdUp();
  mGisdbase = dir.path();

  QgsDebugMsg( QString( "gisdbase: %1" ).arg( mGisdbase ) );
  QgsDebugMsg( QString( "location: %1" ).arg( mLocation ) );
  QgsDebugMsg( QString( "mapset: %1" ).arg( mMapset ) );
  QgsDebugMsg( QString( "mapName: %1" ).arg( mMapName ) );

  mTimestamp = dataTimestamp();

  mRasterValue.set( mGisdbase, mLocation, mMapset, mMapName );
  //mValidNoDataValue = true;

  QString error;
  mCrs = QgsGrass::crs( mGisdbase, mLocation, error );
  appendIfError( error );
  QgsDebugMsg( "mCrs: " + mCrs.toWkt() );

  // the block size can change of course when the raster is overridden
  // ibut it is only called once when statistics are calculated
  error.clear();
  QgsGrass::size( mGisdbase, mLocation, mMapset, mMapName, &mCols, &mRows, error );
  appendIfError( error );

  error.clear();
  mInfo = QgsGrass::info( mGisdbase, mLocation, mMapset, mMapName, QgsGrassObject::Raster,
                          QStringLiteral( "info" ), QgsRectangle(), 0, 0, 3000, error );
  appendIfError( error );

  mGrassDataType = mInfo[QStringLiteral( "TYPE" )].toInt();
  QgsDebugMsg( "mGrassDataType = " + QString::number( mGrassDataType ) );

  // TODO: avoid showing these strange numbers in GUI
  // TODO: don't save no data values in project file, add a flag if value was defined by user

  double myInternalNoDataValue;
  if ( mGrassDataType == CELL_TYPE )
  {
    myInternalNoDataValue = INT_MIN;
  }
  else if ( mGrassDataType == DCELL_TYPE )
  {
    // Don't use numeric limits, raster layer is using
    //    qAbs( myValue - mNoDataValue ) <= TINY_VALUE
    // if the mNoDataValue would be a limit, the subtraction could overflow.
    // No data value is shown in GUI, use some nice number.
    // Choose values with small representation error.
    // limit: 1.7976931348623157e+308
    //myInternalNoDataValue = -1e+300;
    myInternalNoDataValue = std::numeric_limits<double>::quiet_NaN();
  }
  else
  {
    if ( mGrassDataType != FCELL_TYPE )
    {
      QgsDebugMsg( "unexpected data type" );
    }

    // limit: 3.40282347e+38
    //myInternalNoDataValue = -1e+30;
    myInternalNoDataValue = std::numeric_limits<float>::quiet_NaN();
  }
  mNoDataValue = myInternalNoDataValue;
  mSrcHasNoDataValue.append( true );
  mSrcNoDataValue.append( mNoDataValue );
  mUseSrcNoDataValue.append( true );
  QgsDebugMsg( QString( "myInternalNoDataValue = %1" ).arg( myInternalNoDataValue ) );

  // TODO: refresh mRows and mCols if raster was rewritten
  // We have to decide some reasonable block size, not to big to occupate too much
  // memory, not too small to result in too many calls to readBlock -> qgis.d.rast
  // for statistics
  int typeSize = dataTypeSize( dataType( 1 ) );
  if ( mCols > 0 && typeSize > 0 )
  {
    const int cache_size = 10000000; // ~ 10 MB
    mYBlockSize = cache_size / typeSize / mCols;
    if ( mYBlockSize > mRows )
    {
      mYBlockSize = mRows;
    }
    QgsDebugMsg( "mYBlockSize = " + QString::number( mYBlockSize ) );
    mValid = true;
  }
}
void QgsVectorDataProvider::fillMinMaxCache()
{
  if ( !mCacheMinMaxDirty )
    return;

  const QgsFieldMap& flds = fields();
  for ( QgsFieldMap::const_iterator it = flds.begin(); it != flds.end(); ++it )
  {
    if ( it->type() == QVariant::Int )
    {
      mCacheMinValues[it.key()] = QVariant( INT_MAX );
      mCacheMaxValues[it.key()] = QVariant( INT_MIN );
    }
    else if ( it->type() == QVariant::Double )
    {
      mCacheMinValues[it.key()] = QVariant( DBL_MAX );
      mCacheMaxValues[it.key()] = QVariant( -DBL_MAX );
    }
    else
    {
      mCacheMinValues[it.key()] = QVariant();
      mCacheMaxValues[it.key()] = QVariant();
    }
  }

  QgsFeature f;
  QgsAttributeList keys = mCacheMinValues.keys();
  select( keys, QgsRectangle(), false );

  while ( nextFeature( f ) )
  {
    QgsAttributeMap attrMap = f.attributeMap();
    for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
    {
      const QVariant& varValue = attrMap[*it];

      if ( flds[*it].type() == QVariant::Int )
      {
        int value = varValue.toInt();
        if ( value < mCacheMinValues[*it].toInt() )
          mCacheMinValues[*it] = value;
        if ( value > mCacheMaxValues[*it].toInt() )
          mCacheMaxValues[*it] = value;
      }
      else if ( flds[*it].type() == QVariant::Double )
      {
        double value = varValue.toDouble();
        if ( value < mCacheMinValues[*it].toDouble() )
          mCacheMinValues[*it] = value;
        if ( value > mCacheMaxValues[*it].toDouble() )
          mCacheMaxValues[*it] = value;
      }
      else
      {
        QString value = varValue.toString();
        if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
        {
          mCacheMinValues[*it] = value;
        }
        if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
        {
          mCacheMaxValues[*it] = value;
        }
      }
    }
  }

  mCacheMinMaxDirty = false;
}
Exemple #5
0
ErrorList topolTest::runTest( const QString& testName, QgsVectorLayer* layer1, QgsVectorLayer* layer2, ValidateType type, double tolerance )
{
  QgsDebugMsg( QString( "Running test %1" ).arg( testName ) );
  ErrorList errors;

  if ( !layer1 )
  {
    QgsMessageLog::logMessage( tr( "First layer not found in registry." ), tr( "Topology plugin" ) );
    return errors;
  }

  if ( !layer2 && mTopologyRuleMap[testName].useSecondLayer )
  {
    QgsMessageLog::logMessage( tr( "Second layer not found in registry." ), tr( "Topology plugin" ) );
    return errors;
  }

  QString secondLayerId;
  mFeatureList1.clear();
  mFeatureMap2.clear();

  //checking if new features are not
  //being recognised due to indexing not being upto date

  mLayerIndexes.clear();

  if ( mTopologyRuleMap[testName].useSecondLayer )
  {
    // validate all features or current extent
    QgsRectangle extent;
    if ( type == ValidateExtent )
    {
      extent = theQgsInterface->mapCanvas()->extent();
    }
    else
    {
      extent = QgsRectangle();
    }

    fillFeatureList( layer1, extent );
    //fillFeatureMap( layer1, extent );

    QString secondLayerId = layer2->id();

    if ( !mLayerIndexes.contains( layer2->id() ) )
    {
      mLayerIndexes[layer2->id()] = createIndex( layer2, extent );
    }
  }
  else
  {
    // validate all features or current extent
    QgsRectangle extent;
    if ( type == ValidateExtent )
    {
      extent = theQgsInterface->mapCanvas()->extent();
      if ( mTopologyRuleMap[testName].useSpatialIndex )
      {
        mLayerIndexes[layer1->id()] = createIndex( layer1, theQgsInterface->mapCanvas()->extent() );
      }
      else
      {
        fillFeatureList( layer1, extent );
      }
    }
    else
    {
      if ( mTopologyRuleMap[testName].useSpatialIndex )
      {
        if ( !mLayerIndexes.contains( layer1->id() ) )
        {

          mLayerIndexes[layer1->id()] = createIndex( layer1, QgsRectangle() );
        }
      }
      else
      {
        fillFeatureList( layer1, QgsRectangle() );
      }
    }

  }

  //call test routine
  bool isValidatingExtent;
  if ( type == ValidateExtent )
  {
    isValidatingExtent = true;
  }
  else
  {
    isValidatingExtent = false;
  }

  return ( this->*( mTopologyRuleMap[testName].f ) )( tolerance, layer1, layer2, isValidatingExtent );
}
Exemple #6
0
bool QgsGeometryAnalyzer::buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance,
                                  bool onlySelectedFeatures, bool dissolve, int bufferDistanceField, QProgressDialog* p )
{
  if ( !layer )
  {
    return false;
  }

  QgsVectorDataProvider* dp = layer->dataProvider();
  if ( !dp )
  {
    return false;
  }

  QGis::WkbType outputType = QGis::WKBPolygon;
  if ( dissolve )
  {
    outputType = QGis::WKBMultiPolygon;
  }
  const QgsCoordinateReferenceSystem crs = layer->crs();

  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
  QgsFeature currentFeature;
  QgsGeometry *dissolveGeometry = 0; //dissolve geometry (if dissolve enabled)

  //take only selection
  if ( onlySelectedFeatures )
  {
    //use QgsVectorLayer::featureAtId
    const QgsFeatureIds selection = layer->selectedFeaturesIds();
    if ( p )
    {
      p->setMaximum( selection.size() );
    }

    int processedFeatures = 0;
    QgsFeatureIds::const_iterator it = selection.constBegin();
    for ( ; it != selection.constEnd(); ++it )
    {
      if ( p )
      {
        p->setValue( processedFeatures );
      }

      if ( p && p->wasCanceled() )
      {
        break;
      }
      if ( !layer->featureAtId( *it, currentFeature, true, true ) )
      {
        continue;
      }
      bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField );
      ++processedFeatures;
    }

    if ( p )
    {
      p->setValue( selection.size() );
    }
  }
  //take all features
  else
  {
    layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );


    int featureCount = layer->featureCount();
    if ( p )
    {
      p->setMaximum( featureCount );
    }
    int processedFeatures = 0;

    while ( layer->nextFeature( currentFeature ) )
    {
      if ( p )
      {
        p->setValue( processedFeatures );
      }
      if ( p && p->wasCanceled() )
      {
        break;
      }
      bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField );
      ++processedFeatures;
    }
    if ( p )
    {
      p->setValue( featureCount );
    }
  }

  if ( dissolve )
  {
    QgsFeature dissolveFeature;
    if ( !dissolveGeometry )
    {
      QgsDebugMsg( "no dissolved geometry - should not happen" );
      return false;
    }
    dissolveFeature.setGeometry( dissolveGeometry );
    vWriter.addFeature( dissolveFeature );
  }
  return true;
}
QgsRectangle QgsCoordinateTransform::transformBoundingBox( const QgsRectangle &rect, TransformDirection direction, const bool handle180Crossover ) const
{
  // Calculate the bounding box of a QgsRectangle in the source CRS
  // when projected to the destination CRS (or the inverse).
  // This is done by looking at a number of points spread evenly
  // across the rectangle

  if ( !d->mIsValid || d->mShortCircuit )
    return rect;

  if ( rect.isEmpty() )
  {
    QgsPointXY p = transform( rect.xMinimum(), rect.yMinimum(), direction );
    return QgsRectangle( p, p );
  }

  // 64 points (<=2.12) is not enough, see #13665, for EPSG:4326 -> EPSG:3574 (say that it is a hard one),
  // are decent result from about 500 points and more. This method is called quite often, but
  // even with 1000 points it takes < 1ms
  // TODO: how to effectively and precisely reproject bounding box?
  const int nPoints = 1000;
  double d = std::sqrt( ( rect.width() * rect.height() ) / std::pow( std::sqrt( static_cast< double >( nPoints ) ) - 1, 2.0 ) );
  int nXPoints = static_cast< int >( std::ceil( rect.width() / d ) ) + 1;
  int nYPoints = static_cast< int >( std::ceil( rect.height() / d ) ) + 1;

  QgsRectangle bb_rect;
  bb_rect.setMinimal();

  // We're interfacing with C-style vectors in the
  // end, so let's do C-style vectors here too.

  QVector<double> x( nXPoints * nYPoints );
  QVector<double> y( nXPoints * nYPoints );
  QVector<double> z( nXPoints * nYPoints );

  QgsDebugMsgLevel( QStringLiteral( "Entering transformBoundingBox..." ), 4 );

  // Populate the vectors

  double dx = rect.width()  / static_cast< double >( nXPoints - 1 );
  double dy = rect.height() / static_cast< double >( nYPoints - 1 );

  double pointY = rect.yMinimum();

  for ( int i = 0; i < nYPoints ; i++ )
  {

    // Start at right edge
    double pointX = rect.xMinimum();

    for ( int j = 0; j < nXPoints; j++ )
    {
      x[( i * nXPoints ) + j] = pointX;
      y[( i * nXPoints ) + j] = pointY;
      // and the height...
      z[( i * nXPoints ) + j] = 0.0;
      // QgsDebugMsg(QString("BBox coord: (%1, %2)").arg(x[(i*numP) + j]).arg(y[(i*numP) + j]));
      pointX += dx;
    }
    pointY += dy;
  }

  // Do transformation. Any exception generated must
  // be handled in above layers.
  try
  {
    transformCoords( nXPoints * nYPoints, x.data(), y.data(), z.data(), direction );
  }
  catch ( const QgsCsException & )
  {
    // rethrow the exception
    QgsDebugMsg( QStringLiteral( "rethrowing exception" ) );
    throw;
  }

  // Calculate the bounding box and use that for the extent

  for ( int i = 0; i < nXPoints * nYPoints; i++ )
  {
    if ( !std::isfinite( x[i] ) || !std::isfinite( y[i] ) )
    {
      continue;
    }

    if ( handle180Crossover )
    {
      //if crossing the date line, temporarily add 360 degrees to -ve longitudes
      bb_rect.combineExtentWith( x[i] >= 0.0 ? x[i] : x[i] + 360.0, y[i] );
    }
    else
    {
      bb_rect.combineExtentWith( x[i], y[i] );
    }
  }

  if ( bb_rect.isNull() )
  {
    // something bad happened when reprojecting the filter rect... no finite points were left!
    throw QgsCsException( QObject::tr( "Could not transform bounding box to target CRS" ) );
  }

  if ( handle180Crossover )
  {
    //subtract temporary addition of 360 degrees from longitudes
    if ( bb_rect.xMinimum() > 180.0 )
      bb_rect.setXMinimum( bb_rect.xMinimum() - 360.0 );
    if ( bb_rect.xMaximum() > 180.0 )
      bb_rect.setXMaximum( bb_rect.xMaximum() - 360.0 );
  }

  QgsDebugMsgLevel( "Projected extent: " + bb_rect.toString(), 4 );

  if ( bb_rect.isEmpty() )
  {
    QgsDebugMsgLevel( "Original extent: " + rect.toString(), 4 );
  }

  return bb_rect;
}
QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value )
{
  if ( !vl )
    return 0;

  QWidget *myWidget = 0;
  QgsVectorLayer::EditType editType = vl->editType( idx );
  const QgsField &field = vl->pendingFields()[idx];
  QVariant::Type myFieldType = field.type();

  switch ( editType )
  {
    case QgsVectorLayer::UniqueValues:
    {
      QList<QVariant> values;
      vl->dataProvider()->uniqueValues( idx, values );

      QComboBox *cb = comboBox( editor, parent );
      if ( cb )
      {
        cb->setEditable( false );

        for ( QList<QVariant>::iterator it = values.begin(); it != values.end(); it++ )
          cb->addItem( it->toString(), it->toString() );

        myWidget = cb;
      }

    }
    break;

    case QgsVectorLayer::Enumeration:
    {
      QStringList enumValues;
      vl->dataProvider()->enumValues( idx, enumValues );

      QComboBox *cb = comboBox( editor, parent );
      if ( cb )
      {
        QStringList::const_iterator s_it = enumValues.constBegin();
        for ( ; s_it != enumValues.constEnd(); ++s_it )
        {
          cb->addItem( *s_it, *s_it );
        }

        myWidget = cb;
      }
    }
    break;

    case QgsVectorLayer::ValueMap:
    {
      const QMap<QString, QVariant> &map = vl->valueMap( idx );

      QComboBox *cb = comboBox( editor, parent );
      if ( cb )
      {
        for ( QMap<QString, QVariant>::const_iterator it = map.begin(); it != map.end(); it++ )
        {
          cb->addItem( it.key(), it.value() );
        }

        myWidget = cb;
      }
    }
    break;

    case QgsVectorLayer::ValueRelation:
    {
      QSettings settings;
      QString nullValue = settings.value( "qgis/nullValue", "NULL" ).toString();

      const QgsVectorLayer::ValueRelationData &data = vl->valueRelation( idx );

      QgsVectorLayer *layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( data.mLayer ) );
      QMap< QString, QString > map;

      int fi = -1;
      if ( layer )
      {
        int ki = layer->fieldNameIndex( data.mOrderByValue ? data.mValue : data.mKey );
        int vi = layer->fieldNameIndex( data.mOrderByValue ? data.mKey : data.mValue );

        if ( !data.mFilterAttributeColumn.isNull() )
          fi = layer->fieldNameIndex( data.mFilterAttributeColumn );

        if ( data.mAllowNull )
          map.insert( nullValue, tr( "(no selection)" ) );

        if ( ki >= 0 && vi >= 0 )
        {
          QgsAttributeList attributes;
          attributes << ki;
          attributes << vi;
          if ( fi >= 0 )
            attributes << fi;
          layer->select( attributes, QgsRectangle(), false );
          QgsFeature f;
          while ( layer->nextFeature( f ) )
          {
            if ( fi >= 0 && f.attributeMap()[ fi ].toString() != data.mFilterAttributeValue )
              continue;

            map.insert( f.attributeMap()[ ki ].toString(), f.attributeMap()[ vi ].toString() );
          }
        }
      }

      if ( !data.mAllowMulti )
      {
        QComboBox *cb = comboBox( editor, parent );
        if ( cb )
        {
          for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); it++ )
          {
            if ( data.mOrderByValue )
              cb->addItem( it.key(), it.value() );
            else
              cb->addItem( it.value(), it.key() );
          }

          myWidget = cb;
        }
      }
      else
      {
        QListWidget *lw = listWidget( editor, parent );
        if ( lw )
        {
          QStringList checkList = value.toString().remove( QChar( '{' ) ).remove( QChar( '}' ) ).split( "," );

          for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); it++ )
          {
            QListWidgetItem *item;
            if ( data.mOrderByValue )
            {
              item = new QListWidgetItem( it.key() );
              item->setData( Qt::UserRole, it.value() );
              item->setCheckState( checkList.contains( it.value() ) ? Qt::Checked : Qt::Unchecked );
            }
            else
            {
              item = new QListWidgetItem( it.value() );
              item->setData( Qt::UserRole, it.key() );
              item->setCheckState( checkList.contains( it.key() ) ? Qt::Checked : Qt::Unchecked );
            }
            lw->addItem( item );
          }

          myWidget = lw;
        }
      }
    }
    break;

    case QgsVectorLayer::Classification:
    {
      QMap<QString, QString> classes;

      const QgsUniqueValueRenderer *uvr = dynamic_cast<const QgsUniqueValueRenderer *>( vl->renderer() );
      if ( uvr )
      {
        const QList<QgsSymbol *> symbols = uvr->symbols();

        for ( int i = 0; i < symbols.size(); i++ )
        {
          QString label = symbols[i]->label();
          QString name = symbols[i]->lowerValue();

          if ( label == "" )
            label = name;

          classes.insert( name, label );
        }
      }

      const QgsCategorizedSymbolRendererV2 *csr = dynamic_cast<const QgsCategorizedSymbolRendererV2 *>( vl->rendererV2() );
      if ( csr )
      {
        const QgsCategoryList &categories = (( QgsCategorizedSymbolRendererV2 * )csr )->categories(); // FIXME: QgsCategorizedSymbolRendererV2::categories() should be const
        for ( int i = 0; i < categories.size(); i++ )
        {
          QString label = categories[i].label();
          QString value = categories[i].value().toString();
          if ( label.isEmpty() )
            label = value;
          classes.insert( value, label );
        }
      }

      QComboBox *cb = comboBox( editor, parent );
      if ( cb )
      {
        for ( QMap<QString, QString>::const_iterator it = classes.begin(); it != classes.end(); it++ )
        {
          cb->addItem( it.value(), it.key() );
        }

        myWidget = cb;
      }
    }
    break;

    case QgsVectorLayer::DialRange:
    case QgsVectorLayer::SliderRange:
    case QgsVectorLayer::EditRange:
    {
      if ( myFieldType == QVariant::Int )
      {
        int min = vl->range( idx ).mMin.toInt();
        int max = vl->range( idx ).mMax.toInt();
        int step = vl->range( idx ).mStep.toInt();

        if ( editType == QgsVectorLayer::EditRange )
        {
          QSpinBox *sb = 0;

          if ( editor )
            sb = qobject_cast<QSpinBox *>( editor );
          else
            sb = new QSpinBox( parent );

          if ( sb )
          {
            sb->setRange( min, max );
            sb->setSingleStep( step );

            myWidget = sb;
          }
        }
        else
        {
          QAbstractSlider *sl = 0;

          if ( editor )
          {
            sl = qobject_cast<QAbstractSlider*>( editor );
          }
          else if ( editType == QgsVectorLayer::DialRange )
          {
            sl = new QDial( parent );
          }
          else
          {
            sl = new QSlider( Qt::Horizontal, parent );
          }

          if ( sl )
          {
            sl->setRange( min, max );
            sl->setSingleStep( step );

            myWidget = sl;
          }
        }
        break;
      }
      else if ( myFieldType == QVariant::Double )
      {
        QDoubleSpinBox *dsb = 0;
        if ( editor )
          dsb = qobject_cast<QDoubleSpinBox*>( editor );
        else
          dsb = new QDoubleSpinBox( parent );

        if ( dsb )
        {
          double min = vl->range( idx ).mMin.toDouble();
          double max = vl->range( idx ).mMax.toDouble();
          double step = vl->range( idx ).mStep.toDouble();

          dsb->setRange( min, max );
          dsb->setSingleStep( step );

          myWidget = dsb;
        }
        break;
      }
    }

    case QgsVectorLayer::CheckBox:
    {
      QCheckBox *cb = 0;
      if ( editor )
        cb = qobject_cast<QCheckBox*>( editor );
      else
        cb = new QCheckBox( parent );

      if ( cb )
      {
        myWidget = cb;
        break;
      }
    }

    // fall-through

    case QgsVectorLayer::LineEdit:
    case QgsVectorLayer::TextEdit:
    case QgsVectorLayer::UuidGenerator:
    case QgsVectorLayer::UniqueValuesEditable:
    case QgsVectorLayer::Immutable:
    {
      QLineEdit *le = 0;
      QTextEdit *te = 0;
      QPlainTextEdit *pte = 0;

      if ( editor )
      {
        le = qobject_cast<QLineEdit *>( editor );
        te = qobject_cast<QTextEdit *>( editor );
        pte = qobject_cast<QPlainTextEdit *>( editor );
      }
      else if ( editType == QgsVectorLayer::TextEdit )
      {
        pte = new QPlainTextEdit( parent );
      }
      else
      {
        le = new QLineEdit( parent );
      }

      if ( le )
      {

        if ( editType == QgsVectorLayer::UniqueValuesEditable )
        {
          QList<QVariant> values;
          vl->dataProvider()->uniqueValues( idx, values );

          QStringList svalues;
          for ( QList<QVariant>::const_iterator it = values.begin(); it != values.end(); it++ )
            svalues << it->toString();

          QCompleter *c = new QCompleter( svalues );
          c->setCompletionMode( QCompleter::PopupCompletion );
          le->setCompleter( c );
        }

        if ( editType == QgsVectorLayer::UuidGenerator )
        {
          le->setReadOnly( true );
        }

        le->setValidator( new QgsFieldValidator( le, field ) );
        myWidget = le;
      }

      if ( te )
      {
        te->setAcceptRichText( true );
        myWidget = te;
      }

      if ( pte )
      {
        myWidget = pte;
      }

      if ( myWidget )
      {
        myWidget->setDisabled( editType == QgsVectorLayer::Immutable );
      }
    }
    break;

    case QgsVectorLayer::Hidden:
      myWidget = 0;
      break;

    case QgsVectorLayer::FileName:
    case QgsVectorLayer::Calendar:
    {
      QPushButton *pb = 0;
      QLineEdit *le = qobject_cast<QLineEdit *>( editor );
      if ( le )
      {
        if ( le )
          myWidget = le;

        if ( editor->parent() )
        {
          pb = editor->parent()->findChild<QPushButton *>();
        }
      }
      else
      {
        le = new QLineEdit();

        pb = new QPushButton( tr( "..." ) );

        QHBoxLayout *hbl = new QHBoxLayout();
        hbl->addWidget( le );
        hbl->addWidget( pb );

        myWidget = new QWidget( parent );
        myWidget->setBackgroundRole( QPalette::Window );
        myWidget->setAutoFillBackground( true );
        myWidget->setLayout( hbl );
      }

      if ( pb )
      {
        if ( editType == QgsVectorLayer::FileName )
          connect( pb, SIGNAL( clicked() ), new QgsAttributeEditor( pb ), SLOT( selectFileName() ) );
        if ( editType == QgsVectorLayer::Calendar )
          connect( pb, SIGNAL( clicked() ), new QgsAttributeEditor( pb ), SLOT( selectDate() ) );
      }
    }
    break;
  }

  setValue( myWidget, vl, idx, value );

  return myWidget;
}
Exemple #9
0
QgsRectangle QgsAlignRaster::clipExtent() const
{
  return QgsRectangle( mClipExtent[0], mClipExtent[1],
                       mClipExtent[2], mClipExtent[3] );
}
Exemple #10
0
bool QgsAtlasComposition::prepareForFeature( const int featureI, const bool updateMaps )
{
  if ( !mCoverageLayer )
  {
    return false;
  }

  if ( mFeatureIds.isEmpty() )
  {
    emit statusMsgChanged( tr( "No matching atlas features" ) );
    return false;
  }

  if ( featureI >= mFeatureIds.size() )
  {
    return false;
  }

  mCurrentFeatureNo = featureI;

  // retrieve the next feature, based on its id
  mCoverageLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ].first ) ).nextFeature( mCurrentFeature );

  QgsExpressionContext expressionContext = createExpressionContext();

  // generate filename for current feature
  if ( !evalFeatureFilename( expressionContext ) )
  {
    //error evaluating filename
    return false;
  }

  mGeometryCache.clear();
  emit featureChanged( &mCurrentFeature );
  emit statusMsgChanged( QString( tr( "Atlas feature %1 of %2" ) ).arg( featureI + 1 ).arg( mFeatureIds.size() ) );

  if ( !mCurrentFeature.isValid() )
  {
    //bad feature
    return true;
  }

  if ( !updateMaps )
  {
    //nothing more to do
    return true;
  }

  //update composer maps

  //build a list of atlas-enabled composer maps
  QList<QgsComposerMap*> maps;
  QList<QgsComposerMap*> atlasMaps;
  mComposition->composerItems( maps );
  if ( maps.isEmpty() )
  {
    return true;
  }
  for ( QList<QgsComposerMap*>::iterator mit = maps.begin(); mit != maps.end(); ++mit )
  {
    QgsComposerMap* currentMap = ( *mit );
    if ( !currentMap->atlasDriven() )
    {
      continue;
    }
    atlasMaps << currentMap;
  }

  if ( !atlasMaps.isEmpty() )
  {
    //clear the transformed bounds of the previous feature
    mTransformedFeatureBounds = QgsRectangle();

    // compute extent of current feature in the map CRS. This should be set on a per-atlas map basis,
    // but given that it's not currently possible to have maps with different CRSes we can just
    // calculate it once based on the first atlas maps' CRS.
    computeExtent( atlasMaps[0] );
  }

  for ( QList<QgsComposerMap*>::iterator mit = maps.begin(); mit != maps.end(); ++mit )
  {
    if (( *mit )->atlasDriven() )
    {
      // map is atlas driven, so update it's bounds (causes a redraw)
      prepareMap( *mit );
    }
    else
    {
      // map is not atlas driven, so manually force a redraw (to reflect possibly atlas
      // dependent symbology)
      ( *mit )->cache();
    }
  }

  return true;
}
Exemple #11
0
void QgsAtlasComposition::prepareMap( QgsComposerMap* map )
{
  if ( !map->atlasDriven() || mCoverageLayer->wkbType() == QGis::WKBNoGeometry )
  {
    return;
  }

  if ( mTransformedFeatureBounds.isEmpty() )
  {
    //transformed extent of current feature hasn't been calculated yet. This can happen if
    //a map has been set to be atlas controlled after prepare feature was called
    computeExtent( map );
  }

  double xa1 = mTransformedFeatureBounds.xMinimum();
  double xa2 = mTransformedFeatureBounds.xMaximum();
  double ya1 = mTransformedFeatureBounds.yMinimum();
  double ya2 = mTransformedFeatureBounds.yMaximum();
  QgsRectangle newExtent = mTransformedFeatureBounds;
  QgsRectangle mOrigExtent( map->extent() );

  //sanity check - only allow fixed scale mode for point layers
  bool isPointLayer = false;
  switch ( mCoverageLayer->wkbType() )
  {
    case QGis::WKBPoint:
    case QGis::WKBPoint25D:
    case QGis::WKBMultiPoint:
    case QGis::WKBMultiPoint25D:
      isPointLayer = true;
      break;
    default:
      isPointLayer = false;
      break;
  }

  if ( map->atlasScalingMode() == QgsComposerMap::Fixed || map->atlasScalingMode() == QgsComposerMap::Predefined || isPointLayer )
  {
    QgsScaleCalculator calc;
    calc.setMapUnits( composition()->mapSettings().mapUnits() );
    calc.setDpi( 25.4 );
    double originalScale = calc.calculate( mOrigExtent, map->rect().width() );
    double geomCenterX = ( xa1 + xa2 ) / 2.0;
    double geomCenterY = ( ya1 + ya2 ) / 2.0;

    if ( map->atlasScalingMode() == QgsComposerMap::Fixed || isPointLayer )
    {
      // only translate, keep the original scale (i.e. width x height)
      double xMin = geomCenterX - mOrigExtent.width() / 2.0;
      double yMin = geomCenterY - mOrigExtent.height() / 2.0;
      newExtent = QgsRectangle( xMin,
                                yMin,
                                xMin + mOrigExtent.width(),
                                yMin + mOrigExtent.height() );

      //scale newExtent to match original scale of map
      //this is required for geographic coordinate systems, where the scale varies by extent
      double newScale = calc.calculate( newExtent, map->rect().width() );
      newExtent.scale( originalScale / newScale );
    }
    else if ( map->atlasScalingMode() == QgsComposerMap::Predefined )
    {
      // choose one of the predefined scales
      double newWidth = mOrigExtent.width();
      double newHeight = mOrigExtent.height();
      const QVector<qreal>& scales = mPredefinedScales;
      for ( int i = 0; i < scales.size(); i++ )
      {
        double ratio = scales[i] / originalScale;
        newWidth = mOrigExtent.width() * ratio;
        newHeight = mOrigExtent.height() * ratio;

        // compute new extent, centered on feature
        double xMin = geomCenterX - newWidth / 2.0;
        double yMin = geomCenterY - newHeight / 2.0;
        newExtent = QgsRectangle( xMin,
                                  yMin,
                                  xMin + newWidth,
                                  yMin + newHeight );

        //scale newExtent to match desired map scale
        //this is required for geographic coordinate systems, where the scale varies by extent
        double newScale = calc.calculate( newExtent, map->rect().width() );
        newExtent.scale( scales[i] / newScale );

        if (( newExtent.width() >= mTransformedFeatureBounds.width() ) && ( newExtent.height() >= mTransformedFeatureBounds.height() ) )
        {
          // this is the smallest extent that embeds the feature, stop here
          break;
        }
      }
    }
  }
  else if ( map->atlasScalingMode() == QgsComposerMap::Auto )
  {
    // auto scale

    double geomRatio = mTransformedFeatureBounds.width() / mTransformedFeatureBounds.height();
    double mapRatio = mOrigExtent.width() / mOrigExtent.height();

    // geometry height is too big
    if ( geomRatio < mapRatio )
    {
      // extent the bbox's width
      double adjWidth = ( mapRatio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0;
      xa1 -= adjWidth;
      xa2 += adjWidth;
    }
    // geometry width is too big
    else if ( geomRatio > mapRatio )
    {
      // extent the bbox's height
      double adjHeight = ( mTransformedFeatureBounds.width() / mapRatio - mTransformedFeatureBounds.height() ) / 2.0;
      ya1 -= adjHeight;
      ya2 += adjHeight;
    }
    newExtent = QgsRectangle( xa1, ya1, xa2, ya2 );

    if ( map->atlasMargin() > 0.0 )
    {
      newExtent.scale( 1 + map->atlasMargin() );
    }
  }

  // set the new extent (and render)
  map->setNewAtlasFeatureExtent( newExtent );
}
QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
  QgsVectorLayer* vlayer,
  QString attrName,
  int classes,
  Mode mode,
  QgsSymbolV2* symbol,
  QgsVectorColorRampV2* ramp )
{
  if ( classes < 1 )
    return NULL;

  int attrNum = vlayer->fieldNameIndex( attrName );

  double minimum = vlayer->minimumValue( attrNum ).toDouble();
  double maximum = vlayer->maximumValue( attrNum ).toDouble();
  QgsDebugMsg( QString( "min %1 // max %2" ).arg( minimum ).arg( maximum ) );

  QList<double> breaks;
  QList<int> labels;
  if ( mode == EqualInterval )
  {
    breaks = _calcEqualIntervalBreaks( minimum, maximum, classes );
  }
  else if ( mode == Pretty )
  {
    breaks = _calcPrettyBreaks( minimum, maximum, classes );
  }
  else if ( mode == Quantile || mode == Jenks || mode == StdDev )
  {
    // get values from layer
    QList<double> values;
    QgsFeature f;
    QgsAttributeList lst;
    lst.append( attrNum );
    vlayer->select( lst, QgsRectangle(), false );
    while ( vlayer->nextFeature( f ) )
      values.append( f.attributeMap()[attrNum].toDouble() );
    // calculate the breaks
    if ( mode == Quantile )
    {
      breaks = _calcQuantileBreaks( values, classes );
    }
    else if ( mode == Jenks )
    {
      breaks = _calcJenksBreaks( values, classes, minimum, maximum );
    }
    else if ( mode == StdDev )
    {
      breaks = _calcStdDevBreaks( values, classes, labels );
    }
  }
  else
  {
    Q_ASSERT( false );
  }

  QgsRangeList ranges;
  double lower, upper = minimum;
  QString label;

  // "breaks" list contains all values at class breaks plus maximum as last break
  int i = 0;
  for ( QList<double>::iterator it = breaks.begin(); it != breaks.end(); ++it, ++i )
  {
    lower = upper; // upper border from last interval
    upper = *it;
    if ( mode == StdDev )
    {
      if ( i == 0 )
      {
        label = "< " + QString::number( labels[i], 'i', 0 ) + " Std Dev";
      }
      else if ( i == labels.count() - 1 )
      {
        label = ">= " + QString::number( labels[i-1], 'i', 0 ) + " Std Dev";
      }
      else
      {
        label = QString::number( labels[i-1], 'i', 0 ) + " Std Dev" + " - " + QString::number( labels[i], 'i', 0 ) + " Std Dev";
      }
    }
    else
    {
      label = QString::number( lower, 'f', 4 ) + " - " + QString::number( upper, 'f', 4 );
    }

    QgsSymbolV2* newSymbol = symbol->clone();
    double colorValue = ( breaks.count() > 1 ? ( double ) i / ( breaks.count() - 1 ) : 0 );
    newSymbol->setColor( ramp->color( colorValue ) ); // color from (0 / cl-1) to (cl-1 / cl-1)

    ranges.append( QgsRendererRangeV2( lower, upper, newSymbol, label ) );
  }

  QgsGraduatedSymbolRendererV2* r = new QgsGraduatedSymbolRendererV2( attrName, ranges );
  r->setSourceSymbol( symbol->clone() );
  r->setSourceColorRamp( ramp->clone() );
  r->setMode( mode );
  return r;
}
Exemple #13
0
void QgsFieldCalculator::accept()
{
    if ( mVectorLayer && mVectorLayer->isEditable() )
    {
        QString calcString = mExpressionTextEdit->toPlainText();

        //create QgsExpression
        QgsExpression exp( calcString );
        if ( exp.hasParserError() )
        {
            //expression not valid
            QMessageBox::critical( 0, tr( "Syntax error" ), tr( QString( "Invalid expression syntax. The error message of the parser is: '" + exp.parserErrorString() + "'" ).toLocal8Bit().data() ) );
            return;
        }

        if ( ! exp.prepare( mVectorLayer->pendingFields() ) )
        {
            QMessageBox::critical( 0, tr( "Evaluation error" ), exp.evalErrorString() );
            return;
        }

        mVectorLayer->beginEditCommand( "Field calculator" );

        //update existing field
        if ( mUpdateExistingFieldCheckBox->checkState() == Qt::Checked )
        {
            QMap<QString, int>::const_iterator fieldIt = mFieldMap.find( mExistingFieldComboBox->currentText() );
            if ( fieldIt != mFieldMap.end() )
            {
                mAttributeId = fieldIt.value();
            }
        }
        //create new field
        else
        {
            //create new field
            QgsField newField( mOutputFieldNameLineEdit->text(),
                               ( QVariant::Type ) mOutputFieldTypeComboBox->itemData( mOutputFieldTypeComboBox->currentIndex(), Qt::UserRole ).toInt(),
                               mOutputFieldTypeComboBox->itemData( mOutputFieldTypeComboBox->currentIndex(), Qt::UserRole + 1 ).toString(),
                               mOuputFieldWidthSpinBox->value(),
                               mOutputFieldPrecisionSpinBox->value() );

            if ( !mVectorLayer->addAttribute( newField ) )
            {
                QMessageBox::critical( 0, tr( "Provider error" ), tr( "Could not add the new field to the provider." ) );
                mVectorLayer->destroyEditCommand();
                return;
            }

            //get index of the new field
            const QgsFieldMap fieldList = mVectorLayer->pendingFields();

            QgsFieldMap::const_iterator it = fieldList.constBegin();
            for ( ; it != fieldList.constEnd(); ++it )
            {
                if ( it.value().name() == mOutputFieldNameLineEdit->text() )
                {
                    mAttributeId = it.key();
                    break;
                }
            }
        }

        if ( mAttributeId == -1 )
        {
            mVectorLayer->destroyEditCommand();
            return;
        }

        //go through all the features and change the new attribute
        QgsFeature feature;
        bool calculationSuccess = true;
        QString error;

        bool onlySelected = ( mOnlyUpdateSelectedCheckBox->checkState() == Qt::Checked );
        QgsFeatureIds selectedIds = mVectorLayer->selectedFeaturesIds();

        // block layerModified signals (that would trigger table update)
        mVectorLayer->blockSignals( true );

        bool useGeometry = exp.needsGeometry();
        int rownum = 1;

        mVectorLayer->select( mVectorLayer->pendingAllAttributesList(), QgsRectangle(), useGeometry, false );
        while ( mVectorLayer->nextFeature( feature ) )
        {
            if ( onlySelected )
            {
                if ( !selectedIds.contains( feature.id() ) )
                {
                    continue;
                }
            }

            exp.setCurrentRowNumber( rownum );

            QVariant value = exp.evaluate( &feature );
            if ( exp.hasEvalError() )
            {
                calculationSuccess = false;
                error = exp.evalErrorString();
                break;
            }
            else
            {
                mVectorLayer->changeAttributeValue( feature.id(), mAttributeId, value, false );
            }

            rownum++;
        }

        // stop blocking layerModified signals and make sure that one layerModified signal is emitted
        mVectorLayer->blockSignals( false );
        mVectorLayer->setModified( true, false );

        if ( !calculationSuccess )
        {
            QMessageBox::critical( 0, tr( "Error" ), tr( "An error occured while evaluating the calculation string:\n%1" ).arg( error ) );
            mVectorLayer->destroyEditCommand();
            return;
        }

        mVectorLayer->endEditCommand();
    }
    QDialog::accept();
}
Exemple #14
0
void QgsWfsCapabilities::capabilitiesReplyFinished()
{
  const QByteArray &buffer = mResponse;

  QgsDebugMsg( "parsing capabilities: " + buffer );

  // parse XML
  QString capabilitiesDocError;
  QDomDocument capabilitiesDocument;
  if ( !capabilitiesDocument.setContent( buffer, true, &capabilitiesDocError ) )
  {
    mErrorCode = QgsWfsRequest::XmlError;
    mErrorMessage = capabilitiesDocError;
    emit gotCapabilities();
    return;
  }

  QDomElement doc = capabilitiesDocument.documentElement();

  // handle exceptions
  if ( doc.tagName() == QLatin1String( "ExceptionReport" ) )
  {
    QDomNode ex = doc.firstChild();
    QString exc = ex.toElement().attribute( QStringLiteral( "exceptionCode" ), QStringLiteral( "Exception" ) );
    QDomElement ext = ex.firstChild().toElement();
    mErrorCode = QgsWfsRequest::ServerExceptionError;
    mErrorMessage = exc + ": " + ext.firstChild().nodeValue();
    emit gotCapabilities();
    return;
  }

  mCaps.clear();

  //test wfs version
  mCaps.version = doc.attribute( QStringLiteral( "version" ) );
  if ( !mCaps.version.startsWith( QLatin1String( "1.0" ) ) &&
       !mCaps.version.startsWith( QLatin1String( "1.1" ) ) &&
       !mCaps.version.startsWith( QLatin1String( "2.0" ) ) )
  {
    mErrorCode = WFSVersionNotSupported;
    mErrorMessage = tr( "WFS version %1 not supported" ).arg( mCaps.version );
    emit gotCapabilities();
    return;
  }

  // WFS 2.0 implementation are supposed to implement resultType=hits, and some
  // implementations (GeoServer) might advertize it, whereas others (MapServer) do not.
  // WFS 1.1 implementation too I think, but in the examples of the GetCapabilities
  // response of the WFS 1.1 standard (and in common implementations), this is
  // explicitly advertized
  if ( mCaps.version.startsWith( QLatin1String( "2.0" ) ) )
    mCaps.supportsHits = true;

  // Note: for conveniency, we do not use the elementsByTagNameNS() method as
  // the WFS and OWS namespaces URI are not the same in all versions

  if ( mCaps.version.startsWith( QLatin1String( "1.0" ) ) )
  {
    QDomElement capabilityElem = doc.firstChildElement( QStringLiteral( "Capability" ) );
    if ( !capabilityElem.isNull() )
    {
      QDomElement requestElem = capabilityElem.firstChildElement( QStringLiteral( "Request" ) );
      if ( !requestElem.isNull() )
      {
        QDomElement getFeatureElem = requestElem.firstChildElement( QStringLiteral( "GetFeature" ) );
        if ( !getFeatureElem.isNull() )
        {
          QDomElement resultFormatElem = getFeatureElem.firstChildElement( QStringLiteral( "ResultFormat" ) );
          if ( !resultFormatElem.isNull() )
          {
            QDomElement child = resultFormatElem.firstChildElement();
            while ( !child.isNull() )
            {
              mCaps.outputFormats << child.tagName();
              child = child.nextSiblingElement();
            }
          }
        }
      }
    }
  }

  // find <ows:OperationsMetadata>
  QDomElement operationsMetadataElem = doc.firstChildElement( QStringLiteral( "OperationsMetadata" ) );
  if ( !operationsMetadataElem.isNull() )
  {
    QDomNodeList contraintList = operationsMetadataElem.elementsByTagName( QStringLiteral( "Constraint" ) );
    for ( int i = 0; i < contraintList.size(); ++i )
    {
      QDomElement contraint = contraintList.at( i ).toElement();
      if ( contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "DefaultMaxFeatures" ) /* WFS 1.1 */ )
      {
        QDomElement value = contraint.firstChildElement( QStringLiteral( "Value" ) );
        if ( !value.isNull() )
        {
          mCaps.maxFeatures = value.text().toInt();
          QgsDebugMsg( QString( "maxFeatures: %1" ).arg( mCaps.maxFeatures ) );
        }
      }
      else if ( contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "CountDefault" ) /* WFS 2.0 (e.g. MapServer) */ )
      {
        QDomElement value = contraint.firstChildElement( QStringLiteral( "DefaultValue" ) );
        if ( !value.isNull() )
        {
          mCaps.maxFeatures = value.text().toInt();
          QgsDebugMsg( QString( "maxFeatures: %1" ).arg( mCaps.maxFeatures ) );
        }
      }
      else if ( contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "ImplementsResultPaging" ) /* WFS 2.0 */ )
      {
        QDomElement value = contraint.firstChildElement( QStringLiteral( "DefaultValue" ) );
        if ( !value.isNull() && value.text() == QLatin1String( "TRUE" ) )
        {
          mCaps.supportsPaging = true;
          QgsDebugMsg( "Supports paging" );
        }
      }
      else if ( contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "ImplementsStandardJoins" ) ||
                contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "ImplementsSpatialJoins" ) /* WFS 2.0 */ )
      {
        QDomElement value = contraint.firstChildElement( QStringLiteral( "DefaultValue" ) );
        if ( !value.isNull() && value.text() == QLatin1String( "TRUE" ) )
        {
          mCaps.supportsJoins = true;
          QgsDebugMsg( "Supports joins" );
        }
      }
    }

    // In WFS 2.0, max features can also be set in Operation.GetFeature (e.g. GeoServer)
    // and we are also interested by resultType=hits for WFS 1.1
    QDomNodeList operationList = operationsMetadataElem.elementsByTagName( QStringLiteral( "Operation" ) );
    for ( int i = 0; i < operationList.size(); ++i )
    {
      QDomElement operation = operationList.at( i ).toElement();
      if ( operation.attribute( QStringLiteral( "name" ) ) == QLatin1String( "GetFeature" ) )
      {
        QDomNodeList operationContraintList = operation.elementsByTagName( QStringLiteral( "Constraint" ) );
        for ( int j = 0; j < operationContraintList.size(); ++j )
        {
          QDomElement contraint = operationContraintList.at( j ).toElement();
          if ( contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "CountDefault" ) )
          {
            QDomElement value = contraint.firstChildElement( QStringLiteral( "DefaultValue" ) );
            if ( !value.isNull() )
            {
              mCaps.maxFeatures = value.text().toInt();
              QgsDebugMsg( QString( "maxFeatures: %1" ).arg( mCaps.maxFeatures ) );
            }
            break;
          }
        }

        QDomNodeList parameterList = operation.elementsByTagName( QStringLiteral( "Parameter" ) );
        for ( int j = 0; j < parameterList.size(); ++j )
        {
          QDomElement parameter = parameterList.at( j ).toElement();
          if ( parameter.attribute( QStringLiteral( "name" ) ) == QLatin1String( "resultType" ) )
          {
            QDomNodeList valueList = parameter.elementsByTagName( QStringLiteral( "Value" ) );
            for ( int k = 0; k < valueList.size(); ++k )
            {
              QDomElement value = valueList.at( k ).toElement();
              if ( value.text() == QLatin1String( "hits" ) )
              {
                mCaps.supportsHits = true;
                QgsDebugMsg( "Support hits" );
                break;
              }
            }
          }
          else if ( parameter.attribute( QStringLiteral( "name" ) ) == QLatin1String( "outputFormat" ) )
          {
            QDomNodeList valueList = parameter.elementsByTagName( QStringLiteral( "Value" ) );
            for ( int k = 0; k < valueList.size(); ++k )
            {
              QDomElement value = valueList.at( k ).toElement();
              mCaps.outputFormats << value.text();
            }
          }
        }

        break;
      }
    }
  }

  //go to <FeatureTypeList>
  QDomElement featureTypeListElem = doc.firstChildElement( QStringLiteral( "FeatureTypeList" ) );
  if ( featureTypeListElem.isNull() )
  {
    emit gotCapabilities();
    return;
  }

  // Parse operations supported for all feature types
  bool insertCap = false;
  bool updateCap = false;
  bool deleteCap = false;
  // WFS < 2
  if ( mCaps.version.startsWith( QLatin1String( "1" ) ) )
  {
    parseSupportedOperations( featureTypeListElem.firstChildElement( QStringLiteral( "Operations" ) ),
                              insertCap,
                              updateCap,
                              deleteCap );
  }
  else // WFS 2.0.0 tested on GeoServer
  {
    QDomNodeList operationNodes = doc.elementsByTagName( "Operation" );
    for ( int i = 0; i < operationNodes.count(); i++ )
    {
      QDomElement operationElement = operationNodes.at( i ).toElement( );
      if ( operationElement.isElement( ) && "Transaction" == operationElement.attribute( "name" ) )
      {
        insertCap = true;
        updateCap = true;
        deleteCap = true;
      }
    }
  }

  // get the <FeatureType> elements
  QDomNodeList featureTypeList = featureTypeListElem.elementsByTagName( QStringLiteral( "FeatureType" ) );
  for ( int i = 0; i < featureTypeList.size(); ++i )
  {
    FeatureType featureType;
    QDomElement featureTypeElem = featureTypeList.at( i ).toElement();

    //Name
    QDomNodeList nameList = featureTypeElem.elementsByTagName( QStringLiteral( "Name" ) );
    if ( nameList.length() > 0 )
    {
      featureType.name = nameList.at( 0 ).toElement().text();
    }
    //Title
    QDomNodeList titleList = featureTypeElem.elementsByTagName( QStringLiteral( "Title" ) );
    if ( titleList.length() > 0 )
    {
      featureType.title = titleList.at( 0 ).toElement().text();
    }
    //Abstract
    QDomNodeList abstractList = featureTypeElem.elementsByTagName( QStringLiteral( "Abstract" ) );
    if ( abstractList.length() > 0 )
    {
      featureType.abstract = abstractList.at( 0 ).toElement().text();
    }

    //DefaultSRS is always the first entry in the feature srs list
    QDomNodeList defaultCRSList = featureTypeElem.elementsByTagName( QStringLiteral( "DefaultSRS" ) );
    if ( defaultCRSList.length() == 0 )
      // In WFS 2.0, this is spelled DefaultCRS...
      defaultCRSList = featureTypeElem.elementsByTagName( QStringLiteral( "DefaultCRS" ) );
    if ( defaultCRSList.length() > 0 )
    {
      QString srsname( defaultCRSList.at( 0 ).toElement().text() );
      // Some servers like Geomedia advertize EPSG:XXXX even in WFS 1.1 or 2.0
      if ( srsname.startsWith( QLatin1String( "EPSG:" ) ) )
        mCaps.useEPSGColumnFormat = true;
      featureType.crslist.append( NormalizeSRSName( srsname ) );
    }

    //OtherSRS
    QDomNodeList otherCRSList = featureTypeElem.elementsByTagName( QStringLiteral( "OtherSRS" ) );
    if ( otherCRSList.length() == 0 )
      // In WFS 2.0, this is spelled OtherCRS...
      otherCRSList = featureTypeElem.elementsByTagName( QStringLiteral( "OtherCRS" ) );
    for ( int i = 0; i < otherCRSList.size(); ++i )
    {
      featureType.crslist.append( NormalizeSRSName( otherCRSList.at( i ).toElement().text() ) );
    }

    //Support <SRS> for compatibility with older versions
    QDomNodeList srsList = featureTypeElem.elementsByTagName( QStringLiteral( "SRS" ) );
    for ( int i = 0; i < srsList.size(); ++i )
    {
      featureType.crslist.append( NormalizeSRSName( srsList.at( i ).toElement().text() ) );
    }

    // Get BBox WFS 1.0 way
    QDomElement latLongBB = featureTypeElem.firstChildElement( QStringLiteral( "LatLongBoundingBox" ) );
    if ( latLongBB.hasAttributes() )
    {
      // Despite the name LatLongBoundingBox, the coordinates are supposed to
      // be expressed in <SRS>. From the WFS schema;
      // <!-- The LatLongBoundingBox element is used to indicate the edges of
      // an enclosing rectangle in the SRS of the associated feature type.
      featureType.bbox = QgsRectangle(
                           latLongBB.attribute( QStringLiteral( "minx" ) ).toDouble(),
                           latLongBB.attribute( QStringLiteral( "miny" ) ).toDouble(),
                           latLongBB.attribute( QStringLiteral( "maxx" ) ).toDouble(),
                           latLongBB.attribute( QStringLiteral( "maxy" ) ).toDouble() );
      featureType.bboxSRSIsWGS84 = false;

      // But some servers do not honour this and systematically reproject to WGS84
      // such as GeoServer. See http://osgeo-org.1560.x6.nabble.com/WFS-LatLongBoundingBox-td3813810.html
      // This is also true of TinyOWS
      if ( !featureType.crslist.isEmpty() &&
           featureType.bbox.xMinimum() >= -180 && featureType.bbox.yMinimum() >= -90 &&
           featureType.bbox.xMaximum() <= 180 && featureType.bbox.yMaximum() < 90 )
      {
        QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( featureType.crslist[0] );
        if ( !crs.isGeographic() )
        {
          // If the CRS is projected then check that projecting the corner of the bbox, assumed to be in WGS84,
          // into the CRS, and then back to WGS84, works (check that we are in the validity area)
          QgsCoordinateReferenceSystem crsWGS84 = QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "CRS:84" ) );
          QgsCoordinateTransform ct( crsWGS84, crs );

          QgsPointXY ptMin( featureType.bbox.xMinimum(), featureType.bbox.yMinimum() );
          QgsPointXY ptMinBack( ct.transform( ct.transform( ptMin, QgsCoordinateTransform::ForwardTransform ), QgsCoordinateTransform::ReverseTransform ) );
          QgsPointXY ptMax( featureType.bbox.xMaximum(), featureType.bbox.yMaximum() );
          QgsPointXY ptMaxBack( ct.transform( ct.transform( ptMax, QgsCoordinateTransform::ForwardTransform ), QgsCoordinateTransform::ReverseTransform ) );

          QgsDebugMsg( featureType.bbox.toString() );
          QgsDebugMsg( ptMinBack.toString() );
          QgsDebugMsg( ptMaxBack.toString() );

          if ( fabs( featureType.bbox.xMinimum() - ptMinBack.x() ) < 1e-5 &&
               fabs( featureType.bbox.yMinimum() - ptMinBack.y() ) < 1e-5 &&
               fabs( featureType.bbox.xMaximum() - ptMaxBack.x() ) < 1e-5 &&
               fabs( featureType.bbox.yMaximum() - ptMaxBack.y() ) < 1e-5 )
          {
            QgsDebugMsg( "Values of LatLongBoundingBox are consistent with WGS84 long/lat bounds, so as the CRS is projected, assume they are indeed in WGS84 and not in the CRS units" );
            featureType.bboxSRSIsWGS84 = true;
          }
        }
      }
    }
    else
    {
      // WFS 1.1 way
      QDomElement WGS84BoundingBox = featureTypeElem.firstChildElement( QStringLiteral( "WGS84BoundingBox" ) );
      if ( !WGS84BoundingBox.isNull() )
      {
        QDomElement lowerCorner = WGS84BoundingBox.firstChildElement( QStringLiteral( "LowerCorner" ) );
        QDomElement upperCorner = WGS84BoundingBox.firstChildElement( QStringLiteral( "UpperCorner" ) );
        if ( !lowerCorner.isNull() && !upperCorner.isNull() )
        {
          QStringList lowerCornerList = lowerCorner.text().split( QStringLiteral( " " ), QString::SkipEmptyParts );
          QStringList upperCornerList = upperCorner.text().split( QStringLiteral( " " ), QString::SkipEmptyParts );
          if ( lowerCornerList.size() == 2 && upperCornerList.size() == 2 )
          {
            featureType.bbox = QgsRectangle(
                                 lowerCornerList[0].toDouble(),
                                 lowerCornerList[1].toDouble(),
                                 upperCornerList[0].toDouble(),
                                 upperCornerList[1].toDouble() );
            featureType.bboxSRSIsWGS84 = true;
          }
        }
      }
    }

    // Parse Operations specific to the type name
    parseSupportedOperations( featureTypeElem.firstChildElement( QStringLiteral( "Operations" ) ),
                              featureType.insertCap,
                              featureType.updateCap,
                              featureType.deleteCap );
    featureType.insertCap |= insertCap;
    featureType.updateCap |= updateCap;
    featureType.deleteCap |= deleteCap;

    mCaps.featureTypes.push_back( featureType );
  }

  Q_FOREACH ( const FeatureType &f, mCaps.featureTypes )
  {
    mCaps.setAllTypenames.insert( f.name );
    QString unprefixed( QgsWFSUtils::removeNamespacePrefix( f.name ) );
    if ( !mCaps.setAmbiguousUnprefixedTypename.contains( unprefixed ) )
    {
      if ( mCaps.mapUnprefixedTypenameToPrefixedTypename.contains( unprefixed ) )
      {
        mCaps.setAmbiguousUnprefixedTypename.insert( unprefixed );
        mCaps.mapUnprefixedTypenameToPrefixedTypename.remove( unprefixed );
      }
      else
      {
        mCaps.mapUnprefixedTypenameToPrefixedTypename[unprefixed] = f.name;
      }
    }
  }

  //go to <Filter_Capabilities>
  QDomElement filterCapabilitiesElem = doc.firstChildElement( QStringLiteral( "Filter_Capabilities" ) );
  if ( !filterCapabilitiesElem.isNull() )
    parseFilterCapabilities( filterCapabilitiesElem );

  // Hard-coded functions
  Function f_ST_GeometryFromText( QStringLiteral( "ST_GeometryFromText" ), 1, 2 );
  f_ST_GeometryFromText.returnType = QStringLiteral( "gml:AbstractGeometryType" );
  f_ST_GeometryFromText.argumentList << Argument( QStringLiteral( "wkt" ), QStringLiteral( "xs:string" ) );
  f_ST_GeometryFromText.argumentList << Argument( QStringLiteral( "srsname" ), QStringLiteral( "xs:string" ) );
  mCaps.functionList << f_ST_GeometryFromText;

  Function f_ST_GeomFromGML( QStringLiteral( "ST_GeomFromGML" ), 1 );
  f_ST_GeomFromGML.returnType = QStringLiteral( "gml:AbstractGeometryType" );
  f_ST_GeomFromGML.argumentList << Argument( QStringLiteral( "gml" ), QStringLiteral( "xs:string" ) );
  mCaps.functionList << f_ST_GeomFromGML;

  Function f_ST_MakeEnvelope( QStringLiteral( "ST_MakeEnvelope" ), 4, 5 );
  f_ST_MakeEnvelope.returnType = QStringLiteral( "gml:AbstractGeometryType" );
  f_ST_MakeEnvelope.argumentList << Argument( QStringLiteral( "minx" ), QStringLiteral( "xs:double" ) );
  f_ST_MakeEnvelope.argumentList << Argument( QStringLiteral( "miny" ), QStringLiteral( "xs:double" ) );
  f_ST_MakeEnvelope.argumentList << Argument( QStringLiteral( "maxx" ), QStringLiteral( "xs:double" ) );
  f_ST_MakeEnvelope.argumentList << Argument( QStringLiteral( "maxy" ), QStringLiteral( "xs:double" ) );
  f_ST_MakeEnvelope.argumentList << Argument( QStringLiteral( "srsname" ), QStringLiteral( "xs:string" ) );
  mCaps.functionList << f_ST_MakeEnvelope;

  emit gotCapabilities();
}
Exemple #15
0
bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shapefileName,
                                      bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p )
{
  if ( !layer )
  {
    return false;
  }
  QgsVectorDataProvider* dp = layer->dataProvider();
  if ( !dp )
  {
    return false;
  }
  bool useField = false;
  if ( uniqueIdField == -1 )
  {
    uniqueIdField = 0;
  }
  else
  {
    useField = true;
  }
  QgsFieldMap fields;
  fields.insert( 0 , QgsField( QString( "UID" ), QVariant::String ) );
  fields.insert( 1 , QgsField( QString( "AREA" ), QVariant::Double ) );
  fields.insert( 2 , QgsField( QString( "PERIM" ), QVariant::Double ) );

  QGis::WkbType outputType = QGis::WKBPolygon;
  const QgsCoordinateReferenceSystem crs = layer->crs();

  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs );
  QgsFeature currentFeature;
  QgsGeometry* dissolveGeometry = 0; //dissolve geometry
  QMultiMap<QString, QgsFeatureId> map;

  if ( onlySelectedFeatures )
  {
    //use QgsVectorLayer::featureAtId
    const QgsFeatureIds selection = layer->selectedFeaturesIds();
    QgsFeatureIds::const_iterator it = selection.constBegin();
    for ( ; it != selection.constEnd(); ++it )
    {
#if 0
      if ( p )
      {
        p->setValue( processedFeatures );
      }
      if ( p && p->wasCanceled() )
      {
        // break; // it may be better to do something else here?
        return false;
      }
#endif
      if ( !layer->featureAtId( *it, currentFeature, true, true ) )
      {
        continue;
      }
      map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
    }
  }
  else
  {
    layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
    while ( layer->nextFeature( currentFeature ) )
    {
#if 0
      if ( p )
      {
        p->setValue( processedFeatures );
      }
      if ( p && p->wasCanceled() )
      {
        // break; // it may be better to do something else here?
        return false;
      }
#endif
      map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
    }
  }

  QMultiMap<QString, QgsFeatureId>::const_iterator jt = map.constBegin();
  while ( jt != map.constEnd() )
  {
    QString currentKey = jt.key();
    int processedFeatures = 0;
    //take only selection
    if ( onlySelectedFeatures )
    {
      //use QgsVectorLayer::featureAtId
      const QgsFeatureIds selection = layer->selectedFeaturesIds();
      if ( p )
      {
        p->setMaximum( selection.size() );
      }
      processedFeatures = 0;
      while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
      {
        if ( p && p->wasCanceled() )
        {
          break;
        }
        if ( selection.contains( jt.value() ) )
        {
          if ( p )
          {
            p->setValue( processedFeatures );
          }
          if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
          {
            continue;
          }
          convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
          ++processedFeatures;
        }
        ++jt;
      }
      QList<double> values;
      if ( !dissolveGeometry )
      {
        QgsDebugMsg( "no dissolved geometry - should not happen" );
        return false;
      }
      dissolveGeometry = dissolveGeometry->convexHull();
      values = simpleMeasure( dissolveGeometry );
      QgsAttributeMap attributeMap;
      attributeMap.insert( 0 , QVariant( currentKey ) );
      attributeMap.insert( 1 , values[ 0 ] );
      attributeMap.insert( 2 , values[ 1 ] );
      QgsFeature dissolveFeature;
      dissolveFeature.setAttributeMap( attributeMap );
      dissolveFeature.setGeometry( dissolveGeometry );
      vWriter.addFeature( dissolveFeature );
    }
    //take all features
    else
    {
      int featureCount = layer->featureCount();
      if ( p )
      {
        p->setMaximum( featureCount );
      }
      processedFeatures = 0;
      while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
      {
        if ( p )
        {
          p->setValue( processedFeatures );
        }

        if ( p && p->wasCanceled() )
        {
          break;
        }
        if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
        {
          continue;
        }
        convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
        ++processedFeatures;
        ++jt;
      }
      QList<double> values;
      // QgsGeometry* tmpGeometry = 0;
      if ( !dissolveGeometry )
      {
        QgsDebugMsg( "no dissolved geometry - should not happen" );
        return false;
      }
      dissolveGeometry = dissolveGeometry->convexHull();
      // values = simpleMeasure( tmpGeometry );
      values = simpleMeasure( dissolveGeometry );
      QgsAttributeMap attributeMap;
      attributeMap.insert( 0 , QVariant( currentKey ) );
      attributeMap.insert( 1 , QVariant( values[ 0 ] ) );
      attributeMap.insert( 2 , QVariant( values[ 1 ] ) );
      QgsFeature dissolveFeature;
      dissolveFeature.setAttributeMap( attributeMap );
      dissolveFeature.setGeometry( dissolveGeometry );
      vWriter.addFeature( dissolveFeature );
    }
  }
  return true;
}
void QgsRasterProjector::calcSrcExtent()
{
  /* Run around the mCPMatrix and find source extent */
  // Attention, source limits are not necessarily on destination edges, e.g.
  // for destination EPSG:32661 Polar Stereographic and source EPSG:4326,
  // the maximum y may be in the middle of destination extent
  // TODO: How to find extent exactly and quickly?
  // For now, we runt through all matrix
  QgsPoint myPoint = mCPMatrix[0][0];
  mSrcExtent = QgsRectangle( myPoint.x(), myPoint.y(), myPoint.x(), myPoint.y() );
  for ( int i = 0; i < mCPRows; i++ )
  {
    for ( int j = 0; j < mCPCols ; j++ )
    {
      myPoint = mCPMatrix[i][j];
      if ( mCPLegalMatrix[i][j] )
      {
        mSrcExtent.combineExtentWith( myPoint.x(), myPoint.y() );
      }
    }
  }
  // Expand a bit to avoid possible approx coords falling out because of representation error?

  // Combine with maximum source  extent
  mSrcExtent = mSrcExtent.intersect( &mExtent );

  // If mMaxSrcXRes, mMaxSrcYRes are defined (fixed src resolution)
  // align extent to src resolution to avoid jumping of reprojected pixels
  // when shifting resampled grid.
  // Important especially if we are over mMaxSrcXRes, mMaxSrcYRes limits
  // Note however, that preceding filters (like resampler) may read data
  // on different resolution.

  QgsDebugMsg( "mSrcExtent = " + mSrcExtent.toString() );
  QgsDebugMsg( "mExtent = " + mExtent.toString() );
  if ( !mExtent.isEmpty() )
  {
    if ( mMaxSrcXRes > 0 )
    {
      // with floor/ceil it should work correctly also for mSrcExtent.xMinimum() < mExtent.xMinimum()
      double col = floor(( mSrcExtent.xMinimum() - mExtent.xMinimum() ) / mMaxSrcXRes );
      double x = mExtent.xMinimum() + col * mMaxSrcXRes;
      mSrcExtent.setXMinimum( x );

      col = ceil(( mSrcExtent.xMaximum() - mExtent.xMinimum() ) / mMaxSrcXRes );
      x = mExtent.xMinimum() + col * mMaxSrcXRes;
      mSrcExtent.setXMaximum( x );
    }
    if ( mMaxSrcYRes > 0 )
    {
      double row = floor(( mExtent.yMaximum() - mSrcExtent.yMaximum() ) / mMaxSrcYRes );
      double y = mExtent.yMaximum() - row * mMaxSrcYRes;
      mSrcExtent.setYMaximum( y );

      row = ceil(( mExtent.yMaximum() - mSrcExtent.yMinimum() ) / mMaxSrcYRes );
      y = mExtent.yMaximum() - row * mMaxSrcYRes;
      mSrcExtent.setYMinimum( y );
    }
  }
  QgsDebugMsg( "mSrcExtent = " + mSrcExtent.toString() );
}
Exemple #17
0
bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapefileName,
                                    bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p )
{
  if ( !layer )
  {
    return false;
  }
  QgsVectorDataProvider* dp = layer->dataProvider();
  if ( !dp )
  {
    return false;
  }
  bool useField = false;
  if ( uniqueIdField == -1 )
  {
    uniqueIdField = 0;
  }
  else
  {
    useField = true;
  }

  QGis::WkbType outputType = dp->geometryType();
  const QgsCoordinateReferenceSystem crs = layer->crs();

  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
  QgsFeature currentFeature;
  QMultiMap<QString, QgsFeatureId> map;

  if ( onlySelectedFeatures )
  {
    //use QgsVectorLayer::featureAtId
    const QgsFeatureIds selection = layer->selectedFeaturesIds();
    QgsFeatureIds::const_iterator it = selection.constBegin();
    for ( ; it != selection.constEnd(); ++it )
    {
      if ( !layer->featureAtId( *it, currentFeature, true, true ) )
      {
        continue;
      }
      map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
    }
  }
  else
  {
    layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
    while ( layer->nextFeature( currentFeature ) )
    {
      map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
    }
  }

  QgsGeometry *dissolveGeometry = 0; //dissolve geometry
  QMultiMap<QString, QgsFeatureId>::const_iterator jt = map.constBegin();
  QgsFeature outputFeature;
  while ( jt != map.constEnd() )
  {
    QString currentKey = jt.key();
    int processedFeatures = 0;
    bool first = true;
    //take only selection
    if ( onlySelectedFeatures )
    {
      //use QgsVectorLayer::featureAtId
      const QgsFeatureIds selection = layer->selectedFeaturesIds();
      if ( p )
      {
        p->setMaximum( selection.size() );
      }
      while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
      {
        if ( p && p->wasCanceled() )
        {
          break;
        }
        if ( selection.contains( jt.value() ) )
        {
          if ( p )
          {
            p->setValue( processedFeatures );
          }
          if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
          {
            continue;
          }
          if ( first )
          {
            outputFeature.setAttributeMap( currentFeature.attributeMap() );
            first = false;
          }
          dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
          ++processedFeatures;
        }
        ++jt;
      }
    }
    //take all features
    else
    {
      int featureCount = layer->featureCount();
      if ( p )
      {
        p->setMaximum( featureCount );
      }
      while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
      {
        if ( p )
        {
          p->setValue( processedFeatures );
        }

        if ( p && p->wasCanceled() )
        {
          break;
        }
        if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
        {
          continue;
        }
        {
          outputFeature.setAttributeMap( currentFeature.attributeMap() );
          first = false;
        }
        dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
        ++processedFeatures;
        ++jt;
      }
    }
    outputFeature.setGeometry( dissolveGeometry );
    vWriter.addFeature( outputFeature );
  }
  return true;
}
void QgsAtlasComposition::prepareForFeature( size_t featureI )
{
  if ( !mComposerMap || !mCoverageLayer )
  {
    return;
  }

  // retrieve the next feature, based on its id
  mCoverageLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ] ) ).nextFeature( mCurrentFeature );

  if ( !mSingleFile && mFilenamePattern.size() > 0 )
  {
    QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) );
    QVariant filenameRes = mFilenameExpr->evaluate( &mCurrentFeature, mCoverageLayer->pendingFields() );
    if ( mFilenameExpr->hasEvalError() )
    {
      throw std::runtime_error( tr( "Filename eval error: %1" ).arg( mFilenameExpr->evalErrorString() ).toLocal8Bit().data() );
    }

    mCurrentFilename = filenameRes.toString();
  }

  //
  // compute the new extent
  // keep the original aspect ratio
  // and apply a margin

  // QgsGeometry::boundingBox is expressed in the geometry"s native CRS
  // We have to transform the grometry to the destination CRS and ask for the bounding box
  // Note: we cannot directly take the transformation of the bounding box, since transformations are not linear

  QgsGeometry tgeom( *mCurrentFeature.geometry() );
  tgeom.transform( mTransform );
  QgsRectangle geom_rect = tgeom.boundingBox();

  double xa1 = geom_rect.xMinimum();
  double xa2 = geom_rect.xMaximum();
  double ya1 = geom_rect.yMinimum();
  double ya2 = geom_rect.yMaximum();
  QgsRectangle new_extent = geom_rect;

  // restore the original extent
  // (successive calls to setNewExtent tend to deform the original rectangle)
  mComposerMap->setNewExtent( mOrigExtent );

  if ( mFixedScale )
  {
    // only translate, keep the original scale (i.e. width x height)

    double geom_center_x = ( xa1 + xa2 ) / 2.0;
    double geom_center_y = ( ya1 + ya2 ) / 2.0;
    double xx = geom_center_x - mOrigExtent.width() / 2.0;
    double yy = geom_center_y - mOrigExtent.height() / 2.0;
    new_extent = QgsRectangle( xx,
                               yy,
                               xx + mOrigExtent.width(),
                               yy + mOrigExtent.height() );
  }
  else
  {
    // auto scale

    double geom_ratio = geom_rect.width() / geom_rect.height();
    double map_ratio = mOrigExtent.width() / mOrigExtent.height();

    // geometry height is too big
    if ( geom_ratio < map_ratio )
    {
      // extent the bbox's width
      double adj_width = ( map_ratio * geom_rect.height() - geom_rect.width() ) / 2.0;
      xa1 -= adj_width;
      xa2 += adj_width;
    }
    // geometry width is too big
    else if ( geom_ratio > map_ratio )
    {
      // extent the bbox's height
      double adj_height = ( geom_rect.width() / map_ratio - geom_rect.height() ) / 2.0;
      ya1 -= adj_height;
      ya2 += adj_height;
    }
    new_extent = QgsRectangle( xa1, ya1, xa2, ya2 );

    if ( mMargin > 0.0 )
    {
      new_extent.scale( 1 + mMargin );
    }
  }

  // evaluate label expressions
  QList<QgsComposerLabel*> labels;
  mComposition->composerItems( labels );
  QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) );

  for ( QList<QgsComposerLabel*>::iterator lit = labels.begin(); lit != labels.end(); ++lit )
  {
    ( *lit )->setExpressionContext( &mCurrentFeature, mCoverageLayer );
  }

  // set the new extent (and render)
  mComposerMap->setNewExtent( new_extent );
}
Exemple #19
0
bool QgsGeometryAnalyzer::eventLayer( QgsVectorLayer* lineLayer, QgsVectorLayer* eventLayer, int lineField, int eventField, QList<int>& unlocatedFeatureIds, const QString& outputLayer,
                                      const QString& outputFormat, int locationField1, int locationField2, int offsetField, double offsetScale,
                                      bool forceSingleGeometry, QgsVectorDataProvider* memoryProvider, QProgressDialog* p )
{
  if ( !lineLayer || !eventLayer || !lineLayer->isValid() || !eventLayer->isValid() )
  {
    return false;
  }

  //create line field / id map for line layer
  QMultiHash< QString, QgsFeatureId > lineLayerIdMap; //1:n possible (e.g. several linear reference geometries for one feature in the event layer)
  lineLayer->select( QgsAttributeList() << lineField,
                     QgsRectangle(), false, false );
  QgsFeature fet;
  while ( lineLayer->nextFeature( fet ) )
  {
    lineLayerIdMap.insert( fet.attributeMap()[lineField].toString(), fet.id() );
  }

  //create output datasource or attributes in memory provider
  QgsVectorFileWriter* fileWriter = 0;
  QgsFeatureList memoryProviderFeatures;
  if ( !memoryProvider )
  {
    QGis::WkbType memoryProviderType = QGis::WKBMultiLineString;
    if ( locationField2 == -1 )
    {
      memoryProviderType = forceSingleGeometry ? QGis::WKBPoint : QGis::WKBMultiPoint;
    }
    else
    {
      memoryProviderType = forceSingleGeometry ? QGis::WKBLineString : QGis::WKBMultiLineString;
    }
    fileWriter = new QgsVectorFileWriter( outputLayer,
                                          eventLayer->dataProvider()->encoding(),
                                          eventLayer->pendingFields(),
                                          memoryProviderType,
                                          &( lineLayer->crs() ),
                                          outputFormat );
  }
  else
  {
    memoryProvider->addAttributes( eventLayer->pendingFields().values() );
  }

  //iterate over eventLayer and write new features to output file or layer
  eventLayer->select( eventLayer->pendingAllAttributesList(), QgsRectangle(), false, false );
  QgsGeometry* lrsGeom = 0;
  QgsFeature lineFeature;
  double measure1, measure2;

  int nEventFeatures = eventLayer->pendingFeatureCount();
  int featureCounter = 0;
  int nOutputFeatures = 0; //number of output features for the current event feature
  if ( p )
  {
    p->setWindowModality( Qt::WindowModal );
    p->setMinimum( 0 );
    p->setMaximum( nEventFeatures );
    p->show();
  }

  while ( eventLayer->nextFeature( fet ) )
  {
    nOutputFeatures = 0;

    //update progress dialog
    if ( p )
    {
      if ( p->wasCanceled() )
      {
        break;
      }
      p->setValue( featureCounter );
      ++featureCounter;
    }

    measure1 = fet.attributeMap()[locationField1].toDouble();
    if ( locationField2 != -1 )
    {
      measure2 = fet.attributeMap()[locationField2].toDouble();
    }

    QList<QgsFeatureId> featureIdList = lineLayerIdMap.values( fet.attributeMap()[eventField].toString() );
    QList<QgsFeatureId>::const_iterator featureIdIt = featureIdList.constBegin();
    for ( ; featureIdIt != featureIdList.constEnd(); ++featureIdIt )
    {
      if ( !lineLayer->featureAtId( *featureIdIt, lineFeature, true, false ) )
      {
        continue;
      }

      if ( locationField2 == -1 )
      {
        lrsGeom = locateAlongMeasure( measure1, lineFeature.geometry() );
      }
      else
      {
        lrsGeom = locateBetweenMeasures( measure1, measure2, lineFeature.geometry() );
      }

      if ( lrsGeom )
      {
        ++nOutputFeatures;
        addEventLayerFeature( fet, lrsGeom, lineFeature.geometry(), fileWriter, memoryProviderFeatures, offsetField, offsetScale, forceSingleGeometry );
      }
    }
    if ( nOutputFeatures < 1 )
    {
      unlocatedFeatureIds.push_back( fet.id() );
    }
  }

  if ( p )
  {
    p->setValue( nEventFeatures );
  }

  if ( memoryProvider )
  {
    memoryProvider->addFeatures( memoryProviderFeatures );
  }
  delete fileWriter;
  return true;
}
void QgsComposerView::mousePressEvent( QMouseEvent* e )
{
  if ( !composition() )
  {
    return;
  }

  QPointF scenePoint = mapToScene( e->pos() );
  QPointF snappedScenePoint = composition()->snapPointToGrid( scenePoint );
  mMousePressStartPos = e->pos();

  //lock/unlock position of item with right click
  if ( e->button() == Qt::RightButton )
  {
    QgsComposerItem* selectedItem = composition()->composerItemAt( scenePoint );
    if ( selectedItem )
    {
      bool lock = selectedItem->positionLock() ? false : true;
      selectedItem->setPositionLock( lock );
      selectedItem->update();
    }
    return;
  }
  else if ( e->button() == Qt::MidButton )
  {
    //pan composer with middle button
    mPanning = true;
    mMouseLastXY = e->pos();
    if ( composition() )
    {
      //lock cursor to closed hand cursor
      composition()->setPreventCursorChange( true );
    }
    viewport()->setCursor( Qt::ClosedHandCursor );
    return;
  }

  switch ( mCurrentTool )
  {
      //select/deselect items and pass mouse event further
    case Select:
    {
      //check if we are clicking on a selection handle
      if ( composition()->selectionHandles()->isVisible() )
      {
        //selection handles are being shown, get mouse action for current cursor position
        QgsComposerMouseHandles::MouseAction mouseAction = composition()->selectionHandles()->mouseActionForScenePos( scenePoint );

        if ( mouseAction != QgsComposerMouseHandles::MoveItem && mouseAction != QgsComposerMouseHandles::NoAction && mouseAction != QgsComposerMouseHandles::SelectItem )
        {
          //mouse is over a resize handle, so propagate event onward
          QGraphicsView::mousePressEvent( e );
          return;
        }
      }

      QgsComposerItem* selectedItem = 0;
      QgsComposerItem* previousSelectedItem = 0;

      if ( e->modifiers() & Qt::ControlModifier )
      {
        //CTRL modifier, so we are trying to select the next item below the current one
        //first, find currently selected item
        QList<QgsComposerItem*> selectedItems = composition()->selectedComposerItems();
        if ( selectedItems.size() > 0 )
        {
          previousSelectedItem = selectedItems.at( 0 );
        }
      }

      if ( previousSelectedItem )
      {
        //select highest item just below previously selected item at position of event
        selectedItem = composition()->composerItemAt( scenePoint, previousSelectedItem );

        //if we didn't find a lower item we'll use the top-most as fall-back
        //this duplicates mapinfo/illustrator/etc behaviour where ctrl-clicks are "cyclic"
        if ( !selectedItem )
        {
          selectedItem = composition()->composerItemAt( scenePoint );
        }
      }
      else
      {
        //select topmost item at position of event
        selectedItem = composition()->composerItemAt( scenePoint );
      }

      if ( !selectedItem )
      {
        //not clicking over an item, so start marquee selection
        startMarqueeSelect( scenePoint );
        break;
      }

      if (( !selectedItem->selected() ) &&        //keep selection if an already selected item pressed
          !( e->modifiers() & Qt::ShiftModifier ) ) //keep selection if shift key pressed
      {
        composition()->clearSelection();
      }

      if (( e->modifiers() & Qt::ShiftModifier ) && ( selectedItem->selected() ) )
      {
        //SHIFT-clicking a selected item deselects it
        selectedItem->setSelected( false );

        //Check if we have any remaining selected items, and if so, update the item panel
        QList<QgsComposerItem*> selectedItems = composition()->selectedComposerItems();
        if ( selectedItems.size() > 0 )
        {
          emit selectedItemChanged( selectedItems.at( 0 ) );
        }
      }
      else
      {
        selectedItem->setSelected( true );
        QGraphicsView::mousePressEvent( e );
        emit selectedItemChanged( selectedItem );
      }
      break;
    }

    case Zoom:
    {
      if ( !( e->modifiers() & Qt::ShiftModifier ) )
      {
        //zoom in action
        startMarqueeZoom( scenePoint );
      }
      else
      {
        //zoom out action, so zoom out and recenter on clicked point
        double scaleFactor = 2;
        //get current visible part of scene
        QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
        QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() );

        //transform the mouse pos to scene coordinates
        QPointF scenePoint = mapToScene( e->pos() );

        visibleRect.scale( scaleFactor, scenePoint.x(), scenePoint.y() );
        QRectF boundsRect = visibleRect.toRectF();

        //zoom view to fit desired bounds
        fitInView( boundsRect, Qt::KeepAspectRatio );
      }
      break;
    }

    case Pan:
    {
      //pan action
      mPanning = true;
      mMouseLastXY = e->pos();
      viewport()->setCursor( Qt::ClosedHandCursor );
      break;
    }

    case MoveItemContent:
    {
      //get a list of items at clicked position
      QList<QGraphicsItem *> itemsAtCursorPos = items( e->pos() );
      if ( itemsAtCursorPos.size() == 0 )
      {
        //no items at clicked position
        return;
      }

      //find highest QgsComposerItem at clicked position
      //(other graphics items may be higher, eg selection handles)
      QList<QGraphicsItem*>::iterator itemIter = itemsAtCursorPos.begin();
      for ( ; itemIter != itemsAtCursorPos.end(); ++itemIter )
      {
        QgsComposerItem* item = dynamic_cast<QgsComposerItem *>(( *itemIter ) );
        if ( item )
        {
          //we've found the highest QgsComposerItem
          mMoveContentStartPos = scenePoint;
          mMoveContentItem = item;
          break;
        }
      }

      //no QgsComposerItem at clicked position
      return;
    }

    case AddArrow:
    {
      mRubberBandStartPos = QPointF( snappedScenePoint.x(), snappedScenePoint.y() );
      mRubberBandLineItem = new QGraphicsLineItem( snappedScenePoint.x(), snappedScenePoint.y(), snappedScenePoint.x(), snappedScenePoint.y() );
      mRubberBandLineItem->setZValue( 1000 );
      scene()->addItem( mRubberBandLineItem );
      scene()->update();
      break;
    }

    //create rubber band for map and ellipse items
    case AddMap:
    case AddRectangle:
    case AddTriangle:
    case AddEllipse:
    case AddHtml:
    {
      QTransform t;
      mRubberBandItem = new QGraphicsRectItem( 0, 0, 0, 0 );
      mRubberBandStartPos = QPointF( snappedScenePoint.x(), snappedScenePoint.y() );
      t.translate( snappedScenePoint.x(), snappedScenePoint.y() );
      mRubberBandItem->setTransform( t );
      mRubberBandItem->setZValue( 1000 );
      scene()->addItem( mRubberBandItem );
      scene()->update();
    }
    break;

    case AddLabel:
      if ( composition() )
      {
        QgsComposerLabel* newLabelItem = new QgsComposerLabel( composition() );
        newLabelItem->setText( tr( "QGIS" ) );
        newLabelItem->adjustSizeToText();
        newLabelItem->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLabelItem->rect().width(), newLabelItem->rect().height() ) );
        composition()->addComposerLabel( newLabelItem );
        emit actionFinished();
        composition()->pushAddRemoveCommand( newLabelItem, tr( "Label added" ) );
      }
      break;

    case AddScalebar:
      if ( composition() )
      {
        QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( composition() );
        newScaleBar->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 20, 20 ) );
        composition()->addComposerScaleBar( newScaleBar );
        QList<const QgsComposerMap*> mapItemList = composition()->composerMapItems();
        if ( mapItemList.size() > 0 )
        {
          newScaleBar->setComposerMap( mapItemList.at( 0 ) );
        }
        newScaleBar->applyDefaultSize(); //4 segments, 1/5 of composer map width
        emit actionFinished();
        composition()->pushAddRemoveCommand( newScaleBar, tr( "Scale bar added" ) );
      }
      break;

    case AddLegend:
    {
      if ( composition() )
      {
        QgsComposerLegend* newLegend = new QgsComposerLegend( composition() );
        newLegend->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLegend->rect().width(), newLegend->rect().height() ) );
        composition()->addComposerLegend( newLegend );
        newLegend->updateLegend();
        emit actionFinished();
        composition()->pushAddRemoveCommand( newLegend, tr( "Legend added" ) );
      }
      break;
    }
    case AddPicture:
      if ( composition() )
      {
        QgsComposerPicture* newPicture = new QgsComposerPicture( composition() );
        newPicture->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 30, 30 ) );
        composition()->addComposerPicture( newPicture );
        emit actionFinished();
        composition()->pushAddRemoveCommand( newPicture, tr( "Picture added" ) );
      }
      break;
    case AddTable:
      if ( composition() )
      {
        QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( composition() );
        newTable->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 50, 50 ) );
        composition()->addComposerTable( newTable );
        emit actionFinished();
        composition()->pushAddRemoveCommand( newTable, tr( "Table added" ) );
      }
      break;
    default:
      break;
  }
}
void TestQgsWcsPublicServers::test( )
{
  QStringList versions;
  // It may happen that server supports 1.1.1, but does not accept 1.1 (http://zeus.pin.unifi.it/gi-wcs/http)
  versions << "" << "1.0.0" << "1.1.0"; // empty for default
  QStringList servers;
  // Some (first) coverages do not advertize any supportedCRS and sever gives
  // error both with native CRS (EPSG::561005) and EPSG:4326
  // MOD* coverages work OK
  servers << "http://argon.geogr.uni-jena.de:8080/geoserver/ows";
  servers << "http://demo.geonode.org/geoserver/wcs";
  servers << "http://demo.mapserver.org/cgi-bin/wcs";
  servers << "http://demo.opengeo.org/geoserver/wcs";
  // geobrain.laits.gmu.edu servers are quite slow
  servers << "http://geobrain.laits.gmu.edu/cgi-bin/gbwcs-dem";
  servers << "http://geobrain.laits.gmu.edu/cgi-bin/ows8/wcseo";
  servers << "http://geobrain.laits.gmu.edu/cgi-bin/wcs110";
  servers << "http://geobrain.laits.gmu.edu/cgi-bin/wcs-all";
  servers << "http://iceds.ge.ucl.ac.uk/cgi-bin/icedswcs";
  servers << "http://motherlode.ucar.edu:8080/thredds/wcs/fmrc/NCEP/DGEX/Alaska_12km/NCEP-DGEX-Alaska_12km_best.ncd";
  servers << "http://navigator.state.or.us/ArcGIS/services/Framework/Imagery_Mosaic2009/ImageServer/WCSServer";
  servers << "http://nsidc.org/cgi-bin/atlas_north";
  servers << "http://sedac.ciesin.columbia.edu/geoserver/wcs";
  // Big and slow
  //servers << "http://webmap.ornl.gov/ogcbroker/wcs";
  servers << "http://ws.csiss.gmu.edu/cgi-bin/wcs-t";
  // Big and slow
  //servers << "http://ws.laits.gmu.edu/cgi-bin/wcs-all";
  // Currently very slow or down
  //servers << "http://www.sogeo.ch/geoserver/wcs";
  // Slow and erroneous
  //servers << "http://zeus.pin.unifi.it/gi-wcs/http";

  foreach ( QString server, servers )
  {
    QStringList myServerLog;
    myServerLog << "server:" + server;
    QString myServerDirName = server;
    myServerDirName.replace( QRegExp( "[:/]+" ), "." );
    myServerDirName.replace( QRegExp( "\\.$" ), "" );
    QgsDebugMsg( "myServerDirName = " + myServerDirName );

    QDir myServerDir( mCacheDir.absolutePath() + QDir::separator() + myServerDirName );
    QString myServerLogPath = myServerDir.absolutePath() + QDir::separator() + "server.log";
    if ( QFileInfo( myServerLogPath ).exists() )
    {
      QgsDebugMsg( "cache exists " + myServerDir.absolutePath() );
      continue;
    }

    if ( !myServerDir.exists() )
    {
      mCacheDir.mkdir( myServerDirName );
    }

    foreach ( QString version, versions )
    {
      QgsDebugMsg( "server: " + server + " version: " + version );

      QgsDataSourceURI myServerUri;

      myServerUri.setParam( "url", server );
      if ( !version.isEmpty() )
      {
        myServerUri.setParam( "version", version );
      }

      QgsWcsCapabilities myCapabilities;
      myCapabilities.setUri( myServerUri );

      if ( !myCapabilities.lastError().isEmpty() )
      {
        QgsDebugMsg( myCapabilities.lastError() );
        myServerLog << "error: (version: " + version + ") " +  myCapabilities.lastError().replace( "\n", " " );
        continue;
      }

      QVector<QgsWcsCoverageSummary> myCoverages;
      if ( !myCapabilities.supportedCoverages( myCoverages ) )
      {
        QgsDebugMsg( "Cannot get list of coverages" );
        myServerLog << "error: (version: " + version + ") Cannot get list of coverages";
        continue;
      }

      int myCoverageCount = 0;
      int myStep = myCoverages.size() / mMaxCoverages;
      int myStepCount = -1;
      foreach ( QgsWcsCoverageSummary myCoverage, myCoverages )
      {
        QgsDebugMsg( "coverage: " + myCoverage.identifier );
        // Go in steps to get more success/errors
        if ( myStepCount == -1 || myStepCount > myStep )
        {
          myStepCount = 0;
        }
        else
        {
          myStepCount++;
          continue;
        }

        myCoverageCount++;
        if ( myCoverageCount > mMaxCoverages ) break;

        QString myPath = myServerDir.absolutePath() + QDir::separator() + myCoverage.identifier;

        if ( !version.isEmpty() )
        {
          myPath += "-" + version;
        }
        QString myLogPath = myPath + ".log";

        if ( QFileInfo( myLogPath ).exists() )
        {
          QMap<QString, QString> log = readLog( myLogPath );
          if ( !log.value( "identifier" ).isEmpty() && log.value( "error" ).isEmpty() ) continue;
        }

        QStringList myLog;
        myLog << "identifier:" + myCoverage.identifier;
        myCapabilities.describeCoverage( myCoverage.identifier );
        myCoverage = myCapabilities.coverage( myCoverage.identifier ); // get described
        QgsDataSourceURI myUri = myServerUri;
        myUri.setParam( "identifier", myCoverage.identifier );
        if ( myCoverage.times.size() > 0 )
        {
          myUri.setParam( "time", myCoverage.times.value( 0 ) );
        }
        myLog << "version:" + version;
        myLog << "uri:" + myUri.encodedUri();

        int myWidth = 100;
        int myHeight = 100;
        if ( myCoverage.hasSize )
        {
          myHeight = static_cast<int>( qRound( 1.0 * myWidth * myCoverage.height / myCoverage.width ) );
        }
        myLog << QString( "hasSize:%1" ).arg( myCoverage.hasSize );

        QgsRasterLayer * myLayer = new QgsRasterLayer( myUri.encodedUri(), myCoverage.identifier, "wcs", true );
        if ( myLayer->isValid() )
        {
          int myBandCount = myLayer->dataProvider()->bandCount();
          myLog << "bandCount:" + QString::number( myBandCount );
          if ( myBandCount > 0 )
          {
            myLog << "srcType:" + QString::number( myLayer->dataProvider()->srcDataType( 1 ) );

            QgsRasterBandStats myStats = myLayer->dataProvider()->bandStatistics( 1, QgsRasterBandStats::All, QgsRectangle(), myWidth * myHeight );
            myLog << "min:" + QString::number( myStats.minimumValue );
            myLog << "max:" + QString::number( myStats.maximumValue );
          }

          QgsMapRenderer myMapRenderer;
          QList<QgsMapLayer *> myLayersList;

          myLayersList.append( myLayer );
          QgsMapLayerRegistry::instance()->addMapLayers( myLayersList, false );

          QMap<QString, QgsMapLayer*> myLayersMap = QgsMapLayerRegistry::instance()->mapLayers();

          myMapRenderer.setLayerSet( myLayersMap.keys() );

          myMapRenderer.setExtent( myLayer->extent() );

          QImage myImage( myWidth, myHeight, QImage::Format_ARGB32_Premultiplied );
          myImage.fill( 0 );

          myMapRenderer.setOutputSize( QSize( myWidth, myHeight ), myImage.logicalDpiX() );

          QPainter myPainter( &myImage );
          myMapRenderer.render( &myPainter );

          // Save rendered image
          QString myPngPath = myPath + ".png";
          QgsDebugMsg( "myPngPath = " + myPngPath );
          myImage.save( myPngPath );

          // Verify data
          QSet<QString> myValues; // cannot be QSet<double>
          void *myData = myLayer->dataProvider()->readBlock( 1, myLayer->extent(), myWidth, myHeight );
          if ( myData )
          {
            int myType = myLayer->dataProvider()->dataType( 1 );
            for ( int row = 0; row < myHeight; row++ )
            {
              for ( int col = 0; col < myWidth; col++ )
              {
                double value = myLayer->dataProvider()->readValue( myData, myType, row * myWidth + col );
                QString valueStr = QString::number( value );
                if ( !myValues.contains( valueStr ) ) myValues.insert( valueStr );
              }
            }
            free( myData );
          }
          QgsDebugMsg( QString( "%1 values" ).arg( myValues.size() ) );
          myLog << QString( "valuesCount:%1" ).arg( myValues.size() );

          // Verify image colors
          QSet<QRgb> myColors;
          for ( int row = 0; row < myHeight; row++ )
          {
            for ( int col = 0; col < myWidth; col++ )
            {
              QRgb color = myImage.pixel( col, row );
              if ( !myColors.contains( color ) ) myColors.insert( color );
            }
          }
          QgsDebugMsg( QString( "%1 colors" ).arg( myColors.size() ) );
          myLog << QString( "colorsCount:%1" ).arg( myColors.size() );
        }
        else
        {
          QgsDebugMsg( "Layer is not valid" );
          myLog << "error:Layer is not valid";
        }

        QFile myLogFile( myLogPath );
        myLogFile.open( QIODevice::WriteOnly | QIODevice::Text );
        QTextStream myStream( &myLogFile );
        myStream << myLog.join( "\n" );

        myLogFile.close();
        QgsMapLayerRegistry::instance()->removeAllMapLayers();
      }
void QgsComposerView::wheelZoom( QWheelEvent * event )
{
  //get mouse wheel zoom behaviour settings
  QSettings mySettings;
  int wheelAction = mySettings.value( "/qgis/wheel_action", 2 ).toInt();
  double zoomFactor = mySettings.value( "/qgis/zoom_factor", 2 ).toDouble();

  if (( QgsMapCanvas::WheelAction )wheelAction == QgsMapCanvas::WheelNothing )
  {
    return;
  }

  if ( event->modifiers() & Qt::ControlModifier )
  {
    //holding ctrl while wheel zooming results in a finer zoom
    zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 10.0;
  }

  //caculate zoom scale factor
  bool zoomIn = event->delta() > 0;
  double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );

  //get current visible part of scene
  QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
  QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() );

  //transform the mouse pos to scene coordinates
  QPointF scenePoint = mapToScene( event->pos() );

  //adjust view center according to wheel action setting
  switch (( QgsMapCanvas::WheelAction )wheelAction )
  {
    case QgsMapCanvas::WheelZoomAndRecenter:
    {
      centerOn( scenePoint.x(), scenePoint.y() );
      break;
    }

    case QgsMapCanvas::WheelZoomToMouseCursor:
    {
      QgsPoint oldCenter( visibleRect.center() );
      QgsPoint newCenter( scenePoint.x() + (( oldCenter.x() - scenePoint.x() ) * scaleFactor ),
                          scenePoint.y() + (( oldCenter.y() - scenePoint.y() ) * scaleFactor ) );
      centerOn( newCenter.x(), newCenter.y() );
      break;
    }

    default:
      break;
  }

  //zoom composition
  if ( zoomIn )
  {
    scale( zoomFactor, zoomFactor );
  }
  else
  {
    scale( 1 / zoomFactor, 1 / zoomFactor );
  }

  //update composition for new zoom
  emit zoomLevelChanged();
  updateRulers();
  update();
  //redraw cached map items
  QList<QGraphicsItem *> itemList = composition()->items();
  QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
  for ( ; itemIt != itemList.end(); ++itemIt )
  {
    QgsComposerMap* mypItem = dynamic_cast<QgsComposerMap *>( *itemIt );
    if (( mypItem ) && ( mypItem->previewMode() == QgsComposerMap::Render ) )
    {
      mypItem->updateCachedImage();
    }
  }
}
QgsRectangle QgsOSMDownloadDialog::rect() const
{
  return QgsRectangle( editXMin->text().toDouble(), editYMin->text().toDouble(),
                       editXMax->text().toDouble(), editYMax->text().toDouble() );
}
void QgsComposerView::mouseReleaseEvent( QMouseEvent* e )
{
  if ( !composition() )
  {
    return;
  }

  QPoint mousePressStopPoint = e->pos();
  int diffX = mousePressStopPoint.x() - mMousePressStartPos.x();
  int diffY = mousePressStopPoint.y() - mMousePressStartPos.y();

  //was this just a click? or a click and drag?
  bool clickOnly = false;
  if ( qAbs( diffX ) < 2 && qAbs( diffY ) < 2 )
  {
    clickOnly = true;
  }

  QPointF scenePoint = mapToScene( e->pos() );

  if ( mPanning )
  {
    mPanning = false;

    if ( clickOnly && e->button() == Qt::MidButton )
    {
      //middle mouse button click = recenter on point

      //get current visible part of scene
      QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
      QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() );
      visibleRect.scale( 1, scenePoint.x(), scenePoint.y() );
      QRectF boundsRect = visibleRect.toRectF();

      //zoom view to fit desired bounds
      fitInView( boundsRect, Qt::KeepAspectRatio );
    }

    //set new cursor
    if ( mCurrentTool == Pan )
    {
      viewport()->setCursor( Qt::OpenHandCursor );
    }
    else
    {
      if ( composition() )
      {
        //allow composer items to change cursor
        composition()->setPreventCursorChange( false );
      }
      viewport()->setCursor( Qt::ArrowCursor );
    }
  }

  if ( mMarqueeSelect )
  {
    endMarqueeSelect( e );
    return;
  }

  switch ( mCurrentTool )
  {
    case Select:
    {
      QGraphicsView::mouseReleaseEvent( e );
      break;
    }

    case Zoom:
    {
      if ( mMarqueeZoom )
      {
        endMarqueeZoom( e );
      }
      break;
    }

    case MoveItemContent:
    {
      if ( mMoveContentItem )
      {
        //update map preview if composer map
        QgsComposerMap* composerMap = dynamic_cast<QgsComposerMap *>( mMoveContentItem );
        if ( composerMap )
        {
          composerMap->setOffset( 0, 0 );
        }

        double moveX = scenePoint.x() - mMoveContentStartPos.x();
        double moveY = scenePoint.y() - mMoveContentStartPos.y();

        composition()->beginCommand( mMoveContentItem, tr( "Move item content" ) );
        mMoveContentItem->moveContent( -moveX, -moveY );
        composition()->endCommand();
        mMoveContentItem = 0;
      }
      break;
    }
    case AddArrow:
      if ( composition() )
      {
        QPointF scenePoint = mapToScene( e->pos() );
        QPointF snappedScenePoint = composition()->snapPointToGrid( scenePoint );
        QgsComposerArrow* composerArrow = new QgsComposerArrow( mRubberBandStartPos, QPointF( snappedScenePoint.x(), snappedScenePoint.y() ), composition() );
        composition()->addComposerArrow( composerArrow );
        scene()->removeItem( mRubberBandLineItem );
        delete mRubberBandLineItem;
        mRubberBandLineItem = 0;
        emit actionFinished();
        composition()->pushAddRemoveCommand( composerArrow, tr( "Arrow added" ) );
      }
      break;

    case AddRectangle:
    case AddTriangle:
    case AddEllipse:
      addShape( mCurrentTool );
      break;

    case AddMap:
      if ( !mRubberBandItem || ( mRubberBandItem->rect().width() < 0.1 && mRubberBandItem->rect().height() < 0.1 ) )
      {
        removeRubberBand();
        return;
      }
      if ( composition() )
      {
        QgsComposerMap* composerMap = new QgsComposerMap( composition(), mRubberBandItem->transform().dx(), mRubberBandItem->transform().dy(), mRubberBandItem->rect().width(), mRubberBandItem->rect().height() );
        composition()->addComposerMap( composerMap );
        removeRubberBand();
        emit actionFinished();
        composition()->pushAddRemoveCommand( composerMap, tr( "Map added" ) );
      }
      break;

    case AddHtml:
      if ( composition() )
      {
        QgsComposerHtml* composerHtml = new QgsComposerHtml( composition(), true );
        QgsAddRemoveMultiFrameCommand* command = new QgsAddRemoveMultiFrameCommand( QgsAddRemoveMultiFrameCommand::Added,
            composerHtml, composition(), tr( "Html item added" ) );
        composition()->undoStack()->push( command );
        QgsComposerFrame* frame = new QgsComposerFrame( composition(), composerHtml, mRubberBandItem->transform().dx(),
            mRubberBandItem->transform().dy(), mRubberBandItem->rect().width(),
            mRubberBandItem->rect().height() );
        composition()->beginMultiFrameCommand( composerHtml, tr( "Html frame added" ) );
        composerHtml->addFrame( frame );
        composition()->endMultiFrameCommand();
        removeRubberBand();
        emit actionFinished();
      }
    default:
      break;
  }
}
QgsRectangle QgsCoordinateTransform::transformBoundingBox( const QgsRectangle rect, TransformDirection direction ) const
{
  // Calculate the bounding box of a QgsRectangle in the source CRS
  // when projected to the destination CRS (or the inverse).
  // This is done by looking at a number of points spread evenly
  // across the rectangle

  if ( mShortCircuit || !mInitialisedFlag )
    return rect;

  if ( rect.isEmpty() )
  {
    QgsPoint p = transform( rect.xMinimum(), rect.yMinimum(), direction );
    return QgsRectangle( p, p );
  }

  static const int numP = 8;

  QgsRectangle bb_rect;
  bb_rect.setMinimal();

  // We're interfacing with C-style vectors in the
  // end, so let's do C-style vectors here too.

  double x[numP * numP];
  double y[numP * numP];
  double z[numP * numP];

  QgsDebugMsg( "Entering transformBoundingBox..." );

  // Populate the vectors

  double dx = rect.width()  / ( double )( numP - 1 );
  double dy = rect.height() / ( double )( numP - 1 );

  double pointY = rect.yMinimum();

  for ( int i = 0; i < numP ; i++ )
  {

    // Start at right edge
    double pointX = rect.xMinimum();

    for ( int j = 0; j < numP; j++ )
    {
      x[( i*numP ) + j] = pointX;
      y[( i*numP ) + j] = pointY;
      // and the height...
      z[( i*numP ) + j] = 0.0;
      // QgsDebugMsg(QString("BBox coord: (%1, %2)").arg(x[(i*numP) + j]).arg(y[(i*numP) + j]));
      pointX += dx;
    }
    pointY += dy;
  }

  // Do transformation. Any exception generated must
  // be handled in above layers.
  try
  {
    transformCoords( numP * numP, x, y, z, direction );
  }
  catch ( QgsCsException &cse )
  {
    // rethrow the exception
    QgsDebugMsg( "rethrowing exception" );
    throw cse;
  }

  // Calculate the bounding box and use that for the extent

  for ( int i = 0; i < numP * numP; i++ )
  {
    if ( qIsFinite( x[i] ) && qIsFinite( y[i] ) )
      bb_rect.combineExtentWith( x[i], y[i] );
  }

  QgsDebugMsg( "Projected extent: " + bb_rect.toString() );

  if ( bb_rect.isEmpty() )
  {
    QgsDebugMsg( "Original extent: " + rect.toString() );
  }

  return bb_rect;
}
Exemple #26
0
void QgsCurve::clearCache() const
{
  mBoundingBox = QgsRectangle();
  QgsAbstractGeometry::clearCache();
}
Exemple #27
0
bool QgsVectorLayerRenderer::render()
{
  if ( mGeometryType == QgsWkbTypes::NullGeometry || mGeometryType == QgsWkbTypes::UnknownGeometry )
    return true;

  if ( !mRenderer )
  {
    mErrors.append( QObject::tr( "No renderer for drawing." ) );
    return false;
  }

  bool usingEffect = false;
  if ( mRenderer->paintEffect() && mRenderer->paintEffect()->enabled() )
  {
    usingEffect = true;
    mRenderer->paintEffect()->begin( mContext );
  }

  // Per feature blending mode
  if ( mContext.useAdvancedEffects() && mFeatureBlendMode != QPainter::CompositionMode_SourceOver )
  {
    // set the painter to the feature blend mode, so that features drawn
    // on this layer will interact and blend with each other
    mContext.painter()->setCompositionMode( mFeatureBlendMode );
  }

  mRenderer->startRender( mContext, mFields );

  QString rendererFilter = mRenderer->filter( mFields );

  QgsRectangle requestExtent = mContext.extent();
  mRenderer->modifyRequestExtent( requestExtent, mContext );

  QgsFeatureRequest featureRequest = QgsFeatureRequest()
                                     .setFilterRect( requestExtent )
                                     .setSubsetOfAttributes( mAttrNames, mFields )
                                     .setExpressionContext( mContext.expressionContext() );
  if ( mRenderer->orderByEnabled() )
  {
    featureRequest.setOrderBy( mRenderer->orderBy() );
  }

  const QgsFeatureFilterProvider *featureFilterProvider = mContext.featureFilterProvider();
  if ( featureFilterProvider )
  {
    featureFilterProvider->filterFeatures( mLayer, featureRequest );
  }
  if ( !rendererFilter.isEmpty() && rendererFilter != QLatin1String( "TRUE" ) )
  {
    featureRequest.combineFilterExpression( rendererFilter );
  }

  // enable the simplification of the geometries (Using the current map2pixel context) before send it to renderer engine.
  if ( mSimplifyGeometry )
  {
    double map2pixelTol = mSimplifyMethod.threshold();
    bool validTransform = true;

    const QgsMapToPixel &mtp = mContext.mapToPixel();
    map2pixelTol *= mtp.mapUnitsPerPixel();
    QgsCoordinateTransform ct = mContext.coordinateTransform();

    // resize the tolerance using the change of size of an 1-BBOX from the source CoordinateSystem to the target CoordinateSystem
    if ( ct.isValid() && !ct.isShortCircuited() )
    {
      try
      {
        QgsPointXY center = mContext.extent().center();
        double rectSize = ct.sourceCrs().isGeographic() ? 0.0008983 /* ~100/(40075014/360=111319.4833) */ : 100;

        QgsRectangle sourceRect = QgsRectangle( center.x(), center.y(), center.x() + rectSize, center.y() + rectSize );
        QgsRectangle targetRect = ct.transform( sourceRect );

        QgsDebugMsgLevel( QString( "Simplify - SourceTransformRect=%1" ).arg( sourceRect.toString( 16 ) ), 4 );
        QgsDebugMsgLevel( QString( "Simplify - TargetTransformRect=%1" ).arg( targetRect.toString( 16 ) ), 4 );

        if ( !sourceRect.isEmpty() && sourceRect.isFinite() && !targetRect.isEmpty() && targetRect.isFinite() )
        {
          QgsPointXY minimumSrcPoint( sourceRect.xMinimum(), sourceRect.yMinimum() );
          QgsPointXY maximumSrcPoint( sourceRect.xMaximum(), sourceRect.yMaximum() );
          QgsPointXY minimumDstPoint( targetRect.xMinimum(), targetRect.yMinimum() );
          QgsPointXY maximumDstPoint( targetRect.xMaximum(), targetRect.yMaximum() );

          double sourceHypothenuse = std::sqrt( minimumSrcPoint.sqrDist( maximumSrcPoint ) );
          double targetHypothenuse = std::sqrt( minimumDstPoint.sqrDist( maximumDstPoint ) );

          QgsDebugMsgLevel( QString( "Simplify - SourceHypothenuse=%1" ).arg( sourceHypothenuse ), 4 );
          QgsDebugMsgLevel( QString( "Simplify - TargetHypothenuse=%1" ).arg( targetHypothenuse ), 4 );

          if ( !qgsDoubleNear( targetHypothenuse, 0.0 ) )
            map2pixelTol *= ( sourceHypothenuse / targetHypothenuse );
        }
      }
      catch ( QgsCsException &cse )
      {
        QgsMessageLog::logMessage( QObject::tr( "Simplify transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
        validTransform = false;
      }
    }

    if ( validTransform )
    {
      QgsSimplifyMethod simplifyMethod;
      simplifyMethod.setMethodType( QgsSimplifyMethod::OptimizeForRendering );
      simplifyMethod.setTolerance( map2pixelTol );
      simplifyMethod.setThreshold( mSimplifyMethod.threshold() );
      simplifyMethod.setForceLocalOptimization( mSimplifyMethod.forceLocalOptimization() );
      featureRequest.setSimplifyMethod( simplifyMethod );

      QgsVectorSimplifyMethod vectorMethod = mSimplifyMethod;
      vectorMethod.setTolerance( map2pixelTol );
      mContext.setVectorSimplifyMethod( vectorMethod );
    }
    else
    {
      QgsVectorSimplifyMethod vectorMethod;
      vectorMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
      mContext.setVectorSimplifyMethod( vectorMethod );
    }
  }
  else
  {
    QgsVectorSimplifyMethod vectorMethod;
    vectorMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
    mContext.setVectorSimplifyMethod( vectorMethod );
  }

  QgsFeatureIterator fit = mSource->getFeatures( featureRequest );
  // Attach an interruption checker so that iterators that have potentially
  // slow fetchFeature() implementations, such as in the WFS provider, can
  // check it, instead of relying on just the mContext.renderingStopped() check
  // in drawRenderer()
  fit.setInterruptionChecker( &mInterruptionChecker );

  if ( ( mRenderer->capabilities() & QgsFeatureRenderer::SymbolLevels ) && mRenderer->usingSymbolLevels() )
    drawRendererLevels( fit );
  else
    drawRenderer( fit );

  if ( usingEffect )
  {
    mRenderer->paintEffect()->end( mContext );
  }

  return true;
}
Exemple #28
0
bool QgsGeometryAnalyzer::simplify( QgsVectorLayer* layer,
                                    const QString& shapefileName,
                                    double tolerance,
                                    bool onlySelectedFeatures,
                                    QProgressDialog *p )
{
  if ( !layer )
  {
    return false;
  }

  QgsVectorDataProvider* dp = layer->dataProvider();
  if ( !dp )
  {
    return false;
  }

  QGis::WkbType outputType = dp->geometryType();
  const QgsCoordinateReferenceSystem crs = layer->crs();

  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
  QgsFeature currentFeature;

  //take only selection
  if ( onlySelectedFeatures )
  {
    //use QgsVectorLayer::featureAtId
    const QgsFeatureIds selection = layer->selectedFeaturesIds();
    if ( p )
    {
      p->setMaximum( selection.size() );
    }

    int processedFeatures = 0;
    QgsFeatureIds::const_iterator it = selection.constBegin();
    for ( ; it != selection.constEnd(); ++it )
    {
      if ( p )
      {
        p->setValue( processedFeatures );
      }

      if ( p && p->wasCanceled() )
      {
        break;
      }
      if ( !layer->featureAtId( *it, currentFeature, true, true ) )
      {
        continue;
      }
      simplifyFeature( currentFeature, &vWriter, tolerance );
      ++processedFeatures;
    }

    if ( p )
    {
      p->setValue( selection.size() );
    }
  }
  //take all features
  else
  {
    layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );


    int featureCount = layer->featureCount();
    if ( p )
    {
      p->setMaximum( featureCount );
    }
    int processedFeatures = 0;

    while ( layer->nextFeature( currentFeature ) )
    {
      if ( p )
      {
        p->setValue( processedFeatures );
      }
      if ( p && p->wasCanceled() )
      {
        break;
      }
      simplifyFeature( currentFeature, &vWriter, tolerance );
      ++processedFeatures;
    }
    if ( p )
    {
      p->setValue( featureCount );
    }
  }

  return true;
}
QString QgsPostgresFeatureIterator::whereClauseRect()
{
    QgsRectangle rect = mRequest.filterRect();
    if ( mSource->mSpatialColType == sctGeography )
    {
        rect = QgsRectangle( -180.0, -90.0, 180.0, 90.0 ).intersect( &rect );
    }

    if ( !rect.isFinite() )
    {
        QgsMessageLog::logMessage( QObject::tr( "Infinite filter rectangle specified" ), QObject::tr( "PostGIS" ) );
        return "false";
    }

    QString qBox;
    if ( mConn->majorVersion() < 2 )
    {
        qBox = QString( "setsrid('BOX3D(%1)'::box3d,%2)" )
               .arg( rect.asWktCoordinates(),
                     mSource->mRequestedSrid.isEmpty() ? mSource->mDetectedSrid : mSource->mRequestedSrid );
    }
    else
    {
        qBox = QString( "st_makeenvelope(%1,%2,%3,%4,%5)" )
               .arg( qgsDoubleToString( rect.xMinimum() ),
                     qgsDoubleToString( rect.yMinimum() ),
                     qgsDoubleToString( rect.xMaximum() ),
                     qgsDoubleToString( rect.yMaximum() ),
                     mSource->mRequestedSrid.isEmpty() ? mSource->mDetectedSrid : mSource->mRequestedSrid );
    }

    bool castToGeometry = mSource->mSpatialColType == sctGeography ||
                          mSource->mSpatialColType == sctPcPatch;

    QString whereClause = QString( "%1%2 && %3" )
                          .arg( QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ),
                                castToGeometry ? "::geometry" : "",
                                qBox );

    if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
    {
        QString curveToLineFn; // in postgis < 1.5 the st_curvetoline function does not exist
        if ( mConn->majorVersion() >= 2 || ( mConn->majorVersion() == 1 && mConn->minorVersion() >= 5 ) )
            curveToLineFn = "st_curvetoline"; // st_ prefix is always used
        whereClause += QString( " AND %1(%2(%3%4),%5)" )
                       .arg( mConn->majorVersion() < 2 ? "intersects" : "st_intersects",
                             curveToLineFn,
                             QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ),
                             castToGeometry ? "::geometry" : "",
                             qBox );
    }

    if ( !mSource->mRequestedSrid.isEmpty() && ( mSource->mRequestedSrid != mSource->mDetectedSrid || mSource->mRequestedSrid.toInt() == 0 ) )
    {
        whereClause += QString( " AND %1(%2%3)=%4" )
                       .arg( mConn->majorVersion() < 2 ? "srid" : "st_srid",
                             QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ),
                             castToGeometry ? "::geometry" : "",
                             mSource->mRequestedSrid );
    }

    if ( mSource->mRequestedGeomType != QGis::WKBUnknown && mSource->mRequestedGeomType != mSource->mDetectedGeomType )
    {
        whereClause += QString( " AND %1" ).arg( QgsPostgresConn::postgisTypeFilter( mSource->mGeometryColumn, ( QgsWKBTypes::Type )mSource->mRequestedGeomType, castToGeometry ) );
    }

    return whereClause;
}
QgsRectangle QgsPointDisplacementRenderer::searchRect( const QgsPoint& p ) const
{
  return QgsRectangle( p.x() - mTolerance, p.y() - mTolerance, p.x() + mTolerance, p.y() + mTolerance );
}