QgsRasterBlock * QgsRasterNuller::block( int bandNo, QgsRectangle  const & extent, int width, int height )
{
  QgsDebugMsg( "Entered" );
  QgsRasterBlock *outputBlock = new QgsRasterBlock();
  if ( !mInput )
  {
    return outputBlock;
  }

  //void * rasterData = mInput->block( bandNo, extent, width, height );
  QgsRasterBlock *inputBlock = mInput->block( bandNo, extent, width, height );

  // Input may be without no data value
  //double noDataValue = mInput->noDataValue( bandNo );
  double noDataValue = mOutputNoData;

  for ( int i = 0; i < height; i++ )
  {
    for ( int j = 0; j < width; j++ )
    {
      //int index = i * width + j;

      //double value = readValue( rasterData, dataType, index );
      double value = inputBlock->value( i, j );

      foreach ( NoData noData, mNoData )
      {
        if (( value >= noData.min && value <= noData.max ) ||
            doubleNear( value, noData.min ) ||
            doubleNear( value, noData.max ) )
        {
          inputBlock->setValue( i, j, noDataValue );
        }
      }
    }
  }

  return inputBlock;
}
Example #2
0
void * QgsRasterNuller::readBlock( int bandNo, QgsRectangle  const & extent, int width, int height )
{
  QgsDebugMsg( "Entered" );
  if ( !mInput ) return 0;

  //QgsRasterDataProvider *provider = dynamic_cast<QgsRasterDataProvider*>( mInput->srcInput() );

  void * rasterData = mInput->block( bandNo, extent, width, height );

  QgsRasterInterface::DataType dataType =  mInput->dataType( bandNo ); 
  int pixelSize = mInput->typeSize( dataType ) / 8; 

  double noDataValue = mInput->noDataValue ( bandNo );

  for ( int i = 0; i < height; ++i )
  {
    for ( int j = 0; j < width; ++j )
    {
      int index = pixelSize * ( i * width + j );

      double value = readValue( rasterData, dataType, index );
  
      foreach ( NoData noData, mNoData )
      {
        if ( ( value >= noData.min && value <= noData.max ) ||
             doubleNear( value, noData.min ) ||
             doubleNear( value, noData.max ) )
        {
          writeValue( rasterData, dataType, index, noDataValue );
        }
      }
    }
  }

  return rasterData;
}
Example #3
0
QgsSvgCacheEntry* QgsSvgCache::cacheEntry( const QString& file, double size, const QColor& fill, const QColor& outline, double outlineWidth,
    double widthScaleFactor, double rasterScaleFactor )
{
  //search entries in mEntryLookup
  QgsSvgCacheEntry* currentEntry = 0;
  QList<QgsSvgCacheEntry*> entries = mEntryLookup.values( file );

  QList<QgsSvgCacheEntry*>::iterator entryIt = entries.begin();
  for ( ; entryIt != entries.end(); ++entryIt )
  {
    QgsSvgCacheEntry* cacheEntry = *entryIt;
    if ( cacheEntry->file == file && doubleNear( cacheEntry->size, size ) && cacheEntry->fill == fill && cacheEntry->outline == outline &&
         cacheEntry->outlineWidth == outlineWidth && cacheEntry->widthScaleFactor == widthScaleFactor && cacheEntry->rasterScaleFactor == rasterScaleFactor )
    {
      currentEntry = cacheEntry;
      break;
    }
  }

  //if not found: create new entry
  //cache and replace params in svg content
  if ( !currentEntry )
  {
    currentEntry = insertSVG( file, size, fill, outline, outlineWidth, widthScaleFactor, rasterScaleFactor );
  }
  else
  {
    takeEntryFromList( currentEntry );
    if ( !mMostRecentEntry ) //list is empty
    {
      mMostRecentEntry = currentEntry;
      mLeastRecentEntry = currentEntry;
    }
    else
    {
      mMostRecentEntry->nextEntry = currentEntry;
      currentEntry->previousEntry = mMostRecentEntry;
      currentEntry->nextEntry = 0;
      mMostRecentEntry = currentEntry;
    }
  }

  //debugging
  //printEntryList();

  return currentEntry;
}
void QgsImageFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
{
  QPainter* p = context.renderContext().painter();
  if ( !p )
  {
    return;
  }
  p->setPen( QPen( Qt::NoPen ) );
  if ( context.selected() )
  {
    QColor selColor = context.selectionColor();
    // Alister - this doesn't seem to work here
    //if ( ! selectionIsOpaque )
    //  selColor.setAlphaF( context.alpha() );
    p->setBrush( QBrush( selColor ) );
    _renderPolygon( p, points, rings );
  }

  if ( doubleNear( mAngle, 0.0 ) )
  {
    p->setBrush( mBrush );
  }
  else
  {
    QTransform t = mBrush.transform();
    t.rotate( mAngle );
    QBrush rotatedBrush = mBrush;
    rotatedBrush.setTransform( t );
    p->setBrush( rotatedBrush );
  }
  _renderPolygon( p, points, rings );
  if ( mOutline )
  {
    mOutline->renderPolyline( points, context.feature(), context.renderContext(), -1, selectFillBorder && context.selected() );
    if ( rings )
    {
      QList<QPolygonF>::const_iterator ringIt = rings->constBegin();
      for ( ; ringIt != rings->constEnd(); ++ringIt )
      {
        mOutline->renderPolyline( *ringIt, context.feature(), context.renderContext(), -1, selectFillBorder && context.selected() );
      }
    }
  }
}
Example #5
0
void QgsSvgCache::cachePicture( QgsSvgCacheEntry *entry )
{
  if ( !entry )
  {
    return;
  }

  delete entry->picture;
  entry->picture = 0;

  //correct QPictures dpi correction
  QPicture* picture = new QPicture();
  QRectF rect;
  QSvgRenderer r( entry->svgContent );
  double hwRatio = 1.0;
  if ( r.viewBoxF().width() > 0 )
  {
    hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
  }
  bool drawOnScreen = doubleNear( entry->rasterScaleFactor, 1.0, 0.1 );
  if ( drawOnScreen )
  {
    // fix to ensure rotated symbols scale with composer page (i.e. not map item) zoom
    double wSize = entry->size;
    double hSize = wSize * hwRatio;
    QSizeF s( r.viewBoxF().size() );
    s.scale( wSize, hSize, Qt::KeepAspectRatio );
    rect = QRectF( -s.width() / 2.0, -s.height() / 2.0, s.width(), s.height() );
  }
  else
  {
    // output for print or image saving @ specific dpi
    double scaledSize = entry->size / 25.4 / ( entry->rasterScaleFactor * entry->widthScaleFactor );
    double wSize = scaledSize * picture->logicalDpiX();
    double hSize = scaledSize * picture->logicalDpiY() * r.viewBoxF().height() / r.viewBoxF().width();
    rect = QRectF( QPointF( -wSize / 2.0, -hSize / 2.0 ), QSizeF( wSize, hSize ) );
  }

  QPainter p( picture );
  r.render( &p, rect );
  entry->picture = picture;
  mTotalSize += entry->picture->size();
}
Example #6
0
double QgsPoint::sqrDistToSegment( double x1, double y1, double x2, double y2, QgsPoint& minDistPoint ) const
{
  double nx, ny; //normal vector

  nx = y2 - y1;
  ny = -( x2 - x1 );

  double t;
  t = ( m_x * ny - m_y * nx - x1 * ny + y1 * nx ) / (( x2 - x1 ) * ny - ( y2 - y1 ) * nx );

  if ( t < 0.0 )
  {
    minDistPoint.setX( x1 );
    minDistPoint.setY( y1 );
  }
  else if ( t > 1.0 )
  {
    minDistPoint.setX( x2 );
    minDistPoint.setY( y2 );
  }
  else
  {
    minDistPoint.setX( x1 + t *( x2 - x1 ) );
    minDistPoint.setY( y1 + t *( y2 - y1 ) );
  }

  double dist = sqrDist( minDistPoint );
  //prevent rounding errors if the point is directly on the segment
  if ( doubleNear( dist, 0.0, 0.00000001 ) )
  {
    minDistPoint.setX( m_x );
    minDistPoint.setY( m_y );
    return 0.0;
  }
  return dist;
}
QgsRasterBlock * QgsRasterResampleFilter::block( int bandNo, QgsRectangle  const & extent, int width, int height )
{
  Q_UNUSED( bandNo );
  QgsDebugMsg( "Entered" );
  QgsRasterBlock *outputBlock = new QgsRasterBlock();
  if ( !mInput ) return outputBlock;

  double oversampling = 1.0; // approximate global oversampling factor

  if ( mZoomedInResampler || mZoomedOutResampler )
  {
    QgsRasterDataProvider *provider = dynamic_cast<QgsRasterDataProvider*>( mInput->srcInput() );
    // Do not oversample if data source does not have fixed resolution (WMS)
    if ( provider && ( provider->capabilities() & QgsRasterDataProvider::ExactResolution ) )
    {
      double xRes = extent.width() / width;
      double providerXRes = provider->extent().width() / provider->xSize();
      double pixelRatio = xRes / providerXRes;
      oversampling = ( pixelRatio > mMaxOversampling ) ? mMaxOversampling : pixelRatio;
      QgsDebugMsg( QString( "xRes = %1 providerXRes = %2 pixelRatio = %3 oversampling = %4" ).arg( xRes ).arg( providerXRes ).arg( pixelRatio ).arg( oversampling ) );
    }
  }

  //set oversampling back to 1.0 if no resampler for zoomed in / zoomed out (nearest neighbour)
  if (( oversampling < 1.0 && !mZoomedInResampler ) || ( oversampling > 1.0 && !mZoomedOutResampler ) )
  {
    oversampling = 1.0;
  }

  QgsDebugMsg( QString( "oversampling %1" ).arg( oversampling ) );

  //effective oversampling factors are different to global one because of rounding
  double oversamplingX = (( double )width * oversampling ) / width;
  double oversamplingY = (( double )height * oversampling ) / height;

  // TODO: we must also increase the extent to get correct result on borders of parts

  int resWidth = width * oversamplingX;
  int resHeight = height * oversamplingY;

  // At moment we know that we read rendered image
  int bandNumber = 1;
  //void *rasterData = mInput->block( bandNumber, extent, resWidth, resHeight );
  QgsRasterBlock *inputBlock = mInput->block( bandNumber, extent, resWidth, resHeight );
  if ( !inputBlock || inputBlock->isEmpty() )
  {
    QgsDebugMsg( "No raster data!" );
    delete inputBlock;
    return outputBlock;
  }

  if ( doubleNear( oversamplingX, 1.0 ) || doubleNear( oversamplingY, 1.0 ) )
  {
    QgsDebugMsg( "No oversampling." );
    delete outputBlock;
    return inputBlock;
  }

  if ( !outputBlock->reset( QgsRasterBlock::ARGB32_Premultiplied, width, height ) )
  {
    delete inputBlock;
    return outputBlock;
  }

  //resample image
  QImage img = inputBlock->image();

  QImage dstImg = QImage( width, height, QImage::Format_ARGB32_Premultiplied );

  if ( mZoomedInResampler && oversamplingX < 1.0 )
  {
    QgsDebugMsg( "zoomed in resampling" );
    mZoomedInResampler->resample( img, dstImg );
  }
  else if ( mZoomedOutResampler && oversamplingX > 1.0 )
  {
    QgsDebugMsg( "zoomed out resampling" );
    mZoomedOutResampler->resample( img, dstImg );
  }
  else
  {
    // Should not happen
    QgsDebugMsg( "Unexpected resampling" );
    dstImg = img.scaled( width, height );
  }

  outputBlock->setImage( &dstImg );

  delete inputBlock;
  return outputBlock; // No resampling
}
QImage* QgsPieDiagramFactory::createDiagram( int size, const QgsFeature& f, const QgsRenderContext& renderContext ) const
{
  QgsAttributeMap dataValues = f.attributeMap();
  double sizeScaleFactor = diagramSizeScaleFactor( renderContext );

  //create transparent QImage
  int imageSideLength = size * sizeScaleFactor * renderContext.rasterScaleFactor() + 2 * mMaximumPenWidth + 2 * mMaximumGap;
  QImage* diagramImage = new QImage( QSize( imageSideLength, imageSideLength ), QImage::Format_ARGB32_Premultiplied );
  diagramImage->fill( qRgba( 0, 0, 0, 0 ) ); //transparent background
  QPainter p;
  p.begin( diagramImage );
  p.setRenderHint( QPainter::Antialiasing );
  p.setPen( Qt::NoPen );

  //calculate sum of data values
  double sum = 0;
  QList<double> valueList; //cash the values to use them in drawing later

  QgsAttributeMap::const_iterator value_it;
  QList<QgsDiagramCategory>::const_iterator it = mCategories.constBegin();
  for ( ; it != mCategories.constEnd(); ++it )
  {
    value_it = dataValues.find( it->propertyIndex() );
    valueList.push_back( value_it->toDouble() );
    if ( value_it != dataValues.constEnd() )
    {
      sum += value_it->toDouble();
    }
  }

  if ( doubleNear( sum, 0.0 ) )
  {
    p.end();
    delete diagramImage;
    return 0;
  }

  //draw pies

  int totalAngle = 0;
  int currentAngle, currentGap;
  int xGapOffset = 0;
  int yGapOffset = 0;

  QList<QgsDiagramCategory>::const_iterator category_it = mCategories.constBegin();
  QList<double>::const_iterator valueList_it = valueList.constBegin();

  for ( ; category_it != mCategories.constEnd() && valueList_it != valueList.constEnd(); ++category_it, ++valueList_it )
  {
    p.setPen( category_it->pen() );
    currentAngle = ( int )(( *valueList_it ) / sum * 360 * 16 );
    p.setBrush( category_it->brush() );

    xGapOffset = 0;
    yGapOffset = 0;
    currentGap = category_it->gap();
    if ( currentGap != 0 )
    {
      //qt angles are degrees*16
      gapOffsetsForPieSlice( currentGap, totalAngle + currentAngle / 2, xGapOffset, yGapOffset );
    }

    p.drawPie( mMaximumPenWidth * renderContext.rasterScaleFactor() + mMaximumGap + xGapOffset, mMaximumPenWidth * renderContext.rasterScaleFactor() + mMaximumGap - yGapOffset, sizeScaleFactor * renderContext.rasterScaleFactor() * size, sizeScaleFactor * renderContext.rasterScaleFactor() * size, totalAngle, currentAngle );
    totalAngle += currentAngle;
  }
  p.end();

  return diagramImage;
}
Example #9
0
void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle  const & extent, int width, int height )
{
  Q_UNUSED( bandNo );
  if ( !mInput )
  {
    return 0;
  }

  //In some (common) cases, we can simplify the drawing loop considerably and save render time
  bool fastDraw = ( !usesTransparency()
                    && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
                    && mAlphaBand < 1 && !mRedContrastEnhancement && !mGreenContrastEnhancement && !mBlueContrastEnhancement
                    && !mInvertColor );

  QgsRasterInterface::DataType redType = QgsRasterInterface::UnknownDataType;

  if ( mRedBand > 0 )
  {
    redType = ( QgsRasterInterface::DataType )mInput->dataType( mRedBand );
  }
  QgsRasterInterface::DataType greenType = QgsRasterInterface::UnknownDataType;
  if ( mGreenBand > 0 )
  {
    greenType = ( QgsRasterInterface::DataType )mInput->dataType( mGreenBand );
  }
  QgsRasterInterface::DataType blueType = QgsRasterInterface::UnknownDataType;
  if ( mBlueBand > 0 )
  {
    blueType = ( QgsRasterInterface::DataType )mInput->dataType( mBlueBand );
  }
  QgsRasterInterface::DataType transparencyType = QgsRasterInterface::UnknownDataType;
  if ( mAlphaBand > 0 )
  {
    transparencyType = ( QgsRasterInterface::DataType )mInput->dataType( mAlphaBand );
  }

  QSet<int> bands;
  if ( mRedBand > 0 )
  {
    bands << mRedBand;
  }
  if ( mGreenBand > 0 )
  {
    bands << mGreenBand;
  }
  if ( mBlueBand > 0 )
  {
    bands << mBlueBand;
  }
  if ( bands.size() < 1 )
  {
    return 0; //no need to draw anything if no band is set
  }

  if ( mAlphaBand > 0 )
  {
    bands << mAlphaBand;
  }

  QMap<int, void*> bandData;
  void* defaultPointer = 0;
  QSet<int>::const_iterator bandIt = bands.constBegin();
  for ( ; bandIt != bands.constEnd(); ++bandIt )
  {
    bandData.insert( *bandIt, defaultPointer );
  }

  void* redData = 0;
  void* greenData = 0;
  void* blueData = 0;
  void* alphaData = 0;

  bandIt = bands.constBegin();
  for ( ; bandIt != bands.constEnd(); ++bandIt )
  {
    bandData[*bandIt] =  mInput->block( *bandIt, extent, width, height );
    if ( !bandData[*bandIt] )
    {
      // We should free the alloced mem from block().
      QgsDebugMsg( "No input band" );
      bandIt--;
      for ( ; bandIt != bands.constBegin(); bandIt-- )
      {
        VSIFree( bandData[*bandIt] );
      }
      return 0;
    }
  }

  if ( mRedBand > 0 )
  {
    redData = bandData[mRedBand];
  }
  if ( mGreenBand > 0 )
  {
    greenData = bandData[mGreenBand];
  }
  if ( mBlueBand > 0 )
  {
    blueData = bandData[mBlueBand];
  }
  if ( mAlphaBand > 0 )
  {
    alphaData = bandData[mAlphaBand];
  }

  QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
  if ( img.isNull() )
  {
    QgsDebugMsg( "Could not create QImage" );
    bandIt = bands.constBegin();
    for ( ; bandIt != bands.constEnd(); ++bandIt )
    {
      VSIFree( bandData[*bandIt] );
    }
    return 0;
  }

  QRgb* imageScanLine = 0;
  int currentRasterPos = 0;
  int redVal = 0;
  int greenVal = 0;
  int blueVal = 0;
  QRgb defaultColor = qRgba( 255, 255, 255, 0 );
  double currentOpacity = mOpacity; //opacity (between 0 and 1)

  for ( int i = 0; i < height; ++i )
  {
    imageScanLine = ( QRgb* )( img.scanLine( i ) );
    for ( int j = 0; j < width; ++j )
    {
      if ( fastDraw ) //fast rendering if no transparency, stretching, color inversion, etc.
      {
        redVal = readValue( redData, redType, currentRasterPos );
        greenVal = readValue( greenData, greenType, currentRasterPos );
        blueVal = readValue( blueData, blueType, currentRasterPos );
        if ( mInput->isNoDataValue( mRedBand, redVal ) ||
             mInput->isNoDataValue( mGreenBand, greenVal ) ||
             mInput->isNoDataValue( mBlueBand, blueVal ) )
        {
          imageScanLine[j] = defaultColor;
        }
        else
        {
          imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
        }

        ++currentRasterPos;
        continue;
      }

      bool isNoData = false;
      if ( mRedBand > 0 )
      {
        redVal = readValue( redData, redType, currentRasterPos );
        if ( mInput->isNoDataValue( mRedBand, redVal ) ) isNoData = true;
      }
      if ( mGreenBand > 0 )
      {
        greenVal = readValue( greenData, greenType, currentRasterPos );
        if ( mInput->isNoDataValue( mGreenBand, greenVal ) ) isNoData = true;
      }
      if ( mBlueBand > 0 )
      {
        blueVal = readValue( blueData, blueType, currentRasterPos );
        if ( mInput->isNoDataValue( mBlueBand, blueVal ) ) isNoData = true;
      }
      if ( isNoData )
      {
        imageScanLine[j] = defaultColor;
        ++currentRasterPos;
        continue;
      }

      //apply default color if red, green or blue not in displayable range
      if (( mRedContrastEnhancement && !mRedContrastEnhancement->isValueInDisplayableRange( redVal ) )
          || ( mGreenContrastEnhancement && !mGreenContrastEnhancement->isValueInDisplayableRange( redVal ) )
          || ( mBlueContrastEnhancement && !mBlueContrastEnhancement->isValueInDisplayableRange( redVal ) ) )
      {
        imageScanLine[j] = defaultColor;
        ++currentRasterPos;
        continue;
      }

      //stretch color values
      if ( mRedContrastEnhancement )
      {
        redVal = mRedContrastEnhancement->enhanceContrast( redVal );
      }
      if ( mGreenContrastEnhancement )
      {
        greenVal = mGreenContrastEnhancement->enhanceContrast( greenVal );
      }
      if ( mBlueContrastEnhancement )
      {
        blueVal = mBlueContrastEnhancement->enhanceContrast( blueVal );
      }

      if ( mInvertColor )
      {
        redVal = 255 - redVal;
        greenVal = 255 - greenVal;
        blueVal = 255 - blueVal;
      }

      //opacity
      currentOpacity = mOpacity;
      if ( mRasterTransparency )
      {
        currentOpacity = mRasterTransparency->alphaValue( redVal, greenVal, blueVal, mOpacity * 255 ) / 255.0;
      }
      if ( mAlphaBand > 0 )
      {
        currentOpacity *= ( readValue( alphaData, transparencyType, currentRasterPos ) / 255.0 );
      }

      if ( doubleNear( currentOpacity, 1.0 ) )
      {
        imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
      }
      else
      {
        imageScanLine[j] = qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 );
      }

      ++currentRasterPos;
    }
  }

  bandIt = bands.constBegin();
  for ( ; bandIt != bands.constEnd(); ++bandIt )
  {
    VSIFree( bandData[*bandIt] );
  }

  void * data = VSIMalloc( img.byteCount() );
  if ( ! data )
  {
    QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
    return 0;
  }
  return memcpy( data, img.bits(), img.byteCount() );
}
void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
{
  double outlinePixelWidth = context.outputPixelSize( mLineWidth );
  double outputPixelDist = context.outputPixelSize( mDistance );
  double outputPixelOffset = context.outputPixelSize( mOffset );

  //create image
  int height, width;
  if ( doubleNear( mLineAngle, 0 ) || doubleNear( mLineAngle, 360 ) || doubleNear( mLineAngle, 90 ) || doubleNear( mLineAngle, 180 ) || doubleNear( mLineAngle, 270 ) )
  {
    height = outputPixelDist;
    width = height; //width can be set to arbitrary value
  }
  else
  {
    height = qAbs( outputPixelDist / cos( mLineAngle * M_PI / 180 ) ); //keep perpendicular distance between lines constant
    width = qAbs( height / tan( mLineAngle * M_PI / 180 ) );
  }

  //depending on the angle, we might need to render into a larger image and use a subset of it
  int dx = 0;
  int dy = 0;

  QImage patternImage( width, height, QImage::Format_ARGB32 );
  patternImage.fill( 0 );
  QPainter p( &patternImage );

  p.setRenderHint( QPainter::Antialiasing, true );
  QPen pen( mColor );
  pen.setWidthF( outlinePixelWidth );
  pen.setCapStyle( Qt::FlatCap );
  p.setPen( pen );

  QPoint p1, p2, p3, p4, p5, p6;
  if ( doubleNear( mLineAngle, 0.0 ) || doubleNear( mLineAngle, 360.0 ) || doubleNear( mLineAngle, 180.0 ) )
  {
    p1 = QPoint( 0, height );
    p2 = QPoint( width, height );
    p3 = QPoint( 0, 0 );
    p4 = QPoint( width, 0 );
    p5 = QPoint( 0, 2 * height );
    p6 = QPoint( width, 2 * height );
  }
  else if ( doubleNear( mLineAngle, 90.0 ) || doubleNear( mLineAngle, 270.0 ) )
  {
    p1 = QPoint( 0, height );
    p2 = QPoint( 0, 0 );
    p3 = QPoint( width, height );
    p4 = QPoint( width, 0 );
    p5 = QPoint( -width, height );
    p6 = QPoint( -width, 0 );
  }
  else if (( mLineAngle > 0 && mLineAngle < 90 ) || ( mLineAngle > 180 && mLineAngle < 270 ) )
  {
    dx = outputPixelDist * cos(( 90 - mLineAngle ) * M_PI / 180.0 );
    dy = outputPixelDist * sin(( 90 - mLineAngle ) * M_PI / 180.0 );
    p1 = QPoint( 0, height );
    p2 = QPoint( width, 0 );
    p3 = QPoint( -dx, height - dy );
    p4 = QPoint( width - dx, -dy ); //p4 = QPoint( p3.x() + width, p3.y() - height );
    p5 = QPoint( dx, height + dy );
    p6 = QPoint( width + dx, dy ); //p6 = QPoint( p5.x() + width, p5.y() - height );
  }
  else if (( mLineAngle < 180 ) || ( mLineAngle > 270 && mLineAngle < 360 ) )
  {
    dy = outputPixelDist * cos(( 180 - mLineAngle ) * M_PI / 180 );
    dx = outputPixelDist * sin(( 180 - mLineAngle ) * M_PI / 180 );
    p1 = QPoint( width, height );
    p2 = QPoint( 0, 0 );
    p5 = QPoint( width + dx, height - dy );
    p6 = QPoint( p5.x() - width, p5.y() - height ); //p6 = QPoint( dx, -dy );
    p3 = QPoint( width - dx, height + dy );
    p4 = QPoint( p3.x() - width, p3.y() - height ); //p4 = QPoint( -dx, dy );
  }

  if ( !doubleNear( mOffset, 0.0 ) ) //shift everything
  {
    QPointF tempPt;
    tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p1, p3, outputPixelDist + outputPixelOffset );
    p3 = QPoint( tempPt.x(), tempPt.y() );
    tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p2, p4, outputPixelDist + outputPixelOffset );
    p4 = QPoint( tempPt.x(), tempPt.y() );
    tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p1, p5, outputPixelDist - outputPixelOffset );
    p5 = QPoint( tempPt.x(), tempPt.y() );
    tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p2, p6, outputPixelDist - outputPixelOffset );
    p6 = QPoint( tempPt.x(), tempPt.y() );

    //update p1, p2 last
    tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p1, p3, outputPixelOffset ).toPoint();
    p1 = QPoint( tempPt.x(), tempPt.y() );
    tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p2, p4, outputPixelOffset ).toPoint();
    p2 = QPoint( tempPt.x(), tempPt.y() );;
  }

  p.drawLine( p1, p2 );
  p.drawLine( p3, p4 );
  p.drawLine( p5, p6 );
  p.end();

  //set image to mBrush
  if ( !doubleNear( context.alpha(), 1.0 ) )
  {
    QImage transparentImage = patternImage.copy();
    QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() );
    mBrush.setTextureImage( transparentImage );
  }
  else
  {
    mBrush.setTextureImage( patternImage );
  }

  QTransform brushTransform;
  brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() );
  mBrush.setTransform( brushTransform );

  if ( mOutline )
  {
    mOutline->startRender( context.renderContext() );
  }
}
void QgsPointPatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
{
  //render 3 rows and columns in one go to easily incorporate displacement
  double width = context.outputPixelSize( mDistanceX ) * 2.0;
  double height = context.outputPixelSize( mDistanceY ) * 2.0;

  QImage patternImage( width, height, QImage::Format_ARGB32 );
  patternImage.fill( 0 );

  if ( mMarkerSymbol )
  {
    QPainter p( &patternImage );

    //marker rendering needs context for drawing on patternImage
    QgsRenderContext pointRenderContext;
    pointRenderContext.setPainter( &p );
    pointRenderContext.setRasterScaleFactor( 1.0 );
    pointRenderContext.setScaleFactor( context.renderContext().scaleFactor() * context.renderContext().rasterScaleFactor() );
    QgsMapToPixel mtp( context.renderContext().mapToPixel().mapUnitsPerPixel() / context.renderContext().rasterScaleFactor() );
    pointRenderContext.setMapToPixel( mtp );
    pointRenderContext.setForceVectorOutput( false );

    mMarkerSymbol->setOutputUnit( context.outputUnit() );
    mMarkerSymbol->startRender( pointRenderContext );

    //render corner points
    mMarkerSymbol->renderPoint( QPointF( 0, 0 ), context.feature(), pointRenderContext );
    mMarkerSymbol->renderPoint( QPointF( width, 0 ), context.feature(), pointRenderContext );
    mMarkerSymbol->renderPoint( QPointF( 0, height ), context.feature(), pointRenderContext );
    mMarkerSymbol->renderPoint( QPointF( width, height ), context.feature(), pointRenderContext );

    //render displaced points
    double displacementPixelX = context.outputPixelSize( mDisplacementX );
    double displacementPixelY = context.outputPixelSize( mDisplacementY );
    mMarkerSymbol->renderPoint( QPointF( width / 2.0, -displacementPixelY ), context.feature(), pointRenderContext );
    mMarkerSymbol->renderPoint( QPointF( displacementPixelX, height / 2.0 ), context.feature(), pointRenderContext );
    mMarkerSymbol->renderPoint( QPointF( width / 2.0 + displacementPixelX, height / 2.0 - displacementPixelY ), context.feature(), pointRenderContext );
    mMarkerSymbol->renderPoint( QPointF( width + displacementPixelX, height / 2.0 ), context.feature(), pointRenderContext );
    mMarkerSymbol->renderPoint( QPointF( width / 2.0, height - displacementPixelY ), context.feature(), pointRenderContext );

    mMarkerSymbol->stopRender( pointRenderContext );
  }

  if ( !doubleNear( context.alpha(), 1.0 ) )
  {
    QImage transparentImage = patternImage.copy();
    QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() );
    mBrush.setTextureImage( transparentImage );
  }
  else
  {
    mBrush.setTextureImage( patternImage );
  }
  QTransform brushTransform;
  brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() );
  mBrush.setTransform( brushTransform );

  if ( mOutline )
  {
    mOutline->startRender( context.renderContext() );
  }
}
Example #12
0
bool QgsMapToolSimplify::calculateSliderBoudaries()
{
  double minTolerance = -1, maxTolerance = -1;

  double tol = 0.000001;
  bool found = false;
  bool isLine = mSelectedFeature.geometry()->type() == QGis::Line;
  QVector<QgsPoint> pts = getPointList( mSelectedFeature );
  int size = pts.size();
  if ( size == 0 || ( isLine && size <= 2 ) || ( !isLine && size <= 4 ) )
  {
    return false;
  }

  // calculate minimum tolerance where no vertex is excluded
  bool maximized = false;
  int count = 0;
  while ( !found )
  {
    count++;
    if ( count == 30 && !maximized )
    { //special case when tolerance is too low to be correct so it's near 0
      // else in some special cases this algorithm would create infinite loop
      found = true;
      minTolerance = 0;
    }

    if ( QgsSimplifyFeature::simplifyPoints( pts, tol ).size() < size )
    { //some vertexes were already excluded
      if ( maximized ) //if we were already in second direction end
      {
        found = true;
        minTolerance = tol / 2;
      }
      else //only lowering tolerance till it's low enough to have all vertexes
      {
        tol = tol / 2;
      }
    }
    else
    { // simplified feature has all vertexes therefore no need we need higher tolerance also ending flag set
      // when some tolerance will exclude some of vertexes
      maximized = true;
      tol = tol * 2;
    }
  }
  found = false;
  int requiredCnt = ( isLine ? 2 : 4 ); //4 for polygon is correct because first and last points are the same
  bool bottomFound = false;
  double highTol = DBL_MAX, lowTol = DBL_MIN;// two boundaries to be used when no directly correct solution is found
  // calculate minimum tolerance where minimum (requiredCnt) of vertexes are left in geometry
  while ( !found )
  {

    int foundVertexes = QgsSimplifyFeature::simplifyPoints( pts, tol ).size();
    if ( foundVertexes < requiredCnt + 1 )
    { //required or lower number of verticies found
      if ( foundVertexes == requiredCnt )
      {
        found = true;
        maxTolerance = tol;
      }
      else
      { //solving problem that polygon would have less than minimum alowed vertexes
        bottomFound = true;
        highTol = tol;
        tol = ( highTol + lowTol ) / 2;
        if ( doubleNear( highTol, lowTol ) )
        { //solving problem that two points are in same distance from  line, so they will be both excluded at same time
          //so some time more than required count of vertices can stay
          found = true;
          maxTolerance = lowTol;
        }
      }
    }
    else
    {
      if ( bottomFound )
      {
        lowTol = tol;
        tol = ( highTol + lowTol ) / 2;
        if ( doubleNear( highTol, lowTol ) )
        { //solving problem that two points are in same distance from  line, so they will be both excluded at same time
          //so some time more than required count of vertices can stay
          found = true;
          maxTolerance = lowTol;
        }
      }
      else
      { //still too much verticies left so we need to increase tolerance
        lowTol = tol;
        tol = tol * 2;
      }
    }
  }
  toleranceDivider = calculateDivider( minTolerance, maxTolerance );
  // set min and max
  mSimplifyDialog->setRange( int( minTolerance * toleranceDivider ),
                             int( maxTolerance * toleranceDivider ) );
  return true;
}
bool QgsRasterRenderer::usesTransparency( ) const
{
  if ( !mInput )
  {
    return true;
  }
  // TODO: nodata per band
  return ( mAlphaBand > 0 || ( mRasterTransparency && !mRasterTransparency->isEmpty( mInput->noDataValue( 1 ) ) ) || !doubleNear( mOpacity, 1.0 ) );
}
Example #14
0
void QgsGeometryAnalyzer::locateAlongSegment( double x1, double y1, double m1, double x2, double y2, double m2, double measure, bool& pt1Ok, QgsPoint& pt1, bool& pt2Ok, QgsPoint& pt2 )
{
  bool reversed = false;
  pt1Ok = false;
  pt2Ok = false;
  double tolerance = 0.000001; //work with a small tolerance to catch e.g. locations at endpoints

  if ( m1 > m2 )
  {
    double tmp = m1;
    m1 = m2;
    m2 = tmp;
    reversed = true;
  }

  //segment does not match
  if (( m1 - measure ) > tolerance || ( measure - m2 ) > tolerance )
  {
    pt1Ok = false;
    pt2Ok = false;
    return;
  }

  //match with vertex1
  if ( doubleNear( m1, measure, tolerance ) )
  {
    if ( reversed )
    {
      pt2Ok = true;
      pt2.setX( x2 ); pt2.setY( y2 );
    }
    else
    {
      pt1Ok = true;
      pt1.setX( x1 ); pt1.setY( y1 );
    }
  }

  //match with vertex2
  if ( doubleNear( m2, measure, tolerance ) )
  {
    if ( reversed )
    {
      pt1Ok = true;
      pt1.setX( x1 ); pt1.setY( y1 );
    }
    else
    {
      pt2Ok = true;
      pt2.setX( x2 ); pt2.setY( y2 );
    }
  }


  if ( pt1Ok || pt2Ok )
  {
    return;
  }

  //match between the vertices
  if ( doubleNear( m1, m2 ) )
  {
    pt1.setX( x1 );
    pt1.setY( y1 );
    pt1Ok = true;
    return;
  }
  double dist = ( measure - m1 ) / ( m2 - m1 );
  if ( reversed )
  {
    dist = 1 - dist;
  }

  pt1.setX( x1 + dist * ( x2 - x1 ) );
  pt1.setY( y1 + dist * ( y2 - y1 ) );
  pt1Ok = true;
}
Example #15
0
void * QgsSingleBandGrayRenderer::readBlock( int bandNo, QgsRectangle  const & extent, int width, int height )
{
  Q_UNUSED( bandNo );
  if ( !mInput )
  {
    return 0;
  }

  QgsRasterInterface::DataType rasterType = ( QgsRasterInterface::DataType )mInput->dataType( mGrayBand );
  QgsRasterInterface::DataType alphaType = QgsRasterInterface::UnknownDataType;
  if ( mAlphaBand > 0 )
  {
    alphaType = ( QgsRasterInterface::DataType )mInput->dataType( mAlphaBand );
  }

  void* rasterData = mInput->block( mGrayBand, extent, width, height );
  if ( !rasterData ) return 0;

  void* alphaData = 0;
  double currentAlpha = mOpacity;
  int grayVal;
  QRgb myDefaultColor = qRgba( 0, 0, 0, 0 );

  if ( mAlphaBand > 0 && mGrayBand != mAlphaBand )
  {
    alphaData = mInput->block( mAlphaBand, extent, width, height );
    if ( !alphaData )
    {
      free( rasterData );
      return 0;
    }
  }
  else if ( mAlphaBand > 0 )
  {
    alphaData = rasterData;
  }

  QImage *img = createImage( width, height, QImage::Format_ARGB32_Premultiplied );
  QRgb* imageScanLine = 0;
  int currentRasterPos = 0;

  for ( int i = 0; i < height; ++i )
  {
    imageScanLine = ( QRgb* )( img->scanLine( i ) );
    for ( int j = 0; j < width; ++j )
    {
      grayVal = readValue( rasterData, rasterType, currentRasterPos );

      //alpha
      currentAlpha = mOpacity;
      if ( mRasterTransparency )
      {
        currentAlpha = mRasterTransparency->alphaValue( grayVal, mOpacity * 255 ) / 255.0;
      }
      if ( mAlphaBand > 0 )
      {
        currentAlpha *= ( readValue( alphaData, alphaType, currentRasterPos ) / 255.0 );
      }

      if ( mContrastEnhancement )
      {
        if ( !mContrastEnhancement->isValueInDisplayableRange( grayVal ) )
        {
          imageScanLine[ j ] = myDefaultColor;
          ++currentRasterPos;
          continue;
        }
        grayVal = mContrastEnhancement->enhanceContrast( grayVal );
      }

      if ( mInvertColor )
      {
        grayVal = 255 - grayVal;
      }

      if ( doubleNear( currentAlpha, 1.0 ) )
      {
        imageScanLine[j] = qRgba( grayVal, grayVal, grayVal, 255 );
      }
      else
      {
        imageScanLine[j] = qRgba( currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * 255 );
      }
      ++currentRasterPos;
    }
  }

  free( rasterData );
  if ( mAlphaBand > 0 && mGrayBand != mAlphaBand )
  {
    free( alphaData );
  }

  void * data = ( void * )img->bits();
  delete img;
  return data; // OK, the image was created with extraneous data
}
void QgsMultiBandColorRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel )
{
  if ( !p || !mProvider || !viewPort || !theQgsMapToPixel )
  {
    return;
  }

  //In some (common) cases, we can simplify the drawing loop considerably and save render time
  bool fastDraw = (
                    !usesTransparency( viewPort->mSrcCRS, viewPort->mDestCRS )
                    && mRedBand > 0 && mGreenBand > 0 && mBlueBand > 0
                    && mAlphaBand < 1 && !mRedContrastEnhancement && !mGreenContrastEnhancement && !mBlueContrastEnhancement
                    && !mInvertColor );

  QgsRasterDataProvider::DataType redType = QgsRasterDataProvider::UnknownDataType;
  if ( mRedBand > 0 )
  {
    redType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mRedBand );
  }
  QgsRasterDataProvider::DataType greenType = QgsRasterDataProvider::UnknownDataType;
  if ( mGreenBand > 0 )
  {
    greenType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mGreenBand );
  }
  QgsRasterDataProvider::DataType blueType = QgsRasterDataProvider::UnknownDataType;
  if ( mBlueBand > 0 )
  {
    blueType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mBlueBand );
  }
  QgsRasterDataProvider::DataType transparencyType = QgsRasterDataProvider::UnknownDataType;
  if ( mAlphaBand > 0 )
  {
    transparencyType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mAlphaBand );
  }

  double oversamplingX = 1.0, oversamplingY = 1.0;
  QSet<int> bands;
  if ( mRedBand > 0 )
  {
    bands << mRedBand;
  }
  if ( mGreenBand > 0 )
  {
    bands << mGreenBand;
  }
  if ( mBlueBand > 0 )
  {
    bands << mBlueBand;
  }
  if ( bands.size() < 1 )
  {
    return; //no need to draw anything if no band is set
  }

  if ( mAlphaBand > 0 )
  {
    bands << mAlphaBand;
  }

  QMap<int, void*> bandData;
  void* defaultPointer = 0;
  QSet<int>::const_iterator bandIt = bands.constBegin();
  for ( ; bandIt != bands.constEnd(); ++bandIt )
  {
    bandData.insert( *bandIt, defaultPointer );
    startRasterRead( *bandIt, viewPort, theQgsMapToPixel, oversamplingX, oversamplingY );
  }

  void* redData = 0;
  void* greenData = 0;
  void* blueData = 0;
  void* alphaData = 0;
  //number of cols/rows in output pixels
  int nCols = 0;
  int nRows = 0;
  //number of raster cols/rows with oversampling
  int nRasterCols = 0;
  int nRasterRows = 0;
  //shift to top left point for the raster part
  int topLeftCol = 0;
  int topLeftRow = 0;

  bool readSuccess = true;
  while ( true )
  {
    QSet<int>::const_iterator bandIt = bands.constBegin();
    for ( ; bandIt != bands.constEnd(); ++bandIt )
    {
      readSuccess = readSuccess && readNextRasterPart( *bandIt, oversamplingX, oversamplingY, viewPort, nCols, nRows,
                    nRasterCols, nRasterRows, &bandData[*bandIt], topLeftCol, topLeftRow );
    }

    if ( !readSuccess )
    {
      break;
    }

    if ( mRedBand > 0 )
    {
      redData = bandData[mRedBand];
    }
    if ( mGreenBand > 0 )
    {
      greenData = bandData[mGreenBand];
    }
    if ( mBlueBand > 0 )
    {
      blueData = bandData[mBlueBand];
    }
    if ( mAlphaBand > 0 )
    {
      alphaData = bandData[mAlphaBand];
    }

    QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied );
    QRgb* imageScanLine = 0;
    int currentRasterPos = 0;
    int redVal = 0;
    int greenVal = 0;
    int blueVal = 0;
    int redDataVal = 0;
    int greenDataVal = 0;
    int blueDataVal = 0;
    QRgb defaultColor = qRgba( 255, 255, 255, 0 );
    double currentOpacity = mOpacity; //opacity (between 0 and 1)

    for ( int i = 0; i < nRasterRows; ++i )
    {
      imageScanLine = ( QRgb* )( img.scanLine( i ) );
      for ( int j = 0; j < nRasterCols; ++j )
      {

        if ( fastDraw ) //fast rendering if no transparency, stretching, color inversion, etc.
        {
          redVal = readValue( redData, redType, currentRasterPos );
          greenVal = readValue( greenData, greenType, currentRasterPos );
          blueVal = readValue( blueData, blueType, currentRasterPos );
          imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
          ++currentRasterPos;
          continue;
        }

        if ( mRedBand > 0 )
        {
          redVal = readValue( redData, redType, currentRasterPos );
          redDataVal = redVal;
        }
        if ( mGreenBand > 0 )
        {
          greenVal = readValue( greenData, greenType, currentRasterPos );
          greenDataVal = greenVal;
        }
        if ( mBlueBand > 0 )
        {
          blueVal = readValue( blueData, blueType, currentRasterPos );
          blueDataVal = blueVal;
        }

        //apply default color if red, green or blue not in displayable range
        if (( mRedContrastEnhancement && !mRedContrastEnhancement->isValueInDisplayableRange( redVal ) )
            || ( mGreenContrastEnhancement && !mGreenContrastEnhancement->isValueInDisplayableRange( redVal ) )
            || ( mBlueContrastEnhancement && !mBlueContrastEnhancement->isValueInDisplayableRange( redVal ) ) )
        {
          imageScanLine[j] = defaultColor;
          ++currentRasterPos;
          continue;
        }

        //stretch color values
        if ( mRedContrastEnhancement )
        {
          redVal = mRedContrastEnhancement->enhanceContrast( redVal );
        }
        if ( mGreenContrastEnhancement )
        {
          greenVal = mGreenContrastEnhancement->enhanceContrast( greenVal );
        }
        if ( mBlueContrastEnhancement )
        {
          blueVal = mBlueContrastEnhancement->enhanceContrast( blueVal );
        }

        if ( mInvertColor )
        {
          redVal = 255 - redVal;
          greenVal = 255 - greenVal;
          blueVal = 255 - blueVal;
        }

        //opacity
        currentOpacity = mOpacity;
        if ( mRasterTransparency )
        {
          currentOpacity = mRasterTransparency->alphaValue( redDataVal, greenDataVal, blueDataVal, mOpacity * 255 ) / 255.0;
        }
        if ( mAlphaBand > 0 )
        {
          currentOpacity *= ( readValue( alphaData, transparencyType, currentRasterPos ) / 255.0 );
        }

        if ( doubleNear( currentOpacity, 1.0 ) )
        {
          imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
        }
        else
        {
          imageScanLine[j] = qRgba( currentOpacity * redVal, currentOpacity * greenVal, currentOpacity * blueVal, currentOpacity * 255 );
        }
        ++currentRasterPos;
      }
    }

    drawImage( p, viewPort, img, topLeftCol, topLeftRow, nCols, nRows, oversamplingX, oversamplingY );
  }

  bandIt = bands.constBegin();
  for ( ; bandIt != bands.constEnd(); ++bandIt )
  {
    stopRasterRead( *bandIt );
  }
}
void QgsMarkerLineSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
{
  for ( int i = 0; i < mMarker->symbolLayerCount(); i++ )
  {
    QDomElement symbolizerElem = doc.createElement( "se:LineSymbolizer" );
    if ( !props.value( "uom", "" ).isEmpty() )
      symbolizerElem.setAttribute( "uom", props.value( "uom", "" ) );
    element.appendChild( symbolizerElem );

    // <Geometry>
    QgsSymbolLayerV2Utils::createGeometryElement( doc, symbolizerElem, props.value( "geom", "" ) );

    QString gap;
    switch ( mPlacement )
    {
      case FirstVertex:
        symbolizerElem.appendChild( QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "placement", "firstPoint" ) );
        break;
      case LastVertex:
        symbolizerElem.appendChild( QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "placement", "lastPoint" ) );
        break;
      case CentralPoint:
        symbolizerElem.appendChild( QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "placement", "centralPoint" ) );
        break;
      case Vertex:
        // no way to get line/polygon's vertices, use a VendorOption
        symbolizerElem.appendChild( QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "placement", "points" ) );
        break;
      default:
        gap = QString::number( mInterval );
        break;
    }

    if ( !mRotateMarker )
    {
      // markers in LineSymbolizer must be drawn following the line orientation,
      // use a VendorOption when no marker rotation
      symbolizerElem.appendChild( QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "rotateMarker", "0" ) );
    }

    // <Stroke>
    QDomElement strokeElem = doc.createElement( "se:Stroke" );
    symbolizerElem.appendChild( strokeElem );

    // <GraphicStroke>
    QDomElement graphicStrokeElem = doc.createElement( "se:GraphicStroke" );
    strokeElem.appendChild( graphicStrokeElem );

    QgsSymbolLayerV2 *layer = mMarker->symbolLayer( i );
    QgsMarkerSymbolLayerV2 *markerLayer = static_cast<QgsMarkerSymbolLayerV2 *>( layer );
    if ( !markerLayer )
    {
      graphicStrokeElem.appendChild( doc.createComment( QString( "MarkerSymbolLayerV2 expected, %1 found. Skip it." ).arg( markerLayer->layerType() ) ) );
    }
    else
    {
      markerLayer->writeSldMarker( doc, graphicStrokeElem, props );
    }

    if ( !gap.isEmpty() )
    {
      QDomElement gapElem = doc.createElement( "se:Gap" );
      QgsSymbolLayerV2Utils::createFunctionElement( doc, gapElem, gap );
      graphicStrokeElem.appendChild( gapElem );
    }

    if ( !doubleNear( mOffset, 0.0 ) )
    {
      QDomElement perpOffsetElem = doc.createElement( "se:PerpendicularOffset" );
      perpOffsetElem.appendChild( doc.createTextNode( QString::number( mOffset ) ) );
      symbolizerElem.appendChild( perpOffsetElem );
    }
  }
}
Example #18
0
bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height ) const
{
  if ( qAbs( mRotation ) <= 0.0 ) //width and height stays the same if there is no rotation
  {
    return true;
  }

  if ( doubleNear( qAbs( mRotation ), 90 ) || doubleNear( qAbs( mRotation ), 270 ) )
  {
    double tmp = width;
    width = height;
    height = tmp;
    return true;
  }

  double x1 = 0;
  double y1 = 0;
  double x2 = width;
  double y2 = 0;
  double x3 = width;
  double y3 = height;
  double x4 = 0;
  double y4 = height;
  double midX = width / 2.0;
  double midY = height / 2.0;

  if ( !cornerPointOnRotatedAndScaledRect( x1, y1, width, height ) )
  {
    return false;
  }
  if ( !cornerPointOnRotatedAndScaledRect( x2, y2, width, height ) )
  {
    return false;
  }
  if ( !cornerPointOnRotatedAndScaledRect( x3, y3, width, height ) )
  {
    return false;
  }
  if ( !cornerPointOnRotatedAndScaledRect( x4, y4, width, height ) )
  {
    return false;
  }


  //assume points 1 and 3 are on the rectangle boundaries. Calculate 2 and 4.
  double distM1 = sqrt(( x1 - midX ) * ( x1 - midX ) + ( y1 - midY ) * ( y1 - midY ) );
  QPointF p2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x2, y2 ), distM1 );

  if ( p2.x() < width && p2.x() > 0 && p2.y() < height && p2.y() > 0 )
  {
    width = sqrt(( p2.x() - x1 ) * ( p2.x() - x1 ) + ( p2.y() - y1 ) * ( p2.y() - y1 ) );
    height = sqrt(( x3 - p2.x() ) * ( x3 - p2.x() ) + ( y3 - p2.y() ) * ( y3 - p2.y() ) );
    return true;
  }

  //else assume that points 2 and 4 are on the rectangle boundaries. Calculate 1 and 3
  double distM2 = sqrt(( x2 - midX ) * ( x2 - midX ) + ( y2 - midY ) * ( y2 - midY ) );
  QPointF p1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x1, y1 ), distM2 );
  QPointF p3 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x3, y3 ), distM2 );
  width = sqrt(( x2 - p1.x() ) * ( x2 - p1.x() ) + ( y2 - p1.y() ) * ( y2 - p1.y() ) );
  height = sqrt(( p3.x() - x2 ) * ( p3.x() - x2 ) + ( p3.y() - y2 ) * ( p3.y() - y2 ) );
  return true;
}
void QgsSvgMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context )
{
  QPainter* p = context.renderContext().painter();
  if ( !p )
  {
    return;
  }

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

  p->save();
  QPointF outputOffset = QPointF( context.outputLineWidth( mOffset.x() ), context.outputLineWidth( mOffset.y() ) );
  if ( mAngle )
    outputOffset = _rotatedOffset( outputOffset, mAngle );
  p->translate( point + outputOffset );

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

  bool fitsInCache = true;
  bool usePict = true;
  double hwRatio = 1.0;
  if ( drawOnScreen && !rotated )
  {
    usePict = false;
    const QImage& img = QgsSvgCache::instance()->svgAsImage( mPath, size, mFillColor, mOutlineColor, mOutlineWidth,
                        context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor(), fitsInCache );
    if ( fitsInCache && img.width() > 1 )
    {
      //consider transparency
      if ( !doubleNear( 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( mPath, size, mFillColor, mOutlineColor, mOutlineWidth,
                          context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor() );

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

  if ( context.selected() )
  {
    QPen pen( context.selectionColor() );
    double penWidth = context.outputLineWidth( 1.0 );
    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();
}
QgsRasterBlock * QgsRasterDataProvider::block( int theBandNo, QgsRectangle  const & theExtent, int theWidth, int theHeight )
{
  QgsDebugMsg( QString( "theBandNo = %1 theWidth = %2 theHeight = %3" ).arg( theBandNo ).arg( theWidth ).arg( theHeight ) );
  QgsDebugMsg( QString( "theExtent = %1" ).arg( theExtent.toString() ) );

  QgsRasterBlock *block = new QgsRasterBlock( dataType( theBandNo ), theWidth, theHeight, noDataValue( theBandNo ) );

  if ( block->isEmpty() )
  {
    QgsDebugMsg( "Couldn't create raster block" );
    return block;
  }

  // Read necessary extent only
  QgsRectangle tmpExtent = extent().intersect( &theExtent );

  if ( tmpExtent.isEmpty() )
  {
    QgsDebugMsg( "Extent outside provider extent" );
    block->setIsNoData();
    return block;
  }

  double xRes = theExtent.width() / theWidth;
  double yRes = theExtent.height() / theHeight;
  double tmpXRes, tmpYRes;
  double providerXRes = 0;
  double providerYRes = 0;
  if ( capabilities() & ExactResolution )
  {
    providerXRes = extent().width() / xSize();
    providerYRes = extent().height() / ySize();
    tmpXRes = qMax( providerXRes, xRes );
    tmpYRes = qMax( providerYRes, yRes );
    if ( doubleNear( tmpXRes, xRes ) ) tmpXRes = xRes;
    if ( doubleNear( tmpYRes, yRes ) ) tmpYRes = yRes;
  }
  else
  {
    tmpXRes = xRes;
    tmpYRes = yRes;
  }

  if ( tmpExtent != theExtent ||
       tmpXRes > xRes || tmpYRes > yRes )
  {
    // Read smaller extent or lower resolution

    // Calculate row/col limits (before tmpExtent is aligned)
    int fromRow = qRound(( theExtent.yMaximum() - tmpExtent.yMaximum() ) / yRes );
    int toRow = qRound(( theExtent.yMaximum() - tmpExtent.yMinimum() ) / yRes ) - 1;
    int fromCol = qRound(( tmpExtent.xMinimum() - theExtent.xMinimum() ) / xRes ) ;
    int toCol = qRound(( tmpExtent.xMaximum() - theExtent.xMinimum() ) / xRes ) - 1;

    QgsDebugMsg( QString( "fromRow = %1 toRow = %2 fromCol = %3 toCol = %4" ).arg( fromRow ).arg( toRow ).arg( fromCol ).arg( toCol ) );

    if ( fromRow < 0 || fromRow >= theHeight || toRow < 0 || toRow >= theHeight ||
         fromCol < 0 || fromCol >= theWidth || toCol < 0 || toCol >= theWidth )
    {
      // Should not happen
      QgsDebugMsg( "Row or column limits out of range" );
      return block;
    }

    // If lower source resolution is used, the extent must beS aligned to original
    // resolution to avoid possible shift due to resampling
    if ( tmpXRes > xRes )
    {
      int col = floor(( tmpExtent.xMinimum() - extent().xMinimum() ) / providerXRes );
      tmpExtent.setXMinimum( extent().xMinimum() + col * providerXRes );
      col = ceil(( tmpExtent.xMaximum() - extent().xMinimum() ) / providerXRes );
      tmpExtent.setXMaximum( extent().xMinimum() + col * providerXRes );
    }
    if ( tmpYRes > yRes )
    {
      int row = floor(( extent().yMaximum() - tmpExtent.yMaximum() ) / providerYRes );
      tmpExtent.setYMaximum( extent().yMaximum() - row * providerYRes );
      row = ceil(( extent().yMaximum() - tmpExtent.yMinimum() ) / providerYRes );
      tmpExtent.setYMinimum( extent().yMaximum() - row * providerYRes );
    }
    int tmpWidth = qRound( tmpExtent.width() / tmpXRes );
    int tmpHeight = qRound( tmpExtent.height() / tmpYRes );
    tmpXRes = tmpExtent.width() / tmpWidth;
    tmpYRes = tmpExtent.height() / tmpHeight;

    QgsDebugMsg( QString( "Reading smaller block tmpWidth = %1 theHeight = %2" ).arg( tmpWidth ).arg( tmpHeight ) );
    QgsDebugMsg( QString( "tmpExtent = %1" ).arg( tmpExtent.toString() ) );

    block->setIsNoData();

    QgsRasterBlock *tmpBlock = new QgsRasterBlock( dataType( theBandNo ), tmpWidth, tmpHeight, noDataValue( theBandNo ) );

    readBlock( theBandNo, tmpExtent, tmpWidth, tmpHeight, tmpBlock->data() );

    int pixelSize = dataTypeSize( theBandNo );

    double xMin = theExtent.xMinimum();
    double yMax = theExtent.yMaximum();
    double tmpXMin = tmpExtent.xMinimum();
    double tmpYMax = tmpExtent.yMaximum();

    for ( int row = fromRow; row <= toRow; row++ )
    {
      double y = yMax - ( row + 0.5 ) * yRes;
      int tmpRow = floor(( tmpYMax - y ) / tmpYRes );

      for ( int col = fromCol; col <= toCol; col++ )
      {
        double x = xMin + ( col + 0.5 ) * xRes;
        int tmpCol = floor(( x - tmpXMin ) / tmpXRes );

        if ( tmpRow < 0 || tmpRow >= tmpHeight || tmpCol < 0 || tmpCol >= tmpWidth )
        {
          QgsDebugMsg( "Source row or column limits out of range" );
          block->setIsNoData(); // so that the problem becomes obvious and fixed
          delete tmpBlock;
          return block;
        }

        size_t tmpIndex = tmpRow * tmpWidth + tmpCol;
        size_t index = row * theWidth + col;

        char *tmpBits = tmpBlock->bits( tmpIndex );
        char *bits = block->bits( index );
        if ( !tmpBits )
        {
          QgsDebugMsg( QString( "Cannot get input block data tmpRow = %1 tmpCol = %2 tmpIndex = %3." ).arg( tmpRow ).arg( tmpCol ).arg( tmpIndex ) );
          continue;
        }
        if ( !bits )
        {
          QgsDebugMsg( "Cannot set output block data." );
          continue;
        }
        memcpy( bits, tmpBits, pixelSize );
      }
    }

    delete tmpBlock;
  }
  else
  {
    readBlock( theBandNo, theExtent, theWidth, theHeight, block->data() );
  }

  // apply user no data values
  // TODO: there are other readBlock methods where no data are not applied
  block->applyNodataValues( userNoDataValue( theBandNo ) );
  return block;
}