Skip to content

Instantly share code, notes, and snippets.

@3nids
Created January 27, 2014 16:45
Show Gist options
  • Save 3nids/8652202 to your computer and use it in GitHub Desktop.
Save 3nids/8652202 to your computer and use it in GitHub Desktop.
convert geometry
bool QgsVectorLayer::convertToLayerGeometry( QgsGeometry &geometry )
{
QGis::GeometryType layerGeomType = geometryType();
QGis::GeometryType geomType = geometry.type();
switch ( geomType )
{
// geometry type is point
case QGis::Point:
{
if ( layerGeomType == QGis::Point )
{
if ( (mIsMultiPart && geometry.isMultipart()) ||
(!mIsMultiPart && ! geometry.isMultipart()) )
{
// keep the same geom
return true;
}
if ( mIsMultiPart )
{
// layer is multipart => makes a multipoint with a single point
geometry = *QgsGeometry::fromMultiPoint( QgsMultiPoint() << geometry.asPoint() );
}
else
{
// layer is singlepart => make a point if geometry contains only one, return false otherwise
QgsMultiPoint multiPoint = geometry.asMultiPoint();
if ( multiPoint.count() != 1 )
{
return false;
}
else
{
geometry = *QgsGeometry::fromPoint( multiPoint[0] );
}
}
}
else
{
// cannot change point in any other type,
// even for multipoints since there is no ordering
return false;
}
}
// geometry type is line
case QGis::Line:
{
QgsMultiPolyline multiLine;
QgsPolyline line;
if ( geometry.isMultipart() )
{
multiLine = geometry.asMultiPolyline();
if ( multiLine.isEmpty() )
return false;
}
else
{
line = geometry.asPolyline();
if ( line.isEmpty() )
return false;
}
switch ( layerGeomType )
{
// line geometry for point layer => make a multipoint
case QGis::Point:
{
// if layer is not multi part: cannot transform
if ( !mIsMultiPart )
return false;
// input geometry is multipart
if ( geometry.isMultipart() )
{
QgsMultiPoint multiPoint;
for ( QgsMultiPolyline::const_iterator multiLineIt = multiLine.constBegin(); multiLineIt != multiLine.constEnd(); ++multiLineIt )
for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
multiPoint << *lineIt;
geometry = *QgsGeometry::fromMultiPoint( multiPoint );
return true;
}
// input geometry is not multipart
else
{
geometry = *QgsGeometry::fromMultiPoint( line );
return true;
}
break;
}
case QGis::Line:
{
if ( (mIsMultiPart && geometry.isMultipart()) ||
(!mIsMultiPart && ! geometry.isMultipart()) )
{
// keep the same geom
return true;
}
if ( mIsMultiPart )
{
// layer is multipart => makes a multipoint with a single line
geometry = *QgsGeometry::fromMultiPolyline( QgsMultiPolyline() << line );
}
else
{
// layer is singlepart => make a point if geometry contains only one, return false otherwise
if ( multiLine.count() != 1 )
{
return false;
}
else
{
geometry = *QgsGeometry::fromPolyline( multiLine[0] );
}
}
}
// line geometry for polygon layer => create polygon by closing the line(s)
case QGis::Polygon:
{
// input geometry is multipart
if ( geometry.isMultipart() )
{
QgsMultiPolygon multiPolygon;
for ( QgsMultiPolyline::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
{
// do not create polygon for a 2 segment line
if (( *multiLineIt ).count() < 3 )
continue;
// add closing node
if (( *multiLineIt ).first() != ( *multiLineIt ).last() )
*multiLineIt << ( *multiLineIt ).first();
multiPolygon << ( QgsPolygon() << *multiLineIt );
}
// no polygons were added
if ( multiPolygon.isEmpty() )
return false;
if ( mIsMultiPart )
{
geometry = *QgsGeometry::fromMultiPolygon( multiPolygon );
return true;
}
else
{
if ( multiPolygon.count() > 1 )
{
// cannot fit a multipolygon in a polygon layer
return false;
}
else
{
// since the geometry contains only one polygon, make it single part geometry
geometry = *QgsGeometry::fromPolygon( multiPolygon[0] );
return true;
}
}
}
// input geometry is not multipart
else
{
// do not create polygon for a 2 segment line
if ( line.count() < 3 )
return false;
// add closing node
if ( line.first() != line.last() )
line << line.first();
// layer is multipart
if ( mIsMultiPart )
{
geometry = *QgsGeometry::fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << line ) );
return true;
}
else
{
geometry = *QgsGeometry::fromPolygon( QgsPolygon() << line );
return true;
}
}
break;
}
default:
return false;
}
}
// geometry type is polygon
case QGis::Polygon:
{
QgsMultiPolygon multiPolygon;
QgsPolygon polygon;
if ( geometry.isMultipart() )
{
multiPolygon = geometry.asMultiPolygon();
if ( multiPolygon.isEmpty() )
return false;
}
else
{
polygon = geometry.asPolygon();
if ( polygon.isEmpty() )
return false;
}
switch ( layerGeomType )
{
// feature: polygon & layer point => make a multipoint
case QGis::Point:
{
// if layer is not multi part: cannot transform
if ( !mIsMultiPart )
return false;
// input geometry is multipart
if ( geometry.isMultipart() )
{
QgsMultiPoint multiPoint;
for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
multiPoint << *lineIt;
geometry = *QgsGeometry::fromMultiPoint( multiPoint );
return true;
}
// input geometry is not multipart
else
{
QgsMultiPoint multiPoint;
for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
multiPoint << *lineIt;
geometry = *QgsGeometry::fromMultiPoint( multiPoint );
return true;
}
break;
}
// feature: polygon & layer: line => polygon to line
// convert multipolygon and rings to multilines
case QGis::Line:
{
if ( geometry.isMultipart() )
{
QgsMultiPolyline multiLine;
for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
multiLine << *multiLineIt;
// layer is multipart
if ( mIsMultiPart )
{
geometry = *QgsGeometry::fromMultiPolyline( multiLine );
return true;
}
else
{
if ( multiLine.count() > 1 )
{
// cannot fit a multiline in a line layer
return false;
}
else
{
// since the geometry contains only one polygon without ring, make it single part geometry
geometry = *QgsGeometry::fromPolyline( multiLine[0] );
return true;
}
}
}
// not multipart
else
{
// if polygon has rings
if ( polygon.count() > 1 )
{
// cannot fit a polygon with rings in a single line layer
// TODO: would it be better to remove rings?
if ( !mIsMultiPart )
return false;
QgsMultiPolyline multiLine;
for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
multiLine << *multiLineIt;
geometry = *QgsGeometry::fromMultiPolyline( multiLine );
}
// no rings
else
{
if ( mIsMultiPart )
{
geometry = *QgsGeometry::fromMultiPolyline( polygon );
return true;
}
else
{
geometry = *QgsGeometry::fromPolyline( polygon[0] );
return true;
}
}
}
}
case QGis::Polygon:
{
if ( (mIsMultiPart && geometry.isMultipart()) ||
(!mIsMultiPart && ! geometry.isMultipart()) )
{
// keep the same geom
return true;
}
if ( mIsMultiPart )
{
// layer is multipart => makes a multipoint with a single polygon
geometry = *QgsGeometry::fromMultiPolygon( QgsMultiPolygon() << polygon );
}
else
{
// layer is singlepart => make a point if geometry contains only one, return false otherwise
if ( multiPolygon.count() != 1 )
{
return false;
}
else
{
geometry = *QgsGeometry::fromPolygon( multiPolygon[0] );
}
}
}
default:
return false;
}
}
default:
return false;
}
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment