mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	Fix QgsGeometry::asQPolygonF doesn't handle multipolygon inputs
gracefully
This commit is contained in:
		
							parent
							
								
									766e0b290e
								
							
						
					
					
						commit
						33f31d826a
					
				@ -1823,9 +1823,14 @@ otherwise returns a null QPointF.
 | 
			
		||||
 | 
			
		||||
    QPolygonF asQPolygonF() const;
 | 
			
		||||
%Docstring
 | 
			
		||||
Returns contents of the geometry as a QPolygonF. If geometry is a linestring,
 | 
			
		||||
then the result will be an open QPolygonF. If the geometry is a polygon,
 | 
			
		||||
then the result will be a closed QPolygonF of the geometry's exterior ring.
 | 
			
		||||
Returns contents of the geometry as a QPolygonF.
 | 
			
		||||
 | 
			
		||||
If geometry is a linestring, then the result will be an open QPolygonF.
 | 
			
		||||
If the geometry is a polygon, then the result will be a closed QPolygonF
 | 
			
		||||
of the geometry's exterior ring.
 | 
			
		||||
 | 
			
		||||
If the geometry is a multi-part geometry, then only the first part will
 | 
			
		||||
be considered when converting to a QPolygonF.
 | 
			
		||||
 | 
			
		||||
.. versionadded:: 2.7
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
@ -2558,36 +2558,22 @@ QPointF QgsGeometry::asQPointF() const
 | 
			
		||||
 | 
			
		||||
QPolygonF QgsGeometry::asQPolygonF() const
 | 
			
		||||
{
 | 
			
		||||
  const QgsWkbTypes::Type type = wkbType();
 | 
			
		||||
  const QgsLineString *line = nullptr;
 | 
			
		||||
  if ( QgsWkbTypes::flatType( type ) == QgsWkbTypes::LineString )
 | 
			
		||||
  const QgsAbstractGeometry *part = constGet();
 | 
			
		||||
 | 
			
		||||
  // if a geometry collection, get first part only
 | 
			
		||||
  if ( const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection *>( part ) )
 | 
			
		||||
  {
 | 
			
		||||
    line = qgsgeometry_cast< const QgsLineString * >( constGet() );
 | 
			
		||||
  }
 | 
			
		||||
  else if ( QgsWkbTypes::flatType( type ) == QgsWkbTypes::Polygon )
 | 
			
		||||
  {
 | 
			
		||||
    const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( constGet() );
 | 
			
		||||
    if ( polygon )
 | 
			
		||||
      line = qgsgeometry_cast< const QgsLineString * >( polygon->exteriorRing() );
 | 
			
		||||
    if ( collection->numGeometries() > 0 )
 | 
			
		||||
      part = collection->geometryN( 0 );
 | 
			
		||||
    else
 | 
			
		||||
      return QPolygonF();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if ( line )
 | 
			
		||||
  {
 | 
			
		||||
    const double *srcX = line->xData();
 | 
			
		||||
    const double *srcY = line->yData();
 | 
			
		||||
    const int count = line->numPoints();
 | 
			
		||||
    QPolygonF res( count );
 | 
			
		||||
    QPointF *dest = res.data();
 | 
			
		||||
    for ( int i = 0; i < count; ++i )
 | 
			
		||||
    {
 | 
			
		||||
      *dest++ = QPointF( *srcX++, *srcY++ );
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    return QPolygonF();
 | 
			
		||||
  }
 | 
			
		||||
  if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( part ) )
 | 
			
		||||
    return curve->asQPolygonF();
 | 
			
		||||
  else if ( const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( part ) )
 | 
			
		||||
    return polygon->exteriorRing() ? polygon->exteriorRing()->asQPolygonF() : QPolygonF();
 | 
			
		||||
  return QPolygonF();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsGeometry::deleteRing( int ringNum, int partNum )
 | 
			
		||||
 | 
			
		||||
@ -1917,9 +1917,15 @@ class CORE_EXPORT QgsGeometry
 | 
			
		||||
    QPointF asQPointF() const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns contents of the geometry as a QPolygonF. If geometry is a linestring,
 | 
			
		||||
     * then the result will be an open QPolygonF. If the geometry is a polygon,
 | 
			
		||||
     * then the result will be a closed QPolygonF of the geometry's exterior ring.
 | 
			
		||||
     * Returns contents of the geometry as a QPolygonF.
 | 
			
		||||
     *
 | 
			
		||||
     * If geometry is a linestring, then the result will be an open QPolygonF.
 | 
			
		||||
     * If the geometry is a polygon, then the result will be a closed QPolygonF
 | 
			
		||||
     * of the geometry's exterior ring.
 | 
			
		||||
     *
 | 
			
		||||
     * If the geometry is a multi-part geometry, then only the first part will
 | 
			
		||||
     * be considered when converting to a QPolygonF.
 | 
			
		||||
     *
 | 
			
		||||
     * \since QGIS 2.7
 | 
			
		||||
     */
 | 
			
		||||
    QPolygonF asQPolygonF() const;
 | 
			
		||||
 | 
			
		||||
@ -16590,6 +16590,34 @@ void TestQgsGeometry::asQPolygonF()
 | 
			
		||||
  QgsGeometry badGeom( QgsGeometry::fromPointXY( mPoint1 ) );
 | 
			
		||||
  QPolygonF fromBad = badGeom.asQPolygonF();
 | 
			
		||||
  QVERIFY( fromBad.isEmpty() );
 | 
			
		||||
 | 
			
		||||
  // test a multipolygon
 | 
			
		||||
  QPolygonF res = QgsGeometry::fromWkt( QStringLiteral( "MultiPolygon (((0 0, 10 0, 10 10, 0 10, 0 0 )),((2 2, 4 2, 4 4, 2 4, 2 2)))" ) ).asQPolygonF();
 | 
			
		||||
  QVERIFY( res.isClosed() );
 | 
			
		||||
  QCOMPARE( res.size(), 5 );
 | 
			
		||||
  QCOMPARE( res.at( 0 ).x(), 0.0 );
 | 
			
		||||
  QCOMPARE( res.at( 0 ).y(), 0.0 );
 | 
			
		||||
  QCOMPARE( res.at( 1 ).x(), 10.0 );
 | 
			
		||||
  QCOMPARE( res.at( 1 ).y(), 0.0 );
 | 
			
		||||
  QCOMPARE( res.at( 2 ).x(), 10.0 );
 | 
			
		||||
  QCOMPARE( res.at( 2 ).y(), 10.0 );
 | 
			
		||||
  QCOMPARE( res.at( 3 ).x(), 0.0 );
 | 
			
		||||
  QCOMPARE( res.at( 3 ).y(), 10.0 );
 | 
			
		||||
  QCOMPARE( res.at( 4 ).x(), 0.0 );
 | 
			
		||||
  QCOMPARE( res.at( 4 ).y(), 0.0 );
 | 
			
		||||
 | 
			
		||||
  // test a multilinestring
 | 
			
		||||
  res = QgsGeometry::fromWkt( QStringLiteral( "MultiLineString((0 0, 10 0, 10 10, 0 10 ),(2 2, 4 2, 4 4, 2 4))" ) ).asQPolygonF();
 | 
			
		||||
  QVERIFY( !res.isClosed() );
 | 
			
		||||
  QCOMPARE( res.size(), 4 );
 | 
			
		||||
  QCOMPARE( res.at( 0 ).x(), 0.0 );
 | 
			
		||||
  QCOMPARE( res.at( 0 ).y(), 0.0 );
 | 
			
		||||
  QCOMPARE( res.at( 1 ).x(), 10.0 );
 | 
			
		||||
  QCOMPARE( res.at( 1 ).y(), 0.0 );
 | 
			
		||||
  QCOMPARE( res.at( 2 ).x(), 10.0 );
 | 
			
		||||
  QCOMPARE( res.at( 2 ).y(), 10.0 );
 | 
			
		||||
  QCOMPARE( res.at( 3 ).x(), 0.0 );
 | 
			
		||||
  QCOMPARE( res.at( 3 ).y(), 10.0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TestQgsGeometry::comparePolylines()
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user