Esempio n. 1
0
QgsProperty QgsProperty::fromValue( const QVariant &value, bool isActive )
{
  QgsProperty p;
  p.setStaticValue( value );
  p.setActive( isActive );
  return p;
}
void QgsPropertyOverrideButton::setToProperty( const QgsProperty &property )
{
  if ( property )
  {
    switch ( property.propertyType() )
    {
      case QgsProperty::StaticProperty:
      case QgsProperty::InvalidProperty:
        break;
      case QgsProperty::FieldBasedProperty:
      {
        mFieldName = property.field();
        break;
      }
      case QgsProperty::ExpressionBasedProperty:
      {
        mExpressionString = property.expressionString();
        break;
      }
    }
  }
  else
  {
    mFieldName.clear();
    mExpressionString.clear();
  }
  mProperty = property;
  setActive( mProperty && mProperty.isActive() );
  updateSiblingWidgets( isActive() );
  updateGui();
}
Esempio n. 3
0
QgsProperty QgsProperty::fromExpression( const QString &expression, bool isActive )
{
  QgsProperty p;
  p.setExpressionString( expression );
  p.setActive( isActive );
  return p;
}
Esempio n. 4
0
QgsProperty QgsProperty::fromField( const QString &fieldName, bool isActive )
{
  QgsProperty p;
  p.setField( fieldName );
  p.setActive( isActive );
  return p;
}
Esempio n. 5
0
QStringList
QgsProject::readListEntry( QString const & scope,
                           const QString & key,
                           bool * ok ) const
{
  QgsProperty * property = findKey_( scope, key, imp_->properties_ );

  QVariant value;

  if ( property )
  {
    value = property->value();
  }

  bool valid = QVariant::StringList == value.type();

  if ( ok )
  {
    *ok = valid;
  }

  if ( valid )
  {
    return value.toStringList();
  }

  return QStringList();
} // QgsProject::readListEntry
Esempio n. 6
0
bool
QgsProject::readBoolEntry( QString const &scope, const QString & key, bool def,
                           bool * ok ) const
{
  QgsProperty * property = findKey_( scope, key, imp_->properties_ );

  QVariant value;

  if ( property )
  {
    value = property->value();
  }

  bool valid = value.canConvert( QVariant::Bool );

  if ( ok )
  {
    *ok = valid;
  }

  if ( valid )
  {
    return value.toBool();
  }

  return def;
} // QgsProject::readBoolEntry
Esempio n. 7
0
QString QgsProcessingAlgorithm::invalidSinkError( const QVariantMap &parameters, const QString &name )
{
  if ( !parameters.contains( name ) )
    return QObject::tr( "Could not create destination layer for %1: no value specified for parameter" ).arg( name );
  else
  {
    QVariant var = parameters.value( name );
    if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
    {
      QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
      var = fromVar.sink;
    }
    if ( var.canConvert<QgsProperty>() )
    {
      QgsProperty p = var.value< QgsProperty >();
      if ( p.propertyType() == QgsProperty::StaticProperty )
      {
        var = p.staticValue();
      }
    }
    if ( !var.toString().isEmpty() )
      return QObject::tr( "Could not create destination layer for %1: %2" ).arg( name, var.toString() );
    else
      return QObject::tr( "Could not create destination layer for %1: invalid value" ).arg( name );
  }
}
Esempio n. 8
0
void QgsEllipseSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
{
  // <Graphic>
  QDomElement graphicElem = doc.createElement( QStringLiteral( "se:Graphic" ) );
  element.appendChild( graphicElem );

  double strokeWidth = QgsSymbolLayerUtils::rescaleUom( mStrokeWidth, mStrokeWidthUnit, props );
  double symbolWidth = QgsSymbolLayerUtils::rescaleUom( mSymbolWidth, mSymbolWidthUnit, props );
  QgsSymbolLayerUtils::wellKnownMarkerToSld( doc, graphicElem, mSymbolName, mColor, mStrokeColor, mStrokeStyle, strokeWidth, symbolWidth );

  // <Rotation>
  QgsProperty ddRotation = mDataDefinedProperties.property( QgsSymbolLayer::PropertyAngle );

  QString angleFunc = props.value( QStringLiteral( "angle" ), QLatin1String( "" ) );
  if ( angleFunc.isEmpty() )  // symbol has no angle set
  {
    if ( ddRotation && ddRotation.isActive() )
    {
      angleFunc = ddRotation.asExpression();
    }
    else if ( !qgsDoubleNear( mAngle, 0.0 ) )
      angleFunc = QString::number( mAngle );
  }
  else if ( ddRotation && ddRotation.isActive() )
  {
    // the symbol has an angle and the symbol layer have a rotation
    // property set
    angleFunc = QStringLiteral( "%1 + %2" ).arg( angleFunc, ddRotation.asExpression() );
  }
  else if ( !qgsDoubleNear( mAngle, 0.0 ) )
  {
    // both the symbol and the symbol layer have angle value set
    bool ok;
    double angle = angleFunc.toDouble( &ok );
    if ( !ok )
    {
      // its a string (probably a property name or a function)
      angleFunc = QStringLiteral( "%1 + %2" ).arg( angleFunc ).arg( mAngle );
    }
    else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
    {
      // it's a double value
      angleFunc = QString::number( angle + mAngle );
    }
  }
  QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc );

  // <Displacement>
  QPointF offset = QgsSymbolLayerUtils::rescaleUom( mOffset, mOffsetUnit, props );
  QgsSymbolLayerUtils::createDisplacementElement( doc, graphicElem, offset );

  // store w/h factor in a <VendorOption>
  double widthHeightFactor = mSymbolWidth / mSymbolHeight;
  QDomElement factorElem = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "widthHeightFactor" ), QString::number( widthHeightFactor ) );
  graphicElem.appendChild( factorElem );
}
Esempio n. 9
0
void QgsSymbolsListWidget::createAuxiliaryField()
{
  // try to create an auxiliary layer if not yet created
  if ( !mLayer->auxiliaryLayer() )
  {
    QgsNewAuxiliaryLayerDialog dlg( mLayer, this );
    dlg.exec();
  }

  // return if still not exists
  if ( !mLayer->auxiliaryLayer() )
    return;

  QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
  QgsSymbolLayer::Property key = static_cast<  QgsSymbolLayer::Property >( button->propertyKey() );
  const QgsPropertyDefinition def = QgsSymbolLayer::propertyDefinitions()[key];

  // create property in auxiliary storage if necessary
  if ( !mLayer->auxiliaryLayer()->exists( def ) )
    mLayer->auxiliaryLayer()->addAuxiliaryField( def );

  // update property with join field name from auxiliary storage
  QgsProperty property = button->toProperty();
  property.setField( QgsAuxiliaryLayer::nameFromProperty( def, true ) );
  property.setActive( true );
  button->updateFieldLists();
  button->setToProperty( property );

  QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
  QgsLineSymbol *lineSymbol = static_cast<QgsLineSymbol *>( mSymbol );
  switch ( key )
  {
    case QgsSymbolLayer::PropertyAngle:
      if ( markerSymbol )
        markerSymbol->setDataDefinedAngle( button->toProperty() );
      break;

    case QgsSymbolLayer::PropertySize:
      if ( markerSymbol )
      {
        markerSymbol->setDataDefinedSize( button->toProperty() );
        markerSymbol->setScaleMethod( QgsSymbol::ScaleDiameter );
      }
      break;

    case QgsSymbolLayer::PropertyStrokeWidth:
      if ( lineSymbol )
        lineSymbol->setDataDefinedWidth( button->toProperty() );
      break;

    default:
      break;
  }

  emit changed();
}
Esempio n. 10
0
QString QgsMapToolLabel::dataDefinedColumnName( QgsPalLayerSettings::Property p, const QgsPalLayerSettings &labelSettings ) const
{
  if ( !labelSettings.dataDefinedProperties().isActive( p ) )
    return QString();

  QgsProperty prop = labelSettings.dataDefinedProperties().property( p );
  if ( prop.propertyType() != QgsProperty::FieldBasedProperty )
    return QString();

  return prop.field();
}
Esempio n. 11
0
void QgsLabelPropertyDialog::insertChangedValue( QgsPalLayerSettings::Property p, const QVariant &value )
{
  if ( mDataDefinedProperties.isActive( p ) )
  {
    QgsProperty prop = mDataDefinedProperties.property( p );
    if ( prop.propertyType() == QgsProperty::FieldBasedProperty )
    {
      mChangedProperties.insert( mCurLabelFeat.fieldNameIndex( prop.field() ), value );
    }
  }
}
Esempio n. 12
0
QVariant QgsPropertyKey::value() const
{
  QgsProperty *foundQgsProperty = mProperties.value( name() );

  if ( !foundQgsProperty )
  {
    QgsDebugMsg( "key has null child" );
    return QVariant();     // just return an QVariant::Invalid
  }

  return foundQgsProperty->value();
} // QVariant QgsPropertyKey::value()
Esempio n. 13
0
QVariant QgsPropertyKey::value() const
{
  QgsProperty * foundQgsProperty;

  if ( 0 == ( foundQgsProperty = mProperties.value( name() ) ) )
  {                        // recurse down to next key
    return foundQgsProperty->value();
  }
  else
  {
    QgsDebugMsg( "key has null child" );

    return QVariant();     // just return an QVariant::Invalid
  }
} // QVariant QgsPropertyKey::value()
Esempio n. 14
0
void QgsDataDefinedSizeLegend::updateFromSymbolAndProperty( const QgsMarkerSymbol *symbol, const QgsProperty &ddSize )
{
  mSymbol.reset( symbol->clone() );
  mSymbol->setDataDefinedSize( QgsProperty() );  // original symbol may have had data-defined size associated

  const QgsSizeScaleTransformer *sizeTransformer = dynamic_cast< const QgsSizeScaleTransformer * >( ddSize.transformer() );
  mSizeScaleTransformer.reset( sizeTransformer ? sizeTransformer->clone() : nullptr );

  if ( mTitleLabel.isEmpty() )
    mTitleLabel = ddSize.propertyType() == QgsProperty::ExpressionBasedProperty ? ddSize.expressionString() : ddSize.field();

  // automatically generate classes if no classes are defined
  if ( sizeTransformer && mSizeClasses.isEmpty() )
  {
    mSizeClasses.clear();
    Q_FOREACH ( double v, QgsSymbolLayerUtils::prettyBreaks( sizeTransformer->minValue(), sizeTransformer->maxValue(), 4 ) )
    {
      mSizeClasses << SizeClass( v, QString::number( v ) );
    }
  }
Esempio n. 15
0
bool QgsMapToolLabel::createAuxiliaryFields( LabelDetails &details, QgsPalIndexes &indexes ) const
{
  bool newAuxiliaryLayer = false;
  QgsVectorLayer *vlayer = details.layer;
  QString providerId = details.pos.providerID;

  if ( !vlayer || !vlayer->labelsEnabled() )
    return false;

  if ( !vlayer->auxiliaryLayer() )
  {
    QgsNewAuxiliaryLayerDialog dlg( vlayer );
    dlg.exec();
    newAuxiliaryLayer = true;
  }

  if ( !vlayer->auxiliaryLayer() )
    return false;

  for ( const QgsPalLayerSettings::Property &p : qgis::as_const( mPalProperties ) )
  {
    int index = -1;

    // always use the default activated property
    QgsProperty prop = details.settings.dataDefinedProperties().property( p );
    if ( prop.propertyType() == QgsProperty::FieldBasedProperty && prop.isActive() )
    {
      index = vlayer->fields().lookupField( prop.field() );
    }
    else
    {
      index = QgsAuxiliaryLayer::createProperty( p, vlayer );
    }

    indexes[p] = index;
  }

  details.settings = vlayer->labeling()->settings( providerId );

  return newAuxiliaryLayer;
}
Esempio n. 16
0
QString QgsProcessingAlgorithm::invalidRasterError( const QVariantMap &parameters, const QString &name )
{
  if ( !parameters.contains( name ) )
    return QObject::tr( "Could not load source layer for %1: no value specified for parameter" ).arg( name );
  else
  {
    QVariant var = parameters.value( name );
    if ( var.canConvert<QgsProperty>() )
    {
      QgsProperty p = var.value< QgsProperty >();
      if ( p.propertyType() == QgsProperty::StaticProperty )
      {
        var = p.staticValue();
      }
    }
    if ( !var.toString().isEmpty() )
      return QObject::tr( "Could not load source layer for %1: %2 not found" ).arg( name, var.toString() );
    else
      return QObject::tr( "Could not load source layer for %1: invalid value" ).arg( name );
  }
}
Esempio n. 17
0
bool QgsMapToolLabel::createAuxiliaryFields( LabelDetails &details, QgsDiagramIndexes &indexes )
{
  bool newAuxiliaryLayer = false;
  QgsVectorLayer *vlayer = details.layer;

  if ( !vlayer )
    return newAuxiliaryLayer;

  if ( !vlayer->auxiliaryLayer() )
  {
    QgsNewAuxiliaryLayerDialog dlg( vlayer );
    dlg.exec();
    newAuxiliaryLayer = true;
  }

  if ( !vlayer->auxiliaryLayer() )
    return false;

  for ( const QgsDiagramLayerSettings::Property &p : qgis::as_const( mDiagramProperties ) )
  {
    int index = -1;

    // always use the default activated property
    QgsProperty prop = vlayer->diagramLayerSettings()->dataDefinedProperties().property( p );
    if ( prop.propertyType() == QgsProperty::FieldBasedProperty && prop.isActive() )
    {
      index = vlayer->fields().lookupField( prop.field() );
    }
    else
    {
      index = QgsAuxiliaryLayer::createProperty( p, vlayer );
    }

    indexes[p] = index;
  }

  return newAuxiliaryLayer;
}
Esempio n. 18
0
/**
   return the property that matches the given key sequence, if any

   @param scope scope of key
   @param key keyname
   @param rootProperty is likely to be the top level QgsPropertyKey in QgsProject:e:Imp.

   @return null if not found, otherwise located Property
*/
static
QgsProperty * findKey_( QString const & scope,
                        QString const & key,
                        QgsPropertyKey &   rootProperty )
{
  QgsPropertyKey * currentProperty = &rootProperty;
  QgsProperty * nextProperty;           // link to next property down hiearchy

  QStringList keySequence = makeKeyTokens_( scope, key );

  while ( ! keySequence.isEmpty() )
  {
    // if the current head of the sequence list matches the property name,
    // then traverse down the property hierarchy
    if ( keySequence.first() == currentProperty->name() )
    {
      // remove front key since we're traversing down a level
      keySequence.pop_front();

      // if we have only one key name left, then return the key found
      if ( 1 == keySequence.count() )
      {
        return currentProperty->find( keySequence.front() );

      }
      // if we're out of keys then the current property is the one we
      // want; i.e., we're in the rate case of being at the top-most
      // property node
      else if ( keySequence.isEmpty() )
      {
        return currentProperty;
      }
      else if (( nextProperty = currentProperty->find( keySequence.first() ) ) )
      {
        if ( nextProperty->isKey() )
        {
          currentProperty = dynamic_cast<QgsPropertyKey*>( nextProperty );
        }
        // it may be that this may be one of several property value
        // nodes keyed by QDict string; if this is the last remaining
        // key token and the next property is a value node, then
        // that's the situation, so return the currentProperty
        else if ( nextProperty->isValue() && ( 1 == keySequence.count() ) )
        {
          return currentProperty;
        }
        else            // QgsPropertyValue not Key, so return null
        {
          return 0x0;
        }
      }
      else                // if the next key down isn't found
      {                   // then the overall key sequence doesn't exist
        return 0x0;
      }
    }
    else
    {
      return 0x0;
    }
  }

  return 0x0;
} // findKey_
Esempio n. 19
0
QVariant QgsXmlUtils::readVariant( const QDomElement &element )
{
  QString type = element.attribute( QStringLiteral( "type" ) );

  if ( type == QLatin1String( "invalid" ) )
  {
    return QVariant();
  }
  else if ( type == QLatin1String( "int" ) )
  {
    return element.attribute( QStringLiteral( "value" ) ).toInt();
  }
  else if ( type == QLatin1String( "uint" ) )
  {
    return element.attribute( QStringLiteral( "value" ) ).toUInt();
  }
  else if ( type == QLatin1String( "qlonglong" ) )
  {
    return element.attribute( QStringLiteral( "value" ) ).toLongLong();
  }
  else if ( type == QLatin1String( "qulonglong" ) )
  {
    return element.attribute( QStringLiteral( "value" ) ).toULongLong();
  }
  else if ( type == QLatin1String( "double" ) )
  {
    return element.attribute( QStringLiteral( "value" ) ).toDouble();
  }
  else if ( type == QLatin1String( "QString" ) )
  {
    return element.attribute( QStringLiteral( "value" ) );
  }
  else if ( type == QLatin1String( "bool" ) )
  {
    return element.attribute( QStringLiteral( "value" ) ) == QLatin1String( "true" );
  }
  else if ( type == QLatin1String( "Map" ) )
  {
    QVariantMap map;
    QDomNodeList options = element.childNodes();

    for ( int i = 0; i < options.count(); ++i )
    {
      QDomElement elem = options.at( i ).toElement();
      if ( elem.tagName() == QLatin1String( "Option" ) )
        map.insert( elem.attribute( QStringLiteral( "name" ) ), readVariant( elem ) );
    }
    return map;
  }
  else if ( type == QLatin1String( "List" ) )
  {
    QVariantList list;
    QDomNodeList values = element.childNodes();
    for ( int i = 0; i < values.count(); ++i )
    {
      QDomElement elem = values.at( i ).toElement();
      list.append( readVariant( elem ) );
    }
    return list;
  }
  else if ( type == QLatin1String( "StringList" ) )
  {
    QStringList list;
    QDomNodeList values = element.childNodes();
    for ( int i = 0; i < values.count(); ++i )
    {
      QDomElement elem = values.at( i ).toElement();
      list.append( readVariant( elem ).toString() );
    }
    return list;
  }
  else if ( type == QLatin1String( "QgsProperty" ) )
  {
    const QDomNodeList values = element.childNodes();
    if ( values.isEmpty() )
      return QVariant();

    QgsProperty p;
    if ( p.loadVariant( QgsXmlUtils::readVariant( values.at( 0 ).toElement() ) ) )
      return p;

    return QVariant();
  }
  else if ( type == QLatin1String( "QgsCoordinateReferenceSystem" ) )
  {
    QgsCoordinateReferenceSystem crs;
    crs.readXml( element );
    return crs;
  }
  else if ( type == QLatin1String( "QgsGeometry" ) )
  {
    return QgsGeometry::fromWkt( element.attribute( "value" ) );
  }
  else
  {
    return QVariant();
  }
}
Esempio n. 20
0
void QgsLabelPropertyDialog::enableDataDefinedWidgets( QgsVectorLayer *vlayer )
{
  //loop through data defined properties, this time setting whether or not the widgets are enabled
  //this can only be done for properties which are assigned to fields
  Q_FOREACH ( int key, mDataDefinedProperties.propertyKeys() )
  {
    QgsProperty prop = mDataDefinedProperties.property( key );
    if ( !prop || !prop.isActive() || prop.propertyType() != QgsProperty::FieldBasedProperty )
    {
      continue; // can only modify attributes with an active data definition of a mapped field
    }

    QString ddField = prop.field();
    if ( ddField.isEmpty() )
    {
      continue;
    }

    int ddIndx = vlayer->fields().lookupField( ddField );
    if ( ddIndx == -1 )
    {
      continue;
    }

    QgsDebugMsg( QStringLiteral( "ddField: %1" ).arg( ddField ) );

    switch ( key )
    {
      case QgsPalLayerSettings::Show:
        mShowLabelChkbx->setEnabled( true );
        break;
      case QgsPalLayerSettings::AlwaysShow:
        mAlwaysShowChkbx->setEnabled( true );
        break;
      case QgsPalLayerSettings::MinimumScale:
        mMinScaleWidget->setEnabled( true );
        break;
      case QgsPalLayerSettings::MaximumScale:
        mMaxScaleWidget->setEnabled( true );
        break;
      case QgsPalLayerSettings::BufferSize:
        mBufferSizeSpinBox->setEnabled( true );
        break;
      case QgsPalLayerSettings::PositionX:
        mXCoordSpinBox->setEnabled( true );
        break;
      case QgsPalLayerSettings::PositionY:
        mYCoordSpinBox->setEnabled( true );
        break;
      case QgsPalLayerSettings::LabelDistance:
        mLabelDistanceSpinBox->setEnabled( true );
        break;
      case QgsPalLayerSettings::Hali:
        mHaliComboBox->setEnabled( true );
        break;
      case QgsPalLayerSettings::Vali:
        mValiComboBox->setEnabled( true );
        break;
      case QgsPalLayerSettings::BufferColor:
        mBufferColorButton->setEnabled( true );
        break;
      case QgsPalLayerSettings::Color:
        mFontColorButton->setEnabled( true );
        break;
      case QgsPalLayerSettings::LabelRotation:
        mRotationSpinBox->setEnabled( true );
        break;
      //font related properties
      case QgsPalLayerSettings::Family:
        mFontFamilyCmbBx->setEnabled( true );
        break;
      case QgsPalLayerSettings::FontStyle:
        mFontStyleCmbBx->setEnabled( true );
        break;
      case QgsPalLayerSettings::Underline:
        mFontUnderlineBtn->setEnabled( true );
        break;
      case QgsPalLayerSettings::Strikeout:
        mFontStrikethroughBtn->setEnabled( true );
        break;
      case QgsPalLayerSettings::Bold:
        mFontBoldBtn->setEnabled( true );
        break;
      case QgsPalLayerSettings::Italic:
        mFontItalicBtn->setEnabled( true );
        break;
      case QgsPalLayerSettings::Size:
        mFontSizeSpinBox->setEnabled( true );
        break;
      default:
        break;
    }
  }
}
Esempio n. 21
0
QVariantMap QgsJoinWithLinesAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
  if ( parameters.value( QStringLiteral( "SPOKES" ) ) == parameters.value( QStringLiteral( "HUBS" ) ) )
    throw QgsProcessingException( QObject::tr( "Same layer given for both hubs and spokes" ) );

  std::unique_ptr< QgsProcessingFeatureSource > hubSource( parameterAsSource( parameters, QStringLiteral( "HUBS" ), context ) );
  if ( !hubSource )
    throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "HUBS" ) ) );

  std::unique_ptr< QgsProcessingFeatureSource > spokeSource( parameterAsSource( parameters, QStringLiteral( "SPOKES" ), context ) );
  if ( !hubSource || !spokeSource )
    throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "SPOKES" ) ) );

  QString fieldHubName = parameterAsString( parameters, QStringLiteral( "HUB_FIELD" ), context );
  int fieldHubIndex = hubSource->fields().lookupField( fieldHubName );
  const QStringList hubFieldsToCopy = parameterAsFields( parameters, QStringLiteral( "HUB_FIELDS" ), context );

  QString fieldSpokeName = parameterAsString( parameters, QStringLiteral( "SPOKE_FIELD" ), context );
  int fieldSpokeIndex = spokeSource->fields().lookupField( fieldSpokeName );
  const QStringList spokeFieldsToCopy = parameterAsFields( parameters, QStringLiteral( "SPOKE_FIELDS" ), context );

  if ( fieldHubIndex < 0 || fieldSpokeIndex < 0 )
    throw QgsProcessingException( QObject::tr( "Invalid ID field" ) );

  const bool geodesic = parameterAsBool( parameters, QStringLiteral( "GEODESIC" ), context );
  const double geodesicDistance = parameterAsDouble( parameters, QStringLiteral( "GEODESIC_DISTANCE" ), context ) * 1000;
  bool dynamicGeodesicDistance = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "GEODESIC_DISTANCE" ) );
  QgsExpressionContext expressionContext = createExpressionContext( parameters, context, hubSource.get() );
  QgsProperty geodesicDistanceProperty;
  if ( dynamicGeodesicDistance )
  {
    geodesicDistanceProperty = parameters.value( QStringLiteral( "GEODESIC_DISTANCE" ) ).value< QgsProperty >();
  }

  const bool splitAntimeridian = parameterAsBool( parameters, QStringLiteral( "ANTIMERIDIAN_SPLIT" ), context );
  QgsDistanceArea da;
  da.setSourceCrs( hubSource->sourceCrs(), context.transformContext() );
  da.setEllipsoid( context.project()->ellipsoid() );

  QgsFields hubOutFields;
  QgsAttributeList hubFieldIndices;
  if ( hubFieldsToCopy.empty() )
  {
    hubOutFields = hubSource->fields();
    hubFieldIndices.reserve( hubOutFields.count() );
    for ( int i = 0; i < hubOutFields.count(); ++i )
    {
      hubFieldIndices << i;
    }
  }
  else
  {
    hubFieldIndices.reserve( hubOutFields.count() );
    for ( const QString &field : hubFieldsToCopy )
    {
      int index = hubSource->fields().lookupField( field );
      if ( index >= 0 )
      {
        hubFieldIndices << index;
        hubOutFields.append( hubSource->fields().at( index ) );
      }
    }
  }

  QgsAttributeList hubFields2Fetch = hubFieldIndices;
  hubFields2Fetch << fieldHubIndex;

  QgsFields spokeOutFields;
  QgsAttributeList spokeFieldIndices;
  if ( spokeFieldsToCopy.empty() )
  {
    spokeOutFields = spokeSource->fields();
    spokeFieldIndices.reserve( spokeOutFields.count() );
    for ( int i = 0; i < spokeOutFields.count(); ++i )
    {
      spokeFieldIndices << i;
    }
  }
  else
  {
    for ( const QString &field : spokeFieldsToCopy )
    {
      int index = spokeSource->fields().lookupField( field );
      if ( index >= 0 )
      {
        spokeFieldIndices << index;
        spokeOutFields.append( spokeSource->fields().at( index ) );
      }
    }
  }

  QgsAttributeList spokeFields2Fetch = spokeFieldIndices;
  spokeFields2Fetch << fieldSpokeIndex;


  QgsFields fields = QgsProcessingUtils::combineFields( hubOutFields, spokeOutFields );

  QgsWkbTypes::Type outType = geodesic ? QgsWkbTypes::MultiLineString : QgsWkbTypes::LineString;
  bool hasZ = false;
  if ( QgsWkbTypes::hasZ( hubSource->wkbType() ) || QgsWkbTypes::hasZ( spokeSource->wkbType() ) )
  {
    outType = QgsWkbTypes::addZ( outType );
    hasZ = true;
  }
  bool hasM = false;
  if ( QgsWkbTypes::hasM( hubSource->wkbType() ) || QgsWkbTypes::hasM( spokeSource->wkbType() ) )
  {
    outType = QgsWkbTypes::addM( outType );
    hasM = true;
  }

  QString dest;
  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields,
                                          outType, hubSource->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) );
  if ( !sink )
    throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

  auto getPointFromFeature = [hasZ, hasM]( const QgsFeature & feature )->QgsPoint
  {
    QgsPoint p;
    if ( feature.geometry().type() == QgsWkbTypes::PointGeometry && !feature.geometry().isMultipart() )
      p = *static_cast< const QgsPoint *>( feature.geometry().constGet() );
    else
      p = *static_cast< const QgsPoint *>( feature.geometry().pointOnSurface().constGet() );
    if ( hasZ && !p.is3D() )
      p.addZValue( 0 );
    if ( hasM && !p.isMeasure() )
      p.addMValue( 0 );
    return p;
  };

  QgsFeatureIterator hubFeatures = hubSource->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( hubFields2Fetch ), QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks );
  double step = hubSource->featureCount() > 0 ? 100.0 / hubSource->featureCount() : 1;
  int i = 0;
  QgsFeature hubFeature;
  while ( hubFeatures.nextFeature( hubFeature ) )
  {
    i++;
    if ( feedback->isCanceled() )
    {
      break;
    }

    feedback->setProgress( i * step );

    if ( !hubFeature.hasGeometry() )
      continue;

    QgsPoint hubPoint = getPointFromFeature( hubFeature );

    // only keep selected attributes
    QgsAttributes hubAttributes;
    for ( int j = 0; j < hubFeature.attributes().count(); ++j )
    {
      if ( !hubFieldIndices.contains( j ) )
        continue;
      hubAttributes << hubFeature.attribute( j );
    }

    QgsFeatureRequest spokeRequest = QgsFeatureRequest().setDestinationCrs( hubSource->sourceCrs(), context.transformContext() );
    spokeRequest.setSubsetOfAttributes( spokeFields2Fetch );
    spokeRequest.setFilterExpression( QgsExpression::createFieldEqualityExpression( fieldSpokeName, hubFeature.attribute( fieldHubIndex ) ) );

    QgsFeatureIterator spokeFeatures = spokeSource->getFeatures( spokeRequest, QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks );
    QgsFeature spokeFeature;
    while ( spokeFeatures.nextFeature( spokeFeature ) )
    {
      if ( feedback->isCanceled() )
      {
        break;
      }
      if ( !spokeFeature.hasGeometry() )
        continue;

      QgsPoint spokePoint = getPointFromFeature( spokeFeature );
      QgsGeometry line;
      if ( !geodesic )
      {
        line = QgsGeometry( new QgsLineString( QVector< QgsPoint >() << hubPoint << spokePoint ) );
        if ( splitAntimeridian )
          line = da.splitGeometryAtAntimeridian( line );
      }
      else
      {
        double distance = geodesicDistance;
        if ( dynamicGeodesicDistance )
        {
          expressionContext.setFeature( hubFeature );
          distance = geodesicDistanceProperty.valueAsDouble( expressionContext, distance );
        }

        std::unique_ptr< QgsMultiLineString > ml = qgis::make_unique< QgsMultiLineString >();
        std::unique_ptr< QgsLineString > l = qgis::make_unique< QgsLineString >( QVector< QgsPoint >() << hubPoint );
        QVector< QVector< QgsPointXY > > points = da.geodesicLine( QgsPointXY( hubPoint ), QgsPointXY( spokePoint ), distance, splitAntimeridian );
        QVector< QgsPointXY > points1 = points.at( 0 );
        points1.pop_front();
        if ( points.count() == 1 )
          points1.pop_back();

        QgsLineString geodesicPoints( points1 );
        l->append( &geodesicPoints );
        if ( points.count() == 1 )
          l->addVertex( spokePoint );

        ml->addGeometry( l.release() );
        if ( points.count() > 1 )
        {
          QVector< QgsPointXY > points2 = points.at( 1 );
          points2.pop_back();
          l = qgis::make_unique< QgsLineString >( points2 );
          if ( hasZ )
            l->addZValue( std::numeric_limits<double>::quiet_NaN() );
          if ( hasM )
            l->addMValue( std::numeric_limits<double>::quiet_NaN() );

          l->addVertex( spokePoint );
          ml->addGeometry( l.release() );
        }
        line = QgsGeometry( std::move( ml ) );
      }

      QgsFeature outFeature;
      QgsAttributes outAttributes = hubAttributes;

      // only keep selected attributes
      QgsAttributes spokeAttributes;
      for ( int j = 0; j < spokeFeature.attributes().count(); ++j )
      {
        if ( !spokeFieldIndices.contains( j ) )
          continue;
        spokeAttributes << spokeFeature.attribute( j );
      }

      outAttributes.append( spokeAttributes );
      outFeature.setAttributes( outAttributes );
      outFeature.setGeometry( line );
      sink->addFeature( outFeature, QgsFeatureSink::FastInsert );
    }
  }

  QVariantMap outputs;
  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
  return outputs;
}
Esempio n. 22
0
QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
  std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
  if ( !source )
    throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );

  QString dest;
  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(), QgsWkbTypes::Polygon, source->sourceCrs() ) );
  if ( !sink )
    throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

  // fixed parameters
  bool dissolve = parameterAsBool( parameters, QStringLiteral( "DISSOLVE" ), context );
  int segments = parameterAsInt( parameters, QStringLiteral( "SEGMENTS" ), context );
  QgsGeometry::EndCapStyle endCapStyle = static_cast< QgsGeometry::EndCapStyle >( 1 + parameterAsInt( parameters, QStringLiteral( "END_CAP_STYLE" ), context ) );
  QgsGeometry::JoinStyle joinStyle = static_cast< QgsGeometry::JoinStyle>( 1 + parameterAsInt( parameters, QStringLiteral( "JOIN_STYLE" ), context ) );
  double miterLimit = parameterAsDouble( parameters, QStringLiteral( "MITER_LIMIT" ), context );
  double bufferDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context );
  bool dynamicBuffer = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) );
  QgsExpressionContext expressionContext = createExpressionContext( parameters, context, dynamic_cast< QgsProcessingFeatureSource * >( source.get() ) );
  QgsProperty bufferProperty;
  if ( dynamicBuffer )
  {
    bufferProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value< QgsProperty >();
  }

  long count = source->featureCount();

  QgsFeature f;
  QgsFeatureIterator it = source->getFeatures();

  double step = count > 0 ? 100.0 / count : 1;
  int current = 0;

  QVector< QgsGeometry > bufferedGeometriesForDissolve;
  QgsAttributes dissolveAttrs;

  while ( it.nextFeature( f ) )
  {
    if ( feedback->isCanceled() )
    {
      break;
    }
    if ( dissolveAttrs.isEmpty() )
      dissolveAttrs = f.attributes();

    QgsFeature out = f;
    if ( out.hasGeometry() )
    {
      double distance =  bufferDistance;
      if ( dynamicBuffer )
      {
        expressionContext.setFeature( f );
        distance = bufferProperty.valueAsDouble( expressionContext, bufferDistance );
      }

      QgsGeometry outputGeometry = f.geometry().buffer( distance, segments, endCapStyle, joinStyle, miterLimit );
      if ( !outputGeometry )
      {
        QgsMessageLog::logMessage( QObject::tr( "Error calculating buffer for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), Qgis::Warning );
      }
      if ( dissolve )
        bufferedGeometriesForDissolve << outputGeometry;
      else
        out.setGeometry( outputGeometry );
    }

    if ( !dissolve )
      sink->addFeature( out, QgsFeatureSink::FastInsert );

    feedback->setProgress( current * step );
    current++;
  }

  if ( dissolve )
  {
    QgsGeometry finalGeometry = QgsGeometry::unaryUnion( bufferedGeometriesForDissolve );
    QgsFeature f;
    f.setGeometry( finalGeometry );
    f.setAttributes( dissolveAttrs );
    sink->addFeature( f, QgsFeatureSink::FastInsert );
  }

  QVariantMap outputs;
  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
  return outputs;
}
Esempio n. 23
0
QVariantMap QgsTransectAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
  Side orientation = static_cast< QgsTransectAlgorithm::Side >( parameterAsInt( parameters, QStringLiteral( "SIDE" ), context ) );
  double angle = fabs( parameterAsDouble( parameters, QStringLiteral( "ANGLE" ), context ) );
  bool dynamicAngle = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "ANGLE" ) );
  QgsProperty angleProperty;
  if ( dynamicAngle )
    angleProperty = parameters.value( QStringLiteral( "ANGLE" ) ).value< QgsProperty >();

  double length = parameterAsDouble( parameters, QStringLiteral( "LENGTH" ), context );
  bool dynamicLength = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "LENGTH" ) );
  QgsProperty lengthProperty;
  if ( dynamicLength )
    lengthProperty = parameters.value( QStringLiteral( "LENGTH" ) ).value< QgsProperty >();

  if ( orientation == QgsTransectAlgorithm::Both )
    length /= 2.0;

  std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
  if ( !source )
    throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );

  QgsExpressionContext expressionContext = createExpressionContext( parameters, context, dynamic_cast< QgsProcessingFeatureSource * >( source.get() ) );

  QgsFields fields = source->fields();

  fields.append( QgsField( QStringLiteral( "TR_FID" ), QVariant::Int, QString(), 20 ) );
  fields.append( QgsField( QStringLiteral( "TR_ID" ), QVariant::Int, QString(), 20 ) );
  fields.append( QgsField( QStringLiteral( "TR_SEGMENT" ), QVariant::Int, QString(), 20 ) );
  fields.append( QgsField( QStringLiteral( "TR_ANGLE" ), QVariant::Double, QString(), 5, 2 ) );
  fields.append( QgsField( QStringLiteral( "TR_LENGTH" ), QVariant::Double, QString(), 20, 6 ) );
  fields.append( QgsField( QStringLiteral( "TR_ORIENT" ), QVariant::Int, QString(), 1 ) );

  QgsWkbTypes::Type outputWkb = QgsWkbTypes::LineString;
  if ( QgsWkbTypes::hasZ( source->wkbType() ) )
    outputWkb = QgsWkbTypes::addZ( outputWkb );
  if ( QgsWkbTypes::hasM( source->wkbType() ) )
    outputWkb = QgsWkbTypes::addM( outputWkb );

  QString dest;
  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields,
                                          outputWkb, source->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) );
  if ( !sink )
    throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

  QgsFeatureIterator features = source->getFeatures( );

  int current = -1;
  int number = 0;
  double step =  source->featureCount() > 0 ? 100.0 / source->featureCount() : 1;
  QgsFeature feat;


  while ( features.nextFeature( feat ) )
  {
    current++;
    if ( feedback->isCanceled() )
    {
      break;
    }

    feedback->setProgress( current * step );
    if ( !feat.hasGeometry() )
      continue;

    QgsGeometry inputGeometry = feat.geometry();

    if ( dynamicLength || dynamicAngle )
    {
      expressionContext.setFeature( feat );
    }

    double evaluatedLength = length;
    if ( dynamicLength )
      evaluatedLength = lengthProperty.valueAsDouble( context.expressionContext(), length );
    double evaluatedAngle = angle;
    if ( dynamicAngle )
      evaluatedAngle = angleProperty.valueAsDouble( context.expressionContext(), angle );

    inputGeometry.convertToMultiType();
    const QgsMultiLineString *multiLine = static_cast< const QgsMultiLineString *  >( inputGeometry.constGet() );
    for ( int id = 0; id < multiLine->numGeometries(); ++id )
    {
      const QgsLineString *line = static_cast< const QgsLineString * >( multiLine->geometryN( id ) );
      QgsAbstractGeometry::vertex_iterator it = line->vertices_begin();
      while ( it != line->vertices_end() )
      {
        QgsVertexId vertexId = it.vertexId();
        int i = vertexId.vertex;
        QgsFeature outFeat;
        QgsAttributes attrs = feat.attributes();
        attrs << current << number << i + 1 << evaluatedAngle <<
              ( ( orientation == QgsTransectAlgorithm::Both ) ? evaluatedLength * 2 : evaluatedLength ) <<
              orientation;
        outFeat.setAttributes( attrs );
        double angleAtVertex = line->vertexAngle( vertexId );
        outFeat.setGeometry( calcTransect( *it, angleAtVertex, evaluatedLength, orientation, evaluatedAngle ) );
        sink->addFeature( outFeat, QgsFeatureSink::FastInsert );
        number++;
        it++;
      }
    }
  }

  QVariantMap outputs;
  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
  return outputs;
}