bool QgsLabelSearchTree::insertLabel( LabelPosition* labelPos, int featureId, const QString& layerName, bool diagram, bool frozen ) { if ( !labelPos ) { return false; } double c_min[2]; double c_max[2]; labelPos->getBoundingBox( c_min, c_max ); QVector<QgsPoint> cornerPoints; for ( int i = 0; i < 4; ++i ) { cornerPoints.push_back( QgsPoint( labelPos->getX( i ), labelPos->getY( i ) ) ); } QgsLabelPosition* newEntry = new QgsLabelPosition( featureId, labelPos->getAlpha(), cornerPoints, QgsRectangle( c_min[0], c_min[1], c_max[0], c_max[1] ), labelPos->getWidth(), labelPos->getHeight(), layerName, labelPos->getUpsideDown(), diagram, frozen ); mSpatialIndex.Insert( c_min, c_max, newEntry ); return true; }
QgsRectangle QgsRasterCalcDialog::outputRectangle() const { return QgsRectangle( mXMinSpinBox->value(), mYMinSpinBox->value(), mXMaxSpinBox->value(), mYMaxSpinBox->value() ); }
QgsGrassRasterProvider::QgsGrassRasterProvider( QString const &uri ) : QgsRasterDataProvider( uri ) , mValid( false ) , mGrassDataType( 0 ) , mCols( 0 ) , mRows( 0 ) , mYBlockSize( 0 ) , mNoDataValue( std::numeric_limits<double>::quiet_NaN() ) { QgsDebugMsg( "QgsGrassRasterProvider: constructing with uri '" + uri + "'." ); if ( !QgsGrass::init() ) { return; } // Parse URI, it is the same like using GDAL, i.e. path to raster cellhd, i.e. // /path/to/gisdbase/location/mapset/cellhd/map QFileInfo fileInfo( uri ); if ( !fileInfo.exists() ) // then we keep it valid forever { appendError( ERR( tr( "cellhd file %1 does not exist" ).arg( uri ) ) ); return; } mMapName = fileInfo.fileName(); QDir dir = fileInfo.dir(); QString element = dir.dirName(); if ( element != QLatin1String( "cellhd" ) ) { appendError( ERR( tr( "Groups not yet supported" ) ) ); return; } dir.cdUp(); // skip cellhd mMapset = dir.dirName(); dir.cdUp(); mLocation = dir.dirName(); dir.cdUp(); mGisdbase = dir.path(); QgsDebugMsg( QString( "gisdbase: %1" ).arg( mGisdbase ) ); QgsDebugMsg( QString( "location: %1" ).arg( mLocation ) ); QgsDebugMsg( QString( "mapset: %1" ).arg( mMapset ) ); QgsDebugMsg( QString( "mapName: %1" ).arg( mMapName ) ); mTimestamp = dataTimestamp(); mRasterValue.set( mGisdbase, mLocation, mMapset, mMapName ); //mValidNoDataValue = true; QString error; mCrs = QgsGrass::crs( mGisdbase, mLocation, error ); appendIfError( error ); QgsDebugMsg( "mCrs: " + mCrs.toWkt() ); // the block size can change of course when the raster is overridden // ibut it is only called once when statistics are calculated error.clear(); QgsGrass::size( mGisdbase, mLocation, mMapset, mMapName, &mCols, &mRows, error ); appendIfError( error ); error.clear(); mInfo = QgsGrass::info( mGisdbase, mLocation, mMapset, mMapName, QgsGrassObject::Raster, QStringLiteral( "info" ), QgsRectangle(), 0, 0, 3000, error ); appendIfError( error ); mGrassDataType = mInfo[QStringLiteral( "TYPE" )].toInt(); QgsDebugMsg( "mGrassDataType = " + QString::number( mGrassDataType ) ); // TODO: avoid showing these strange numbers in GUI // TODO: don't save no data values in project file, add a flag if value was defined by user double myInternalNoDataValue; if ( mGrassDataType == CELL_TYPE ) { myInternalNoDataValue = INT_MIN; } else if ( mGrassDataType == DCELL_TYPE ) { // Don't use numeric limits, raster layer is using // qAbs( myValue - mNoDataValue ) <= TINY_VALUE // if the mNoDataValue would be a limit, the subtraction could overflow. // No data value is shown in GUI, use some nice number. // Choose values with small representation error. // limit: 1.7976931348623157e+308 //myInternalNoDataValue = -1e+300; myInternalNoDataValue = std::numeric_limits<double>::quiet_NaN(); } else { if ( mGrassDataType != FCELL_TYPE ) { QgsDebugMsg( "unexpected data type" ); } // limit: 3.40282347e+38 //myInternalNoDataValue = -1e+30; myInternalNoDataValue = std::numeric_limits<float>::quiet_NaN(); } mNoDataValue = myInternalNoDataValue; mSrcHasNoDataValue.append( true ); mSrcNoDataValue.append( mNoDataValue ); mUseSrcNoDataValue.append( true ); QgsDebugMsg( QString( "myInternalNoDataValue = %1" ).arg( myInternalNoDataValue ) ); // TODO: refresh mRows and mCols if raster was rewritten // We have to decide some reasonable block size, not to big to occupate too much // memory, not too small to result in too many calls to readBlock -> qgis.d.rast // for statistics int typeSize = dataTypeSize( dataType( 1 ) ); if ( mCols > 0 && typeSize > 0 ) { const int cache_size = 10000000; // ~ 10 MB mYBlockSize = cache_size / typeSize / mCols; if ( mYBlockSize > mRows ) { mYBlockSize = mRows; } QgsDebugMsg( "mYBlockSize = " + QString::number( mYBlockSize ) ); mValid = true; } }
void QgsVectorDataProvider::fillMinMaxCache() { if ( !mCacheMinMaxDirty ) return; const QgsFieldMap& flds = fields(); for ( QgsFieldMap::const_iterator it = flds.begin(); it != flds.end(); ++it ) { if ( it->type() == QVariant::Int ) { mCacheMinValues[it.key()] = QVariant( INT_MAX ); mCacheMaxValues[it.key()] = QVariant( INT_MIN ); } else if ( it->type() == QVariant::Double ) { mCacheMinValues[it.key()] = QVariant( DBL_MAX ); mCacheMaxValues[it.key()] = QVariant( -DBL_MAX ); } else { mCacheMinValues[it.key()] = QVariant(); mCacheMaxValues[it.key()] = QVariant(); } } QgsFeature f; QgsAttributeList keys = mCacheMinValues.keys(); select( keys, QgsRectangle(), false ); while ( nextFeature( f ) ) { QgsAttributeMap attrMap = f.attributeMap(); for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it ) { const QVariant& varValue = attrMap[*it]; if ( flds[*it].type() == QVariant::Int ) { int value = varValue.toInt(); if ( value < mCacheMinValues[*it].toInt() ) mCacheMinValues[*it] = value; if ( value > mCacheMaxValues[*it].toInt() ) mCacheMaxValues[*it] = value; } else if ( flds[*it].type() == QVariant::Double ) { double value = varValue.toDouble(); if ( value < mCacheMinValues[*it].toDouble() ) mCacheMinValues[*it] = value; if ( value > mCacheMaxValues[*it].toDouble() ) mCacheMaxValues[*it] = value; } else { QString value = varValue.toString(); if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() ) { mCacheMinValues[*it] = value; } if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() ) { mCacheMaxValues[*it] = value; } } } } mCacheMinMaxDirty = false; }
ErrorList topolTest::runTest( const QString& testName, QgsVectorLayer* layer1, QgsVectorLayer* layer2, ValidateType type, double tolerance ) { QgsDebugMsg( QString( "Running test %1" ).arg( testName ) ); ErrorList errors; if ( !layer1 ) { QgsMessageLog::logMessage( tr( "First layer not found in registry." ), tr( "Topology plugin" ) ); return errors; } if ( !layer2 && mTopologyRuleMap[testName].useSecondLayer ) { QgsMessageLog::logMessage( tr( "Second layer not found in registry." ), tr( "Topology plugin" ) ); return errors; } QString secondLayerId; mFeatureList1.clear(); mFeatureMap2.clear(); //checking if new features are not //being recognised due to indexing not being upto date mLayerIndexes.clear(); if ( mTopologyRuleMap[testName].useSecondLayer ) { // validate all features or current extent QgsRectangle extent; if ( type == ValidateExtent ) { extent = theQgsInterface->mapCanvas()->extent(); } else { extent = QgsRectangle(); } fillFeatureList( layer1, extent ); //fillFeatureMap( layer1, extent ); QString secondLayerId = layer2->id(); if ( !mLayerIndexes.contains( layer2->id() ) ) { mLayerIndexes[layer2->id()] = createIndex( layer2, extent ); } } else { // validate all features or current extent QgsRectangle extent; if ( type == ValidateExtent ) { extent = theQgsInterface->mapCanvas()->extent(); if ( mTopologyRuleMap[testName].useSpatialIndex ) { mLayerIndexes[layer1->id()] = createIndex( layer1, theQgsInterface->mapCanvas()->extent() ); } else { fillFeatureList( layer1, extent ); } } else { if ( mTopologyRuleMap[testName].useSpatialIndex ) { if ( !mLayerIndexes.contains( layer1->id() ) ) { mLayerIndexes[layer1->id()] = createIndex( layer1, QgsRectangle() ); } } else { fillFeatureList( layer1, QgsRectangle() ); } } } //call test routine bool isValidatingExtent; if ( type == ValidateExtent ) { isValidatingExtent = true; } else { isValidatingExtent = false; } return ( this->*( mTopologyRuleMap[testName].f ) )( tolerance, layer1, layer2, isValidatingExtent ); }
bool QgsGeometryAnalyzer::buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance, bool onlySelectedFeatures, bool dissolve, int bufferDistanceField, QProgressDialog* p ) { if ( !layer ) { return false; } QgsVectorDataProvider* dp = layer->dataProvider(); if ( !dp ) { return false; } QGis::WkbType outputType = QGis::WKBPolygon; if ( dissolve ) { outputType = QGis::WKBMultiPolygon; } const QgsCoordinateReferenceSystem crs = layer->crs(); QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs ); QgsFeature currentFeature; QgsGeometry *dissolveGeometry = 0; //dissolve geometry (if dissolve enabled) //take only selection if ( onlySelectedFeatures ) { //use QgsVectorLayer::featureAtId const QgsFeatureIds selection = layer->selectedFeaturesIds(); if ( p ) { p->setMaximum( selection.size() ); } int processedFeatures = 0; QgsFeatureIds::const_iterator it = selection.constBegin(); for ( ; it != selection.constEnd(); ++it ) { if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { break; } if ( !layer->featureAtId( *it, currentFeature, true, true ) ) { continue; } bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField ); ++processedFeatures; } if ( p ) { p->setValue( selection.size() ); } } //take all features else { layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false ); int featureCount = layer->featureCount(); if ( p ) { p->setMaximum( featureCount ); } int processedFeatures = 0; while ( layer->nextFeature( currentFeature ) ) { if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { break; } bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField ); ++processedFeatures; } if ( p ) { p->setValue( featureCount ); } } if ( dissolve ) { QgsFeature dissolveFeature; if ( !dissolveGeometry ) { QgsDebugMsg( "no dissolved geometry - should not happen" ); return false; } dissolveFeature.setGeometry( dissolveGeometry ); vWriter.addFeature( dissolveFeature ); } return true; }
QgsRectangle QgsCoordinateTransform::transformBoundingBox( const QgsRectangle &rect, TransformDirection direction, const bool handle180Crossover ) const { // Calculate the bounding box of a QgsRectangle in the source CRS // when projected to the destination CRS (or the inverse). // This is done by looking at a number of points spread evenly // across the rectangle if ( !d->mIsValid || d->mShortCircuit ) return rect; if ( rect.isEmpty() ) { QgsPointXY p = transform( rect.xMinimum(), rect.yMinimum(), direction ); return QgsRectangle( p, p ); } // 64 points (<=2.12) is not enough, see #13665, for EPSG:4326 -> EPSG:3574 (say that it is a hard one), // are decent result from about 500 points and more. This method is called quite often, but // even with 1000 points it takes < 1ms // TODO: how to effectively and precisely reproject bounding box? const int nPoints = 1000; double d = std::sqrt( ( rect.width() * rect.height() ) / std::pow( std::sqrt( static_cast< double >( nPoints ) ) - 1, 2.0 ) ); int nXPoints = static_cast< int >( std::ceil( rect.width() / d ) ) + 1; int nYPoints = static_cast< int >( std::ceil( rect.height() / d ) ) + 1; QgsRectangle bb_rect; bb_rect.setMinimal(); // We're interfacing with C-style vectors in the // end, so let's do C-style vectors here too. QVector<double> x( nXPoints * nYPoints ); QVector<double> y( nXPoints * nYPoints ); QVector<double> z( nXPoints * nYPoints ); QgsDebugMsgLevel( QStringLiteral( "Entering transformBoundingBox..." ), 4 ); // Populate the vectors double dx = rect.width() / static_cast< double >( nXPoints - 1 ); double dy = rect.height() / static_cast< double >( nYPoints - 1 ); double pointY = rect.yMinimum(); for ( int i = 0; i < nYPoints ; i++ ) { // Start at right edge double pointX = rect.xMinimum(); for ( int j = 0; j < nXPoints; j++ ) { x[( i * nXPoints ) + j] = pointX; y[( i * nXPoints ) + j] = pointY; // and the height... z[( i * nXPoints ) + j] = 0.0; // QgsDebugMsg(QString("BBox coord: (%1, %2)").arg(x[(i*numP) + j]).arg(y[(i*numP) + j])); pointX += dx; } pointY += dy; } // Do transformation. Any exception generated must // be handled in above layers. try { transformCoords( nXPoints * nYPoints, x.data(), y.data(), z.data(), direction ); } catch ( const QgsCsException & ) { // rethrow the exception QgsDebugMsg( QStringLiteral( "rethrowing exception" ) ); throw; } // Calculate the bounding box and use that for the extent for ( int i = 0; i < nXPoints * nYPoints; i++ ) { if ( !std::isfinite( x[i] ) || !std::isfinite( y[i] ) ) { continue; } if ( handle180Crossover ) { //if crossing the date line, temporarily add 360 degrees to -ve longitudes bb_rect.combineExtentWith( x[i] >= 0.0 ? x[i] : x[i] + 360.0, y[i] ); } else { bb_rect.combineExtentWith( x[i], y[i] ); } } if ( bb_rect.isNull() ) { // something bad happened when reprojecting the filter rect... no finite points were left! throw QgsCsException( QObject::tr( "Could not transform bounding box to target CRS" ) ); } if ( handle180Crossover ) { //subtract temporary addition of 360 degrees from longitudes if ( bb_rect.xMinimum() > 180.0 ) bb_rect.setXMinimum( bb_rect.xMinimum() - 360.0 ); if ( bb_rect.xMaximum() > 180.0 ) bb_rect.setXMaximum( bb_rect.xMaximum() - 360.0 ); } QgsDebugMsgLevel( "Projected extent: " + bb_rect.toString(), 4 ); if ( bb_rect.isEmpty() ) { QgsDebugMsgLevel( "Original extent: " + rect.toString(), 4 ); } return bb_rect; }
QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value ) { if ( !vl ) return 0; QWidget *myWidget = 0; QgsVectorLayer::EditType editType = vl->editType( idx ); const QgsField &field = vl->pendingFields()[idx]; QVariant::Type myFieldType = field.type(); switch ( editType ) { case QgsVectorLayer::UniqueValues: { QList<QVariant> values; vl->dataProvider()->uniqueValues( idx, values ); QComboBox *cb = comboBox( editor, parent ); if ( cb ) { cb->setEditable( false ); for ( QList<QVariant>::iterator it = values.begin(); it != values.end(); it++ ) cb->addItem( it->toString(), it->toString() ); myWidget = cb; } } break; case QgsVectorLayer::Enumeration: { QStringList enumValues; vl->dataProvider()->enumValues( idx, enumValues ); QComboBox *cb = comboBox( editor, parent ); if ( cb ) { QStringList::const_iterator s_it = enumValues.constBegin(); for ( ; s_it != enumValues.constEnd(); ++s_it ) { cb->addItem( *s_it, *s_it ); } myWidget = cb; } } break; case QgsVectorLayer::ValueMap: { const QMap<QString, QVariant> &map = vl->valueMap( idx ); QComboBox *cb = comboBox( editor, parent ); if ( cb ) { for ( QMap<QString, QVariant>::const_iterator it = map.begin(); it != map.end(); it++ ) { cb->addItem( it.key(), it.value() ); } myWidget = cb; } } break; case QgsVectorLayer::ValueRelation: { QSettings settings; QString nullValue = settings.value( "qgis/nullValue", "NULL" ).toString(); const QgsVectorLayer::ValueRelationData &data = vl->valueRelation( idx ); QgsVectorLayer *layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( data.mLayer ) ); QMap< QString, QString > map; int fi = -1; if ( layer ) { int ki = layer->fieldNameIndex( data.mOrderByValue ? data.mValue : data.mKey ); int vi = layer->fieldNameIndex( data.mOrderByValue ? data.mKey : data.mValue ); if ( !data.mFilterAttributeColumn.isNull() ) fi = layer->fieldNameIndex( data.mFilterAttributeColumn ); if ( data.mAllowNull ) map.insert( nullValue, tr( "(no selection)" ) ); if ( ki >= 0 && vi >= 0 ) { QgsAttributeList attributes; attributes << ki; attributes << vi; if ( fi >= 0 ) attributes << fi; layer->select( attributes, QgsRectangle(), false ); QgsFeature f; while ( layer->nextFeature( f ) ) { if ( fi >= 0 && f.attributeMap()[ fi ].toString() != data.mFilterAttributeValue ) continue; map.insert( f.attributeMap()[ ki ].toString(), f.attributeMap()[ vi ].toString() ); } } } if ( !data.mAllowMulti ) { QComboBox *cb = comboBox( editor, parent ); if ( cb ) { for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); it++ ) { if ( data.mOrderByValue ) cb->addItem( it.key(), it.value() ); else cb->addItem( it.value(), it.key() ); } myWidget = cb; } } else { QListWidget *lw = listWidget( editor, parent ); if ( lw ) { QStringList checkList = value.toString().remove( QChar( '{' ) ).remove( QChar( '}' ) ).split( "," ); for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); it++ ) { QListWidgetItem *item; if ( data.mOrderByValue ) { item = new QListWidgetItem( it.key() ); item->setData( Qt::UserRole, it.value() ); item->setCheckState( checkList.contains( it.value() ) ? Qt::Checked : Qt::Unchecked ); } else { item = new QListWidgetItem( it.value() ); item->setData( Qt::UserRole, it.key() ); item->setCheckState( checkList.contains( it.key() ) ? Qt::Checked : Qt::Unchecked ); } lw->addItem( item ); } myWidget = lw; } } } break; case QgsVectorLayer::Classification: { QMap<QString, QString> classes; const QgsUniqueValueRenderer *uvr = dynamic_cast<const QgsUniqueValueRenderer *>( vl->renderer() ); if ( uvr ) { const QList<QgsSymbol *> symbols = uvr->symbols(); for ( int i = 0; i < symbols.size(); i++ ) { QString label = symbols[i]->label(); QString name = symbols[i]->lowerValue(); if ( label == "" ) label = name; classes.insert( name, label ); } } const QgsCategorizedSymbolRendererV2 *csr = dynamic_cast<const QgsCategorizedSymbolRendererV2 *>( vl->rendererV2() ); if ( csr ) { const QgsCategoryList &categories = (( QgsCategorizedSymbolRendererV2 * )csr )->categories(); // FIXME: QgsCategorizedSymbolRendererV2::categories() should be const for ( int i = 0; i < categories.size(); i++ ) { QString label = categories[i].label(); QString value = categories[i].value().toString(); if ( label.isEmpty() ) label = value; classes.insert( value, label ); } } QComboBox *cb = comboBox( editor, parent ); if ( cb ) { for ( QMap<QString, QString>::const_iterator it = classes.begin(); it != classes.end(); it++ ) { cb->addItem( it.value(), it.key() ); } myWidget = cb; } } break; case QgsVectorLayer::DialRange: case QgsVectorLayer::SliderRange: case QgsVectorLayer::EditRange: { if ( myFieldType == QVariant::Int ) { int min = vl->range( idx ).mMin.toInt(); int max = vl->range( idx ).mMax.toInt(); int step = vl->range( idx ).mStep.toInt(); if ( editType == QgsVectorLayer::EditRange ) { QSpinBox *sb = 0; if ( editor ) sb = qobject_cast<QSpinBox *>( editor ); else sb = new QSpinBox( parent ); if ( sb ) { sb->setRange( min, max ); sb->setSingleStep( step ); myWidget = sb; } } else { QAbstractSlider *sl = 0; if ( editor ) { sl = qobject_cast<QAbstractSlider*>( editor ); } else if ( editType == QgsVectorLayer::DialRange ) { sl = new QDial( parent ); } else { sl = new QSlider( Qt::Horizontal, parent ); } if ( sl ) { sl->setRange( min, max ); sl->setSingleStep( step ); myWidget = sl; } } break; } else if ( myFieldType == QVariant::Double ) { QDoubleSpinBox *dsb = 0; if ( editor ) dsb = qobject_cast<QDoubleSpinBox*>( editor ); else dsb = new QDoubleSpinBox( parent ); if ( dsb ) { double min = vl->range( idx ).mMin.toDouble(); double max = vl->range( idx ).mMax.toDouble(); double step = vl->range( idx ).mStep.toDouble(); dsb->setRange( min, max ); dsb->setSingleStep( step ); myWidget = dsb; } break; } } case QgsVectorLayer::CheckBox: { QCheckBox *cb = 0; if ( editor ) cb = qobject_cast<QCheckBox*>( editor ); else cb = new QCheckBox( parent ); if ( cb ) { myWidget = cb; break; } } // fall-through case QgsVectorLayer::LineEdit: case QgsVectorLayer::TextEdit: case QgsVectorLayer::UuidGenerator: case QgsVectorLayer::UniqueValuesEditable: case QgsVectorLayer::Immutable: { QLineEdit *le = 0; QTextEdit *te = 0; QPlainTextEdit *pte = 0; if ( editor ) { le = qobject_cast<QLineEdit *>( editor ); te = qobject_cast<QTextEdit *>( editor ); pte = qobject_cast<QPlainTextEdit *>( editor ); } else if ( editType == QgsVectorLayer::TextEdit ) { pte = new QPlainTextEdit( parent ); } else { le = new QLineEdit( parent ); } if ( le ) { if ( editType == QgsVectorLayer::UniqueValuesEditable ) { QList<QVariant> values; vl->dataProvider()->uniqueValues( idx, values ); QStringList svalues; for ( QList<QVariant>::const_iterator it = values.begin(); it != values.end(); it++ ) svalues << it->toString(); QCompleter *c = new QCompleter( svalues ); c->setCompletionMode( QCompleter::PopupCompletion ); le->setCompleter( c ); } if ( editType == QgsVectorLayer::UuidGenerator ) { le->setReadOnly( true ); } le->setValidator( new QgsFieldValidator( le, field ) ); myWidget = le; } if ( te ) { te->setAcceptRichText( true ); myWidget = te; } if ( pte ) { myWidget = pte; } if ( myWidget ) { myWidget->setDisabled( editType == QgsVectorLayer::Immutable ); } } break; case QgsVectorLayer::Hidden: myWidget = 0; break; case QgsVectorLayer::FileName: case QgsVectorLayer::Calendar: { QPushButton *pb = 0; QLineEdit *le = qobject_cast<QLineEdit *>( editor ); if ( le ) { if ( le ) myWidget = le; if ( editor->parent() ) { pb = editor->parent()->findChild<QPushButton *>(); } } else { le = new QLineEdit(); pb = new QPushButton( tr( "..." ) ); QHBoxLayout *hbl = new QHBoxLayout(); hbl->addWidget( le ); hbl->addWidget( pb ); myWidget = new QWidget( parent ); myWidget->setBackgroundRole( QPalette::Window ); myWidget->setAutoFillBackground( true ); myWidget->setLayout( hbl ); } if ( pb ) { if ( editType == QgsVectorLayer::FileName ) connect( pb, SIGNAL( clicked() ), new QgsAttributeEditor( pb ), SLOT( selectFileName() ) ); if ( editType == QgsVectorLayer::Calendar ) connect( pb, SIGNAL( clicked() ), new QgsAttributeEditor( pb ), SLOT( selectDate() ) ); } } break; } setValue( myWidget, vl, idx, value ); return myWidget; }
QgsRectangle QgsAlignRaster::clipExtent() const { return QgsRectangle( mClipExtent[0], mClipExtent[1], mClipExtent[2], mClipExtent[3] ); }
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; }
void QgsAtlasComposition::prepareMap( QgsComposerMap* map ) { if ( !map->atlasDriven() || mCoverageLayer->wkbType() == QGis::WKBNoGeometry ) { return; } if ( mTransformedFeatureBounds.isEmpty() ) { //transformed extent of current feature hasn't been calculated yet. This can happen if //a map has been set to be atlas controlled after prepare feature was called computeExtent( map ); } double xa1 = mTransformedFeatureBounds.xMinimum(); double xa2 = mTransformedFeatureBounds.xMaximum(); double ya1 = mTransformedFeatureBounds.yMinimum(); double ya2 = mTransformedFeatureBounds.yMaximum(); QgsRectangle newExtent = mTransformedFeatureBounds; QgsRectangle mOrigExtent( map->extent() ); //sanity check - only allow fixed scale mode for point layers bool isPointLayer = false; switch ( mCoverageLayer->wkbType() ) { case QGis::WKBPoint: case QGis::WKBPoint25D: case QGis::WKBMultiPoint: case QGis::WKBMultiPoint25D: isPointLayer = true; break; default: isPointLayer = false; break; } if ( map->atlasScalingMode() == QgsComposerMap::Fixed || map->atlasScalingMode() == QgsComposerMap::Predefined || isPointLayer ) { QgsScaleCalculator calc; calc.setMapUnits( composition()->mapSettings().mapUnits() ); calc.setDpi( 25.4 ); double originalScale = calc.calculate( mOrigExtent, map->rect().width() ); double geomCenterX = ( xa1 + xa2 ) / 2.0; double geomCenterY = ( ya1 + ya2 ) / 2.0; if ( map->atlasScalingMode() == QgsComposerMap::Fixed || isPointLayer ) { // only translate, keep the original scale (i.e. width x height) double xMin = geomCenterX - mOrigExtent.width() / 2.0; double yMin = geomCenterY - mOrigExtent.height() / 2.0; newExtent = QgsRectangle( xMin, yMin, xMin + mOrigExtent.width(), yMin + mOrigExtent.height() ); //scale newExtent to match original scale of map //this is required for geographic coordinate systems, where the scale varies by extent double newScale = calc.calculate( newExtent, map->rect().width() ); newExtent.scale( originalScale / newScale ); } else if ( map->atlasScalingMode() == QgsComposerMap::Predefined ) { // choose one of the predefined scales double newWidth = mOrigExtent.width(); double newHeight = mOrigExtent.height(); const QVector<qreal>& scales = mPredefinedScales; for ( int i = 0; i < scales.size(); i++ ) { double ratio = scales[i] / originalScale; newWidth = mOrigExtent.width() * ratio; newHeight = mOrigExtent.height() * ratio; // compute new extent, centered on feature double xMin = geomCenterX - newWidth / 2.0; double yMin = geomCenterY - newHeight / 2.0; newExtent = QgsRectangle( xMin, yMin, xMin + newWidth, yMin + newHeight ); //scale newExtent to match desired map scale //this is required for geographic coordinate systems, where the scale varies by extent double newScale = calc.calculate( newExtent, map->rect().width() ); newExtent.scale( scales[i] / newScale ); if (( newExtent.width() >= mTransformedFeatureBounds.width() ) && ( newExtent.height() >= mTransformedFeatureBounds.height() ) ) { // this is the smallest extent that embeds the feature, stop here break; } } } } else if ( map->atlasScalingMode() == QgsComposerMap::Auto ) { // auto scale double geomRatio = mTransformedFeatureBounds.width() / mTransformedFeatureBounds.height(); double mapRatio = mOrigExtent.width() / mOrigExtent.height(); // geometry height is too big if ( geomRatio < mapRatio ) { // extent the bbox's width double adjWidth = ( mapRatio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0; xa1 -= adjWidth; xa2 += adjWidth; } // geometry width is too big else if ( geomRatio > mapRatio ) { // extent the bbox's height double adjHeight = ( mTransformedFeatureBounds.width() / mapRatio - mTransformedFeatureBounds.height() ) / 2.0; ya1 -= adjHeight; ya2 += adjHeight; } newExtent = QgsRectangle( xa1, ya1, xa2, ya2 ); if ( map->atlasMargin() > 0.0 ) { newExtent.scale( 1 + map->atlasMargin() ); } } // set the new extent (and render) map->setNewAtlasFeatureExtent( newExtent ); }
QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer( QgsVectorLayer* vlayer, QString attrName, int classes, Mode mode, QgsSymbolV2* symbol, QgsVectorColorRampV2* ramp ) { if ( classes < 1 ) return NULL; int attrNum = vlayer->fieldNameIndex( attrName ); double minimum = vlayer->minimumValue( attrNum ).toDouble(); double maximum = vlayer->maximumValue( attrNum ).toDouble(); QgsDebugMsg( QString( "min %1 // max %2" ).arg( minimum ).arg( maximum ) ); QList<double> breaks; QList<int> labels; if ( mode == EqualInterval ) { breaks = _calcEqualIntervalBreaks( minimum, maximum, classes ); } else if ( mode == Pretty ) { breaks = _calcPrettyBreaks( minimum, maximum, classes ); } else if ( mode == Quantile || mode == Jenks || mode == StdDev ) { // get values from layer QList<double> values; QgsFeature f; QgsAttributeList lst; lst.append( attrNum ); vlayer->select( lst, QgsRectangle(), false ); while ( vlayer->nextFeature( f ) ) values.append( f.attributeMap()[attrNum].toDouble() ); // calculate the breaks if ( mode == Quantile ) { breaks = _calcQuantileBreaks( values, classes ); } else if ( mode == Jenks ) { breaks = _calcJenksBreaks( values, classes, minimum, maximum ); } else if ( mode == StdDev ) { breaks = _calcStdDevBreaks( values, classes, labels ); } } else { Q_ASSERT( false ); } QgsRangeList ranges; double lower, upper = minimum; QString label; // "breaks" list contains all values at class breaks plus maximum as last break int i = 0; for ( QList<double>::iterator it = breaks.begin(); it != breaks.end(); ++it, ++i ) { lower = upper; // upper border from last interval upper = *it; if ( mode == StdDev ) { if ( i == 0 ) { label = "< " + QString::number( labels[i], 'i', 0 ) + " Std Dev"; } else if ( i == labels.count() - 1 ) { label = ">= " + QString::number( labels[i-1], 'i', 0 ) + " Std Dev"; } else { label = QString::number( labels[i-1], 'i', 0 ) + " Std Dev" + " - " + QString::number( labels[i], 'i', 0 ) + " Std Dev"; } } else { label = QString::number( lower, 'f', 4 ) + " - " + QString::number( upper, 'f', 4 ); } QgsSymbolV2* newSymbol = symbol->clone(); double colorValue = ( breaks.count() > 1 ? ( double ) i / ( breaks.count() - 1 ) : 0 ); newSymbol->setColor( ramp->color( colorValue ) ); // color from (0 / cl-1) to (cl-1 / cl-1) ranges.append( QgsRendererRangeV2( lower, upper, newSymbol, label ) ); } QgsGraduatedSymbolRendererV2* r = new QgsGraduatedSymbolRendererV2( attrName, ranges ); r->setSourceSymbol( symbol->clone() ); r->setSourceColorRamp( ramp->clone() ); r->setMode( mode ); return r; }
void QgsFieldCalculator::accept() { if ( mVectorLayer && mVectorLayer->isEditable() ) { QString calcString = mExpressionTextEdit->toPlainText(); //create QgsExpression QgsExpression exp( calcString ); if ( exp.hasParserError() ) { //expression not valid QMessageBox::critical( 0, tr( "Syntax error" ), tr( QString( "Invalid expression syntax. The error message of the parser is: '" + exp.parserErrorString() + "'" ).toLocal8Bit().data() ) ); return; } if ( ! exp.prepare( mVectorLayer->pendingFields() ) ) { QMessageBox::critical( 0, tr( "Evaluation error" ), exp.evalErrorString() ); return; } mVectorLayer->beginEditCommand( "Field calculator" ); //update existing field if ( mUpdateExistingFieldCheckBox->checkState() == Qt::Checked ) { QMap<QString, int>::const_iterator fieldIt = mFieldMap.find( mExistingFieldComboBox->currentText() ); if ( fieldIt != mFieldMap.end() ) { mAttributeId = fieldIt.value(); } } //create new field else { //create new field QgsField newField( mOutputFieldNameLineEdit->text(), ( QVariant::Type ) mOutputFieldTypeComboBox->itemData( mOutputFieldTypeComboBox->currentIndex(), Qt::UserRole ).toInt(), mOutputFieldTypeComboBox->itemData( mOutputFieldTypeComboBox->currentIndex(), Qt::UserRole + 1 ).toString(), mOuputFieldWidthSpinBox->value(), mOutputFieldPrecisionSpinBox->value() ); if ( !mVectorLayer->addAttribute( newField ) ) { QMessageBox::critical( 0, tr( "Provider error" ), tr( "Could not add the new field to the provider." ) ); mVectorLayer->destroyEditCommand(); return; } //get index of the new field const QgsFieldMap fieldList = mVectorLayer->pendingFields(); QgsFieldMap::const_iterator it = fieldList.constBegin(); for ( ; it != fieldList.constEnd(); ++it ) { if ( it.value().name() == mOutputFieldNameLineEdit->text() ) { mAttributeId = it.key(); break; } } } if ( mAttributeId == -1 ) { mVectorLayer->destroyEditCommand(); return; } //go through all the features and change the new attribute QgsFeature feature; bool calculationSuccess = true; QString error; bool onlySelected = ( mOnlyUpdateSelectedCheckBox->checkState() == Qt::Checked ); QgsFeatureIds selectedIds = mVectorLayer->selectedFeaturesIds(); // block layerModified signals (that would trigger table update) mVectorLayer->blockSignals( true ); bool useGeometry = exp.needsGeometry(); int rownum = 1; mVectorLayer->select( mVectorLayer->pendingAllAttributesList(), QgsRectangle(), useGeometry, false ); while ( mVectorLayer->nextFeature( feature ) ) { if ( onlySelected ) { if ( !selectedIds.contains( feature.id() ) ) { continue; } } exp.setCurrentRowNumber( rownum ); QVariant value = exp.evaluate( &feature ); if ( exp.hasEvalError() ) { calculationSuccess = false; error = exp.evalErrorString(); break; } else { mVectorLayer->changeAttributeValue( feature.id(), mAttributeId, value, false ); } rownum++; } // stop blocking layerModified signals and make sure that one layerModified signal is emitted mVectorLayer->blockSignals( false ); mVectorLayer->setModified( true, false ); if ( !calculationSuccess ) { QMessageBox::critical( 0, tr( "Error" ), tr( "An error occured while evaluating the calculation string:\n%1" ).arg( error ) ); mVectorLayer->destroyEditCommand(); return; } mVectorLayer->endEditCommand(); } QDialog::accept(); }
void QgsWfsCapabilities::capabilitiesReplyFinished() { const QByteArray &buffer = mResponse; QgsDebugMsg( "parsing capabilities: " + buffer ); // parse XML QString capabilitiesDocError; QDomDocument capabilitiesDocument; if ( !capabilitiesDocument.setContent( buffer, true, &capabilitiesDocError ) ) { mErrorCode = QgsWfsRequest::XmlError; mErrorMessage = capabilitiesDocError; emit gotCapabilities(); return; } QDomElement doc = capabilitiesDocument.documentElement(); // handle exceptions if ( doc.tagName() == QLatin1String( "ExceptionReport" ) ) { QDomNode ex = doc.firstChild(); QString exc = ex.toElement().attribute( QStringLiteral( "exceptionCode" ), QStringLiteral( "Exception" ) ); QDomElement ext = ex.firstChild().toElement(); mErrorCode = QgsWfsRequest::ServerExceptionError; mErrorMessage = exc + ": " + ext.firstChild().nodeValue(); emit gotCapabilities(); return; } mCaps.clear(); //test wfs version mCaps.version = doc.attribute( QStringLiteral( "version" ) ); if ( !mCaps.version.startsWith( QLatin1String( "1.0" ) ) && !mCaps.version.startsWith( QLatin1String( "1.1" ) ) && !mCaps.version.startsWith( QLatin1String( "2.0" ) ) ) { mErrorCode = WFSVersionNotSupported; mErrorMessage = tr( "WFS version %1 not supported" ).arg( mCaps.version ); emit gotCapabilities(); return; } // WFS 2.0 implementation are supposed to implement resultType=hits, and some // implementations (GeoServer) might advertize it, whereas others (MapServer) do not. // WFS 1.1 implementation too I think, but in the examples of the GetCapabilities // response of the WFS 1.1 standard (and in common implementations), this is // explicitly advertized if ( mCaps.version.startsWith( QLatin1String( "2.0" ) ) ) mCaps.supportsHits = true; // Note: for conveniency, we do not use the elementsByTagNameNS() method as // the WFS and OWS namespaces URI are not the same in all versions if ( mCaps.version.startsWith( QLatin1String( "1.0" ) ) ) { QDomElement capabilityElem = doc.firstChildElement( QStringLiteral( "Capability" ) ); if ( !capabilityElem.isNull() ) { QDomElement requestElem = capabilityElem.firstChildElement( QStringLiteral( "Request" ) ); if ( !requestElem.isNull() ) { QDomElement getFeatureElem = requestElem.firstChildElement( QStringLiteral( "GetFeature" ) ); if ( !getFeatureElem.isNull() ) { QDomElement resultFormatElem = getFeatureElem.firstChildElement( QStringLiteral( "ResultFormat" ) ); if ( !resultFormatElem.isNull() ) { QDomElement child = resultFormatElem.firstChildElement(); while ( !child.isNull() ) { mCaps.outputFormats << child.tagName(); child = child.nextSiblingElement(); } } } } } } // find <ows:OperationsMetadata> QDomElement operationsMetadataElem = doc.firstChildElement( QStringLiteral( "OperationsMetadata" ) ); if ( !operationsMetadataElem.isNull() ) { QDomNodeList contraintList = operationsMetadataElem.elementsByTagName( QStringLiteral( "Constraint" ) ); for ( int i = 0; i < contraintList.size(); ++i ) { QDomElement contraint = contraintList.at( i ).toElement(); if ( contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "DefaultMaxFeatures" ) /* WFS 1.1 */ ) { QDomElement value = contraint.firstChildElement( QStringLiteral( "Value" ) ); if ( !value.isNull() ) { mCaps.maxFeatures = value.text().toInt(); QgsDebugMsg( QString( "maxFeatures: %1" ).arg( mCaps.maxFeatures ) ); } } else if ( contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "CountDefault" ) /* WFS 2.0 (e.g. MapServer) */ ) { QDomElement value = contraint.firstChildElement( QStringLiteral( "DefaultValue" ) ); if ( !value.isNull() ) { mCaps.maxFeatures = value.text().toInt(); QgsDebugMsg( QString( "maxFeatures: %1" ).arg( mCaps.maxFeatures ) ); } } else if ( contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "ImplementsResultPaging" ) /* WFS 2.0 */ ) { QDomElement value = contraint.firstChildElement( QStringLiteral( "DefaultValue" ) ); if ( !value.isNull() && value.text() == QLatin1String( "TRUE" ) ) { mCaps.supportsPaging = true; QgsDebugMsg( "Supports paging" ); } } else if ( contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "ImplementsStandardJoins" ) || contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "ImplementsSpatialJoins" ) /* WFS 2.0 */ ) { QDomElement value = contraint.firstChildElement( QStringLiteral( "DefaultValue" ) ); if ( !value.isNull() && value.text() == QLatin1String( "TRUE" ) ) { mCaps.supportsJoins = true; QgsDebugMsg( "Supports joins" ); } } } // In WFS 2.0, max features can also be set in Operation.GetFeature (e.g. GeoServer) // and we are also interested by resultType=hits for WFS 1.1 QDomNodeList operationList = operationsMetadataElem.elementsByTagName( QStringLiteral( "Operation" ) ); for ( int i = 0; i < operationList.size(); ++i ) { QDomElement operation = operationList.at( i ).toElement(); if ( operation.attribute( QStringLiteral( "name" ) ) == QLatin1String( "GetFeature" ) ) { QDomNodeList operationContraintList = operation.elementsByTagName( QStringLiteral( "Constraint" ) ); for ( int j = 0; j < operationContraintList.size(); ++j ) { QDomElement contraint = operationContraintList.at( j ).toElement(); if ( contraint.attribute( QStringLiteral( "name" ) ) == QLatin1String( "CountDefault" ) ) { QDomElement value = contraint.firstChildElement( QStringLiteral( "DefaultValue" ) ); if ( !value.isNull() ) { mCaps.maxFeatures = value.text().toInt(); QgsDebugMsg( QString( "maxFeatures: %1" ).arg( mCaps.maxFeatures ) ); } break; } } QDomNodeList parameterList = operation.elementsByTagName( QStringLiteral( "Parameter" ) ); for ( int j = 0; j < parameterList.size(); ++j ) { QDomElement parameter = parameterList.at( j ).toElement(); if ( parameter.attribute( QStringLiteral( "name" ) ) == QLatin1String( "resultType" ) ) { QDomNodeList valueList = parameter.elementsByTagName( QStringLiteral( "Value" ) ); for ( int k = 0; k < valueList.size(); ++k ) { QDomElement value = valueList.at( k ).toElement(); if ( value.text() == QLatin1String( "hits" ) ) { mCaps.supportsHits = true; QgsDebugMsg( "Support hits" ); break; } } } else if ( parameter.attribute( QStringLiteral( "name" ) ) == QLatin1String( "outputFormat" ) ) { QDomNodeList valueList = parameter.elementsByTagName( QStringLiteral( "Value" ) ); for ( int k = 0; k < valueList.size(); ++k ) { QDomElement value = valueList.at( k ).toElement(); mCaps.outputFormats << value.text(); } } } break; } } } //go to <FeatureTypeList> QDomElement featureTypeListElem = doc.firstChildElement( QStringLiteral( "FeatureTypeList" ) ); if ( featureTypeListElem.isNull() ) { emit gotCapabilities(); return; } // Parse operations supported for all feature types bool insertCap = false; bool updateCap = false; bool deleteCap = false; // WFS < 2 if ( mCaps.version.startsWith( QLatin1String( "1" ) ) ) { parseSupportedOperations( featureTypeListElem.firstChildElement( QStringLiteral( "Operations" ) ), insertCap, updateCap, deleteCap ); } else // WFS 2.0.0 tested on GeoServer { QDomNodeList operationNodes = doc.elementsByTagName( "Operation" ); for ( int i = 0; i < operationNodes.count(); i++ ) { QDomElement operationElement = operationNodes.at( i ).toElement( ); if ( operationElement.isElement( ) && "Transaction" == operationElement.attribute( "name" ) ) { insertCap = true; updateCap = true; deleteCap = true; } } } // get the <FeatureType> elements QDomNodeList featureTypeList = featureTypeListElem.elementsByTagName( QStringLiteral( "FeatureType" ) ); for ( int i = 0; i < featureTypeList.size(); ++i ) { FeatureType featureType; QDomElement featureTypeElem = featureTypeList.at( i ).toElement(); //Name QDomNodeList nameList = featureTypeElem.elementsByTagName( QStringLiteral( "Name" ) ); if ( nameList.length() > 0 ) { featureType.name = nameList.at( 0 ).toElement().text(); } //Title QDomNodeList titleList = featureTypeElem.elementsByTagName( QStringLiteral( "Title" ) ); if ( titleList.length() > 0 ) { featureType.title = titleList.at( 0 ).toElement().text(); } //Abstract QDomNodeList abstractList = featureTypeElem.elementsByTagName( QStringLiteral( "Abstract" ) ); if ( abstractList.length() > 0 ) { featureType.abstract = abstractList.at( 0 ).toElement().text(); } //DefaultSRS is always the first entry in the feature srs list QDomNodeList defaultCRSList = featureTypeElem.elementsByTagName( QStringLiteral( "DefaultSRS" ) ); if ( defaultCRSList.length() == 0 ) // In WFS 2.0, this is spelled DefaultCRS... defaultCRSList = featureTypeElem.elementsByTagName( QStringLiteral( "DefaultCRS" ) ); if ( defaultCRSList.length() > 0 ) { QString srsname( defaultCRSList.at( 0 ).toElement().text() ); // Some servers like Geomedia advertize EPSG:XXXX even in WFS 1.1 or 2.0 if ( srsname.startsWith( QLatin1String( "EPSG:" ) ) ) mCaps.useEPSGColumnFormat = true; featureType.crslist.append( NormalizeSRSName( srsname ) ); } //OtherSRS QDomNodeList otherCRSList = featureTypeElem.elementsByTagName( QStringLiteral( "OtherSRS" ) ); if ( otherCRSList.length() == 0 ) // In WFS 2.0, this is spelled OtherCRS... otherCRSList = featureTypeElem.elementsByTagName( QStringLiteral( "OtherCRS" ) ); for ( int i = 0; i < otherCRSList.size(); ++i ) { featureType.crslist.append( NormalizeSRSName( otherCRSList.at( i ).toElement().text() ) ); } //Support <SRS> for compatibility with older versions QDomNodeList srsList = featureTypeElem.elementsByTagName( QStringLiteral( "SRS" ) ); for ( int i = 0; i < srsList.size(); ++i ) { featureType.crslist.append( NormalizeSRSName( srsList.at( i ).toElement().text() ) ); } // Get BBox WFS 1.0 way QDomElement latLongBB = featureTypeElem.firstChildElement( QStringLiteral( "LatLongBoundingBox" ) ); if ( latLongBB.hasAttributes() ) { // Despite the name LatLongBoundingBox, the coordinates are supposed to // be expressed in <SRS>. From the WFS schema; // <!-- The LatLongBoundingBox element is used to indicate the edges of // an enclosing rectangle in the SRS of the associated feature type. featureType.bbox = QgsRectangle( latLongBB.attribute( QStringLiteral( "minx" ) ).toDouble(), latLongBB.attribute( QStringLiteral( "miny" ) ).toDouble(), latLongBB.attribute( QStringLiteral( "maxx" ) ).toDouble(), latLongBB.attribute( QStringLiteral( "maxy" ) ).toDouble() ); featureType.bboxSRSIsWGS84 = false; // But some servers do not honour this and systematically reproject to WGS84 // such as GeoServer. See http://osgeo-org.1560.x6.nabble.com/WFS-LatLongBoundingBox-td3813810.html // This is also true of TinyOWS if ( !featureType.crslist.isEmpty() && featureType.bbox.xMinimum() >= -180 && featureType.bbox.yMinimum() >= -90 && featureType.bbox.xMaximum() <= 180 && featureType.bbox.yMaximum() < 90 ) { QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( featureType.crslist[0] ); if ( !crs.isGeographic() ) { // If the CRS is projected then check that projecting the corner of the bbox, assumed to be in WGS84, // into the CRS, and then back to WGS84, works (check that we are in the validity area) QgsCoordinateReferenceSystem crsWGS84 = QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "CRS:84" ) ); QgsCoordinateTransform ct( crsWGS84, crs ); QgsPointXY ptMin( featureType.bbox.xMinimum(), featureType.bbox.yMinimum() ); QgsPointXY ptMinBack( ct.transform( ct.transform( ptMin, QgsCoordinateTransform::ForwardTransform ), QgsCoordinateTransform::ReverseTransform ) ); QgsPointXY ptMax( featureType.bbox.xMaximum(), featureType.bbox.yMaximum() ); QgsPointXY ptMaxBack( ct.transform( ct.transform( ptMax, QgsCoordinateTransform::ForwardTransform ), QgsCoordinateTransform::ReverseTransform ) ); QgsDebugMsg( featureType.bbox.toString() ); QgsDebugMsg( ptMinBack.toString() ); QgsDebugMsg( ptMaxBack.toString() ); if ( fabs( featureType.bbox.xMinimum() - ptMinBack.x() ) < 1e-5 && fabs( featureType.bbox.yMinimum() - ptMinBack.y() ) < 1e-5 && fabs( featureType.bbox.xMaximum() - ptMaxBack.x() ) < 1e-5 && fabs( featureType.bbox.yMaximum() - ptMaxBack.y() ) < 1e-5 ) { QgsDebugMsg( "Values of LatLongBoundingBox are consistent with WGS84 long/lat bounds, so as the CRS is projected, assume they are indeed in WGS84 and not in the CRS units" ); featureType.bboxSRSIsWGS84 = true; } } } } else { // WFS 1.1 way QDomElement WGS84BoundingBox = featureTypeElem.firstChildElement( QStringLiteral( "WGS84BoundingBox" ) ); if ( !WGS84BoundingBox.isNull() ) { QDomElement lowerCorner = WGS84BoundingBox.firstChildElement( QStringLiteral( "LowerCorner" ) ); QDomElement upperCorner = WGS84BoundingBox.firstChildElement( QStringLiteral( "UpperCorner" ) ); if ( !lowerCorner.isNull() && !upperCorner.isNull() ) { QStringList lowerCornerList = lowerCorner.text().split( QStringLiteral( " " ), QString::SkipEmptyParts ); QStringList upperCornerList = upperCorner.text().split( QStringLiteral( " " ), QString::SkipEmptyParts ); if ( lowerCornerList.size() == 2 && upperCornerList.size() == 2 ) { featureType.bbox = QgsRectangle( lowerCornerList[0].toDouble(), lowerCornerList[1].toDouble(), upperCornerList[0].toDouble(), upperCornerList[1].toDouble() ); featureType.bboxSRSIsWGS84 = true; } } } } // Parse Operations specific to the type name parseSupportedOperations( featureTypeElem.firstChildElement( QStringLiteral( "Operations" ) ), featureType.insertCap, featureType.updateCap, featureType.deleteCap ); featureType.insertCap |= insertCap; featureType.updateCap |= updateCap; featureType.deleteCap |= deleteCap; mCaps.featureTypes.push_back( featureType ); } Q_FOREACH ( const FeatureType &f, mCaps.featureTypes ) { mCaps.setAllTypenames.insert( f.name ); QString unprefixed( QgsWFSUtils::removeNamespacePrefix( f.name ) ); if ( !mCaps.setAmbiguousUnprefixedTypename.contains( unprefixed ) ) { if ( mCaps.mapUnprefixedTypenameToPrefixedTypename.contains( unprefixed ) ) { mCaps.setAmbiguousUnprefixedTypename.insert( unprefixed ); mCaps.mapUnprefixedTypenameToPrefixedTypename.remove( unprefixed ); } else { mCaps.mapUnprefixedTypenameToPrefixedTypename[unprefixed] = f.name; } } } //go to <Filter_Capabilities> QDomElement filterCapabilitiesElem = doc.firstChildElement( QStringLiteral( "Filter_Capabilities" ) ); if ( !filterCapabilitiesElem.isNull() ) parseFilterCapabilities( filterCapabilitiesElem ); // Hard-coded functions Function f_ST_GeometryFromText( QStringLiteral( "ST_GeometryFromText" ), 1, 2 ); f_ST_GeometryFromText.returnType = QStringLiteral( "gml:AbstractGeometryType" ); f_ST_GeometryFromText.argumentList << Argument( QStringLiteral( "wkt" ), QStringLiteral( "xs:string" ) ); f_ST_GeometryFromText.argumentList << Argument( QStringLiteral( "srsname" ), QStringLiteral( "xs:string" ) ); mCaps.functionList << f_ST_GeometryFromText; Function f_ST_GeomFromGML( QStringLiteral( "ST_GeomFromGML" ), 1 ); f_ST_GeomFromGML.returnType = QStringLiteral( "gml:AbstractGeometryType" ); f_ST_GeomFromGML.argumentList << Argument( QStringLiteral( "gml" ), QStringLiteral( "xs:string" ) ); mCaps.functionList << f_ST_GeomFromGML; Function f_ST_MakeEnvelope( QStringLiteral( "ST_MakeEnvelope" ), 4, 5 ); f_ST_MakeEnvelope.returnType = QStringLiteral( "gml:AbstractGeometryType" ); f_ST_MakeEnvelope.argumentList << Argument( QStringLiteral( "minx" ), QStringLiteral( "xs:double" ) ); f_ST_MakeEnvelope.argumentList << Argument( QStringLiteral( "miny" ), QStringLiteral( "xs:double" ) ); f_ST_MakeEnvelope.argumentList << Argument( QStringLiteral( "maxx" ), QStringLiteral( "xs:double" ) ); f_ST_MakeEnvelope.argumentList << Argument( QStringLiteral( "maxy" ), QStringLiteral( "xs:double" ) ); f_ST_MakeEnvelope.argumentList << Argument( QStringLiteral( "srsname" ), QStringLiteral( "xs:string" ) ); mCaps.functionList << f_ST_MakeEnvelope; emit gotCapabilities(); }
bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p ) { if ( !layer ) { return false; } QgsVectorDataProvider* dp = layer->dataProvider(); if ( !dp ) { return false; } bool useField = false; if ( uniqueIdField == -1 ) { uniqueIdField = 0; } else { useField = true; } QgsFieldMap fields; fields.insert( 0 , QgsField( QString( "UID" ), QVariant::String ) ); fields.insert( 1 , QgsField( QString( "AREA" ), QVariant::Double ) ); fields.insert( 2 , QgsField( QString( "PERIM" ), QVariant::Double ) ); QGis::WkbType outputType = QGis::WKBPolygon; const QgsCoordinateReferenceSystem crs = layer->crs(); QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs ); QgsFeature currentFeature; QgsGeometry* dissolveGeometry = 0; //dissolve geometry QMultiMap<QString, QgsFeatureId> map; if ( onlySelectedFeatures ) { //use QgsVectorLayer::featureAtId const QgsFeatureIds selection = layer->selectedFeaturesIds(); QgsFeatureIds::const_iterator it = selection.constBegin(); for ( ; it != selection.constEnd(); ++it ) { #if 0 if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { // break; // it may be better to do something else here? return false; } #endif if ( !layer->featureAtId( *it, currentFeature, true, true ) ) { continue; } map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() ); } } else { layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false ); while ( layer->nextFeature( currentFeature ) ) { #if 0 if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { // break; // it may be better to do something else here? return false; } #endif map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() ); } } QMultiMap<QString, QgsFeatureId>::const_iterator jt = map.constBegin(); while ( jt != map.constEnd() ) { QString currentKey = jt.key(); int processedFeatures = 0; //take only selection if ( onlySelectedFeatures ) { //use QgsVectorLayer::featureAtId const QgsFeatureIds selection = layer->selectedFeaturesIds(); if ( p ) { p->setMaximum( selection.size() ); } processedFeatures = 0; while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) ) { if ( p && p->wasCanceled() ) { break; } if ( selection.contains( jt.value() ) ) { if ( p ) { p->setValue( processedFeatures ); } if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) ) { continue; } convexFeature( currentFeature, processedFeatures, &dissolveGeometry ); ++processedFeatures; } ++jt; } QList<double> values; if ( !dissolveGeometry ) { QgsDebugMsg( "no dissolved geometry - should not happen" ); return false; } dissolveGeometry = dissolveGeometry->convexHull(); values = simpleMeasure( dissolveGeometry ); QgsAttributeMap attributeMap; attributeMap.insert( 0 , QVariant( currentKey ) ); attributeMap.insert( 1 , values[ 0 ] ); attributeMap.insert( 2 , values[ 1 ] ); QgsFeature dissolveFeature; dissolveFeature.setAttributeMap( attributeMap ); dissolveFeature.setGeometry( dissolveGeometry ); vWriter.addFeature( dissolveFeature ); } //take all features else { int featureCount = layer->featureCount(); if ( p ) { p->setMaximum( featureCount ); } processedFeatures = 0; while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) ) { if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { break; } if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) ) { continue; } convexFeature( currentFeature, processedFeatures, &dissolveGeometry ); ++processedFeatures; ++jt; } QList<double> values; // QgsGeometry* tmpGeometry = 0; if ( !dissolveGeometry ) { QgsDebugMsg( "no dissolved geometry - should not happen" ); return false; } dissolveGeometry = dissolveGeometry->convexHull(); // values = simpleMeasure( tmpGeometry ); values = simpleMeasure( dissolveGeometry ); QgsAttributeMap attributeMap; attributeMap.insert( 0 , QVariant( currentKey ) ); attributeMap.insert( 1 , QVariant( values[ 0 ] ) ); attributeMap.insert( 2 , QVariant( values[ 1 ] ) ); QgsFeature dissolveFeature; dissolveFeature.setAttributeMap( attributeMap ); dissolveFeature.setGeometry( dissolveGeometry ); vWriter.addFeature( dissolveFeature ); } } return true; }
void QgsRasterProjector::calcSrcExtent() { /* Run around the mCPMatrix and find source extent */ // Attention, source limits are not necessarily on destination edges, e.g. // for destination EPSG:32661 Polar Stereographic and source EPSG:4326, // the maximum y may be in the middle of destination extent // TODO: How to find extent exactly and quickly? // For now, we runt through all matrix QgsPoint myPoint = mCPMatrix[0][0]; mSrcExtent = QgsRectangle( myPoint.x(), myPoint.y(), myPoint.x(), myPoint.y() ); for ( int i = 0; i < mCPRows; i++ ) { for ( int j = 0; j < mCPCols ; j++ ) { myPoint = mCPMatrix[i][j]; if ( mCPLegalMatrix[i][j] ) { mSrcExtent.combineExtentWith( myPoint.x(), myPoint.y() ); } } } // Expand a bit to avoid possible approx coords falling out because of representation error? // Combine with maximum source extent mSrcExtent = mSrcExtent.intersect( &mExtent ); // If mMaxSrcXRes, mMaxSrcYRes are defined (fixed src resolution) // align extent to src resolution to avoid jumping of reprojected pixels // when shifting resampled grid. // Important especially if we are over mMaxSrcXRes, mMaxSrcYRes limits // Note however, that preceding filters (like resampler) may read data // on different resolution. QgsDebugMsg( "mSrcExtent = " + mSrcExtent.toString() ); QgsDebugMsg( "mExtent = " + mExtent.toString() ); if ( !mExtent.isEmpty() ) { if ( mMaxSrcXRes > 0 ) { // with floor/ceil it should work correctly also for mSrcExtent.xMinimum() < mExtent.xMinimum() double col = floor(( mSrcExtent.xMinimum() - mExtent.xMinimum() ) / mMaxSrcXRes ); double x = mExtent.xMinimum() + col * mMaxSrcXRes; mSrcExtent.setXMinimum( x ); col = ceil(( mSrcExtent.xMaximum() - mExtent.xMinimum() ) / mMaxSrcXRes ); x = mExtent.xMinimum() + col * mMaxSrcXRes; mSrcExtent.setXMaximum( x ); } if ( mMaxSrcYRes > 0 ) { double row = floor(( mExtent.yMaximum() - mSrcExtent.yMaximum() ) / mMaxSrcYRes ); double y = mExtent.yMaximum() - row * mMaxSrcYRes; mSrcExtent.setYMaximum( y ); row = ceil(( mExtent.yMaximum() - mSrcExtent.yMinimum() ) / mMaxSrcYRes ); y = mExtent.yMaximum() - row * mMaxSrcYRes; mSrcExtent.setYMinimum( y ); } } QgsDebugMsg( "mSrcExtent = " + mSrcExtent.toString() ); }
bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p ) { if ( !layer ) { return false; } QgsVectorDataProvider* dp = layer->dataProvider(); if ( !dp ) { return false; } bool useField = false; if ( uniqueIdField == -1 ) { uniqueIdField = 0; } else { useField = true; } QGis::WkbType outputType = dp->geometryType(); const QgsCoordinateReferenceSystem crs = layer->crs(); QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs ); QgsFeature currentFeature; QMultiMap<QString, QgsFeatureId> map; if ( onlySelectedFeatures ) { //use QgsVectorLayer::featureAtId const QgsFeatureIds selection = layer->selectedFeaturesIds(); QgsFeatureIds::const_iterator it = selection.constBegin(); for ( ; it != selection.constEnd(); ++it ) { if ( !layer->featureAtId( *it, currentFeature, true, true ) ) { continue; } map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() ); } } else { layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false ); while ( layer->nextFeature( currentFeature ) ) { map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() ); } } QgsGeometry *dissolveGeometry = 0; //dissolve geometry QMultiMap<QString, QgsFeatureId>::const_iterator jt = map.constBegin(); QgsFeature outputFeature; while ( jt != map.constEnd() ) { QString currentKey = jt.key(); int processedFeatures = 0; bool first = true; //take only selection if ( onlySelectedFeatures ) { //use QgsVectorLayer::featureAtId const QgsFeatureIds selection = layer->selectedFeaturesIds(); if ( p ) { p->setMaximum( selection.size() ); } while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) ) { if ( p && p->wasCanceled() ) { break; } if ( selection.contains( jt.value() ) ) { if ( p ) { p->setValue( processedFeatures ); } if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) ) { continue; } if ( first ) { outputFeature.setAttributeMap( currentFeature.attributeMap() ); first = false; } dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry ); ++processedFeatures; } ++jt; } } //take all features else { int featureCount = layer->featureCount(); if ( p ) { p->setMaximum( featureCount ); } while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) ) { if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { break; } if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) ) { continue; } { outputFeature.setAttributeMap( currentFeature.attributeMap() ); first = false; } dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry ); ++processedFeatures; ++jt; } } outputFeature.setGeometry( dissolveGeometry ); vWriter.addFeature( outputFeature ); } return true; }
void QgsAtlasComposition::prepareForFeature( size_t featureI ) { if ( !mComposerMap || !mCoverageLayer ) { return; } // retrieve the next feature, based on its id mCoverageLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ] ) ).nextFeature( mCurrentFeature ); if ( !mSingleFile && mFilenamePattern.size() > 0 ) { QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) ); QVariant filenameRes = mFilenameExpr->evaluate( &mCurrentFeature, mCoverageLayer->pendingFields() ); if ( mFilenameExpr->hasEvalError() ) { throw std::runtime_error( tr( "Filename eval error: %1" ).arg( mFilenameExpr->evalErrorString() ).toLocal8Bit().data() ); } mCurrentFilename = filenameRes.toString(); } // // compute the new extent // keep the original aspect ratio // and apply a margin // QgsGeometry::boundingBox is expressed in the geometry"s native CRS // We have to transform the grometry to the destination CRS and ask for the bounding box // Note: we cannot directly take the transformation of the bounding box, since transformations are not linear QgsGeometry tgeom( *mCurrentFeature.geometry() ); tgeom.transform( mTransform ); QgsRectangle geom_rect = tgeom.boundingBox(); double xa1 = geom_rect.xMinimum(); double xa2 = geom_rect.xMaximum(); double ya1 = geom_rect.yMinimum(); double ya2 = geom_rect.yMaximum(); QgsRectangle new_extent = geom_rect; // restore the original extent // (successive calls to setNewExtent tend to deform the original rectangle) mComposerMap->setNewExtent( mOrigExtent ); if ( mFixedScale ) { // only translate, keep the original scale (i.e. width x height) double geom_center_x = ( xa1 + xa2 ) / 2.0; double geom_center_y = ( ya1 + ya2 ) / 2.0; double xx = geom_center_x - mOrigExtent.width() / 2.0; double yy = geom_center_y - mOrigExtent.height() / 2.0; new_extent = QgsRectangle( xx, yy, xx + mOrigExtent.width(), yy + mOrigExtent.height() ); } else { // auto scale double geom_ratio = geom_rect.width() / geom_rect.height(); double map_ratio = mOrigExtent.width() / mOrigExtent.height(); // geometry height is too big if ( geom_ratio < map_ratio ) { // extent the bbox's width double adj_width = ( map_ratio * geom_rect.height() - geom_rect.width() ) / 2.0; xa1 -= adj_width; xa2 += adj_width; } // geometry width is too big else if ( geom_ratio > map_ratio ) { // extent the bbox's height double adj_height = ( geom_rect.width() / map_ratio - geom_rect.height() ) / 2.0; ya1 -= adj_height; ya2 += adj_height; } new_extent = QgsRectangle( xa1, ya1, xa2, ya2 ); if ( mMargin > 0.0 ) { new_extent.scale( 1 + mMargin ); } } // evaluate label expressions QList<QgsComposerLabel*> labels; mComposition->composerItems( labels ); QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) ); for ( QList<QgsComposerLabel*>::iterator lit = labels.begin(); lit != labels.end(); ++lit ) { ( *lit )->setExpressionContext( &mCurrentFeature, mCoverageLayer ); } // set the new extent (and render) mComposerMap->setNewExtent( new_extent ); }
bool QgsGeometryAnalyzer::eventLayer( QgsVectorLayer* lineLayer, QgsVectorLayer* eventLayer, int lineField, int eventField, QList<int>& unlocatedFeatureIds, const QString& outputLayer, const QString& outputFormat, int locationField1, int locationField2, int offsetField, double offsetScale, bool forceSingleGeometry, QgsVectorDataProvider* memoryProvider, QProgressDialog* p ) { if ( !lineLayer || !eventLayer || !lineLayer->isValid() || !eventLayer->isValid() ) { return false; } //create line field / id map for line layer QMultiHash< QString, QgsFeatureId > lineLayerIdMap; //1:n possible (e.g. several linear reference geometries for one feature in the event layer) lineLayer->select( QgsAttributeList() << lineField, QgsRectangle(), false, false ); QgsFeature fet; while ( lineLayer->nextFeature( fet ) ) { lineLayerIdMap.insert( fet.attributeMap()[lineField].toString(), fet.id() ); } //create output datasource or attributes in memory provider QgsVectorFileWriter* fileWriter = 0; QgsFeatureList memoryProviderFeatures; if ( !memoryProvider ) { QGis::WkbType memoryProviderType = QGis::WKBMultiLineString; if ( locationField2 == -1 ) { memoryProviderType = forceSingleGeometry ? QGis::WKBPoint : QGis::WKBMultiPoint; } else { memoryProviderType = forceSingleGeometry ? QGis::WKBLineString : QGis::WKBMultiLineString; } fileWriter = new QgsVectorFileWriter( outputLayer, eventLayer->dataProvider()->encoding(), eventLayer->pendingFields(), memoryProviderType, &( lineLayer->crs() ), outputFormat ); } else { memoryProvider->addAttributes( eventLayer->pendingFields().values() ); } //iterate over eventLayer and write new features to output file or layer eventLayer->select( eventLayer->pendingAllAttributesList(), QgsRectangle(), false, false ); QgsGeometry* lrsGeom = 0; QgsFeature lineFeature; double measure1, measure2; int nEventFeatures = eventLayer->pendingFeatureCount(); int featureCounter = 0; int nOutputFeatures = 0; //number of output features for the current event feature if ( p ) { p->setWindowModality( Qt::WindowModal ); p->setMinimum( 0 ); p->setMaximum( nEventFeatures ); p->show(); } while ( eventLayer->nextFeature( fet ) ) { nOutputFeatures = 0; //update progress dialog if ( p ) { if ( p->wasCanceled() ) { break; } p->setValue( featureCounter ); ++featureCounter; } measure1 = fet.attributeMap()[locationField1].toDouble(); if ( locationField2 != -1 ) { measure2 = fet.attributeMap()[locationField2].toDouble(); } QList<QgsFeatureId> featureIdList = lineLayerIdMap.values( fet.attributeMap()[eventField].toString() ); QList<QgsFeatureId>::const_iterator featureIdIt = featureIdList.constBegin(); for ( ; featureIdIt != featureIdList.constEnd(); ++featureIdIt ) { if ( !lineLayer->featureAtId( *featureIdIt, lineFeature, true, false ) ) { continue; } if ( locationField2 == -1 ) { lrsGeom = locateAlongMeasure( measure1, lineFeature.geometry() ); } else { lrsGeom = locateBetweenMeasures( measure1, measure2, lineFeature.geometry() ); } if ( lrsGeom ) { ++nOutputFeatures; addEventLayerFeature( fet, lrsGeom, lineFeature.geometry(), fileWriter, memoryProviderFeatures, offsetField, offsetScale, forceSingleGeometry ); } } if ( nOutputFeatures < 1 ) { unlocatedFeatureIds.push_back( fet.id() ); } } if ( p ) { p->setValue( nEventFeatures ); } if ( memoryProvider ) { memoryProvider->addFeatures( memoryProviderFeatures ); } delete fileWriter; return true; }
void QgsComposerView::mousePressEvent( QMouseEvent* e ) { if ( !composition() ) { return; } QPointF scenePoint = mapToScene( e->pos() ); QPointF snappedScenePoint = composition()->snapPointToGrid( scenePoint ); mMousePressStartPos = e->pos(); //lock/unlock position of item with right click if ( e->button() == Qt::RightButton ) { QgsComposerItem* selectedItem = composition()->composerItemAt( scenePoint ); if ( selectedItem ) { bool lock = selectedItem->positionLock() ? false : true; selectedItem->setPositionLock( lock ); selectedItem->update(); } return; } else if ( e->button() == Qt::MidButton ) { //pan composer with middle button mPanning = true; mMouseLastXY = e->pos(); if ( composition() ) { //lock cursor to closed hand cursor composition()->setPreventCursorChange( true ); } viewport()->setCursor( Qt::ClosedHandCursor ); return; } switch ( mCurrentTool ) { //select/deselect items and pass mouse event further case Select: { //check if we are clicking on a selection handle if ( composition()->selectionHandles()->isVisible() ) { //selection handles are being shown, get mouse action for current cursor position QgsComposerMouseHandles::MouseAction mouseAction = composition()->selectionHandles()->mouseActionForScenePos( scenePoint ); if ( mouseAction != QgsComposerMouseHandles::MoveItem && mouseAction != QgsComposerMouseHandles::NoAction && mouseAction != QgsComposerMouseHandles::SelectItem ) { //mouse is over a resize handle, so propagate event onward QGraphicsView::mousePressEvent( e ); return; } } QgsComposerItem* selectedItem = 0; QgsComposerItem* previousSelectedItem = 0; if ( e->modifiers() & Qt::ControlModifier ) { //CTRL modifier, so we are trying to select the next item below the current one //first, find currently selected item QList<QgsComposerItem*> selectedItems = composition()->selectedComposerItems(); if ( selectedItems.size() > 0 ) { previousSelectedItem = selectedItems.at( 0 ); } } if ( previousSelectedItem ) { //select highest item just below previously selected item at position of event selectedItem = composition()->composerItemAt( scenePoint, previousSelectedItem ); //if we didn't find a lower item we'll use the top-most as fall-back //this duplicates mapinfo/illustrator/etc behaviour where ctrl-clicks are "cyclic" if ( !selectedItem ) { selectedItem = composition()->composerItemAt( scenePoint ); } } else { //select topmost item at position of event selectedItem = composition()->composerItemAt( scenePoint ); } if ( !selectedItem ) { //not clicking over an item, so start marquee selection startMarqueeSelect( scenePoint ); break; } if (( !selectedItem->selected() ) && //keep selection if an already selected item pressed !( e->modifiers() & Qt::ShiftModifier ) ) //keep selection if shift key pressed { composition()->clearSelection(); } if (( e->modifiers() & Qt::ShiftModifier ) && ( selectedItem->selected() ) ) { //SHIFT-clicking a selected item deselects it selectedItem->setSelected( false ); //Check if we have any remaining selected items, and if so, update the item panel QList<QgsComposerItem*> selectedItems = composition()->selectedComposerItems(); if ( selectedItems.size() > 0 ) { emit selectedItemChanged( selectedItems.at( 0 ) ); } } else { selectedItem->setSelected( true ); QGraphicsView::mousePressEvent( e ); emit selectedItemChanged( selectedItem ); } break; } case Zoom: { if ( !( e->modifiers() & Qt::ShiftModifier ) ) { //zoom in action startMarqueeZoom( scenePoint ); } else { //zoom out action, so zoom out and recenter on clicked point double scaleFactor = 2; //get current visible part of scene QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() ); QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() ); //transform the mouse pos to scene coordinates QPointF scenePoint = mapToScene( e->pos() ); visibleRect.scale( scaleFactor, scenePoint.x(), scenePoint.y() ); QRectF boundsRect = visibleRect.toRectF(); //zoom view to fit desired bounds fitInView( boundsRect, Qt::KeepAspectRatio ); } break; } case Pan: { //pan action mPanning = true; mMouseLastXY = e->pos(); viewport()->setCursor( Qt::ClosedHandCursor ); break; } case MoveItemContent: { //get a list of items at clicked position QList<QGraphicsItem *> itemsAtCursorPos = items( e->pos() ); if ( itemsAtCursorPos.size() == 0 ) { //no items at clicked position return; } //find highest QgsComposerItem at clicked position //(other graphics items may be higher, eg selection handles) QList<QGraphicsItem*>::iterator itemIter = itemsAtCursorPos.begin(); for ( ; itemIter != itemsAtCursorPos.end(); ++itemIter ) { QgsComposerItem* item = dynamic_cast<QgsComposerItem *>(( *itemIter ) ); if ( item ) { //we've found the highest QgsComposerItem mMoveContentStartPos = scenePoint; mMoveContentItem = item; break; } } //no QgsComposerItem at clicked position return; } case AddArrow: { mRubberBandStartPos = QPointF( snappedScenePoint.x(), snappedScenePoint.y() ); mRubberBandLineItem = new QGraphicsLineItem( snappedScenePoint.x(), snappedScenePoint.y(), snappedScenePoint.x(), snappedScenePoint.y() ); mRubberBandLineItem->setZValue( 1000 ); scene()->addItem( mRubberBandLineItem ); scene()->update(); break; } //create rubber band for map and ellipse items case AddMap: case AddRectangle: case AddTriangle: case AddEllipse: case AddHtml: { QTransform t; mRubberBandItem = new QGraphicsRectItem( 0, 0, 0, 0 ); mRubberBandStartPos = QPointF( snappedScenePoint.x(), snappedScenePoint.y() ); t.translate( snappedScenePoint.x(), snappedScenePoint.y() ); mRubberBandItem->setTransform( t ); mRubberBandItem->setZValue( 1000 ); scene()->addItem( mRubberBandItem ); scene()->update(); } break; case AddLabel: if ( composition() ) { QgsComposerLabel* newLabelItem = new QgsComposerLabel( composition() ); newLabelItem->setText( tr( "QGIS" ) ); newLabelItem->adjustSizeToText(); newLabelItem->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLabelItem->rect().width(), newLabelItem->rect().height() ) ); composition()->addComposerLabel( newLabelItem ); emit actionFinished(); composition()->pushAddRemoveCommand( newLabelItem, tr( "Label added" ) ); } break; case AddScalebar: if ( composition() ) { QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( composition() ); newScaleBar->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 20, 20 ) ); composition()->addComposerScaleBar( newScaleBar ); QList<const QgsComposerMap*> mapItemList = composition()->composerMapItems(); if ( mapItemList.size() > 0 ) { newScaleBar->setComposerMap( mapItemList.at( 0 ) ); } newScaleBar->applyDefaultSize(); //4 segments, 1/5 of composer map width emit actionFinished(); composition()->pushAddRemoveCommand( newScaleBar, tr( "Scale bar added" ) ); } break; case AddLegend: { if ( composition() ) { QgsComposerLegend* newLegend = new QgsComposerLegend( composition() ); newLegend->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLegend->rect().width(), newLegend->rect().height() ) ); composition()->addComposerLegend( newLegend ); newLegend->updateLegend(); emit actionFinished(); composition()->pushAddRemoveCommand( newLegend, tr( "Legend added" ) ); } break; } case AddPicture: if ( composition() ) { QgsComposerPicture* newPicture = new QgsComposerPicture( composition() ); newPicture->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 30, 30 ) ); composition()->addComposerPicture( newPicture ); emit actionFinished(); composition()->pushAddRemoveCommand( newPicture, tr( "Picture added" ) ); } break; case AddTable: if ( composition() ) { QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( composition() ); newTable->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 50, 50 ) ); composition()->addComposerTable( newTable ); emit actionFinished(); composition()->pushAddRemoveCommand( newTable, tr( "Table added" ) ); } break; default: break; } }
void TestQgsWcsPublicServers::test( ) { QStringList versions; // It may happen that server supports 1.1.1, but does not accept 1.1 (http://zeus.pin.unifi.it/gi-wcs/http) versions << "" << "1.0.0" << "1.1.0"; // empty for default QStringList servers; // Some (first) coverages do not advertize any supportedCRS and sever gives // error both with native CRS (EPSG::561005) and EPSG:4326 // MOD* coverages work OK servers << "http://argon.geogr.uni-jena.de:8080/geoserver/ows"; servers << "http://demo.geonode.org/geoserver/wcs"; servers << "http://demo.mapserver.org/cgi-bin/wcs"; servers << "http://demo.opengeo.org/geoserver/wcs"; // geobrain.laits.gmu.edu servers are quite slow servers << "http://geobrain.laits.gmu.edu/cgi-bin/gbwcs-dem"; servers << "http://geobrain.laits.gmu.edu/cgi-bin/ows8/wcseo"; servers << "http://geobrain.laits.gmu.edu/cgi-bin/wcs110"; servers << "http://geobrain.laits.gmu.edu/cgi-bin/wcs-all"; servers << "http://iceds.ge.ucl.ac.uk/cgi-bin/icedswcs"; servers << "http://motherlode.ucar.edu:8080/thredds/wcs/fmrc/NCEP/DGEX/Alaska_12km/NCEP-DGEX-Alaska_12km_best.ncd"; servers << "http://navigator.state.or.us/ArcGIS/services/Framework/Imagery_Mosaic2009/ImageServer/WCSServer"; servers << "http://nsidc.org/cgi-bin/atlas_north"; servers << "http://sedac.ciesin.columbia.edu/geoserver/wcs"; // Big and slow //servers << "http://webmap.ornl.gov/ogcbroker/wcs"; servers << "http://ws.csiss.gmu.edu/cgi-bin/wcs-t"; // Big and slow //servers << "http://ws.laits.gmu.edu/cgi-bin/wcs-all"; // Currently very slow or down //servers << "http://www.sogeo.ch/geoserver/wcs"; // Slow and erroneous //servers << "http://zeus.pin.unifi.it/gi-wcs/http"; foreach ( QString server, servers ) { QStringList myServerLog; myServerLog << "server:" + server; QString myServerDirName = server; myServerDirName.replace( QRegExp( "[:/]+" ), "." ); myServerDirName.replace( QRegExp( "\\.$" ), "" ); QgsDebugMsg( "myServerDirName = " + myServerDirName ); QDir myServerDir( mCacheDir.absolutePath() + QDir::separator() + myServerDirName ); QString myServerLogPath = myServerDir.absolutePath() + QDir::separator() + "server.log"; if ( QFileInfo( myServerLogPath ).exists() ) { QgsDebugMsg( "cache exists " + myServerDir.absolutePath() ); continue; } if ( !myServerDir.exists() ) { mCacheDir.mkdir( myServerDirName ); } foreach ( QString version, versions ) { QgsDebugMsg( "server: " + server + " version: " + version ); QgsDataSourceURI myServerUri; myServerUri.setParam( "url", server ); if ( !version.isEmpty() ) { myServerUri.setParam( "version", version ); } QgsWcsCapabilities myCapabilities; myCapabilities.setUri( myServerUri ); if ( !myCapabilities.lastError().isEmpty() ) { QgsDebugMsg( myCapabilities.lastError() ); myServerLog << "error: (version: " + version + ") " + myCapabilities.lastError().replace( "\n", " " ); continue; } QVector<QgsWcsCoverageSummary> myCoverages; if ( !myCapabilities.supportedCoverages( myCoverages ) ) { QgsDebugMsg( "Cannot get list of coverages" ); myServerLog << "error: (version: " + version + ") Cannot get list of coverages"; continue; } int myCoverageCount = 0; int myStep = myCoverages.size() / mMaxCoverages; int myStepCount = -1; foreach ( QgsWcsCoverageSummary myCoverage, myCoverages ) { QgsDebugMsg( "coverage: " + myCoverage.identifier ); // Go in steps to get more success/errors if ( myStepCount == -1 || myStepCount > myStep ) { myStepCount = 0; } else { myStepCount++; continue; } myCoverageCount++; if ( myCoverageCount > mMaxCoverages ) break; QString myPath = myServerDir.absolutePath() + QDir::separator() + myCoverage.identifier; if ( !version.isEmpty() ) { myPath += "-" + version; } QString myLogPath = myPath + ".log"; if ( QFileInfo( myLogPath ).exists() ) { QMap<QString, QString> log = readLog( myLogPath ); if ( !log.value( "identifier" ).isEmpty() && log.value( "error" ).isEmpty() ) continue; } QStringList myLog; myLog << "identifier:" + myCoverage.identifier; myCapabilities.describeCoverage( myCoverage.identifier ); myCoverage = myCapabilities.coverage( myCoverage.identifier ); // get described QgsDataSourceURI myUri = myServerUri; myUri.setParam( "identifier", myCoverage.identifier ); if ( myCoverage.times.size() > 0 ) { myUri.setParam( "time", myCoverage.times.value( 0 ) ); } myLog << "version:" + version; myLog << "uri:" + myUri.encodedUri(); int myWidth = 100; int myHeight = 100; if ( myCoverage.hasSize ) { myHeight = static_cast<int>( qRound( 1.0 * myWidth * myCoverage.height / myCoverage.width ) ); } myLog << QString( "hasSize:%1" ).arg( myCoverage.hasSize ); QgsRasterLayer * myLayer = new QgsRasterLayer( myUri.encodedUri(), myCoverage.identifier, "wcs", true ); if ( myLayer->isValid() ) { int myBandCount = myLayer->dataProvider()->bandCount(); myLog << "bandCount:" + QString::number( myBandCount ); if ( myBandCount > 0 ) { myLog << "srcType:" + QString::number( myLayer->dataProvider()->srcDataType( 1 ) ); QgsRasterBandStats myStats = myLayer->dataProvider()->bandStatistics( 1, QgsRasterBandStats::All, QgsRectangle(), myWidth * myHeight ); myLog << "min:" + QString::number( myStats.minimumValue ); myLog << "max:" + QString::number( myStats.maximumValue ); } QgsMapRenderer myMapRenderer; QList<QgsMapLayer *> myLayersList; myLayersList.append( myLayer ); QgsMapLayerRegistry::instance()->addMapLayers( myLayersList, false ); QMap<QString, QgsMapLayer*> myLayersMap = QgsMapLayerRegistry::instance()->mapLayers(); myMapRenderer.setLayerSet( myLayersMap.keys() ); myMapRenderer.setExtent( myLayer->extent() ); QImage myImage( myWidth, myHeight, QImage::Format_ARGB32_Premultiplied ); myImage.fill( 0 ); myMapRenderer.setOutputSize( QSize( myWidth, myHeight ), myImage.logicalDpiX() ); QPainter myPainter( &myImage ); myMapRenderer.render( &myPainter ); // Save rendered image QString myPngPath = myPath + ".png"; QgsDebugMsg( "myPngPath = " + myPngPath ); myImage.save( myPngPath ); // Verify data QSet<QString> myValues; // cannot be QSet<double> void *myData = myLayer->dataProvider()->readBlock( 1, myLayer->extent(), myWidth, myHeight ); if ( myData ) { int myType = myLayer->dataProvider()->dataType( 1 ); for ( int row = 0; row < myHeight; row++ ) { for ( int col = 0; col < myWidth; col++ ) { double value = myLayer->dataProvider()->readValue( myData, myType, row * myWidth + col ); QString valueStr = QString::number( value ); if ( !myValues.contains( valueStr ) ) myValues.insert( valueStr ); } } free( myData ); } QgsDebugMsg( QString( "%1 values" ).arg( myValues.size() ) ); myLog << QString( "valuesCount:%1" ).arg( myValues.size() ); // Verify image colors QSet<QRgb> myColors; for ( int row = 0; row < myHeight; row++ ) { for ( int col = 0; col < myWidth; col++ ) { QRgb color = myImage.pixel( col, row ); if ( !myColors.contains( color ) ) myColors.insert( color ); } } QgsDebugMsg( QString( "%1 colors" ).arg( myColors.size() ) ); myLog << QString( "colorsCount:%1" ).arg( myColors.size() ); } else { QgsDebugMsg( "Layer is not valid" ); myLog << "error:Layer is not valid"; } QFile myLogFile( myLogPath ); myLogFile.open( QIODevice::WriteOnly | QIODevice::Text ); QTextStream myStream( &myLogFile ); myStream << myLog.join( "\n" ); myLogFile.close(); QgsMapLayerRegistry::instance()->removeAllMapLayers(); }
void QgsComposerView::wheelZoom( QWheelEvent * event ) { //get mouse wheel zoom behaviour settings QSettings mySettings; int wheelAction = mySettings.value( "/qgis/wheel_action", 2 ).toInt(); double zoomFactor = mySettings.value( "/qgis/zoom_factor", 2 ).toDouble(); if (( QgsMapCanvas::WheelAction )wheelAction == QgsMapCanvas::WheelNothing ) { return; } if ( event->modifiers() & Qt::ControlModifier ) { //holding ctrl while wheel zooming results in a finer zoom zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 10.0; } //caculate zoom scale factor bool zoomIn = event->delta() > 0; double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor ); //get current visible part of scene QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() ); QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() ); //transform the mouse pos to scene coordinates QPointF scenePoint = mapToScene( event->pos() ); //adjust view center according to wheel action setting switch (( QgsMapCanvas::WheelAction )wheelAction ) { case QgsMapCanvas::WheelZoomAndRecenter: { centerOn( scenePoint.x(), scenePoint.y() ); break; } case QgsMapCanvas::WheelZoomToMouseCursor: { QgsPoint oldCenter( visibleRect.center() ); QgsPoint newCenter( scenePoint.x() + (( oldCenter.x() - scenePoint.x() ) * scaleFactor ), scenePoint.y() + (( oldCenter.y() - scenePoint.y() ) * scaleFactor ) ); centerOn( newCenter.x(), newCenter.y() ); break; } default: break; } //zoom composition if ( zoomIn ) { scale( zoomFactor, zoomFactor ); } else { scale( 1 / zoomFactor, 1 / zoomFactor ); } //update composition for new zoom emit zoomLevelChanged(); updateRulers(); update(); //redraw cached map items QList<QGraphicsItem *> itemList = composition()->items(); QList<QGraphicsItem *>::iterator itemIt = itemList.begin(); for ( ; itemIt != itemList.end(); ++itemIt ) { QgsComposerMap* mypItem = dynamic_cast<QgsComposerMap *>( *itemIt ); if (( mypItem ) && ( mypItem->previewMode() == QgsComposerMap::Render ) ) { mypItem->updateCachedImage(); } } }
QgsRectangle QgsOSMDownloadDialog::rect() const { return QgsRectangle( editXMin->text().toDouble(), editYMin->text().toDouble(), editXMax->text().toDouble(), editYMax->text().toDouble() ); }
void QgsComposerView::mouseReleaseEvent( QMouseEvent* e ) { if ( !composition() ) { return; } QPoint mousePressStopPoint = e->pos(); int diffX = mousePressStopPoint.x() - mMousePressStartPos.x(); int diffY = mousePressStopPoint.y() - mMousePressStartPos.y(); //was this just a click? or a click and drag? bool clickOnly = false; if ( qAbs( diffX ) < 2 && qAbs( diffY ) < 2 ) { clickOnly = true; } QPointF scenePoint = mapToScene( e->pos() ); if ( mPanning ) { mPanning = false; if ( clickOnly && e->button() == Qt::MidButton ) { //middle mouse button click = recenter on point //get current visible part of scene QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() ); QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() ); visibleRect.scale( 1, scenePoint.x(), scenePoint.y() ); QRectF boundsRect = visibleRect.toRectF(); //zoom view to fit desired bounds fitInView( boundsRect, Qt::KeepAspectRatio ); } //set new cursor if ( mCurrentTool == Pan ) { viewport()->setCursor( Qt::OpenHandCursor ); } else { if ( composition() ) { //allow composer items to change cursor composition()->setPreventCursorChange( false ); } viewport()->setCursor( Qt::ArrowCursor ); } } if ( mMarqueeSelect ) { endMarqueeSelect( e ); return; } switch ( mCurrentTool ) { case Select: { QGraphicsView::mouseReleaseEvent( e ); break; } case Zoom: { if ( mMarqueeZoom ) { endMarqueeZoom( e ); } break; } case MoveItemContent: { if ( mMoveContentItem ) { //update map preview if composer map QgsComposerMap* composerMap = dynamic_cast<QgsComposerMap *>( mMoveContentItem ); if ( composerMap ) { composerMap->setOffset( 0, 0 ); } double moveX = scenePoint.x() - mMoveContentStartPos.x(); double moveY = scenePoint.y() - mMoveContentStartPos.y(); composition()->beginCommand( mMoveContentItem, tr( "Move item content" ) ); mMoveContentItem->moveContent( -moveX, -moveY ); composition()->endCommand(); mMoveContentItem = 0; } break; } case AddArrow: if ( composition() ) { QPointF scenePoint = mapToScene( e->pos() ); QPointF snappedScenePoint = composition()->snapPointToGrid( scenePoint ); QgsComposerArrow* composerArrow = new QgsComposerArrow( mRubberBandStartPos, QPointF( snappedScenePoint.x(), snappedScenePoint.y() ), composition() ); composition()->addComposerArrow( composerArrow ); scene()->removeItem( mRubberBandLineItem ); delete mRubberBandLineItem; mRubberBandLineItem = 0; emit actionFinished(); composition()->pushAddRemoveCommand( composerArrow, tr( "Arrow added" ) ); } break; case AddRectangle: case AddTriangle: case AddEllipse: addShape( mCurrentTool ); break; case AddMap: if ( !mRubberBandItem || ( mRubberBandItem->rect().width() < 0.1 && mRubberBandItem->rect().height() < 0.1 ) ) { removeRubberBand(); return; } if ( composition() ) { QgsComposerMap* composerMap = new QgsComposerMap( composition(), mRubberBandItem->transform().dx(), mRubberBandItem->transform().dy(), mRubberBandItem->rect().width(), mRubberBandItem->rect().height() ); composition()->addComposerMap( composerMap ); removeRubberBand(); emit actionFinished(); composition()->pushAddRemoveCommand( composerMap, tr( "Map added" ) ); } break; case AddHtml: if ( composition() ) { QgsComposerHtml* composerHtml = new QgsComposerHtml( composition(), true ); QgsAddRemoveMultiFrameCommand* command = new QgsAddRemoveMultiFrameCommand( QgsAddRemoveMultiFrameCommand::Added, composerHtml, composition(), tr( "Html item added" ) ); composition()->undoStack()->push( command ); QgsComposerFrame* frame = new QgsComposerFrame( composition(), composerHtml, mRubberBandItem->transform().dx(), mRubberBandItem->transform().dy(), mRubberBandItem->rect().width(), mRubberBandItem->rect().height() ); composition()->beginMultiFrameCommand( composerHtml, tr( "Html frame added" ) ); composerHtml->addFrame( frame ); composition()->endMultiFrameCommand(); removeRubberBand(); emit actionFinished(); } default: break; } }
QgsRectangle QgsCoordinateTransform::transformBoundingBox( const QgsRectangle rect, TransformDirection direction ) const { // Calculate the bounding box of a QgsRectangle in the source CRS // when projected to the destination CRS (or the inverse). // This is done by looking at a number of points spread evenly // across the rectangle if ( mShortCircuit || !mInitialisedFlag ) return rect; if ( rect.isEmpty() ) { QgsPoint p = transform( rect.xMinimum(), rect.yMinimum(), direction ); return QgsRectangle( p, p ); } static const int numP = 8; QgsRectangle bb_rect; bb_rect.setMinimal(); // We're interfacing with C-style vectors in the // end, so let's do C-style vectors here too. double x[numP * numP]; double y[numP * numP]; double z[numP * numP]; QgsDebugMsg( "Entering transformBoundingBox..." ); // Populate the vectors double dx = rect.width() / ( double )( numP - 1 ); double dy = rect.height() / ( double )( numP - 1 ); double pointY = rect.yMinimum(); for ( int i = 0; i < numP ; i++ ) { // Start at right edge double pointX = rect.xMinimum(); for ( int j = 0; j < numP; j++ ) { x[( i*numP ) + j] = pointX; y[( i*numP ) + j] = pointY; // and the height... z[( i*numP ) + j] = 0.0; // QgsDebugMsg(QString("BBox coord: (%1, %2)").arg(x[(i*numP) + j]).arg(y[(i*numP) + j])); pointX += dx; } pointY += dy; } // Do transformation. Any exception generated must // be handled in above layers. try { transformCoords( numP * numP, x, y, z, direction ); } catch ( QgsCsException &cse ) { // rethrow the exception QgsDebugMsg( "rethrowing exception" ); throw cse; } // Calculate the bounding box and use that for the extent for ( int i = 0; i < numP * numP; i++ ) { if ( qIsFinite( x[i] ) && qIsFinite( y[i] ) ) bb_rect.combineExtentWith( x[i], y[i] ); } QgsDebugMsg( "Projected extent: " + bb_rect.toString() ); if ( bb_rect.isEmpty() ) { QgsDebugMsg( "Original extent: " + rect.toString() ); } return bb_rect; }
void QgsCurve::clearCache() const { mBoundingBox = QgsRectangle(); QgsAbstractGeometry::clearCache(); }
bool QgsVectorLayerRenderer::render() { if ( mGeometryType == QgsWkbTypes::NullGeometry || mGeometryType == QgsWkbTypes::UnknownGeometry ) return true; if ( !mRenderer ) { mErrors.append( QObject::tr( "No renderer for drawing." ) ); return false; } bool usingEffect = false; if ( mRenderer->paintEffect() && mRenderer->paintEffect()->enabled() ) { usingEffect = true; mRenderer->paintEffect()->begin( mContext ); } // Per feature blending mode if ( mContext.useAdvancedEffects() && mFeatureBlendMode != QPainter::CompositionMode_SourceOver ) { // set the painter to the feature blend mode, so that features drawn // on this layer will interact and blend with each other mContext.painter()->setCompositionMode( mFeatureBlendMode ); } mRenderer->startRender( mContext, mFields ); QString rendererFilter = mRenderer->filter( mFields ); QgsRectangle requestExtent = mContext.extent(); mRenderer->modifyRequestExtent( requestExtent, mContext ); QgsFeatureRequest featureRequest = QgsFeatureRequest() .setFilterRect( requestExtent ) .setSubsetOfAttributes( mAttrNames, mFields ) .setExpressionContext( mContext.expressionContext() ); if ( mRenderer->orderByEnabled() ) { featureRequest.setOrderBy( mRenderer->orderBy() ); } const QgsFeatureFilterProvider *featureFilterProvider = mContext.featureFilterProvider(); if ( featureFilterProvider ) { featureFilterProvider->filterFeatures( mLayer, featureRequest ); } if ( !rendererFilter.isEmpty() && rendererFilter != QLatin1String( "TRUE" ) ) { featureRequest.combineFilterExpression( rendererFilter ); } // enable the simplification of the geometries (Using the current map2pixel context) before send it to renderer engine. if ( mSimplifyGeometry ) { double map2pixelTol = mSimplifyMethod.threshold(); bool validTransform = true; const QgsMapToPixel &mtp = mContext.mapToPixel(); map2pixelTol *= mtp.mapUnitsPerPixel(); QgsCoordinateTransform ct = mContext.coordinateTransform(); // resize the tolerance using the change of size of an 1-BBOX from the source CoordinateSystem to the target CoordinateSystem if ( ct.isValid() && !ct.isShortCircuited() ) { try { QgsPointXY center = mContext.extent().center(); double rectSize = ct.sourceCrs().isGeographic() ? 0.0008983 /* ~100/(40075014/360=111319.4833) */ : 100; QgsRectangle sourceRect = QgsRectangle( center.x(), center.y(), center.x() + rectSize, center.y() + rectSize ); QgsRectangle targetRect = ct.transform( sourceRect ); QgsDebugMsgLevel( QString( "Simplify - SourceTransformRect=%1" ).arg( sourceRect.toString( 16 ) ), 4 ); QgsDebugMsgLevel( QString( "Simplify - TargetTransformRect=%1" ).arg( targetRect.toString( 16 ) ), 4 ); if ( !sourceRect.isEmpty() && sourceRect.isFinite() && !targetRect.isEmpty() && targetRect.isFinite() ) { QgsPointXY minimumSrcPoint( sourceRect.xMinimum(), sourceRect.yMinimum() ); QgsPointXY maximumSrcPoint( sourceRect.xMaximum(), sourceRect.yMaximum() ); QgsPointXY minimumDstPoint( targetRect.xMinimum(), targetRect.yMinimum() ); QgsPointXY maximumDstPoint( targetRect.xMaximum(), targetRect.yMaximum() ); double sourceHypothenuse = std::sqrt( minimumSrcPoint.sqrDist( maximumSrcPoint ) ); double targetHypothenuse = std::sqrt( minimumDstPoint.sqrDist( maximumDstPoint ) ); QgsDebugMsgLevel( QString( "Simplify - SourceHypothenuse=%1" ).arg( sourceHypothenuse ), 4 ); QgsDebugMsgLevel( QString( "Simplify - TargetHypothenuse=%1" ).arg( targetHypothenuse ), 4 ); if ( !qgsDoubleNear( targetHypothenuse, 0.0 ) ) map2pixelTol *= ( sourceHypothenuse / targetHypothenuse ); } } catch ( QgsCsException &cse ) { QgsMessageLog::logMessage( QObject::tr( "Simplify transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) ); validTransform = false; } } if ( validTransform ) { QgsSimplifyMethod simplifyMethod; simplifyMethod.setMethodType( QgsSimplifyMethod::OptimizeForRendering ); simplifyMethod.setTolerance( map2pixelTol ); simplifyMethod.setThreshold( mSimplifyMethod.threshold() ); simplifyMethod.setForceLocalOptimization( mSimplifyMethod.forceLocalOptimization() ); featureRequest.setSimplifyMethod( simplifyMethod ); QgsVectorSimplifyMethod vectorMethod = mSimplifyMethod; vectorMethod.setTolerance( map2pixelTol ); mContext.setVectorSimplifyMethod( vectorMethod ); } else { QgsVectorSimplifyMethod vectorMethod; vectorMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification ); mContext.setVectorSimplifyMethod( vectorMethod ); } } else { QgsVectorSimplifyMethod vectorMethod; vectorMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification ); mContext.setVectorSimplifyMethod( vectorMethod ); } QgsFeatureIterator fit = mSource->getFeatures( featureRequest ); // Attach an interruption checker so that iterators that have potentially // slow fetchFeature() implementations, such as in the WFS provider, can // check it, instead of relying on just the mContext.renderingStopped() check // in drawRenderer() fit.setInterruptionChecker( &mInterruptionChecker ); if ( ( mRenderer->capabilities() & QgsFeatureRenderer::SymbolLevels ) && mRenderer->usingSymbolLevels() ) drawRendererLevels( fit ); else drawRenderer( fit ); if ( usingEffect ) { mRenderer->paintEffect()->end( mContext ); } return true; }
bool QgsGeometryAnalyzer::simplify( QgsVectorLayer* layer, const QString& shapefileName, double tolerance, bool onlySelectedFeatures, QProgressDialog *p ) { if ( !layer ) { return false; } QgsVectorDataProvider* dp = layer->dataProvider(); if ( !dp ) { return false; } QGis::WkbType outputType = dp->geometryType(); const QgsCoordinateReferenceSystem crs = layer->crs(); QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs ); QgsFeature currentFeature; //take only selection if ( onlySelectedFeatures ) { //use QgsVectorLayer::featureAtId const QgsFeatureIds selection = layer->selectedFeaturesIds(); if ( p ) { p->setMaximum( selection.size() ); } int processedFeatures = 0; QgsFeatureIds::const_iterator it = selection.constBegin(); for ( ; it != selection.constEnd(); ++it ) { if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { break; } if ( !layer->featureAtId( *it, currentFeature, true, true ) ) { continue; } simplifyFeature( currentFeature, &vWriter, tolerance ); ++processedFeatures; } if ( p ) { p->setValue( selection.size() ); } } //take all features else { layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false ); int featureCount = layer->featureCount(); if ( p ) { p->setMaximum( featureCount ); } int processedFeatures = 0; while ( layer->nextFeature( currentFeature ) ) { if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { break; } simplifyFeature( currentFeature, &vWriter, tolerance ); ++processedFeatures; } if ( p ) { p->setValue( featureCount ); } } return true; }
QString QgsPostgresFeatureIterator::whereClauseRect() { QgsRectangle rect = mRequest.filterRect(); if ( mSource->mSpatialColType == sctGeography ) { rect = QgsRectangle( -180.0, -90.0, 180.0, 90.0 ).intersect( &rect ); } if ( !rect.isFinite() ) { QgsMessageLog::logMessage( QObject::tr( "Infinite filter rectangle specified" ), QObject::tr( "PostGIS" ) ); return "false"; } QString qBox; if ( mConn->majorVersion() < 2 ) { qBox = QString( "setsrid('BOX3D(%1)'::box3d,%2)" ) .arg( rect.asWktCoordinates(), mSource->mRequestedSrid.isEmpty() ? mSource->mDetectedSrid : mSource->mRequestedSrid ); } else { qBox = QString( "st_makeenvelope(%1,%2,%3,%4,%5)" ) .arg( qgsDoubleToString( rect.xMinimum() ), qgsDoubleToString( rect.yMinimum() ), qgsDoubleToString( rect.xMaximum() ), qgsDoubleToString( rect.yMaximum() ), mSource->mRequestedSrid.isEmpty() ? mSource->mDetectedSrid : mSource->mRequestedSrid ); } bool castToGeometry = mSource->mSpatialColType == sctGeography || mSource->mSpatialColType == sctPcPatch; QString whereClause = QString( "%1%2 && %3" ) .arg( QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ), castToGeometry ? "::geometry" : "", qBox ); if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) { QString curveToLineFn; // in postgis < 1.5 the st_curvetoline function does not exist if ( mConn->majorVersion() >= 2 || ( mConn->majorVersion() == 1 && mConn->minorVersion() >= 5 ) ) curveToLineFn = "st_curvetoline"; // st_ prefix is always used whereClause += QString( " AND %1(%2(%3%4),%5)" ) .arg( mConn->majorVersion() < 2 ? "intersects" : "st_intersects", curveToLineFn, QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ), castToGeometry ? "::geometry" : "", qBox ); } if ( !mSource->mRequestedSrid.isEmpty() && ( mSource->mRequestedSrid != mSource->mDetectedSrid || mSource->mRequestedSrid.toInt() == 0 ) ) { whereClause += QString( " AND %1(%2%3)=%4" ) .arg( mConn->majorVersion() < 2 ? "srid" : "st_srid", QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ), castToGeometry ? "::geometry" : "", mSource->mRequestedSrid ); } if ( mSource->mRequestedGeomType != QGis::WKBUnknown && mSource->mRequestedGeomType != mSource->mDetectedGeomType ) { whereClause += QString( " AND %1" ).arg( QgsPostgresConn::postgisTypeFilter( mSource->mGeometryColumn, ( QgsWKBTypes::Type )mSource->mRequestedGeomType, castToGeometry ) ); } return whereClause; }
QgsRectangle QgsPointDisplacementRenderer::searchRect( const QgsPoint& p ) const { return QgsRectangle( p.x() - mTolerance, p.y() - mTolerance, p.x() + mTolerance, p.y() + mTolerance ); }