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