bool QgsCurvePolygon::fromWkb( QgsConstWkbPtr &wkbPtr )
{
  clear();
  if ( !wkbPtr )
  {
    return false;
  }

  QgsWkbTypes::Type type = wkbPtr.readHeader();
  if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::CurvePolygon )
  {
    return false;
  }
  mWkbType = type;

  int nRings;
  wkbPtr >> nRings;
  std::unique_ptr< QgsCurve > currentCurve;
  for ( int i = 0; i < nRings; ++i )
  {
    QgsWkbTypes::Type curveType = wkbPtr.readHeader();
    wkbPtr -= 1 + sizeof( int );
    QgsWkbTypes::Type flatCurveType = QgsWkbTypes::flatType( curveType );
    if ( flatCurveType == QgsWkbTypes::LineString )
    {
      currentCurve.reset( new QgsLineString() );
    }
    else if ( flatCurveType == QgsWkbTypes::CircularString )
    {
      currentCurve.reset( new QgsCircularString() );
    }
    else if ( flatCurveType == QgsWkbTypes::CompoundCurve )
    {
      currentCurve.reset( new QgsCompoundCurve() );
    }
    else
    {
      return false;
    }
    currentCurve->fromWkb( wkbPtr );  // also updates wkbPtr
    if ( i == 0 )
    {
      mExteriorRing = std::move( currentCurve );
    }
    else
    {
      mInteriorRings.append( currentCurve.release() );
    }
  }

  return true;
}
Example #2
0
QgsConstWkbPtr QgsClipper::clippedLineWKB( QgsConstWkbPtr wkbPtr, const QgsRectangle& clipExtent, QPolygonF& line )
{
  QgsWKBTypes::Type wkbType = wkbPtr.readHeader();

  int nPoints;
  wkbPtr >> nPoints;

  int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );

  if ( static_cast<int>( nPoints * ( 2 * sizeof( double ) + skipZM ) ) > wkbPtr.remaining() )
  {
    QgsDebugMsg( QString( "%1 points exceed wkb length (%2>%3)" ).arg( nPoints ).arg( nPoints * ( 2 * sizeof( double ) + skipZM ) ).arg( wkbPtr.remaining() ) );
    return QgsConstWkbPtr( nullptr, 0 );
  }

  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 ( int i = 0; i < nPoints; ++i )
  {
    if ( i == 0 )
    {
      wkbPtr >> p1x >> p1y;
      wkbPtr += skipZM;
      continue;
    }
    else
    {
Example #3
0
bool QgsPolygonV2::fromWkb( QgsConstWkbPtr wkbPtr )
{
  clear();
  if ( !wkbPtr )
  {
    return false;
  }

  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;
}
Example #4
0
bool QgsCompoundCurve::fromWkb( QgsConstWkbPtr &wkbPtr )
{
  clear();
  if ( !wkbPtr )
  {
    return false;
  }

  QgsWkbTypes::Type type = wkbPtr.readHeader();
  if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::CompoundCurve )
  {
    return false;
  }
  mWkbType = type;

  int nCurves;
  wkbPtr >> nCurves;
  QgsCurve *currentCurve = nullptr;
  for ( int i = 0; i < nCurves; ++i )
  {
    QgsWkbTypes::Type curveType = wkbPtr.readHeader();
    wkbPtr -= 1 + sizeof( int );
    if ( QgsWkbTypes::flatType( curveType ) == QgsWkbTypes::LineString )
    {
      currentCurve = new QgsLineString();
    }
    else if ( QgsWkbTypes::flatType( curveType ) == QgsWkbTypes::CircularString )
    {
      currentCurve = new QgsCircularString();
    }
    else
    {
      return false;
    }
    currentCurve->fromWkb( wkbPtr );  // also updates wkbPtr
    mCurves.append( currentCurve );
  }
  return true;
}
Example #5
0
QgsConstWkbPtr QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkbPtr, bool clipToExtent )
{
  QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
  unsigned int nPoints;
  wkbPtr >> nPoints;

  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 -= 1 + 2 * sizeof( int );
    wkbPtr = QgsClipper::clippedLineWKB( wkbPtr, clipRect, pts );
  }
  else
  {
    pts.resize( nPoints );

    int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
    Q_ASSERT( skipZM >= 0 );

    QPointF *ptr = pts.data();
    for ( unsigned int i = 0; i < nPoints; ++i, ++ptr )
    {
      wkbPtr >> ptr->rx() >> ptr->ry();
      wkbPtr += skipZM;
    }
  }

  //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;
}
Example #6
0
bool QgsTriangle::fromWkb( QgsConstWkbPtr &wkbPtr )
{
  clear();
  if ( !wkbPtr )
  {
    return false;
  }

  QgsWkbTypes::Type type = wkbPtr.readHeader();
  if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::Triangle )
  {
    return false;
  }
  mWkbType = type;

  QgsWkbTypes::Type ringType;
  switch ( mWkbType )
  {
    case QgsWkbTypes::TriangleZ:
      ringType = QgsWkbTypes::LineStringZ;
      break;
    case QgsWkbTypes::TriangleM:
      ringType = QgsWkbTypes::LineStringM;
      break;
    case QgsWkbTypes::TriangleZM:
      ringType = QgsWkbTypes::LineStringZM;
      break;
    default:
      ringType = QgsWkbTypes::LineString;
      break;
  }

  int nRings;
  wkbPtr >> nRings;
  if ( nRings > 1 )
  {
    return false;
  }

  QgsLineString *line = new QgsLineString();
  line->fromWkbPoints( ringType, wkbPtr );
  if ( !mExteriorRing )
  {
    mExteriorRing = line;
  }

  return true;
}
Example #7
0
bool QgsLineString::fromWkb( QgsConstWkbPtr &wkbPtr )
{
  if ( !wkbPtr )
  {
    return false;
  }

  QgsWkbTypes::Type type = wkbPtr.readHeader();
  if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::LineString )
  {
    return false;
  }
  mWkbType = type;
  importVerticesFromWkb( wkbPtr );
  return true;
}
Example #8
0
bool QgsCircularString::fromWkb( QgsConstWkbPtr &wkbPtr )
{
  if ( !wkbPtr )
    return false;

  QgsWkbTypes::Type type = wkbPtr.readHeader();
  if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::CircularString )
  {
    return false;
  }
  clearCache();
  mWkbType = type;

  //type
  bool hasZ = is3D();
  bool hasM = isMeasure();
  int nVertices = 0;
  wkbPtr >> nVertices;
  mX.resize( nVertices );
  mY.resize( nVertices );
  hasZ ? mZ.resize( nVertices ) : mZ.clear();
  hasM ? mM.resize( nVertices ) : mM.clear();
  for ( int i = 0; i < nVertices; ++i )
  {
    wkbPtr >> mX[i];
    wkbPtr >> mY[i];
    if ( hasZ )
    {
      wkbPtr >> mZ[i];
    }
    if ( hasM )
    {
      wkbPtr >> mM[i];
    }
  }

  return true;
}
Example #9
0
std::unique_ptr<QgsAbstractGeometry> QgsGeometryFactory::geomFromWkb( QgsConstWkbPtr &wkbPtr )
{
  if ( !wkbPtr )
    return nullptr;

  //find out type (bytes 2-5)
  QgsWkbTypes::Type type = QgsWkbTypes::Unknown;
  try
  {
    type = wkbPtr.readHeader();
  }
  catch ( const QgsWkbException &e )
  {
    Q_UNUSED( e );
    QgsDebugMsg( "WKB exception while reading header: " + e.what() );
    return nullptr;
  }
  wkbPtr -= 1 + sizeof( int );

  std::unique_ptr< QgsAbstractGeometry > geom = geomFromWkbType( type );

  if ( geom )
  {
    try
    {
      geom->fromWkb( wkbPtr );  // also updates wkbPtr
    }
    catch ( const QgsWkbException &e )
    {
      Q_UNUSED( e );
      QgsDebugMsg( "WKB exception: " + e.what() );
      geom.reset();
    }
  }

  return geom;
}
bool QgsGeometryCollection::fromWkb( QgsConstWkbPtr &wkbPtr )
{
  if ( !wkbPtr )
  {
    return false;
  }

  QgsWkbTypes::Type wkbType = wkbPtr.readHeader();
  if ( QgsWkbTypes::flatType( wkbType ) != QgsWkbTypes::flatType( mWkbType ) )
    return false;

  mWkbType = wkbType;

  int nGeometries = 0;
  wkbPtr >> nGeometries;

  QVector<QgsAbstractGeometry *> geometryListBackup = mGeometries;
  mGeometries.clear();
  for ( int i = 0; i < nGeometries; ++i )
  {
    std::unique_ptr< QgsAbstractGeometry > geom( QgsGeometryFactory::geomFromWkb( wkbPtr ) );  // also updates wkbPtr
    if ( geom )
    {
      if ( !addGeometry( geom.release() ) )
      {
        qDeleteAll( mGeometries );
        mGeometries = geometryListBackup;
        return false;
      }
    }
  }
  qDeleteAll( geometryListBackup );

  clearCache(); //set bounding box invalid

  return true;
}
Example #11
0
QgsConstWkbPtr QgsSymbolV2::_getPolygon( QPolygonF &pts, QList<QPolygonF> &holes, QgsRenderContext &context, QgsConstWkbPtr wkbPtr, bool clipToExtent )
{
  QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
  QgsDebugMsg( QString( "wkbType=%1" ).arg( wkbType ) );
  unsigned int numRings;
  wkbPtr >> numRings;

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

  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 );

  int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
  Q_ASSERT( skipZM >= 0 );

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

    QPolygonF poly( nPoints );

    QPointF *ptr = poly.data();
    for ( unsigned int jdx = 0; jdx < nPoints; ++jdx, ++ptr )
    {
      wkbPtr >> ptr->rx() >> ptr->ry();
      wkbPtr += skipZM;
    }

    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;
}
//! Simplify the WKB-geometry using the specified tolerance
bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
  int simplifyFlags,
  SimplifyAlgorithm simplifyAlgorithm,
  QGis::WkbType wkbType,
  QgsConstWkbPtr sourceWkbPtr,
  QgsWkbPtr targetWkbPtr,
  int &targetWkbSize,
  const QgsRectangle &envelope, double map2pixelTol,
  bool writeHeader, bool isaLinearRing )
{
  bool isGeneralizable = true;
  bool result = false;

  // Save initial WKB settings to use when the simplification creates invalid geometries
  QgsConstWkbPtr sourcePrevWkbPtr( sourceWkbPtr );
  QgsWkbPtr targetPrevWkbPtr( targetWkbPtr );
  int targetWkbPrevSize = targetWkbSize;

  // Can replace the geometry by its BBOX ?
  if (( simplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope ) &&
      isGeneralizableByMapBoundingBox( envelope, map2pixelTol ) )
  {
    isGeneralizable = generalizeWkbGeometryByBoundingBox( wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize, envelope, writeHeader );
    if ( isGeneralizable )
      return true;
  }

  if ( !( simplifyFlags & QgsMapToPixelSimplifier::SimplifyGeometry ) )
    isGeneralizable = false;

  // Write the main header of the geometry
  if ( writeHeader )
  {
    QgsWKBTypes::Type geometryType = sourceWkbPtr.readHeader();

    targetWkbPtr << ( char ) QgsApplication::endian() << QgsWKBTypes::flatType( geometryType );

    targetWkbSize += targetWkbPtr - targetPrevWkbPtr;
  }

  unsigned int flatType = QGis::flatType( wkbType );

  // Write the geometry
  if ( flatType == QGis::WKBLineString || isaLinearRing )
  {
    QgsWkbPtr savedTargetWkbPtr( targetWkbPtr );
    double x = 0.0, y = 0.0, lastX = 0, lastY = 0;
    QgsRectangle r;
    r.setMinimal();

    int skipZM = ( QGis::wkbDimensions( wkbType ) - 2 ) * sizeof( double );
    Q_ASSERT( skipZM >= 0 );

    int numPoints;
    sourceWkbPtr >> numPoints;

    if ( numPoints <= ( isaLinearRing ? 5 : 2 ) )
      isGeneralizable = false;

    QgsWkbPtr numPtr( targetWkbPtr );

    int numTargetPoints = 0;
    targetWkbPtr << numTargetPoints;
    targetWkbSize += 4;

    bool isLongSegment;
    bool hasLongSegments = false; //-> To avoid replace the simplified geometry by its BBOX when there are 'long' segments.
    bool badLuck = false;

    // Check whether the LinearRing is really closed.
    if ( isaLinearRing )
    {
      QgsConstWkbPtr checkPtr( sourceWkbPtr );

      double x1, y1, x2, y2;

      checkPtr >> x1 >> y1;
      checkPtr += skipZM + ( numPoints - 2 ) * ( 2 * sizeof( double ) + skipZM );
      checkPtr >> x2 >> y2;

      isaLinearRing = qgsDoubleNear( x1, x2 ) && qgsDoubleNear( y1, y2 );
    }

    // Process each vertex...
    if ( simplifyAlgorithm == SnapToGrid )
    {
      double gridOriginX = envelope.xMinimum();
      double gridOriginY = envelope.yMinimum();

      // Use a factor for the maximum displacement distance for simplification, similar as GeoServer does
      float gridInverseSizeXY = map2pixelTol != 0 ? ( float )( 1.0f / ( 0.8 * map2pixelTol ) ) : 0.0f;

      for ( int i = 0; i < numPoints; ++i )
      {
        sourceWkbPtr >> x >> y;
        sourceWkbPtr += skipZM;

        if ( i == 0 ||
             !isGeneralizable ||
             !equalSnapToGrid( x, y, lastX, lastY, gridOriginX, gridOriginY, gridInverseSizeXY ) ||
             ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
        {
          targetWkbPtr << x << y;
          lastX = x;
          lastY = y;
          numTargetPoints++;
        }

        r.combineExtentWith( x, y );
      }
    }
Example #13
0
QgsConstWkbPtr QgsClipper::clippedLineWKB( QgsConstWkbPtr& wkbPtr, const QgsRectangle& clipExtent, QPolygonF& line )
{
  QgsWKBTypes::Type wkbType = wkbPtr.readHeader();

  int nPoints;
  wkbPtr >> nPoints;

  int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );

  if ( static_cast<int>( nPoints * ( 2 * sizeof( double ) + skipZM ) ) > wkbPtr.remaining() )
  {
    QgsDebugMsg( QString( "%1 points exceed wkb length (%2>%3)" ).arg( nPoints ).arg( nPoints * ( 2 * sizeof( double ) + skipZM ) ).arg( wkbPtr.remaining() ) );
    return QgsConstWkbPtr( nullptr, 0 );
  }

  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

  QPolygonF pts;
  wkbPtr -= sizeof( unsigned int );
  wkbPtr >> pts;
  nPoints = pts.size();

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

  QPointF *ptr = pts.data();

  for ( int i = 0; i < nPoints; ++i, ++ptr )
  {
    if ( i == 0 )
    {
      p1x = ptr->rx();
      p1y = ptr->ry();
      continue;
    }
    else
    {
      p0x = p1x;
      p0y = p1y;

      p1x = ptr->rx();
      p1y = ptr->ry();

      p1x_c = p1x;
      p1y_c = p1y;
      if ( clipLineSegment( clipExtent.xMinimum(), clipExtent.xMaximum(), clipExtent.yMinimum(), clipExtent.yMaximum(),
                            p0x, p0y, p1x_c,  p1y_c ) )
      {
        bool newLine = !line.isEmpty() && ( !qgsDoubleNear( p0x, lastClipX ) || !qgsDoubleNear( p0y, lastClipY ) );
        if ( newLine )
        {
          //add edge points to connect old and new line
          connectSeparatedLines( lastClipX, lastClipY, p0x, p0y, clipExtent, line );
        }
        if ( line.size() < 1 || newLine )
        {
          //add first point
          line << QPointF( p0x, p0y );
        }

        //add second point
        lastClipX = p1x_c;
        lastClipY = p1y_c;
        line << QPointF( p1x_c,  p1y_c );
      }
    }
  }
  return wkbPtr;
}
Example #14
0
QgsConstWkbPtr QgsDistanceArea::measurePolygon( QgsConstWkbPtr wkbPtr, double* area, double* perimeter, bool hasZptr ) const
{
  if ( !wkbPtr )
  {
    QgsDebugMsg( "no feature to measure" );
    return wkbPtr;
  }

  wkbPtr.readHeader();

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

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

  // 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;
}