QgsGeometry* QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry* lineGeom )
{
    if ( !lineGeom )
    {
        return nullptr;
    }

    QgsMultiPolyline resultGeom;

    //need to go with WKB and z coordinate until QgsGeometry supports M values
    QgsConstWkbPtr wkbPtr( lineGeom->asWkb(), lineGeom->wkbSize() );
    wkbPtr.readHeader();

    QGis::WkbType wkbType = lineGeom->wkbType();
    if ( wkbType != QGis::WKBLineString25D && wkbType != QGis::WKBMultiLineString25D )
    {
        return nullptr;
    }

    if ( wkbType == QGis::WKBLineString25D )
    {
        locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure );
    }
    else if ( wkbType == QGis::WKBMultiLineString25D )
    {
        int nLines;
        wkbPtr >> nLines;
        for ( int i = 0; i < nLines; ++i )
        {
            wkbPtr.readHeader();
            wkbPtr = locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure );
        }
    }
示例#2
0
文件: qgsgml.cpp 项目: avautour/QGIS
int QgsGml::createMultiPolygonFromFragments()
{
    mCurrentWKBSize = 0;
    mCurrentWKBSize += 1 + 2 * sizeof( int );
    mCurrentWKBSize += totalWKBFragmentSize();
    mCurrentWKBSize += mCurrentWKBFragments.size() * ( 1 + 2 * sizeof( int ) ); //fragments are just the rings

    mCurrentWKB = QgsWkbPtr( new unsigned char[mCurrentWKBSize], mCurrentWKBSize );

    QgsWkbPtr wkbPtr( mCurrentWKB );
    wkbPtr << ( char ) mEndian << QGis::WKBMultiPolygon << mCurrentWKBFragments.size();

    //have outer and inner iterators
    QList< QList<QgsWkbPtr> >::const_iterator outerWkbIt = mCurrentWKBFragments.constBegin();

    for ( ; outerWkbIt != mCurrentWKBFragments.constEnd(); ++outerWkbIt )
    {
        //new polygon
        wkbPtr << ( char ) mEndian << QGis::WKBPolygon << outerWkbIt->size();

        QList<QgsWkbPtr>::const_iterator innerWkbIt = outerWkbIt->constBegin();
        for ( ; innerWkbIt != outerWkbIt->constEnd(); ++innerWkbIt )
        {
            memcpy( wkbPtr, *innerWkbIt, innerWkbIt->size() );
            wkbPtr += innerWkbIt->size();
            delete[] *innerWkbIt;
        }
    }

    mCurrentWKBFragments.clear();
    *mWkbType = QGis::WKBMultiPolygon;
    return 0;
}
QgsGeometry QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry& lineGeom )
{
  if ( lineGeom.isEmpty() )
  {
    return QgsGeometry();
  }

  QgsMultiPolyline resultGeom;

  //need to go with WKB and z coordinate until QgsGeometry supports M values
  QByteArray wkb( lineGeom.exportToWkb() );
  QgsConstWkbPtr wkbPtr( wkb );
  wkbPtr.readHeader();

  QgsWkbTypes::Type wkbType = lineGeom.wkbType();
  if ( wkbType != QgsWkbTypes::LineString25D && wkbType != QgsWkbTypes::MultiLineString25D )
  {
    return QgsGeometry();
  }

  if ( wkbType == QgsWkbTypes::LineString25D )
  {
    locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure );
  }
  else if ( wkbType == QgsWkbTypes::MultiLineString25D )
  {
    int nLines;
    wkbPtr >> nLines;
    for ( int i = 0; i < nLines; ++i )
    {
      wkbPtr.readHeader();
      wkbPtr = locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure );
    }
  }
QByteArray QgsCurvePolygon::asWkb() const
{
  int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
  QVector<QByteArray> wkbForRings;
  wkbForRings.reserve( 1 + mInteriorRings.size() );
  if ( mExteriorRing )
  {
    QByteArray wkb( mExteriorRing->asWkb() );
    binarySize += wkb.length();
    wkbForRings << wkb;
  }
  for ( const QgsCurve *curve : mInteriorRings )
  {
    QByteArray wkb( curve->asWkb() );
    binarySize += wkb.length();
    wkbForRings << wkb;
  }

  QByteArray wkbArray;
  wkbArray.resize( binarySize );
  QgsWkbPtr wkbPtr( wkbArray );
  wkbPtr << static_cast<char>( QgsApplication::endian() );
  wkbPtr << static_cast<quint32>( wkbType() );
  wkbPtr << static_cast<quint32>( wkbForRings.count() );
  for ( const QByteArray &wkb : qgis::as_const( wkbForRings ) )
  {
    wkbPtr << wkb;
  }
  return wkbArray;
}
示例#5
0
bool QgsGeometryCollectionV2::fromWkb( const unsigned char * wkb )
{
  if ( !wkb )
  {
    return false;
  }
  QgsConstWkbPtr wkbPtr( wkb + 1 );
  //type
  wkbPtr >> mWkbType;
  int nGeometries = 0;
  wkbPtr >> nGeometries;

  QList<QgsAbstractGeometryV2*> geometryList;
  for ( int i = 0; i < nGeometries; ++i )
  {
    QgsAbstractGeometryV2* geom = QgsGeometryFactory::geomFromWkb( wkbPtr );
    if ( geom )
    {
      geometryList.append( geom );
      wkbPtr += geom->wkbSize();
    }
  }

  mGeometries.resize( geometryList.size() );
  for ( int i = 0; i < geometryList.size(); ++i )
  {
    mGeometries[i] = geometryList.at( i );
  }

  return true;
}
示例#6
0
const unsigned char* QgsClipper::clippedLineWKB( const unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line )
{
  QgsConstWkbPtr wkbPtr( wkb + 1 );

  unsigned int wkbType, nPoints;

  wkbPtr >> wkbType >> nPoints;

  bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) );
  bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) );


  double p0x, p0y, p1x = 0.0, p1y = 0.0; //original coordinates
  double p1x_c, p1y_c; //clipped end coordinates
  double lastClipX = 0.0, lastClipY = 0.0; //last successfully clipped coords

  line.clear();
  line.reserve( nPoints + 1 );

  for ( unsigned int i = 0; i < nPoints; ++i )
  {
    if ( i == 0 )
    {
      wkbPtr >> p1x >> p1y;
      if ( hasZValue )
        wkbPtr += sizeof( double );
      if ( hasMValue )
        wkbPtr += sizeof( double );

      continue;
    }
    else
    {
示例#7
0
const unsigned char* QgsDistanceArea::measureLine( const unsigned char* feature, double* area, bool hasZptr )
{
  QgsConstWkbPtr wkbPtr( feature + 1 + sizeof( int ) );
  int nPoints;
  wkbPtr >> nPoints;

  QList<QgsPoint> points;
  double x, y;

  QgsDebugMsg( "This feature WKB has " + QString::number( nPoints ) + " points" );
  // Extract the points from the WKB format into the vector
  for ( int i = 0; i < nPoints; ++i )
  {
    wkbPtr >> x >> y;
    if ( hasZptr )
    {
      // totally ignore Z value
      wkbPtr += sizeof( double );
    }

    points.append( QgsPoint( x, y ) );
  }

  *area = measureLine( points );
  return wkbPtr;
}
示例#8
0
bool QgsPolygonV2::fromWkb( const unsigned char* wkb )
{
  clear();
  if ( !wkb )
  {
    return false;
  }

  QgsConstWkbPtr wkbPtr( wkb );
  QgsWKBTypes::Type type = wkbPtr.readHeader();
  if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::Polygon )
  {
    return false;
  }
  mWkbType = type;

  QgsWKBTypes::Type ringType;
  switch ( mWkbType )
  {
    case QgsWKBTypes::PolygonZ:
      ringType = QgsWKBTypes::LineStringZ;
      break;
    case QgsWKBTypes::PolygonM:
      ringType = QgsWKBTypes::LineStringM;
      break;
    case QgsWKBTypes::PolygonZM:
      ringType = QgsWKBTypes::LineStringZM;
      break;
    case QgsWKBTypes::Polygon25D:
      ringType = QgsWKBTypes::LineString25D;
      break;
    default:
      ringType = QgsWKBTypes::LineString;
      break;
  }

  int nRings;
  wkbPtr >> nRings;
  for ( int i = 0; i < nRings; ++i )
  {
    QgsLineStringV2* line = new QgsLineStringV2();
    line->fromWkbPoints( ringType, wkbPtr );
    /*if ( !line->isRing() )
    {
      delete line; continue;
    }*/

    if ( !mExteriorRing )
    {
      mExteriorRing = line;
    }
    else
    {
      mInteriorRings.append( line );
    }
  }

  return true;
}
示例#9
0
double QgsDistanceArea::measurePerimeter( const QgsGeometry* geometry )
{
  if ( !geometry )
    return 0.0;

  const unsigned char* wkb = geometry->asWkb();
  if ( !wkb )
    return 0.0;

  QgsConstWkbPtr wkbPtr( wkb + 1 );
  QGis::WkbType wkbType;
  wkbPtr >> wkbType;

  double res = 0.0, resTotal = 0.0;
  int count, i;

  // measure distance or area based on what is the type of geometry
  bool hasZptr = false;

  switch ( wkbType )
  {
    case QGis::WKBLineString25D:
    case QGis::WKBLineString:
    case QGis::WKBMultiLineString25D:
    case QGis::WKBMultiLineString:
      return 0.0;

    case QGis::WKBPolygon25D:
      hasZptr = true;
      //intentional fall-through
    case QGis::WKBPolygon:
      measurePolygon( wkb, 0, &res, hasZptr );
      QgsDebugMsg( "returning " + QString::number( res ) );
      return res;

    case QGis::WKBMultiPolygon25D:
      hasZptr = true;
      //intentional fall-through
    case QGis::WKBMultiPolygon:
      wkbPtr >> count;
      for ( i = 0; i < count; i++ )
      {
        wkbPtr = measurePolygon( wkbPtr, 0, &res, hasZptr );
        if ( !wkbPtr )
        {
          QgsDebugMsg( "measurePolygon returned 0" );
          break;
        }
        resTotal += res;
      }
      QgsDebugMsg( "returning " + QString::number( resTotal ) );
      return resTotal;

    default:
      QgsDebugMsg( QString( "measure: unexpected geometry type: %1" ).arg( wkbType ) );
      return 0;
  }
}
示例#10
0
const unsigned char* QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent )
{
  QgsConstWkbPtr wkbPtr( wkb + 1 );
  unsigned int wkbType, nPoints;
  wkbPtr >> wkbType >> nPoints;

  bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) );
  bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) );

  double x = 0.0;
  double y = 0.0;
  const QgsCoordinateTransform* ct = context.coordinateTransform();
  const QgsMapToPixel& mtp = context.mapToPixel();

  //apply clipping for large lines to achieve a better rendering performance
  if ( clipToExtent && nPoints > 1 )
  {
    const QgsRectangle& e = context.extent();
    double cw = e.width() / 10;
    double ch = e.height() / 10;
    QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
    wkbPtr = QgsConstWkbPtr( QgsClipper::clippedLineWKB( wkb, clipRect, pts ) );
  }
  else
  {
    pts.resize( nPoints );

    QPointF* ptr = pts.data();
    for ( unsigned int i = 0; i < nPoints; ++i, ++ptr )
    {
      wkbPtr >> x >> y;
      if ( hasZValue )
        wkbPtr += sizeof( double );
      if ( hasMValue )
        wkbPtr += sizeof( double );

      *ptr = QPointF( x, y );
    }
  }

  //transform the QPolygonF to screen coordinates
  if ( ct )
  {
    ct->transformPolygon( pts );
  }

  QPointF* ptr = pts.data();
  for ( int i = 0; i < pts.size(); ++i, ++ptr )
  {
    mtp.transformInPlace( ptr->rx(), ptr->ry() );
  }

  return wkbPtr;
}
示例#11
0
QgsGeometry *QgsGPXFeatureIterator::readWaypointGeometry( const QgsWaypoint &wpt )
{
  int size = 1 + sizeof( int ) + 2 * sizeof( double );
  unsigned char *geo = new unsigned char[size];

  QgsWkbPtr wkbPtr( geo, size );
  wkbPtr << ( char ) QgsApplication::endian() << QgsWkbTypes::Point << wpt.lon << wpt.lat;

  QgsGeometry *g = new QgsGeometry();
  g->fromWkb( geo, size );
  return g;
}
示例#12
0
bool QgsLineStringV2::fromWkb( const unsigned char* wkb )
{
  if ( !wkb )
  {
    return false;
  }
  QgsConstWkbPtr wkbPtr( wkb );
  QgsWKBTypes::Type type = wkbPtr.readHeader();
  if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::LineString )
  {
    return false;
  }
  mWkbType = type;
  importVerticesFromWkb( wkbPtr );
  return true;
}
示例#13
0
QgsGeometry *QgsGPXFeatureIterator::readTrackGeometry( const QgsTrack &trk )
{
  // TODO: support multi line string for segments
  if ( trk.segments.isEmpty() )
    return nullptr;

  // A track consists of several segments. Add all those segments into one.
  int totalPoints = 0;
  for ( int i = 0; i < trk.segments.size(); i ++ )
  {
    totalPoints += trk.segments[i].points.size();
  }

  if ( totalPoints == 0 )
    return nullptr;

  //QgsDebugMsg( "GPX feature track total points: " + QString::number( totalPoints ) );

  // some wkb voodoo
  int size = 1 + 2 * sizeof( int ) + 2 * sizeof( double ) * totalPoints;
  unsigned char *geo = new unsigned char[size];
  if ( !geo )
  {
    QgsDebugMsg( "Track too large!" );
    return nullptr;
  }

  QgsWkbPtr wkbPtr( geo, size );
  wkbPtr << ( char ) QgsApplication::endian() << QgsWkbTypes::LineString << totalPoints;

  for ( int k = 0; k < trk.segments.size(); k++ )
  {
    int nPoints = trk.segments[k].points.size();
    for ( int i = 0; i < nPoints; ++i )
    {
      wkbPtr << trk.segments[k].points[i].lon << trk.segments[k].points[i].lat;
    }
  }

  //create QgsGeometry and use it for intersection test
  //if geometry is to be fetched, it is attached to the feature, otherwise we delete it
  QgsGeometry *g = new QgsGeometry();
  g->fromWkb( geo, size );
  return g;
}
示例#14
0
const unsigned char* QgsFeatureRendererV2::_getPoint( QPointF& pt, QgsRenderContext& context, const unsigned char* wkb )
{
    QgsConstWkbPtr wkbPtr( wkb + 1 );
    unsigned int wkbType;
    wkbPtr >> wkbType >> pt.rx() >> pt.ry();

    if ( static_cast< QgsWKBTypes::Type >( wkbType ) == QgsWKBTypes::Point25D || static_cast< QgsWKBTypes::Type >( wkbType ) == QgsWKBTypes::PointZ )
        wkbPtr += sizeof( double );

    if ( context.coordinateTransform() )
    {
        double z = 0; // dummy variable for coordiante transform
        context.coordinateTransform()->transformInPlace( pt.rx(), pt.ry(), z );
    }

    context.mapToPixel().transformInPlace( pt.rx(), pt.ry() );

    return wkbPtr;
}
示例#15
0
QgsGeometry *QgsGPXFeatureIterator::readRouteGeometry( const QgsRoute &rte )
{
  // some wkb voodoo
  int size = 1 + 2 * sizeof( int ) + 2 * sizeof( double ) * rte.points.size();
  unsigned char *geo = new unsigned char[size];

  QgsWkbPtr wkbPtr( geo, size );
  wkbPtr << ( char ) QgsApplication::endian() << QgsWkbTypes::LineString << rte.points.size();

  for ( int i = 0; i < rte.points.size(); ++i )
  {
    wkbPtr << rte.points[i].lon << rte.points[i].lat;
  }

  //create QgsGeometry and use it for intersection test
  //if geometry is to be fetched, it is attached to the feature, otherwise we delete it
  QgsGeometry *g = new QgsGeometry();
  g->fromWkb( geo, size );
  return g;
}
示例#16
0
文件: qgsgml.cpp 项目: avautour/QGIS
int QgsGml::createPolygonFromFragments()
{
    mCurrentWKBSize = 1 + 2 * sizeof( int ) + totalWKBFragmentSize();
    mCurrentWKB = QgsWkbPtr( new unsigned char[mCurrentWKBSize], mCurrentWKBSize );

    QgsWkbPtr wkbPtr( mCurrentWKB );
    wkbPtr << mEndian << QGis::WKBPolygon << mCurrentWKBFragments.constBegin()->size();

    QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
    for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
    {
        memcpy( wkbPtr, *wkbIt, wkbIt->size() );
        wkbPtr += wkbIt->size();
        delete[] *wkbIt;
    }

    mCurrentWKBFragments.clear();
    *mWkbType = QGis::WKBPolygon;
    return 0;
}
示例#17
0
文件: qgsgml.cpp 项目: avautour/QGIS
int QgsGml::createMultiLineFromFragments()
{
    mCurrentWKBSize = 1 + 2 * sizeof( int ) + totalWKBFragmentSize();
    mCurrentWKB = QgsWkbPtr( new unsigned char[mCurrentWKBSize], mCurrentWKBSize );

    QgsWkbPtr wkbPtr( mCurrentWKB, mCurrentWKBSize );

    wkbPtr << mEndian << QGis::WKBMultiLineString << mCurrentWKBFragments.constBegin()->size();

    //copy (and delete) all the wkb fragments
    QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
    for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
    {
        memcpy( wkbPtr, *wkbIt, wkbIt->size() );
        wkbPtr += wkbIt->size();
        delete[] *wkbIt;
    }

    mCurrentWKBFragments.clear();
    *mWkbType = QGis::WKBMultiLineString;
    return 0;
}
示例#18
0
void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymbolV2* symbol, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker )
{
  QgsSymbolV2::SymbolType symbolType = symbol->type();


  const QgsGeometry* geom = feature.constGeometry();
  if ( !geom || !geom->geometry() )
  {
    return;
  }

  const QgsGeometry* segmentizedGeometry = geom;
  bool deleteSegmentizedGeometry = false;
  context.setGeometry( geom->geometry() );

  //convert curve types to normal point/line/polygon ones
  switch ( QgsWKBTypes::flatType( geom->geometry()->wkbType() ) )
  {
    case QgsWKBTypes::CurvePolygon:
    case QgsWKBTypes::CircularString:
    case QgsWKBTypes::CompoundCurve:
    case QgsWKBTypes::MultiSurface:
    case QgsWKBTypes::MultiCurve:
    {
      QgsAbstractGeometryV2* g = geom->geometry()->segmentize();
      if ( !g )
      {
        return;
      }
      segmentizedGeometry = new QgsGeometry( g );
      deleteSegmentizedGeometry = true;
      break;
    }

    default:
      break;
  }

  switch ( QgsWKBTypes::flatType( segmentizedGeometry->geometry()->wkbType() ) )
  {
    case QgsWKBTypes::Point:
    {
      if ( symbolType != QgsSymbolV2::Marker )
      {
        QgsDebugMsg( "point can be drawn only with marker symbol!" );
        break;
      }
      QPointF pt;
      _getPoint( pt, context, segmentizedGeometry->asWkb() );
      (( QgsMarkerSymbolV2* )symbol )->renderPoint( pt, &feature, context, layer, selected );
      if ( context.testFlag( QgsRenderContext::DrawSymbolBounds ) )
      {
        //draw debugging rect
        context.painter()->setPen( Qt::red );
        context.painter()->setBrush( QColor( 255, 0, 0, 100 ) );
        context.painter()->drawRect((( QgsMarkerSymbolV2* )symbol )->bounds( pt, context ) );
      }
    }
    break;
    case QgsWKBTypes::LineString:
    {
      if ( symbolType != QgsSymbolV2::Line )
      {
        QgsDebugMsg( "linestring can be drawn only with line symbol!" );
        break;
      }
      QPolygonF pts;
      _getLineString( pts, context, segmentizedGeometry->asWkb(), symbol->clipFeaturesToExtent() );
      (( QgsLineSymbolV2* )symbol )->renderPolyline( pts, &feature, context, layer, selected );
    }
    break;
    case QgsWKBTypes::Polygon:
    {
      if ( symbolType != QgsSymbolV2::Fill )
      {
        QgsDebugMsg( "polygon can be drawn only with fill symbol!" );
        break;
      }
      QPolygonF pts;
      QList<QPolygonF> holes;
      _getPolygon( pts, holes, context, segmentizedGeometry->asWkb(), symbol->clipFeaturesToExtent() );
      (( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), &feature, context, layer, selected );
    }
    break;

    case QgsWKBTypes::MultiPoint:
    {
      if ( symbolType != QgsSymbolV2::Marker )
      {
        QgsDebugMsg( "multi-point can be drawn only with marker symbol!" );
        break;
      }

      QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb() + 1 + sizeof( int ) );
      unsigned int num;
      wkbPtr >> num;
      const unsigned char* ptr = wkbPtr;
      QPointF pt;

      for ( unsigned int i = 0; i < num; ++i )
      {
        ptr = QgsConstWkbPtr( _getPoint( pt, context, ptr ) );
        (( QgsMarkerSymbolV2* )symbol )->renderPoint( pt, &feature, context, layer, selected );
      }
    }
    break;

    case QgsWKBTypes::MultiCurve:
    case QgsWKBTypes::MultiLineString:
    {
      if ( symbolType != QgsSymbolV2::Line )
      {
        QgsDebugMsg( "multi-linestring can be drawn only with line symbol!" );
        break;
      }

      QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb() + 1 + sizeof( int ) );
      unsigned int num;
      wkbPtr >> num;
      const unsigned char* ptr = wkbPtr;
      QPolygonF pts;

      const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );

      for ( unsigned int i = 0; i < num; ++i )
      {
        if ( geomCollection )
        {
          context.setGeometry( geomCollection->geometryN( i ) );
        }
        ptr = QgsConstWkbPtr( _getLineString( pts, context, ptr, symbol->clipFeaturesToExtent() ) );
        (( QgsLineSymbolV2* )symbol )->renderPolyline( pts, &feature, context, layer, selected );
      }
    }
    break;

    case QgsWKBTypes::MultiSurface:
    case QgsWKBTypes::MultiPolygon:
    {
      if ( symbolType != QgsSymbolV2::Fill )
      {
        QgsDebugMsg( "multi-polygon can be drawn only with fill symbol!" );
        break;
      }

      QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb() + 1 + sizeof( int ) );
      unsigned int num;
      wkbPtr >> num;
      const unsigned char* ptr = wkbPtr;
      QPolygonF pts;
      QList<QPolygonF> holes;

      const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );

      for ( unsigned int i = 0; i < num; ++i )
      {
        if ( geomCollection )
        {
          context.setGeometry( geomCollection->geometryN( i ) );
        }
        ptr = _getPolygon( pts, holes, context, ptr, symbol->clipFeaturesToExtent() );
        (( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), &feature, context, layer, selected );
      }
      break;
    }
    default:
      QgsDebugMsg( QString( "feature %1: unsupported wkb type 0x%2 for rendering" ).arg( feature.id() ).arg( geom->wkbType(), 0, 16 ) );
  }

  if ( drawVertexMarker )
  {
    const QgsCoordinateTransform* ct = context.coordinateTransform();
    const QgsMapToPixel& mtp = context.mapToPixel();

    QgsPointV2 vertexPoint;
    QgsVertexId vertexId;
    double x, y, z;
    QPointF mapPoint;
    while ( geom->geometry()->nextVertex( vertexId, vertexPoint ) )
    {
      //transform
      x = vertexPoint.x(); y = vertexPoint.y(); z = vertexPoint.z();
      if ( ct )
      {
        ct->transformInPlace( x, y, z );
      }
      mapPoint.setX( x ); mapPoint.setY( y );
      mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() );
      renderVertexMarker( mapPoint, context );
    }
  }

  if ( deleteSegmentizedGeometry )
  {
    delete segmentizedGeometry;
  }
}
示例#19
0
const unsigned char* QgsSymbolV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent )
{
  QgsConstWkbPtr wkbPtr( wkb + 1 );

  unsigned int wkbType, numRings;
  wkbPtr >> wkbType >> numRings;

  if ( numRings == 0 )  // sanity check for zero rings in polygon
    return wkbPtr;

  bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) );
  bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) );

  double x, y;
  holes.clear();

  const QgsCoordinateTransform* ct = context.coordinateTransform();
  const QgsMapToPixel& mtp = context.mapToPixel();
  const QgsRectangle& e = context.extent();
  double cw = e.width() / 10;
  double ch = e.height() / 10;
  QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );

  for ( unsigned int idx = 0; idx < numRings; idx++ )
  {
    unsigned int nPoints;
    wkbPtr >> nPoints;

    QPolygonF poly( nPoints );

    // Extract the points from the WKB and store in a pair of vectors.
    QPointF* ptr = poly.data();
    for ( unsigned int jdx = 0; jdx < nPoints; ++jdx, ++ptr )
    {
      wkbPtr >> x >> y;
      if ( hasZValue )
        wkbPtr += sizeof( double );
      if ( hasMValue )
        wkbPtr += sizeof( double );

      *ptr = QPointF( x, y );
    }

    if ( nPoints < 1 )
      continue;

    //clip close to view extent, if needed
    QRectF ptsRect = poly.boundingRect();
    if ( clipToExtent && !context.extent().contains( ptsRect ) ) QgsClipper::trimPolygon( poly, clipRect );

    //transform the QPolygonF to screen coordinates
    if ( ct )
    {
      ct->transformPolygon( poly );
    }


    ptr = poly.data();
    for ( int i = 0; i < poly.size(); ++i, ++ptr )
    {
      mtp.transformInPlace( ptr->rx(), ptr->ry() );
    }

    if ( idx == 0 )
      pts = poly;
    else
      holes.append( poly );
  }

  return wkbPtr;
}
示例#20
0
const unsigned char *QgsDistanceArea::measurePolygon( const unsigned char* feature, double* area, double* perimeter, bool hasZptr ) const
{
  if ( !feature )
  {
    QgsDebugMsg( "no feature to measure" );
    return nullptr;
  }

  QgsConstWkbPtr wkbPtr( feature + 1 + sizeof( int ) );

  // get number of rings in the polygon
  int numRings;
  wkbPtr >> numRings;

  if ( numRings == 0 )
  {
    QgsDebugMsg( "no rings to measure" );
    return nullptr;
  }

  // Set pointer to the first ring
  QList<QgsPoint> points;
  QgsPoint pnt;
  double x, y;
  if ( area )
    *area = 0;
  if ( perimeter )
    *perimeter = 0;

  try
  {
    for ( int idx = 0; idx < numRings; idx++ )
    {
      int nPoints;
      wkbPtr >> nPoints;

      // Extract the points from the WKB and store in a pair of
      // vectors.
      for ( int jdx = 0; jdx < nPoints; jdx++ )
      {
        wkbPtr >> x >> y;
        if ( hasZptr )
        {
          // totally ignore Z value
          wkbPtr += sizeof( double );
        }

        pnt = QgsPoint( x, y );

        if ( mEllipsoidalMode && ( mEllipsoid != GEO_NONE ) )
        {
          pnt = mCoordTransform->transform( pnt );
        }
        points.append( pnt );
      }

      if ( points.size() > 2 )
      {
        if ( area )
        {
          double areaTmp = computePolygonArea( points );
          if ( idx == 0 )
          {
            // exterior ring
            *area += areaTmp;
          }
          else
          {
            *area -= areaTmp; // interior rings
          }
        }

        if ( perimeter )
        {
          if ( idx == 0 )
          {
            // exterior ring
            *perimeter += computeDistance( points );
          }
        }
      }

      points.clear();
    }
  }
  catch ( QgsCsException &cse )
  {
    Q_UNUSED( cse );
    QgsMessageLog::logMessage( QObject::tr( "Caught a coordinate system exception while trying to transform a point. Unable to calculate polygon area or perimeter." ) );
  }

  return wkbPtr;
}
void QgsPointDisplacementRenderer::drawGroup( const DisplacementGroup& group, QgsRenderContext& context )
{
  const QgsFeature& feature = group.begin().value().first;
  bool selected = mSelectedFeatures.contains( feature.id() ); // maybe we should highlight individual features instead of the whole group?



  //get list of labels and symbols
  QStringList labelAttributeList;
  QList< QgsMarkerSymbolV2* > symbolList;
  QgsFeatureList featureList;

  QgsMultiPointV2* groupMultiPoint = new QgsMultiPointV2();
  for ( DisplacementGroup::const_iterator attIt = group.constBegin(); attIt != group.constEnd(); ++attIt )
  {
    labelAttributeList << ( mDrawLabels ? getLabel( attIt.value().first ) : QString() );
    symbolList << dynamic_cast<QgsMarkerSymbolV2*>( attIt.value().second );
    featureList << attIt.value().first;
    groupMultiPoint->addGeometry( attIt.value().first.constGeometry()->geometry()->clone() );
  }

  //calculate centroid of all points, this will be center of group
  QgsGeometry groupGeom( groupMultiPoint );
  QgsGeometry* centroid = groupGeom.centroid();
  QPointF pt;
  QgsConstWkbPtr wkbPtr( centroid->asWkb(), centroid->wkbSize() );
  _getPoint( pt, context, wkbPtr );
  delete centroid;

  //calculate max diagonal size from all symbols in group
  double diagonal = 0;
  Q_FOREACH ( QgsMarkerSymbolV2* symbol, symbolList )
  {
    if ( symbol )
    {
      diagonal = qMax( diagonal, QgsSymbolLayerV2Utils::convertToPainterUnits( context,
                       M_SQRT2 * symbol->size(),
                       symbol->sizeUnit(), symbol->sizeMapUnitScale() ) );
    }
  }

  QgsSymbolV2RenderContext symbolContext( context, QgsSymbolV2::MM, 1.0, selected );

  QList<QPointF> symbolPositions;
  QList<QPointF> labelPositions;
  double circleRadius = -1.0;
  calculateSymbolAndLabelPositions( symbolContext, pt, symbolList.size(), diagonal, symbolPositions, labelPositions, circleRadius );

  //draw Circle
  if ( circleRadius > 0 )
    drawCircle( circleRadius, symbolContext, pt, symbolList.size() );

  //draw mid point
  if ( labelAttributeList.size() > 1 )
  {
    if ( mCenterSymbol )
    {
      mCenterSymbol->renderPoint( pt, &feature, context, -1, selected );
    }
    else
    {
      context.painter()->drawRect( QRectF( pt.x() - symbolContext.outputLineWidth( 1 ), pt.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) );
    }
  }

  //draw symbols on the circle
  drawSymbols( featureList, context, symbolList, symbolPositions, selected );
  //and also the labels
  drawLabels( pt, symbolContext, labelPositions, labelAttributeList );
}
示例#22
0
文件: qgsgml.cpp 项目: avautour/QGIS
void QgsGml::endElement( const XML_Char* el )
{
    QString elementName( QString::fromUtf8( el ) );
    ParseMode theParseMode( mParseModeStack.isEmpty() ? none : mParseModeStack.top() );
    QStringList splitName =  elementName.split( NS_SEPARATOR );
    QString localName = splitName.last();
    QString ns = splitName.size() > 1 ? splitName.first() : "";

    if (( theParseMode == coordinate && elementName == GML_NAMESPACE + NS_SEPARATOR + "coordinates" )
            || ( theParseMode == posList && (
                     elementName == GML_NAMESPACE + NS_SEPARATOR + "pos"
                     || elementName == GML_NAMESPACE + NS_SEPARATOR + "posList" ) ) )
    {
        mParseModeStack.pop();
    }
    else if ( theParseMode == attribute && localName == mAttributeName ) //add a thematic attribute to the feature
    {
        mParseModeStack.pop();

        setAttribute( mAttributeName, mStringCash );
    }
    else if ( theParseMode == geometry && localName == mGeometryAttribute )
    {
        mParseModeStack.pop();
    }
    else if ( theParseMode == boundingBox && elementName == GML_NAMESPACE + NS_SEPARATOR + "boundedBy" )
    {
        //create bounding box from mStringCash
        if ( createBBoxFromCoordinateString( mCurrentExtent, mStringCash ) != 0 )
        {
            QgsDebugMsg( "creation of bounding box failed" );
        }

        mParseModeStack.pop();
    }
    else if ( theParseMode == feature && localName == mTypeName )
    {
        Q_ASSERT( mCurrentFeature );
        if ( mCurrentWKBSize > 0 )
        {
            QgsGeometry *g = new QgsGeometry();
            g->fromWkb( mCurrentWKB, mCurrentWKBSize );
            mCurrentFeature->setGeometry( g );
            mCurrentWKB = QgsWkbPtr( nullptr, 0 );
        }
        else if ( !mCurrentExtent.isEmpty() )
        {
            mCurrentFeature->setGeometry( QgsGeometry::fromRect( mCurrentExtent ) );
        }
        else
        {
            mCurrentFeature->setGeometry( nullptr );
        }
        mCurrentFeature->setValid( true );

        mFeatures.insert( mCurrentFeature->id(), mCurrentFeature );
        if ( !mCurrentFeatureId.isEmpty() )
        {
            mIdMap.insert( mCurrentFeature->id(), mCurrentFeatureId );
        }
        mCurrentFeature = nullptr;
        ++mFeatureCount;
        mParseModeStack.pop();
    }
    else if ( elementName == GML_NAMESPACE + NS_SEPARATOR + "Point" )
    {
        QList<QgsPoint> pointList;
        if ( pointsFromString( pointList, mStringCash ) != 0 )
        {
            //error
        }

        if ( pointList.isEmpty() )
            return;  // error

        if ( theParseMode == QgsGml::geometry )
        {
            //directly add WKB point to the feature
            if ( getPointWKB( mCurrentWKB, *( pointList.constBegin() ) ) != 0 )
            {
                //error
            }

            if ( *mWkbType != QGis::WKBMultiPoint ) //keep multitype in case of geometry type mix
            {
                *mWkbType = QGis::WKBPoint;
            }
        }
        else //multipoint, add WKB as fragment
        {
            QgsWkbPtr wkbPtr( nullptr, 0 );
            if ( getPointWKB( wkbPtr, *( pointList.constBegin() ) ) != 0 )
            {
                //error
            }
            if ( !mCurrentWKBFragments.isEmpty() )
            {
                mCurrentWKBFragments.last().push_back( wkbPtr );
            }
            else
            {
                QgsDebugMsg( "No wkb fragments" );
                delete [] wkbPtr;
            }
        }
    }
    else if ( elementName == GML_NAMESPACE + NS_SEPARATOR + "LineString" )
    {
        //add WKB point to the feature

        QList<QgsPoint> pointList;
        if ( pointsFromString( pointList, mStringCash ) != 0 )
        {
            //error
        }
        if ( theParseMode == QgsGml::geometry )
        {
            if ( getLineWKB( mCurrentWKB, pointList ) != 0 )
            {
                //error
            }

            if ( *mWkbType != QGis::WKBMultiLineString )//keep multitype in case of geometry type mix
            {
                *mWkbType = QGis::WKBLineString;
            }
        }
        else //multiline, add WKB as fragment
        {
            QgsWkbPtr wkbPtr( nullptr, 0 );
            if ( getLineWKB( wkbPtr, pointList ) != 0 )
            {
                //error
            }
            if ( !mCurrentWKBFragments.isEmpty() )
            {
                mCurrentWKBFragments.last().push_back( wkbPtr );
            }
            else
            {
                QgsDebugMsg( "no wkb fragments" );
                delete [] wkbPtr;
            }
        }
    }
    else if (( theParseMode == geometry || theParseMode == multiPolygon ) && elementName == GML_NAMESPACE + NS_SEPARATOR + "LinearRing" )
    {
        QList<QgsPoint> pointList;
        if ( pointsFromString( pointList, mStringCash ) != 0 )
        {
            //error
        }

        QgsWkbPtr wkbPtr( nullptr, 0 );
        if ( getRingWKB( wkbPtr, pointList ) != 0 )
        {
            //error
        }

        if ( !mCurrentWKBFragments.isEmpty() )
        {
            mCurrentWKBFragments.last().push_back( wkbPtr );
        }
        else
        {
            delete[] wkbPtr;
            QgsDebugMsg( "no wkb fragments" );
        }
    }
    else if (( theParseMode == geometry || theParseMode == multiPolygon ) && elementName == GML_NAMESPACE + NS_SEPARATOR + "Polygon" )
    {
        if ( *mWkbType != QGis::WKBMultiPolygon )//keep multitype in case of geometry type mix
        {
            *mWkbType = QGis::WKBPolygon;
        }

        if ( theParseMode == geometry )
        {
            createPolygonFromFragments();
        }
    }
    else if ( theParseMode == multiPoint && elementName == GML_NAMESPACE + NS_SEPARATOR + "MultiPoint" )
    {
        *mWkbType = QGis::WKBMultiPoint;
        mParseModeStack.pop();
        createMultiPointFromFragments();
    }
    else if ( theParseMode == multiLine && elementName == GML_NAMESPACE + NS_SEPARATOR + "MultiLineString" )
    {
        *mWkbType = QGis::WKBMultiLineString;
        mParseModeStack.pop();
        createMultiLineFromFragments();
    }
    else if ( theParseMode == multiPolygon && elementName == GML_NAMESPACE + NS_SEPARATOR + "MultiPolygon" )
    {
        *mWkbType = QGis::WKBMultiPolygon;
        mParseModeStack.pop();
        createMultiPolygonFromFragments();
    }
}