Beispiel #1
0
void QgsMarkerSymbolLayerV2::markerOffset( const QgsSymbolV2RenderContext& context, double width, double height,
    QgsSymbolV2::OutputUnit widthUnit, QgsSymbolV2::OutputUnit heightUnit,
    double& offsetX, double& offsetY ) const
{
  offsetX = mOffset.x();
  offsetY = mOffset.y();

  QgsExpression* offsetExpression = expression( "offset" );
  if ( offsetExpression )
  {
    QPointF offset = QgsSymbolLayerV2Utils::decodePoint( offsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() );
    offsetX = offset.x();
    offsetY = offset.y();
  }

  offsetX *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit );
  offsetY *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit );

  HorizontalAnchorPoint horizontalAnchorPoint = mHorizontalAnchorPoint;
  VerticalAnchorPoint verticalAnchorPoint = mVerticalAnchorPoint;
  QgsExpression* horizontalAnchorExpression = expression( "horizontal_anchor_point" );
  if ( horizontalAnchorExpression )
  {
    horizontalAnchorPoint = decodeHorizontalAnchorPoint( horizontalAnchorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() );
  }
  QgsExpression* verticalAnchorExpression = expression( "vertical_anchor_point" );
  if ( verticalAnchorExpression )
  {
    verticalAnchorPoint = decodeVerticalAnchorPoint( verticalAnchorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() );
  }

  //correct horizontal position according to anchor point
  if ( horizontalAnchorPoint == HCenter && verticalAnchorPoint == VCenter )
  {
    return;
  }

  double anchorPointCorrectionX = width * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), widthUnit ) / 2.0;
  double anchorPointCorrectionY = height * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), heightUnit ) / 2.0;
  if ( horizontalAnchorPoint == Left )
  {
    offsetX += anchorPointCorrectionX;
  }
  else if ( horizontalAnchorPoint == Right )
  {
    offsetX -= anchorPointCorrectionX;
  }

  //correct vertical position according to anchor point
  if ( verticalAnchorPoint == Top )
  {
    offsetY += anchorPointCorrectionY;
  }
  else if ( verticalAnchorPoint == Bottom )
  {
    offsetY -= anchorPointCorrectionY;
  }
}
void QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context )
{
  double offset = mOffset;
  QgsExpression* offsetExpression = expression( "offset" );
  if ( offsetExpression )
  {
    offset = offsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }

  Placement placement = mPlacement;
  QgsExpression* placementExpression = expression( "placement" );
  if ( placementExpression )
  {
    QString placementString = placementExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
    if ( placementString.compare( "vertex", Qt::CaseInsensitive ) == 0 )
    {
      placement = Vertex;
    }
    else if ( placementString.compare( "lastvertex", Qt::CaseInsensitive ) == 0 )
    {
      placement = LastVertex;
    }
    else if ( placementString.compare( "firstvertex", Qt::CaseInsensitive ) == 0 )
    {
      placement = FirstVertex;
    }
    else if ( placementString.compare( "centerpoint", Qt::CaseInsensitive ) == 0 )
    {
      placement = CentralPoint;
    }
    else
    {
      placement = Interval;
    }
  }

  if ( offset == 0 )
  {
    if ( placement == Interval )
      renderPolylineInterval( points, context );
    else if ( placement == CentralPoint )
      renderPolylineCentral( points, context );
    else
      renderPolylineVertex( points, context, placement );
  }
  else
  {
    QPolygonF points2 = ::offsetLine( points, offset * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit ) );
    if ( placement == Interval )
      renderPolylineInterval( points2, context );
    else if ( placement == CentralPoint )
      renderPolylineCentral( points2, context );
    else
      renderPolylineVertex( points2, context, placement );
  }
}
void QgsExpressionSelectionDialog::on_mActionSelectInstersect_triggered()
{
  const QgsFeatureIds &oldSelection = mLayer->selectedFeaturesIds();
  QgsFeatureIds newSelection;

  QgsExpression* expression = new QgsExpression( mExpressionBuilder->expressionText() );

  const QgsFields fields = mLayer->fields();

  expression->prepare( fields );

  QgsFeature feat;
  foreach ( const QgsFeatureId fid, oldSelection )
  {
    QgsFeatureIterator features = mLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) );

    if ( features.nextFeature( feat ) )
    {
      if ( expression->evaluate( &feat, fields ).toBool() )
      {
        newSelection << feat.id();
      }
    }
    else
    {
      Q_ASSERT( false );
    }

    features.close();
  }
Beispiel #4
0
QSizeF QgsTextDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
{
  QgsExpressionContext expressionContext = c.expressionContext();
  expressionContext.setFeature( feature );
  if ( feature.fields() )
    expressionContext.setFields( *feature.fields() );

  QVariant attrVal;
  if ( is.classificationAttributeIsExpression )
  {
    QgsExpression* expression = getExpression( is.classificationAttributeExpression, expressionContext );
    attrVal = expression->evaluate( &expressionContext );
  }
  else
  {
    attrVal = feature.attributes().at( is.classificationAttribute );
  }

  bool ok = false;
  double val = attrVal.toDouble( &ok );
  if ( !ok )
  {
    return QSizeF(); //zero size if attribute is missing
  }

  return sizeForValue( val, s, is );
}
void QgsExpressionSelectionDialog::on_mActionAddToSelection_triggered()
{
  QgsFeatureIds newSelection = mLayer->selectedFeaturesIds();
  QgsExpression* expression = new QgsExpression( mExpressionBuilder->expressionText() );

  const QgsFields fields = mLayer->fields();

  QgsFeatureIterator features = mLayer->getFeatures();

  expression->prepare( fields );

  QgsFeature feat;
  while ( features.nextFeature( feat ) )
  {
    if ( expression->evaluate( &feat, fields ).toBool() )
    {
      newSelection << feat.id();
    }
  }

  features.close();

  mLayer->setSelectedFeatures( newSelection );

  delete expression;
  saveRecent();
}
void QgsExpressionSelectionDialog::on_mActionSelectIntersect_triggered()
{
  const QgsFeatureIds &oldSelection = mLayer->selectedFeaturesIds();
  QgsFeatureIds newSelection;

  QgsExpression* expression = new QgsExpression( mExpressionBuilder->expressionText() );

  QgsExpressionContext context;
  context << QgsExpressionContextUtils::globalScope()
  << QgsExpressionContextUtils::projectScope()
  << QgsExpressionContextUtils::layerScope( mLayer );

  expression->prepare( &context );

  QgsFeature feat;
  Q_FOREACH ( const QgsFeatureId fid, oldSelection )
  {
    QgsFeatureIterator features = mLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) );

    if ( features.nextFeature( feat ) )
    {
      context.setFeature( feat );
      if ( expression->evaluate( &context ).toBool() )
      {
        newSelection << feat.id();
      }
    }
    else
    {
      Q_ASSERT( false );
    }

    features.close();
  }
QColor QgsSimpleLineSymbolLayerV2::dxfColor( const QgsSymbolV2RenderContext& context ) const
{
  QgsExpression* strokeColorExpression = expression( "color" );
  if ( strokeColorExpression )
  {
    return ( QgsSymbolLayerV2Utils::decodeColor( strokeColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) );
  }
  return mColor;
}
Beispiel #8
0
QSizeF QgsTextDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
{
  Q_UNUSED( c );

  QVariant attrVal;
  if ( is.classificationAttributeIsExpression )
  {
    QgsExpression* expression = getExpression( is.classificationAttributeExpression, feature.fields() );
    attrVal = expression->evaluate( feature );
  }
  else
  {
    attrVal = feature.attributes()[is.classificationAttribute];
  }

  if ( !attrVal.isValid() )
  {
    return QSizeF(); //zero size if attribute is missing
  }

  double scaledValue = attrVal.toDouble();
  double scaledLowerValue = is.lowerValue;
  double scaledUpperValue = is.upperValue;
  double scaledLowerSizeWidth = is.lowerSize.width();
  double scaledLowerSizeHeight = is.lowerSize.height();
  double scaledUpperSizeWidth = is.upperSize.width();
  double scaledUpperSizeHeight = is.upperSize.height();

  // interpolate the squared value if scale by area
  if ( s.scaleByArea )
  {
    scaledValue = sqrt( scaledValue );
    scaledLowerValue = sqrt( scaledLowerValue );
    scaledUpperValue = sqrt( scaledUpperValue );
    scaledLowerSizeWidth = sqrt( scaledLowerSizeWidth );
    scaledLowerSizeHeight = sqrt( scaledLowerSizeHeight );
    scaledUpperSizeWidth = sqrt( scaledUpperSizeWidth );
    scaledUpperSizeHeight = sqrt( scaledUpperSizeHeight );
  }

  //interpolate size
  double scaledRatio = ( scaledValue - scaledLowerValue ) / ( scaledUpperValue - scaledLowerValue );

  QSizeF size = QSizeF( is.upperSize.width() * scaledRatio + is.lowerSize.width() * ( 1 - scaledRatio ),
                        is.upperSize.height() * scaledRatio + is.lowerSize.height() * ( 1 - scaledRatio ) );

  // Scale, if extension is smaller than the specified minimum
  if ( size.width() <= s.minimumSize && size.height() <= s.minimumSize )
  {
    size.scale( s.minimumSize, s.minimumSize, Qt::KeepAspectRatio );
  }

  return size;
}
double QgsSimpleLineSymbolLayerV2::dxfOffset( const QgsDxfExport& e, const QgsSymbolV2RenderContext& context ) const
{
  Q_UNUSED( e );
  double offset = mOffset;
  QgsExpression* offsetExpression = expression( "offset" );
  if ( offsetExpression )
  {
    offset = offsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }
  return offset;
}
double QgsSimpleLineSymbolLayerV2::dxfWidth( const QgsDxfExport& e, const QgsSymbolV2RenderContext& context ) const
{
  double width = mWidth;
  QgsExpression* strokeWidthExpression = expression( "width" );
  if ( strokeWidthExpression )
  {
    width = strokeWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble() * e.mapUnitScaleFactor( e.symbologyScaleDenominator(), widthUnit(), e.mapUnits() );
  }
  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale )
  {
    width = mWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit, mWidthMapUnitScale );
  }

  return width * e.mapUnitScaleFactor( e.symbologyScaleDenominator(), widthUnit(), e.mapUnits() );
}
void QgsMarkerSymbolLayerV2::markerOffset( QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY )
{
  offsetX = mOffset.x();
  offsetY = mOffset.y();

  QgsExpression* offsetExpression = expression( "offset" );
  if ( offsetExpression )
  {
    QPointF offset = QgsSymbolLayerV2Utils::decodePoint( offsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() );
    offsetX = offset.x();
    offsetY = offset.y();
  }

  offsetX *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit );
  offsetY *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit );
}
QSizeF QgsHistogramDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
{
  QSizeF size;
  if ( feature.attributes().isEmpty() )
  {
    return size; //zero size if no attributes
  }

  if ( qgsDoubleNear( is.upperValue, is.lowerValue ) )
    return size; // invalid value range => zero size

  double maxValue = 0;

  QgsExpressionContext expressionContext = c.expressionContext();
  expressionContext.setFeature( feature );
  if ( !feature.fields().isEmpty() )
    expressionContext.setFields( feature.fields() );

  Q_FOREACH ( const QString& cat, s.categoryAttributes )
  {
    QgsExpression* expression = getExpression( cat, expressionContext );
    maxValue = qMax( expression->evaluate( &expressionContext ).toDouble(), maxValue );
  }

  // Scale, if extension is smaller than the specified minimum
  if ( maxValue < s.minimumSize )
  {
    maxValue = s.minimumSize;
  }

  switch ( s.diagramOrientation )
  {
    case QgsDiagramSettings::Up:
    case QgsDiagramSettings::Down:
      mScaleFactor = (( is.upperSize.width() - is.lowerSize.height() ) / ( is.upperValue - is.lowerValue ) );
      size.scale( s.barWidth * s.categoryAttributes.size(), maxValue * mScaleFactor, Qt::IgnoreAspectRatio );
      break;

    case QgsDiagramSettings::Right:
    case QgsDiagramSettings::Left:
      mScaleFactor = (( is.upperSize.width() - is.lowerSize.width() ) / ( is.upperValue - is.lowerValue ) );
      size.scale( maxValue * mScaleFactor, s.barWidth * s.categoryAttributes.size(), Qt::IgnoreAspectRatio );
      break;
  }

  return size;
}
void QgsAttributeTypeDialog::defaultExpressionChanged()
{
  QString expression = mExpressionWidget->expression();
  if ( expression.isEmpty() )
  {
    mDefaultPreviewLabel->setText( QString() );
    return;
  }

  QgsExpressionContext context = mLayer->createExpressionContext();

  if ( !mPreviewFeature.isValid() )
  {
    // get first feature
    QgsFeatureIterator it = mLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ) );
    it.nextFeature( mPreviewFeature );
  }

  context.setFeature( mPreviewFeature );

  QgsExpression exp = QgsExpression( expression );
  exp.prepare( &context );

  if ( exp.hasParserError() )
  {
    mDefaultPreviewLabel->setText( "<i>" + exp.parserErrorString() + "</i>" );
    return;
  }

  QVariant val = exp.evaluate( &context );
  if ( exp.hasEvalError() )
  {
    mDefaultPreviewLabel->setText( "<i>" + exp.evalErrorString() + "</i>" );
    return;
  }

  QString previewText = val.toString();

  QgsEditorWidgetFactory *factory = QgsEditorWidgetRegistry::instance()->factory( editorWidgetType() );
  if ( factory )
  {
    previewText = factory->representValue( mLayer, mFieldIdx, editorWidgetConfig(), QVariant(), val );
  }

  mDefaultPreviewLabel->setText( "<i>" + previewText + "</i>" );
}
Beispiel #14
0
void QgsTextDiagram::renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, QPointF position )
{
  QPainter* p = c.painter();
  if ( !p )
  {
    return;
  }

  //convert from mm / map units to painter units
  QSizeF spu = sizePainterUnits( s.size, s, c );
  double w = spu.width();
  double h = spu.height();

  double baseX = position.x();
  double baseY = position.y() - h;

  QVector<QPointF> textPositions; //midpoints for text placement
  int nCategories = s.categoryAttributes.size();
  for ( int i = 0; i < nCategories; ++i )
  {
    if ( mOrientation == Horizontal )
    {
      textPositions.push_back( QPointF( baseX + ( w / nCategories ) * i + w / nCategories / 2.0, baseY + h / 2.0 ) );
    }
    else //vertical
    {
      textPositions.push_back( QPointF( baseX + w / 2.0, baseY + h / nCategories * i + w / nCategories / 2.0 ) );
    }
  }

  mPen.setColor( s.penColor );
  setPenWidth( mPen, s, c );
  p->setPen( mPen );
  mBrush.setColor( s.backgroundColor );
  p->setBrush( mBrush );

  //draw shapes and separator lines first
  if ( mShape == Circle )
  {
    p->drawEllipse( baseX, baseY, w, h );

    //draw separator lines
    QList<QPointF> intersect; //intersections between shape and separation lines
    QPointF center( baseX + w / 2.0, baseY + h / 2.0 );
    double r1 = w / 2.0;
    double r2 = h / 2.0;

    for ( int i = 1; i < nCategories; ++i )
    {
      if ( mOrientation == Horizontal )
      {
        lineEllipseIntersection( QPointF( baseX + w / nCategories * i, baseY ), QPointF( baseX + w / nCategories * i, baseY + h ), center, r1, r2, intersect );
      }
      else //vertical
      {
        lineEllipseIntersection( QPointF( baseX, baseY + h / nCategories * i ), QPointF( baseX + w, baseY + h / nCategories * i ), center, r1, r2, intersect );
      }
      if ( intersect.size() > 1 )
      {
        p->drawLine( intersect.at( 0 ), intersect.at( 1 ) );
      }
    }
  }
  else if ( mShape == Rectangle )
  {
    p->drawRect( QRectF( baseX, baseY, w, h ) );
    for ( int i = 1; i < nCategories; ++i )
    {
      if ( mOrientation == Horizontal )
      {
        p->drawLine( QPointF( baseX + w / nCategories * i, baseY ), QPointF( baseX + w / nCategories * i, baseY + h ) );
      }
      else
      {
        p->drawLine( QPointF( baseX, baseY + h / nCategories * i ), QPointF( baseX + w, baseY + h / nCategories * i ) );
      }
    }
  }
  else //triangle
  {
    QPolygonF triangle;
    triangle << QPointF( baseX, baseY + h ) << QPointF( baseX + w, baseY + h ) << QPointF( baseX + w / 2.0, baseY );
    p->drawPolygon( triangle );

    QLineF triangleEdgeLeft( baseX + w / 2.0, baseY, baseX, baseY + h );
    QLineF triangleEdgeRight( baseX + w, baseY + h, baseX + w / 2.0, baseY );
    QPointF intersectionPoint1, intersectionPoint2;

    for ( int i = 1; i < nCategories; ++i )
    {
      if ( mOrientation == Horizontal )
      {
        QLineF verticalLine( baseX + w / nCategories * i, baseY + h, baseX + w / nCategories * i, baseY );
        if ( baseX + w / nCategories * i < baseX + w / 2.0 )
        {
          verticalLine.intersect( triangleEdgeLeft, &intersectionPoint1 );
        }
        else
        {
          verticalLine.intersect( triangleEdgeRight, &intersectionPoint1 );
        }
        p->drawLine( QPointF( baseX + w / nCategories * i, baseY + h ), intersectionPoint1 );
      }
      else //vertical
      {
        QLineF horizontalLine( baseX, baseY + h / nCategories * i, baseX + w, baseY + h / nCategories * i );
        horizontalLine.intersect( triangleEdgeLeft, &intersectionPoint1 );
        horizontalLine.intersect( triangleEdgeRight, &intersectionPoint2 );
        p->drawLine( intersectionPoint1, intersectionPoint2 );
      }
    }
  }

  //draw text
  QFont sFont = scaledFont( s, c );
  QFontMetricsF fontMetrics( sFont );
  p->setFont( sFont );

  QgsExpressionContext expressionContext = c.expressionContext();
  expressionContext.setFeature( feature );
  if ( feature.fields() )
    expressionContext.setFields( *feature.fields() );

  for ( int i = 0; i < textPositions.size(); ++i )
  {
    QgsExpression* expression = getExpression( s.categoryAttributes.at( i ), expressionContext );
    QString val = expression->evaluate( &expressionContext ).toString();

    //find out dimesions
    double textWidth = fontMetrics.width( val );
    double textHeight = fontMetrics.height();

    mPen.setColor( s.categoryColors.at( i ) );
    p->setPen( mPen );
    QPointF position = textPositions.at( i );

    // Calculate vertical placement
    double xOffset = 0;

    switch ( s.labelPlacementMethod )
    {
      case QgsDiagramSettings::Height:
        xOffset = textHeight / 2.0;
        break;

      case QgsDiagramSettings::XHeight:
        xOffset = fontMetrics.xHeight();
        break;
    }
    p->drawText( QPointF( position.x() - textWidth / 2.0, position.y() + xOffset ), val );
  }
}
void QgsSimpleLineSymbolLayerV2::applyDataDefinedSymbology( QgsSymbolV2RenderContext& context, QPen& pen, QPen& selPen, double& offset )
{
  if ( mDataDefinedProperties.isEmpty() )
    return; // shortcut

  //data defined properties
  double scaledWidth = 0;
  QgsExpression* strokeWidthExpression = expression( "width" );
  if ( strokeWidthExpression )
  {
    scaledWidth = strokeWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble()
                  * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit, mWidthMapUnitScale );
    pen.setWidthF( scaledWidth );
    selPen.setWidthF( scaledWidth );
  }
  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale )
  {
    scaledWidth = mWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit, mWidthMapUnitScale );
    pen.setWidthF( scaledWidth );
    selPen.setWidthF( scaledWidth );
  }

  //color
  QgsExpression* strokeColorExpression = expression( "color" );
  if ( strokeColorExpression )
  {
    pen.setColor( QgsSymbolLayerV2Utils::decodeColor( strokeColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) );
  }

  //offset
  QgsExpression* lineOffsetExpression = expression( "offset" );
  if ( lineOffsetExpression )
  {
    offset = lineOffsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }

  //dash dot vector
  QgsExpression* dashPatternExpression = expression( "customdash" );
  if ( dashPatternExpression )
  {
    double scaledWidth = mWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit, mWidthMapUnitScale );
    double dashWidthDiv = mPen.widthF();

    if ( strokeWidthExpression )
    {
      dashWidthDiv = pen.widthF();
      scaledWidth = pen.widthF();
    }

    //fix dash pattern width in Qt 4.8
    QStringList versionSplit = QString( qVersion() ).split( "." );
    if ( versionSplit.size() > 1
         && versionSplit.at( 1 ).toInt() >= 8
         && ( scaledWidth * context.renderContext().rasterScaleFactor() ) < 1.0 )
    {
      dashWidthDiv = 1.0;
    }

    QVector<qreal> dashVector;
    QStringList dashList = dashPatternExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString().split( ";" );
    QStringList::const_iterator dashIt = dashList.constBegin();
    for ( ; dashIt != dashList.constEnd(); ++dashIt )
    {
      dashVector.push_back( dashIt->toDouble() * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mCustomDashPatternUnit, mCustomDashPatternMapUnitScale ) / dashWidthDiv );
    }
    pen.setDashPattern( dashVector );
  }

  //join style
  QgsExpression* joinStyleExpression = expression( "joinstyle" );
  if ( joinStyleExpression )
  {
    QString joinStyleString = joinStyleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
    pen.setJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( joinStyleString ) );
  }

  //cap style
  QgsExpression* capStyleExpression = expression( "capstyle" );
  if ( capStyleExpression )
  {
    QString capStyleString = capStyleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
    pen.setCapStyle( QgsSymbolLayerV2Utils::decodePenCapStyle( capStyleString ) );
  }
}
Beispiel #16
0
void QgsSimpleMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context )
{
  QPainter *p = context.renderContext().painter();
  if ( !p )
  {
    return;
  }

  //offset
  double offsetX = 0;
  double offsetY = 0;
  markerOffset( context, offsetX, offsetY );
  QPointF off( offsetX, offsetY );

  //angle
  double angle = mAngle;
  if ( mAngleExpression )
  {
    angle = mAngleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }
  if ( angle )
    off = _rotatedOffset( off, angle );

  //data defined shape?
  if ( mNameExpression )
  {
    QString name = mNameExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
    if ( !prepareShape( name ) ) // drawing as a polygon
    {
      preparePath( name ); // drawing as a painter path
    }
  }

  if ( mUsingCache )
  {
    // we will use cached image
    QImage &img = context.selected() ? mSelCache : mCache;
    double s = img.width() / context.renderContext().rasterScaleFactor();
    p->drawImage( QRectF( point.x() - s / 2.0 + off.x(),
                          point.y() - s / 2.0 + off.y(),
                          s, s ), img );
  }
  else
  {
    QMatrix transform;

    // move to the desired position
    transform.translate( point.x() + off.x(), point.y() + off.y() );

    QgsExpression *sizeExpression = expression( "size" );
    bool hasDataDefinedSize = context.renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression;

    // resize if necessary
    if ( hasDataDefinedSize )
    {
      double scaledSize = mSize;
      if ( sizeExpression )
      {
        scaledSize = sizeExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
      }
      scaledSize *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mSizeUnit );

      switch ( mScaleMethod )
      {
        case QgsSymbolV2::ScaleArea:
          scaledSize = sqrt( scaledSize );
          break;
        case QgsSymbolV2::ScaleDiameter:
          break;
      }

      double half = scaledSize / 2.0;
      transform.scale( half, half );
    }

    bool hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || mAngleExpression;
    if ( angle != 0 && hasDataDefinedRotation )
      transform.rotate( angle );

    QgsExpression* colorExpression = expression( "color" );
    QgsExpression* colorBorderExpression = expression( "color_border" );
    QgsExpression* outlineWidthExpression = expression( "outline_width" );
    if ( colorExpression )
    {
      mBrush.setColor( QgsSymbolLayerV2Utils::decodeColor( colorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) );
    }
    if ( colorBorderExpression )
    {
      mPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorBorderExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) );
      mSelPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorBorderExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) );
    }
    if ( outlineWidthExpression )
    {
      double outlineWidth = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
      mPen.setWidthF( outlineWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOutlineWidthUnit ) );
      mSelPen.setWidthF( outlineWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOutlineWidthUnit ) );
    }

    p->setBrush( context.selected() ? mSelBrush : mBrush );
    p->setPen( context.selected() ? mSelPen : mPen );

    if ( !mPolygon.isEmpty() )
      p->drawPolygon( transform.map( mPolygon ) );
    else
      p->drawPath( transform.map( mPath ) );
  }
}
Beispiel #17
0
bool QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const
{
  //data defined size?
  double size = mSize;

  QgsExpression *sizeExpression = expression( "size" );
  bool hasDataDefinedSize = false;
  if ( context )
  {
    hasDataDefinedSize = context->renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression;
  }

  //data defined size
  if ( hasDataDefinedSize )
  {
    if ( sizeExpression )
    {
      size = sizeExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
    }
    size *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context->renderContext(), mSizeUnit );

    switch ( mScaleMethod )
    {
      case QgsSymbolV2::ScaleArea:
        size = sqrt( size );
        break;
      case QgsSymbolV2::ScaleDiameter:
        break;
    }
  }

  if ( mSizeUnit == QgsSymbolV2::MM )
  {
    size *= mmMapUnitScaleFactor;
  }
  double halfSize = size / 2.0;

  QColor c = mPen.color();
  if ( mPen.style() == Qt::NoPen )
  {
    c = mBrush.color();
  }
  QgsExpression* colorExpression = expression( "color" );
  if ( colorExpression )
  {
    c = QgsSymbolLayerV2Utils::decodeColor( colorExpression->evaluate( *f ).toString() );
  }
  int colorIndex = QgsDxfExport::closestColorMatch( c.rgb() );

  //offset
  double offsetX = 0;
  double offsetY = 0;
  markerOffset( *context, offsetX, offsetY );
  QPointF off( offsetX, offsetY );

  //angle
  double angle = mAngle;
  QgsExpression* angleExpression = expression( "angle" );
  if ( angleExpression )
  {
    angle = angleExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
  }
  angle = -angle; //rotation in Qt is counterclockwise
  if ( angle )
    off = _rotatedOffset( off, angle );

  if ( mSizeUnit == QgsSymbolV2::MM )
  {
    off *= mmMapUnitScaleFactor;
  }

  QTransform t;
  t.translate( shift.x() + offsetX, shift.y() + offsetY );

  if ( angle != 0 )
    t.rotate( angle );

  //data defined symbol name

  if ( mName == "circle" )
  {
    e.writeGroup( 0, "CIRCLE" );
    e.writeGroup( 8, layerName );

    e.writeGroup( 62, colorIndex );
    e.writeGroup( 10, halfSize + shift.x() );
    e.writeGroup( 20, halfSize + shift.y() );
    e.writeGroup( 30, 0.0 );
    e.writeGroup( 40, halfSize );
  }
  else if ( mName == "square" || mName == "rectangle" )
  {
    QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
    QPointF pt2 = t.map( QPointF( halfSize, -halfSize ) );
    QPointF pt3 = t.map( QPointF( -halfSize, halfSize ) );
    QPointF pt4 = t.map( QPointF( halfSize, halfSize ) );
    e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) );
  }
  else if ( mName == "diamond" )
  {
    QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
    QPointF pt2 = t.map( QPointF( 0, -halfSize ) );
    QPointF pt3 = t.map( QPointF( 0, halfSize ) );
    QPointF pt4 = t.map( QPointF( halfSize, 0 ) );
    e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) );
  }
  else
  {
    return false;
  }
  return true;
}
void QgsEllipseSymbolLayerV2::preparePath( const QString& symbolName, QgsSymbolV2RenderContext& context, const QgsFeature* f )
{
  mPainterPath = QPainterPath();
  const QgsRenderContext& ct = context.renderContext();

  double width = 0;

  QgsExpression* widthExpression = expression( "width" );
  if ( widthExpression ) //1. priority: data defined setting on symbol layer level
  {
    width = widthExpression->evaluate( const_cast<QgsFeature*>( f ) ).toDouble();
  }
  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
  {
    width = mSize;
  }
  else //3. priority: global width setting
  {
    width = mSymbolWidth;
  }
  width *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( ct, mSymbolWidthUnit );

  double height = 0;
  QgsExpression* heightExpression = expression( "height" );
  if ( heightExpression ) //1. priority: data defined setting on symbol layer level
  {
    height =  heightExpression->evaluate( const_cast<QgsFeature*>( f ) ).toDouble();
  }
  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
  {
    height = mSize;
  }
  else //3. priority: global height setting
  {
    height = mSymbolHeight;
  }
  height *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( ct, mSymbolHeightUnit );

  if ( symbolName == "circle" )
  {
    mPainterPath.addEllipse( QRectF( -width / 2.0, -height / 2.0, width, height ) );
  }
  else if ( symbolName == "rectangle" )
  {
    mPainterPath.addRect( QRectF( -width / 2.0, -height / 2.0, width, height ) );
  }
  else if ( symbolName == "cross" )
  {
    mPainterPath.moveTo( 0, -height / 2.0 );
    mPainterPath.lineTo( 0, height / 2.0 );
    mPainterPath.moveTo( -width / 2.0, 0 );
    mPainterPath.lineTo( width / 2.0, 0 );
  }
  else if ( symbolName == "triangle" )
  {
    mPainterPath.moveTo( 0, -height / 2.0 );
    mPainterPath.lineTo( -width / 2.0, height / 2.0 );
    mPainterPath.lineTo( width / 2.0, height / 2.0 );
    mPainterPath.lineTo( 0, -height / 2.0 );
  }
}
void QgsEllipseSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context )
{
  QgsExpression* outlineWidthExpression = expression( "outline_width" );
  QgsExpression* fillColorExpression = expression( "fill_color" );
  QgsExpression* outlineColorExpression = expression( "outline_color" );
  QgsExpression* widthExpression = expression( "width" );
  QgsExpression* heightExpression = expression( "height" );
  QgsExpression* symbolNameExpression = expression( "symbol_name" );
  QgsExpression* rotationExpression = expression( "rotation" );

  if ( outlineWidthExpression )
  {
    double width = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
    width *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOutlineWidthUnit );
    mPen.setWidthF( width );
  }
  if ( fillColorExpression )
  {
    QString colorString = fillColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
    mBrush.setColor( QColor( colorString ) );
  }
  if ( outlineColorExpression )
  {
    QString colorString = outlineColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
    mPen.setColor( QColor( colorString ) );
  }
  if ( widthExpression || heightExpression || symbolNameExpression )
  {
    QString symbolName =  mSymbolName;
    if ( symbolNameExpression )
    {
      symbolName = symbolNameExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
    }
    preparePath( symbolName, context, context.feature() );
  }

  //offset
  double offsetX = 0;
  double offsetY = 0;
  markerOffset( context, mSymbolWidth, mSymbolHeight, mSymbolWidthUnit, mSymbolHeightUnit, offsetX, offsetY );
  QPointF off( offsetX, offsetY );

  QPainter* p = context.renderContext().painter();
  if ( !p )
  {
    return;
  }

  //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
  double rotation = 0.0;
  if ( rotationExpression )
  {
    rotation = rotationExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }
  else if ( !qgsDoubleNear( mAngle, 0.0 ) )
  {
    rotation = mAngle;
  }
  if ( rotation )
    off = _rotatedOffset( off, rotation );

  QMatrix transform;
  transform.translate( point.x() + off.x(), point.y() + off.y() );
  if ( !qgsDoubleNear( rotation, 0.0 ) )
  {
    transform.rotate( rotation );
  }

  p->setPen( mPen );
  p->setBrush( mBrush );
  p->drawPath( transform.map( mPainterPath ) );
}
void QgsAttributeTableModel::loadAttributes()
{
  if ( !layer() )
  {
    return;
  }

  bool ins = false, rm = false;

  QgsAttributeList attributes;
  const QgsFields& fields = layer()->pendingFields();
  for ( int idx = 0; idx < fields.count(); ++idx )
  {
    switch ( layer()->editType( idx ) )
    {
      case QgsVectorLayer::Hidden:
        continue;

      case QgsVectorLayer::ValueMap:
        mValueMaps.insert( idx, new QMap< QString, QVariant >( layer()->valueMap( idx ) ) );
        break;

      case QgsVectorLayer::ValueRelation:
      {
        const QgsVectorLayer::ValueRelationData &data =  layer()->valueRelation( idx );

        QgsVectorLayer *layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( data.mLayer ) );
        if ( !layer )
          continue;

        int ki = layer->fieldNameIndex( data.mKey );
        int vi = layer->fieldNameIndex( data.mValue );

        QgsExpression *e = 0;
        if ( !data.mFilterExpression.isEmpty() )
        {
          e = new QgsExpression( data.mFilterExpression );
          if ( e->hasParserError() || !e->prepare( layer->pendingFields() ) )
            continue;
        }

        if ( ki >= 0 && vi >= 0 )
        {
          QSet<int> attributes;
          attributes << ki << vi;

          QgsFeatureRequest::Flag flags = QgsFeatureRequest::NoGeometry;

          if ( e )
          {
            if ( e->needsGeometry() )
              flags = QgsFeatureRequest::NoFlags;

            foreach ( const QString &field, e->referencedColumns() )
            {
              int idx = layer->fieldNameIndex( field );
              if ( idx < 0 )
                continue;
              attributes << idx;
            }
          }

          QMap< QString, QVariant > *map = new QMap< QString, QVariant >();

          QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFlags( flags ).setSubsetOfAttributes( attributes.toList() ) );
          QgsFeature f;
          while ( fit.nextFeature( f ) )
          {
            if ( e && !e->evaluate( &f ).toBool() )
              continue;

            map->insert( f.attribute( vi ).toString(), f.attribute( ki ) );
          }

          mValueMaps.insert( idx, map );
        }
      }
      break;

      default:
        break;
    }

    attributes << idx;
  }
void QgsHistogramDiagram::renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, QPointF position )
{
  QPainter* p = c.painter();
  if ( !p )
  {
    return;
  }

  QList<double> values;
  double maxValue = 0;

  QgsExpressionContext expressionContext = c.expressionContext();
  expressionContext.setFeature( feature );
  if ( !feature.fields().isEmpty() )
    expressionContext.setFields( feature.fields() );

  Q_FOREACH ( const QString& cat, s.categoryAttributes )
  {
    QgsExpression* expression = getExpression( cat, expressionContext );
    double currentVal = expression->evaluate( &expressionContext ).toDouble();
    values.push_back( currentVal );
    maxValue = qMax( currentVal, maxValue );
  }

  double scaledMaxVal = sizePainterUnits( maxValue * mScaleFactor, s, c );

  double currentOffset = 0;
  double scaledWidth = sizePainterUnits( s.barWidth, s, c );

  double baseX = position.x();
  double baseY = position.y();

  mPen.setColor( s.penColor );
  setPenWidth( mPen, s, c );
  p->setPen( mPen );

  QList<double>::const_iterator valIt = values.constBegin();
  QList< QColor >::const_iterator colIt = s.categoryColors.constBegin();
  for ( ; valIt != values.constEnd(); ++valIt, ++colIt )
  {
    double length = sizePainterUnits( *valIt * mScaleFactor, s, c );

    mCategoryBrush.setColor( *colIt );
    p->setBrush( mCategoryBrush );

    switch ( s.diagramOrientation )
    {
      case QgsDiagramSettings::Up:
        p->drawRect( baseX + currentOffset, baseY, scaledWidth, length * -1 );
        break;

      case QgsDiagramSettings::Down:
        p->drawRect( baseX + currentOffset, baseY - scaledMaxVal, scaledWidth, length );
        break;

      case QgsDiagramSettings::Right:
        p->drawRect( baseX, baseY - currentOffset, length, scaledWidth * -1 );
        break;

      case QgsDiagramSettings::Left:
        p->drawRect( baseX + scaledMaxVal, baseY - currentOffset, 0 - length, scaledWidth * -1 );
        break;
    }

    currentOffset += scaledWidth;
  }
}
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement )
{
  if ( points.isEmpty() )
    return;

  QgsRenderContext& rc = context.renderContext();

  double origAngle = mMarker->angle();
  int i, maxCount;
  bool isRing = false;

  double offsetAlongLine = mOffsetAlongLine;
  QgsExpression* offsetAlongLineExpression = expression( "offset_along_line" );
  if ( offsetAlongLineExpression )
  {
    offsetAlongLine = offsetAlongLineExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }
  if ( offsetAlongLine != 0 )
  {
    //scale offset along line
    offsetAlongLine *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mOffsetAlongLineUnit, mOffsetAlongLineMapUnitScale );
  }

  if ( placement == FirstVertex )
  {
    i = 0;
    maxCount = 1;
  }
  else if ( placement == LastVertex )
  {
    i = points.count() - 1;
    maxCount = points.count();
  }
  else
  {
    i = 0;
    maxCount = points.count();
    if ( points.first() == points.last() )
      isRing = true;
  }

  if ( offsetAlongLine > 0 && ( placement == FirstVertex || placement == LastVertex ) )
  {
    double distance;
    distance = placement == FirstVertex ? offsetAlongLine : -offsetAlongLine;
    renderOffsetVertexAlongLine( points, i, distance, context );
    // restore original rotation
    mMarker->setAngle( origAngle );
    return;
  }

  for ( ; i < maxCount; ++i )
  {
    if ( isRing && placement == Vertex && i == points.count() - 1 )
    {
      continue; // don't draw the last marker - it has been drawn already
    }
    // rotate marker (if desired)
    if ( mRotateMarker )
    {
      double angle = markerAngle( points, isRing, i );
      mMarker->setAngle( origAngle + angle * 180 / M_PI );
    }

    mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() );
  }

  // restore original rotation
  mMarker->setAngle( origAngle );
}
Beispiel #23
0
void QgsSvgMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context )
{
  QPainter *p = context.renderContext().painter();
  if ( !p )
    return;

  double size = mSize;
  QgsExpression* sizeExpression = expression( "size" );
  bool hasDataDefinedSize = context.renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression;

  if ( sizeExpression )
  {
    size = sizeExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }
  size *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mSizeUnit );

  if ( hasDataDefinedSize )
  {
    switch ( mScaleMethod )
    {
      case QgsSymbolV2::ScaleArea:
        size = sqrt( size );
        break;
      case QgsSymbolV2::ScaleDiameter:
        break;
    }
  }

  //don't render symbols with size below one or above 10,000 pixels
  if (( int )size < 1 || 10000.0 < size )
  {
    return;
  }

  p->save();

  //offset
  double offsetX = 0;
  double offsetY = 0;
  markerOffset( context, offsetX, offsetY );
  QPointF outputOffset( offsetX, offsetY );

  double angle = mAngle;
  QgsExpression* angleExpression = expression( "angle" );
  if ( angleExpression )
  {
    angle = angleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }
  if ( angle )
    outputOffset = _rotatedOffset( outputOffset, angle );
  p->translate( point + outputOffset );

  bool rotated = !qgsDoubleNear( angle, 0 );
  bool drawOnScreen = qgsDoubleNear( context.renderContext().rasterScaleFactor(), 1.0, 0.1 );
  if ( rotated )
    p->rotate( angle );

  QString path = mPath;
  QgsExpression* nameExpression = expression( "name" );
  if ( nameExpression )
  {
    path = nameExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
  }

  double outlineWidth = mOutlineWidth;
  QgsExpression* outlineWidthExpression = expression( "outline_width" );
  if ( outlineWidthExpression )
  {
    outlineWidth = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }

  QColor fillColor = mFillColor;
  QgsExpression* fillExpression = expression( "fill" );
  if ( fillExpression )
  {
    fillColor = QgsSymbolLayerV2Utils::decodeColor( fillExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() );
  }

  QColor outlineColor = mOutlineColor;
  QgsExpression* outlineExpression = expression( "outline" );
  if ( outlineExpression )
  {
    outlineColor = QgsSymbolLayerV2Utils::decodeColor( outlineExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() );
  }


  bool fitsInCache = true;
  bool usePict = true;
  double hwRatio = 1.0;
  if ( drawOnScreen && !rotated )
  {
    usePict = false;
    const QImage& img = QgsSvgCache::instance()->svgAsImage( path, size, fillColor, outlineColor, outlineWidth,
                        context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor(), fitsInCache );
    if ( fitsInCache && img.width() > 1 )
    {
      //consider transparency
      if ( !qgsDoubleNear( context.alpha(), 1.0 ) )
      {
        QImage transparentImage = img.copy();
        QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() );
        p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage );
        hwRatio = ( double )transparentImage.height() / ( double )transparentImage.width();
      }
      else
      {
        p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
        hwRatio = ( double )img.height() / ( double )img.width();
      }
    }
  }

  if ( usePict || !fitsInCache )
  {
    p->setOpacity( context.alpha() );
    const QPicture& pct = QgsSvgCache::instance()->svgAsPicture( path, size, fillColor, outlineColor, outlineWidth,
                          context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor(), context.renderContext().forceVectorOutput() );

    if ( pct.width() > 1 )
    {
      p->drawPicture( 0, 0, pct );
      hwRatio = ( double )pct.height() / ( double )pct.width();
    }
  }

  if ( context.selected() )
  {
    QPen pen( context.renderContext().selectionColor() );
    double penWidth = QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), QgsSymbolV2::MM );
    if ( penWidth > size / 20 )
    {
      // keep the pen width from covering symbol
      penWidth = size / 20;
    }
    double penOffset = penWidth / 2;
    pen.setWidth( penWidth );
    p->setPen( pen );
    p->setBrush( Qt::NoBrush );
    double wSize = size + penOffset;
    double hSize = size * hwRatio + penOffset;
    p->drawRect( QRectF( -wSize / 2.0, -hSize / 2.0, wSize, hSize ) );
  }

  p->restore();
}
void QgsSimpleLineSymbolLayerV2::applyDataDefinedSymbology( QgsSymbolV2RenderContext& context, QPen& pen, QPen& selPen, double& offset )
{
  //data defined properties
  double scaledWidth = 0;
  QgsExpression* strokeWidthExpression = expression( "width" );
  if ( strokeWidthExpression )
  {
    scaledWidth = strokeWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble()
                  * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit );
    pen.setWidthF( scaledWidth );
    selPen.setWidthF( scaledWidth );
  }
  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale )
  {
    scaledWidth = mWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mWidthUnit );
    pen.setWidthF( scaledWidth );
    selPen.setWidthF( scaledWidth );
  }

  //color
  QgsExpression* strokeColorExpression = expression( "color" );
  if ( strokeColorExpression )
  {
    pen.setColor( QgsSymbolLayerV2Utils::decodeColor( strokeColorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) );
  }

  //offset
  offset = mOffset;
  QgsExpression* lineOffsetExpression = expression( "offset" );
  if ( lineOffsetExpression )
  {
    offset = lineOffsetExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }

  //dash dot vector
  QgsExpression* dashPatternExpression = expression( "customdash" );
  if ( dashPatternExpression )
  {
    QVector<qreal> dashVector;
    QStringList dashList = dashPatternExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString().split( ";" );
    QStringList::const_iterator dashIt = dashList.constBegin();
    for ( ; dashIt != dashList.constEnd(); ++dashIt )
    {
      dashVector.push_back( dashIt->toDouble() * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mCustomDashPatternUnit ) / mPen.widthF() );
    }
    pen.setDashPattern( dashVector );
  }

  //join style
  QgsExpression* joinStyleExpression = expression( "joinstyle" );
  if ( joinStyleExpression )
  {
    QString joinStyleString = joinStyleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
    pen.setJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( joinStyleString ) );
  }

  //cap style
  QgsExpression* capStyleExpression = expression( "capstyle" );
  if ( capStyleExpression )
  {
    QString capStyleString = capStyleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
    pen.setCapStyle( QgsSymbolLayerV2Utils::decodePenCapStyle( capStyleString ) );
  }
}
Beispiel #25
0
void QgsPieDiagram::renderDiagram( const QgsFeature& feature, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
{
  QPainter* p = c.painter();
  if ( !p )
  {
    return;
  }

  //get sum of values
  QList<double> values;
  double currentVal = 0;
  double valSum = 0;
  int valCount = 0;

  QList<QString>::const_iterator catIt = s.categoryAttributes.constBegin();
  for ( ; catIt != s.categoryAttributes.constEnd(); ++catIt )
  {
    QgsExpression* expression = getExpression( *catIt, feature.fields() );
    currentVal = expression->evaluate( feature ).toDouble();
    values.push_back( currentVal );
    valSum += currentVal;
    if ( currentVal ) valCount++;
  }

  //draw the slices
  double totalAngle = 0;
  double currentAngle;

  //convert from mm / map units to painter units
  QSizeF spu = sizePainterUnits( s.size, s, c );
  double w = spu.width();
  double h = spu.height();

  double baseX = position.x();
  double baseY = position.y() - h;

  mPen.setColor( s.penColor );
  setPenWidth( mPen, s, c );
  p->setPen( mPen );

  // there are some values > 0 available
  if ( valSum > 0 )
  {
    QList<double>::const_iterator valIt = values.constBegin();
    QList< QColor >::const_iterator colIt = s.categoryColors.constBegin();
    for ( ; valIt != values.constEnd(); ++valIt, ++colIt )
    {
      if ( *valIt )
      {
        currentAngle = *valIt / valSum * 360 * 16;
        mCategoryBrush.setColor( *colIt );
        p->setBrush( mCategoryBrush );
        // if only 1 value is > 0, draw a circle
        if ( valCount == 1 )
        {
          p->drawEllipse( baseX, baseY, w, h );
        }
        else
        {
          p->drawPie( baseX, baseY, w, h, totalAngle + s.angleOffset, currentAngle );
        }
        totalAngle += currentAngle;
      }
    }
  }
  else // valSum > 0
  {
    // draw empty circle if no values are defined at all
    mCategoryBrush.setColor( Qt::transparent );
    p->setBrush( mCategoryBrush );
    p->drawEllipse( baseX, baseY, w, h );
  }
}
bool QgsEllipseSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const
{
  //width
  double symbolWidth = mSymbolWidth;
  QgsExpression* widthExpression = expression( "width" );
  if ( widthExpression ) //1. priority: data defined setting on symbol layer level
  {
    symbolWidth = widthExpression->evaluate( const_cast<QgsFeature*>( f ) ).toDouble();
  }
  else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
  {
    symbolWidth = mSize;
  }
  if ( mSymbolWidthUnit == QgsSymbolV2::MM )
  {
    symbolWidth *= mmMapUnitScaleFactor;
  }

  //height
  double symbolHeight = mSymbolHeight;
  QgsExpression* heightExpression = expression( "height" );
  if ( heightExpression ) //1. priority: data defined setting on symbol layer level
  {
    symbolHeight =  heightExpression->evaluate( const_cast<QgsFeature*>( f ) ).toDouble();
  }
  else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
  {
    symbolHeight = mSize;
  }
  if ( mSymbolHeightUnit == QgsSymbolV2::MM )
  {
    symbolHeight *= mmMapUnitScaleFactor;
  }

  //outline width
  double outlineWidth = mOutlineWidth;
  QgsExpression* outlineWidthExpression = expression( "outline_width" );
  if ( outlineWidthExpression )
  {
    outlineWidth = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
  }
  if ( mOutlineWidthUnit == QgsSymbolV2::MM )
  {
    outlineWidth *= outlineWidth;
  }

  //color
  QColor c = mFillColor;
  QgsExpression* fillColorExpression = expression( "fill_color" );
  if ( fillColorExpression )
  {
    c = QColor( fillColorExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toString() );
  }
  int colorIndex = e.closestColorMatch( c.rgb() );

  //symbol name
  QString symbolName =  mSymbolName;
  QgsExpression* symbolNameExpression = expression( "symbol_name" );
  if ( symbolNameExpression )
  {
    QgsExpression* symbolNameExpression = expression( "symbol_name" );
    symbolName = symbolNameExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toString();
  }

  //offset
  double offsetX = 0;
  double offsetY = 0;
  markerOffset( *context, offsetX, offsetY );
  QPointF off( offsetX, offsetY );

  //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
  double rotation = 0.0;
  QgsExpression* rotationExpression = expression( "rotation" );
  if ( rotationExpression )
  {
    rotation = rotationExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
  }
  else if ( !qgsDoubleNear( mAngle, 0.0 ) )
  {
    rotation = mAngle;
  }
  rotation = -rotation; //rotation in Qt is counterclockwise
  if ( rotation )
    off = _rotatedOffset( off, rotation );

  QTransform t;
  t.translate( shift.x() + offsetX, shift.y() + offsetY );

  if ( rotation != 0 )
    t.rotate( rotation );

  double halfWidth = symbolWidth / 2.0;
  double halfHeight = symbolHeight / 2.0;

  if ( symbolName == "circle" )
  {
    //soon...
  }
  else if ( symbolName == "rectangle" )
  {
    QPointF pt1( t.map( QPointF( -halfWidth, -halfHeight ) ) );
    QPointF pt2( t.map( QPointF( halfWidth, -halfHeight ) ) );
    QPointF pt3( t.map( QPointF( -halfWidth, halfHeight ) ) );
    QPointF pt4( t.map( QPointF( halfWidth, halfHeight ) ) );
    e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) );
    return true;
  }
  else if ( symbolName == "cross" )
  {
    QgsPolyline line1( 2 );
    QPointF pt1( t.map( QPointF( -halfWidth, 0 ) ) );
    QPointF pt2( t.map( QPointF( halfWidth, 0 ) ) );
    line1[0] = QgsPoint( pt1.x(), pt1.y() );
    line1[1] = QgsPoint( pt2.x(), pt2.y() );
    e.writePolyline( line1, layerName, "CONTINUOUS", colorIndex, outlineWidth, false );
    QgsPolyline line2( 2 );
    QPointF pt3( t.map( QPointF( 0, halfHeight ) ) );
    QPointF pt4( t.map( QPointF( 0, -halfHeight ) ) );
    line2[0] = QgsPoint( pt3.x(), pt3.y() );
    line2[1] = QgsPoint( pt3.x(), pt3.y() );
    e.writePolyline( line2, layerName, "CONTINUOUS", colorIndex, outlineWidth, false );
    return true;
  }
  else if ( symbolName == "triangle" )
  {
    QPointF pt1( t.map( QPointF( -halfWidth, -halfHeight ) ) );
    QPointF pt2( t.map( QPointF( halfWidth, -halfHeight ) ) );
    QPointF pt3( t.map( QPointF( 0, halfHeight ) ) );
    QPointF pt4( t.map( QPointF( 0, halfHeight ) ) );
    e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) );
    return true;
  }

  return false; //soon...
}
void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context )
{
  if ( points.isEmpty() )
    return;

  QPointF lastPt = points[0];
  double lengthLeft = 0; // how much is left until next marker
  bool first = mOffsetAlongLine ? false : true; //only draw marker at first vertex when no offset along line is set
  double origAngle = mMarker->angle();

  QgsRenderContext& rc = context.renderContext();
  double interval = mInterval;

  QgsExpression* intervalExpression = expression( "interval" );
  if ( intervalExpression )
  {
    interval = intervalExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }
  if ( interval <= 0 )
  {
    interval = 0.1;
  }
  double offsetAlongLine = mOffsetAlongLine;
  QgsExpression* offsetAlongLineExpression = expression( "offset_along_line" );
  if ( offsetAlongLineExpression )
  {
    offsetAlongLine = offsetAlongLineExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }

  double painterUnitInterval = interval * QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mIntervalUnit, mIntervalMapUnitScale );
  lengthLeft = painterUnitInterval - offsetAlongLine * QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mIntervalUnit, mIntervalMapUnitScale );

  for ( int i = 1; i < points.count(); ++i )
  {
    const QPointF& pt = points[i];

    if ( lastPt == pt ) // must not be equal!
      continue;

    // for each line, find out dx and dy, and length
    MyLine l( lastPt, pt );
    QPointF diff = l.diffForInterval( painterUnitInterval );

    // if there's some length left from previous line
    // use only the rest for the first point in new line segment
    double c = 1 - lengthLeft / painterUnitInterval;

    lengthLeft += l.length();

    // rotate marker (if desired)
    if ( mRotateMarker )
    {
      mMarker->setAngle( origAngle + ( l.angle() * 180 / M_PI ) );
    }

    // draw first marker
    if ( first )
    {
      mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() );
      first = false;
    }

    // while we're not at the end of line segment, draw!
    while ( lengthLeft > painterUnitInterval )
    {
      // "c" is 1 for regular point or in interval (0,1] for begin of line segment
      lastPt += c * diff;
      lengthLeft -= painterUnitInterval;
      mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() );
      c = 1; // reset c (if wasn't 1 already)
    }

    lastPt = pt;
  }

  // restore original rotation
  mMarker->setAngle( origAngle );

}
bool QgsComposerAttributeTableV2::getTableContents( QgsComposerTableContents &contents )
{
  contents.clear();

  if (( mSource == QgsComposerAttributeTableV2::AtlasFeature || mSource == QgsComposerAttributeTableV2::RelationChildren )
      && !mComposition->atlasComposition().enabled() )
  {
    //source mode requires atlas, but atlas disabled
    return false;
  }

  QgsVectorLayer* layer = sourceLayer();

  if ( !layer )
  {
    //no source layer
    return false;
  }

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

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

  QgsFeatureRequest req;

  if ( mSource == QgsComposerAttributeTableV2::RelationChildren )
  {
    QgsRelation relation = QgsProject::instance()->relationManager()->relation( mRelationId );
    QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature();
    if ( atlasFeature )
    {
      req = relation.getRelatedFeaturesRequest( *atlasFeature );
    }
    else
    {
      //no atlas feature, so empty table
      return true;
    }
  }

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

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

  if ( mSource == QgsComposerAttributeTableV2::AtlasFeature
       && mComposition->atlasComposition().enabled() )
  {
    //source mode is current atlas feature
    QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature();
    if ( atlasFeature )
    {
      req.setFilterFid( atlasFeature->id() );
    }
    else
    {
      //no atlas feature, so empty table
      return true;
    }
  }

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

  while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures )
  {
    //check feature against filter
    if ( activeFilter )
    {
      QVariant result = filterExpression->evaluate( &f, layer->pendingFields() );
      // skip this feature if the filter evaluation is false
      if ( !result.toBool() )
      {
        continue;
      }
    }
    //check against atlas feature intersection
    if ( mFilterToAtlasIntersection )
    {
      if ( !f.geometry() || ! mComposition->atlasComposition().enabled() )
      {
        continue;
      }
      QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature();
      if ( !atlasFeature || !atlasFeature->geometry() ||
           !f.geometry()->intersects( atlasFeature->geometry() ) )
      {
        //feature falls outside current atlas feature
        continue;
      }
    }

    QgsComposerTableRow currentRow;

    QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin();
    for ( ; columnIt != mColumns.constEnd(); ++columnIt )
    {
      int idx = layer->fieldNameIndex(( *columnIt )->attribute() );
      if ( idx != -1 )
      {
        currentRow << f.attributes()[idx];
      }
      else
      {
        // Lets assume it's an expression
        QgsExpression* expression = new QgsExpression(( *columnIt )->attribute() );
        expression->setCurrentRowNumber( counter + 1 );
        expression->prepare( layer->pendingFields() );
        QVariant value = expression->evaluate( f ) ;
        currentRow << value;
      }
    }

    if ( !mShowUniqueRowsOnly || !contentsContainsRow( contents, currentRow ) )
    {
      contents << currentRow;
      ++counter;
    }
  }

  //sort the list, starting with the last attribute
  QgsComposerAttributeTableCompareV2 c;
  QList< QPair<int, bool> > sortColumns = sortAttributes();
  for ( int i = sortColumns.size() - 1; i >= 0; --i )
  {
    c.setSortColumn( sortColumns.at( i ).first );
    c.setAscending( sortColumns.at( i ).second );
    qStableSort( contents.begin(), contents.end(), c );
  }

  recalculateTableSize();
  return true;
}
Beispiel #29
0
QVariant QmlExpression::evaluate( const QString &expression ) const
{
  QgsExpression exp = QgsExpression( expression );
  exp.prepare( &mExpressionContext );
  return exp.evaluate( &mExpressionContext );
}
bool QgsComposerAttributeTable::getFeatureAttributes( QList<QgsAttributeMap> &attributeMaps )
{
  if ( !mVectorLayer )
  {
    return false;
  }

  QScopedPointer< QgsExpressionContext > context( createExpressionContext() );
  context->setFields( mVectorLayer->fields() );

  attributeMaps.clear();

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

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

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

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

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

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

    attributeMaps.push_back( QgsAttributeMap() );

    QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin();
    int i = 0;
    for ( ; columnIt != mColumns.constEnd(); ++columnIt )
    {
      int idx = mVectorLayer->fieldNameIndex(( *columnIt )->attribute() );
      if ( idx != -1 )
      {
        attributeMaps.last().insert( i, f.attributes().at( idx ) );
      }
      else
      {
        // Lets assume it's an expression
        QgsExpression* expression = new QgsExpression(( *columnIt )->attribute() );
        context->lastScope()->setVariable( QString( "row_number" ), counter + 1 );
        expression->prepare( context.data() );
        QVariant value = expression->evaluate( context.data() );
        attributeMaps.last().insert( i, value.toString() );
      }

      i++;
    }
    ++counter;
  }

  //sort the list, starting with the last attribute
  QgsComposerAttributeTableCompare c;
  QList< QPair<int, bool> > sortColumns = sortAttributes();
  for ( int i = sortColumns.size() - 1; i >= 0; --i )
  {
    c.setSortColumn( sortColumns.at( i ).first );
    c.setAscending( sortColumns.at( i ).second );
    qStableSort( attributeMaps.begin(), attributeMaps.end(), c );
  }

  adjustFrameToSize();
  return true;
}