Exemplo n.º 1
0
QSizeF Text3DOverlay::textSize(const QString& text) const {
    auto textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
    auto extents = textRenderer->computeExtent(text);

    float maxHeight = (float)textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO;
    float pointToWorldScale = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;

    return QSizeF(extents.x, extents.y) * pointToWorldScale;
}
Exemplo n.º 2
0
void MDAL::DriverGdal::createMesh()
{
  Vertices vertices( meshGDALDataset()->mNPoints );
  bool is_longitude_shifted = initVertices( vertices );

  Faces faces( meshGDALDataset()->mNVolumes );
  initFaces( vertices, faces, is_longitude_shifted );

  mMesh.reset( new MemoryMesh(
                 name(),
                 vertices.size(),
                 faces.size(),
                 4, //maximum quads
                 computeExtent( vertices ),
                 mFileName
               )
             );
  mMesh->vertices = vertices;
  mMesh->faces = faces;
  bool proj_added = addSrcProj();
  if ( ( !proj_added ) && is_longitude_shifted )
  {
    std::string wgs84( "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" );
    mMesh->setSourceCrs( wgs84 );
  }
}
Exemplo n.º 3
0
void MDAL::DriverFlo2D::createMesh( const std::vector<CellCenter> &cells, double half_cell_size )
{
  // Create all Faces from cell centers.
  // Vertexs must be also created, they are not stored in FLO-2D files
  // try to reuse Vertexs already created for other Faces by usage of unique_Vertexs set.
  Faces faces;
  Vertices vertices;
  std::map<Vertex, size_t, VertexCompare> unique_vertices; //vertex -> id
  size_t vertex_idx = 0;

  for ( size_t i = 0; i < cells.size(); ++i )
  {
    Face e( 4 );

    for ( size_t position = 0; position < 4; ++position )
    {
      Vertex n = createVertex( position, half_cell_size, cells[i] );
      const auto iter = unique_vertices.find( n );
      if ( iter == unique_vertices.end() )
      {
        unique_vertices[n] = vertex_idx;
        vertices.push_back( n );
        e[position] = vertex_idx;
        ++vertex_idx;
      }
      else
      {
        e[position] = iter->second;
      }
    }

    faces.push_back( e );
  }

  mMesh.reset(
    new MemoryMesh(
      name(),
      vertices.size(),
      faces.size(),
      4, //maximum quads
      computeExtent( vertices ),
      mDatFileName
    )
  );
  mMesh->faces = faces;
  mMesh->vertices = vertices;
}
Exemplo n.º 4
0
bool MDAL::LoaderGdal::initVertices( Vertices &vertices )
{
  Vertex *VertexsPtr = vertices.data();
  unsigned int mXSize = meshGDALDataset()->mXSize;
  unsigned int mYSize = meshGDALDataset()->mYSize;
  const double *mGT = meshGDALDataset()->mGT;

  for ( unsigned int y = 0; y < mYSize; ++y )
  {
    for ( unsigned int x = 0; x < mXSize; ++x, ++VertexsPtr )
    {
      // VertexsPtr->setId(x + mXSize*y);
      VertexsPtr->x = mGT[0] + ( x + 0.5 ) * mGT[1] + ( y + 0.5 ) * mGT[2];
      VertexsPtr->y = mGT[3] + ( x + 0.5 ) * mGT[4] + ( y + 0.5 ) * mGT[5];
      VertexsPtr->z = 0.0;
    }
  }

  BBox extent = computeExtent( vertices );
  // we want to detect situation when there is whole earth represented in dataset
  bool is_longitude_shifted = ( extent.minX >= 0.0 ) &&
                              ( fabs( extent.minX + extent.maxX - 360.0 ) < 1.0 ) &&
                              ( extent.minY >= -90.0 ) &&
                              ( extent.maxX <= 360.0 ) &&
                              ( extent.maxX > 180.0 ) &&
                              ( extent.maxY <= 90.0 );
  if ( is_longitude_shifted )
  {
    for ( Vertices::size_type n = 0; n < vertices.size(); ++n )
    {
      if ( vertices[n].x > 180.0 )
      {
        vertices[n].x -= 360.0;
      }
    }
  }

  return is_longitude_shifted;
}
Exemplo n.º 5
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 );
}
Exemplo n.º 6
0
void QgsAtlasComposition::prepareForFeature( int featureI )
{
  if ( !mCoverageLayer )
  {
    return;
  }

  if ( mFeatureIds.size() == 0 )
  {
    emit statusMsgChanged( tr( "No matching atlas features" ) );
    return;
  }

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

  QgsExpression::setSpecialColumn( "$atlasfeatureid", mCurrentFeature.id() );
  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( *mCurrentFeature.geometry() ) );
  QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) );

  // generate filename for current feature
  evalFeatureFilename();

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

  // update shapes (in case they use data defined symbology with atlas properties)
  QList<QgsComposerShape*> shapes;
  mComposition->composerItems( shapes );
  for ( QList<QgsComposerShape*>::iterator lit = shapes.begin(); lit != shapes.end(); ++lit )
  {
    ( *lit )->update();
  }

  // update page background (in case it uses data defined symbology with atlas properties)
  QList<QgsPaperItem*> pages;
  mComposition->composerItems( pages );
  for ( QList<QgsPaperItem*>::iterator pageIt = pages.begin(); pageIt != pages.end(); ++pageIt )
  {
    ( *pageIt )->update();
  }

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

  //update composer maps

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

  //clear the transformed bounds of the previous feature
  mTransformedFeatureBounds = QgsRectangle();

  if ( atlasMaps.isEmpty() )
  {
    //no atlas enabled maps
    return;
  }

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

  //update atlas bounds of every atlas enabled composer map
  for ( QList<QgsComposerMap*>::iterator mit = atlasMaps.begin(); mit != atlasMaps.end(); ++mit )
  {
    prepareMap( *mit );
  }
}
Exemplo n.º 7
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 );
}
Exemplo n.º 8
0
bool QgsAtlasComposition::prepareForFeature( const int featureI, const bool updateMaps )
{
  if ( !mCoverageLayer )
  {
    return false;
  }

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

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

  mCurrentFeatureNo = featureI;

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

  QgsExpressionContext expressionContext = createExpressionContext();

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

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

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

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

  //update composer maps

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

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

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

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

  return true;
}
BBox Mesh::computeMeshExtent(bool projected)
{
  const Node* nodes = projected ? projectedNodes() : mNodes.constData();
  return computeExtent(nodes, mNodes.count());
}
Exemplo n.º 10
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->atlasScalingMode() == QgsComposerMap::Fixed )
  {
    // 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 if ( map->atlasScalingMode() == QgsComposerMap::Predefined )
  {
    // choose one of the predefined scales
    QgsScaleCalculator calc;
    calc.setMapUnits( composition()->mapSettings().mapUnits() );
    calc.setDpi( 25.4 );
    double scale = calc.calculate( map->extent(), map->rect().width() );
    QgsRectangle extent = map->extent();

    double n_width = extent.width(), n_height = extent.height();
    const QVector<double>& scales = mPredefinedScales;
    for ( int i = 0; i < scales.size(); i++ )
    {
      double ratio = scales[i] / scale;
      n_width = extent.width() * ratio;
      n_height = extent.height() * ratio;
      if ( (n_width >= new_extent.width()) && (n_height >= new_extent.height()) ) {
        // this is the smallest extent that embeds the feature, stop here
        break;
      }
    }

    // compute new extent, centered on feature
    double geom_center_x = ( xa1 + xa2 ) / 2.0;
    double geom_center_y = ( ya1 + ya2 ) / 2.0;
    double xx = geom_center_x - n_width / 2.0;
    double yy = geom_center_y - n_height / 2.0;
    new_extent = QgsRectangle( xx,
                               yy,
                               xx + n_width,
                               yy + n_height );
  }
  else if ( map->atlasScalingMode() == QgsComposerMap::Auto )
  {
    // 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 );
}
Exemplo n.º 11
0
bool QgsAtlasComposition::prepareForFeature( int featureI )
{
  if ( !mCoverageLayer )
  {
    return false;
  }

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

  mCurrentFeatureNo = featureI;

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

  QgsExpression::setSpecialColumn( "$atlasfeatureid", mCurrentFeature.id() );
  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( *mCurrentFeature.geometry() ) );
  QgsExpression::setSpecialColumn( "$atlasfeature", QVariant::fromValue( mCurrentFeature ) );
  QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) );

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

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

  //update composer maps

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

  //clear the transformed bounds of the previous feature
  mTransformedFeatureBounds = QgsRectangle();

  if ( atlasMaps.isEmpty() )
  {
    //no atlas enabled maps
    return true;
  }

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

  //update atlas bounds of every atlas enabled composer map
  for ( QList<QgsComposerMap*>::iterator mit = atlasMaps.begin(); mit != atlasMaps.end(); ++mit )
  {
    prepareMap( *mit );
  }

  return true;
}