Example #1
0
void QgsAtlasComposition::prepareMap( QgsComposerMap* map )
{
  if ( !map->atlasDriven() || mCoverageLayer->wkbType() == QgsWkbTypes::NoGeometry )
  {
    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 QgsWkbTypes::Point:
    case QgsWkbTypes::Point25D:
    case QgsWkbTypes::MultiPoint:
    case QgsWkbTypes::MultiPoint25D:
      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 );
}
Example #2
0
int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
{
  if ( !mPolygonLayer || mPolygonLayer->geometryType() != QgsWkbTypes::PolygonGeometry )
  {
    return 1;
  }

  QgsVectorDataProvider *vectorProvider = mPolygonLayer->dataProvider();
  if ( !vectorProvider )
  {
    return 2;
  }

  if ( !mRasterLayer )
  {
    return 3;
  }

  if ( mRasterLayer->bandCount() < mRasterBand )
  {
    return 4;
  }

  mRasterProvider = mRasterLayer->dataProvider();
  mInputNodataValue = mRasterProvider->sourceNoDataValue( mRasterBand );

  //get geometry info about raster layer
  int nCellsXProvider = mRasterProvider->xSize();
  int nCellsYProvider = mRasterProvider->ySize();
  double cellsizeX = mRasterLayer->rasterUnitsPerPixelX();
  if ( cellsizeX < 0 )
  {
    cellsizeX = -cellsizeX;
  }
  double cellsizeY = mRasterLayer->rasterUnitsPerPixelY();
  if ( cellsizeY < 0 )
  {
    cellsizeY = -cellsizeY;
  }
  QgsRectangle rasterBBox = mRasterProvider->extent();

  //add the new fields to the provider
  QList<QgsField> newFieldList;
  QString countFieldName;
  if ( mStatistics & QgsZonalStatistics::Count )
  {
    countFieldName = getUniqueFieldName( mAttributePrefix + "count", newFieldList );
    QgsField countField( countFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( countField );
  }
  QString sumFieldName;
  if ( mStatistics & QgsZonalStatistics::Sum )
  {
    sumFieldName = getUniqueFieldName( mAttributePrefix + "sum", newFieldList );
    QgsField sumField( sumFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( sumField );
  }
  QString meanFieldName;
  if ( mStatistics & QgsZonalStatistics::Mean )
  {
    meanFieldName = getUniqueFieldName( mAttributePrefix + "mean", newFieldList );
    QgsField meanField( meanFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( meanField );
  }
  QString medianFieldName;
  if ( mStatistics & QgsZonalStatistics::Median )
  {
    medianFieldName = getUniqueFieldName( mAttributePrefix + "median", newFieldList );
    QgsField medianField( medianFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( medianField );
  }
  QString stdevFieldName;
  if ( mStatistics & QgsZonalStatistics::StDev )
  {
    stdevFieldName = getUniqueFieldName( mAttributePrefix + "stdev", newFieldList );
    QgsField stdField( stdevFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( stdField );
  }
  QString minFieldName;
  if ( mStatistics & QgsZonalStatistics::Min )
  {
    minFieldName = getUniqueFieldName( mAttributePrefix + "min", newFieldList );
    QgsField minField( minFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( minField );
  }
  QString maxFieldName;
  if ( mStatistics & QgsZonalStatistics::Max )
  {
    maxFieldName = getUniqueFieldName( mAttributePrefix + "max", newFieldList );
    QgsField maxField( maxFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( maxField );
  }
  QString rangeFieldName;
  if ( mStatistics & QgsZonalStatistics::Range )
  {
    rangeFieldName = getUniqueFieldName( mAttributePrefix + "range", newFieldList );
    QgsField rangeField( rangeFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( rangeField );
  }
  QString minorityFieldName;
  if ( mStatistics & QgsZonalStatistics::Minority )
  {
    minorityFieldName = getUniqueFieldName( mAttributePrefix + "minority", newFieldList );
    QgsField minorityField( minorityFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( minorityField );
  }
  QString majorityFieldName;
  if ( mStatistics & QgsZonalStatistics::Majority )
  {
    majorityFieldName = getUniqueFieldName( mAttributePrefix + "majority", newFieldList );
    QgsField majField( majorityFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( majField );
  }
  QString varietyFieldName;
  if ( mStatistics & QgsZonalStatistics::Variety )
  {
    varietyFieldName = getUniqueFieldName( mAttributePrefix + "variety", newFieldList );
    QgsField varietyField( varietyFieldName, QVariant::Int, QStringLiteral( "int" ) );
    newFieldList.push_back( varietyField );
  }
  QString varianceFieldName;
  if ( mStatistics & QgsZonalStatistics::Variance )
  {
    varianceFieldName = getUniqueFieldName( mAttributePrefix + "variance", newFieldList );
    QgsField varianceField( varianceFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
    newFieldList.push_back( varianceField );
  }
  vectorProvider->addAttributes( newFieldList );

  //index of the new fields
  int countIndex = mStatistics & QgsZonalStatistics::Count ? vectorProvider->fieldNameIndex( countFieldName ) : -1;
  int sumIndex = mStatistics & QgsZonalStatistics::Sum ? vectorProvider->fieldNameIndex( sumFieldName ) : -1;
  int meanIndex = mStatistics & QgsZonalStatistics::Mean ? vectorProvider->fieldNameIndex( meanFieldName ) : -1;
  int medianIndex = mStatistics & QgsZonalStatistics::Median ? vectorProvider->fieldNameIndex( medianFieldName ) : -1;
  int stdevIndex = mStatistics & QgsZonalStatistics::StDev ? vectorProvider->fieldNameIndex( stdevFieldName ) : -1;
  int minIndex = mStatistics & QgsZonalStatistics::Min ? vectorProvider->fieldNameIndex( minFieldName ) : -1;
  int maxIndex = mStatistics & QgsZonalStatistics::Max ? vectorProvider->fieldNameIndex( maxFieldName ) : -1;
  int rangeIndex = mStatistics & QgsZonalStatistics::Range ? vectorProvider->fieldNameIndex( rangeFieldName ) : -1;
  int minorityIndex = mStatistics & QgsZonalStatistics::Minority ? vectorProvider->fieldNameIndex( minorityFieldName ) : -1;
  int majorityIndex = mStatistics & QgsZonalStatistics::Majority ? vectorProvider->fieldNameIndex( majorityFieldName ) : -1;
  int varietyIndex = mStatistics & QgsZonalStatistics::Variety ? vectorProvider->fieldNameIndex( varietyFieldName ) : -1;
  int varianceIndex = mStatistics & QgsZonalStatistics::Variance ? vectorProvider->fieldNameIndex( varianceFieldName ) : -1;

  if ( ( mStatistics & QgsZonalStatistics::Count && countIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::Sum && sumIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::Mean && meanIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::Median && medianIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::StDev && stdevIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::Min && minIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::Max && maxIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::Range && rangeIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::Minority && minorityIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::Majority && majorityIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::Variety && varietyIndex == -1 )
       || ( mStatistics & QgsZonalStatistics::Variance && varianceIndex == -1 )
     )
  {
    //failed to create a required field
    return 8;
  }

  //progress dialog
  long featureCount = vectorProvider->featureCount();

  //iterate over each polygon
  QgsFeatureRequest request;
  request.setSubsetOfAttributes( QgsAttributeList() );
  QgsFeatureIterator fi = vectorProvider->getFeatures( request );
  QgsFeature f;

  bool statsStoreValues = ( mStatistics & QgsZonalStatistics::Median ) ||
                          ( mStatistics & QgsZonalStatistics::StDev ) ||
                          ( mStatistics & QgsZonalStatistics::Variance );
  bool statsStoreValueCount = ( mStatistics & QgsZonalStatistics::Minority ) ||
                              ( mStatistics & QgsZonalStatistics::Majority );

  FeatureStats featureStats( statsStoreValues, statsStoreValueCount );
  int featureCounter = 0;

  QgsChangedAttributesMap changeMap;
  while ( fi.nextFeature( f ) )
  {
    if ( feedback && feedback->isCanceled() )
    {
      break;
    }

    if ( feedback )
    {
      feedback->setProgress( 100.0 * static_cast< double >( featureCounter ) / featureCount );
    }

    if ( !f.hasGeometry() )
    {
      ++featureCounter;
      continue;
    }
    QgsGeometry featureGeometry = f.geometry();

    QgsRectangle featureRect = featureGeometry.boundingBox().intersect( &rasterBBox );
    if ( featureRect.isEmpty() )
    {
      ++featureCounter;
      continue;
    }

    int offsetX, offsetY, nCellsX, nCellsY;
    if ( cellInfoForBBox( rasterBBox, featureRect, cellsizeX, cellsizeY, offsetX, offsetY, nCellsX, nCellsY ) != 0 )
    {
      ++featureCounter;
      continue;
    }

    //avoid access to cells outside of the raster (may occur because of rounding)
    if ( ( offsetX + nCellsX ) > nCellsXProvider )
    {
      nCellsX = nCellsXProvider - offsetX;
    }
    if ( ( offsetY + nCellsY ) > nCellsYProvider )
    {
      nCellsY = nCellsYProvider - offsetY;
    }

    statisticsFromMiddlePointTest( featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY,
                                   rasterBBox, featureStats );

    if ( featureStats.count <= 1 )
    {
      //the cell resolution is probably larger than the polygon area. We switch to precise pixel - polygon intersection in this case
      statisticsFromPreciseIntersection( featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY,
                                         rasterBBox, featureStats );
    }

    //write the statistics value to the vector data provider
    QgsAttributeMap changeAttributeMap;
    if ( mStatistics & QgsZonalStatistics::Count )
      changeAttributeMap.insert( countIndex, QVariant( featureStats.count ) );
    if ( mStatistics & QgsZonalStatistics::Sum )
      changeAttributeMap.insert( sumIndex, QVariant( featureStats.sum ) );
    if ( featureStats.count > 0 )
    {
      double mean = featureStats.sum / featureStats.count;
      if ( mStatistics & QgsZonalStatistics::Mean )
        changeAttributeMap.insert( meanIndex, QVariant( mean ) );
      if ( mStatistics & QgsZonalStatistics::Median )
      {
        std::sort( featureStats.values.begin(), featureStats.values.end() );
        int size =  featureStats.values.count();
        bool even = ( size % 2 ) < 1;
        double medianValue;
        if ( even )
        {
          medianValue = ( featureStats.values.at( size / 2 - 1 ) + featureStats.values.at( size / 2 ) ) / 2;
        }
        else //odd
        {
          medianValue = featureStats.values.at( ( size + 1 ) / 2 - 1 );
        }
        changeAttributeMap.insert( medianIndex, QVariant( medianValue ) );
      }
      if ( mStatistics & QgsZonalStatistics::StDev || mStatistics & QgsZonalStatistics::Variance )
      {
        double sumSquared = 0;
        for ( int i = 0; i < featureStats.values.count(); ++i )
        {
          double diff = featureStats.values.at( i ) - mean;
          sumSquared += diff * diff;
        }
        double variance = sumSquared / featureStats.values.count();
        if ( mStatistics & QgsZonalStatistics::StDev )
        {
          double stdev = std::pow( variance, 0.5 );
          changeAttributeMap.insert( stdevIndex, QVariant( stdev ) );
        }
        if ( mStatistics & QgsZonalStatistics::Variance )
          changeAttributeMap.insert( varianceIndex, QVariant( variance ) );
      }
      if ( mStatistics & QgsZonalStatistics::Min )
        changeAttributeMap.insert( minIndex, QVariant( featureStats.min ) );
      if ( mStatistics & QgsZonalStatistics::Max )
        changeAttributeMap.insert( maxIndex, QVariant( featureStats.max ) );
      if ( mStatistics & QgsZonalStatistics::Range )
        changeAttributeMap.insert( rangeIndex, QVariant( featureStats.max - featureStats.min ) );
      if ( mStatistics & QgsZonalStatistics::Minority || mStatistics & QgsZonalStatistics::Majority )
      {
        QList<int> vals = featureStats.valueCount.values();
        std::sort( vals.begin(), vals.end() );
        if ( mStatistics & QgsZonalStatistics::Minority )
        {
          float minorityKey = featureStats.valueCount.key( vals.first() );
          changeAttributeMap.insert( minorityIndex, QVariant( minorityKey ) );
        }
        if ( mStatistics & QgsZonalStatistics::Majority )
        {
          float majKey = featureStats.valueCount.key( vals.last() );
          changeAttributeMap.insert( majorityIndex, QVariant( majKey ) );
        }
      }
      if ( mStatistics & QgsZonalStatistics::Variety )
        changeAttributeMap.insert( varietyIndex, QVariant( featureStats.valueCount.count() ) );
    }

    changeMap.insert( f.id(), changeAttributeMap );
    ++featureCounter;
  }

  vectorProvider->changeAttributeValues( changeMap );

  if ( feedback )
  {
    feedback->setProgress( 100 );
  }

  mPolygonLayer->updateFields();

  if ( feedback && feedback->isCanceled() )
  {
    return 9;
  }

  return 0;
}
void QgsGrassFeatureIterator::setSelectionRect( const QgsRectangle& rect, bool useIntersect )
{
  QgsDebugMsg( QString( "useIntersect = %1 rect = %2" ).arg( useIntersect ).arg( rect.toString() ) );

  // TODO: selection of edited lines

  // Lock because functions using static/global variables are used
  // (e.g. static LocList in Vect_select_lines_by_box, global BranchBuf in RTreeGetBranches)
  QgsGrass::lock();

  mSelection.fill( false );

  BOUND_BOX box;
  box.N = rect.yMaximum();
  box.S = rect.yMinimum();
  box.E = rect.xMaximum();
  box.W = rect.xMinimum();
  box.T = PORT_DOUBLE_MAX;
  box.B = -PORT_DOUBLE_MAX;

  // Init structures
  struct ilist * list = Vect_new_list();

  if ( !useIntersect )
  { // select by bounding boxes only
    if ( mSource->mLayerType == QgsGrassProvider::POINT || mSource->mLayerType == QgsGrassProvider::CENTROID ||
         mSource->mLayerType == QgsGrassProvider::LINE || mSource->mLayerType == QgsGrassProvider::FACE ||
         mSource->mLayerType == QgsGrassProvider::BOUNDARY ||
         mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE ||
         mSource->mEditing )
    {
      QgsDebugMsg( "Vect_select_lines_by_box" );
      int type = mSource->mGrassType;
      if ( mSource->mEditing )
      {
        type = GV_POINTS | GV_LINES;
      }
      QgsDebugMsg( QString( "type = %1" ).arg( type ) );
      Vect_select_lines_by_box( mSource->map(), &box, type, list );
    }
    else if ( mSource->mLayerType == QgsGrassProvider::POLYGON )
    {
      Vect_select_areas_by_box( mSource->map(), &box, list );
    }
    else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
    {
      Vect_select_nodes_by_box( mSource->map(), &box, list );
    }
  }
  else
  { // check intersection
    struct line_pnts *polygon = Vect_new_line_struct();

    // Using z coor -PORT_DOUBLE_MAX/PORT_DOUBLE_MAX we cover 3D, Vect_select_lines_by_polygon is
    // using dig_line_box to get the box, it is not perfect, Vect_select_lines_by_polygon
    // should clarify better how 2D/3D is treated
    Vect_append_point( polygon, rect.xMinimum(), rect.yMinimum(), -PORT_DOUBLE_MAX );
    Vect_append_point( polygon, rect.xMaximum(), rect.yMinimum(), PORT_DOUBLE_MAX );
    Vect_append_point( polygon, rect.xMaximum(), rect.yMaximum(), 0 );
    Vect_append_point( polygon, rect.xMinimum(), rect.yMaximum(), 0 );
    Vect_append_point( polygon, rect.xMinimum(), rect.yMinimum(), 0 );

    if ( mSource->mLayerType == QgsGrassProvider::POINT || mSource->mLayerType == QgsGrassProvider::CENTROID ||
         mSource->mLayerType == QgsGrassProvider::LINE || mSource->mLayerType == QgsGrassProvider::FACE ||
         mSource->mLayerType == QgsGrassProvider::BOUNDARY ||
         mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE ||
         mSource->mEditing )
    {
      QgsDebugMsg( "Vect_select_lines_by_polygon" );
      int type = mSource->mGrassType;
      if ( mSource->mEditing )
      {
        type = GV_POINTS | GV_LINES;
      }
      QgsDebugMsg( QString( "type = %1" ).arg( type ) );
      Vect_select_lines_by_polygon( mSource->map(), polygon, 0, NULL, type, list );
    }
    else if ( mSource->mLayerType == QgsGrassProvider::POLYGON )
    {
      Vect_select_areas_by_polygon( mSource->map(), polygon, 0, NULL, list );
    }
    else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE )
    {
      // There is no Vect_select_nodes_by_polygon but for nodes it is the same as by box
      Vect_select_nodes_by_box( mSource->map(), &box, list );
    }

    Vect_destroy_line_struct( polygon );
  }
  for ( int i = 0; i < list->n_values; i++ )
  {
    int lid = list->value[i];
    if ( lid < 1 || lid >= mSelection.size() ) // should not happen
    {
      QgsDebugMsg( QString( "lid %1 out of range <1,%2>" ).arg( lid ).arg( mSelection.size() ) );
      continue;
    }
    mSelection.setBit( lid );
  }
  Vect_destroy_list( list );

  QgsDebugMsg( QString( " %1 features selected" ).arg( list->n_values ) );
  QgsGrass::unlock();
}
Example #4
0
static SpatialIndex::Region rect2region( const QgsRectangle& rect )
{
  double pLow[2] = { rect.xMinimum(), rect.yMinimum() };
  double pHigh[2] = { rect.xMaximum(), rect.yMaximum() };
  return SpatialIndex::Region( pLow, pHigh, 2 );
}
bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, QgsRasterLayer *layer, QgsPoint point, const QgsRectangle& viewExtent, double mapUnitsPerPixel )
{
  QgsDebugMsg( "point = " + point.toString() );
  if ( !layer )
    return false;

  QgsRasterDataProvider *dprovider = layer->dataProvider();
  if ( !dprovider )
    return false;

  int capabilities = dprovider->capabilities();
  if ( !( capabilities & QgsRasterDataProvider::Identify ) )
    return false;

  QgsPoint pointInCanvasCrs = point;
  try
  {
    point = toLayerCoordinates( layer, point );
  }
  catch ( QgsCsException &cse )
  {
    Q_UNUSED( cse );
    QgsDebugMsg( QString( "coordinate not reprojectable: %1" ).arg( cse.what() ) );
    return false;
  }
  QgsDebugMsg( QString( "point = %1 %2" ).arg( point.x() ).arg( point.y() ) );

  if ( !layer->extent().contains( point ) )
    return false;

  QMap< QString, QString > attributes, derivedAttributes;

  QgsRaster::IdentifyFormat format = QgsRasterDataProvider::identifyFormatFromName( layer->customProperty( "identify/format" ).toString() );

  // check if the format is really supported otherwise use first supported format
  if ( !( QgsRasterDataProvider::identifyFormatToCapability( format ) & capabilities ) )
  {
    if ( capabilities & QgsRasterInterface::IdentifyFeature ) format = QgsRaster::IdentifyFormatFeature;
    else if ( capabilities & QgsRasterInterface::IdentifyValue ) format = QgsRaster::IdentifyFormatValue;
    else if ( capabilities & QgsRasterInterface::IdentifyHtml ) format = QgsRaster::IdentifyFormatHtml;
    else if ( capabilities & QgsRasterInterface::IdentifyText ) format = QgsRaster::IdentifyFormatText;
    else return false;
  }

  QgsRasterIdentifyResult identifyResult;
  // We can only use current map canvas context (extent, width, height) if layer is not reprojected,
  if ( mCanvas->hasCrsTransformEnabled() && dprovider->crs() != mCanvas->mapSettings().destinationCrs() )
  {
    // To get some reasonable response for point/line WMS vector layers we must
    // use a context with approximately a resolution in layer CRS units
    // corresponding to current map canvas resolution (for examplei UMN Mapserver
    // in msWMSFeatureInfo() -> msQueryByRect() is using requested pixel
    // + TOLERANCE (layer param) for feature selection)
    //
    QgsRectangle r;
    r.setXMinimum( pointInCanvasCrs.x() - mapUnitsPerPixel / 2. );
    r.setXMaximum( pointInCanvasCrs.x() + mapUnitsPerPixel / 2. );
    r.setYMinimum( pointInCanvasCrs.y() - mapUnitsPerPixel / 2. );
    r.setYMaximum( pointInCanvasCrs.y() + mapUnitsPerPixel / 2. );
    r = toLayerCoordinates( layer, r ); // will be a bit larger
    // Mapserver (6.0.3, for example) does not work with 1x1 pixel box
    // but that is fixed (the rect is enlarged) in the WMS provider
    identifyResult = dprovider->identify( point, format, r, 1, 1 );
  }
  else
  {
    // It would be nice to use the same extent and size which was used for drawing,
    // so that WCS can use cache from last draw, unfortunately QgsRasterLayer::draw()
    // is doing some tricks with extent and size to allign raster to output which
    // would be difficult to replicate here.
    // Note: cutting the extent may result in slightly different x and y resolutions
    // and thus shifted point calculated back in QGIS WMS (using average resolution)
    //viewExtent = dprovider->extent().intersect( &viewExtent );

    // Width and height are calculated from not projected extent and we hope that
    // are similar to source width and height used to reproject layer for drawing.
    // TODO: may be very dangerous, because it may result in different resolutions
    // in source CRS, and WMS server (QGIS server) calcs wrong coor using average resolution.
    int width = qRound( viewExtent.width() / mapUnitsPerPixel );
    int height = qRound( viewExtent.height() / mapUnitsPerPixel );

    QgsDebugMsg( QString( "viewExtent.width = %1 viewExtent.height = %2" ).arg( viewExtent.width() ).arg( viewExtent.height() ) );
    QgsDebugMsg( QString( "width = %1 height = %2" ).arg( width ).arg( height ) );
    QgsDebugMsg( QString( "xRes = %1 yRes = %2 mapUnitsPerPixel = %3" ).arg( viewExtent.width() / width ).arg( viewExtent.height() / height ).arg( mapUnitsPerPixel ) );

    identifyResult = dprovider->identify( point, format, viewExtent, width, height );
  }

  derivedAttributes.insert( tr( "(clicked coordinate)" ), point.toString() );

  if ( identifyResult.isValid() )
  {
    QMap<int, QVariant> values = identifyResult.results();
    QgsGeometry geometry;
    if ( format == QgsRaster::IdentifyFormatValue )
    {
      Q_FOREACH ( int bandNo, values.keys() )
      {
        QString valueString;
        if ( values.value( bandNo ).isNull() )
        {
          valueString = tr( "no data" );
        }
        else
        {
          double value = values.value( bandNo ).toDouble();
          valueString = QgsRasterBlock::printValue( value );
        }
        attributes.insert( dprovider->generateBandName( bandNo ), valueString );
      }
      QString label = layer->name();
      results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
    }
Example #6
0
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 );

        composition()->clearSelection();
        newLabelItem->setSelected( true );
        emit selectedItemChanged( 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

        composition()->clearSelection();
        newScaleBar->setSelected( true );
        emit selectedItemChanged( newScaleBar );

        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();

        composition()->clearSelection();
        newLegend->setSelected( true );
        emit selectedItemChanged( newLegend );

        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 );

        composition()->clearSelection();
        newPicture->setSelected( true );
        emit selectedItemChanged( 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 );

        composition()->clearSelection();
        newTable->setSelected( true );
        emit selectedItemChanged( newTable );

        emit actionFinished();
        composition()->pushAddRemoveCommand( newTable, tr( "Table added" ) );
      }
      break;
    default:
      break;
  }
}
Example #7
0
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 );

        composition()->clearSelection();
        composerArrow->setSelected( true );
        emit selectedItemChanged( 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 );

        composition()->clearSelection();
        composerMap->setSelected( true );
        emit selectedItemChanged( 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();

        composition()->clearSelection();
        frame->setSelected( true );
        emit selectedItemChanged( frame );

        removeRubberBand();
        emit actionFinished();
      }
    default:
      break;
  }
}
void QgsGeometryCheckerResultTab::highlightErrors( bool current )
{
  qDeleteAll( mCurrentRubberBands );
  mCurrentRubberBands.clear();

  QList<QTableWidgetItem*> items;
  QList<QgsPoint> errorPositions;
  QgsRectangle totextent;

  if ( current )
  {
    items.append( ui.tableWidgetErrors->currentItem() );
  }
  else
  {
    items.append( ui.tableWidgetErrors->selectedItems() );
  }
  foreach ( QTableWidgetItem* item, items )
  {
    QgsGeometryCheckError* error = ui.tableWidgetErrors->item( item->row(), 0 )->data( Qt::UserRole ).value<QgsGeometryCheckError*>();

    QgsAbstractGeometryV2* geometry = error->geometry();
    if ( ui.checkBoxHighlight->isChecked() && geometry )
    {
      QgsRubberBand* featureRubberBand = new QgsRubberBand( mIface->mapCanvas() );
      QgsGeometry geom( geometry );
      featureRubberBand->addGeometry( &geom, mFeaturePool->getLayer() );
      featureRubberBand->setWidth( 5 );
      featureRubberBand->setColor( Qt::yellow );
      mCurrentRubberBands.append( featureRubberBand );
    }
    else
    {
      // QgsGeometry above takes ownership of geometry and deletes it when it goes out of scope
      delete geometry;
      geometry = 0;
    }

    if ( ui.radioButtonError->isChecked() || current || error->status() == QgsGeometryCheckError::StatusFixed )
    {
      QgsRubberBand* pointRubberBand = new QgsRubberBand( mIface->mapCanvas(), QGis::Point );
      QgsPoint pos = mIface->mapCanvas()->mapSettings().layerToMapCoordinates( mFeaturePool->getLayer(), QgsPoint( error->location().x(), error->location().y() ) );
      pointRubberBand->addPoint( pos );
      pointRubberBand->setWidth( 20 );
      pointRubberBand->setColor( Qt::red );
      mCurrentRubberBands.append( pointRubberBand );
      errorPositions.append( pos );
    }
    else if ( ui.radioButtonFeature->isChecked() && geometry )
    {
      QgsRectangle geomextent = mIface->mapCanvas()->mapSettings().layerExtentToOutputExtent( mFeaturePool->getLayer(), geometry->boundingBox() );
      if ( totextent.isEmpty() )
      {
        totextent = geomextent;
      }
      else
      {
        totextent.unionRect( geomextent );
      }
    }
  }
Example #9
0
void Qgs3DMapScene::viewZoomFull()
{
  QgsRectangle extent = mMap.terrainGenerator()->extent();
  float side = std::max( extent.width(), extent.height() );
  mCameraController->resetView( side );  // assuming FOV being 45 degrees
}
bool QgsDecorationNorthArrow::calculateNorthDirection()
{
  QgsMapCanvas* mapCanvas = QgisApp::instance()->mapCanvas();

  bool goodDirn = false;

  if ( mapCanvas->layerCount() > 0 )
  {
    QgsCoordinateReferenceSystem outputCRS = mapCanvas->mapRenderer()->destinationCrs();

    if ( outputCRS.isValid() && !outputCRS.geographicFlag() )
    {
      // Use a geographic CRS to get lat/long to work out direction
      QgsCoordinateReferenceSystem ourCRS;
      ourCRS.createFromOgcWmsCrs( GEO_EPSG_CRS_AUTHID );
      assert( ourCRS.isValid() );

      QgsCoordinateTransform transform( outputCRS, ourCRS );

      QgsRectangle extent = mapCanvas->extent();
      QgsPoint p1( extent.center() );
      // A point a bit above p1. XXX assumes that y increases up!!
      // May need to involve the maptopixel transform if this proves
      // to be a problem.
      QgsPoint p2( p1.x(), p1.y() + extent.height() * 0.25 );

      // project p1 and p2 to geographic coords
      try
      {
        p1 = transform.transform( p1 );
        p2 = transform.transform( p2 );
      }
      catch ( QgsCsException &e )
      {
        Q_UNUSED( e );
        // just give up
        QgsDebugMsg( "North Arrow: Transformation error, quitting" );
        return false;
      }

      // Work out the value of the initial heading one takes to go
      // from point p1 to point p2. The north direction is then that
      // many degrees anti-clockwise or vertical.

      // Take some care to not divide by zero, etc, and ensure that we
      // get sensible results for all possible values for p1 and p2.

      goodDirn = true;
      double angle = 0.0;

      // convert to radians for the equations below
      p1.multiply( PI / 180.0 );
      p2.multiply( PI / 180.0 );

      double y = sin( p2.x() - p1.x() ) * cos( p2.y() );
      double x = cos( p1.y() ) * sin( p2.y() ) -
                 sin( p1.y() ) * cos( p2.y() ) * cos( p2.x() - p1.x() );

      if ( y > 0.0 )
      {
        if ( x > TOL )
          angle = atan( y / x );
        else if ( x < -TOL )
          angle = PI - atan( -y / x );
        else
          angle = 0.5 * PI;
      }
      else if ( y < 0.0 )
      {
        if ( x > TOL )
          angle = -atan( -y / x );
        else if ( x < -TOL )
          angle = atan( y / x ) - PI;
        else
          angle = 1.5 * PI;
      }
      else
      {
        if ( x > TOL )
          angle = 0.0;
        else if ( x < -TOL )
          angle = PI;
        else
        {
          angle = 0.0; // p1 = p2
          goodDirn = false;
        }
      }
      // And set the angle of the north arrow. Perhaps do something
      // different if goodDirn = false.
      mRotationInt = static_cast<int>( round( fmod( 360.0 - angle * 180.0 / PI, 360.0 ) ) );
    }
    else
    {
      // For geographic CRS and for when there are no layers, set the
      // direction back to the default
      mRotationInt = 0;
    }
  }
  return goodDirn;
}
Example #11
0
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 ( 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 ( const QgsCsException & )
    {
        // rethrow the exception
        QgsDebugMsg( "rethrowing exception" );
        throw;
    }

    // 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] ) )
        {
            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 ( 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 );
    }

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

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

    return bb_rect;
}
QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTextFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIteratorFromSource<QgsDelimitedTextFeatureSource>( source, ownSource, request )
    , mTestGeometryExact( false )
{

  // Determine mode to use based on request...
  QgsDebugMsg( "Setting up QgsDelimitedTextIterator" );

  // Does the layer have geometry - will revise later to determine if we actually need to
  // load it.
  bool hasGeometry = mSource->mGeomRep != QgsDelimitedTextProvider::GeomNone;

  // Does the layer have an explicit or implicit subset (implicit subset is if we have geometry which can
  // be invalid)

  mTestSubset = mSource->mSubsetExpression;
  mTestGeometry = false;

  mMode = FileScan;
  if ( request.filterType() == QgsFeatureRequest::FilterFid )
  {
    QgsDebugMsg( "Configuring for returning single id" );
    mFeatureIds.append( request.filterFid() );
    mMode = FeatureIds;
    mTestSubset = false;
  }
  // If have geometry and testing geometry then evaluate options...
  // If we don't have geometry then all records pass geometry filter.
  // CC: 2013-05-09
  // Not sure about intended relationship between filtering on geometry and
  // requesting no geometry? Have preserved current logic of ignoring spatial filter
  // if not requesting geometry.

  else if ( request.filterType() == QgsFeatureRequest::FilterRect && hasGeometry )
  {
    QgsDebugMsg( "Configuring for rectangle select" );
    mTestGeometry = true;
    // Exact intersection test only applies for WKT geometries
    mTestGeometryExact = mRequest.flags() & QgsFeatureRequest::ExactIntersect
                         && mSource->mGeomRep == QgsDelimitedTextProvider::GeomAsWkt;

    QgsRectangle rect = request.filterRect();

    // If request doesn't overlap extents, then nothing to return
    if ( ! rect.intersects( mSource->mExtent ) )
    {
      QgsDebugMsg( "Rectangle outside layer extents - no features to return" );
      mMode = FeatureIds;
    }
    // If the request extents include the entire layer, then revert to
    // a file scan

    else if ( rect.contains( mSource->mExtent ) )
    {
      QgsDebugMsg( "Rectangle contains layer extents - bypass spatial filter" );
      mTestGeometry = false;
    }
    // If we have a spatial index then use it.  The spatial index already accounts
    // for the subset.  Also means we don't have to test geometries unless doing exact
    // intersection

    else if ( mSource->mUseSpatialIndex )
    {
      mFeatureIds = mSource->mSpatialIndex->intersects( rect );
      // Sort for efficient sequential retrieval
      qSort( mFeatureIds.begin(), mFeatureIds.end() );
      QgsDebugMsg( QString( "Layer has spatial index - selected %1 features from index" ).arg( mFeatureIds.size() ) );
      mMode = FeatureIds;
      mTestSubset = false;
      mTestGeometry = mTestGeometryExact;
    }
  }

  // If we have a subset index then use it..
  if ( mMode == FileScan && mSource->mUseSubsetIndex )
  {
    QgsDebugMsg( QString( "Layer has subset index - use %1 items from subset index" ).arg( mSource->mSubsetIndex.size() ) );
    mTestSubset = false;
    mMode = SubsetIndex;
  }

  // Otherwise just have to scan the file
  if ( mMode == FileScan )
  {
    QgsDebugMsg( "File will be scanned for desired features" );
  }

  // If the layer has geometry, do we really need to load it?
  // We need it if it is asked for explicitly in the request,
  // if we are testing geometry (ie spatial filter), or
  // if testing the subset expression.
  if ( hasGeometry
       && (
         !( mRequest.flags() & QgsFeatureRequest::NoGeometry )
         || mTestGeometry
         || ( mTestSubset && mSource->mSubsetExpression->needsGeometry() )
       )
     )
  {
    mLoadGeometry = true;
  }
  else
  {
    QgsDebugMsgLevel( "Feature geometries not required", 4 );
    mLoadGeometry = false;
  }

  QgsDebugMsg( QString( "Iterator is scanning file: " ) + ( mMode == FileScan ? "Yes" : "No" ) );
  QgsDebugMsg( QString( "Iterator is loading geometries: " ) + ( mLoadGeometry ? "Yes" : "No" ) );
  QgsDebugMsg( QString( "Iterator is testing geometries: " ) + ( mTestGeometry ? "Yes" : "No" ) );
  QgsDebugMsg( QString( "Iterator is testing subset: " ) + ( mTestSubset ? "Yes" : "No" ) );

  rewind();
}
Example #13
0
/**************************** REGION ********************************/
void QgsGrassNewMapset::setRegionPage()
{
    QgsDebugMsg( "entered." );

    // Set defaults
    if ( !mRegionModified )
    {
        setGrassRegionDefaults();
    }

    // Create new projection
    QgsCoordinateReferenceSystem newSrs;
    if ( mProjRadioButton->isChecked() )
    {
        QgsDebugMsg( QString( "selectedCrsId() = %1" ).arg( mProjectionSelector->selectedCrsId() ) );

        if ( mProjectionSelector->selectedCrsId() > 0 )
        {
            newSrs.createFromSrsId( mProjectionSelector->selectedCrsId() );
            if ( ! newSrs.isValid() )
            {
                QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot create projection." ) );
            }
        }
    }

    // Reproject previous region if it was modified
    // and if previous and current projection is valid
    if ( mRegionModified && newSrs.isValid() && mSrs.isValid()
            && newSrs.srsid() != mSrs.srsid() )
    {
        QgsCoordinateTransform trans( mSrs, newSrs );

        double n = mNorthLineEdit->text().toDouble();
        double s = mSouthLineEdit->text().toDouble();
        double e = mEastLineEdit->text().toDouble();
        double w = mWestLineEdit->text().toDouble();

        std::vector<QgsPoint> points;

        // TODO: this is not perfect
        points.push_back( QgsPoint( w, s ) );
        points.push_back( QgsPoint( e, n ) );

        bool ok = true;
        for ( int i = 0; i < 2; i++ )
        {
            try
            {
                points[i] = trans.transform( points[i] );
            }
            catch ( QgsCsException &cse )
            {
                Q_UNUSED( cse );
                QgsDebugMsg( "Cannot transform point" );
                ok = false;
                break;
            }
        }

        if ( ok )
        {
            mNorthLineEdit->setText( QString::number( points[1].y() ) );
            mSouthLineEdit->setText( QString::number( points[0].y() ) );
            mEastLineEdit->setText( QString::number( points[1].x() ) );
            mWestLineEdit->setText( QString::number( points[0].x() ) );
        }
        else
        {
            QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot reproject previously set region, default region set." ) );

            setGrassRegionDefaults();
        }
    }

    // Set current region projection
    mSrs = newSrs;

    // Enable / disable region selection widgets
    if ( mNoProjRadioButton->isChecked() )
    {
        mRegionMap->hide();
        mCurrentRegionButton->hide();
        mRegionsComboBox->hide();
        mRegionButton->hide();
        mSetRegionFrame->hide();
    }
    else
    {
        mRegionMap->show();
        mCurrentRegionButton->show();
        mRegionsComboBox->show();
        mRegionButton->show();
        mSetRegionFrame->show();

        QgsRectangle ext = mIface->mapCanvas()->extent();

        if ( ext.xMinimum() >= ext.xMaximum() || ext.yMinimum() >= ext.yMaximum() )
        {
            mCurrentRegionButton->setEnabled( false );
        }
    }

    checkRegion();

    if ( !mNoProjRadioButton->isChecked() )
    {
        drawRegion();
    }
}
Example #14
0
QString QgsWFSCapabilities::uriGetFeature( QString typeName, QString crsString, QString filter, QgsRectangle bBox ) const
{
  //get CRS
  if ( !crsString.isEmpty() )
  {
    crsString.prepend( "&SRSNAME=" );
  }

  QString filterString;

  //if the xml comes from the dialog, it needs to be a string to pass the validity test
  if ( filter.startsWith( "'" ) && filter.endsWith( "'" ) && filter.size() > 1 )
  {
    filter.chop( 1 );
    filter.remove( 0, 1 );
  }

  if ( !filter.isEmpty() )
  {
    //test if filterString is already an OGC filter xml
    QDomDocument filterDoc;
    if ( !filterDoc.setContent( filter ) )
    {
      //if not, if must be a QGIS expression
      QgsExpression filterExpression( filter );
      QString errorMsg;
      QDomElement filterElem = QgsOgcUtils::expressionToOgcFilter( filterExpression, filterDoc, &errorMsg );
      if ( !errorMsg.isEmpty() )
      {
        QgsMessageLog::logMessage( "Expression to OGC Filter error: " + errorMsg, "WFS" );
      }
      if ( !filterElem.isNull() )
      {
        filterDoc.appendChild( filterElem );
      }

    }
    filterString = "&FILTER=" + filterDoc.toString();
  }

  QString bBoxString;
  if ( !bBox.isEmpty() )
  {
    bBoxString = QString( "&BBOX=%1,%2,%3,%4" )
                 .arg( qgsDoubleToString( bBox.xMinimum() ) )
                 .arg( qgsDoubleToString( bBox.yMinimum() ) )
                 .arg( qgsDoubleToString( bBox.xMaximum() ) )
                 .arg( qgsDoubleToString( bBox.yMaximum() ) );
  }

  QString uri = mBaseUrl;

  //add a wfs layer to the map
  uri += "SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=" + typeName + crsString + bBoxString + filterString;

  //add authorization information
  if ( mUri.hasParam( "username" ) && mUri.hasParam( "password" ) )
  {
    uri += "&username=" + mUri.param( "username" );
    uri += "&password=" + mUri.param( "password" );
  }
  QgsDebugMsg( uri );
  return uri;
}
Example #15
0
void QgsAtlasComposition::prepareMap( QgsComposerMap* map )
{
  if ( !map->atlasDriven() )
  {
    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 new_extent = mTransformedFeatureBounds;
  QgsRectangle mOrigExtent = map->extent();

  if ( map->atlasFixedScale() )
  {
    // 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 = mTransformedFeatureBounds.width() / mTransformedFeatureBounds.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 * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.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 = ( mTransformedFeatureBounds.width() / map_ratio - mTransformedFeatureBounds.height() ) / 2.0;
      ya1 -= adj_height;
      ya2 += adj_height;
    }
    new_extent = QgsRectangle( xa1, ya1, xa2, ya2 );

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

  // set the new extent (and render)
  map->setNewAtlasFeatureExtent( new_extent );
}
Example #16
0
  QDomElement getFeatureTypeListElement( QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project )
  {
    QgsAccessControl *accessControl = serverIface->accessControls();

    //wfs:FeatureTypeList element
    QDomElement featureTypeListElement = doc.createElement( QStringLiteral( "FeatureTypeList" )/*wfs:FeatureTypeList*/ );
    //wfs:Operations element
    QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ );
    featureTypeListElement.appendChild( operationsElement );
    //wfs:Query element
    QDomElement queryElement = doc.createElement( QStringLiteral( "Query" )/*wfs:Query*/ );
    operationsElement.appendChild( queryElement );

    QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project );
    QStringList wfstUpdateLayersId = QgsServerProjectUtils::wfstUpdateLayerIds( *project );
    QStringList wfstInsertLayersId = QgsServerProjectUtils::wfstInsertLayerIds( *project );
    QStringList wfstDeleteLayersId = QgsServerProjectUtils::wfstDeleteLayerIds( *project );
    for ( int i = 0; i < wfsLayerIds.size(); ++i )
    {
      QgsMapLayer *layer = project->mapLayer( wfsLayerIds.at( i ) );
      if ( layer->type() != QgsMapLayer::LayerType::VectorLayer )
      {
        continue;
      }
      if ( accessControl && !accessControl->layerReadPermission( layer ) )
      {
        continue;
      }

      QDomElement layerElem = doc.createElement( QStringLiteral( "FeatureType" ) );

      //create Name
      QDomElement nameElem = doc.createElement( QStringLiteral( "Name" ) );
      QString typeName = layer->name();
      if ( !layer->shortName().isEmpty() )
        typeName = layer->shortName();
      typeName = typeName.replace( QLatin1String( " " ), QLatin1String( "_" ) );
      QDomText nameText = doc.createTextNode( typeName );
      nameElem.appendChild( nameText );
      layerElem.appendChild( nameElem );

      //create Title
      QDomElement titleElem = doc.createElement( QStringLiteral( "Title" ) );
      QString title = layer->title();
      if ( title.isEmpty() )
      {
        title = layer->name();
      }
      QDomText titleText = doc.createTextNode( title );
      titleElem.appendChild( titleText );
      layerElem.appendChild( titleElem );

      //create Abstract
      QString abstract = layer->abstract();
      if ( !abstract.isEmpty() )
      {
        QDomElement abstractElem = doc.createElement( QStringLiteral( "Abstract" ) );
        QDomText abstractText = doc.createTextNode( abstract );
        abstractElem.appendChild( abstractText );
        layerElem.appendChild( abstractElem );
      }

      //create keywords
      QString keywords = layer->keywordList();
      if ( !keywords.isEmpty() )
      {
        QDomElement keywordsElem = doc.createElement( QStringLiteral( "Keywords" ) );
        QDomText keywordsText = doc.createTextNode( keywords );
        keywordsElem.appendChild( keywordsText );
        layerElem.appendChild( keywordsElem );
      }

      //create SRS
      QDomElement srsElem = doc.createElement( QStringLiteral( "SRS" ) );
      QDomText srsText = doc.createTextNode( layer->crs().authid() );
      srsElem.appendChild( srsText );
      layerElem.appendChild( srsElem );

      //create LatLongBoundingBox
      QgsRectangle layerExtent = layer->extent();
      QDomElement bBoxElement = doc.createElement( QStringLiteral( "LatLongBoundingBox" ) );
      bBoxElement.setAttribute( QStringLiteral( "minx" ), QString::number( layerExtent.xMinimum() ) );
      bBoxElement.setAttribute( QStringLiteral( "miny" ), QString::number( layerExtent.yMinimum() ) );
      bBoxElement.setAttribute( QStringLiteral( "maxx" ), QString::number( layerExtent.xMaximum() ) );
      bBoxElement.setAttribute( QStringLiteral( "maxy" ), QString::number( layerExtent.yMaximum() ) );
      layerElem.appendChild( bBoxElement );

      // layer metadata URL
      QString metadataUrl = layer->metadataUrl();
      if ( !metadataUrl.isEmpty() )
      {
        QDomElement metaUrlElem = doc.createElement( QStringLiteral( "MetadataURL" ) );
        QString metadataUrlType = layer->metadataUrlType();
        metaUrlElem.setAttribute( QStringLiteral( "type" ), metadataUrlType );
        QString metadataUrlFormat = layer->metadataUrlFormat();
        if ( metadataUrlFormat == QLatin1String( "text/xml" ) )
        {
          metaUrlElem.setAttribute( QStringLiteral( "format" ), QStringLiteral( "XML" ) );
        }
        else
        {
          metaUrlElem.setAttribute( QStringLiteral( "format" ), QStringLiteral( "TXT" ) );
        }
        QDomText metaUrlText = doc.createTextNode( metadataUrl );
        metaUrlElem.appendChild( metaUrlText );
        layerElem.appendChild( metaUrlElem );
      }

      //wfs:Operations element
      QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ );
      //wfs:Query element
      QDomElement queryElement = doc.createElement( QStringLiteral( "Query" )/*wfs:Query*/ );
      operationsElement.appendChild( queryElement );
      if ( wfstUpdateLayersId.contains( layer->id() ) ||
           wfstInsertLayersId.contains( layer->id() ) ||
           wfstDeleteLayersId.contains( layer->id() ) )
      {
        QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
        QgsVectorDataProvider *provider = vlayer->dataProvider();
        if ( ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) && wfstInsertLayersId.contains( layer->id() ) )
        {
          //wfs:Insert element
          QDomElement insertElement = doc.createElement( QStringLiteral( "Insert" )/*wfs:Insert*/ );
          operationsElement.appendChild( insertElement );
        }
        if ( ( provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) &&
             ( provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) &&
             wfstUpdateLayersId.contains( layer->id() ) )
        {
          //wfs:Update element
          QDomElement updateElement = doc.createElement( QStringLiteral( "Update" )/*wfs:Update*/ );
          operationsElement.appendChild( updateElement );
        }
        if ( ( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) && wfstDeleteLayersId.contains( layer->id() ) )
        {
          //wfs:Delete element
          QDomElement deleteElement = doc.createElement( QStringLiteral( "Delete" )/*wfs:Delete*/ );
          operationsElement.appendChild( deleteElement );
        }
      }

      layerElem.appendChild( operationsElement );

      featureTypeListElement.appendChild( layerElem );
    }

    return featureTypeListElement;
  }
Example #17
0
void QgsWfsProjectParser::featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const
{
  const QList<QDomElement>& projectLayerElements = mProjectParser->projectLayerElements();
  if ( projectLayerElements.size() < 1 )
  {
    return;
  }

  QStringList wfsLayersId = mProjectParser->wfsLayers();
  QSet<QString> wfstUpdateLayersId = wfstUpdateLayers();
  QSet<QString> wfstInsertLayersId = wfstInsertLayers();
  QSet<QString> wfstDeleteLayersId = wfstDeleteLayers();

  QMap<QString, QgsMapLayer *> layerMap;

  Q_FOREACH ( const QDomElement &elem, projectLayerElements )
  {
    QString type = elem.attribute( "type" );
    if ( type == "vector" )
    {
      QString layerId = mProjectParser->layerId( elem );
      if ( !wfsLayersId.contains( layerId ) )
      {
        continue;
      }
      QgsMapLayer *layer = mProjectParser->createLayerFromElement( elem );
      if ( !layer )
      {
        continue;
      }
#ifdef HAVE_SERVER_PYTHON_PLUGINS
      if ( !mAccessControl->layerReadPermission( layer ) )
      {
        continue;
      }
#endif
      QgsDebugMsg( QString( "add layer %1 to map" ).arg( layer->id() ) );
      layerMap.insert( layer->id(), layer );

      QDomElement layerElem = doc.createElement( "FeatureType" );
      QDomElement nameElem = doc.createElement( "Name" );
      //We use the layer name even though it might not be unique.
      //Because the id sometimes contains user/pw information and the name is more descriptive
      QString typeName = layer->name();
      if ( !layer->shortName().isEmpty() )
        typeName = layer->shortName();
      typeName = typeName.replace( " ", "_" );
      QDomText nameText = doc.createTextNode( typeName );
      nameElem.appendChild( nameText );
      layerElem.appendChild( nameElem );

      QDomElement titleElem = doc.createElement( "Title" );
      QString titleName = layer->title();
      if ( titleName.isEmpty() )
      {
        titleName = layer->name();
      }
      QDomText titleText = doc.createTextNode( titleName );
      titleElem.appendChild( titleText );
      layerElem.appendChild( titleElem );

      QDomElement abstractElem = doc.createElement( "Abstract" );
      QString abstractName = layer->abstract();
      if ( abstractName.isEmpty() )
      {
        abstractName = "";
      }
      QDomText abstractText = doc.createTextNode( abstractName );
      abstractElem.appendChild( abstractText );
      layerElem.appendChild( abstractElem );

      //keyword list
      if ( !layer->keywordList().isEmpty() )
      {
        QDomElement keywordsElem = doc.createElement( "Keywords" );
        QDomText keywordsText = doc.createTextNode( layer->keywordList() );
        keywordsElem.appendChild( keywordsText );
        layerElem.appendChild( keywordsElem );
      }

      //appendExGeographicBoundingBox( layerElem, doc, layer->extent(), layer->crs() );

      QDomElement srsElem = doc.createElement( "SRS" );
      QDomText srsText = doc.createTextNode( layer->crs().authid() );
      srsElem.appendChild( srsText );
      layerElem.appendChild( srsElem );

      //wfs:Operations element
      QDomElement operationsElement = doc.createElement( "Operations"/*wfs:Operations*/ );
      //wfs:Query element
      QDomElement queryElement = doc.createElement( "Query"/*wfs:Query*/ );
      operationsElement.appendChild( queryElement );

      QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( layer );
      QgsVectorDataProvider* provider = vlayer->dataProvider();
      if (( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) && wfstInsertLayersId.contains( layer->id() ) )
      {
        //wfs:Insert element
        QDomElement insertElement = doc.createElement( "Insert"/*wfs:Insert*/ );
        operationsElement.appendChild( insertElement );
      }
      if (( provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) &&
          ( provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) &&
          wfstUpdateLayersId.contains( layer->id() ) )
      {
        //wfs:Update element
        QDomElement updateElement = doc.createElement( "Update"/*wfs:Update*/ );
        operationsElement.appendChild( updateElement );
      }
      if (( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) && wfstDeleteLayersId.contains( layer->id() ) )
      {
        //wfs:Delete element
        QDomElement deleteElement = doc.createElement( "Delete"/*wfs:Delete*/ );
        operationsElement.appendChild( deleteElement );
      }

      layerElem.appendChild( operationsElement );

      QgsRectangle layerExtent = layer->extent();
      QDomElement bBoxElement = doc.createElement( "LatLongBoundingBox" );
      bBoxElement.setAttribute( "minx", QString::number( layerExtent.xMinimum() ) );
      bBoxElement.setAttribute( "miny", QString::number( layerExtent.yMinimum() ) );
      bBoxElement.setAttribute( "maxx", QString::number( layerExtent.xMaximum() ) );
      bBoxElement.setAttribute( "maxy", QString::number( layerExtent.yMaximum() ) );
      layerElem.appendChild( bBoxElement );

      // layer metadata URL
      QString metadataUrl = layer->metadataUrl();
      if ( !metadataUrl.isEmpty() )
      {
        QDomElement metaUrlElem = doc.createElement( "MetadataURL" );
        QString metadataUrlType = layer->metadataUrlType();
        metaUrlElem.setAttribute( "type", metadataUrlType );
        QString metadataUrlFormat = layer->metadataUrlFormat();
        if ( metadataUrlFormat == "text/xml" )
        {
          metaUrlElem.setAttribute( "format", "XML" );
        }
        else
        {
          metaUrlElem.setAttribute( "format", "TXT" );
        }
        QDomText metaUrlText = doc.createTextNode( metadataUrl );
        metaUrlElem.appendChild( metaUrlText );
        layerElem.appendChild( metaUrlElem );
      }

      parentElement.appendChild( layerElem );
    }
  }
bool QgsComposerAttributeTable::getFeatureAttributes( QList<QgsAttributeMap> &attributeMaps )
{
  if ( !mVectorLayer )
  {
    return false;
  }

  attributeMaps.clear();

  //prepare filter expression
  std::auto_ptr<QgsExpression> filterExpression;
  bool activeFilter = false;
  if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
  {
    filterExpression = std::auto_ptr<QgsExpression>( new QgsExpression( mFeatureFilter ) );
    if ( !filterExpression->hasParserError() )
    {
      activeFilter = true;
    }
  }

  QgsRectangle selectionRect;
  if ( mComposerMap && mShowOnlyVisibleFeatures )
  {
    selectionRect = *mComposerMap->currentMapExtent();
    if ( mVectorLayer && mComposition->mapSettings().hasCrsTransformEnabled() )
    {
      //transform back to layer CRS
      QgsCoordinateTransform coordTransform( mVectorLayer->crs(), mComposition->mapSettings().destinationCrs() );
      try
      {
        selectionRect = coordTransform.transformBoundingBox( selectionRect, QgsCoordinateTransform::ReverseTransform );
      }
      catch ( QgsCsException &cse )
      {
        Q_UNUSED( cse );
        return false;
      }
    }
  }

  QgsFeatureRequest req;
  if ( !selectionRect.isEmpty() )
    req.setFilterRect( selectionRect );

  req.setFlags( mShowOnlyVisibleFeatures ? QgsFeatureRequest::ExactIntersect : QgsFeatureRequest::NoGeometry );

  if ( !mDisplayAttributes.isEmpty() )
    req.setSubsetOfAttributes( mDisplayAttributes.toList() );

  QgsFeature f;
  int counter = 0;
  QgsFeatureIterator fit = mVectorLayer->getFeatures( req );

  while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures )
  {
    //check feature against filter
    if ( activeFilter )
    {
      QVariant result = filterExpression->evaluate( &f, mVectorLayer->pendingFields() );
      // skip this feature if the filter evaluation if false
      if ( !result.toBool() )
      {
        continue;
      }
    }

    attributeMaps.push_back( QgsAttributeMap() );

    for ( int i = 0; i < f.attributes().size(); i++ )
    {
      if ( !mDisplayAttributes.isEmpty() && !mDisplayAttributes.contains( i ) )
        continue;

      attributeMaps.last().insert( i, f.attributes()[i] );
    }

    ++counter;
  }

  //sort the list, starting with the last attribute
  QgsComposerAttributeTableCompare c;
  for ( int i = mSortInformation.size() - 1; i >= 0; --i )
  {
    c.setSortColumn( mSortInformation.at( i ).first );
    c.setAscending( mSortInformation.at( i ).second );
    qStableSort( attributeMaps.begin(), attributeMaps.end(), c );
  }
  return true;
}
Example #19
0
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();
    }
  }
}
Example #20
0
void QgsComposerMapWidget::on_mSetToMapCanvasExtentButton_clicked()
{
  if ( mComposerMap )
  {
    const QgsMapRenderer* renderer = mComposerMap->mapRenderer();
    if ( renderer )
    {
      QgsRectangle newExtent = renderer->extent();

      //Make sure the width/height ratio is the same as in current composer map extent.
      //This is to keep the map item frame and the page layout fixed
      QgsRectangle currentMapExtent = mComposerMap->extent();
      double currentWidthHeightRatio = currentMapExtent.width() / currentMapExtent.height();
      double newWidthHeightRatio = newExtent.width() / newExtent.height();

      if ( currentWidthHeightRatio < newWidthHeightRatio )
      {
        //enlarge height of new extent
        double newHeight = newExtent.width() / currentWidthHeightRatio;
        newExtent.setYMinimum( newExtent.yMaximum() - newHeight );
      }
      else if ( currentWidthHeightRatio > newWidthHeightRatio )
      {
        //enlarge width of new extent
        double newWidth = currentWidthHeightRatio * newExtent.height();
        newExtent.setXMaximum( newExtent.xMinimum() + newWidth );
      }

      //fill text into line edits
      mXMinLineEdit->setText( QString::number( newExtent.xMinimum() ) );
      mXMaxLineEdit->setText( QString::number( newExtent.xMaximum() ) );
      mYMinLineEdit->setText( QString::number( newExtent.yMinimum() ) );
      mYMaxLineEdit->setText( QString::number( newExtent.yMaximum() ) );

      mComposerMap->beginCommand( tr( "Map extent changed" ) );
      mComposerMap->setNewExtent( newExtent );
      mComposerMap->endCommand();
    }
  }
}
Example #21
0
  bool isSegmentInRect( double x0, double y0, double x1, double y1 )
  {
    // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle
    OutCode outcode0 = computeOutCode( x0, y0 );
    OutCode outcode1 = computeOutCode( x1, y1 );
    bool accept = false;

    while ( true )
    {
      if ( !( outcode0 | outcode1 ) )
      {
        // Bitwise OR is 0. Trivially accept and get out of loop
        accept = true;
        break;
      }
      else if ( outcode0 & outcode1 )
      {
        // Bitwise AND is not 0. Trivially reject and get out of loop
        break;
      }
      else
      {
        // failed both tests, so calculate the line segment to clip
        // from an outside point to an intersection with clip edge
        double x, y;

        // At least one endpoint is outside the clip rectangle; pick it.
        OutCode outcodeOut = outcode0 ? outcode0 : outcode1;

        // Now find the intersection point;
        // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0)
        if ( outcodeOut & TOP )
        { // point is above the clip rectangle
          x = x0 + ( x1 - x0 ) * ( mRect.yMaximum() - y0 ) / ( y1 - y0 );
          y = mRect.yMaximum();
        }
        else if ( outcodeOut & BOTTOM )
        { // point is below the clip rectangle
          x = x0 + ( x1 - x0 ) * ( mRect.yMinimum() - y0 ) / ( y1 - y0 );
          y = mRect.yMinimum();
        }
        else if ( outcodeOut & RIGHT )
        {  // point is to the right of clip rectangle
          y = y0 + ( y1 - y0 ) * ( mRect.xMaximum() - x0 ) / ( x1 - x0 );
          x = mRect.xMaximum();
        }
        else if ( outcodeOut & LEFT )
        {   // point is to the left of clip rectangle
          y = y0 + ( y1 - y0 ) * ( mRect.xMinimum() - x0 ) / ( x1 - x0 );
          x = mRect.xMinimum();
        }
        else
          break;

        // Now we move outside point to intersection point to clip
        // and get ready for next pass.
        if ( outcodeOut == outcode0 )
        {
          x0 = x;
          y0 = y;
          outcode0 = computeOutCode( x0, y0 );
        }
        else
        {
          x1 = x;
          y1 = y;
          outcode1 = computeOutCode( x1, y1 );
        }
      }
    }
    return accept;
  }
Example #22
0
void QgsComposerMapWidget::updateGuiElements()
{
  if ( mComposerMap )
  {
    blockAllSignals( true );

    //width, height, scale
    QRectF composerMapRect = mComposerMap->rect();
    mWidthLineEdit->setText( QString::number( composerMapRect.width() ) );
    mHeightLineEdit->setText( QString::number( composerMapRect.height() ) );
    mScaleLineEdit->setText( QString::number( mComposerMap->scale(), 'f', 0 ) );

    //preview mode
    QgsComposerMap::PreviewMode previewMode = mComposerMap->previewMode();
    int index = -1;
    if ( previewMode == QgsComposerMap::Cache )
    {
      index = mPreviewModeComboBox->findText( tr( "Cache" ) );
    }
    else if ( previewMode == QgsComposerMap::Render )
    {
      index = mPreviewModeComboBox->findText( tr( "Render" ) );
    }
    else if ( previewMode == QgsComposerMap::Rectangle )
    {
      index = mPreviewModeComboBox->findText( tr( "Rectangle" ) );
      mUpdatePreviewButton->setEnabled( false );
    }
    if ( index != -1 )
    {
      mPreviewModeComboBox->setCurrentIndex( index );
    }

    //composer map extent
    QgsRectangle composerMapExtent = mComposerMap->extent();
    mXMinLineEdit->setText( QString::number( composerMapExtent.xMinimum(), 'f', 3 ) );
    mXMaxLineEdit->setText( QString::number( composerMapExtent.xMaximum(), 'f', 3 ) );
    mYMinLineEdit->setText( QString::number( composerMapExtent.yMinimum(), 'f', 3 ) );
    mYMaxLineEdit->setText( QString::number( composerMapExtent.yMaximum(), 'f', 3 ) );

    mRotationSpinBox->setValue( mComposerMap->rotation() );

    //keep layer list check box
    if ( mComposerMap->keepLayerSet() )
    {
      mKeepLayerListCheckBox->setCheckState( Qt::Checked );
    }
    else
    {
      mKeepLayerListCheckBox->setCheckState( Qt::Unchecked );
    }

    //draw canvas items
    if ( mComposerMap->drawCanvasItems() )
    {
      mDrawCanvasItemsCheckBox->setCheckState( Qt::Checked );
    }
    else
    {
      mDrawCanvasItemsCheckBox->setCheckState( Qt::Unchecked );
    }

    //grid
    if ( mComposerMap->gridEnabled() )
    {
      mGridCheckBox->setChecked( true );
    }
    else
    {
      mGridCheckBox->setChecked( false );
    }

    mIntervalXSpinBox->setValue( mComposerMap->gridIntervalX() );
    mIntervalYSpinBox->setValue( mComposerMap->gridIntervalY() );
    mOffsetXSpinBox->setValue( mComposerMap->gridOffsetX() );
    mOffsetYSpinBox->setValue( mComposerMap->gridOffsetY() );

    QgsComposerMap::GridStyle gridStyle = mComposerMap->gridStyle();
    if ( gridStyle == QgsComposerMap::Cross )
    {
      mGridTypeComboBox->setCurrentIndex( mGridTypeComboBox->findText( tr( "Cross" ) ) );
    }
    else
    {
      mGridTypeComboBox->setCurrentIndex( mGridTypeComboBox->findText( tr( "Solid" ) ) );
    }

    mCrossWidthSpinBox->setValue( mComposerMap->crossLength() );

    QgsComposerMap::GridAnnotationPosition annotationPos = mComposerMap->gridAnnotationPosition();
    if ( annotationPos == QgsComposerMap::InsideMapFrame )
    {
      mAnnotationPositionComboBox->setCurrentIndex( mAnnotationPositionComboBox->findText( tr( "Inside frame" ) ) );
    }
    else
    {
      mAnnotationPositionComboBox->setCurrentIndex( mAnnotationPositionComboBox->findText( tr( "Outside frame" ) ) );
    }

    mDistanceToMapFrameSpinBox->setValue( mComposerMap->annotationFrameDistance() );

    if ( mComposerMap->showGridAnnotation() )
    {
      mDrawAnnotationCheckBox->setCheckState( Qt::Checked );
    }
    else
    {
      mDrawAnnotationCheckBox->setCheckState( Qt::Unchecked );
    }

    QgsComposerMap::GridAnnotationDirection dir = mComposerMap->gridAnnotationDirection();
    if ( dir == QgsComposerMap::Horizontal )
    {
      mAnnotationDirectionComboBox->setCurrentIndex( mAnnotationDirectionComboBox->findText( tr( "Horizontal" ) ) );
    }
    else if ( dir == QgsComposerMap::Vertical )
    {
      mAnnotationDirectionComboBox->setCurrentIndex( mAnnotationDirectionComboBox->findText( tr( "Vertical" ) ) );
    }
    else if ( dir == QgsComposerMap::HorizontalAndVertical )
    {
      mAnnotationDirectionComboBox->setCurrentIndex( mAnnotationDirectionComboBox->findText( tr( "Horizontal and Vertical" ) ) );
    }
    else //BoundaryDirection
    {
      mAnnotationDirectionComboBox->setCurrentIndex( mAnnotationDirectionComboBox->findText( tr( "Boundary direction" ) ) );
    }

    mCoordinatePrecisionSpinBox->setValue( mComposerMap->gridAnnotationPrecision() );

    QPen gridPen = mComposerMap->gridPen();
    mLineWidthSpinBox->setValue( gridPen.widthF() );
    mLineColorButton->setColor( gridPen.color() );

    blockAllSignals( false );
  }
}
bool QgsMapToolIdentify::identifyVectorLayer( QList<IdentifyResult> *results, QgsVectorLayer *layer, const QgsPoint& point )
{
  if ( !layer || !layer->hasGeometryType() )
    return false;

  if ( layer->hasScaleBasedVisibility() &&
       ( layer->minimumScale() > mCanvas->mapSettings().scale() ||
         layer->maximumScale() <= mCanvas->mapSettings().scale() ) )
  {
    QgsDebugMsg( "Out of scale limits" );
    return false;
  }

  QApplication::setOverrideCursor( Qt::WaitCursor );

  QMap< QString, QString > commonDerivedAttributes;

  commonDerivedAttributes.insert( tr( "(clicked coordinate)" ), point.toString() );

  int featureCount = 0;

  QgsFeatureList featureList;

  // toLayerCoordinates will throw an exception for an 'invalid' point.
  // For example, if you project a world map onto a globe using EPSG 2163
  // and then click somewhere off the globe, an exception will be thrown.
  try
  {
    // create the search rectangle
    double searchRadius = searchRadiusMU( mCanvas );

    QgsRectangle r;
    r.setXMinimum( point.x() - searchRadius );
    r.setXMaximum( point.x() + searchRadius );
    r.setYMinimum( point.y() - searchRadius );
    r.setYMaximum( point.y() + searchRadius );

    r = toLayerCoordinates( layer, r );

    QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterRect( r ).setFlags( QgsFeatureRequest::ExactIntersect ) );
    QgsFeature f;
    while ( fit.nextFeature( f ) )
      featureList << QgsFeature( f );
  }
  catch ( QgsCsException & cse )
  {
    Q_UNUSED( cse );
    // catch exception for 'invalid' point and proceed with no features found
    QgsDebugMsg( QString( "Caught CRS exception %1" ).arg( cse.what() ) );
  }

  QgsFeatureList::iterator f_it = featureList.begin();

  bool filter = false;

  QgsRenderContext context( QgsRenderContext::fromMapSettings( mCanvas->mapSettings() ) );
  context.expressionContext() << QgsExpressionContextUtils::layerScope( layer );
  QgsFeatureRendererV2* renderer = layer->rendererV2();
  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
  {
    // setup scale for scale dependent visibility (rule based)
    renderer->startRender( context, layer->fields() );
    filter = renderer->capabilities() & QgsFeatureRendererV2::Filter;
  }

  for ( ; f_it != featureList.end(); ++f_it )
  {
    QMap< QString, QString > derivedAttributes = commonDerivedAttributes;

    QgsFeatureId fid = f_it->id();
    context.expressionContext().setFeature( *f_it );

    if ( filter && !renderer->willRenderFeature( *f_it, context ) )
      continue;

    featureCount++;

    derivedAttributes.unite( featureDerivedAttributes( &( *f_it ), layer, toLayerCoordinates( layer, point ) ) );

    derivedAttributes.insert( tr( "feature id" ), fid < 0 ? tr( "new feature" ) : FID_TO_STRING( fid ) );

    results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), *f_it, derivedAttributes ) );
  }

  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
  {
    renderer->stopRender( context );
  }

  QgsDebugMsg( "Feature count on identify: " + QString::number( featureCount ) );

  QApplication::restoreOverrideCursor();
  return featureCount > 0;
}
Example #24
0
bool QgsVectorLayerRenderer::render()
{
  if ( mGeometryType == QGis::NoGeometry || mGeometryType == QGis::UnknownGeometry )
    return true;

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

  // 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 );
  }

  mRendererV2->startRender( mContext, mFields );

  QgsFeatureRequest featureRequest = QgsFeatureRequest()
                                     .setFilterRect( mContext.extent() )
                                     .setSubsetOfAttributes( mAttrNames, mFields );

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

    const QgsMapToPixel& mtp = mContext.mapToPixel();
    map2pixelTol *= mtp.mapUnitsPerPixel();
    const 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 && !(( QgsCoordinateTransform* )ct )->isShortCircuited() )
    {
      try
      {
        QgsPoint center = mContext.extent().center();
        double rectSize = ct->sourceCrs().geographicFlag() ? 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 );

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

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

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

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

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

    QgsSimplifyMethod simplifyMethod;
    simplifyMethod.setMethodType( QgsSimplifyMethod::OptimizeForRendering );
    simplifyMethod.setTolerance( map2pixelTol );
    simplifyMethod.setForceLocalOptimization( mSimplifyMethod.forceLocalOptimization() );

    featureRequest.setSimplifyMethod( simplifyMethod );

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

  QgsFeatureIterator fit = mSource->getFeatures( featureRequest );

  if (( mRendererV2->capabilities() & QgsFeatureRendererV2::SymbolLevels ) && mRendererV2->usingSymbolLevels() )
    drawRendererV2Levels( fit );
  else
    drawRendererV2( fit );

  //apply layer transparency for vector layers
  if ( mContext.useAdvancedEffects() && mLayerTransparency != 0 )
  {
    // a layer transparency has been set, so update the alpha for the flattened layer
    // by combining it with the layer transparency
    QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * mLayerTransparency / 100 ) );
    // use destination in composition mode to merge source's alpha with destination
    mContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn );
    mContext.painter()->fillRect( 0, 0, mContext.painter()->device()->width(),
                                  mContext.painter()->device()->height(), transparentFillColor );
  }

  return true;
}
Example #25
0
int QgsZonalStatistics::cellInfoForBBox( const QgsRectangle &rasterBBox, const QgsRectangle &featureBBox, double cellSizeX, double cellSizeY,
    int &offsetX, int &offsetY, int &nCellsX, int &nCellsY ) const
{
  //get intersecting bbox
  QgsRectangle intersectBox = rasterBBox.intersect( &featureBBox );
  if ( intersectBox.isEmpty() )
  {
    nCellsX = 0;
    nCellsY = 0;
    offsetX = 0;
    offsetY = 0;
    return 0;
  }

  //get offset in pixels in x- and y- direction
  offsetX = ( int )( ( intersectBox.xMinimum() - rasterBBox.xMinimum() ) / cellSizeX );
  offsetY = ( int )( ( rasterBBox.yMaximum() - intersectBox.yMaximum() ) / cellSizeY );

  int maxColumn = ( int )( ( intersectBox.xMaximum() - rasterBBox.xMinimum() ) / cellSizeX ) + 1;
  int maxRow = ( int )( ( rasterBBox.yMaximum() - intersectBox.yMinimum() ) / cellSizeY ) + 1;

  nCellsX = maxColumn - offsetX;
  nCellsY = maxRow - offsetY;

  return 0;
}
Example #26
0
void QgsZonalStatistics::statisticsFromMiddlePointTest_improved( void* band, QgsGeometry* poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY,
    double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, double& sum, double& count )
{
  double cellCenterX, cellCenterY;
  QgsPoint currentCellCenter;

  float* scanLine = ( float * ) CPLMalloc( sizeof( float ) * nCellsX );
  cellCenterY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2;
  count = 0;
  sum = 0;

  for ( int i = 0; i < nCellsY; ++i )
  {
    GDALRasterIO( band, GF_Read, pixelOffsetX, pixelOffsetY + i, nCellsX, 1, scanLine, nCellsX, 1, GDT_Float32, 0, 0 );
    cellCenterX = rasterBBox.xMinimum() + pixelOffsetX * cellSizeX + cellSizeX / 2;

    //do intersection of scanline with geometry
    GEOSCoordSequence* scanLineSequence = GEOSCoordSeq_create( 2, 2 );
    GEOSCoordSeq_setX( scanLineSequence, 0, cellCenterX );
    GEOSCoordSeq_setY( scanLineSequence, 0, cellCenterY );
    GEOSCoordSeq_setX( scanLineSequence, 1, cellCenterX + nCellsX * cellSizeX );
    GEOSCoordSeq_setY( scanLineSequence, 1, cellCenterY );
    GEOSGeometry* scanLineGeos = GEOSGeom_createLineString( scanLineSequence ); //todo: delete
    GEOSGeometry* polyGeos = poly->asGeos();
    GEOSGeometry* scanLineIntersection = GEOSIntersection( scanLineGeos, polyGeos );
    GEOSGeom_destroy( scanLineGeos );
    if ( !scanLineIntersection )
    {
      cellCenterY -= cellSizeY;
      continue;
    }

    //debug
    //char* scanLineIntersectionType = GEOSGeomType( scanLineIntersection );

    int numGeoms = GEOSGetNumGeometries( scanLineIntersection );
    if ( numGeoms < 1 )
    {
      GEOSGeom_destroy( scanLineIntersection );
      cellCenterY -= cellSizeY;
      continue;
    }

    QList<double> scanLineList;
    double currentValue;
    GEOSGeometry* currentGeom = 0;
    for ( int z = 0; z < numGeoms; ++z )
    {
      if ( numGeoms == 1 )
      {
        currentGeom = scanLineIntersection;
      }
      else
      {
        currentGeom = GEOSGeom_clone( GEOSGetGeometryN( scanLineIntersection, z ) );
      }
      const GEOSCoordSequence* scanLineCoordSequence = GEOSGeom_getCoordSeq( currentGeom );
      if ( !scanLineCoordSequence )
      {
        //error
      }
      unsigned int scanLineIntersectionSize;
      GEOSCoordSeq_getSize( scanLineCoordSequence, &scanLineIntersectionSize );
      if ( !scanLineCoordSequence || scanLineIntersectionSize < 2 || ( scanLineIntersectionSize & 1 ) )
      {
        //error
      }
      for ( unsigned int k = 0; k < scanLineIntersectionSize; ++k )
      {
        GEOSCoordSeq_getX( scanLineCoordSequence, k, &currentValue );
        scanLineList.push_back( currentValue );
      }

      if ( numGeoms != 1 )
      {
        GEOSGeom_destroy( currentGeom );
      }
    }
    GEOSGeom_destroy( scanLineIntersection );
    qSort( scanLineList );

    if ( scanLineList.size() < 1 )
    {
      cellCenterY -= cellSizeY;
      continue;
    }

    int listPlace = -1;
    for ( int j = 0; j < nCellsX; ++j )
    {
      //currentCellCenter = QgsPoint( cellCenterX, cellCenterY );

      //instead of doing a contained test every time, find the place of scanLineList and check if even / odd
      if ( listPlace >= scanLineList.size() - 1 )
      {
        break;
      }
      if ( cellCenterX >= scanLineList.at( listPlace + 1 ) )
      {
        ++listPlace;
        if ( listPlace >= scanLineList.size() )
        {
          break;
        }
      }
      if ( listPlace >= 0 && listPlace < ( scanLineList.size() - 1 ) && !( listPlace & 1 ) )
      {
        if ( scanLine[j] != mInputNodataValue ) //don't consider nodata values
        {
          sum += scanLine[j];
          ++count;
        }
      }
      cellCenterX += cellSizeX;
    }
    cellCenterY -= cellSizeY;
  }
  CPLFree( scanLine );
}
Example #27
0
bool QgsMapRenderer::setExtent( const QgsRectangle& extent )
{
  //remember the previous extent
  mLastExtent = mExtent;

  // Don't allow zooms where the current extent is so small that it
  // can't be accurately represented using a double (which is what
  // currentExtent uses). Excluding 0 avoids a divide by zero and an
  // infinite loop when rendering to a new canvas. Excluding extents
  // greater than 1 avoids doing unnecessary calculations.

  // The scheme is to compare the width against the mean x coordinate
  // (and height against mean y coordinate) and only allow zooms where
  // the ratio indicates that there is more than about 12 significant
  // figures (there are about 16 significant figures in a double).

  if ( extent.width()  > 0 &&
       extent.height() > 0 &&
       extent.width()  < 1 &&
       extent.height() < 1 )
  {
    // Use abs() on the extent to avoid the case where the extent is
    // symmetrical about 0.
    double xMean = ( qAbs( extent.xMinimum() ) + qAbs( extent.xMaximum() ) ) * 0.5;
    double yMean = ( qAbs( extent.yMinimum() ) + qAbs( extent.yMaximum() ) ) * 0.5;

    double xRange = extent.width() / xMean;
    double yRange = extent.height() / yMean;

    static const double minProportion = 1e-12;
    if ( xRange < minProportion || yRange < minProportion )
      return false;
  }

  mExtent = extent;
  if ( !extent.isEmpty() )
    adjustExtentToSize();
  return true;
}
Example #28
0
QgsRectangle QgsServerProjectParser::layerBoundingBoxInProjectCrs( const QDomElement& layerElem, const QDomDocument &doc ) const
{
  QgsRectangle BBox;
  if ( layerElem.isNull() )
  {
    return BBox;
  }

  //read box coordinates and layer auth. id
  QDomElement boundingBoxElem = layerElem.firstChildElement( "BoundingBox" );
  if ( boundingBoxElem.isNull() )
  {
    return BBox;
  }

  double minx, miny, maxx, maxy;
  bool conversionOk;
  minx = boundingBoxElem.attribute( "minx" ).toDouble( &conversionOk );
  if ( !conversionOk )
  {
    return BBox;
  }
  miny = boundingBoxElem.attribute( "miny" ).toDouble( &conversionOk );
  if ( !conversionOk )
  {
    return BBox;
  }
  maxx = boundingBoxElem.attribute( "maxx" ).toDouble( &conversionOk );
  if ( !conversionOk )
  {
    return BBox;
  }
  maxy = boundingBoxElem.attribute( "maxy" ).toDouble( &conversionOk );
  if ( !conversionOk )
  {
    return BBox;
  }


  QString version = doc.documentElement().attribute( "version" );

  //create layer crs
  QgsCoordinateReferenceSystem layerCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( boundingBoxElem.attribute( version == "1.1.1" ? "SRS" : "CRS" ) );
  if ( !layerCrs.isValid() )
  {
    return BBox;
  }

  BBox.setXMinimum( minx );
  BBox.setXMaximum( maxx );
  BBox.setYMinimum( miny );
  BBox.setYMaximum( maxy );

  if ( version != "1.1.1" && layerCrs.hasAxisInverted() )
  {
    BBox.invert();
  }

  //get project crs
  QgsCoordinateTransform t( layerCrs, projectCrs() );

  //transform
  BBox = t.transformBoundingBox( BBox );
  return BBox;
}
void QgsAdvancedDigitizingCanvasItem::paint( QPainter *painter )
{
  if ( !mAdvancedDigitizingDockWidget->cadEnabled() )
    return;

  QgsRectangle mapRect = mMapCanvas->extent();
  if ( rect() != mapRect )
    setRect( mapRect );

  int nPoints = mAdvancedDigitizingDockWidget->pointsCount();
  if ( !nPoints )
    return;

  bool previousPointExist, penulPointExist;
  const QgsPointXY curPoint = mAdvancedDigitizingDockWidget->currentPoint();
  const QgsPointXY prevPoint = mAdvancedDigitizingDockWidget->previousPoint( &previousPointExist );
  const QgsPointXY penulPoint = mAdvancedDigitizingDockWidget->penultimatePoint( &penulPointExist );
  const bool snappedToVertex = mAdvancedDigitizingDockWidget->snappedToVertex();
  const QList<QgsPointXY> snappedSegment = mAdvancedDigitizingDockWidget->snappedSegment();
  const bool hasSnappedSegment = snappedSegment.count() == 2;

  const bool curPointExist = mapRect.contains( curPoint );

  const double mupp = mMapCanvas->getCoordinateTransform()->mapUnitsPerPixel();
  if ( mupp == 0 )
    return;

  QPointF curPointPix, prevPointPix, penulPointPix, snapSegmentPix1, snapSegmentPix2;

  if ( curPointExist )
  {
    curPointPix = toCanvasCoordinates( curPoint );
  }
  if ( previousPointExist )
  {
    prevPointPix = toCanvasCoordinates( prevPoint );
  }
  if ( penulPointExist )
  {
    penulPointPix = toCanvasCoordinates( penulPoint );
  }
  if ( hasSnappedSegment )
  {
    snapSegmentPix1 = toCanvasCoordinates( snappedSegment[0] );
    snapSegmentPix2 = toCanvasCoordinates( snappedSegment[1] );
  }

  painter->setRenderHint( QPainter::Antialiasing );
  painter->setCompositionMode( QPainter::CompositionMode_Difference );

  // Draw point snap
  if ( curPointExist && snappedToVertex )
  {
    painter->setPen( mSnapPen );
    painter->drawEllipse( curPointPix, 10, 10 );
  }

  // Draw segment snap
  if ( hasSnappedSegment && !snappedToVertex )
  {
    painter->setPen( mSnapPen );
    painter->drawLine( snapSegmentPix1, snapSegmentPix2 );

    if ( curPointExist )
    {
      painter->setPen( mSnapLinePen );
      painter->drawLine( snapSegmentPix1, curPointPix );
    }
  }

  // Draw segment par/per input
  if ( mAdvancedDigitizingDockWidget->additionalConstraint() != QgsAdvancedDigitizingDockWidget::NoConstraint && hasSnappedSegment )
  {
    painter->setPen( mConstruction2Pen );
    painter->drawLine( snapSegmentPix1, snapSegmentPix2 );
  }

  // Draw angle
  if ( nPoints > 1 )
  {
    double a0, a;
    if ( mAdvancedDigitizingDockWidget->constraintAngle()->relative() && nPoints > 2 )
    {
      a0 = std::atan2( -( prevPoint.y() - penulPoint.y() ), prevPoint.x() - penulPoint.x() );
    }
    else
    {
      a0 = 0;
    }
    if ( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() )
    {
      a = a0 - mAdvancedDigitizingDockWidget->constraintAngle()->value() * M_PI / 180;
    }
    else
    {
      a = std::atan2( -( curPoint.y() - prevPoint.y() ), curPoint.x() - prevPoint.x() );
    }
    painter->setPen( mConstruction2Pen );
    painter->drawArc( QRectF( prevPointPix.x() - 20,
                              prevPointPix.y() - 20,
                              40, 40 ),
                      static_cast<int>( 16 * -a0 * 180 / M_PI ),
                      static_cast<int>( 16 * ( a0 - a ) * 180 / M_PI ) );
    painter->drawLine( prevPointPix,
                       prevPointPix + 60 * QPointF( std::cos( a0 ), std::sin( a0 ) ) );


    if ( mAdvancedDigitizingDockWidget->constraintAngle()->isLocked() )
    {
      painter->setPen( mLockedPen );
      double d = std::max( boundingRect().width(), boundingRect().height() );
      painter->drawLine( prevPointPix - d * QPointF( std::cos( a ), std::sin( a ) ),
                         prevPointPix + d * QPointF( std::cos( a ), std::sin( a ) ) );
    }
  }

  // Draw distance
  if ( nPoints > 1 && mAdvancedDigitizingDockWidget->constraintDistance()->isLocked() )
  {
    painter->setPen( mLockedPen );
    double r = mAdvancedDigitizingDockWidget->constraintDistance()->value() / mupp;
    painter->drawEllipse( prevPointPix, r, r );
  }

  // Draw x
  if ( mAdvancedDigitizingDockWidget->constraintX()->isLocked() )
  {
    double x = 0.0;
    bool draw = true;
    painter->setPen( mLockedPen );
    if ( mAdvancedDigitizingDockWidget->constraintX()->relative() )
    {
      if ( nPoints > 1 )
      {
        x = mAdvancedDigitizingDockWidget->constraintX()->value() / mupp + prevPointPix.x();
      }
      else
      {
        draw = false;
      }
    }
    else
    {
      x = toCanvasCoordinates( QgsPointXY( mAdvancedDigitizingDockWidget->constraintX()->value(), 0 ) ).x();
    }
    if ( draw )
    {
      painter->drawLine( QPointF( x, 0 ),
                         QPointF( x, boundingRect().height() ) );
    }
  }

  // Draw y
  if ( mAdvancedDigitizingDockWidget->constraintY()->isLocked() )
  {
    double y = 0.0;
    bool draw = true;
    painter->setPen( mLockedPen );
    if ( mAdvancedDigitizingDockWidget->constraintY()->relative() )
    {
      if ( nPoints > 1 )
      {
        // y is reversed!
        y = -mAdvancedDigitizingDockWidget->constraintY()->value() / mupp + prevPointPix.y();
      }
      else
      {
        draw = false;
      }
    }
    else
    {
      y = toCanvasCoordinates( QgsPointXY( 0, mAdvancedDigitizingDockWidget->constraintY()->value() ) ).y();
    }
    if ( draw )
    {
      painter->drawLine( QPointF( 0, y ),
                         QPointF( boundingRect().width(), y ) );
    }
  }

  // Draw constr
  if ( mAdvancedDigitizingDockWidget->additionalConstraint() == QgsAdvancedDigitizingDockWidget::NoConstraint )
  {
    if ( curPointExist && previousPointExist )
    {
      painter->setPen( mConstruction2Pen );
      painter->drawLine( prevPointPix, curPointPix );
    }

    if ( previousPointExist && penulPointExist )
    {
      painter->setPen( mConstruction1Pen );
      painter->drawLine( penulPointPix, prevPointPix );
    }
  }

  if ( curPointExist )
  {
    painter->setPen( mCursorPen );
    painter->drawLine( curPointPix + QPointF( -5, -5 ),
                       curPointPix + QPointF( +5, +5 ) );
    painter->drawLine( curPointPix + QPointF( -5, +5 ),
                       curPointPix + QPointF( +5, -5 ) );
  }


  QgsPointLocator::Match match = mAdvancedDigitizingDockWidget->mapPointMatch();
  if ( match.isValid() )
  {
    mSnapIndicator->setMatch( match );
    mSnapIndicator->setVisible( true );
  }
  else
    mSnapIndicator->setVisible( false );

}
Example #30
0
bool QgsGeometryAnalyzer::extent( QgsVectorLayer *layer,
                                  const QString &shapefileName,
                                  bool onlySelectedFeatures,
                                  QProgressDialog * )
{
  if ( !layer )
  {
    return false;
  }

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

  QgsWkbTypes::Type outputType = QgsWkbTypes::Polygon;
  QgsCoordinateReferenceSystem crs = layer->crs();

  QgsFields fields;
  fields.append( QgsField( QStringLiteral( "MINX" ), QVariant::Double ) );
  fields.append( QgsField( QStringLiteral( "MINY" ), QVariant::Double ) );
  fields.append( QgsField( QStringLiteral( "MAXX" ), QVariant::Double ) );
  fields.append( QgsField( QStringLiteral( "MAXY" ), QVariant::Double ) );
  fields.append( QgsField( QStringLiteral( "CNTX" ), QVariant::Double ) );
  fields.append( QgsField( QStringLiteral( "CNTY" ), QVariant::Double ) );
  fields.append( QgsField( QStringLiteral( "AREA" ), QVariant::Double ) );
  fields.append( QgsField( QStringLiteral( "PERIM" ), QVariant::Double ) );
  fields.append( QgsField( QStringLiteral( "HEIGHT" ), QVariant::Double ) );
  fields.append( QgsField( QStringLiteral( "WIDTH" ), QVariant::Double ) );

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

  QgsRectangle rect;
  if ( onlySelectedFeatures )  // take only selection
  {
    rect = layer->boundingBoxOfSelected();
  }
  else
  {
    rect = layer->extent();
  }

  double minx = rect.xMinimum();
  double miny = rect.yMinimum();
  double maxx = rect.xMaximum();
  double maxy = rect.yMaximum();
  double height = rect.height();
  double width = rect.width();
  double cntx = minx + ( width / 2.0 );
  double cnty = miny + ( height / 2.0 );
  double area = width * height;
  double perim = ( 2 * width ) + ( 2 * height );

  QgsFeature feat;
  QgsAttributes attrs( 10 );
  attrs[0] = QVariant( minx );
  attrs[1] = QVariant( miny );
  attrs[2] = QVariant( maxx );
  attrs[3] = QVariant( maxy );
  attrs[4] = QVariant( cntx );
  attrs[5] = QVariant( cnty );
  attrs[6] = QVariant( area );
  attrs[7] = QVariant( perim );
  attrs[8] = QVariant( height );
  attrs[9] = QVariant( width );
  feat.setAttributes( attrs );
  feat.setGeometry( QgsGeometry::fromRect( rect ) );
  vWriter.addFeature( feat );
  return true;
}